返回作品

AI 聊天与积分充值系统

创建于 2025 年 9 月 19 日

标签
  • Java 8
  • Spring Boot 2.5.15
  • RuoYi 3.9.0
  • Spring Security
  • JWT
  • MyBatis
  • MySQL 8
  • Redis
  • fastjson2
  • DeepSeek API
  • RestTemplate
  • Vue 2.6.12
  • Element UI 2.15.14
  • axios
  • ECharts

项目介绍

这是一个基于若依 RuoYi 3.9.0 前后端分离脚手架二次开发的 AI 聊天与积分充值系统(目录 20250919-ai聊天模拟充值积分,含 -api 后端、-web 前端、全量 SQL 与原型设计文档)。业务形态很直白:用户每天登录系统领积分、充值换积分,再用积分去兑换 AI 服务(文生图、图生图、AI 对话),积分越花越多,会员等级也随累计积分水涨船高——一条”登录 → 任务 → 充值 → 消费 → 成长”的完整用户激励闭环。

项目由三部分构成:后端 20250919-ai聊天api(业务集中在 ruoyi-adminPointsControllerruoyi-framework 的登录钩子)、前端 20250919-ai聊天web(若依 Vue 管理端,首页被积分中心整体替换)、根目录 20250919-ai.sql 全量数据库脚本。业务表共四张:points_record(积分流水,带变动前后余额快照)、points_goods(积分商品)、points_task(积分任务)、chat_record(聊天记录,本次建表但未接入代码);sys_user 表则扩展了 points(当前积分)、total_points(累计积分)、member_level(会员等级)三个字段。

从 SQL 数据能还原真实的调试过程:points_record 里躺着 9 条 2025-09-20 的流水——凌晨 02:33 登录领 10 积分,02:36 首次充 10 元得 100 分,02:45 连续两次购买”图生图”各扣 150 分,03:08 一次性充值 200 元得 2000 分,直到上午 11:44 花 200 分买”AI 对话半小时”,最终 admin 定格在 3520 当前积分 / 5920 累计积分 / gold 黄金会员——充值、消费、升级的链路全都被真实数据走通了。

项目架构

系统沿用若依前后端分离结构,业务代码分布在若依框架的登录链路、新增的业务控制器与前端积分中心页面中:

模块技术栈说明
ruoyi-frameworkSysLoginServiceSpring Security + JWTlogin 成功更新登录信息后调用 handleDailyLoginReward 发放每日登录积分:先查 points_record 当日是否已有 task 类型记录防重复,再 +10 积分、更新累计积分与会员等级并落一条流水
ruoyi-adminPointsControllerJava 8、Spring Boot 2.5.15、fastjson2com.ruoyi.web.controller.system.PointsController 挂在 /system/points 下,提供 userInfo(积分信息 + 等级进度)、tasks(任务列表)、goods(商品列表)、purchase(购买扣费)、recharge(模拟充值)、records(积分明细)、chat(AI 聊天)、ai/status(连接自检)八组接口
ruoyi-adminAIServiceRestTemplate、fastjson2、DeepSeek APIcom.ruoyi.web.service.AIService 封装 POST https://api.deepseek.com/v1/chat/completionsdeepseek-chat 模型、max_tokens=2000temperature=0.7,连接超时 8 秒 / 读取超时 25 秒,按 ResourceAccessExceptionHttpClientErrorException(401 密钥失败、429 限流)、HttpServerErrorException 分类返回中文提示
ruoyi-systemPointsRecordMyBatisPointsRecord 实体 + PointsRecordMapper.xmlinsertPointsRecord 落流水,checkTodayLoginRewardchange_type='task' and like '%每日登录%' and DATE(create_time)=CURDATE() 判当日幂等,getTodayRechargeCount 统计今日充值次数
-web 前端Vue 2.6.12、Element UI 2.15.14、axios、Vuexsrc/views/points-center.vue 作为页面容器,按 $route.query.page 在 index / task / exchange / detail / member / recharge / chat 七个页面间切换;src/views/index.vue<PointsCenter /> 替换若依默认欢迎页(原内容 v-if="false" 隐藏);src/api/system/points.js 集中封装接口(AI 聊天接口超时单独放宽到 60 秒)
20250919-ai.sqlMySQL 8(utf8mb4_0900_ai_ci)全量脚本:四张业务表 + sys_user 三字段扩展 + 若依框架表 + 真实测试数据

