贵州省网站建设_网站建设公司_测试上线_seo优化
2025/12/29 20:05:11 网站建设 项目流程

毕设所有选题:
https://blog.csdn.net/2303_76227485/article/details/131104075

基于Springboot+Vue3+Ai对话的非遗传承管理系统(源代码+数据库+2万字论文)

项目编号:260

一、系统介绍

本项目前后端分离,分为用户、管理员2种角色。

1、用户:

  • 登录、注册、热门作品查询、作品搜索、最新作品查询、活动报名、非遗课程学习、传承人查询
  • 非遗手办商城、订单提交、支付、取消、确认收货
  • 修改密码、个人信息修改、收货地址维护、默认地址设置、非遗作品发布
  • AI智能助手模块:创建会话、会话列表查询、会话消息历史查询、流式对话、非流式对话、更新会话标题、删除会话

2、管理员:

  • 首页大屏数据图表统计:用户数、订单数、销售额、非遗作品数、订单趋势曲线图、销售额柱状图、订单状态分布环状图、非遗类别饼状图
  • 用户管理
  • 非遗作品管理:非遗作品增删改查、作品发布、作品下架
  • 课程管理:课程管理、章节管理
  • 活动管理:报名审核、活动签到、报名列表查询
  • 商城管理:商品增删改查、商品上架、商品下架、商品库存更新、商品分类管理
  • 订单管理(查看、发货)
  • 传承人管理:传承人增删改查、传承人与作品关联管理

4、亮点:

  • 实现ai对话优化用户体验
  • 后台首页大屏使用echarts图表统计,更直观的看出系统的运行数据

二、所用技术

后端技术栈:

  • Springboot3
  • mybatisPlus
  • Jwt
  • Spring Security
  • Mysql
  • Maven

前端技术栈:

  • Vue3
  • Vue-router
  • axios
  • elementPlus
  • echarts

三、环境介绍

基础环境 :IDEA/eclipse, JDK17或以上, Mysql5.7及以上, Maven3.6, node14, navicat, 通义千问apikey

所有项目以及源代码本人均调试运行无问题 可支持远程调试运行

四、页面截图

文档截图:


1、用户:






























2、管理员:





















五、浏览地址

前台地址:http://localhost:8800

  • 用户账号密码:test/123456

  • 管理员账户密码:admin/123456

六、部署教程

  1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并执行项目的sql文件

  2. 使用IDEA/Eclipse导入springboot项目,若为maven项目请选择maven,等待依赖下载完成

  3. 修改application.yml里面的数据库配置和数据库配置,还有通义千问的apikey配置,
    src/main/java/org/example/springboot/SpringbootApplication.java启动后端项目

  4. vscode或idea打开vue3项目

  5. 在编译器中打开terminal,执行npm install 依赖下载完成后执行 npm run serve,执行成功后会显示访问地址

七、ai对话部分代码

