Compare commits

..

108 Commits

Author SHA1 Message Date
otto 48314c1a2b Merge pull request 'fix(AI资源广场): 修正zip组件方法调用' (#1152) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-06-03 15:05:33 +08:00
otto e98663e87b fix(AI资源广场): 修正zip组件方法调用 2026-06-01 09:49:49 +08:00
otto a5e2efe2df feat(AI资源广场): 优化AI资源排序 2026-05-28 10:07:47 +08:00
otto f6b7c31022 Merge pull request '修复解析SKILL.md内容时,部分情况下会出现乱码的问题' (#1151) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-28 09:09:19 +08:00
otto 6f881dad5c feat(AI资源广场): 修复解析SKILL.md内容时,部分情况下会出现乱码的问题 2026-05-28 09:06:16 +08:00
otto 1883e78fcb feat(AI资源广场): 解析Skill压缩包时应该仅解析一级目录和二级目录下的Skill.md(大部分Skill压缩包二级目录才为根目录,所以当一级目录不存在Skill.md时再解析二级目录的) 2026-05-27 17:27:13 +08:00
otto 25032096be Merge pull request '解析Skill压缩包时应该仅解析一级目录和二级目录下的Skill.md' (#1150) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-27 17:27:06 +08:00
otto 08c06957a5 Merge pull request '解析Skill.md的描述时,处理多行文本情况' (#1149) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-27 16:47:40 +08:00
otto 2b2cb706aa feat(AI资源广场): 解析Skill.md的描述时,处理多行文本情况 2026-05-27 16:44:21 +08:00
otto aa4afac1ea Merge pull request 'Skill文件大小限制调整为50Mb' (#1148) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-27 16:26:28 +08:00
otto 1c414c2327 feat(AI资源广场): Skill文件大小限制调整为50Mb 2026-05-27 16:24:22 +08:00
otto bb23a02b45 feat(AI资源广场): 暂时不对Skill简介长度进行限制 2026-05-27 16:13:51 +08:00
otto cd9abdce93 Merge pull request '暂时不对Skill简介长度进行限制' (#1147) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-27 16:13:10 +08:00
otto 3b2b3c7d99 feat(AI资源广场): 暂时不对Skill简介长度进行限制 2026-05-27 16:08:28 +08:00
otto 375e1dd103 Merge pull request 'feat(AI资源广场): 暂时不对Skill简介长度进行限制' (#1146) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-27 16:08:01 +08:00
otto b7b2600df6 feat(AI资源广场): 允许资源在不同的资源类型(数据集/模型/SKILL)下可以重名 2026-05-26 14:05:38 +08:00
otto 7aa251f0ab Merge pull request '允许资源在不同的资源类型(数据集/模型/SKILL)下可以重名' (#1144) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-26 14:04:50 +08:00
otto fb74d59394 Merge pull request '优化模型/数据集/SKILL压缩包内目录树排序逻辑' (#1143) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-26 09:06:52 +08:00
otto 7357093ab1 feat(AI资源广场): 优化模型/数据集/SKILL压缩包内目录树排序逻辑:文件夹在前、文件在后,同类型按名称字母不区分大小写排序 2026-05-26 09:02:39 +08:00
otto 675a080b29 feat(AI资源广场): 模型/数据集/SKILL简介允许为空 2026-05-25 17:21:08 +08:00
otto 3af0fabceb Merge pull request '模型/数据集/SKILL简介允许为空' (#1142) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-25 17:20:59 +08:00
otto a349b2e88f feat(AI资源广场): 优化模型/数据集/SKILL压缩包内目录树排序逻辑:文件夹在前、文件在后,同类型按名称字母不区分大小写排序 2026-05-25 16:57:40 +08:00
otto 695328ab47 Merge pull request '优化模型/数据集/SKILL压缩包内目录树排序逻辑' (#1141) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-25 16:56:54 +08:00
otto 0d042f50d6 feat(AI资源广场): SKILL简介允许为空 2026-05-25 16:44:40 +08:00
otto 4e2f5f0e3f Merge pull request '调整模型/数据集编辑接口逻辑,支持修改模型/数据集的介绍内容' (#1140) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-25 16:24:37 +08:00
otto 5459afcf7a feat(AI资源广场): 模型和数据集资源相关功能开发
调整模型/数据集编辑接口逻辑,支持修改模型/数据集的介绍内容(README.md),将覆盖模型/数据集extendData中的content字段
2026-05-25 16:24:35 +08:00
otto 7b112fab92 feat(AI资源广场): 模型和数据集资源相关功能开发
修复查询我的项目聚合统计时漏传专区id的bug
2026-05-25 10:26:28 +08:00
otto 3b1e370f54 Merge pull request '修复查询我的项目聚合统计时漏传专区id的bug' (#1138) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-25 10:26:05 +08:00
otto 331eb3fc37 Merge pull request '新增我的项目聚合统计接口开发' (#1137) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-25 09:44:10 +08:00
otto 4344217563 feat(AI资源广场): 模型和数据集资源相关功能开发
新增我的项目聚合统计接口开发
2026-05-25 09:41:20 +08:00
otto 7204ec7b78 Merge pull request '新增资源(SKILL/模型/数据集)统计接口开发' (#1136) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-22 15:04:11 +08:00
otto b73eece682 feat(AI资源广场): 模型和数据集资源相关功能开发
新增资源(SKILL/模型/数据集)统计接口开发
2026-05-22 14:51:01 +08:00
otto c7983bd62c feat(AI资源广场): 模型和数据集资源相关功能开发
资源的extendData中模型/数据集的fileTreeJson使用JSONObject格式存储
2026-05-21 17:30:56 +08:00
otto 375ab58865 Merge pull request '资源的extendData中模型/数据集的fileTreeJson使用JSONObject格式存储' (#1135) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 17:30:10 +08:00
otto 34cd199659 Merge pull request '资源的extendData中SKILL/模型/数据集均使用大写' (#1134) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 17:22:30 +08:00
otto 7b81b7c73e feat(AI资源广场): 模型和数据集资源相关功能开发
资源的extendData中SKILL/模型/数据集均使用大写
2026-05-21 17:22:18 +08:00
otto 659293e2f6 feat(AI资源广场): 模型和数据集资源相关功能开发
资源领域支持不同领域分类下存在同名资源领域
2026-05-21 16:11:56 +08:00
otto 5fca7912a3 Merge pull request '资源领域支持不同领域分类下存在同名资源领域' (#1133) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 16:11:14 +08:00
otto d2826fccbd feat(AI资源广场): 模型和数据集资源相关功能开发
调整公开查询资源列表和资源详情接口,兼容Skill/模型/数据集
2026-05-21 16:00:18 +08:00
otto 5dee775367 Merge pull request '调整公开查询资源列表和资源详情接口,兼容Skill/模型/数据集' (#1132) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 15:59:47 +08:00
otto 266e0a86a7 feat(AI资源广场): 模型和数据集资源相关功能开发
AI资源判断增加模型和数据集
2026-05-21 15:31:37 +08:00
otto b50ef615b5 Merge pull request 'AI资源判断增加模型和数据集' (#1131) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 15:30:53 +08:00
otto eef339d228 feat(AI资源广场): 模型和数据集资源相关功能开发
修复commons包的版本问题
2026-05-21 15:28:13 +08:00
otto e5bf683bed Merge pull request '修复commons包的版本问题' (#1130) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-21 15:27:26 +08:00
otto 1fa2facb27 feat(AI资源广场): 模型和数据集资源相关功能开发
Skill的提交、撤回、下架、上架接口兼容模型和数据集
2026-05-20 09:43:31 +08:00
otto d7a750bd74 Merge pull request '模型和数据集资源相关功能开发' (#1126) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-20 09:42:38 +08:00
otto 714305492f Merge pull request '模型和数据集资源相关功能开发' (#1125) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-20 09:30:49 +08:00
otto 7c0572fae1 feat(分片上传功能优化): 分片上传秒传成功时新增一条数据库文件记录,指向同一物理文件 2026-05-20 09:29:27 +08:00
otto cd48af644e fix(微服务架构优化): 修复日志系统的JSON解析错误问题 2026-05-20 08:48:46 +08:00
otto c9f1566094 fix(微服务架构优化): 修复日志系统的JSON解析错误问题 2026-05-20 08:42:11 +08:00
otto 3ad087a325 feat(AI资源广场): 模型和数据集资源相关功能开发
调整模型/数据集前台接口逻辑
2026-05-20 08:32:40 +08:00
otto a9dd3c779e feat(AI资源广场): 模型和数据集资源相关功能开发
Skill的提交、撤回、下架、上架接口兼容模型和数据集
2026-05-19 11:14:13 +08:00
otto 96a11998f3 feat(AI资源广场): 模型和数据集资源相关功能开发
完成资源/数据集新建、修改接口开发
2026-05-18 16:37:32 +08:00
otto ec3249fab4 style(AI资源广场): 模型和数据集资源相关功能开发
AiSkill解析方法重命名为AiResource解析方法
2026-05-18 10:43:28 +08:00
otto fac5f3158f feat(AI资源广场): 模型和数据集资源相关功能开发
检索根目录README.md文件时需要忽略大小写
2026-05-18 10:01:26 +08:00
otto 084042891d feat(AI资源广场): 模型和数据集资源相关功能开发
新增解析已上传的模型/数据集ZIP包分析接口:
使用commons-compress组件可以在不解压压缩包的前提下,对超大压缩包通过读取 Central Directory方式快速获取压缩包内,同时直接从根目录直接提取README.md文件
2026-05-18 09:17:17 +08:00
otto ea17f00fd8 feat(AI资源广场): Skill资源相关功能开发
优化资源及资源领域分类逻辑:
新增SKILL资源时,限制领域必须为SKILL类型
2026-05-13 15:42:43 +08:00
otto 42ddbd0b71 Merge pull request 'Skill资源相关功能开发' (#1122) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-13 15:42:11 +08:00
otto 0a31382003 feat(AI资源广场): Skill资源相关功能开发
优化资源及资源领域分类逻辑:
新增SKILL资源时,限制领域必须为SKILL类型
2026-05-13 11:20:36 +08:00
otto 375197c02a Merge pull request '优化资源及资源领域分类逻辑' (#1121) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-13 11:20:22 +08:00
otto ea2eab6942 Merge pull request '优化资源及资源领域分类逻辑' (#1120) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-13 11:15:12 +08:00
otto fbbe78553d feat(AI资源广场): Skill资源相关功能开发
优化资源及资源领域分类逻辑:
新增SKILL资源时,限制领域必须为SKILL类型
2026-05-13 11:14:31 +08:00
otto fcefe43872 feat(AI资源广场): Skill资源相关功能开发
优化资源及资源领域分类逻辑:
1. 保持原资源逻辑,当用户查询资源/资源领域列表时若未传入Category参数则代表查询原资源/资源领域
2. 支持获取所有资源/资源领域,当用户传入Category参数值为ALL时,则查询所有资源/资源领域
2026-05-13 11:10:15 +08:00
otto be1ed2ce2c Merge pull request '评论附件保持和其他模块评论附件字段一致' (#1119) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 17:03:42 +08:00
欧涛 3126082f61 feat(AI资源广场): Skill资源相关功能开发
评论附件保持和其他模块评论附件字段一致
2026-05-11 17:02:18 +08:00
otto 43d2eeeb3b Merge pull request '完善专区评论功能' (#1118) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 16:25:32 +08:00
欧涛 d20a84f214 feat(AI资源广场): Skill资源相关功能开发
完善专区评论功能
2026-05-11 16:25:26 +08:00
otto 1b573576d9 Merge pull request '完善专区评论功能' (#1117) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 15:24:48 +08:00
欧涛 2acfd3c80d feat(AI资源广场): Skill资源相关功能开发
完善专区评论功能
2026-05-11 15:24:35 +08:00
otto 6ff1d78b20 Merge pull request '完善专区评论功能' (#1116) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 15:10:19 +08:00
欧涛 a07c47b6b7 feat(AI资源广场): Skill资源相关功能开发
完善专区评论功能
2026-05-11 15:09:58 +08:00
otto a5caeefb3c Merge pull request '解析Skill压缩包文件时,自动解析压缩包内的name,自动填充,减少用户内容输入' (#1115) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 11:40:55 +08:00
欧涛 41ec65b242 feat(AI资源广场): Skill资源相关功能开发
解析Skill压缩包文件时,自动解析压缩包内的name,自动填充,减少用户内容输入
2026-05-11 11:36:32 +08:00
otto 1458b34950 Merge pull request '当用户在指定专区检查专区权限时,将用户自动加入该专区会员(指定专区id通过Nacos配置)' (#1114) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 10:40:59 +08:00
欧涛 0643fda6b6 feat(AI资源广场): Skill资源相关功能开发
当用户在指定专区检查专区权限时,将用户自动加入该专区会员(指定专区id通过Nacos配置)
2026-05-11 10:40:38 +08:00
otto 582835acf8 Merge pull request '新增接口:支持传入资源id列表,查询资源是否已点赞' (#1113) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-11 09:11:26 +08:00
欧涛 bc7c212bb6 feat(AI资源广场): Skill资源相关功能开发
新增接口:支持传入资源id列表,查询资源是否已点赞
2026-05-11 09:11:00 +08:00
otto f934f3149d Merge pull request '资源领域新增资源分类属性,支持通过资源分类区分' (#1112) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 16:34:06 +08:00
欧涛 904bbf1cab feat(AI资源广场): Skill资源相关功能开发
资源领域新增资源分类属性,支持通过资源分类区分SKILL/MODEL/DATASET/NULL对应的资源领域
2026-05-09 16:33:49 +08:00
otto 6e38e33b60 Merge pull request '新增上架资源接口,同时已下架资源修改后变成待审核状态' (#1111) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 15:35:57 +08:00
欧涛 7628e38d3a feat(AI资源广场): Skill资源相关功能开发
新增上架资源接口,同时已下架资源修改后变成待审核状态
2026-05-09 15:35:38 +08:00
otto 5c38a3ae6f Merge pull request 'feat(AI资源广场): Skill资源相关功能开发' (#1110) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 15:11:22 +08:00
欧涛 fb9da470e1 feat(AI资源广场): Skill资源相关功能开发
资源审核状态参数支持传入all查询所有审核状态的资源
2026-05-09 15:10:43 +08:00
欧涛 22f095b01d feat(AI资源广场): Skill资源相关功能开发
资源领域新增资源分类属性,支持通过资源分类区分SKILL/MODEL/DATASET/NULL对应的资源领域
2026-05-09 14:56:27 +08:00
otto 969034f319 Merge pull request '获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回' (#1109) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 14:39:55 +08:00
欧涛 c39c826bdb feat(AI资源广场): Skill资源相关功能开发
获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回
2026-05-09 14:38:49 +08:00
欧涛 b7e2541c1d feat(AI资源广场): Skill资源相关功能开发
资源新增草稿状态,撤回审核后资源将变为草稿状态,并且在重新编辑后变为待审核状态
2026-05-09 13:51:01 +08:00
otto 0e1966e9fb Merge pull request '获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回' (#1108) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 11:41:40 +08:00
欧涛 91a96be75f feat(AI资源广场): Skill资源相关功能开发
获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回
2026-05-09 11:41:28 +08:00
otto c930ebe0e8 Merge pull request '获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回' (#1107) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 11:24:25 +08:00
欧涛 9f42c51a5f feat(AI资源广场): Skill资源相关功能开发
获取Skill资源列表时接口不返回Skill详情(Skill.md和Skill文件树),只有在查询Skill资源详情时才返回
2026-05-09 11:24:05 +08:00
欧涛 5a55ea027b feat(AI资源广场): Skill资源相关功能开发
管理员获取项目聚合列表和资源列表时支持查询“我的”相关数据
2026-05-09 11:07:18 +08:00
otto 6ef1d26e65 Merge pull request '合并超算专区相关修改' (#1106) from otto/microservices:aiResourceMRCS into aiResourceMRCS 2026-05-09 09:17:56 +08:00
欧涛 cecc14868a feat(AI资源广场): Skill资源相关功能开发
合并超算相关代码(支持项目聚合审核)
2026-05-09 09:13:02 +08:00
欧涛 b3f5a4898f Merge branch 'chaosuan_zone' into aiResourceMRCS
# Conflicts:
#	microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/FrontController.java
#	microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/OpenController.java
#	microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceDataVo.java
#	microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/mapper/ZoneResourceMapper.java
#	microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneResourceMapper.xml
2026-05-09 08:58:56 +08:00
otto 57dad99399 Merge pull request '修复Skill无法下载的问题' (#1103) from otto/microservices:aiResource into aiResource 2026-05-08 13:59:36 +08:00
欧涛 965cedc275 feat(AI资源广场): Skill资源相关功能开发
修复Skill无法下载的问题
2026-05-08 13:59:16 +08:00
otto b26825084b Merge pull request 'feat(AI资源广场): Skill资源相关功能开发' (#1100) from otto/microservices:aiResource into aiResource 2026-05-07 10:37:19 +08:00
欧涛 53ff26058f feat(AI资源广场): Skill资源相关功能开发
删除老版本评论相关内容
2026-05-07 10:34:41 +08:00
欧涛 46b1b9ed81 feat(AI资源广场): Skill资源相关功能开发
1. 新增Skill资源复用原资源新增逻辑
2. 更新Skill资源复用原资源更新逻辑
3. 获取资源列表接口增加资源分类查询参数
2026-05-07 10:23:33 +08:00
欧涛 20bd41ebf7 feat(AI资源广场): Skill资源相关功能开发
资源下载次数基于文件下载次数进行统计
2026-05-07 08:40:08 +08:00
欧涛 a416b7c856 feat(AI资源广场): Skill资源相关功能开发
Skill资源特有字段使用extendData进行存储
2026-05-06 16:32:06 +08:00
欧涛 d662395f1e feat(AI资源广场): Skill资源相关功能开发
Skill资源特有字段使用extendData进行存储
2026-05-06 16:31:49 +08:00
欧涛 58bdc10a4b feat(AI资源广场): Skill资源相关功能开发
从Skill.md中提取简介
2026-05-06 15:28:26 +08:00
欧涛 343d31024e feat(AI资源广场): Skill资源相关功能开发
Skill文件通过fileId关联
2026-05-06 14:47:21 +08:00
欧涛 020472c4c1 feat(AI资源广场): Skill资源相关功能开发
解析Skill压缩包时,同步将文件上传至File微服务,并返回文件标识
2026-05-06 11:30:24 +08:00
欧涛 356ffd8915 feat(AI资源广场): Skill资源相关功能开发
资源评论基于Gitlink评论通用化改造
2026-04-30 16:39:07 +08:00
欧涛 3a2560f700 feat(AI资源广场): Skill资源相关功能开发
1. 完成Skill资源创建、上传、修改、删除及查询功能开发
2. 完成Skill Zip包解析功能开发
3. 完成资源点赞功能开发
4. 完成资源评论功能开发
2026-04-30 14:16:21 +08:00
180 changed files with 4509 additions and 7963 deletions

View File

@ -9,8 +9,6 @@ import com.microservices.system.api.factory.RemoteCmsFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户服务
*
@ -164,18 +162,4 @@ public interface RemoteCmsService {
@PutMapping("/project/changeOrgRole/user/{userId}/operate/{operate}")
R<Boolean> changeUserOrgRole(@PathVariable("userId") Long userId, @PathVariable("operate") int operate
, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 首页文章合并列表接收置顶文章 docId 有序列表返回合并去重后的结果
* Zone 服务 /open/getTopDoc 改造后调用
*
* @param zoneId 专区ID
* @param topDocIds 置顶文章 docId 有序列表
* @param source 来源
* @return 合并后的首页文章 JSONObject 列表
*/
@PostMapping("/doc/homePageDocMergeList/{zoneId}")
R<List<JSONObject>> selectHomePageDocMergeList(@PathVariable("zoneId") Long zoneId,
@RequestBody List<Long> topDocIds,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@ -52,6 +52,10 @@ public interface RemoteFileService {
@GetMapping("/open/getFile/{fileId}")
public R<SysFileInfo> getFile(@PathVariable("fileId") Long fileId);
@GetMapping("/common/getFileDetail/{fileId}")
public R<SysFileInfo> getFileDetail(@PathVariable("fileId") Long fileId,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 根据文件Id获取文件信息
*

View File

@ -57,15 +57,6 @@ public interface RemoteUserService {
@GetMapping("/user/getSysUserByUserId/{userId}")
public R<SysUser> getSysUserByUserId(@PathVariable("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户ID数组批量获取用户信息POST方法解决URL长度限制
*
* @param userIds 用户ID数组
* @param source 请求来源
* @return 结果
*/
@PostMapping("/user/getSysUserListByUserIds")
R<List<SysUser>> postSysUserListByUserIds(@RequestBody Long[] userIds, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 组织下新增用户身份
@ -73,7 +64,7 @@ public interface RemoteUserService {
* @param deptId
* @param userId
* @param roleKey
* @param source 请求来源
* @param source 请求来源
* @return 结果
*/
@PostMapping("/SysUserDeptRole/dept/{deptId}/user/{userId}/role/{roleKey}")
@ -83,13 +74,14 @@ public interface RemoteUserService {
, @PathVariable("roleKey") String roleKey
, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 组织下删除用户身份
*
* @param deptId
* @param userId
* @param roleKey
* @param source 请求来源
* @param source 请求来源
* @return 结果
*/
@DeleteMapping("/SysUserDeptRole/dept/{deptId}/user/{userId}/role/{roleKey}")
@ -99,16 +91,18 @@ public interface RemoteUserService {
@PathVariable("roleKey") String roleKey,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 注册用户信息
*
* @param sysUser 用户信息
* @param source 请求来源
* @param source 请求来源
* @return 结果
*/
@PostMapping("/user/register")
public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过GitLinkToken获取本系统Token
*
@ -129,6 +123,7 @@ public interface RemoteUserService {
@GetMapping("/SysUserDeptRole/userByUserName/{userName}/list")
public R<List<SysUserDeptRole>> getSysUserDeptRoleListByUserName(@PathVariable("userName") String userName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户名查询用户下第一个身份
*
@ -200,7 +195,7 @@ public interface RemoteUserService {
/**
* 通过GitLink用户Id创建用户
*
* @param gitLinkUserId GitLinkUserId
* @param gitLinkUserId GitLink用户Id
* @param source 请求来源
* @return 系统用户
*/
@ -211,7 +206,7 @@ public interface RemoteUserService {
* 根据角色Key获取菜单权限集合
*
* @param roleKey 角色Key
* @param source 请求来源
* @param source 请求来源
* @return 菜单权限集合
*/
@GetMapping("/menu/roleMenuPermissionByRoleKey/{roleKey}")

View File

@ -10,6 +10,10 @@ import lombok.Data;
@Data
public class SysFile
{
/**
* 文件标识
*/
private Long fileId;
/**
* 文件标识
*/

View File

@ -9,8 +9,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 内容管理服务降级处理
*
@ -90,11 +88,6 @@ public class RemoteCmsFallbackFactory implements FallbackFactory<RemoteCmsServic
public R<Boolean> changeUserOrgRole(Long userId, int operate, String source) {
return R.fail("更新组织权限失败:" + throwable.getMessage());
}
@Override
public R<List<JSONObject>> selectHomePageDocMergeList(Long zoneId, List<Long> topDocIds, String source) {
return R.fail("获取首页文章合并列表失败:" + throwable.getMessage());
}
};
}
}

View File

@ -46,6 +46,11 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
return R.fail("根据文件Id获取文件信息失败:" + throwable.getMessage());
}
@Override
public R<SysFileInfo> getFileDetail(Long fileId, String source) {
return R.fail("根据文件id获取文件详细信息失败:" + throwable.getMessage());
}
@Override
public R<SysFileInfo> getFileByFileIdentifier(String fileIdentifier, String source) {
return R.fail("根据文件标识获取文件信息失败:" + throwable.getMessage());

View File

@ -52,12 +52,6 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<List<SysUser>> postSysUserListByUserIds(Long[] userIds, String source) {
return R.fail("批量获取用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> addUserIdentify(Long deptId, Long userId, String roleKey, String source) {
return R.fail("组织下新增用户身份失败:" + throwable.getMessage());

View File

@ -80,10 +80,6 @@ public class CacheConstants {
* 通过组织Id获取专区详情JSON对象
*/
public final static String ZONE_JSON_OF_DEPT_ID_KEY = "zoneJSONOfDeptId:";
/**
* 积分发放部门
*/
public final static String ZONE_POINTS_DEPT_ID_KEY = "zonePointsDeptId";
/**
* 内容管理同步缓存前缀
*/
@ -249,18 +245,6 @@ public class CacheConstants {
return ZONE_PROJECT_SORT_BY_SCORE + "*:" + zoneId + ":*";
}
/**
* 专区统计数据缓存前缀
*/
private final static String ZONE_STATISTICS_KEY = "zone:statistics:";
/**
* 获取专区统计数据缓存key
*/
public static String getZoneStatisticsKey(Long zoneId) {
return ZONE_STATISTICS_KEY + zoneId;
}
/**
* 文件打包是否完成0代表未完成1代表已完成-1代表打包失败需要重新打包
*/
@ -270,6 +254,15 @@ public class CacheConstants {
return PACKAGE_FILE_IS_FINISH + fileIdentifier;
}
/**
* 项目点赞统计缓存 Key前缀
*/
private final static String PROJECT_STATISTICS_LIKE_COUNT = "project_statistics_like_count:";
public static String getProjectStatisticsLikeCount(Long zoneId, String username) {
return PROJECT_STATISTICS_LIKE_COUNT + zoneId + "-" + username;
}
// 全局资源数据缓存最近一年统计数据
public final static String GLOBAL_RESOURCES_DATA_KEY = "GLOBAL_RESOURCES_DATA:";

View File

@ -171,12 +171,4 @@ public class UserConstants {
* 文章管理-审核文章权限
*/
public static final String CMS_PERMS_DOCS_AUDIT = "cms:doc:audit";
/**
* 专区管理-审核项目权限
*/
public static final String ZONE_PERMS_PROJECT_AUDIT = "zone:project:audit";
/**
* 专区管理-审核资源权限
*/
public static final String ZONE_PERMS_RESOURCE_AUDIT = "zone:resource:audit";
}

View File

@ -8,7 +8,7 @@ package com.microservices.common.core.enums;
public enum DocAndZoneOperation
{
OPERATION_CREATE("创建", "create"), OPERATION_UPDATE("更新", "update"),
OPERATION_DELETE("删除", "delete"), OPERATION_NON_REPO_UPDATE("非仓库更新", "nonRepoUpdate");
OPERATION_DELETE("删除", "delete");
private final String operationName;
private final String operationCode;

View File

@ -37,14 +37,17 @@ import java.util.Map;
*/
@Aspect
@Component
public class LogAspect
{
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/** 排除敏感属性字段 */
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
/**
* 排除敏感属性字段
*/
public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"};
/** 计算操作消耗时间 */
/**
* 计算操作消耗时间
*/
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
@Autowired
@ -54,8 +57,7 @@ public class LogAspect
* 处理请求前执行
*/
@Before(value = "@annotation(controllerLog)")
public void boBefore(JoinPoint joinPoint, Log controllerLog)
{
public void boBefore(JoinPoint joinPoint, Log controllerLog) {
TIME_THREADLOCAL.set(System.currentTimeMillis());
}
@ -65,42 +67,41 @@ public class LogAspect
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
{
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
handleLog(joinPoint, controllerLog, null, jsonResult);
}
/**
* 拦截异常操作
*
*
* @param joinPoint 切点
* @param e 异常
* @param e 异常
*/
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
{
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
handleLog(joinPoint, controllerLog, e, null);
}
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
{
try
{
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
try {
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址
String ip = IpUtils.getIpAddr();
operLog.setOperIp(ip);
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
if (ServletUtils.getRequest() != null) {
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
}
String username = SecurityUtils.getUsername();
if (StringUtils.isNotBlank(username))
{
if (StringUtils.isNotBlank(username)) {
operLog.setOperName(username);
}
if (e != null)
{
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
@ -108,36 +109,29 @@ public class LogAspect
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 设置消耗时间
operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
// 保存数据库
asyncLogService.saveSysLog(operLog);
}
catch (Exception exp)
{
} catch (Exception exp) {
// 记录本地异常日志
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
finally
{
} finally {
TIME_THREADLOCAL.remove();
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param log 日志
*
* @param log 日志
* @param operLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
{
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception {
// 设置action动作
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
@ -145,36 +139,30 @@ public class LogAspect
// 设置操作人类别
operLog.setOperatorType(log.operatorType().ordinal());
// 是否需要保存request参数和值
if (log.isSaveRequestData())
{
if (log.isSaveRequestData()) {
// 获取参数的信息传入到数据库中
setRequestValue(joinPoint, operLog, log.excludeParamNames());
}
// 是否需要保存response参数和值
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
{
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) {
operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
}
}
/**
* 获取请求的参数放到log中
*
*
* @param operLog 操作日志
* @throws Exception 异常
*/
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
{
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception {
String requestMethod = operLog.getRequestMethod();
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
if (StringUtils.isEmpty(paramsMap)
&& (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
{
&& (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))) {
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
}
else
{
} else {
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
}
}
@ -182,64 +170,53 @@ public class LogAspect
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{
String params = "";
if (paramsArray != null && paramsArray.length > 0)
{
for (Object o : paramsArray)
{
if (StringUtils.isNotNull(o) && !isFilterObject(o))
{
try
{
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) {
StringBuilder params = new StringBuilder();
if (paramsArray != null) {
for (Object o : paramsArray) {
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
try {
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params += jsonObj.toString() + " ";
}
catch (Exception e)
{
// 清洗控制字符保留常见空白字符\t, \n, \r
// ASCII 0-8, 11-12, 14-31, 127 是控制字符需要去除
String cleaned = jsonObj.replaceAll("[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F\\x7F]", "");
params.append(cleaned).append(" ");
} catch (Exception e) {
// 记录日志而非静默吞掉便于排查问题
log.error("序列化操作日志参数失败: {}", e.getMessage());
}
}
}
}
return params.trim();
return params.toString().trim();
}
/**
* 忽略敏感属性
*/
public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
{
public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames) {
return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
}
/**
* 判断是否需要过滤的对象
*
*
* @param o 对象信息
* @return 如果是需要过滤的对象则返回true否则返回false
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object o)
{
public boolean isFilterObject(final Object o) {
Class<?> clazz = o.getClass();
if (clazz.isArray())
{
if (clazz.isArray()) {
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
}
else if (Collection.class.isAssignableFrom(clazz))
{
} else if (Collection.class.isAssignableFrom(clazz)) {
Collection collection = (Collection) o;
for (Object value : collection)
{
for (Object value : collection) {
return value instanceof MultipartFile;
}
}
else if (Map.class.isAssignableFrom(clazz))
{
} else if (Map.class.isAssignableFrom(clazz)) {
Map map = (Map) o;
for (Object value : map.entrySet())
{
for (Object value : map.entrySet()) {
Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile;
}

View File

@ -115,7 +115,8 @@ public class AuthLogic {
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission) {
public boolean hasPermi(String permission)
{
return hasPermi(tokenService.getMenuPermissions(), permission);
}
@ -125,8 +126,10 @@ public class AuthLogic {
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public void checkPermi(String permission) {
if (!hasPermi(tokenService.getMenuPermissions(), permission)) {
public void checkPermi(String permission)
{
if (!hasPermi(tokenService.getMenuPermissions(), permission))
{
throw new NotPermissionException(permission);
}
}
@ -150,10 +153,13 @@ public class AuthLogic {
*
* @param permissions 权限列表
*/
public void checkPermiAnd(String... permissions) {
public void checkPermiAnd(String... permissions)
{
Set<String> permissionList = tokenService.getMenuPermissions();
for (String permission : permissions) {
if (!hasPermi(permissionList, permission)) {
for (String permission : permissions)
{
if (!hasPermi(permissionList, permission))
{
throw new NotPermissionException(permission);
}
}
@ -164,10 +170,13 @@ public class AuthLogic {
*
* @param permissions 权限码数组
*/
public void checkPermiOr(String... permissions) {
public void checkPermiOr(String... permissions)
{
Set<String> permissionList = tokenService.getMenuPermissions();
for (String permission : permissions) {
if (hasPermi(permissionList, permission)) {
for (String permission : permissions)
{
if (hasPermi(permissionList, permission))
{
return;
}
}
@ -182,7 +191,8 @@ public class AuthLogic {
* @param role 角色标识
* @return 用户是否具备某角色
*/
public boolean hasRole(String role) {
public boolean hasRole(String role)
{
return hasRole(tokenService.getRolePermissions(), role);
}
@ -215,10 +225,13 @@ public class AuthLogic {
*
* @param roles 角色标识数组
*/
public void checkRoleAnd(String... roles) {
public void checkRoleAnd(String... roles)
{
Set<String> roleList = tokenService.getRolePermissions();
for (String role : roles) {
if (!hasRole(roleList, role)) {
for (String role : roles)
{
if (!hasRole(roleList, role))
{
throw new NotRoleException(role);
}
}
@ -229,14 +242,18 @@ public class AuthLogic {
*
* @param roles 角色标识数组
*/
public void checkRoleOr(String... roles) {
public void checkRoleOr(String... roles)
{
Set<String> roleList = tokenService.getRolePermissions();
for (String role : roles) {
if (hasRole(roleList, role)) {
for (String role : roles)
{
if (hasRole(roleList, role))
{
return;
}
}
if (roles.length > 0) {
if (roles.length > 0)
{
throw new NotRoleException(roles);
}
}
@ -306,9 +323,6 @@ public class AuthLogic {
public boolean hasUserIdentity(Long deptId, String roleKey) {
LoginUser loginUser = getLoginUser();
List<SysUserDeptRole> sysUserDeptRoleList = tokenService.getAllUserIdentity(loginUser.getUsername());
if (sysUserDeptRoleList == null) {
return false;
}
return sysUserDeptRoleList.stream()
.anyMatch(x -> {
if (x.getDeptId() != null && x.getSysRole() != null && x.getDeptId().equals(deptId)) {

View File

@ -3,6 +3,7 @@ package com.microservices.common.security.feign;
import feign.RequestInterceptor;
import feign.codec.Encoder;
import feign.form.FormEncoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
@ -33,6 +34,6 @@ public class FeignAutoConfiguration
// 重要的是返回类型要是 Encoder 并且实现类必须是 FormEncoder 或者其子类
@Bean
public Encoder feignFormEncoder() {
return new FormEncoder(new SpringEncoder(messageConverters));
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}

View File

@ -11,7 +11,6 @@ import com.microservices.common.core.utils.uuid.IdUtils;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.interceptor.HeaderInterceptor;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.RemoteUserService;
import com.microservices.system.api.domain.SysRole;
import com.microservices.system.api.domain.SysUser;
@ -39,8 +38,6 @@ public class TokenService {
private RedisService redisService;
@Autowired
private RemoteUserService remoteUserService;
@Autowired
private RemoteDeptService remoteDeptService;
protected static final long MILLIS_SECOND = 1000;
@ -332,16 +329,4 @@ public class TokenService {
}
return loginUser.getSysUser();
}
public Boolean hasDeptPerms(Long deptId, String perms) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Boolean hasPerms = FeignUtils.getReturnData(
remoteDeptService.checkUserInDeptOrParentDeptHasPerms(deptId, loginUser.getUserId(), perms, SecurityConstants.INNER)
);
if (hasPerms == null) {
hasPerms = false;
}
return hasPerms;
}
}

View File

@ -18,7 +18,6 @@ import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
@ -108,13 +107,23 @@ public class CmsDocController extends BaseController {
@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"),
})
public GenericsTableDataInfo<CmsDocAllDto> docListByZone(
public TableDataInfo docListByZone(
@ApiParam(name = "zoneId", value = "专区Id") @PathVariable("zoneId") Long zoneId
, CmsDocSearchVo cmsDocSearchVo) {
Long deptId = cmsDocService.getDeptIdByZoneId(zoneId);
cmsDocSearchVo.setIsOpen(true);
cmsDocSearchVo.setIsOpen(false);
startPage();
return cmsDocService.selectAllDocList(deptId, cmsDocSearchVo);
List<CmsDocAllDto> list = cmsDocService.selectCmsDocListByDept(deptId, cmsDocSearchVo);
list.forEach(x -> {
String docDetailUrl = cmsDocService.getDocDetailUrl(x.getDeptId(), x.getId());
x.setDocDetailUrl(docDetailUrl);
Boolean editable = cmsDocService.isCmsDocEditable(x);
x.setEditable(editable);
});
int count = cmsDocService.selectCmsDocCountByDept(deptId, cmsDocSearchVo);
return getDataTable(list, count);
}
/**
@ -210,7 +219,7 @@ public class CmsDocController extends BaseController {
@ApiOperation("更新文章")
public AjaxResult edit(@ApiParam(name = "id", value = "文章Id") @PathVariable Long id,
@ApiParam(name = "cmsDoc", value = "文章实体对象") @RequestBody CmsDocDto cmsDocDto) {
return success(cmsDocService.updateCmsDoc(id, cmsDocDto));
return toAjax(cmsDocService.updateCmsDoc(id, cmsDocDto));
}
/**
@ -307,24 +316,6 @@ public class CmsDocController extends BaseController {
return R.ok(cmsDocJSONObject);
}
/**
* 内部接口首页文章合并列表接收置顶文章 docId 有序列表返回合并去重后的结果
* Zone 服务 Feign 调用用于 /open/getTopDoc 改造
*/
@InnerAuth
@PostMapping("/homePageDocMergeList/{zoneId}")
@ApiOperation(value = "首页文章合并列表", hidden = true)
public R<List<JSONObject>> selectHomePageDocMergeList(
@PathVariable("zoneId") Long zoneId,
@RequestBody List<Long> topDocIds) {
List<CmsDocBaseDto> list = cmsDocService.selectHomePageDocMergeList(zoneId, topDocIds);
List<JSONObject> result = new ArrayList<>();
for (CmsDocBaseDto dto : list) {
result.add(JSONObject.from(dto));
}
return R.ok(result);
}
/**
* 通过组织Id获取专区下文章阅读数量
*

View File

@ -121,19 +121,6 @@ public class OpenController extends BaseController {
return getAllGenericsDataTableToPage(list);
}
/**
* 查询文章列表不区分栏目
*/
@GetMapping("/zone/{zoneId}/allDocList")
@ApiOperation("查询文章列表(不区分栏目)")
public GenericsTableDataInfo<CmsDocAllDto> allDocList(@ApiParam(name = "zoneId", value = "专区Id") @PathVariable("zoneId") Long zoneId,
CmsDocSearchVo cmsDocSearchVo) {
Long deptId = cmsDocService.getDeptIdByZoneId(zoneId);
cmsDocSearchVo.setIsOpen(true);
startPage();
return cmsDocService.selectAllDocList(deptId, cmsDocSearchVo);
}
/**
* 查询首页文章列表
*/

View File

@ -83,10 +83,4 @@ public class CmsDocSearchVo {
*/
@ApiModelProperty("关键词")
private String keywords;
/**
* 排除文章Id
*/
@ApiModelProperty(value = "排除文章Id", hidden = true)
private Long excludeId;
}

View File

@ -24,14 +24,6 @@ public interface CmsDocMapper {
*/
public CmsDoc selectCmsDocById(Long id);
/**
* 批量查询文章信息
*
* @param ids 文章ID列表
* @return 文章信息列表
*/
List<CmsDoc> selectCmsDocByIds(@Param("ids") List<Long> ids);
/**
* 查询文章信息列表
*
@ -91,11 +83,6 @@ public interface CmsDocMapper {
CmsDoc selectCmsDocByFilePathAndDeptId(@Param("filePath") String filePath, @Param("deptId") Long deptId);
/**
* 按文章名+deptId查询忽略dirName用于Webhook防重判断
*/
CmsDoc selectCmsDocByNameAndDeptIdIgnoreDirName(@Param("name") String name, @Param("deptId") Long deptId);
List<CmsDoc> selectHotCmsDocList(CmsDoc cmsDocInput);
List<CmsDoc> selectCmsDocDirByDeptIdAndInName(@Param("deptId") Long deptId, @Param("cmsDirNameList") List<String> cmsDirNameList);

View File

@ -101,36 +101,4 @@ public interface ICmsAsyncService {
void pushDocDataSearchEngine(CmsDoc cmsDoc);
void clearTmpDoc(CmsProject cmsProject,List<CmsDoc> tmpDocList);
/**
* 异步增加文章发布积分
*
* @param deptId 组织ID
* @param createBy 创建人用户名
* @param docId 文章ID
* @param subjectDesc 文章标题
*/
void addPublishDocPointsAsync(Long deptId, String createBy, Long docId, String subjectDesc);
/**
* 异步增加文章浏览积分每满100次+2上限50
*
* @param deptId 组织ID
* @param createBy 创建人用户名
* @param docId 文章ID
* @param docName 文章名称
* @param totalVisits 累计阅读次数
* @param pointsTriggerCount 当前第几次增加积分
*/
void addVisitsDocPointsAsync(Long deptId, String createBy, Long docId, String docName, Long totalVisits);
/**
* 异步增加文章被设为精选的积分
*
* @param deptId 组织ID
* @param createBy 创建人用户名
* @param docId 文章ID
* @param subjectDesc 文章标题
*/
void addFeaturedDocPointsAsync(Long deptId, String createBy, Long docId, String subjectDesc);
}

View File

@ -5,7 +5,6 @@ import com.microservices.cms.doc.domain.*;
import com.microservices.cms.doc.domain.gitlink.EntryDto;
import com.microservices.cms.doc.domain.gitlink.FileEntryDto;
import com.microservices.cms.project.domain.CmsProject;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@ -57,9 +56,9 @@ public interface ICmsDocService {
*
* @param id
* @param cmsDocDto 文章信息
* @return 结果 文章id
* @return 结果
*/
public Long updateCmsDoc(Long id, CmsDocDto cmsDocDto);
public boolean updateCmsDoc(Long id, CmsDocDto cmsDocDto);
/**
* 批量删除文章信息
@ -145,15 +144,6 @@ public interface ICmsDocService {
*/
List<CmsDocBaseDto> selectHomePageDocList(Long deptId);
/**
* 查询首页文章合并列表积分置顶文章 + 首页推荐文章自动去重置顶在前
*
* @param zoneId 专区ID
* @param topDocIds 置顶文章 docId 有序列表前端按此顺序排列
* @return 合并后的首页文章列表isTop=true 标识置顶文章
*/
List<CmsDocBaseDto> selectHomePageDocMergeList(Long zoneId, List<Long> topDocIds);
/**
* 初始化栏目
*
@ -208,8 +198,6 @@ public interface ICmsDocService {
*/
List<CmsDocAllDto> selectCmsDocListByDept(Long deptId, CmsDocSearchVo cmsDocSearchVo);
GenericsTableDataInfo<CmsDocAllDto> selectAllDocList(Long deptId, CmsDocSearchVo cmsDocSearchVo);
/**
* 查询专区下文章数量
*

View File

@ -35,7 +35,6 @@ import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.RemoteUserService;
import com.microservices.system.api.RemoteZoneService;
import com.microservices.system.api.utils.FeignUtils;
import org.apache.http.client.config.RequestConfig;
@ -98,8 +97,6 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService {
@Autowired
private RemoteZoneService remoteZoneService;
@Autowired
private RemoteUserService remoteUserService;
@Autowired
private RequestConfig config;
/**
@ -256,16 +253,7 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService {
}
CmsDoc cmsDoc = cmsDocMapper.selectCmsDocByNameAndDeptId(CmsUtils.getFileNameNoSuffix(entry.getName()), cmsProject.getDeptId(), dirName);
if (cmsDoc == null) {
// 防重按文章名+deptId查一次排除正在移动栏目的已有记录
String docName = CmsUtils.getFileNameNoSuffix(entry.getName());
CmsDoc existingDoc = cmsDocMapper.selectCmsDocByNameAndDeptIdIgnoreDirName(docName, cmsProject.getDeptId());
if (existingDoc != null) {
existingDoc.setDirName(dirName);
existingDoc.setFilePath(dirName + "/" + existingDoc.getFileName());
cmsDocMapper.updateCmsDoc(existingDoc);
} else {
syncCreateDoc(entry, dirName, cmsProject.getDeptId(), fileEntry.getLast_commit());
}
syncCreateDoc(entry, dirName, cmsProject.getDeptId(), fileEntry.getLast_commit());
}
}
} catch (Exception e) {
@ -738,8 +726,8 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService {
if (isChangeName || isChangeDir) {
oldCmsDoc = renameAndChangeDirCmsDoc(oldCmsDoc, cmsProject, newName, newDirName, branchName);
// 立即更新数据库中的dirName/filePath避免GitLink Webhook回调时查不到记录导致重复INSERT
cmsDocMapper.updateCmsDoc(oldCmsDoc);
//todo 此处是否需要更新数据库待讨论
//updateCmsCommonDatabase(oldCmsDoc);
}
boolean isChangeContent = false;
@ -1087,127 +1075,4 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService {
}
}
/**
* 检查是否为积分部门
*
* @param deptId 部门ID
* @return 是否为积分部门
*/
private boolean isPointsDept(Long deptId) {
Long cachedPointsDeptId = redisService.getCacheObject(CacheConstants.ZONE_POINTS_DEPT_ID_KEY);
return cachedPointsDeptId != null && cachedPointsDeptId > 0 && cachedPointsDeptId.equals(deptId);
}
@Async
@Override
public void addPublishDocPointsAsync(Long deptId, String createBy, Long docId, String subjectDesc) {
try {
if (deptId == null || createBy == null) {
logger.warn("文章审核通过增加积分失败deptId或createBy为空docId={}", docId);
return;
}
// 检查是否为积分部门
if (!isPointsDept(deptId)) {
logger.info("文章审核通过增加积分跳过非积分部门deptId={}docId={}", deptId, docId);
return;
}
// 获取用户ID
com.microservices.system.api.domain.SysUser sysUser = FeignUtils.getReturnData(
remoteUserService.getSysUserByUserName(createBy, SecurityConstants.INNER));
if (sysUser == null || sysUser.getUserId() == null) {
logger.warn("文章审核通过增加积分失败未找到用户信息createBy={}docId={}", createBy, docId);
return;
}
// 直接写入 Redis 积分队列 Zone 模块定时任务消费
JSONObject task = new JSONObject();
task.put("sourceType", CmsConstants.PUBLISH_DOC);
task.put("userId", sysUser.getUserId());
task.put("deptId", deptId);
task.put("sourceId", docId);
task.put("subjectDesc", subjectDesc);
task.put("operatorId", sysUser.getUserId());
redisService.leftPush(CmsConstants.ZONE_POINTS_ASYNC_QUEUE_KEY, task.toJSONString());
logger.info("文章审核通过增加积分任务已写入队列docId={}userId={}deptId={}", docId, sysUser.getUserId(), deptId);
} catch (Exception e) {
// 捕获异常确保不影响主事务
logger.error("文章审核通过增加积分异常docId={}", docId, e);
}
}
@Async
@Override
public void addVisitsDocPointsAsync(Long deptId, String createBy, Long docId, String docName, Long totalVisits) {
try {
if (deptId == null || createBy == null) {
logger.warn("文章浏览增加积分失败参数不合法deptId={}createBy={}", deptId, createBy);
return;
}
// 检查是否为积分部门
if (!isPointsDept(deptId)) {
logger.info("文章浏览增加积分跳过非积分部门deptId={}docId={}", deptId, docId);
return;
}
// 获取用户ID
com.microservices.system.api.domain.SysUser sysUser = FeignUtils.getReturnData(
remoteUserService.getSysUserByUserName(createBy, SecurityConstants.INNER));
if (sysUser == null || sysUser.getUserId() == null) {
logger.warn("文章浏览增加积分失败未找到用户信息createBy={}docId={}", createBy, docId);
return;
}
// 直接写入 Redis 积分队列 Zone 模块定时任务消费
JSONObject task = new JSONObject();
task.put("sourceType", CmsConstants.VISITS_DOC);
task.put("userId", sysUser.getUserId());
task.put("deptId", deptId);
task.put("sourceId", docId);
// JSONObject sourceData = new JSONObject();
// sourceData.put("totalVisits", totalVisits);
// sourceData.put("currentIncrement", pointsTriggerCount);
task.put("sourceData", totalVisits);
task.put("subjectDesc", docName);
task.put("operatorId", SecurityUtils.getUserId());
redisService.leftPush(CmsConstants.ZONE_POINTS_ASYNC_QUEUE_KEY, task.toJSONString());
logger.info("文章浏览增加积分任务已写入队列docId={}userId={}deptId={}totalVisits={}", docId, sysUser.getUserId(), deptId, totalVisits);
} catch (Exception e) {
// 捕获异常确保不影响主事务
logger.error("文章浏览增加积分异常docId={}", docId, e);
}
}
@Async
@Override
public void addFeaturedDocPointsAsync(Long deptId, String createBy, Long docId, String subjectDesc) {
try {
if (deptId == null || createBy == null) {
logger.warn("积分-文章精选参数不合法deptId={}createBy={}", deptId, createBy);
return;
}
// 检查是否为积分部门
if (!isPointsDept(deptId)) {
logger.info("积分-文章精选非积分部门deptId={}docId={}", deptId, docId);
return;
}
// 获取用户ID
com.microservices.system.api.domain.SysUser sysUser = FeignUtils.getReturnData(
remoteUserService.getSysUserByUserName(createBy, SecurityConstants.INNER));
if (sysUser == null || sysUser.getUserId() == null) {
logger.warn("积分-文章精选未找到用户信息createBy={}docId={}", createBy, docId);
return;
}
// 直接写入 Redis 积分队列 Zone 模块定时任务消费
JSONObject task = new JSONObject();
task.put("sourceType", CmsConstants.FEATURED_DOC);
task.put("userId", sysUser.getUserId());
task.put("deptId", deptId);
task.put("sourceId", docId);
task.put("subjectDesc", "" + subjectDesc + "》管理员标记");
task.put("operatorId", SecurityUtils.getUserId());
redisService.leftPush(CmsConstants.ZONE_POINTS_ASYNC_QUEUE_KEY, task.toJSONString());
logger.info("文章被设为精选增加积分任务已写入队列docId={}userId={}deptId={}", docId, sysUser.getUserId(), deptId);
} catch (Exception e) {
// 捕获异常确保不影响主事务
logger.error("文章被设为精选增加积分异常docId={}", docId, e);
}
}
}

View File

@ -24,12 +24,10 @@ import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.httpClient.constant.GitLinkConstants;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.auth.AuthUtil;
import com.microservices.common.security.service.TokenService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.RemoteUserService;
@ -50,11 +48,7 @@ import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@ -86,8 +80,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
@Autowired
private RemoteDeptService remoteDeptService;
@Autowired
private TokenService tokenService;
@Autowired
@Lazy
private ICmsDocCommentService cmsDocCommentService;
@Value("${cms.detailPath:/newdetail}")
@ -97,7 +89,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
* 查询文章信息
*
* @param id 文章信息主键
* @param isOpen 是否公开访问
* @param isOpen
* @return 文章信息
*/
@Override
@ -112,14 +104,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId());
// 确定查询文件的分支已发布文章或非仓库改动使用 master其他使用临时分支
String branchName;
if (DocAuditStatus.AUDIT_PASS.getAuditCode().equals(cmsDoc.getAuditStatus())
|| (cmsDoc.getAuditType() != null && cmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode()))) {
branchName = CmsConstants.BRANCH_MASTER;
} else {
branchName = cmsDoc.getAuditTmpBranchName();
}
String branchName = DocAuditStatus.AUDIT_PASS.getAuditCode().equals(cmsDoc.getAuditStatus()) ? CmsConstants.BRANCH_MASTER : cmsDoc.getAuditTmpBranchName();
FileEntryDto fileEntryDto = getFileEntryDto(cmsProject, cmsDoc.getFilePath(), branchName);
EntryDto entryDto = fileEntryDto.getEntries();
@ -130,7 +115,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
if (cmsDoc.getPublishTime() != null && cmsDoc.getPublishTime().after(cmsDoc.getCreateTime())) {
cmsDocDto.setIsFirstPublish(false);
}
if (isOpen && DocAuditStatus.AUDIT_PASS.getAuditCode().equals(cmsDoc.getAuditStatus())) {
if (isOpen) {
updateVisits(cmsDocDto.getId());
}
return cmsDocDto;
@ -186,21 +171,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
return cmsDocList.stream().map(CmsDoc::copyToCmsDocAllDto).collect(Collectors.toList());
}
@Override
public GenericsTableDataInfo<CmsDocAllDto> selectAllDocList(Long deptId, CmsDocSearchVo cmsDocSearchVo) {
List<CmsDocAllDto> list = selectCmsDocListByDept(deptId, cmsDocSearchVo);
list.forEach(x -> {
String docDetailUrl = getDocDetailUrl(x.getDeptId(), x.getId());
x.setDocDetailUrl(docDetailUrl);
Boolean editable = isCmsDocEditable(x);
x.setEditable(editable);
});
int count = selectCmsDocCountByDept(deptId, cmsDocSearchVo);
return new GenericsTableDataInfo<>(list, Long.valueOf(count));
}
@Override
public int selectCmsDocCountByDept(Long deptId, CmsDocSearchVo cmsDocSearchVo) {
cmsDocSearchVo.setDeptId(deptId);
@ -263,14 +233,14 @@ public class CmsDocServiceImpl implements ICmsDocService {
@Override
public List<CmsDocDetailDto> selectCmsDocDetailList(Long dirId) {
List<CmsDocDetailDto> cmsDocDetailDtoList = new ArrayList<>();
CmsDoc cmsDir = selectCmsDir(dirId);
CmsDoc cmsDir = cmsDocMapper.selectCmsDocDirById(dirId);
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDir.getDeptId());
CmsDocSearchVo cmsDocSearchVo = new CmsDocSearchVo();
cmsDocSearchVo.setDirName(cmsDir.getName());
cmsDocSearchVo.setDeptId(cmsDir.getDeptId());
cmsDocSearchVo.setIsDir(false);
List<CmsDoc> cmsDocList = cmsDocMapper.selectCmsDocListSetDefaultHeadImg(cmsDocSearchVo);
List<CompletableFuture<CmsDocDetailDto>> futures = new ArrayList<>();
List<CompletableFuture<CmsDocDetailDto>> futures = new ArrayList();
for (CmsDoc cmsDoc : cmsDocList) {
CompletableFuture<CmsDocDetailDto> future = CompletableFuture.supplyAsync(() -> {
CmsDocDetailDto cmsDocDetailDto = cmsDoc.copyToCmsDocDetailDto();
@ -390,16 +360,12 @@ public class CmsDocServiceImpl implements ICmsDocService {
checkCmsLockStatus(dirDoc.getDeptId());
CmsDoc cmsDoc = cmsDocInputDto.toCmsDoc(dirDoc);
if (isNoAuditRequired(dirDoc.getDeptId()) || tokenService.hasDeptPerms(dirDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) {
if (isNoAuditRequired(dirDoc.getDeptId()) || hasDeptAdminPerms(dirDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) {
//文章自动置为审核通过状态值
cmsDoc.setAuditStatus(DocAuditStatus.AUDIT_PASS.getAuditCode());
boolean success = insertCommonCmsDoc(cmsDoc,
"创建文章:" + StringUtils.truncateStringAndConcatenatingSpecifiedString(cmsDoc.getName(), 100, "..."),
cmsDocInputDto.getContent());
if (success) {
// 自动审核通过时也需要增加积分
cmsAsyncService.addPublishDocPointsAsync(cmsDoc.getDeptId(), cmsDoc.getCreateBy(), cmsDoc.getId(), cmsDoc.getName());
}
return success ? cmsDoc.getId().intValue() : null;
} else {
//创建临时分支创建文件创建PR
@ -437,9 +403,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
public String getCmsDocFileContent(CmsProject cmsProject, CmsDoc cmsDoc) {
String branchName = CmsConstants.BRANCH_MASTER;
if (!DocAuditStatus.AUDIT_PASS.getAuditCode().equals(cmsDoc.getAuditStatus())) {
if (StringUtils.isNotEmpty(cmsDoc.getAuditTmpBranchName())) {
branchName = cmsDoc.getAuditTmpBranchName();
}
branchName = cmsDoc.getAuditTmpBranchName();
}
//当删除文章为文件夹时判断该文件夹下是否存在文章若存在需先删除所有文章
JSONObject getSubEntriesResult = gitLinkRequestHelper.doGet(
@ -469,24 +433,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
cmsDoc.setRemark(cmsDocAuditVo.getRemark());
if (cmsDocAuditVo.getPass() == 1) {
// 处理非仓库改动的审核通过
if (cmsDoc.getAuditType() != null
&& cmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode())) {
Long oldCmsDocId = Long.parseLong(cmsDoc.getAuditType().split("-")[1]);
CmsDoc oldCmsDoc = cmsDocMapper.selectCmsDocById(oldCmsDocId);
// 用新文章的非仓库字段更新旧文章
oldCmsDoc.setHeadImg(cmsDoc.getHeadImg());
oldCmsDoc.setSummary(cmsDoc.getSummary());
oldCmsDoc.setKeywords(cmsDoc.getKeywords());
oldCmsDoc.setRemark(cmsDoc.getRemark());
cmsDocMapper.updateCmsDoc(oldCmsDoc);
// 删除待审核记录
cmsDocMapper.deleteCmsDocById(cmsDoc.getId());
return true;
}
//同意合并请求
JSONObject result = mergePullRequestByGitLink(cmsProject, cmsDoc);
if (result.containsKey(GitLinkConstants.STATUS_KEY)) {
@ -508,12 +454,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
}
}
if (cmsDocAuditVo.getPass() == 0) {
// 处理非仓库改动的审核拒绝
if (cmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode())) {
handleCmsDocWithNoPassByReedit(cmsDocAuditVo, cmsDoc, cmsProject);
return true;
}
//拒绝GitLink合并请求
String gitLinkPullRequestNumber = cmsDoc.getAuditPrNumber().split("-")[0];
JSONObject result = gitLinkRequestHelper.doPost(
@ -564,10 +504,8 @@ public class CmsDocServiceImpl implements ICmsDocService {
if (cmsDocAuditVo.getReedit().equals(0)) {
//删除待审核文章
cmsDocMapper.deleteCmsDocById(cmsDoc.getId());
// 删除分支如果有
if (StringUtils.isNotEmpty(cmsDoc.getAuditTmpBranchName())) {
gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null);
}
//删除分支
gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null);
return;
}
}
@ -618,8 +556,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
// 推送文章地址到搜索引擎
cmsAsyncService.pushDocDataSearchEngine(cmsDoc);
// 文章审核通过后给作者增加积分异步执行不影响主事务
cmsAsyncService.addPublishDocPointsAsync(cmsDoc.getDeptId(), cmsDoc.getCreateBy(), cmsDoc.getId(), cmsDoc.getName());
}
private JSONObject mergePullRequestByGitLink(CmsProject cmsProject, CmsDoc cmsDoc) {
@ -775,47 +711,11 @@ public class CmsDocServiceImpl implements ICmsDocService {
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Long updateCmsDoc(Long id, CmsDocDto cmsDocDto) {
public boolean updateCmsDoc(Long id, CmsDocDto cmsDocDto) {
CmsDoc oldCmsDoc = cmsDocMapper.selectCmsDocById(id);
checkCmsLockStatus(oldCmsDoc.getDeptId());
if (!hasRepoRelatedChanged(oldCmsDoc, cmsDocDto)) {
// 更新非仓库字段到原文章对象
if (StringUtils.isNotEmpty(cmsDocDto.getHeadImg())) {
oldCmsDoc.setHeadImg(cmsDocDto.getHeadImg());
}
if (StringUtils.isNotEmpty(cmsDocDto.getSummary())) {
oldCmsDoc.setSummary(cmsDocDto.getSummary());
}
if (StringUtils.isNotEmpty(cmsDocDto.getKeywords())) {
oldCmsDoc.setKeywords(cmsDocDto.getKeywords());
}
// 管理员或免审核直接更新原记录
if (tokenService.hasDeptPerms(oldCmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)
|| isNoAuditRequired(oldCmsDoc.getDeptId())) {
cmsDocMapper.updateCmsDoc(oldCmsDoc);
return oldCmsDoc.getId();
}
// 需要审核创建新的待审核记录与仓库改动逻辑一致
if (oldCmsDoc.getAuditStatus().equals(DocAuditStatus.AUDIT_PASS.getAuditCode())) {
CmsDoc newDocWithAudit = insertDocWithAudit(oldCmsDoc,
DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode() + "-" + oldCmsDoc.getId(),
DocAuditStatus.TO_BE_AUDIT.getAuditCode());
return newDocWithAudit.getId();
}
oldCmsDoc.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode());
if (oldCmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_CREATE.getOperationCode())
|| oldCmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_UPDATE.getOperationCode())) {
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(oldCmsDoc.getDeptId());
// 重新开启PR
String gitLinkPullRequestNumber = oldCmsDoc.getAuditPrNumber().split("-")[0];
gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.REOPEN_PULL_REQUEST(cmsProject, gitLinkPullRequestNumber), null);
}
// 待审核/未通过文章重新编辑
cmsDocMapper.updateCmsDoc(oldCmsDoc);
return oldCmsDoc.getId();
return cmsDocMapper.updateCmsDoc(oldCmsDoc) > 0;
}
// 当文章名称发生更改时判断文章名是否在当前栏目下已存在
if (StringUtils.isNotEmpty(cmsDocDto.getName()) && !cmsDocDto.getName().equals(oldCmsDoc.getName())) {
@ -837,7 +737,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
}
}
//用户为专区管理员或专区无审核机制时直接更新文章及仓库主分支
if (tokenService.hasDeptPerms(oldCmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) || isNoAuditRequired(oldCmsDoc.getDeptId())) {
if (hasDeptAdminPerms(oldCmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) || isNoAuditRequired(oldCmsDoc.getDeptId())) {
//专区管理员重新编辑并提交审核未通过文章 重新编辑并提交待审核文章时专区不需审核机制
if (!oldCmsDoc.getAuditStatus().equals(DocAuditStatus.AUDIT_PASS.getAuditCode())) {
//文章审核类型update-原文章id 取出原文章id直接更新删除待审核更新类型文章
@ -852,8 +752,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
if (oldCmsDoc.getAuditType() != null && oldCmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_CREATE.getOperationCode())) {
deleteTmpBranchIfBranchExist(oldCmsDoc);
cmsDocMapper.deleteCmsDocById(id);
directlyInsertAuditedCmsDocWhenZoneHasNoAuditRequired(cmsDocDto, oldCmsDoc);
return oldCmsDoc.getId();
return directlyInsertAuditedCmsDocWhenZoneHasNoAuditRequired(cmsDocDto, oldCmsDoc);
}
}
String branchName = CmsConstants.BRANCH_MASTER;
@ -861,49 +760,13 @@ public class CmsDocServiceImpl implements ICmsDocService {
oldCmsDoc.setAuditStatus(DocAuditStatus.AUDIT_PASS.getAuditCode());
oldCmsDoc.setAuditTmpBranchName(null);
oldCmsDoc.setKeywords(cmsDocDto.getKeywords());
updateCmsCommonDatabase(oldCmsDoc, CmsConstants.BRANCH_MASTER);
return oldCmsDoc.getId();
return updateCmsCommonDatabase(oldCmsDoc, CmsConstants.BRANCH_MASTER) > 0;
} else {
CmsDoc newDocWithAudit = new CmsDoc();
//待审核未通过文章重新编辑并提交
if (DocAuditStatus.AUDIT_FAIL.getAuditCode().equals(oldCmsDoc.getAuditStatus())
|| DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(oldCmsDoc.getAuditStatus())) {
// 非仓库改动待审核记录检查是否有仓库改动
if (oldCmsDoc.getAuditType() != null
&& oldCmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode())) {
if (!hasRepoRelatedChanged(oldCmsDoc, cmsDocDto)) {
// 纯非仓库改动继续在当前记录上更新
oldCmsDoc.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode());
if (StringUtils.isNotEmpty(cmsDocDto.getHeadImg())) {
oldCmsDoc.setHeadImg(cmsDocDto.getHeadImg());
}
if (StringUtils.isNotEmpty(cmsDocDto.getSummary())) {
oldCmsDoc.setSummary(cmsDocDto.getSummary());
}
if (StringUtils.isNotEmpty(cmsDocDto.getKeywords())) {
oldCmsDoc.setKeywords(cmsDocDto.getKeywords());
}
cmsDocMapper.updateCmsDoc(oldCmsDoc);
return oldCmsDoc.getId();
} else {
// 有仓库改动转为仓库改动类型删除当前记录重新创建
Long oldCmsDocId = Long.parseLong(oldCmsDoc.getAuditType().split("-")[1]);
CmsDoc originCmsDoc = cmsDocMapper.selectCmsDocById(oldCmsDocId);
cmsDocMapper.deleteCmsDocById(oldCmsDoc.getId());
// 按照仓库改动逻辑重新创建
newDocWithAudit = insertDocWithAudit(originCmsDoc,
DocAndZoneOperation.OPERATION_UPDATE.getOperationCode() + "-" + oldCmsDocId,
DocAuditStatus.TO_BE_AUDIT.getAuditCode());
cmsAsyncService.asyncUpdateBranchAndFileAndCreatePR(newDocWithAudit, cmsDocDto);
return newDocWithAudit.getId();
}
}
// 仓库改动待审核记录继续在当前记录上更新
oldCmsDoc.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode());
newDocWithAudit = oldCmsDoc;
} else {
@ -916,7 +779,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
}
}
cmsAsyncService.asyncUpdateBranchAndFileAndCreatePR(newDocWithAudit, cmsDocDto);
return newDocWithAudit.getId();
return true;
}
}
@ -1007,12 +870,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
oldCmsDoc.setAuditType(auditType);
oldCmsDoc.setAuditStatus(auditStatus);
oldCmsDoc.setCreateBy(SecurityUtils.getUsername());
// repo 改动显式设置 auditTmpBranchName null没有对应的分支
if (auditType != null && auditType.contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode())) {
oldCmsDoc.setAuditTmpBranchName(null);
}
cmsDocMapper.insertCmsDoc(oldCmsDoc);
return oldCmsDoc;
}
@ -1167,13 +1024,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
visits = visits + cmsDoc.getVisits();
}
cmsDoc.setVisits(visits);
int rows = cmsDocMapper.updateCmsDoc(cmsDoc);
if (rows > 0) {
cmsAsyncService.addVisitsDocPointsAsync(cmsDoc.getDeptId(), cmsDoc.getCreateBy(),
cmsDoc.getId(), cmsDoc.getName(), cmsDoc.getVisits());
return true;
}
return false;
return cmsDocMapper.updateCmsDoc(cmsDoc) > 0;
}
@Override
@ -1297,9 +1148,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
//首页推荐时需将顺序设置为1
setCmsSort(1, cmsDoc, false, null);
cmsDoc.setIsHomepage(CmsConstants.TRUE);
// 文章被设为精选异步增加作者积分
cmsAsyncService.addFeaturedDocPointsAsync(cmsDoc.getDeptId(), cmsDoc.getCreateBy(),
cmsDoc.getId(), cmsDoc.getName());
}
return cmsDocMapper.updateCmsDoc(cmsDoc);
}
@ -1323,41 +1171,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
return cmsDocBaseDtoList;
}
@Override
public List<CmsDocBaseDto> selectHomePageDocMergeList(Long zoneId, List<Long> topDocIds) {
Long deptId = getDeptIdByZoneId(zoneId);
Set<Long> addedDocIds = new HashSet<>();
// 1. 获取首页推荐文章列表
List<CmsDocBaseDto> homePageDocs = selectHomePageDocList(deptId);
List<CmsDocBaseDto> result = new ArrayList<>();
// 2. 批量查询置顶文章完整数据按传入顺序放入结果头部
if (topDocIds != null && !topDocIds.isEmpty()) {
List<CmsDoc> topCmsDocs = cmsDocMapper.selectCmsDocByIds(topDocIds);
Map<Long, CmsDoc> topDocMap = new HashMap<>();
for (CmsDoc doc : topCmsDocs) {
topDocMap.put(doc.getId(), doc);
}
for (Long docId : topDocIds) {
CmsDoc doc = topDocMap.get(docId);
if (doc != null) {
result.add(doc.copyToCmsDocBaseDto());
addedDocIds.add(docId);
}
}
}
// 3. 追加首页推荐文章跳过已在置顶列表中的
for (CmsDocBaseDto doc : homePageDocs) {
if (!addedDocIds.contains(doc.getId())) {
result.add(doc);
}
}
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public CmsDir initCmsDir(Long deptId, CmsDir cmsDirInput) {
@ -1504,15 +1317,16 @@ public class CmsDocServiceImpl implements ICmsDocService {
cmsAsyncService.updateCmsPublishDataByGitLink(cmsProject, cmsDoc, branchName);
}
private int deleteCmsDir(CmsProject cmsProject, CmsDoc cmsDir) {
if (!isNoAuditRequired(cmsDir.getDeptId()) || tokenService.hasDeptPerms(cmsDir.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) {
boolean deleteResult = cmsAsyncService.deleteCmsDocForGitLink(cmsDir, cmsProject, CmsConstants.BRANCH_MASTER);
if (deleteResult) {
return cmsDocMapper.deleteCmsDocById(cmsDir.getId());
}
throw new ServiceException("栏目删除失败");
private Boolean hasDeptAdminPerms(Long deptId, String perms) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Boolean hasPerms = FeignUtils.getReturnData(
remoteDeptService.checkUserInDeptOrParentDeptHasPerms(deptId, loginUser.getUserId(), perms, SecurityConstants.INNER)
);
if (hasPerms == null) {
hasPerms = false;
}
throw new ServiceException("无权限删除栏目");
return hasPerms;
}
@Override
@ -1524,16 +1338,9 @@ public class CmsDocServiceImpl implements ICmsDocService {
checkCmsLockStatus(cmsDoc.getDeptId());
//2获取专区项目
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId());
if (cmsDoc.getIsDir()) {
return deleteCmsDir(cmsProject, cmsDoc);
}
//删除待审核审核未通过文章删除临时分支拒绝合并请求
if (DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(cmsDoc.getAuditStatus())) {
// 非仓库改动类型直接删除
if (cmsDoc.getAuditType().contains(DocAndZoneOperation.OPERATION_NON_REPO_UPDATE.getOperationCode())) {
return cmsDocMapper.deleteCmsDocById(cmsDoc.getId());
}
//拒绝GitLink合并请求
String gitLinkPullRequestNumber = cmsDoc.getAuditPrNumber().split("-")[0];
@ -1546,7 +1353,7 @@ public class CmsDocServiceImpl implements ICmsDocService {
return cmsDocMapper.deleteCmsDocById(cmsDoc.getId());
}
// 判读当前用户是否拥有文章直接删除权限
if (tokenService.hasDeptPerms(cmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) //当前用户为专区管理员
if (hasDeptAdminPerms(cmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) //当前用户为专区管理员
|| isNoAuditRequired(cmsDoc.getDeptId()) //当前专区文章发布无需审核机制
) {
String branchName = CmsConstants.BRANCH_MASTER;

View File

@ -25,24 +25,4 @@ public class CmsConstants {
*
*/
public final static String TRUE = "1";
/**
* 专区积分异步队列 Redis Key Zone 模块保持一致
*/
public final static String ZONE_POINTS_ASYNC_QUEUE_KEY = "zone:points:async:queue";
/**
* 发布文章积分类型
*/
public final static String PUBLISH_DOC = "publishDoc";
/**
* 浏览文章积分类型
*/
public final static String VISITS_DOC = "visitsDoc";
/**
* 精选文章积分类型
*/
public final static String FEATURED_DOC = "featuredDoc";
}

View File

@ -88,12 +88,6 @@ public class CmsGitLinkRequestUrl extends GitLinkRequestUrl {
);
}
public static GitLinkRequestUrl REOPEN_PULL_REQUEST(CmsProject cmsProject, String giteaPrNumber) {
return getGitLinkRequestUrl(
String.format("/api/v1/%s/%s/pulls/%s/reopen", cmsProject.getUsername(), cmsProject.getIdentifier(), giteaPrNumber)
);
}
public static GitLinkRequestUrl GET_PULL_REQUEST_DETAILS(CmsProject cmsProject, String giteaPrNumber) {
return getGitLinkRequestUrl(
String.format("/api/%s/%s/pulls/%s.json", cmsProject.getUsername(), cmsProject.getIdentifier(), giteaPrNumber)

View File

@ -106,10 +106,6 @@
cd.editor_type,
cd.keywords,
cd.is_dir,
cd.audit_status,
cd.audit_type,
cd.audit_tmp_branch_name,
cd.audit_pr_number,
cd.remark
from cms_doc cd
</sql>
@ -143,10 +139,6 @@
cd.editor_type,
cd.keywords,
cd.is_dir,
cd.audit_status,
cd.audit_type,
cd.audit_tmp_branch_name,
cd.audit_pr_number,
-- 计算全文搜索相关度评分
MATCH(cd.name, cd.summary) AGAINST(#{keyword} IN NATURAL LANGUAGE MODE) AS search_score,
cd.remark
@ -188,10 +180,6 @@
cd.editor_type,
cd.keywords,
cd.is_dir,
cd.audit_status,
cd.audit_type,
cd.audit_tmp_branch_name,
cd.audit_pr_number,
cd.remark
from cms_doc cd
left join cms_doc dir on cd.dir_name = dir.name and cd.dept_id = dir.dept_id and dir.is_dir=1
@ -217,20 +205,10 @@
where id = #{id}
</select>
<select id="selectCmsDocByIds" resultMap="CmsDocResult">
<include refid="selectCmsDocVo"/>
where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
and audit_status = '1'
</select>
<select id="selectCmsDocByNameAndDeptId" resultMap="CmsDocResult">
<include refid="selectCmsDocVo"/>
<where>
and name = #{name}
and audit_status != 0
and dept_id = #{deptId}
<choose>
<when test="dirName != null">
@ -242,10 +220,6 @@
</choose>
</where>
</select>
<select id="selectCmsDocByNameAndDeptIdIgnoreDirName" resultMap="CmsDocResult">
<include refid="selectCmsDocVo"/>
where name = #{name} and dept_id = #{deptId} and is_dir = 0
</select>
<select id="selectCmsDocDirByNameAndDeptId" resultMap="CmsDocResult">
<include refid="selectCmsDocVo"/>
where name = #{name} and dept_id = #{deptId} and is_dir = 1
@ -286,7 +260,6 @@
<if test="auditStatus != null and auditStatus != '-1' ">and audit_status = #{auditStatus}</if>
<if test="auditStatus == null ">and audit_status = '1'</if>
<if test="createBy != null and createBy != '' ">and create_by = #{createBy}</if>
<if test="excludeId != null ">and id != #{excludeId}</if>
</where>
</sql>

View File

@ -138,6 +138,7 @@ public class ChunkedUploadController extends BaseController {
return genericsSuccess(result);
}
/* 屏蔽取消上传接口
/**
* 取消上传
* <p>
@ -147,7 +148,6 @@ public class ChunkedUploadController extends BaseController {
*
* @param uploadId 上传ID
* @return 取消结果
*/
@DeleteMapping("/cancel/{uploadId}")
@ApiOperation("取消上传")
@ApiImplicitParams({
@ -157,6 +157,7 @@ public class ChunkedUploadController extends BaseController {
boolean result = chunkedUploadService.cancelUpload(uploadId);
return genericsSuccess(result ? CancelUploadResponseVo.success() : CancelUploadResponseVo.failed("取消上传失败"));
}
*/
/**
* 获取上传进度

View File

@ -235,4 +235,16 @@ public class CommonController extends BaseController {
R<List<String>> uploadFileToForge(@PathVariable("fileIdentifiers") String fileIdentifiers) {
return R.ok(sysFileInfoService.uploadFileToForge(fileIdentifiers));
}
/**
* 根据文件Id获取文件信息
*/
@InnerAuth
@GetMapping("/getFileDetail/{fileId}")
@ApiOperation(value = "根据文件Id获取文件信息")
public R<SysFileInfo> getFileDetail(@PathVariable("fileId") Long fileId) {
SysFileInfo sysFileInfo = sysFileInfoService.selectSysFileInfoByFileId(fileId);
sysFileInfo.setFilePath(localFilePath + sysFileInfo.getFilePath());
return R.ok(sysFileInfo);
}
}

View File

@ -1,7 +1,6 @@
package com.microservices.file.controller;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.file.service.ISysFileInfoService;
import com.microservices.system.api.domain.SysFileInfo;
@ -121,20 +120,19 @@ public class OpenController {
@ApiImplicitParam(name = "hierarchy", value = "层级结构eg: pms项目管理中{enterpriseIdentifier}/products,{enterpriseIdentifier}/projects,{enterpriseIdentifier}/docs/{projectId}", paramType = "query", dataType = "String")
})
public AjaxResult uploadFile(@RequestPart("file") MultipartFile file, String type, String hierarchy) {
throw new ServiceException("该接口已弃用!");
// SysFileInfo sysFileInfo = sysFileInfoService.upload(file, type, hierarchy);
// AjaxResult ajax = AjaxResult.success();
// ajax.put("url", sysFileInfo.getDownloadUrl());
// if (sysFileInfo.getFileIdentifier() != null) {
// ajax.put("fileIdentifier", sysFileInfo.getFileIdentifier());
// }
// ajax.put("fileName", sysFileInfo.getFilePath());
// if (sysFileInfo.getFileId() != null) {
// ajax.put("fileId", sysFileInfo.getFileId());
// }
// ajax.put("fileOriginName", sysFileInfo.getFileOriginName());
// ajax.put("fileSuffix", sysFileInfo.getFileSuffix());
// ajax.put("fileSize", sysFileInfo.getFileSizeInfo());
// return ajax;
SysFileInfo sysFileInfo = sysFileInfoService.upload(file, type, hierarchy);
AjaxResult ajax = AjaxResult.success();
ajax.put("url", sysFileInfo.getDownloadUrl());
if (sysFileInfo.getFileIdentifier() != null) {
ajax.put("fileIdentifier", sysFileInfo.getFileIdentifier());
}
ajax.put("fileName", sysFileInfo.getFilePath());
if (sysFileInfo.getFileId() != null) {
ajax.put("fileId", sysFileInfo.getFileId());
}
ajax.put("fileOriginName", sysFileInfo.getFileOriginName());
ajax.put("fileSuffix", sysFileInfo.getFileSuffix());
ajax.put("fileSize", sysFileInfo.getFileSizeInfo());
return ajax;
}
}

View File

@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;
@ -33,7 +34,7 @@ public class SysFileController extends BaseController {
*/
@InnerAuth
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file,
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file,
@RequestParam("type") String type,
@RequestParam("hierarchy") String hierarchy) {
try {
@ -43,6 +44,7 @@ public class SysFileController extends BaseController {
sysFile.setName(fileInfo.getFilePath());
sysFile.setUrl(fileInfo.getDownloadUrl());
sysFile.setFileIdentifier(fileInfo.getFileIdentifier());
sysFile.setFileId(fileInfo.getFileId());
return R.ok(sysFile);
} catch (Exception e) {
log.error("上传文件失败", e);

View File

@ -3,6 +3,7 @@ package com.microservices.file.mapper;
import com.microservices.system.api.domain.SysFileInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -85,4 +86,9 @@ public interface SysFileInfoMapper {
* @return 文件
*/
SysFileInfo selectSysFileInfoByIdentifier(String fileIdentifier);
/**
* 统计引用同一物理文件路径的记录数
*/
int countByFilePath(@Param("filePath") String filePath);
}

View File

@ -177,4 +177,10 @@ public interface ISysFileInfoService {
List<String> uploadFileToForge(String fileIdentifiers);
String downloadFileByUrl(String fileUrl, String type, String hierarchy);
/**
* 基于已有文件信息克隆一条新的数据库记录秒传场景使用
* 新记录拥有独立的fileId和downloadCount(=0)共享物理文件
*/
SysFileInfo cloneFileInfo(SysFileInfo source);
}

View File

@ -215,13 +215,15 @@ public class ChunkedUploadServiceImpl implements IChunkedUploadService {
// 清理临时文件
cleanupTempFiles(session);
// 返回已存在文件信息
// 基于原文件创建新的数据库记录独立downloadCount共享物理文件
SysFileInfo newFileInfo = fileInfoService.cloneFileInfo(fileInfo);
return CheckInstantUploadVo.instantSuccess(
fileInfo.getFileId(),
fileInfo.getFileOriginName(),
fileInfo.getFilePath(),
fileInfo.getDownloadUrl(),
fileInfo.getFileSizeInfo()
newFileInfo.getFileId(),
newFileInfo.getFileOriginName(),
newFileInfo.getFilePath(),
newFileInfo.getDownloadUrl(),
newFileInfo.getFileSizeInfo()
);
}
}

View File

@ -96,11 +96,6 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Autowired
private RedisService redisService;
/** 积分异步任务 Redis 队列 Key */
private static final String ZONE_POINTS_ASYNC_QUEUE_KEY = "zone:points:async:queue";
/** 资源下载积分任务 sourceType */
private static final String DOWNLOAD_RESOURCE_SOURCE_TYPE = "downloadResource";
@Override
public SysFileInfo selectSysFileInfoByFileObjectName(String fileObjectName) {
return sysFileInfoMapper.selectSysFileInfoByFileObjectName(fileObjectName);
@ -178,8 +173,9 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
for (int i = 0; i < fileIds.length; i++) {
Long fileId = fileIds[i];
SysFileInfo sysFileInfo = sysFileInfoMapper.selectSysFileInfoByFileId(fileId);
String filePath = localFilePath + StringUtils.substringAfter(sysFileInfo.getFilePath(), Constants.RESOURCE_PREFIX);
FileUtils.deleteFile(filePath);
if (sysFileInfo != null) {
safeDeletePhysicalFile(sysFileInfo.getFilePath());
}
}
return sysFileInfoMapper.deleteSysFileInfoByFileIds(fileIds);
}
@ -193,16 +189,18 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Override
public int deleteSysFileInfoByFileId(Long fileId) {
SysFileInfo sysFileInfo = sysFileInfoMapper.selectSysFileInfoByFileId(fileId);
String filePath = localFilePath + StringUtils.substringAfter(sysFileInfo.getFilePath(), Constants.RESOURCE_PREFIX);
FileUtils.deleteFile(filePath);
if (sysFileInfo != null) {
safeDeletePhysicalFile(sysFileInfo.getFilePath());
}
return sysFileInfoMapper.deleteSysFileInfoByFileId(fileId);
}
@Override
public int deleteSysFileInfoByFileObjectName(String fileObjectName) {
SysFileInfo sysFileInfo = sysFileInfoMapper.selectSysFileInfoByFileObjectName(fileObjectName);
String filePath = localFilePath + StringUtils.substringAfter(sysFileInfo.getFilePath(), Constants.RESOURCE_PREFIX);
FileUtils.deleteFile(filePath);
if (sysFileInfo != null) {
safeDeletePhysicalFile(sysFileInfo.getFilePath());
}
return sysFileInfoMapper.deleteSysFileInfoByFileObjectName(fileObjectName);
}
@ -276,9 +274,9 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Override
public void fileDownloadById(Long fileId, HttpServletResponse response, HttpServletRequest request) {
SysFileInfo sysFileInfo = selectSysFileInfoByFileId(fileId);
if (StringUtils.isNotEmpty(sysFileInfo.getFileIdentifier())) {
throw new ServiceException("当前文件无法下载");
}
// if (StringUtils.isNotEmpty(sysFileInfo.getFileIdentifier())) {
// throw new ServiceException("当前文件无法下载");
// }
fileDownload(sysFileInfo, response);
}
@ -402,6 +400,7 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
hierarchy = validPathSafety(hierarchy);
}
boolean isLocalUpload = true;
boolean isHierarchyPath = false;
Long fileId = null;
switch (fileType) {
case "pms-gitlink":
@ -436,6 +435,7 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
sysFileInfo.setFileIdentifier(genFileIdentifier());
baseFilePath += "/" + fileType + "/" + hierarchy + "/";
isCommonFileType = false;
isHierarchyPath = true;
break;
}
case "dms": {
@ -450,6 +450,13 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
isCommonFileType = false;
break;
}
case "ai-resource": {
sysFileInfo.setFileIdentifier(genFileIdentifier());
baseFilePath += "/" + fileType + "/" + hierarchy + "/";
isCommonFileType = false;
isHierarchyPath = true;
break;
}
case "zone-identifier": {
// 生成唯一标识防止用户通过id递增访问
sysFileInfo.setFileIdentifier(genFileIdentifier());
@ -512,7 +519,7 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
sysFileInfo.setFileOriginName(session.getFileName());
}
if (!isCommonFileType) {
if ("pms".equals(fileType)) {
if (isHierarchyPath) {
filePath = EscapeUtil.removeExtraSlashOfUrl("/" + fileType + "/" + hierarchy + "/" + filePath);
} else {
filePath = EscapeUtil.removeExtraSlashOfUrl("/" + fileType + "/" + filePath);
@ -621,15 +628,6 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
sysFileInfo.setDownloadCount(downloadCount);
updateSysFileInfo(sysFileInfo);
// 触发资源下载积分任务直接写入 Redis 异步队列
try {
JSONObject task = new JSONObject();
task.put("sourceType", DOWNLOAD_RESOURCE_SOURCE_TYPE);
task.put("sourceId", sysFileInfo.getFileId());
redisService.leftPush(ZONE_POINTS_ASYNC_QUEUE_KEY, JSONObject.toJSONString(task));
} catch (Exception e) {
logger.warn("触发资源下载积分任务失败 fileId={} error={}", sysFileInfo.getFileId(), e.getMessage());
}
} catch (Exception e) {
throw new ServiceException("文件下载异常:%s", e.getMessage());
}
@ -684,4 +682,36 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
}
return fileIdentifier;
}
/**
* 安全删除物理文件检查是否有其他数据库记录引用同一物理文件路径
*/
private void safeDeletePhysicalFile(String dbFilePath) {
int refCount = sysFileInfoMapper.countByFilePath(dbFilePath);
if (refCount <= 1) {
String physicalPath = localFilePath + StringUtils.substringAfter(dbFilePath, Constants.RESOURCE_PREFIX);
FileUtils.deleteFile(physicalPath);
}
}
@Override
public SysFileInfo cloneFileInfo(SysFileInfo source) {
SysFileInfo clone = new SysFileInfo();
clone.setFileIdentifier(genFileIdentifier());
clone.setFileOriginName(source.getFileOriginName());
clone.setFileSuffix(source.getFileSuffix());
clone.setFileSizeInfo(source.getFileSizeInfo());
clone.setFileObjectName(source.getFileObjectName());
clone.setFilePath(source.getFilePath());
clone.setDownloadUrl(source.getDownloadUrl());
clone.setContentType(source.getContentType());
clone.setContentTypeName(source.getContentTypeName());
clone.setContentTypeMessage(source.getContentTypeMessage());
clone.setMimeType(source.getMimeType());
clone.setIsPartialMatch(source.getIsPartialMatch());
clone.setDelFlag("N");
clone.setDownloadCount(0);
sysFileInfoMapper.insertSysFileInfo(clone);
return clone;
}
}

View File

@ -97,6 +97,7 @@
<if test="contentTypeMessage != null">content_type_message,</if>
<if test="mimeType != null">mime_type,</if>
<if test="isPartialMatch != null">is_partial_match,</if>
<if test="downloadCount != null">download_count,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="fileOriginName != null and fileOriginName != ''">#{fileOriginName},</if>
@ -115,6 +116,7 @@
<if test="contentTypeMessage != null">#{contentTypeMessage},</if>
<if test="mimeType != null">#{mimeType},</if>
<if test="isPartialMatch != null">#{isPartialMatch},</if>
<if test="downloadCount != null">#{downloadCount},</if>
</trim>
</insert>
@ -159,4 +161,8 @@
from sys_file_info
where file_object_name = #{fileObjectName}
</delete>
<select id="countByFilePath" resultType="int">
select count(*) from sys_file_info where file_path = #{filePath} and del_flag = 'N'
</select>
</mapper>

View File

@ -11,7 +11,6 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Size;
import java.util.List;
/**
@ -72,18 +71,12 @@ public class PmsProjectTestcaseDataVo extends BaseEntityVo {
@ApiModelProperty(value = "关联产品需求")
private PmsProductRequirement productReqSpecs;
@ApiModelProperty(value = "测试追踪")
private String testTracking;
/**
* 用例索引
*/
@ApiModelProperty(value = "用例索引")
private Long index;
@ApiModelProperty(value = "测试用例标识")
private String identifier;
public PmsProjectTestcaseDetailVo toPmsProjectTestcaseDetailVo() {
PmsProjectTestcaseDetailVo target = new PmsProjectTestcaseDetailVo();

View File

@ -25,7 +25,7 @@
<result property="testMethod" column="test_method"/>
<result property="terminationConditions" column="termination_conditions"/>
<result property="identifier" column="identifier"/>
<result property="testTracking" column="test_tracking"/>
<result property="testTracking" column="test_track"/>
<result property="productReqSpecsId" column="product_req_specs_id"/>
<result property="isImport" column="is_import"/>
</resultMap>
@ -33,7 +33,6 @@
<sql id="selectPmsProjectTestcaseVo">
select id,
title,
test_tracking,
assignee_gitlink_id,
pms_project_id,
type_id,
@ -187,7 +186,7 @@
<if test="testMethod != null">test_method = #{testMethod},</if>
<if test="terminationConditions != null">termination_conditions = #{terminationConditions},</if>
<if test="identifier != null">identifier = #{identifier},</if>
<if test="testTracking != null">test_tracking = #{testTracking},</if>
<if test="testTracking != null">#{testTracking},</if>
<if test="productReqSpecsId != null">#{productReqSpecsId},</if>
<if test="isImport != null">#{isImport},</if>
</trim>

View File

@ -1,6 +1,5 @@
package com.microservices.system.controller;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.StringUtils;
@ -204,26 +203,6 @@ public class SysUserController extends BaseController {
return R.ok(sysUser);
}
@InnerAuth
@GetMapping("/getSysUserListByUserIds")
R<List<SysUser>> getSysUserListByUserIds(@RequestParam("userIds") Long[] userIds) {
List<SysUser> sysUserList = userService.selectUserListFromUserIds(userIds);
return R.ok(sysUserList);
}
/**
* 通过用户ID数组批量获取用户信息POST方法解决URL长度限制
*
* @param userIds 用户ID数组
* @return 用户列表
*/
@InnerAuth
@PostMapping("/getSysUserListByUserIds")
R<List<SysUser>> postSysUserListByUserIds(@RequestBody Long[] userIds) {
List<SysUser> sysUserList = userService.selectUserListFromUserIds(userIds);
return R.ok(sysUserList);
}
/**
* 通过GitLinkToken获取本系统Token
*

View File

@ -131,6 +131,4 @@ public interface SysUserMapper
public SysUser checkEmailUnique(String email);
SysUser selectUserByGitLinkUserId(Long gitLinkUserId);
List<SysUser> selectUserListFromUserIds(Long[] ids);
}

View File

@ -222,6 +222,4 @@ public interface ISysUserService
String getUserNameByGitLinkToken(String gitLinkToken);
SysUser gitlinkUserToUpdateSysUser(SysUser sysUser, ForgeUser forgeUser);
List<SysUser> selectUserListFromUserIds(Long[] userIds);
}

View File

@ -169,11 +169,8 @@ public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService {
if (sysUser == null) {
return;
}
String redisKey = CacheConstants.getUserIdentifyListKey(sysUser.getUserName());
// 删除缓存中该用户身份列表信息
redisService.deleteObject(CacheConstants.getUserIdentifyListKey(redisKey));
List<SysUserDeptRole> userIdentifyList = selectSysUserDeptRoleListByUserName(sysUser.getUserName());
redisService.setCacheObject(redisKey, userIdentifyList);
redisService.deleteObject(CacheConstants.getUserIdentifyListKey(sysUser.getUserName()));
}

View File

@ -37,7 +37,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.validation.Validator;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -681,9 +684,4 @@ public class SysUserServiceImpl implements ISysUserService {
return sysUser;
}
@Override
public List<SysUser> selectUserListFromUserIds(Long[] userIds) {
return userMapper.selectUserListFromUserIds(userIds);
}
}

View File

@ -121,24 +121,19 @@ public class SyncGitLinkUserInfoJob {
for (ForgeUserAction forgeUserAction : forgeUserActionList) {
String userActionDataBank = forgeUserAction.getDataBank();
if (StringUtils.isNotEmpty(userActionDataBank)) {
try {
JSONObject jsonObject = JSON.parseObject(userActionDataBank);
if (jsonObject != null) {
Long userId = jsonObject.getLong("id");
if (userId != null) {
SysUser sysUser = sysUserMapper.selectUserByGitLinkUserId(forgeUserAction.getUserId());
if (sysUser != null && UserConstants.DEL_FLAG_FALSE.equals(sysUser.getDelFlag())) {
log.info("检测到用户{}在Forge端已注销将该用户在微服务平台的所有身份标记为已注销同时逻辑删除该用户", sysUser.getUserName());
// 更新用户所有身份为已注销
sysUserDeptRoleService.deleteSysUserDeptRoleByDeleteUser(sysUser.getUserId());
// 逻辑删除该用户
sysUserService.deleteUserById(sysUser.getUserId());
}
JSONObject jsonObject = JSON.parseObject(userActionDataBank);
if (jsonObject != null) {
Long userId = jsonObject.getLong("id");
if (userId != null) {
SysUser sysUser = sysUserMapper.selectUserByGitLinkUserId(forgeUserAction.getUserId());
if (sysUser != null && UserConstants.DEL_FLAG_FALSE.equals(sysUser.getDelFlag())) {
log.info("检测到用户{}在Forge端已注销将该用户在微服务平台的所有身份标记为已注销同时逻辑删除该用户", sysUser.getUserName());
// 更新用户所有身份为已注销
sysUserDeptRoleService.deleteSysUserDeptRoleByDeleteUser(sysUser.getUserId());
// 逻辑删除该用户
sysUserService.deleteUserById(sysUser.getUserId());
}
}
} catch (Exception e) {
log.error("解析Forge用户操作JSON失败forgeUserActionId: {}, userId: {}, dataBank: {}, 错误信息: {}",
forgeUserAction.getId(), forgeUserAction.getUserId(), userActionDataBank, e.getMessage());
}
}
}

View File

@ -200,15 +200,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where u.gitlink_user_id = #{gitLinkUserId}
limit 1
</select>
<select id="selectUserListFromUserIds" resultMap="SysUserResult">
<include refid="selectOnlyUserVo"/>
where user_id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
<if test="userId != null and userId != 0">user_id,</if>
<if test="gitlinkUserId != null and gitlinkUserId != 0">gitlink_user_id,</if>

View File

@ -54,12 +54,6 @@
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Microservices Common Redis -->
<dependency>
<groupId>com.microservices</groupId>
<artifactId>microservices-common-redis</artifactId>
</dependency>
<!-- Microservices Common Async -->
<dependency>
<groupId>com.microservices</groupId>
@ -139,6 +133,12 @@
<version>3.6.2</version>
<scope>compile</scope>
</dependency>
<!-- Apache Commons Compress - 解决 ZIP 文件中文文件名 GBK 编码导致的 MALFORMED 问题 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.0</version>
</dependency>
</dependencies>
<build>

View File

@ -13,23 +13,20 @@ import com.microservices.zone.detail.domain.vo.ZoneFrontRoleVo;
import com.microservices.zone.detail.service.IZoneDetailService;
import com.microservices.zone.project.domain.vo.*;
import com.microservices.zone.project.service.IZoneProjectService;
import com.microservices.zone.member.service.IZonePointsAccountService;
import com.microservices.zone.project.service.IZoneProjectTypeService;
import com.microservices.zone.resource.domain.ZoneResource;
import com.microservices.zone.utils.ZoneConstants;
import com.microservices.zone.resource.domain.vo.ZoneResourceDataVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceInputVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceSearchVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceUpdateVo;
import com.microservices.zone.resource.domain.vo.*;
import com.microservices.zone.resource.service.IAiResourceParseService;
import com.microservices.zone.resource.service.IZoneResourceService;
import io.swagger.annotations.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collections;
import java.util.List;
/**
@ -43,18 +40,15 @@ public class FrontController extends BaseController {
@Autowired
private IZoneResourceService zoneResourceService;
@Autowired
private IAiResourceParseService aiResourceParseService;
@Autowired
private IZoneProjectService zoneProjectService;
@Autowired
private IZoneDetailService zoneDetailService;
@Autowired
private IZoneProjectTypeService zoneProjectTypeService;
@Autowired
private IZonePointsAccountService zonePointsAccountService;
/**
* 查询我的资源列表
*/
@ -162,7 +156,7 @@ public class FrontController extends BaseController {
@Log(title = "专区前台项目操作", businessType = BusinessType.UPDATE)
@PutMapping("/editProject/{projectId}")
@ApiOperation(value = "编辑项目聚合")
public AjaxResult editProject(@PathVariable("projectId") Long projectId,@RequestBody ZoneProjectFrontUpdateVo zoneProjectFrontUpdateVo) {
public AjaxResult editProject(@PathVariable("projectId") Long projectId, @RequestBody ZoneProjectFrontUpdateVo zoneProjectFrontUpdateVo) {
return success(zoneProjectService.updateMyZoneProject(projectId, zoneProjectFrontUpdateVo.toZoneProjectUpdateVo()));
}
@ -187,11 +181,189 @@ public class FrontController extends BaseController {
"3、当权限为None时不展示前台操作按钮\n" +
"4、检测到用户登录后才能调用该接口否则不展示前台操作按钮")
public GenericsAjaxResult<ZoneFrontRoleVo> checkCurrentRole(@PathVariable Long zoneId) {
ZoneFrontRoleVo zoneFrontRoleVo = zoneDetailService.checkCurrentRoleInZone(zoneId);
// 专区普通会员触发每日首次访问积分+1
if (ZoneConstants.FRONT_ROLE_MEMBER.equals(zoneFrontRoleVo.getRole())) {
zonePointsAccountService.addDailyVisitPointsAsync(zoneId);
}
return genericsSuccess(zoneFrontRoleVo);
return genericsSuccess(zoneDetailService.checkCurrentRoleInZone(zoneId));
}
// ==================== Skill资源广场 - 我的资源管理 ====================
/**
* 上传ZIP并解析
*/
@RequiresPermissions("zone:front:skill:add")
@PostMapping("/skill/parse")
@ApiOperation("上传ZIP并解析Skill包")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件实体", paramType = "form", dataType = "_file"),
})
public GenericsAjaxResult<AiSkillParseResultVo> parseSkillZip(@RequestPart("file") MultipartFile file) {
return genericsSuccess(aiResourceParseService.parseSkillZip(file));
}
/**
* 创建Skill资源
*/
@RequiresPermissions("zone:front:skill:add")
@Log(title = "创建Skill资源", businessType = BusinessType.INSERT)
@PostMapping("/skill")
@ApiOperation("创建Skill资源")
public AjaxResult addSkill(@RequestBody @Validated AiSkillInputVo inputVo) {
return success(zoneResourceService.insertAiSkillResource(inputVo));
}
@RequiresPermissions("zone:front:resource:add")
@Log(title = "重新提交被驳回的资源", businessType = BusinessType.UPDATE)
@PutMapping("/resource/{id}/resubmit")
@ApiOperation(value = "重新提交被驳回的资源")
public AjaxResult resubmitAiResource(
@ApiParam(value = "资源ID", required = true) @PathVariable("id") Long id) {
return toAjax(zoneResourceService.resubmitAiResource(id));
}
@RequiresPermissions("zone:front:resource:edit")
@Log(title = "撤回审核中的资源", businessType = BusinessType.UPDATE)
@PutMapping("/resource/{id}/withdraw")
@ApiOperation(value = "撤回审核中的资源")
public AjaxResult withdrawAiResource(
@ApiParam(value = "资源ID", required = true) @PathVariable("id") Long id) {
return toAjax(zoneResourceService.withdrawAiResource(id));
}
/**
* 下架资源
*/
@RequiresPermissions("zone:front:resource:edit")
@Log(title = "下架资源", businessType = BusinessType.UPDATE)
@PutMapping("/{id}/takeDown")
@ApiOperation("下架资源")
public AjaxResult takeDownResource(
@ApiParam(value = "资源ID", required = true) @PathVariable("id") Long id,
@RequestParam(value = "reason", required = false) String reason) {
return toAjax(zoneResourceService.takeDownAiResource(id, reason));
}
/**
* 上架资源
*/
@RequiresPermissions("zone:front:resource:edit")
@Log(title = "上架资源", businessType = BusinessType.UPDATE)
@PutMapping("/{id}/takeUp")
@ApiOperation("上架资源")
public AjaxResult takeUpResource(
@ApiParam(value = "资源ID", required = true) @PathVariable("id") Long id,
@RequestParam(value = "reason", required = false) String reason) {
return toAjax(zoneResourceService.takeUpAiResource(id, reason));
}
/**
* 获取资源统计
*/
@RequiresPermissions("zone:front:resource:query")
@GetMapping("/resourceStatistics")
@ApiOperation("获取资源统计")
@ApiImplicitParams({
@ApiImplicitParam(name = "isMine", value = "是否查询我的资源(true-我的资源,false-专区资源)", paramType = "query", dataType = "boolean"),
@ApiImplicitParam(name = "zoneId", value = "专区ID", paramType = "query", dataType = "Long", required = true),
@ApiImplicitParam(name = "resourceCategory", value = "资源分类(SKILL/MODEL/DATASET),为空则查询所有", paramType = "query", dataType = "String")
})
public GenericsAjaxResult<UserResourceStatisticsVo> resourceStatistics(
@ApiParam(name = "isMine", value = "是否查询我的资源") @RequestParam(value = "isMine", required = false) Boolean isMine,
@ApiParam(name = "zoneId") @RequestParam(value = "zoneId") Long zoneId,
@ApiParam(name = "resourceCategory") @RequestParam(value = "resourceCategory", required = false) String resourceCategory) {
return genericsSuccess(zoneResourceService.getResourceStatistics(zoneId, isMine, resourceCategory));
}
/**
* 获取我的项目聚合统计
*/
@RequiresPermissions("zone:front:project:query")
@GetMapping("/myProjectStatistics")
@ApiOperation("获取我的项目聚合统计")
@ApiImplicitParams({
@ApiImplicitParam(name = "zoneId", value = "专区ID", paramType = "query", dataType = "Long", required = true)
})
public GenericsAjaxResult<UserProjectStatisticsVo> myProjectStatistics(@ApiParam(name = "zoneId") @RequestParam(value = "zoneId") Long zoneId) {
return genericsSuccess(zoneProjectService.getUserProjectStatistics(zoneId,SecurityUtils.getUsername()));
}
/**
* 点赞/取消点赞
*/
@RequiresPermissions("zone:front:resource:query")
@PostMapping("/{id}/like")
@ApiOperation("点赞/取消点赞资源")
public AjaxResult toggleLike(
@ApiParam(value = "资源ID", required = true) @PathVariable("id") Long id) {
boolean liked = zoneResourceService.toggleZoneResourcesLike(id);
return success(liked ? "已点赞" : "已取消点赞");
}
/**
* 修改Skill资源
*/
@RequiresPermissions("zone:front:skill:edit")
@Log(title = "修改Skill资源", businessType = BusinessType.UPDATE)
@PutMapping("/skill")
@ApiOperation("修改Skill资源")
public AjaxResult editSkill(@RequestBody @Validated AiSkillUpdateVo updateVo) {
return success(zoneResourceService.updateAiSkillResource(updateVo));
}
// ==================== 模型资源 ====================
/**
* 创建Model资源
*/
@RequiresPermissions("zone:front:model:add")
@Log(title = "创建Model资源", businessType = BusinessType.INSERT)
@PostMapping("/resource/model")
@ApiOperation("创建Model资源")
public AjaxResult addModel(@RequestBody @Validated AiModelInputVo inputVo) {
return success(zoneResourceService.insertAiModelResource(inputVo));
}
/**
* 修改Model资源
*/
@RequiresPermissions("zone:front:model:edit")
@Log(title = "修改Model资源", businessType = BusinessType.UPDATE)
@PutMapping("/resource/model")
@ApiOperation("修改Model资源")
public AjaxResult editModel(@RequestBody @Validated AiModelUpdateVo updateVo) {
return success(zoneResourceService.updateAiModelResource(updateVo));
}
// ==================== 数据集资源 ====================
/**
* 创建Dataset资源
*/
@RequiresPermissions("zone:front:dataset:add")
@Log(title = "创建Dataset资源", businessType = BusinessType.INSERT)
@PostMapping("/resource/dataset")
@ApiOperation("创建Dataset资源")
public AjaxResult addDataset(@RequestBody @Validated AiDatasetInputVo inputVo) {
return success(zoneResourceService.insertAiDatasetResource(inputVo));
}
/**
* 修改Dataset资源
*/
@RequiresPermissions("zone:front:dataset:edit")
@Log(title = "修改Dataset资源", businessType = BusinessType.UPDATE)
@PutMapping("/resource/dataset")
@ApiOperation("修改Dataset资源")
public AjaxResult editDataset(@RequestBody @Validated AiDatasetUpdateVo updateVo) {
return success(zoneResourceService.updateAiDatasetResource(updateVo));
}
/**
* 查询资源是否点赞
*/
@RequiresPermissions("zone:front:resource:query")
@GetMapping("/{ids}/like")
@ApiOperation(value = "查询资源是否点赞")
public GenericsTableDataInfo<JSONObject> myResource(@PathVariable("ids") String ids) {
return new GenericsTableDataInfo<>(zoneResourceService.selectZoneResourcesIsLike(ids));
}
}

View File

@ -1,7 +1,6 @@
package com.microservices.zone.common.controller;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
@ -17,15 +16,13 @@ import com.microservices.zone.dataset.service.IZoneDataSetService;
import com.microservices.zone.detail.domain.vo.ZoneBaseDataVo;
import com.microservices.zone.detail.domain.vo.ZoneDetailDataVo;
import com.microservices.zone.detail.service.IZoneDetailService;
import com.microservices.zone.journals.domain.vo.ZoneJournalsDataTableVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsParentDataVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberDataVo;
import com.microservices.zone.member.domain.vo.ZoneMemberOpenSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberOverviewVo;
import com.microservices.zone.member.domain.vo.ZoneMemberSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import com.microservices.zone.member.domain.vo.ZonePointsTopDocVo;
import com.microservices.zone.member.service.IZoneMemberService;
import com.microservices.zone.member.service.IZoneMemberTypeService;
import com.microservices.zone.member.service.IZonePointsAccountService;
import com.microservices.zone.partners.domain.vo.ZonePartnersOverviewVo;
import com.microservices.zone.partners.service.IZonePartnersService;
import com.microservices.zone.project.domain.ZoneProjectType;
@ -35,10 +32,14 @@ import com.microservices.zone.project.domain.vo.ZoneProjectSearchVo;
import com.microservices.zone.project.domain.vo.ZoneStatisticsVo;
import com.microservices.zone.project.service.IZoneProjectService;
import com.microservices.zone.project.service.IZoneProjectTypeService;
import com.microservices.zone.resource.domain.ZoneResource;
import com.microservices.zone.resource.domain.ZoneResourceDomain;
import com.microservices.zone.resource.domain.ZoneResourceType;
import com.microservices.zone.resource.domain.vo.ZoneResourceDataVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceDomainSearchVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceOpenSearchVo;
import com.microservices.zone.resource.domain.vo.ZoneResourceSearchVo;
import com.microservices.zone.resource.enums.AiResourceCategory;
import com.microservices.zone.resource.service.IZoneResourceDomainService;
import com.microservices.zone.resource.service.IZoneResourceService;
import com.microservices.zone.resource.service.IZoneResourceTypeService;
@ -63,7 +64,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
/**
@ -79,8 +79,6 @@ public class OpenController extends BaseController {
@Autowired
private IZoneMemberService zoneMemberService;
@Autowired
private IZoneMemberTypeService zoneMemberTypeService;
@Autowired
private IZonePartnersService zonePartnersService;
@Autowired
private IZoneProjectService zoneProjectService;
@ -89,8 +87,6 @@ public class OpenController extends BaseController {
@Autowired
private IZoneDetailService zoneDetailService;
@Autowired
private IZonePointsAccountService zonePointsAccountService;
@Autowired
private IZoneResourceService zoneResourceService;
@Autowired
private IZoneDataSetService zoneDataSetService;
@ -109,6 +105,9 @@ public class OpenController extends BaseController {
@Autowired
private IZoneVisitsService zoneVisitsService;
@Autowired
private IGlobalSearchService globalSearchService;
/**
* 新增特色专区用户浏览
*/
@ -225,27 +224,6 @@ public class OpenController extends BaseController {
return genericsSuccess(zoneDetailService.getZoneStatistics(zoneId));
}
/**
* 查询专区置顶文章列表含首页推荐文章去重置顶在前
*/
@GetMapping("/getTopDoc/{zoneId}")
@ApiOperation(value = "查询专区置顶文章列表(含首页推荐,去重)")
public GenericsAjaxResult<List<ZonePointsTopDocVo>> getTopDoc(@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsAccountService.selectHomePageDocMergeList(zoneId));
}
/**
* 查询专区置顶项目列表
*/
@GetMapping("/getTopProject/{zoneId}")
@ApiOperation(value = "查询专区置顶项目列表")
public GenericsAjaxResult<List<ZoneProjectDataVo>> getTopProject(@PathVariable("zoneId") Long zoneId) {
if (!zoneDetailService.isPointsZone(zoneId)) {
return genericsSuccess(Collections.emptyList());
}
return genericsSuccess(zoneProjectService.selectTopProjectList(zoneId));
}
/**
* 查询特色专区项目分类列表
*/
@ -280,41 +258,6 @@ public class OpenController extends BaseController {
return getGenericsDataTable(list);
}
/**
* 获取特色专区会员分类列表含各分类下已审核会员数量
*/
@GetMapping("/{zoneId}/memberType/list")
@ApiOperation("获取特色专区会员分类列表(含已审核会员数量)")
public GenericsTableDataInfo<ZoneMemberTypeCountVo> memberTypeList(
@ApiParam(name = "zoneId", value = "专区Id", required = true) @PathVariable("zoneId") Long zoneId,
@ApiParam(name = "name", value = "会员分类名称") String name) {
List<ZoneMemberTypeCountVo> list = zoneMemberTypeService.selectZoneMemberTypeListWithCount(zoneId, name);
return getGenericsDataTable(list);
}
/**
* 获取特色专区会员列表仅已审核会员支持名称模糊搜索及分类/等级过滤
*/
@GetMapping("/{zoneId}/member/list")
@ApiOperation("获取特色专区会员列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前页码", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数未传默认100", paramType = "query", dataType = "Integer")
})
public GenericsTableDataInfo<ZoneMemberDataVo> memberList(
@ApiParam(name = "zoneId", value = "专区Id", required = true) @PathVariable("zoneId") Long zoneId,
ZoneMemberSearchVo zoneMemberSearchVo,
@RequestParam(value = "pageNum", required = false) Integer pageNum,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
zoneMemberSearchVo.setZoneId(zoneId);
if (pageNum == null || pageNum < 1) {
pageNum = 1;
}
int effectivePageSize = (pageSize == null || pageSize < 1) ? 100 : pageSize;
PageHelper.startPage(pageNum, effectivePageSize);
return zoneMemberService.selectOpenZoneMemberList(zoneMemberSearchVo);
}
/**
* 检查当前用户是否有该专区的权限
*/
@ -364,14 +307,9 @@ public class OpenController extends BaseController {
*/
@GetMapping("/{zoneId}/resourceDomain/list")
@ApiOperation("查询特色专区资源领域列表")
public GenericsTableDataInfo<ZoneResourceDomain> resourceList(
@ApiParam(name = "zoneId", value = "专区Id", required = true) @PathVariable("zoneId") Long zoneId,
@ApiParam(name = "name", value = "资源领域名称") String name) {
ZoneResourceDomain zoneResourceDomain = new ZoneResourceDomain();
zoneResourceDomain.setName(name);
zoneResourceDomain.setZoneId(zoneId);
public GenericsTableDataInfo<ZoneResourceDomain> resourceList(ZoneResourceDomainSearchVo zoneResourceDomainSearchVo) {
startPage();
List<ZoneResourceDomain> list = zoneResourceDomainService.selectZoneResourceDomainList(zoneResourceDomain);
List<ZoneResourceDomain> list = zoneResourceDomainService.selectZoneResourceDomainList(zoneResourceDomainSearchVo.toZoneResourceDomain());
return getGenericsDataTable(list);
}
@ -482,9 +420,6 @@ public class OpenController extends BaseController {
return getGenericsDataTable(list);
}
@Autowired
private IGlobalSearchService globalSearchService;
/**
* 全局搜索接口POST方法
*
@ -497,4 +432,24 @@ public class OpenController extends BaseController {
GlobalSearchResponse response = globalSearchService.globalSearch(globalSearchRequest);
return new GenericsTableDataInfo<>(response.getResults(), response.getTotal());
}
// ==================== 通用评论 - 开放接口 ====================
@Autowired
private com.microservices.zone.journals.service.IZoneJournalsService zoneJournalsService;
/**
* 公开-资源评论列表
*/
@GetMapping("/journals")
@ApiOperation("公开-评论列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer")
})
public GenericsAjaxResult<ZoneJournalsDataTableVo> journalsList(@Validated ZoneJournalsSearchVo searchVo) {
startPage();
List<ZoneJournalsParentDataVo> list = zoneJournalsService.selectJournalsList(searchVo);
return genericsSuccess(ZoneJournalsDataTableVo.toZoneJournalsDataTableVo(getDataTable(list)));
}
}

View File

@ -56,14 +56,4 @@ public interface IZoneAsyncService {
void clearZoneProjectSortByScoreCache(ZoneProject zoneProject);
List<JSONObject> getGitlinkProjectsDetail(List<String> gitLinkProjectIdList);
/**
* 异步发放项目审核通过积分
*
* @param zoneId 专区ID
* @param createBy 项目创建人用户名
* @param projectId 项目ID
* @param projectName 项目名称
*/
void addPublishProjectPointsAsync(Long zoneId, String createBy, Long projectId, String projectName);
}

View File

@ -1,6 +1,5 @@
package com.microservices.zone.common.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.CacheConstants;
@ -11,7 +10,6 @@ import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.system.api.RemoteCmsService;
import com.microservices.system.api.RemoteUserService;
import com.microservices.system.api.utils.FeignUtils;
import com.microservices.zone.common.service.IZoneAsyncService;
import com.microservices.zone.detail.domain.ZoneDetail;
@ -62,7 +60,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.*;
@ -80,8 +77,6 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
@Autowired
private RemoteCmsService remoteCmsService;
@Autowired
private RemoteUserService remoteUserService;
@Autowired
@Lazy
private IZoneProjectTypeService zoneProjectTypeService;
@Autowired
@ -144,21 +139,6 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
@Value("${zone.needCalcScoreZoneIds:}")
private String needCalcScoreZoneIds;
@Value("${zone.pointsDeptId:0}")
private Long pointsDeptId;
/**
* 项目启动时初始化积分部门ID到缓存
*/
@PostConstruct
public void initPointsDeptId() {
if (pointsDeptId != null && pointsDeptId > 0) {
redisService.setCacheObject(CacheConstants.ZONE_POINTS_DEPT_ID_KEY, pointsDeptId);
logger.info("积分部门ID初始化到缓存完成pointsDeptId={}", pointsDeptId);
}
}
/**
* 创建线程池
* 初始化专区耗时长在初始化文章经实验在文章初始化完成前其他步骤均已执行完成故设核心线程数为2
@ -170,11 +150,11 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
* Nthreads =Ncpu*Ucpu*(1+W/C)
*/
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5
2
, 10
, 10
, TimeUnit.SECONDS
, new ArrayBlockingQueue<>(10000)
, new ArrayBlockingQueue<>(100)
, Executors.defaultThreadFactory()
, (r, executor) -> {
throw new ServiceException("【%s】目前创建的人太多了请稍后再试", DateUtils.getNowDate());
@ -485,6 +465,11 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
List<ZoneProject> zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo);
for (ZoneProject zoneProject : zoneProjectList) {
setProjectGitlinkInfoCache(zoneProject);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
logger.error("初始化gitlink项目统计的定时任务延时被中断");
}
}
}
}
@ -536,26 +521,23 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
@Override
public List<JSONObject> getGitlinkProjectsDetail(List<String> gitLinkProjectIdList) {
int total = gitLinkProjectIdList.size();
if (total == 0) {
return new ArrayList<>();
}
// 向上取整分片修复原 size/50+1 在整除时多出一个空分片会发出一次 ids 为空的请求
int queryCount = (total + 49) / 50;
int queryCount = gitLinkProjectIdList.size() / 50 + 1;
CountDownLatch countDownLatch = new CountDownLatch(queryCount);
// 使用线程安全的 ConcurrentLinkedQueue 收集结果修复原 ArrayList 在多线程并发 addAll 下丢数据/越界的隐患
ConcurrentLinkedQueue<JSONObject> gitLinkProjectQueue = new ConcurrentLinkedQueue<>();
List<JSONObject> gitLinkProjectList = new ArrayList<>();
for (int i = 0; i < queryCount; i++) {
int finalI = i;
threadPoolExecutor.execute(() -> {
try {
int pageMaxCount = Math.min((finalI + 1) * 50, total);
int pageMaxCount = (finalI + 1) * 50;
if (pageMaxCount >= gitLinkProjectIdList.size()) {
pageMaxCount = gitLinkProjectIdList.size();
}
List<String> tmpIdList = gitLinkProjectIdList.subList(finalI * 50, pageMaxCount);
JSONObject result = gitLinkRequestHelper.doGet(
ZoneGitLinkRequestUrl.PROJECTS("?ids=" + String.join(ZoneConstants.ARRAY_SPLIT_SYMBOLS, tmpIdList))
);
gitLinkProjectQueue.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
gitLinkProjectList.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
} catch (Exception e) {
logger.error("异步批量获取项目详细信息失败:{}", e.getMessage());
} finally {
@ -569,7 +551,7 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
logger.error("根据gitlinkProjectId调用Gitlink接口批量获取项目详细信息失败{}", e.getMessage());
throw new ServiceException("获取平台项目详细信息失败");
}
return new ArrayList<>(gitLinkProjectQueue);
return gitLinkProjectList;
}
private Double calcProjectScore(ZoneProject zoneProject, String startDate, String endDate) {
@ -587,35 +569,4 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
return theWeekScore;
}
@Async
@Override
public void addPublishProjectPointsAsync(Long zoneId, String createBy, Long projectId, String projectName) {
try {
if (zoneId == null || createBy == null) {
logger.warn("项目审核通过增加积分失败zoneId或createBy为空projectId={}", projectId);
return;
}
// 获取用户ID
com.microservices.system.api.domain.SysUser sysUser = FeignUtils.getReturnData(
remoteUserService.getSysUserByUserName(createBy, SecurityConstants.INNER));
if (sysUser == null || sysUser.getUserId() == null) {
logger.warn("项目审核通过增加积分失败未找到用户信息createBy={}projectId={}", createBy, projectId);
return;
}
// 写入 Redis 积分队列
JSONObject task = new JSONObject();
task.put("sourceType", ZoneConstants.PublishProject.SOURCE_TYPE);
task.put("userId", sysUser.getUserId());
task.put("zoneId", zoneId);
task.put("sourceId", projectId);
task.put("subjectDesc", projectName);
task.put("operatorId", sysUser.getUserId());
redisService.leftPush(ZoneConstants.ZONE_POINTS_ASYNC_QUEUE_KEY, JSON.toJSONString(task));
logger.info("项目审核通过增加积分任务已提交 userId={} projectId={} projectName={}", sysUser.getUserId(), projectId, projectName);
} catch (Exception e) {
logger.error("项目审核通过增加积分任务提交失败 projectId={} error={}", projectId, e.getMessage(), e);
}
}
}

View File

@ -186,12 +186,6 @@ public class ZoneDetailDataVo extends BaseEntity {
@ApiModelProperty(value = "会员板块是否展示0:不展示1展示")
private Integer sectionMemberShow;
/**
* 积分板块是否展示0:不展示1展示
*/
@ApiModelProperty(value = "积分板块是否展示0:不展示1展示")
private Integer sectionPointsShow;
/**
* 帮助中心板块是否展示0:不展示1展示
*/

View File

@ -172,7 +172,6 @@ public interface IZoneDetailService {
ZoneFrontRoleVo checkCurrentRoleInZone(Long zoneId);
ZoneFrontRoleVo checkUserRoleInZone(Long zoneId, Long userId);
/**
* 通过组织id锁定/解锁专区资讯
*
@ -236,20 +235,4 @@ public interface IZoneDetailService {
ZoneDetail selectZoneDetailByIdNotVerifiedDataScope(Long zoneId);
ZoneStatisticsVo getZoneStatistics(Long zoneId);
/**
* 计算专区统计数据内部方法用于定时任务调用
*
* @param zoneId 专区ID
* @return 统计数据
*/
ZoneStatisticsVo calculateZoneStatistics(Long zoneId);
/**
* 判断专区是否为积分专区
*
* @param zoneId 专区ID
* @return true=是积分专区false=不是积分专区
*/
boolean isPointsZone(Long zoneId);
}

View File

@ -56,7 +56,6 @@ import com.microservices.zone.resource.mapper.ZoneResourceTypeMapper;
import com.microservices.zone.specialProject.domain.ZoneSpecialProject;
import com.microservices.zone.specialProject.service.IZoneSpecialProjectService;
import com.microservices.zone.utils.ZoneConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -68,7 +67,6 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -78,7 +76,6 @@ import java.util.stream.Collectors;
* @date 2023-05-09
*/
@Service
@Slf4j
public class ZoneDetailServiceImpl implements IZoneDetailService {
@Autowired
private ZoneDetailMapper zoneDetailMapper;
@ -114,11 +111,10 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
private ZonePartnersTypeMapper zonePartnersTypeMapper;
@Autowired
@Lazy
private IZoneSpecialProjectService zoneSpecialProjectService;
private IZoneMemberService zoneMemberService;
@Autowired
@Lazy
private IZoneMemberService zoneMemberService;
private IZoneSpecialProjectService zoneSpecialProjectService;
@Value("${zone.zoneAdminUrl}")
private String zoneAdminUrl;
@Value("${zone.zoneConfigurationPath:/zone/configuration}")
@ -131,16 +127,8 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
private String docManagePath;
@Value("${zone.projectManagePath:/zone/project/list}")
private String projectManagePath;
@Value("${zone.resourceManageUrl}")
private String resourceManageUrl;
@Value("${zone.docManageUrl}")
private String docManageUrl;
@Value("${zone.autoMemberZoneIds:}")
private String autoMemberZoneIds;
@Value("${zone.autoMemberTypeName:}")
private String autoMemberTypeName;
@Value("${zone.autoMemberLevelName:}")
private String autoMemberLevelName;
@Autowired
private RedisService redisService;
@ -227,13 +215,13 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
Date[] lastWeek = getLastWeek();
//专区文章数统计
ZoneDetailDataVo articlesGroupByKey = zoneDetailMapper
.countArticlesGroupByKey(lastWeek[0],lastWeek[1],zoneDetail.getKey()) ;
.countArticlesGroupByKey(lastWeek[0], lastWeek[1], zoneDetail.getKey());
if (articlesGroupByKey != null) {
zoneDetailDataVo.setWeekArticles(articlesGroupByKey.getWeekArticles());
}
//专区浏览数据统计
ZoneDetailDataVo puVsGroupByKey = zoneDetailMapper
.countPUVsGroupByKey(lastWeek[0],lastWeek[1],zoneDetail.getKey()) ;
.countPUVsGroupByKey(lastWeek[0], lastWeek[1], zoneDetail.getKey());
if (puVsGroupByKey != null) {
zoneDetailDataVo.setWeekPV(puVsGroupByKey.getWeekPV());
zoneDetailDataVo.setWeekUV(puVsGroupByKey.getWeekUV());
@ -633,16 +621,9 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
if (zoneDetail == null) {
throw new ServiceException(HttpStatus.NOT_FOUND, "该特色专区不存在或无权限访问(专区标识[" + zoneKey + "])");
}
ZoneDetailDataVo zoneDetailDataVo = getZoneDetailDataVoAndCmsProject(zoneDetail);
// 判断当前zone的deptId是否为redis中对应的ZONE_POINTS_DEPT_ID_KEY
Long cachedPointsDeptId = redisService.getCacheObject(CacheConstants.ZONE_POINTS_DEPT_ID_KEY);
if (zoneDetail.getDeptId() != null && cachedPointsDeptId != null
&& zoneDetail.getDeptId().equals(cachedPointsDeptId)) {
zoneDetailDataVo.setSectionPointsShow(1);
} else {
zoneDetailDataVo.setSectionPointsShow(0);
}
return zoneDetailDataVo;
// zoneTemplateCheck(template,zoneDetailDataVo);
return getZoneDetailDataVoAndCmsProject(zoneDetail);
}
@Override
@ -672,6 +653,7 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return JSON.toJSONString(zoneDetail);
}
private ZoneMemberInputVo newZoneMemberInputVo(Long zoneId, SysUser sysUser) {
if (sysUser.getGitlinkUserId() == null) {
return null;
@ -687,9 +669,6 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return null;
}
Long zoneMemberTypeId = zoneMemberTypes.get(0).getId();
if (StringUtils.isNotEmpty(autoMemberTypeName)) {
zoneMemberTypeId = zoneMemberTypes.stream().filter(x -> autoMemberTypeName.equals(x.getName())).map(ZoneMemberType::getId).findFirst().orElse(zoneMemberTypeId);
}
zoneMemberInputVo.setMemberTypeId(zoneMemberTypeId);
ZoneMemberLevel zoneMemberLevelSearch = new ZoneMemberLevel();
zoneMemberLevelSearch.setZoneId(zoneId);
@ -698,9 +677,6 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return null;
}
Long zoneMemberLevelId = zoneMemberLevels.get(0).getId();
if (StringUtils.isNotEmpty(autoMemberLevelName)) {
zoneMemberLevelId = zoneMemberLevels.stream().filter(x -> autoMemberLevelName.equals(x.getName())).map(ZoneMemberLevel::getId).findFirst().orElse(zoneMemberLevelId);
}
zoneMemberInputVo.setMemberLevelId(zoneMemberLevelId);
zoneMemberInputVo.setIsSendInvitation(false);
zoneMemberInputVo.setZoneId(zoneId);
@ -728,6 +704,7 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
}
}
}
SysDept sysDept = FeignUtils.getReturnData(remoteDeptService.getDeptByDeptId(zoneDetail.getDeptId(), SecurityConstants.INNER));
List<SysUserDeptRole> userIdentifyList = FeignUtils.getReturnData(
remoteUserService.getSysUserDeptRoleListByUserName(loginUser.getUsername(), SecurityConstants.INNER)
@ -780,70 +757,6 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return zoneFrontRoleVo;
}
public ZoneFrontRoleVo checkUserRoleInZone(Long zoneId, Long userId) {
ZoneFrontRoleVo zoneFrontRoleVo = new ZoneFrontRoleVo();
ZoneDetail zoneDetail = selectZoneDetailById(zoneId);
SysUser sysUser = FeignUtils.getReturnData(
remoteUserService.getSysUserByUserId(userId, SecurityConstants.INNER)
);
if (sysUser == null) {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_NONE);
return zoneFrontRoleVo;
}
SysDept sysDept = FeignUtils.getReturnData(remoteDeptService.getDeptByDeptId(zoneDetail.getDeptId(), SecurityConstants.INNER));
List<SysUserDeptRole> userIdentifyList = FeignUtils.getReturnData(
remoteUserService.getSysUserDeptRoleListByUserName(sysUser.getUserName(), SecurityConstants.INNER)
);
if (sysDept == null || userIdentifyList == null) {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_NONE);
return zoneFrontRoleVo;
} else {
List<String> deptIdList = Arrays.asList(sysDept.getAncestors().split(","));
SysUserDeptRole parentDeptUserIdentify = userIdentifyList
.stream()
.filter(x -> deptIdList.contains(String.valueOf(x.getDeptId())))
.filter(x -> !x.getSysRole().getRoleKey().equals(SystemRole.ZONE_MEMBER.getRoleKey()))
.findFirst().orElse(null);
SysUserDeptRole currentUserIdentify = userIdentifyList.stream().filter(x -> x.getDeptId().equals(zoneDetail.getDeptId())).findFirst().orElse(null);
String resourceManageUrl = adminUrl + resourceManagePath + "?changeCurrentUserIdentity=";
String docManageUrl = adminUrl + docManagePath + "?changeCurrentUserIdentity=";
String projectManageUrl = adminUrl + projectManagePath + "?changeCurrentUserIdentity=";
if (currentUserIdentify != null) {
if (currentUserIdentify.getSysRole().getRoleKey().equals(SystemRole.ZONE_MEMBER.getRoleKey())) {
if (parentDeptUserIdentify != null) {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER);
zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setDocManageUrl(docManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setDeptId(parentDeptUserIdentify.getDeptId());
} else {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MEMBER);
zoneFrontRoleVo.setDeptId(currentUserIdentify.getDeptId());
}
} else {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER);
zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + currentUserIdentify.getDeptId());
zoneFrontRoleVo.setDocManageUrl(docManageUrl + currentUserIdentify.getDeptId());
zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + currentUserIdentify.getDeptId());
zoneFrontRoleVo.setDeptId(currentUserIdentify.getDeptId());
}
return zoneFrontRoleVo;
} else if (parentDeptUserIdentify != null) {
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER);
zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setDocManageUrl(docManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + parentDeptUserIdentify.getDeptId());
zoneFrontRoleVo.setDeptId(parentDeptUserIdentify.getDeptId());
return zoneFrontRoleVo;
}
}
zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_NONE);
return zoneFrontRoleVo;
}
@Override
public int lockCmsByDeptId(Long deptId, Integer lockStatus) {
ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailByDeptId(deptId);
@ -920,7 +833,7 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
}
@Override
public ZoneStatisticsVo calculateZoneStatistics(Long zoneId) {
public ZoneStatisticsVo getZoneStatistics(Long zoneId) {
ZoneStatisticsVo zoneStatisticsVo = new ZoneStatisticsVo();
ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailById(zoneId);
@ -985,45 +898,6 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return zoneStatisticsVo;
}
@Override
public ZoneStatisticsVo getZoneStatistics(Long zoneId) {
String cacheKey = CacheConstants.getZoneStatisticsKey(zoneId);
try {
// 1. 尝试从Redis缓存获取
ZoneStatisticsVo cachedStatistics = redisService.getCacheObject(cacheKey);
if (cachedStatistics != null) {
log.debug("专区[{}]统计数据来自缓存", zoneId);
return cachedStatistics;
}
} catch (Exception e) {
log.warn("专区[{}]统计数据缓存读取失败,执行降级逻辑", zoneId, e);
}
// 2. 缓存异常或未命中执行实时计算
log.info("专区[{}]统计数据缓存未命中,执行实时计算", zoneId);
ZoneStatisticsVo statistics = calculateZoneStatistics(zoneId);
// 3. 尝试缓存计算结果失败不影响主流程
try {
redisService.setCacheObject(cacheKey, statistics, 7200L, TimeUnit.SECONDS);
} catch (Exception e) {
log.warn("专区[{}]统计数据缓存写入失败", zoneId, e);
}
return statistics;
}
@Override
public boolean isPointsZone(Long zoneId) {
ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailById(zoneId);
if (zoneDetail == null || zoneDetail.getDeptId() == null) {
return false;
}
Long cachedPointsDeptId = redisService.getCacheObject(CacheConstants.ZONE_POINTS_DEPT_ID_KEY);
return cachedPointsDeptId != null && zoneDetail.getDeptId().equals(cachedPointsDeptId);
}
public Date[] getLastWeek() {
LocalDate today = LocalDate.now();
LocalDate startOfWeek = today.with(java.time.DayOfWeek.MONDAY).minusDays(7);

View File

@ -0,0 +1,109 @@
package com.microservices.zone.journals.controller;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.core.web.page.TableDataInfo;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.zone.journals.domain.ZoneJournals;
import com.microservices.zone.journals.domain.vo.ZoneJournalsInputVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsParentDataVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsSearchVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsUpdateVo;
import com.microservices.zone.journals.service.IZoneJournalsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 通用评论Controller
*
* @author otto
* @date 2025-04-30
*/
@RestController
@RequestMapping("/journals")
@Api(tags = "通用评论接口")
public class ZoneJournalsController extends BaseController {
@Autowired
private IZoneJournalsService zoneJournalsService;
/**
* 查询评论列表二级结构
*/
// @RequiresPermissions("zone:journals:list")
@GetMapping("/list")
@ApiOperation("查询评论列表")
public GenericsTableDataInfo<ZoneJournalsParentDataVo> list(ZoneJournalsSearchVo searchVo) {
startPage();
List<ZoneJournalsParentDataVo> list = zoneJournalsService.selectJournalsList(searchVo);
return new GenericsTableDataInfo<>(list);
}
/**
* 获取评论详细信息
*/
// @RequiresPermissions("zone:journals:query")
@GetMapping("/{id}")
@ApiOperation("获取评论详细信息")
public AjaxResult getInfo(@ApiParam(value = "评论ID", required = true) @PathVariable("id") Long id) {
ZoneJournals zoneJournals = zoneJournalsService.selectZoneJournalsById(id);
return success(zoneJournals);
}
/**
* 新增评论
*/
// @RequiresPermissions("zone:journals:add")
@Log(title = "新增评论", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增评论")
public AjaxResult add(@RequestBody @Validated ZoneJournalsInputVo inputVo) {
Long journalId = zoneJournalsService.insertJournals(inputVo);
return success(journalId);
}
/**
* 修改评论
*/
// @RequiresPermissions("zone:journals:edit")
@Log(title = "修改评论", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改评论")
public AjaxResult edit(@RequestBody @Validated ZoneJournalsUpdateVo updateVo) {
int result = zoneJournalsService.updateJournals(updateVo);
return toAjax(result);
}
/**
* 删除评论
*/
// @RequiresPermissions("zone:journals:remove")
@Log(title = "删除评论", businessType = BusinessType.DELETE)
@DeleteMapping("/{id}")
@ApiOperation("删除评论")
public AjaxResult remove(@ApiParam(value = "评论ID", required = true) @PathVariable("id") Long id) {
int result = zoneJournalsService.deleteJournalsById(id);
return toAjax(result);
}
/**
* 批量删除评论
*/
// @RequiresPermissions("zone:journals:remove")
@Log(title = "批量删除评论", businessType = BusinessType.DELETE)
@DeleteMapping("/batch/{ids}")
@ApiOperation("批量删除评论")
public AjaxResult removeBatch(@ApiParam(value = "评论ID数组", required = true) @PathVariable Long[] ids) {
int result = zoneJournalsService.deleteJournalsByIds(ids);
return toAjax(result);
}
}

View File

@ -0,0 +1,84 @@
package com.microservices.zone.journals.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.microservices.common.core.web.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* 通用评论对象 zone_journals
*
* @author otto
* @date 2025-04-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("通用评论对象")
public class ZoneJournals extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 评论对象类型常量
*/
public static final String JOURNAL_TYPE_ZONE_RESOURCE = "resource";
/** 评论ID */
@ApiModelProperty(value = "评论ID")
private Long id;
/** 评论对象ID */
@ApiModelProperty(value = "评论对象ID")
private Long journalizedId;
/** 评论对象类型 */
@ApiModelProperty(value = "评论对象类型")
private String journalizedType;
/** GitLink用户ID */
@ApiModelProperty(value = "GitLink用户ID")
private Long userId;
/** 评论内容 */
@ApiModelProperty(value = "评论内容")
private String notes;
/** 父级评论ID */
@ApiModelProperty(value = "父级评论ID")
private Long parentId;
/** 回复的评论ID */
@ApiModelProperty(value = "回复的评论ID")
private Long replyId;
/** 评论数量 */
@ApiModelProperty(value = "评论数量")
private Integer commentsCount;
/** 附件标识列表 */
@ApiModelProperty(value = "附件标识列表")
private String attachmentIdentifiers;
/** @用户列表 */
@ApiModelProperty(value = "@用户列表")
private String receiversLogin;
/** 删除标志 */
@ApiModelProperty(value = "删除标志")
private String delFlag;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createdOn;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updatedOn;
}

View File

@ -0,0 +1,23 @@
package com.microservices.zone.journals.domain.vo;
import com.microservices.system.api.domain.SimpleSysUser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 通用评论子级评论数据VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("子级评论数据对象")
public class ZoneJournalsChildrenDataVo extends ZoneJournalsDataVo {
/** 回复的用户 */
@ApiModelProperty(value = "回复的用户")
private SimpleSysUser reply_user;
}

View File

@ -0,0 +1,40 @@
package com.microservices.zone.journals.domain.vo;
import com.microservices.common.core.web.page.TableDataInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 评论列表对象
*/
@Data
@ApiModel("评论列表对象")
public class ZoneJournalsDataTableVo {
@ApiModelProperty(value = "评论列表")
private List<?> journals;
@ApiModelProperty(value = "评论总数量")
private Long total_comment_journals_count;
@ApiModelProperty(value = "当前总数量")
private Long total_count;
@ApiModelProperty(value = "评论+操作总数量")
private Long total_journals_count;
@ApiModelProperty(value = "操作总数量")
private Long total_operate_journals_count;
public static ZoneJournalsDataTableVo toZoneJournalsDataTableVo(TableDataInfo tableDataInfo) {
ZoneJournalsDataTableVo target = new ZoneJournalsDataTableVo();
target.setJournals(tableDataInfo.getRows());
target.setTotal_comment_journals_count(tableDataInfo.getTotal());
target.setTotal_count(tableDataInfo.getTotal());
target.setTotal_journals_count(tableDataInfo.getTotal());
target.setTotal_operate_journals_count(0L);
return target;
}
}

View File

@ -0,0 +1,57 @@
package com.microservices.zone.journals.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.microservices.system.api.domain.SimpleGitlinkFileInfo;
import com.microservices.system.api.domain.SysFileInfo;
import com.microservices.system.api.domain.SimpleSysUser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 通用评论基础数据VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@ApiModel("评论数据对象")
public class ZoneJournalsDataVo {
/** 评论ID */
@ApiModelProperty(value = "评论ID")
private Long id;
/** 评论用户 */
@ApiModelProperty(value = "评论用户")
private SimpleSysUser user;
/** 评论内容 */
@ApiModelProperty(value = "评论内容")
private String notes;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date created_on;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updated_on;
/** 附件列表 */
@ApiModelProperty(value = "附件列表")
private List<SimpleGitlinkFileInfo> attachments;
/** 评论数量 */
@ApiModelProperty(value = "评论数量")
private Integer comments_count = 0;
/** 是否详情 */
@ApiModelProperty(value = "是否详情")
private Boolean is_journal_detail = false;
}

View File

@ -0,0 +1,52 @@
package com.microservices.zone.journals.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 通用评论输入VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@ApiModel("评论输入对象")
public class ZoneJournalsInputVo {
/** 评论对象ID */
@NotNull(message = "评论对象ID不能为空")
@ApiModelProperty(value = "评论对象ID", required = true)
private Long journalized_id;
/** 评论对象类型 */
@NotBlank(message = "评论对象类型不能为空资源resource")
@ApiModelProperty(value = "评论对象类型", required = true)
private String journalized_type;
/** 父级评论ID */
@ApiModelProperty(value = "父级评论ID")
private Long parent_id;
/** 回复的评论ID */
@ApiModelProperty(value = "回复的评论ID")
private Long reply_id;
/** 评论内容 */
@NotBlank(message = "评论内容不能为空")
@Size(max = 2000, message = "评论内容不能超过2000个字符")
@ApiModelProperty(value = "评论内容", required = true)
private String notes;
/** @用户列表 */
@ApiModelProperty(value = "@用户列表")
private String[] receivers_login;
/** 附件标识列表 */
@ApiModelProperty(value = "附件标识列表")
private String attachment_identifiers;
}

View File

@ -0,0 +1,24 @@
package com.microservices.zone.journals.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 通用评论父级评论数据VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("父级评论数据对象")
public class ZoneJournalsParentDataVo extends ZoneJournalsDataVo {
/** 子级评论列表 */
@ApiModelProperty(value = "子级评论列表")
private List<ZoneJournalsChildrenDataVo> children_journals;
}

View File

@ -0,0 +1,28 @@
package com.microservices.zone.journals.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 通用评论查询VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@ApiModel("评论查询对象")
public class ZoneJournalsSearchVo {
/** 评论对象ID */
@NotNull
@ApiModelProperty(value = "评论对象ID")
private Long journalized_id;
/** 评论对象类型 */
@NotBlank
@ApiModelProperty(value = "评论对象类型资源resource")
private String journalized_type;
}

View File

@ -0,0 +1,39 @@
package com.microservices.zone.journals.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 通用评论更新VO
*
* @author otto
* @date 2025-04-30
*/
@Data
@ApiModel("评论更新对象")
public class ZoneJournalsUpdateVo {
/** 评论ID */
@NotNull(message = "评论ID不能为空")
@ApiModelProperty(value = "评论ID", required = true)
private Long id;
/** 评论内容 */
@NotBlank(message = "评论内容不能为空")
@Size(max = 2000, message = "评论内容不能超过2000个字符")
@ApiModelProperty(value = "评论内容", required = true)
private String notes;
/** @用户列表 */
@ApiModelProperty(value = "@用户列表")
private String[] receivers_login;
/** 附件标识列表 */
@ApiModelProperty(value = "附件标识列表")
private String attachment_identifiers;
}

View File

@ -0,0 +1,115 @@
package com.microservices.zone.journals.mapper;
import com.microservices.zone.journals.domain.ZoneJournals;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 通用评论Mapper接口
*
* @author otto
* @date 2025-04-30
*/
@Mapper
public interface ZoneJournalsMapper {
/**
* 查询评论
*
* @param id 评论主键
* @return 评论
*/
ZoneJournals selectZoneJournalsById(Long id);
/**
* 查询评论列表父评论
*
* @param zoneJournals 评论查询条件
* @return 评论集合
*/
List<ZoneJournals> selectZoneJournalsList(ZoneJournals zoneJournals);
/**
* 查询子评论列表
*
* @param parentId 父评论ID
* @return 子评论集合
*/
List<ZoneJournals> selectChildrenZoneJournalsList(@Param("parentId") Long parentId);
/**
* 新增评论
*
* @param zoneJournals 评论
* @return 结果
*/
int insertZoneJournals(ZoneJournals zoneJournals);
/**
* 修改评论
*
* @param zoneJournals 评论
* @return 结果
*/
int updateZoneJournals(ZoneJournals zoneJournals);
/**
* 删除评论逻辑删除
*
* @param id 评论主键
* @return 结果
*/
int deleteZoneJournalsById(Long id);
/**
* 批量删除评论逻辑删除
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deleteZoneJournalsByIds(Long[] ids);
/**
* 删除子评论逻辑删除
*
* @param parentId 父评论ID
* @return 结果
*/
int deleteZoneJournalsByParentId(@Param("parentId") Long parentId);
/**
* 根据类型和评论对象Id删除所有评论
*
* @param type 类型
* @param journalId 评论对象Id
*/
void deleteZoneJournalsByTypeAndJournalId(@Param("type") String type, @Param("journalId") Long journalId);
/**
* 批量更新关联ID
*
* @param type 类型
* @param oldJournalId 旧评论对象Id
* @param journalId 新评论对象Id
*/
void updateJournalsIdByTypeAndOldId(@Param("type") String type, @Param("oldJournalId") Long oldJournalId, @Param("journalId") Long journalId);
/**
* 更新父评论的子评论数量
*
* @param id 父评论ID
* @return 结果
*/
int updateCommentsCountById(@Param("id") Long id);
/**
* 统计评论数量
*
* @param journalizedId 评论对象ID
* @param journalizedType 评论对象类型
* @return 评论数量
*/
int countByJournalized(@Param("journalizedId") Long journalizedId, @Param("journalizedType") String journalizedType);
}

View File

@ -0,0 +1,83 @@
package com.microservices.zone.journals.service;
import com.microservices.zone.journals.domain.ZoneJournals;
import com.microservices.zone.journals.domain.vo.ZoneJournalsInputVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsParentDataVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsSearchVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsUpdateVo;
import java.util.List;
/**
* 通用评论Service接口
*
* @author otto
* @date 2025-04-30
*/
public interface IZoneJournalsService {
/**
* 查询评论
*
* @param id 评论主键
* @return 评论
*/
ZoneJournals selectZoneJournalsById(Long id);
/**
* 查询评论列表二级结构
*
* @param searchVo 查询条件
* @return 评论列表父评论包含子评论
*/
List<ZoneJournalsParentDataVo> selectJournalsList(ZoneJournalsSearchVo searchVo);
/**
* 新增评论
*
* @param inputVo 评论输入信息
* @return 评论ID
*/
Long insertJournals(ZoneJournalsInputVo inputVo);
/**
* 修改评论
*
* @param updateVo 评论更新信息
* @return 结果
*/
int updateJournals(ZoneJournalsUpdateVo updateVo);
/**
* 删除评论级联删除子评论
*
* @param id 评论主键
* @return 结果
*/
int deleteJournalsById(Long id);
/**
* 批量删除评论
*
* @param ids 需要删除的评论主键集合
* @return 结果
*/
int deleteJournalsByIds(Long[] ids);
/**
* 根据类型和评论对象Id删除所有评论
*
* @param type 类型
* @param journalId 评论对象Id
*/
void deleteJournalsByTypeAndJournalId(String type, Long journalId);
/**
* 批量更新关联ID
*
* @param type 类型
* @param oldJournalId 旧评论对象Id
* @param journalId 新评论对象Id
*/
void updateJournalsIdByTypeAndOldId(String type, Long oldJournalId, Long journalId);
}

View File

@ -0,0 +1,406 @@
package com.microservices.zone.journals.service.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.system.api.RemoteFileService;
import com.microservices.system.api.domain.SimpleGitlinkFileInfo;
import com.microservices.system.api.domain.SysFileInfo;
import com.microservices.system.api.domain.SimpleSysUser;
import com.microservices.system.api.utils.FeignUtils;
import com.microservices.zone.common.service.IZoneCommonService;
import com.microservices.zone.journals.domain.ZoneJournals;
import com.microservices.zone.journals.domain.vo.ZoneJournalsChildrenDataVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsInputVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsParentDataVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsSearchVo;
import com.microservices.zone.journals.domain.vo.ZoneJournalsUpdateVo;
import com.microservices.zone.journals.mapper.ZoneJournalsMapper;
import com.microservices.zone.journals.service.IZoneJournalsService;
import com.microservices.zone.resource.service.IZoneResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 通用评论Service业务层处理
*
* @author otto
* @date 2025-04-30
*/
@Service
public class ZoneJournalsServiceImpl implements IZoneJournalsService {
@Autowired
private ZoneJournalsMapper zoneJournalsMapper;
@Autowired
private IZoneCommonService zoneCommonService;
@Autowired
private IZoneResourceService zoneResourceService;
@Autowired
private RemoteFileService remoteFileService;
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 查询评论
*
* @param id 评论主键
* @return 评论
*/
@Override
public ZoneJournals selectZoneJournalsById(Long id) {
ZoneJournals zoneJournals = zoneJournalsMapper.selectZoneJournalsById(id);
if (zoneJournals == null) {
throw new ServiceException("该评论不存在(评论Id[%d])", id);
}
// 校验评论对象是否存在
checkByType(zoneJournals);
return zoneJournals;
}
/**
* 查询评论列表二级结构
*
* @param searchVo 查询条件
* @return 评论列表父评论包含子评论
*/
@Override
public List<ZoneJournalsParentDataVo> selectJournalsList(ZoneJournalsSearchVo searchVo) {
// 校验评论对象是否存在
ZoneJournals checkJournal = new ZoneJournals();
checkJournal.setJournalizedId(searchVo.getJournalized_id());
checkJournal.setJournalizedType(searchVo.getJournalized_type());
checkByType(checkJournal);
// 查询父评论列表
ZoneJournals query = new ZoneJournals();
query.setJournalizedId(searchVo.getJournalized_id());
query.setJournalizedType(searchVo.getJournalized_type());
List<ZoneJournals> parentJournalsList = zoneJournalsMapper.selectZoneJournalsList(query);
// 转换为VO并组装子评论
return parentJournalsList.stream()
.map(this::toParentDataVo)
.collect(Collectors.toList());
}
/**
* 新增评论
*
* @param inputVo 评论输入信息
* @return 评论ID
*/
@Override
public Long insertJournals(ZoneJournalsInputVo inputVo) {
// 校验评论对象类型
ZoneJournals zoneJournals = new ZoneJournals();
zoneJournals.setJournalizedId(inputVo.getJournalized_id());
zoneJournals.setJournalizedType(inputVo.getJournalized_type());
checkByType(zoneJournals);
// 如果是子评论校验父评论
if (inputVo.getParent_id() != null) {
ZoneJournals parentJournal = selectZoneJournalsById(inputVo.getParent_id());
if (parentJournal.getParentId() != null) {
throw new ServiceException("该评论非父级评论(评论ID[%d])", parentJournal.getId());
}
if (!parentJournal.getJournalizedType().equals(inputVo.getJournalized_type())) {
throw new ServiceException("当前父级评论与当前评论类型不相同");
}
if (!parentJournal.getJournalizedId().equals(inputVo.getJournalized_id())) {
throw new ServiceException("当前父级评论与当前评论对象不相同");
}
}
// 如果有回复评论校验回复评论
if (inputVo.getReply_id() != null) {
if (inputVo.getParent_id() == null) {
throw new ServiceException("一级评论不能进行回复操作");
}
ZoneJournals replyJournal = selectZoneJournalsById(inputVo.getReply_id());
if (!replyJournal.getJournalizedType().equals(inputVo.getJournalized_type())) {
throw new ServiceException("当前回复评论与当前评论类型不相同");
}
if (!replyJournal.getJournalizedId().equals(inputVo.getJournalized_id())) {
throw new ServiceException("当前回复评论与当前评论对象不相同");
}
}
// 校验附件列表
checkAttachments(inputVo.getAttachment_identifiers());
// 构建评论对象
ZoneJournals newJournal = new ZoneJournals();
newJournal.setJournalizedId(inputVo.getJournalized_id());
newJournal.setJournalizedType(inputVo.getJournalized_type());
newJournal.setParentId(inputVo.getParent_id());
newJournal.setReplyId(inputVo.getReply_id());
newJournal.setNotes(inputVo.getNotes());
newJournal.setAttachmentIdentifiers(inputVo.getAttachment_identifiers());
// 处理@用户列表
if (inputVo.getReceivers_login() != null && inputVo.getReceivers_login().length > 0) {
try {
newJournal.setReceiversLogin(objectMapper.writeValueAsString(inputVo.getReceivers_login()));
} catch (Exception e) {
throw new ServiceException("@用户列表格式错误");
}
}
// 获取当前用户ID
Long userId = SecurityUtils.getUserId();
if (userId == null || userId == 0) {
throw new ServiceException("无法获取当前用户信息");
}
newJournal.setUserId(userId);
newJournal.setCreateBy(SecurityUtils.getUsername());
newJournal.setCreatedOn(DateUtils.getNowDate());
// 插入评论
zoneJournalsMapper.insertZoneJournals(newJournal);
// 如果是子评论更新父评论的子评论数量
if (inputVo.getParent_id() != null) {
zoneJournalsMapper.updateCommentsCountById(inputVo.getParent_id());
}
return newJournal.getId();
}
/**
* 修改评论
*
* @param updateVo 评论更新信息
* @return 结果
*/
@Override
public int updateJournals(ZoneJournalsUpdateVo updateVo) {
// 查询原评论并校验
ZoneJournals oldJournal = selectZoneJournalsById(updateVo.getId());
// 校验是否为评论创建者
Long userId = SecurityUtils.getUserId();
if (!oldJournal.getUserId().equals(userId)) {
throw new ServiceException("只能修改自己的评论");
}
// 校验附件列表
checkAttachments(updateVo.getAttachment_identifiers());
// 构建更新对象
ZoneJournals updateJournal = new ZoneJournals();
updateJournal.setId(updateVo.getId());
updateJournal.setNotes(updateVo.getNotes());
updateJournal.setAttachmentIdentifiers(updateVo.getAttachment_identifiers());
// 处理@用户列表
if (updateVo.getReceivers_login() != null && updateVo.getReceivers_login().length > 0) {
try {
updateJournal.setReceiversLogin(objectMapper.writeValueAsString(updateVo.getReceivers_login()));
} catch (Exception e) {
throw new ServiceException("@用户列表格式错误");
}
}
updateJournal.setUpdateBy(SecurityUtils.getUsername());
updateJournal.setUpdatedOn(DateUtils.getNowDate());
return zoneJournalsMapper.updateZoneJournals(updateJournal);
}
/**
* 删除评论级联删除子评论
*
* @param id 评论主键
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteJournalsById(Long id) {
ZoneJournals zoneJournals = selectZoneJournalsById(id);
// 校验是否为评论创建者
Long userId = SecurityUtils.getUserId();
if (!zoneJournals.getUserId().equals(userId)) {
throw new ServiceException("只能删除自己的评论");
}
// 如果是父级评论先删除所有子评论
if (zoneJournals.getParentId() == null) {
List<ZoneJournals> childrenJournalsList = zoneJournalsMapper.selectChildrenZoneJournalsList(zoneJournals.getId());
for (ZoneJournals childrenJournal : childrenJournalsList) {
zoneJournalsMapper.deleteZoneJournalsById(childrenJournal.getId());
}
}
return zoneJournalsMapper.deleteZoneJournalsById(id);
}
/**
* 批量删除评论
*
* @param ids 需要删除的评论主键集合
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteJournalsByIds(Long[] ids) {
int success = 0;
for (Long id : ids) {
success += deleteJournalsById(id);
}
return success;
}
/**
* 根据类型和评论对象Id删除所有评论
*
* @param type 类型
* @param journalId 评论对象Id
*/
@Override
public void deleteJournalsByTypeAndJournalId(String type, Long journalId) {
zoneJournalsMapper.deleteZoneJournalsByTypeAndJournalId(type, journalId);
}
/**
* 批量更新关联ID
*
* @param type 类型
* @param oldJournalId 旧评论对象Id
* @param journalId 新评论对象Id
*/
@Override
public void updateJournalsIdByTypeAndOldId(String type, Long oldJournalId, Long journalId) {
zoneJournalsMapper.updateJournalsIdByTypeAndOldId(type, oldJournalId, journalId);
}
/**
* 根据类型校验评论对象是否存在
*
* @param zoneJournals 评论对象
*/
private void checkByType(ZoneJournals zoneJournals) {
if (zoneJournals.getJournalizedType().equals(ZoneJournals.JOURNAL_TYPE_ZONE_RESOURCE)) {// 校验资源是否存在
zoneResourceService.selectZoneResourceById(zoneJournals.getJournalizedId());
} else {
throw new ServiceException("当前不支持该类型评论(评论类型[%s])", zoneJournals.getJournalizedType());
}
}
/**
* 校验附件列表
*
* @param attachmentIdentifiers 附件标识列表
*/
private void checkAttachments(String attachmentIdentifiers) {
if (StringUtils.isEmpty(attachmentIdentifiers)) {
return;
}
try {
List<SysFileInfo> fileInfos = FeignUtils.getReturnData(
remoteFileService.getFileListByIdentifier(attachmentIdentifiers)
);
if (CollectionUtils.isEmpty(fileInfos)) {
throw new ServiceException("附件不存在或已被删除");
}
} catch (Exception e) {
throw new ServiceException("附件校验失败:%s", e.getMessage());
}
}
/**
* 转换为父评论VO
*
* @param zoneJournals 评论实体
* @return 父评论VO
*/
private ZoneJournalsParentDataVo toParentDataVo(ZoneJournals zoneJournals) {
ZoneJournalsParentDataVo parentVo = new ZoneJournalsParentDataVo();
parentVo.setId(zoneJournals.getId());
parentVo.setNotes(zoneJournals.getNotes());
parentVo.setCreated_on(zoneJournals.getCreatedOn());
parentVo.setUpdated_on(zoneJournals.getUpdatedOn());
// 获取用户信息
SimpleSysUser user = zoneCommonService.getSimpleSysUserByUserId(zoneJournals.getUserId());
parentVo.setUser(user);
// 获取附件列表
parentVo.setAttachments(getAttachments(zoneJournals.getAttachmentIdentifiers()));
// 获取子评论列表
List<ZoneJournals> childrenJournalsList = zoneJournalsMapper.selectChildrenZoneJournalsList(zoneJournals.getId());
List<ZoneJournalsChildrenDataVo> childrenVoList = childrenJournalsList.stream()
.map(this::toChildrenDataVo)
.collect(Collectors.toList());
parentVo.setChildren_journals(childrenVoList);
parentVo.setComments_count(childrenVoList.size());
return parentVo;
}
/**
* 转换为子评论VO
*
* @param zoneJournals 评论实体
* @return 子评论VO
*/
private ZoneJournalsChildrenDataVo toChildrenDataVo(ZoneJournals zoneJournals) {
ZoneJournalsChildrenDataVo childrenVo = new ZoneJournalsChildrenDataVo();
childrenVo.setId(zoneJournals.getId());
childrenVo.setNotes(zoneJournals.getNotes());
childrenVo.setCreated_on(zoneJournals.getCreatedOn());
childrenVo.setUpdated_on(zoneJournals.getUpdatedOn());
// 获取用户信息
SimpleSysUser user = zoneCommonService.getSimpleSysUserByUserId(zoneJournals.getUserId());
childrenVo.setUser(user);
// 获取附件列表
childrenVo.setAttachments(getAttachments(zoneJournals.getAttachmentIdentifiers()));
// 获取回复用户信息
if (zoneJournals.getReplyId() != null) {
ZoneJournals replyJournal = zoneJournalsMapper.selectZoneJournalsById(zoneJournals.getReplyId());
if (replyJournal != null) {
SimpleSysUser replyUser = zoneCommonService.getSimpleSysUserByUserId(replyJournal.getUserId());
childrenVo.setReply_user(replyUser);
}
}
return childrenVo;
}
/**
* 获取附件列表
*
* @param attachmentIdentifiers 附件标识列表
* @return 附件列表
*/
private List<SimpleGitlinkFileInfo> getAttachments(String attachmentIdentifiers) {
if (StringUtils.isEmpty(attachmentIdentifiers)) {
return new ArrayList<>();
}
try {
List<SysFileInfo> fileInfos = FeignUtils.getReturnData(
remoteFileService.getFileListByIdentifier(attachmentIdentifiers)
);
return CollectionUtils.isEmpty(fileInfos) ? new ArrayList<>() : fileInfos.stream().map(SysFileInfo::toSimpleGitlinkFileInfo).collect(Collectors.toList());
} catch (Exception e) {
return new ArrayList<>();
}
}
}

View File

@ -67,16 +67,6 @@ public class ZoneMemberController extends BaseController {
return AjaxResult.success("审核状态获取成功",auditStatus);
}
/**
* 查询当前登录用户会员审核状态
*/
@GetMapping("/zone/{zoneId}/memberInfo")
@ApiOperation("查询当前登录用户会员信息")
public AjaxResult getMemberInfo(@PathVariable("zoneId") Long zoneId) {
ZoneMember memberInfo = zoneMemberService.selectZoneMemberInfo(zoneId);
return AjaxResult.success("审核状态获取成功",memberInfo);
}
/**
* 查询GitLink用户列表
*/
@ -118,16 +108,6 @@ public class ZoneMemberController extends BaseController {
return genericsSuccess(zoneMemberService.selectZoneMemberById(id));
}
/**
* 根据专区ID修改当前登录用户会员信息
*/
@PutMapping(value = "/customEdit/zone/{zoneId}")
@ApiOperation("根据专区ID修改当前登录用户会员信息")
@Log(title = "特色专区会员", businessType = BusinessType.UPDATE)
public AjaxResult customEdit(@PathVariable("zoneId") Long zoneId, @RequestBody ZoneMemberUpdateVo zoneMemberUpdateVo) {
return toAjax(zoneMemberService.updateZoneMemberByMember(zoneId, zoneMemberUpdateVo));
}
/**
* 检查并获取组织下的会员列表
*/

View File

@ -1,218 +0,0 @@
package com.microservices.zone.member.controller;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import com.microservices.zone.member.domain.vo.*;
import com.microservices.zone.member.service.IZonePointsAccountService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 专区积分账户Controller
*
* @author otto
*/
@RestController
@RequestMapping("/points/account")
@Api(tags = "专区积分账户接口")
public class ZonePointsAccountController extends BaseController {
@Autowired
private IZonePointsAccountService zonePointsAccountService;
/**
* 查询专区积分账户列表
*/
@RequiresPermissions("zone:points:account:list")
@GetMapping("/list")
@ApiOperation("查询专区积分账户列表")
public GenericsTableDataInfo<ZonePointsAccount> list(ZonePointsAccountSearchVo searchVo) {
startPage();
List<ZonePointsAccount> list = zonePointsAccountService.selectZonePointsAccountList(searchVo.toZonePointsAccount());
return getGenericsDataTable(list);
}
/**
* 获取专区积分账户详细信息
*/
@RequiresPermissions("zone:points:account:query")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取专区积分账户详细信息")
public GenericsAjaxResult<ZonePointsAccount> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(zonePointsAccountService.selectZonePointsAccountById(id));
}
/**
* 新增专区积分账户
*/
@RequiresPermissions("zone:points:account:add")
@Log(title = "专区积分账户", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增专区积分账户")
public AjaxResult add(@RequestBody ZonePointsAccountInputVo inputVo) {
return toAjax(zonePointsAccountService.insertZonePointsAccount(inputVo));
}
/**
* 修改专区积分账户
*/
@RequiresPermissions("zone:points:account:edit")
@Log(title = "专区积分账户", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改专区积分账户")
public AjaxResult edit(@RequestBody ZonePointsAccountUpdateVo updateVo) {
return toAjax(zonePointsAccountService.updateZonePointsAccount(updateVo));
}
/**
* 删除专区积分账户
*/
@RequiresPermissions("zone:points:account:remove")
@Log(title = "专区积分账户", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除专区积分账户")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(zonePointsAccountService.deleteZonePointsAccountByIds(ids));
}
/**
* 根据用户ID和专区ID查询积分账户
*/
@RequiresPermissions("zone:points:account:query")
@GetMapping("/user/{userId}/zone/{zoneId}")
@ApiOperation(value = "根据用户ID和专区ID查询积分账户")
public GenericsAjaxResult<ZonePointsAccount> getByUserIdAndZoneId(@PathVariable("userId") Long userId,
@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsAccountService.selectZonePointsAccountByUserIdAndZoneId(userId, zoneId));
}
/**
* 根据会员ID查询积分账户列表
*/
@RequiresPermissions("zone:points:account:query")
@GetMapping("/member/{memberId}")
@ApiOperation(value = "根据会员ID查询积分账户列表")
public GenericsAjaxResult<List<ZonePointsAccount>> getByMemberId(@PathVariable("memberId") Long memberId) {
return genericsSuccess(zonePointsAccountService.selectZonePointsAccountByMemberId(memberId));
}
/**
* 获取当前登录用户的积分账户总览信息
*/
@GetMapping("/overview/{zoneId}")
@ApiOperation(value = "获取当前登录用户的积分账户总览信息")
public GenericsAjaxResult<ZonePointsOverviewVo> getCurrentUserPointsOverview(@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsAccountService.getCurrentUserPointsOverview(zoneId));
}
/**
* 电子证书积分扣减前台用户操作业务层已做会员身份+积分专区+幂等+积分校验
*/
@PostMapping("/certificate/redeem")
@ApiOperation(value = "电子证书积分扣减")
public AjaxResult redeemCertificate(@RequestBody ZonePointsTransactionInputVo inputVo) {
zonePointsAccountService.deductPointsForCertificate(inputVo);
return success();
}
/**
* 文章置顶积分扣减前台用户操作业务层已做会员身份+积分专区+积分校验
* 用户使用当前登录用户
*/
@PostMapping("/article/top")
@ApiOperation(value = "文章置顶积分扣减")
public AjaxResult topArticle(@RequestBody ZonePointsArticleTopInputVo inputVo) {
zonePointsAccountService.deductPointsForArticleTop(inputVo.getZoneId(), inputVo.getId(), inputVo.getName());
return success();
}
/**
* 获取当前登录用户的置顶文章信息
*/
@GetMapping("/article/top/{zoneId}")
@ApiOperation(value = "获取当前登录用户的置顶文章信息")
public GenericsAjaxResult<ZonePointsTopDocVo> getCurrentUserPointsTopDoc(@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsAccountService.getCurrentUserPointsTopDoc(zoneId));
}
/**
* 获取当前登录用户的置顶项目信息
*/
@GetMapping("/project/top/{zoneId}")
@ApiOperation(value = "获取当前登录用户的置顶项目信息")
public GenericsAjaxResult<ZonePointsTopProjectVo> getZonePointsTopProject(@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsAccountService.getZonePointsTopProject(zoneId));
}
/**
* 项目置顶积分扣减前台用户操作业务层已做会员身份+积分专区+积分校验
* 用户使用当前登录用户
*/
@PostMapping("/project/top")
@ApiOperation(value = "项目置顶积分扣减")
public AjaxResult topProject(@RequestBody ZonePointsProjectTopInputVo inputVo) {
zonePointsAccountService.deductPointsForProjectTop(inputVo.getZoneId(), inputVo.getId(), inputVo.getName());
return success();
}
/**
* 线下活动积分冻结前台用户操作业务层已做会员身份+积分专区+幂等+积分校验
*/
@PostMapping("/offlineActivity/freeze")
@ApiOperation(value = "线下活动积分冻结")
public AjaxResult freezePointsForOfflineActivity(@RequestBody ZonePointsApplyInputVo inputVo) {
zonePointsAccountService.freezePointsForOfflineActivity(inputVo);
return success();
}
/**
* 专家答疑积分冻结前台用户操作业务层已做会员身份+积分专区+幂等+积分校验
*/
@PostMapping("/expert/qa/freeze")
@ApiOperation(value = "专家答疑积分冻结")
public AjaxResult freezePointsForExpertQa(@RequestBody ZonePointsApplyInputVo inputVo) {
zonePointsAccountService.freezePointsForExpertQa(inputVo);
return success();
}
/**
* 驳回积分申请管理员操作
* 查询对应申请记录pending状态更新状态为fail
* 同时更新pointsEvent的subject括号内容为"已退回"replyContent为驳回原因
* 并触发积分解冻操作
*/
@RequiresPermissions("zone:points:account:reject")
@Log(title = "驳回积分申请", businessType = BusinessType.UPDATE)
@PostMapping("/apply/reject")
@ApiOperation(value = "驳回积分申请")
public AjaxResult rejectPointsApply(@RequestBody ZonePointsApplyInputVo inputVo) {
zonePointsAccountService.rejectPointsApply(inputVo);
return success();
}
/**
* 通过积分申请管理员操作
* 查询对应申请记录pending状态更新状态为success
* 同时更新pointsEvent的subject去除原括号内容
* 并从冻结积分中正式扣减积分含总积分扣减
*/
@RequiresPermissions("zone:points:account:approve")
@Log(title = "通过积分申请", businessType = BusinessType.UPDATE)
@PostMapping("/apply/approve")
@ApiOperation(value = "通过积分申请")
public AjaxResult approvePointsApply(@RequestBody ZonePointsApplyInputVo inputVo) {
zonePointsAccountService.approvePointsApply(inputVo);
return success();
}
}

View File

@ -1,111 +0,0 @@
package com.microservices.zone.member.controller;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import com.microservices.zone.member.domain.vo.ZonePointsApplyDetailVo;
import com.microservices.zone.member.domain.vo.ZonePointsApplyInputVo;
import com.microservices.zone.member.domain.vo.ZonePointsApplySearchVo;
import com.microservices.zone.member.domain.vo.ZonePointsApplyUpdateVo;
import com.microservices.zone.member.service.IZonePointsApplyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 积分申请表Controller
*
* @author otto
*/
@RestController
@RequestMapping("/points/apply")
@Api(tags = "积分申请表接口")
public class ZonePointsApplyController extends BaseController {
@Autowired
private IZonePointsApplyService zonePointsApplyService;
/**
* 查询积分申请列表
*/
@RequiresPermissions("zone:points:apply:list")
@GetMapping("/list")
@ApiOperation("查询积分申请列表")
public GenericsTableDataInfo<ZonePointsApplyDetailVo> list(ZonePointsApplySearchVo searchVo) {
startPage();
return zonePointsApplyService.selectZonePointsApplyList(searchVo);
}
/**
* 查询我的积分申请列表
*/
@GetMapping("/my/list")
@ApiOperation("查询我的积分申请列表")
public GenericsTableDataInfo<ZonePointsApplyDetailVo> myList(ZonePointsApplySearchVo searchVo) {
startPage();
searchVo.setUserId(SecurityUtils.getUserId());
return zonePointsApplyService.selectZonePointsApplyList(searchVo);
}
/**
* 获取积分申请详细信息
*/
@RequiresPermissions("zone:points:apply:query")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取积分申请详细信息")
public GenericsAjaxResult<ZonePointsApply> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(zonePointsApplyService.selectZonePointsApplyById(id));
}
/**
* 新增积分申请
*/
@RequiresPermissions("zone:points:apply:add")
@Log(title = "积分申请", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增积分申请")
public AjaxResult add(@RequestBody ZonePointsApplyInputVo inputVo) {
return toAjax(zonePointsApplyService.insertZonePointsApply(inputVo));
}
/**
* 修改积分申请
*/
@RequiresPermissions("zone:points:apply:edit")
@Log(title = "积分申请", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改积分申请")
public AjaxResult edit(@RequestBody ZonePointsApplyUpdateVo updateVo) {
return toAjax(zonePointsApplyService.updateZonePointsApply(updateVo));
}
/**
* 删除积分申请
*/
@RequiresPermissions("zone:points:apply:remove")
@Log(title = "积分申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除积分申请")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(zonePointsApplyService.deleteZonePointsApplyByIds(ids));
}
/**
* 根据用户ID和专区ID查询积分申请列表
*/
@RequiresPermissions("zone:points:apply:query")
@GetMapping("/user/{userId}/zone/{zoneId}")
@ApiOperation(value = "根据用户ID和专区ID查询积分申请列表")
public GenericsAjaxResult<List<ZonePointsApply>> getByUserIdAndZoneId(@PathVariable("userId") Long userId,
@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsApplyService.selectZonePointsApplyByUserIdAndZoneId(userId, zoneId));
}
}

View File

@ -1,110 +0,0 @@
package com.microservices.zone.member.controller;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import com.microservices.zone.member.domain.vo.ZonePointsTransactionInputVo;
import com.microservices.zone.member.domain.vo.ZonePointsTransactionSearchVo;
import com.microservices.zone.member.domain.vo.ZonePointsTransactionUpdateVo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.zone.member.service.IZonePointsTransactionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 专区积分流水Controller
*
* @author otto
*/
@RestController
@RequestMapping("/points/transaction")
@Api(tags = "专区积分流水接口")
public class ZonePointsTransactionController extends BaseController {
@Autowired
private IZonePointsTransactionService zonePointsTransactionService;
/**
* 查询专区积分流水列表
*/
@RequiresPermissions("zone:points:transaction:list")
@GetMapping("/list")
@ApiOperation("查询专区积分流水列表")
public GenericsTableDataInfo<ZonePointsTransaction> list(ZonePointsTransactionSearchVo searchVo) {
startPage();
List<ZonePointsTransaction> list = zonePointsTransactionService.selectZonePointsTransactionList(searchVo.toZonePointsTransaction());
return getGenericsDataTable(list);
}
/**
* 获取专区积分流水详细信息
*/
@RequiresPermissions("zone:points:transaction:query")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取专区积分流水详细信息")
public GenericsAjaxResult<ZonePointsTransaction> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(zonePointsTransactionService.selectZonePointsTransactionById(id));
}
/**
* 根据事件ID查询流水列表
*/
@RequiresPermissions("zone:points:transaction:query")
@GetMapping("/event/{eventId}")
@ApiOperation(value = "根据事件ID查询流水列表")
public GenericsAjaxResult<List<ZonePointsTransaction>> getByEventId(@PathVariable("eventId") String eventId) {
return genericsSuccess(zonePointsTransactionService.selectZonePointsTransactionByEventId(eventId));
}
/**
* 根据账户ID查询流水列表
*/
@RequiresPermissions("zone:points:transaction:query")
@GetMapping("/account/{accountId}")
@ApiOperation(value = "根据账户ID查询流水列表")
public GenericsAjaxResult<List<ZonePointsTransaction>> getByAccountId(@PathVariable("accountId") Long accountId) {
return genericsSuccess(zonePointsTransactionService.selectZonePointsTransactionByAccountId(accountId));
}
/**
* 根据用户ID和专区ID查询流水列表
*/
@RequiresPermissions("zone:points:transaction:query")
@GetMapping("/user/{userId}/zone/{zoneId}")
@ApiOperation(value = "根据用户ID和专区ID查询流水列表")
public GenericsAjaxResult<List<ZonePointsTransaction>> getByUserIdAndZoneId(@PathVariable("userId") Long userId,
@PathVariable("zoneId") Long zoneId) {
return genericsSuccess(zonePointsTransactionService.selectZonePointsTransactionByUserIdAndZoneId(userId, zoneId));
}
/**
* 根据专区ID获取当前用户积分明细分页
*/
@GetMapping("/my/{zoneId}")
@ApiOperation(value = "根据专区ID获取当前用户积分明细分页")
public GenericsTableDataInfo<ZonePointsTransaction> getMyPointsDetailsByZone(@PathVariable("zoneId") Long zoneId,
ZonePointsTransactionSearchVo searchVo) {
startPage();
List<ZonePointsTransaction> list = zonePointsTransactionService.selectMyPointsTransactionDetailsByZone(zoneId, SecurityUtils.getUserId(), searchVo.getTransactionType());
return getGenericsDataTable(list);
}
/**
* 分页查询当前登录用户流水列表合并后所有业务字段已包含在流水中
*/
@GetMapping("/currentUser/{zoneId}")
@ApiOperation(value = "分页查询当前登录用户流水列表")
public GenericsTableDataInfo<ZonePointsTransaction> getCurrentUserTransactionList(@PathVariable("zoneId") Long zoneId) {
startPage();
List<ZonePointsTransaction> list = zonePointsTransactionService.selectCurrentUserTransactionWithEvent(SecurityUtils.getUserId(), zoneId);
return getGenericsDataTable(list);
}
}

View File

@ -5,14 +5,10 @@ import com.microservices.common.core.annotation.Excel;
import com.microservices.common.core.web.domain.BaseEntity;
import com.microservices.system.api.domain.SysDept;
import com.microservices.system.api.domain.SysUser;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import com.microservices.zone.member.domain.vo.ZoneMemberDataVo;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 特色专区会员对象 zone_member
@ -96,18 +92,6 @@ public class ZoneMember extends BaseEntity {
private SysUser sysUser;
private SysDept sysDept;
private ZoneMemberLevel zoneMemberLevel;
private ZonePointsAccount zonePointsAccount;
/**
* 积分流水合并后由 zone_points_transaction 表承载事件信息
*/
private ZonePointsTransaction pointsEvent;
/**
* 积分申请列表
*/
private List<ZonePointsApply> applyList;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;

View File

@ -21,6 +21,4 @@ public class ZoneMemberWithScore extends ZoneMember implements Serializable {
private Double searchScore;
private String memberTypeName;
private String memberLevelName;
}

View File

@ -1,68 +0,0 @@
package com.microservices.zone.member.domain.points;
import com.microservices.common.core.annotation.Excel;
import com.microservices.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 专区积分账户对象 zone_points_account
*
* @author otto
*/
@Data
public class ZonePointsAccount extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 积分账户主键
*/
private Long id;
/**
* 用户ID
*/
@Excel(name = "用户ID")
private Long userId;
/**
* 专区ID积分按专区隔离
*/
@Excel(name = "专区ID")
private Long zoneId;
/**
* 累计积分
*/
@Excel(name = "累计积分")
private Integer totalPoints;
/**
* 累计获取积分
*/
@Excel(name = "累计获取积分")
private Integer totalEarnedPoints;
/**
* 累计消费积分
*/
@Excel(name = "累计消费积分")
private Integer totalConsumedPoints;
/**
* 可用积分
*/
@Excel(name = "可用积分")
private Integer availablePoints;
/**
* 冻结积分
*/
@Excel(name = "冻结积分")
private Integer frozenPoints;
/**
* 所属组织ID
*/
@Excel(name = "所属组织ID")
private Long deptId;
}

View File

@ -1,121 +0,0 @@
package com.microservices.zone.member.domain.points;
import com.microservices.common.core.annotation.Excel;
import com.microservices.common.core.web.domain.BaseEntity;
import com.microservices.system.api.domain.SysUser;
import lombok.Data;
/**
* 积分申请表 zone_points_apply
*
* @author otto
*/
@Data
public class ZonePointsApply extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 用户ID
*/
@Excel(name = "用户ID")
private Long userId;
/**
* 专区ID
*/
@Excel(name = "专区ID")
private Long zoneId;
/**
* 组织ID
*/
@Excel(name = "组织ID")
private Long deptId;
/**
* 申请类型download下载/redeem兑换等
*/
@Excel(name = "申请类型")
private String applyType;
/**
* 事件ID关联积分流水事件
*/
@Excel(name = "事件ID")
private String eventId;
/**
* 回复/响应内容
*/
@Excel(name = "回复/响应内容")
private String reply;
/**
* 状态pending待处理/success成功/fail失败/rejected已拒绝
*/
@Excel(name = "状态")
private String status;
/**
* 申请积分数量
*/
@Excel(name = "申请积分数量")
private Integer points;
/**
* 回复人ID
*/
@Excel(name = "回复人ID")
private Long replyId;
/**
* 手机号
*/
@Excel(name = "手机号")
private String phone;
/**
* 真实姓名
*/
@Excel(name = "真实姓名")
private String realName;
/**
* 描述
*/
@Excel(name = "描述")
private String description;
/**
* 组织
*/
@Excel(name = "组织")
private String organization;
/**
* 微信号
*/
@Excel(name = "微信号")
private String wechat;
/**
* 邮箱
*/
@Excel(name = "邮箱")
private String email;
/**
* 专区成员名称
*/
private String memberName;
/**
* 系统用户信息
*/
private SysUser sysUser;
}

View File

@ -1,56 +0,0 @@
package com.microservices.zone.member.domain.points;
import com.microservices.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 专区积分文档对象 zone_points_doc
*
* @author otto
*/
@Data
public class ZonePointsDoc extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 专区ID
*/
private Long zoneId;
/**
* 文章ID
*/
private Long docId;
/**
* 初始访问次数
*/
private Integer pointsStartVisits;
/**
* 已触发积分次数
*/
private Integer pointsTriggerCount;
/**
* 创建者
*/
private Long userId;
/**
* 过期时间
*/
private Date expiryTime;
/**
* 是否积分置顶0代表不置顶 1代表置顶
*/
private Boolean isPointsTop;
}

View File

@ -1,51 +0,0 @@
package com.microservices.zone.member.domain.points;
import com.microservices.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 积分异步任务失败记录对象 zone_points_fail_log
*
* @author otto
*/
@Data
public class ZonePointsFailLog extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 任务完整JSON数据
*/
private String taskData;
/**
* 失败时间
*/
private Date failTime;
/**
* 最后失败原因
*/
private String lastError;
/**
* 处理状态
*/
private String status;
/**
* 处理时间
*/
private Date processTime;
/**
* 人工处理备注
*/
private String processRemark;
}

View File

@ -1,104 +0,0 @@
package com.microservices.zone.member.domain.points;
import com.microservices.common.core.annotation.Excel;
import com.microservices.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 专区积分流水对象 zone_points_transaction合并事件+流水
*
* @author otto
*/
@Data
public class ZonePointsTransaction extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 流水主键
*/
private Long id;
/**
* 事件ID关联同一事件的所有操作
*/
@Excel(name = "事件ID")
private String eventId;
/**
* 事件类型
*/
@Excel(name = "事件类型")
private String eventType;
/**
* 积分账户ID
*/
@Excel(name = "积分账户ID")
private Long accountId;
/**
* 类型add增/reduce减/freezed冻结/unfreezed解冻
*/
@Excel(name = "类型")
private String transactionType;
/**
* 积分数量正数
*/
@Excel(name = "积分数量")
private Integer points;
/**
* 变动后可用积分
*/
@Excel(name = "变动后可用积分")
private Integer availableAfter;
/**
* 变动后冻结积分
*/
@Excel(name = "变动后冻结积分")
private Integer frozenAfter;
/**
* 操作人ID
*/
@Excel(name = "操作人ID")
private Long operatorId;
/**
* 变动原因
*/
@Excel(name = "变动原因")
private String reason;
/**
* 回复内容
*/
@Excel(name = "回复内容")
private String replyContent;
/**
* 来源ID
*/
@Excel(name = "来源ID")
private Long sourceId;
/**
* 来源数据
*/
@Excel(name = "来源数据")
private String sourceData;
/**
* 主题
*/
@Excel(name = "主题")
private String subject;
/**
* 主题描述
*/
@Excel(name = "主题描述")
private String subjectDesc;
}

View File

@ -1,5 +1,6 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.system.api.domain.SysUser;
import com.microservices.zone.member.domain.ZoneMember;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

View File

@ -1,25 +0,0 @@
package com.microservices.zone.member.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 专区会员分类含已审核会员数量对象
*
* @author otto
*/
@Data
@ApiModel("专区会员分类(含已审核会员数量)对象")
public class ZoneMemberTypeCountVo {
@ApiModelProperty(value = "专区会员分类Id")
private Long id;
@ApiModelProperty(value = "专区会员分类名称")
private String name;
@ApiModelProperty(value = "专区会员分类简介")
private String introduction;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "已审核会员数量")
private Long memberCount;
}

View File

@ -1,52 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 积分账户输入对象
*
* @author otto
*/
@Data
@ApiModel("积分账户输入对象")
public class ZonePointsAccountInputVo {
@ApiModelProperty(value = "用户ID", required = true)
@NotNull
private Long userId;
@ApiModelProperty(value = "专区ID", required = true)
@NotNull
private Long zoneId;
@ApiModelProperty(value = "累计积分")
private Integer totalPoints;
@ApiModelProperty(value = "累计获取积分")
private Integer totalEarnedPoints;
@ApiModelProperty(value = "累计消费积分")
private Integer totalConsumedPoints;
@ApiModelProperty(value = "可用积分")
private Integer availablePoints;
@ApiModelProperty(value = "冻结积分")
private Integer frozenPoints;
public ZonePointsAccount toZonePointsAccount() {
ZonePointsAccount zonePointsAccount = new ZonePointsAccount();
zonePointsAccount.setUserId(userId);
zonePointsAccount.setZoneId(zoneId);
zonePointsAccount.setTotalPoints(totalPoints != null ? totalPoints : 0);
zonePointsAccount.setTotalEarnedPoints(totalEarnedPoints != null ? totalEarnedPoints : 0);
zonePointsAccount.setTotalConsumedPoints(totalConsumedPoints != null ? totalConsumedPoints : 0);
zonePointsAccount.setAvailablePoints(availablePoints != null ? availablePoints : 0);
zonePointsAccount.setFrozenPoints(frozenPoints != null ? frozenPoints : 0);
return zonePointsAccount;
}
}

View File

@ -1,28 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 积分账户搜索对象
*
* @author otto
*/
@Data
@ApiModel("积分账户搜索对象")
public class ZonePointsAccountSearchVo {
@ApiModelProperty(value = "用户ID")
private Long userId;
@ApiModelProperty(value = "专区ID")
private Long zoneId;
public ZonePointsAccount toZonePointsAccount() {
ZonePointsAccount zonePointsAccount = new ZonePointsAccount();
zonePointsAccount.setUserId(userId);
zonePointsAccount.setZoneId(zoneId);
return zonePointsAccount;
}
}

View File

@ -1,48 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 积分账户更新对象
*
* @author otto
*/
@Data
@ApiModel("积分账户更新对象")
public class ZonePointsAccountUpdateVo {
@ApiModelProperty(value = "积分账户ID", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "累计积分")
private int totalPoints;
@ApiModelProperty(value = "累计获取积分")
private int totalEarnedPoints;
@ApiModelProperty(value = "累计消费积分")
private int totalConsumedPoints;
@ApiModelProperty(value = "可用积分")
private int availablePoints;
@ApiModelProperty(value = "冻结积分")
private int frozenPoints;
public ZonePointsAccount toZonePointsAccount() {
ZonePointsAccount zonePointsAccount = new ZonePointsAccount();
zonePointsAccount.setId(id);
zonePointsAccount.setTotalPoints(totalPoints);
zonePointsAccount.setTotalEarnedPoints(totalEarnedPoints);
zonePointsAccount.setTotalConsumedPoints(totalConsumedPoints);
zonePointsAccount.setAvailablePoints(availablePoints);
zonePointsAccount.setFrozenPoints(frozenPoints);
return zonePointsAccount;
}
}

View File

@ -1,18 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 积分申请详情VO含系统用户信息
*
* @author otto
*/
@Data
public class ZonePointsApplyDetailVo extends ZonePointsApply {
@ApiModelProperty("GitLink账号")
private String userName;
@ApiModelProperty("GitLink个人主页地址")
private String gitLinkUserUrl;
}

View File

@ -1,81 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 积分申请输入对象
*
* @author otto
*/
@Data
@ApiModel("积分申请输入对象")
public class ZonePointsApplyInputVo {
@ApiModelProperty(value = "申请记录ID驳回操作时必填")
private Long id;
@ApiModelProperty(value = "用户ID", required = true)
@NotNull
private Long userId;
@ApiModelProperty(value = "专区ID", required = true)
@NotNull
private Long zoneId;
@ApiModelProperty(value = "组织ID", required = true)
@NotNull
private Long deptId;
@ApiModelProperty(value = "申请类型download下载/redeem兑换等", required = true)
@NotNull
private String applyType;
@ApiModelProperty(value = "事件ID关联积分流水事件")
private String eventId;
@ApiModelProperty(value = "申请积分数量")
private Integer points;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "回复/驳回内容")
private String reply;
@ApiModelProperty(value = "组织")
private String organization;
@ApiModelProperty(value = "微信号")
private String wechat;
@ApiModelProperty(value = "邮箱")
private String email;
public ZonePointsApply toZonePointsApply() {
ZonePointsApply zonePointsApply = new ZonePointsApply();
zonePointsApply.setUserId(userId);
zonePointsApply.setZoneId(zoneId);
zonePointsApply.setDeptId(deptId);
zonePointsApply.setApplyType(applyType);
zonePointsApply.setEventId(eventId);
zonePointsApply.setPoints(points);
zonePointsApply.setStatus("pending");
zonePointsApply.setPhone(phone);
zonePointsApply.setRealName(realName);
zonePointsApply.setDescription(description);
zonePointsApply.setOrganization(organization);
zonePointsApply.setWechat(wechat);
zonePointsApply.setEmail(email);
return zonePointsApply;
}
}

View File

@ -1,46 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.common.core.web.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 积分申请搜索对象
*
* @author otto
*/
@Data
@ApiModel("积分申请搜索对象")
public class ZonePointsApplySearchVo extends BaseEntity {
@ApiModelProperty(value = "用户ID")
private Long userId;
@ApiModelProperty(value = "专区ID")
private Long zoneId;
@ApiModelProperty(value = "申请类型")
private String applyType;
@ApiModelProperty(value = "事件ID")
private String eventId;
@ApiModelProperty(value = "状态")
private String status;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "成员名称")
private String memberName;
@ApiModelProperty(value = "系统用户名")
private String userName;
}

View File

@ -1,40 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 积分申请修改对象
*
* @author otto
*/
@Data
@ApiModel("积分申请修改对象")
public class ZonePointsApplyUpdateVo {
@ApiModelProperty(value = "主键ID", required = true)
private Long id;
@ApiModelProperty(value = "回复/响应内容")
private String reply;
@ApiModelProperty(value = "状态pending待处理/success成功/fail失败/rejected已拒绝")
private String status;
@ApiModelProperty(value = "事件ID关联积分流水事件")
private String eventId;
@ApiModelProperty(value = "回复人ID")
private Long replyId;
public ZonePointsApply toZonePointsApply() {
ZonePointsApply zonePointsApply = new ZonePointsApply();
zonePointsApply.setId(id);
zonePointsApply.setReply(reply);
zonePointsApply.setStatus(status);
zonePointsApply.setEventId(eventId);
zonePointsApply.setReplyId(replyId);
return zonePointsApply;
}
}

View File

@ -1,27 +0,0 @@
package com.microservices.zone.member.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 文章置顶积分扣减输入对象
*
* @author otto
*/
@Data
@ApiModel("文章置顶积分扣减请求")
public class ZonePointsArticleTopInputVo {
@ApiModelProperty(value = "组织ID", required = true)
private Long deptId;
@ApiModelProperty(value = "专区ID", required = true)
private Long zoneId;
@ApiModelProperty(value = "文章ID", required = true)
private Long id;
@ApiModelProperty(value = "文章名称", required = true)
private String name;
}

View File

@ -1,32 +0,0 @@
package com.microservices.zone.member.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 专区积分账户总览对象
*
* @author otto
*/
@Data
@ApiModel("专区积分账户总览对象")
public class ZonePointsOverviewVo {
@ApiModelProperty(value = "积分账户ID")
private Long accountId;
@ApiModelProperty(value = "专区ID")
private Long zoneId;
@ApiModelProperty(value = "累计获取积分")
private Integer totalEarnedPoints;
@ApiModelProperty(value = "累计消费积分")
private Integer totalConsumedPoints;
@ApiModelProperty(value = "当前可用积分")
private Integer availablePoints;
@ApiModelProperty(value = "冻结积分")
private Integer frozenPoints;
}

View File

@ -1,27 +0,0 @@
package com.microservices.zone.member.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 项目置顶积分扣减输入对象
*
* @author otto
*/
@Data
@ApiModel("项目置顶积分扣减请求")
public class ZonePointsProjectTopInputVo {
@ApiModelProperty(value = "组织ID", required = true)
private Long deptId;
@ApiModelProperty(value = "专区ID", required = true)
private Long zoneId;
@ApiModelProperty(value = "项目ID", required = true)
private Long id;
@ApiModelProperty(value = "项目名称", required = true)
private String name;
}

View File

@ -1,55 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 置顶文章信息返回对象
*
* @author otto
*/
@Data
@ApiModel("置顶文章信息")
public class ZonePointsTopDocVo {
@ApiModelProperty("专区积分文档记录ID")
private Long id;
@ApiModelProperty("专区ID")
private Long zoneId;
@ApiModelProperty("文章ID")
private Long docId;
@ApiModelProperty("文章名称")
private String docName;
@ApiModelProperty("文章概要")
private String summary;
@ApiModelProperty("是否积分置顶")
private Boolean isPointsTop;
@ApiModelProperty("置顶过期时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expiryTime;
@ApiModelProperty("文章头图")
private String headImg;
@ApiModelProperty("发布时间")
private String publishTime;
@ApiModelProperty("发布人")
private String publishUser;
@ApiModelProperty("浏览量")
private Long visits;
@ApiModelProperty("文章详情访问地址")
private String docDetailUrl;
}

View File

@ -1,43 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 置顶项目信息返回对象
*
* @author otto
*/
@Data
@ApiModel("置顶项目信息")
public class ZonePointsTopProjectVo {
@ApiModelProperty("项目聚合主键")
private Long id;
@ApiModelProperty("专区ID")
private Long zoneId;
@ApiModelProperty("项目名称")
private String name;
@ApiModelProperty("gitlink项目完整路径")
private String fullName;
@ApiModelProperty("gitlink项目ID")
private Long gitlinkProjectId;
@ApiModelProperty("是否积分置顶0代表不是 1代表是")
private String isPointsTop;
@ApiModelProperty("置顶过期时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expiryTime;
@ApiModelProperty("项目访问URL")
private String projectURL;
}

View File

@ -1,87 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 积分流水输入对象合并事件+流水同时兼容原 ZonePointsEventInputVo API 入参
*
* @author otto
*/
@Data
@ApiModel("积分流水输入对象")
public class ZonePointsTransactionInputVo {
@ApiModelProperty(value = "事件ID")
private String eventId;
@ApiModelProperty(value = "专区IDAPI 入参,不存入流水表)")
private Long zoneId;
@ApiModelProperty(value = "用户IDAPI 入参,不存入流水表)")
private Long userId;
@ApiModelProperty(value = "事件类型")
private String eventType;
@ApiModelProperty(value = "积分账户ID", required = true)
@NotNull
private Long accountId;
@ApiModelProperty(value = "类型add增/reduce减/freezed冻结/unfreezed解冻", required = true)
@NotNull
private String transactionType;
@ApiModelProperty(value = "积分数量(正数)", required = true)
@NotNull
private Integer points;
@ApiModelProperty(value = "变动后可用积分")
private Integer availableAfter;
@ApiModelProperty(value = "变动后冻结积分")
private Integer frozenAfter;
@ApiModelProperty(value = "操作人ID")
private Long operatorId;
@ApiModelProperty(value = "变动原因")
private String reason;
@ApiModelProperty(value = "回复内容")
private String replyContent;
@ApiModelProperty(value = "来源ID")
private Long sourceId;
@ApiModelProperty(value = "来源数据")
private String sourceData;
@ApiModelProperty(value = "主题")
private String subject;
@ApiModelProperty(value = "主题描述")
private String subjectDesc;
public ZonePointsTransaction toZonePointsTransaction() {
ZonePointsTransaction zonePointsTransaction = new ZonePointsTransaction();
zonePointsTransaction.setEventId(eventId);
zonePointsTransaction.setEventType(eventType);
zonePointsTransaction.setAccountId(accountId);
zonePointsTransaction.setTransactionType(transactionType);
zonePointsTransaction.setPoints(points);
zonePointsTransaction.setAvailableAfter(availableAfter);
zonePointsTransaction.setFrozenAfter(frozenAfter);
zonePointsTransaction.setOperatorId(operatorId);
zonePointsTransaction.setReason(reason);
zonePointsTransaction.setReplyContent(replyContent);
zonePointsTransaction.setSourceId(sourceId);
zonePointsTransaction.setSourceData(sourceData);
zonePointsTransaction.setSubject(subject);
zonePointsTransaction.setSubjectDesc(subjectDesc);
return zonePointsTransaction;
}
}

View File

@ -1,40 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 积分流水搜索对象合并事件+流水
*
* @author otto
*/
@Data
@ApiModel("积分流水搜索对象")
public class ZonePointsTransactionSearchVo {
@ApiModelProperty(value = "事件ID")
private String eventId;
@ApiModelProperty(value = "事件类型")
private String eventType;
@ApiModelProperty(value = "积分账户ID")
private Long accountId;
@ApiModelProperty(value = "类型add增/reduce减/freezed冻结/unfreezed解冻")
private String transactionType;
@ApiModelProperty(value = "来源ID")
private Long sourceId;
public ZonePointsTransaction toZonePointsTransaction() {
ZonePointsTransaction zonePointsTransaction = new ZonePointsTransaction();
zonePointsTransaction.setEventId(eventId);
zonePointsTransaction.setEventType(eventType);
zonePointsTransaction.setAccountId(accountId);
zonePointsTransaction.setTransactionType(transactionType);
zonePointsTransaction.setSourceId(sourceId);
return zonePointsTransaction;
}
}

View File

@ -1,64 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 积分流水更新对象合并事件+流水
*
* @author otto
*/
@Data
@ApiModel("积分流水更新对象")
public class ZonePointsTransactionUpdateVo {
@ApiModelProperty(value = "流水ID", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "类型add增/reduce减/freezed冻结/unfreezed解冻")
private String transactionType;
@ApiModelProperty(value = "积分数量(正数)")
private int points;
@ApiModelProperty(value = "变动后可用积分")
private int availableAfter;
@ApiModelProperty(value = "变动后冻结积分")
private int frozenAfter;
@ApiModelProperty(value = "事件类型")
private String eventType;
@ApiModelProperty(value = "变动原因")
private String reason;
@ApiModelProperty(value = "回复内容")
private String replyContent;
@ApiModelProperty(value = "主题")
private String subject;
@ApiModelProperty(value = "主题描述")
private String subjectDesc;
public ZonePointsTransaction toZonePointsTransaction() {
ZonePointsTransaction zonePointsTransaction = new ZonePointsTransaction();
zonePointsTransaction.setId(id);
zonePointsTransaction.setTransactionType(transactionType);
zonePointsTransaction.setPoints(points);
zonePointsTransaction.setAvailableAfter(availableAfter);
zonePointsTransaction.setFrozenAfter(frozenAfter);
zonePointsTransaction.setEventType(eventType);
zonePointsTransaction.setReason(reason);
zonePointsTransaction.setReplyContent(replyContent);
zonePointsTransaction.setSubject(subject);
zonePointsTransaction.setSubjectDesc(subjectDesc);
return zonePointsTransaction;
}
}

View File

@ -1,20 +0,0 @@
package com.microservices.zone.member.domain.vo;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 专区积分流水带事件信息对象合并后不再需要单独事件关联保留此类用于前端兼容
*
* @author otto
* @deprecated 合并后可直接使用 ZonePointsTransaction此类仅用于 API 兼容过渡
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("积分流水带事件信息对象")
@Deprecated
public class ZonePointsTransactionWithEventVo extends ZonePointsTransaction {
// 合并后所有业务字段已在 ZonePointsTransaction 此类仅保留兼容
}

View File

@ -2,7 +2,6 @@ package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.ZoneMember;
import com.microservices.zone.member.domain.vo.ZoneMemberSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -73,25 +72,6 @@ public interface ZoneMemberMapper {
*/
ZoneMember selectZoneMemberByZoneIdAndUserId(@Param("zoneId") Long zoneId, @Param("userId") Long userId);
/**
* 根据用户Id和专区/组织查询专区会员审核状态不为审核未通过
*
* @param zoneId 专区ID与deptId二选一
* @param userId 用户ID
* @param deptId 组织ID与zoneId二选一
* @return
*/
ZoneMember selectZoneMember(@Param("zoneId") Long zoneId, @Param("userId") Long userId, @Param("deptId") Long deptId);
/**
* 查询专区会员信息含等级和积分账户
*
* @param zoneId 专区ID
* @param userId 用户ID
* @return 专区会员信息
*/
ZoneMember selectZoneMemberInfoByZoneIdAndUserId(@Param("zoneId") Long zoneId, @Param("userId") Long userId);
Integer selectZoneMemberListCount(ZoneMemberSearchVo zoneMemberSearchVo);
int updateZoneMemberHomePageShow(@Param("id") Long id, @Param("isHomepage") String isHomepage);
@ -122,14 +102,6 @@ public interface ZoneMemberMapper {
*/
Integer selectCountByZoneId(ZoneMember zoneMember);
/**
* 按会员分类统计专区下已审核会员数量
*
* @param zoneId 专区Id
* @return 每个分类id对应的已审核会员数量
*/
List<ZoneMemberTypeCountVo> selectAuditedMemberCountByType(@Param("zoneId") Long zoneId);
/**
* 获取指定序号的会员
*
@ -199,28 +171,4 @@ public interface ZoneMemberMapper {
@Param("pageSize") int pageSize);
Long globalSearchCount(@Param("keyword") String keyword, @Param("zoneId") Long zoneId);
/**
* 全局搜索 - 扩展模糊搜索含会员分类和等级
*
* @param keyword 搜索关键词
* @param zoneId 专区ID
* @param offset 偏移量
* @param pageSize 每页数量
* @return 搜索结果列表含评分
*/
List<com.microservices.zone.member.domain.ZoneMemberWithScore> globalSearchWithScoreExtended(
@Param("keyword") String keyword,
@Param("zoneId") Long zoneId,
@Param("offset") int offset,
@Param("pageSize") int pageSize);
/**
* 全局搜索 - 扩展模糊搜索计数含会员分类和等级
*
* @param keyword 搜索关键词
* @param zoneId 专区ID
* @return 匹配总数
*/
Long globalSearchCountExtended(@Param("keyword") String keyword, @Param("zoneId") Long zoneId);
}

View File

@ -1,126 +0,0 @@
package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.points.ZonePointsAccount;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 专区积分账户Mapper接口
*
* @author otto
*/
@Mapper
public interface ZonePointsAccountMapper {
/**
* 查询专区积分账户
*
* @param id 专区积分账户主键
* @return 专区积分账户
*/
public ZonePointsAccount selectZonePointsAccountById(Long id);
/**
* 查询专区积分账户列表
*
* @param zonePointsAccount 专区积分账户
* @return 专区积分账户集合
*/
public List<ZonePointsAccount> selectZonePointsAccountList(ZonePointsAccount zonePointsAccount);
/**
* 新增专区积分账户
*
* @param zonePointsAccount 专区积分账户
* @return 结果
*/
public int insertZonePointsAccount(ZonePointsAccount zonePointsAccount);
/**
* 修改专区积分账户
*
* @param zonePointsAccount 专区积分账户
* @return 结果
*/
public int updateZonePointsAccount(ZonePointsAccount zonePointsAccount);
/**
* 删除专区积分账户
*
* @param id 专区积分账户主键
* @return 结果
*/
public int deleteZonePointsAccountById(Long id);
/**
* 批量删除专区积分账户
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteZonePointsAccountByIds(Long[] ids);
/**
* 根据用户ID和专区ID查询积分账户
*
* @param userId 用户ID
* @param zoneId 专区ID
* @return 专区积分账户
*/
ZonePointsAccount selectZonePointsAccountByUserIdAndZoneId(@Param("userId") Long userId, @Param("zoneId") Long zoneId);
/**
* 根据会员ID查询积分账户列表
*
* @param memberId 专区会员ID
* @return 专区积分账户列表
*/
List<ZonePointsAccount> selectZonePointsAccountByMemberId(@Param("memberId") Long memberId);
/**
* 锁定行获取账户信息用于并发安全更新
*
* @param id 账户ID
* @return 专区积分账户
*/
ZonePointsAccount selectZonePointsAccountByIdForUpdate(Long id);
/**
* 原子增加积分并发安全
*
* @param id 账户ID
* @param addPoints 增加的积分
* @return 影响行数
*/
int addPointsAtomic(@Param("id") Long id, @Param("addPoints") int addPoints);
/**
* 原子扣除积分并发安全
*
* @param id 账户ID
* @param deductPoints 扣除的积分
* @return 影响行数
*/
int deductPointsAtomic(@Param("id") Long id, @Param("deductPoints") int deductPoints);
int freezePointsAtomic(@Param("id") Long id, @Param("freezePoints") int freezePoints);
/**
* 原子解冻积分并发安全
*
* @param id 账户ID
* @param unfreezePoints 解冻的积分
* @return 影响行数
*/
int unfreezePointsAtomic(@Param("id") Long id, @Param("unfreezePoints") int unfreezePoints);
/**
* 原子扣减冻结积分并发安全用于申请通过时从冻结积分中正式扣除
*
* @param id 账户ID
* @param deductPoints 扣减的积分
* @return 影响行数
*/
int deductFrozenPointsAtomic(@Param("id") Long id, @Param("deductPoints") int deductPoints);
}

View File

@ -1,83 +0,0 @@
package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.points.ZonePointsApply;
import com.microservices.zone.member.domain.vo.ZonePointsApplySearchVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 积分申请表Mapper接口
*
* @author otto
*/
@Mapper
public interface ZonePointsApplyMapper {
/**
* 查询积分申请
*
* @param id 积分申请主键
* @return 积分申请
*/
public ZonePointsApply selectZonePointsApplyById(Long id);
/**
* 查询积分申请列表
*
* @param zonePointsApply 积分申请
* @return 积分申请集合
*/
public List<ZonePointsApply> selectZonePointsApplyList(ZonePointsApplySearchVo searchVo);
/**
* 新增积分申请
*
* @param zonePointsApply 积分申请
* @return 结果
*/
public int insertZonePointsApply(ZonePointsApply zonePointsApply);
/**
* 修改积分申请
*
* @param zonePointsApply 积分申请
* @return 结果
*/
public int updateZonePointsApply(ZonePointsApply zonePointsApply);
/**
* 删除积分申请
*
* @param id 积分申请主键
* @return 结果
*/
public int deleteZonePointsApplyById(Long id);
/**
* 批量删除积分申请
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteZonePointsApplyByIds(Long[] ids);
/**
* 根据用户ID和专区ID查询积分申请列表
*
* @param userId 用户ID
* @param zoneId 专区ID
* @return 积分申请列表
*/
List<ZonePointsApply> selectZonePointsApplyByUserIdAndZoneId(@Param("userId") Long userId, @Param("zoneId") Long zoneId);
/**
* 统计用户某类型待处理的申请数量幂等校验
*
* @param userId 用户ID
* @param zoneId 专区ID
* @param applyType 申请类型
* @return 待处理申请数量
*/
int countPendingByUserZoneAndType(@Param("userId") Long userId, @Param("zoneId") Long zoneId, @Param("applyType") String applyType);
}

View File

@ -1,92 +0,0 @@
package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.points.ZonePointsDoc;
import com.microservices.zone.member.domain.vo.ZonePointsTopDocVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 专区积分文档Mapper接口
*
* @author otto
*/
@Mapper
public interface ZonePointsDocMapper {
/**
* 查询专区积分文档
*
* @param id 主键ID
* @return 专区积分文档
*/
ZonePointsDoc selectZonePointsDocById(Long id);
/**
* 查询专区积分文档
*
* @param zoneId 专区ID
* @param docId 文章ID
* @return 专区积分文档
*/
ZonePointsDoc selectZonePointsDocByZoneIdAndDocId(@Param("zoneId") Long zoneId, @Param("docId") Long docId);
/**
* 新增专区积分文档
*
* @param zonePointsDoc 专区积分文档
* @return 结果
*/
int insertZonePointsDoc(ZonePointsDoc zonePointsDoc);
/**
* 修改专区积分文档
*
* @param zonePointsDoc 专区积分文档
* @return 结果
*/
int updateZonePointsDoc(ZonePointsDoc zonePointsDoc);
/**
* 增加触发次数原子操作
*
* @param id 主键ID
* @param addCount 增加的触发次数
* @return 影响行数
*/
int incrementTriggerCount(@Param("id") Long id, @Param("addCount") int addCount);
/**
* 检查用户在指定专区下是否已有置顶文章
*
* @param zoneId 专区ID
* @param userId 用户ID
* @return 置顶文章记录数
*/
int hasPointsTopByZoneIdAndUserId(@Param("zoneId") Long zoneId, @Param("userId") Long userId);
/**
* 查询用户在指定专区下的置顶文章
*
* @param zoneId 专区ID
* @param userId 用户ID
* @return 置顶文章记录
*/
ZonePointsDoc selectPointsTopByZoneIdAndUserId(@Param("zoneId") Long zoneId, @Param("userId") Long userId);
/**
* 查询专区下置顶文章列表左联 cms_doc过期时间晚于当前时间用于前台展示
*
* @param zoneId 专区ID
* @return 置顶文章列表含文章名称和概要
*/
List<ZonePointsTopDocVo> selectTopDocList(@Param("zoneId") Long zoneId);
/**
* 批量取消已过期的积分置顶is_points_top=1 expiry_time 早于当前时间
*
* @return 影响行数
*/
int updateExpiredPointsTop();
}

View File

@ -1,21 +0,0 @@
package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.points.ZonePointsFailLog;
import org.apache.ibatis.annotations.Mapper;
/**
* 积分异步任务失败记录Mapper接口
*
* @author otto
*/
@Mapper
public interface ZonePointsFailLogMapper {
/**
* 新增积分异步任务失败记录
*
* @param zonePointsFailLog 失败记录
* @return 结果
*/
int insertZonePointsFailLog(ZonePointsFailLog zonePointsFailLog);
}

View File

@ -1,137 +0,0 @@
package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.points.ZonePointsTransaction;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
* 专区积分流水Mapper接口合并事件+流水
*
* @author otto
*/
@Mapper
public interface ZonePointsTransactionMapper {
/**
* 查询专区积分流水
*
* @param id 专区积分流水主键
* @return 专区积分流水
*/
public ZonePointsTransaction selectZonePointsTransactionById(Long id);
/**
* 查询专区积分流水列表
*
* @param zonePointsTransaction 专区积分流水
* @return 专区积分流水集合
*/
public List<ZonePointsTransaction> selectZonePointsTransactionList(ZonePointsTransaction zonePointsTransaction);
/**
* 新增专区积分流水
*
* @param zonePointsTransaction 专区积分流水
* @return 结果
*/
public int insertZonePointsTransaction(ZonePointsTransaction zonePointsTransaction);
/**
* 修改专区积分流水
*
* @param zonePointsTransaction 专区积分流水
* @return 结果
*/
public int updateZonePointsTransaction(ZonePointsTransaction zonePointsTransaction);
/**
* 删除专区积分流水
*
* @param id 专区积分流水主键
* @return 结果
*/
public int deleteZonePointsTransactionById(Long id);
/**
* 批量删除专区积分流水
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteZonePointsTransactionByIds(Long[] ids);
/**
* 根据事件ID查询流水列表
*
* @param eventId 事件ID
* @return 专区积分流水列表
*/
List<ZonePointsTransaction> selectZonePointsTransactionByEventId(@Param("eventId") String eventId);
/**
* 根据账户ID查询流水列表
*
* @param accountId 积分账户ID
* @return 专区积分流水列表
*/
List<ZonePointsTransaction> selectZonePointsTransactionByAccountId(@Param("accountId") Long accountId);
/**
* 根据用户ID和专区ID查询流水列表
*
* @param userId 用户ID
* @param zoneId 专区ID
* @return 专区积分流水列表
*/
List<ZonePointsTransaction> selectZonePointsTransactionByUserIdAndZoneId(@Param("userId") Long userId, @Param("zoneId") Long zoneId);
/**
* 根据专区ID获取当前用户积分明细分页
*
* @param zoneId 专区ID
* @param userId 用户ID
* @param transactionType 交易类型可选
* @return 专区积分流水列表
*/
List<ZonePointsTransaction> selectMyPointsTransactionDetailsByZone(@Param("zoneId") Long zoneId, @Param("userId") Long userId, @Param("transactionType") String transactionType);
/**
* 查询当前用户流水列表合并后直接从流水表查询包含所有业务字段
*
* @param userId 用户ID
* @param zoneId 专区ID
* @return 专区积分流水列表
*/
List<ZonePointsTransaction> selectCurrentUserTransactionWithEvent(@Param("userId") Long userId, @Param("zoneId") Long zoneId);
/**
* 统计指定事件类型来源ID账户ID的流水记录数用于幂等校验
*/
int countByEventTypeAndSourceAndUser(@Param("eventType") String eventType,
@Param("sourceId") Long sourceId,
@Param("accountId") Long accountId);
/**
* 统计指定事件类型专区ID用户ID的流水记录数用于幂等校验JOIN account 获取 zoneId
*/
int countByEventTypeAndZoneAndUser(@Param("eventType") String eventType,
@Param("zoneId") Long zoneId,
@Param("userId") Long userId);
/**
* 根据专区ID用户ID和事件类型查询积分流水限制一条JOIN account 获取 zoneId/userId
*/
ZonePointsTransaction selectPointsTransactionOne(@Param("zoneId") Long zoneId,
@Param("userId") Long userId,
@Param("eventType") String eventType);
/**
* 统计指定账户事件类型在给定时间范围内的流水记录数用于幂等校验日期约束在 SQL 层避免脏数据干扰
*/
int countByAccountIdAndEventTypeAndDateRange(@Param("accountId") Long accountId,
@Param("eventType") String eventType,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
}

View File

@ -31,14 +31,6 @@ public interface IZoneMemberService {
*/
public GenericsTableDataInfo<ZoneMemberDetailVo> selectZoneMemberList(ZoneMemberSearchVo zoneMemberSearchVo, boolean isOpen);
/**
* 查询特色专区已审核会员列表公开接口不分页由调用方通过 PageHelper 控制
*
* @param zoneMemberSearchVo 特色专区会员查询对象zoneIdnamememberTypeIdmemberLevelId
* @return 特色专区会员集合
*/
public GenericsTableDataInfo<ZoneMemberDataVo> selectOpenZoneMemberList(ZoneMemberSearchVo zoneMemberSearchVo);
/**
* 新增特色专区会员
*
@ -105,15 +97,6 @@ public interface IZoneMemberService {
*/
int updateZoneMemberHomePageShow(Long id);
/**
* 根据专区ID修改当前登录用户会员信息
*
* @param zoneId 专区ID
* @param zoneMemberUpdateVo 会员更新信息
* @return 结果
*/
int updateZoneMemberByMember(Long zoneId, ZoneMemberUpdateVo zoneMemberUpdateVo);
/**
* 获取特色专区项目会员总览列表
*
@ -153,8 +136,6 @@ public interface IZoneMemberService {
*/
String selectZoneMemberAuditStatus(Long zoneId);
ZoneMember selectZoneMemberInfo(Long zoneId);
Integer selectZoneMemberAuditCount(ZoneMemberSearchVo zoneMemberSearchVo);
/**

View File

@ -1,7 +1,6 @@
package com.microservices.zone.member.service;
import com.microservices.zone.member.domain.ZoneMemberType;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeUpdateVo;
import java.util.List;
@ -29,15 +28,6 @@ public interface IZoneMemberTypeService {
*/
public List<ZoneMemberType> selectZoneMemberTypeList(ZoneMemberType zoneMemberType);
/**
* 查询特色专区会员分类列表含各分类下已审核会员数量
*
* @param zoneId 专区Id
* @param name 会员分类名称模糊搜索可为空
* @return 会员分类集合含已审核会员数量
*/
public List<ZoneMemberTypeCountVo> selectZoneMemberTypeListWithCount(Long zoneId, String name);
/**
* 新增特色专区会员分类
*

Some files were not shown because too many files have changed in this diff Show More