积分体系的核心数据模型是 points_record:每次变动都记录 points_change(正负值)、change_type(task 任务 / exchange 兑换 / recharge 充值 / chat 聊天)、change_reasonbefore_pointsafter_points 余额快照——任何一笔积分从哪来到哪去、变动前后余额多少,都能对账审计。member_level 则完全由 total_points 派生:normal(0) → bronze(500) → silver(2000) → gold(5000) → platinum(10000) → diamond(20000) → super(50000)calculateMemberLevel 在登录领奖与充值两个入口统一调用,前端再配合 calculateLevelProgress 算出的百分比渲染进度条与”还差 X 积分升级”的引导文案。

核心功能

积分中心首页。 src/views/index.vue 将若依默认的框架介绍页整体替换为 <PointsCenter />:顶部是用户信息卡(头像、昵称、脱敏 ID、当前积分、累计积分、按等级配色的 el-progress 进度条与升级引导),中部三行功能模块卡片——任务列表 / 积分兑换 / 积分明细、会员权限 / 积分充值 / AI 聊天、快速充值(10 元起充)/ 立即对话 / 我的信息,点击卡片通过 this.$router.push('/index?page=xxx') 在 SPA 内切换子页面,无需新增路由表。页面还内置了”我的信息”弹窗与”积分不足一键跳转充值”的联动引导。

每日登录自动送积分。 这是对若依登录链路的侵入式扩展,代码写在 SysLoginService.login 成功路径的末尾:

// 更新登录 IP / 时间后
handleDailyLoginReward(userId);

private void handleDailyLoginReward(Long userId) {
    // 当天已领过则直接返回,保证幂等
    if (pointsRecordService.checkTodayLoginReward(userId)) {
        return;
    }
    int rewardPoints = 10;
    int currentPoints = user.getPoints() != null ? user.getPoints() : 0;
    int totalPoints = user.getTotalPoints() != null ? user.getTotalPoints() : 0;
    // 更新当前积分与累计积分
    user.setPoints(currentPoints + rewardPoints);
    user.setTotalPoints(totalPoints + rewardPoints);
    // 同步重算会员等级
    String newLevel = calculateMemberLevel(user.getTotalPoints());
    user.setMemberLevel(newLevel);
    userService.updateUser(user);
    // 落流水:task 类型,变动前后余额快照
    pointsRecordService.addPointsRecord(userId, rewardPoints, "task",
        "完成每日登录任务,获得积分", beforePoints, user.getPoints());
}

模拟充值。 recharge.vue 提供 10/20/50/100/200/500 元预设档位与自定义金额输入,前端校验后调 POST /system/points/recharge;后端按”1 元 = 10 积分”换算,同时累加 pointstotal_points,重算会员等级,写入 change_type='recharge' 的流水并返回”充值成功,获得积分:X”。SQL 里的真实流水显示这套逻辑被反复验证过:10 元、200 元面额都留下了记录,getTodayRechargeCount 还能支撑”今日充值”任务的进度统计。

积分兑换 AI 服务。 exchange.vue/system/points/goods 拉取”文生图 100 分 / 图生图 150 分 / AI 对话半小时 200 分”三档商品,支持多选并实时汇总总价;前端先校验余额,不足时弹”积分不足,是否前往充值?“确认框跳充值页。后端 purchasegoodsIds 用 switch 重新计算总价(二次校验防篡改),余额不足直接返回错误,扣减后调用 recordPointsChangeexchange 流水,前端购买成功提示 1.5 秒后自动 goToChat 跳入聊天页——“消费 → 服务”的转化路径非常顺滑。