/** * 流式聊天接口(SSE) */@PostMapping(value="/stream",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<String>chatStream(@Valid@RequestBodyChatRequestrequest,HttpServletResponseresponse){response.setHeader("X-Accel-Buffering","no");// 禁用Nginx缓冲response.setHeader("Cache-Control","no-cache, no-store");// 禁用浏览器缓冲response.setHeader("Pragma","no-cache");response.setCharacterEncoding("UTF-8");LonguserId=JwtTokenUtils.getCurrentUserId();// 验证权限if(!sessionService.isSessionOwnedByUser(request.getSessionId(),userId)){returnFlux.just("data: 无权访问此会话\n\n");}log.info("开始流式对话,sessionId: {}, userId: {}",request.getSessionId(),userId);returntongyiQianwenService.chatStream(request.getSessionId(),request.getUserMessage()).map(chatResponse->"data: "+JSON.toJSONString(chatResponse)+"\n\n");}/** * 流式聊天(SSE实时返回) */publicFlux<ChatResponse>chatStream(StringsessionId,Stringprompt){log.info("开始AI对话,sessionId: {}, userMessage: {}",sessionId,prompt);// 保存用户消息sessionService.saveMessage(sessionId,"user",prompt);// 1. 获取会话上下文SessionContextcontext=sessionManager.getSessionContext(sessionId);if(context==null){context=newSessionContext(sessionId);// 初始化空上下文sessionManager.saveSessionContext(context);}StringfinalSessionId=context.getSessionId();// 2. 构建请求体Map<String,Object>requestBody=buildRequestBody(context,prompt,true);// 定义原子变量累加完整响应文本AtomicReference<String>fullAnswer=newAtomicReference<>("");// 3. 流式调用APIreturnWebClient.create().post().uri(apiUrl).headers(headers->headers.addAll(buildHeaders())).bodyValue(requestBody).retrieve()// 禁用WebClient的响应缓冲(关键!).bodyToFlux(String.class)// 逐个处理通义千问返回的流式片段.doOnNext(line->log.info("通义千问原生片段:{}",line))// 打印原生片段,验证是否逐行返回// 步骤1:先过滤空行(提前剔除无效数据).filter(line->line!=null&&!line.trim().isEmpty()).scan(newAccumulator(null,""),(acc,line)->{// 空行处理:保留原有累加文本,line设为nullif(line==null||line.isEmpty()){returnnewAccumulator(null,acc.getFullAnswer());}// 解析SSE数据前缀Stringdata=line.startsWith("data: ")?line.substring(6):line;// 解析流式片段TongyiQianwenResponsefragment=JSON.parseObject(data,TongyiQianwenResponse.class);// 1. 流结束标识:返回完整响应if("stop".equals(fragment.getOutput().getFinish_reason())){returnnewAccumulator(data,acc.getFullAnswer());}// 解析失败:保留原有累加文本,line设为nullif(fragment==null||fragment.getOutput()==null){returnnewAccumulator(null,acc.getFullAnswer());}// 正常片段:累加文本StringnewFullAnswer=acc.getFullAnswer()+fragment.getOutput().getText();// 返回新的累加器(当前行 + 最新累加文本)returnnewAccumulator(line,newFullAnswer);})// 步骤3:过滤累加器中line为null的无效数据(替代map里返回null).filter(acc->acc.getLine()!=null).map(acc->{Stringline=acc.getLine();StringcurrentFullAnswer=acc.getFullAnswer();ChatResponseresponse=newChatResponse();// 空行/解析失败的累加器直接返回null(后续filter过滤)if(line==null){returnnull;}// 解析SSE数据前缀Stringdata=line.startsWith("data: ")?line.substring(6):line;// 2. 解析流式片段TongyiQianwenResponsefragment=JSON.parseObject(data,TongyiQianwenResponse.class);// 1. 流结束标识:返回完整响应if("stop".equals(fragment.getOutput().getFinish_reason())){response.setSuccess(true);response.setSessionId(finalSessionId);response.setDone(true);response.setAnswer(currentFullAnswer);// 完整回答// 保存完整回答到会话sessionService.saveMessage(finalSessionId,"assistant",currentFullAnswer);log.info("AI对话完成,sessionId: {}, 响应长度: {}",sessionId,currentFullAnswer.length());returnresponse;}if(fragment==null||fragment.getOutput()==null){returnnull;}// 3. 异常处理(非stop结束)if(fragment.getOutput().getFinish_reason()!=null&&!"null".equals(fragment.getOutput().getFinish_reason())&&!"stop".equals(fragment.getOutput().getFinish_reason())){response.setSuccess(false);response.setMessage(fragment.getOutput().getFinish_reason());response.setRequestId(fragment.getRequest_id());returnresponse;}// 4. 正常片段:返回单条流式响应response.setSuccess(true);response.setSessionId(finalSessionId);response.setAnswer(fragment.getOutput().getText());// 单片段文本response.setDone(false);response.setRequestId(fragment.getRequest_id());// 设置token用量response.setUsage(Map.of("inputTokens",fragment.getUsage().getInput_tokens(),"outputTokens",fragment.getUsage().getOutput_tokens(),"totalTokens",fragment.getUsage().getTotal_tokens()));returnresponse;})// 过滤掉null响应(空行/解析失败的情况).filter(res->res!=null);}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询