三模式 AI 聊天页。 chat.vue 是 967 行的重头页面,深色渐变底(#667eea → #764ba2)配顶部毛玻璃导航,顶部实时显示”剩余积分”。底部功能选择器可切换智能对话 / 文本创作 / 图片生成三种模式,输入框支持 Ctrl+Enter 发送与图片上传(FileReader 转 Base64,before-upload 返回 false 阻止自动上传)。发送时统一调 POST /system/points/chat,后端按 functionType 分流:image 模式走 generateImagePrompt 生成图片描述提示词,writing 模式给消息包一层”请提供高质量、结构清晰的文本内容,包括引言、主体和结论”的创作提示,其余走 chatWithAI 直连 DeepSeek。异常链路做了多级兜底:网络超时返回”网络连接超时”、401 返回”API 密钥验证失败”、429 返回”请求过于频繁”,generateImagePrompt 失败还有按”风景/人物/建筑/动物”关键词本地拼装的降级提示词,前端再兜一层”AI 服务暂时不可用”的降级回复;/ai/status 接口可用一句话测试连接是否正常。

积分明细与会员体系。 detail.vue 拉取 /system/points/records 以时间倒序渲染流水表格(变动分值、类型、原因、变动前后余额、时间),无真实数据时后端补三条示例记录。member.vue 展示七级会员阶梯:每个等级卡片带积分区间、升级所需积分与”当前等级”高亮,等级颜色(青铜 #CD7F32、白银 #C0C0C0、黄金 #FFD700、白金 #E5E4E2、钻石 #B9F2FF)贯穿首页进度条、充值页与会员页三处 UI。

功能截图

暂无运行截图。

快速上手

  1. 初始化数据库:执行根目录 20250919-ai.sql(全量脚本,含框架表、四张业务表、sys_user 积分字段与测试数据),修改 ruoyi-admin/src/main/resources/application-druid.yml 的 MySQL 连接、application.yml 的 Redis 配置与 deepseek.api.key

  2. 启动后端与前端:

cd "20250919-ai聊天api"
mvn clean package -DskipTests
java -jar ruoyi-admin/target/ruoyi-admin.jar   # 默认端口 8080

cd "../20250919-ai聊天web"
npm install
npm run dev   # http://localhost:80,默认账号 admin / admin123
  1. 体验完整流程:登录 admin(密码 admin123)后首页即积分中心,观察”每日登录 +10 积分”自动到账与流水落库 → 进”积分充值”选 10 元档模拟充值 100 积分 → 进”积分兑换”选”文生图”购买(100 分),成功后自动跳转 AI 聊天页 → 在聊天页分别试”智能对话 / 文本创作 / 图片生成”三种模式,或上传图片发送 → 回”积分明细”核对每一笔 task / recharge / exchange 流水的余额快照,再进”会员权限”查看等级进度。

总结

这个项目把”AI 服务 + 积分运营”的 C 端激励闭环搭得很完整,值得借鉴的有四点:一是登录钩子挂积分——直接在 SysLoginService 成功路径里扩展 handleDailyLoginReward,用 points_record 当日查询做幂等,10 行代码就实现”每日登录领奖”,不破坏若依原有登录逻辑;二是积分流水可对账——points_record 记录 change_type + before/after 余额快照,task / exchange / recharge 三类变动各有明确语义,配合 getTodayRechargeCount 等聚合查询,运营数据随时可查;三是会员等级纯派生——member_level 只由 total_points 在登录与充值两个入口重算,七档阈值集中在一个方法里,前端进度条/升级文案/等级配色三处消费同一份数据,改阈值只需动一处;四是AI 接入的多级降级——RestTemplate 超时配置、异常分类文案、关键词兜底提示词、前端二次降级,四层防护让”AI 挂了”用户也拿得到可用回复。

当然也能看到”模拟”二字的真实边界:充值没有接支付渠道,后端直接按 1 元 = 10 积分加余额;任务与商品列表在 PointsController 里是硬编码的 Map 拼装,points_task / points_goods 表建了但代码没走表查询;chat_record 表建好了却没接入,聊天不消耗积分(扣费仅发生在兑换购买时);AIService@Value 默认值里还躺着一段明文 apikey,上生产前必须收敛到配置中心并轮换密钥。这些留白恰好勾勒出一个”功能先行、再补严谨”的真实开发轨迹——对想用若依快速搭积分体系或做 AI 应用变现原型的人来说,这个项目把”登录领积分 → 充值 → 兑换 AI 能力 → 会员成长”的整条业务动线演示得明明白白,照着改很容易长出自己的正式版本。