Compare commits

...

301 Commits

Author SHA1 Message Date
wanjia9506 4b1042c25d Merge pull request '区块链交易信息查询' (#909) from liuhuazhong/microservices:feat_chievements_dev into feat_chievements_dev 2025-06-06 08:39:48 +08:00
wanjia9506 e9c41768e1 Merge pull request '资源库-数据产权子系统' (#907) from liuhuazhong/microservices:feat_chievements_dev into feat_chievements_dev 2025-06-03 11:50:12 +08:00
wanjia9506 6ef1fafac8 Merge pull request '资源库-大屏展示' (#877) from liuhuazhong/microservices:feat_chievements_dev into feat_chievements_dev 2025-05-21 19:44:37 +08:00
otto 616bf1229f Merge pull request '数据管理模块-成果管理开发' (#865) from liuhuazhong/microservices:feat_chievements_dev into feat_chievements_dev 2025-04-28 11:34:33 +08:00
wanjia9506 a36e4b7256 Merge pull request '创客首页数据统计接口' (#864) from wanjia9506/microservices:dev_data_statistics into master 2025-04-18 14:33:29 +08:00
wanjia 24ecd3953c feat(数据统计):累计奖金金额过滤异常关闭任务 2025-04-10 10:51:29 +08:00
otto de54dfff7a Merge pull request '项目管理分支合并主干分支' (#862) from otto/microservices:master into master 2025-04-07 14:30:19 +08:00
wanjia e866c11d46 feat(数据统计):开源项目统计接口访问权限修改 https://pm.osredm.com/osredm/projects/27/bug/2380 2025-04-07 10:35:47 +08:00
OTTO 09d4401583 Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact_merge_master
# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/common/controller/OpenController.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/service/SoftwareFactStatisticsServiceImpl.java
2025-04-07 10:14:54 +08:00
OTTO ec3db48214 feat(项目管理总览接口开发): 合并主干分支
Signed-off-by: OTTO <731554297@qq.com>
2025-04-07 10:11:15 +08:00
OTTO 75c8d48860 Merge branch 'master' of code.gitlink.org.cn:Gitlink/microservices into product_refact
# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/common/controller/OpenController.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/constant/Constant.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/domain/ZonePmsProject.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/domain/vo/ProjectSituationVO.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/mapper/SoftwareFactStatisForgeMapper.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/mapper/SoftwareFactStatisPmsMapper.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/specialArea/service/SoftwareFactStatisticsServiceImpl.java
#	microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/SoftwareFactStatisForgeMapper.xml
#	microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/SoftwareFactStatisPmsMapper.xml
2025-04-07 09:41:19 +08:00
wanjia 3c29e65c46 feat(数据统计):创客首页数据统计接口 2025-04-01 10:16:53 +08:00
wanjia9506 97a016361d Merge pull request '添加公开上传接口' (#859) from wanjia9506/microservices:kanban_refact into product_refact 2025-03-26 11:27:41 +08:00
wanjia b2d98dabc9 fix(产品):添加公开上传接口 2025-03-26 11:29:58 +08:00
wanjia 99d58df966 fix(产品):添加原始需求公开接口 2025-03-26 10:32:13 +08:00
wanjia9506 83fd822d0e Merge pull request '添加原始需求公开接口' (#857) from wanjia9506/microservices:kanban_refact into product_refact 2025-03-26 10:28:34 +08:00
wanjia 759922b3db fix(产品):添加用户需求公开接口 2025-03-26 10:14:25 +08:00
wanjia9506 7e37ef0a36 Merge pull request '添加原始需求公开接口' (#856) from wanjia9506/microservices:kanban_refact into product_refact 2025-03-26 10:11:08 +08:00
xxq250 e40d9bf5c0 Merge remote-tracking branch 'origin/product_refact' into product_refact 2025-03-26 09:43:15 +08:00
xxq250 e791a3f02a fixed 流水线分组查询时repo_name变更 2025-03-26 09:43:07 +08:00
wanjia ceca31cb5c fix(产品):添加用户需求公开接口 2025-03-26 09:36:45 +08:00
wanjia9506 105ce14327 Merge pull request '添加用户需求公开接口' (#855) from wanjia9506/microservices:kanban_refact into product_refact 2025-03-26 09:34:10 +08:00
wanjia 6a46e8dfdf fix(组织工作台):看板里程碑按开始时间排序 2025-03-26 09:22:46 +08:00
wanjia e1f73ed177 fix(产品):添加用户需求公开接口 2025-03-26 09:22:04 +08:00
wanjia9506 1eacfa7e9e Merge pull request '看板里程碑按开始时间排序+添加用户需求公开接口' (#854) from wanjia9506/microservices:kanban_refact into product_refact 2025-03-26 09:20:26 +08:00
xxq250 67318f6d0f fixed 流水线分组查询时repo_name变更 2025-03-26 09:08:03 +08:00
wanjia f460559674 Merge remote-tracking branch 'main/product_refact' into kanban_refact 2025-03-26 08:36:25 +08:00
wanjia9506 5c67195157 Merge pull request 'fix(软件工厂): 最多缺陷个人改为最多缺陷解决个人;测试用例执行数统计错误' (#853) from xjy_software_fact_statis into master 2025-03-25 11:23:36 +08:00
wanjia9506 24b98366ab Merge pull request 'fix(软件工厂): 最多缺陷个人改为最多缺陷解决个人;测试用例执行数统计错误' (#852) from liuhuazhong/microservices:xjy_software_fact_statis into xjy_software_fact_statis 2025-03-25 10:23:48 +08:00
liuhuazhong c0a5ff23fe fix(软件工厂): 最多缺陷个人改为最多缺陷解决个人;测试用例执行数统计错误 2025-03-25 10:16:49 +08:00
OTTO 8da6005d9f feat(项目管理总览接口开发): 增加项目成员数量属性返回
Signed-off-by: OTTO <731554297@qq.com>
2025-03-21 14:29:59 +08:00
otto b5b228a3da Merge pull request '增加项目成员数量属性返回' (#851) from otto/microservices:product_refact into product_refact 2025-03-21 14:26:53 +08:00
OTTO 40b6256204 feat(项目管理总览接口开发): 完成项目管理总览接口开发
Signed-off-by: OTTO <731554297@qq.com>
2025-03-21 11:20:09 +08:00
otto 08096df571 Merge pull request 'feat(项目管理适配线上环境): 打印请求Forge响应异常日志' (#849) from otto/microservices:master into master 2025-03-20 14:12:58 +08:00
OTTO f0e01ecaf6 feat(项目管理适配线上环境): 打印请求Forge响应异常日志
Signed-off-by: OTTO <731554297@qq.com>
2025-03-20 14:10:32 +08:00
otto cf9c1b5ade Merge pull request '项目管理产品需求改版' (#848) from otto/microservices:master into master 2025-03-20 09:41:54 +08:00
OTTO 03a11ab7df Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact_deliver 2025-03-20 09:35:19 +08:00
OTTO 123d967254 feat(项目管理适配线上环境): 修复变更时无法删除附件的问题
Signed-off-by: OTTO <731554297@qq.com>
2025-03-19 11:11:19 +08:00
OTTO 729cdb8017 feat(项目管理适配线上环境): 修复基于产品需求创建项目计划报错的问题
Signed-off-by: OTTO <731554297@qq.com>
2025-03-19 10:47:28 +08:00
OTTO 689229801c feat(项目管理适配线上环境): 合并主干分支代码
Signed-off-by: OTTO <731554297@qq.com>
2025-03-18 17:07:55 +08:00
OTTO 1498f93a06 Merge branch 'master' of code.gitlink.org.cn:Gitlink/microservices into product_refact_deliver 2025-03-18 17:07:40 +08:00
OTTO 904a1b551c Merge branch 'master' of code.gitlink.org.cn:otto/microservices into product_refact_deliver
# Conflicts:
#	microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/controller/PmsCiPipelinesController.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/IPmsCiPipelinesService.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/utils/PmsGitLinkRequestUrl.java
2025-03-18 17:03:23 +08:00
OTTO 06bf1c2910 feat(项目管理适配线上环境): 项目计划逻辑调整
1. 若项目未关联产品允许新增项目计划
2. 若项目未关联产品允许编辑项目计划

Signed-off-by: OTTO <731554297@qq.com>
2025-03-18 14:12:50 +08:00
OTTO 509de16d62 feat(项目管理适配线上环境): 项目若已关联产品不允许取消或修改关联
Signed-off-by: OTTO <731554297@qq.com>
2025-03-18 10:20:26 +08:00
OTTO 2e44e2b24e fix(制品库优化): 修复产品版本标签正则表达式错误的问题
Signed-off-by: OTTO <731554297@qq.com>
2025-03-03 10:38:37 +08:00
otto d759a5d913 Merge pull request 'fix(制品库优化): 修复产品版本标签正则表达式错误的问题' (#833) from otto/microservices:product_refact into product_refact 2025-03-03 10:35:31 +08:00
OTTO e21c8b451e fix(产品模块): 模块处的需求数量统计错误
计算产品需求的配置项模块的所有需求时,通过数据库查询不包含无所属模块以及非固定模块的需求数量来统计

Signed-off-by: OTTO <731554297@qq.com>
2025-02-19 15:05:15 +08:00
otto 2a7ab04e08 Merge pull request 'fix(产品模块): 模块处的需求数量统计错误' (#830) from otto/microservices:product_refact into product_refact 2025-02-19 15:02:13 +08:00
OTTO 6d547cd0df fix(产品模块): 模块处的需求数量统计错误
计算产品需求的配置项模块的所有需求时,通过数据库查询不包含无所属模块以及非固定模块的需求数量来统计

Signed-off-by: OTTO <731554297@qq.com>
2025-02-19 09:22:20 +08:00
otto 601f87273f Merge pull request '计算产品需求的配置项模块的所有需求时,通过数据库查询不包含无所属模块以及非固定模块的需求数量来统计' (#829) from otto/microservices:product_refact into product_refact 2025-02-19 09:19:13 +08:00
OTTO 65ea36f889 fix(产品模块): 模块处的需求数量统计错误
无所属模块查询使用-1进行查询

Signed-off-by: OTTO <731554297@qq.com>
2025-02-19 08:43:18 +08:00
otto 9ed4ce2cc2 Merge pull request '无所属模块查询使用-1进行查询' (#828) from otto/microservices:product_refact into product_refact 2025-02-19 08:40:13 +08:00
OTTO 48ddc9ccdb fix(产品模块): 模块处的需求数量统计错误
无所属模块查询使用-1进行查询

Signed-off-by: OTTO <731554297@qq.com>
2025-02-18 16:57:55 +08:00
otto 2b7bbdf512 Merge pull request '无所属模块查询使用-1进行查询' (#827) from otto/microservices:product_refact into product_refact 2025-02-18 16:54:46 +08:00
OTTO 44d78caca1 fix(产品模块): 模块处的需求数量统计错误
优化配置项需求名称显示

Signed-off-by: OTTO <731554297@qq.com>
2025-02-18 16:50:33 +08:00
otto de1bb39187 Merge pull request '优化配置项需求名称显示' (#826) from otto/microservices:product_refact into product_refact 2025-02-18 16:47:24 +08:00
OTTO 8e51a872ba fix(制品库优化): 打包文件时需对Nexus下载地址进行urlEncode处理
Signed-off-by: OTTO <731554297@qq.com>
2025-02-18 15:34:30 +08:00
otto 133d821023 Merge pull request 'fix(制品库优化): 打包文件时需对Nexus下载地址进行urlEncode处理' (#825) from otto/microservices:product_refact into product_refact 2025-02-18 15:31:27 +08:00
OTTO f2238aec52 fix(产品模块): 模块处的需求数量统计错误
无所属模块查询使用-1进行查询

Signed-off-by: OTTO <731554297@qq.com>
2025-02-18 15:12:48 +08:00
otto 041ca0c542 Merge pull request '无所属模块查询使用-1进行查询' (#824) from otto/microservices:product_refact into product_refact 2025-02-18 15:09:52 +08:00
OTTO efa45f7d79 fix(产品模块): 模块处的需求数量统计错误
计算产品需求的配置项模块的所有需求时,通过数据库查询不包含无所属模块以及非固定模块的需求数量来统计

Signed-off-by: OTTO <731554297@qq.com>
2025-02-17 17:31:33 +08:00
otto ac5f3d9821 Merge pull request '计算产品需求的配置项模块的所有需求时,通过数据库查询不包含无所属模块以及非固定模块的需求数量来统计' (#823) from otto/microservices:product_refact into product_refact 2025-02-17 17:28:23 +08:00
OTTO 4058e652a0 fix(制品库优化): 产品库移入文档时若文档内容为空则设置文档的文件内容为空字符串
Signed-off-by: OTTO <731554297@qq.com>
2025-02-17 17:10:00 +08:00
otto b8e13f2b97 Merge pull request 'fix(制品库优化): 产品库移入文档时若文档内容为空则设置文档的文件内容为空字符串' (#822) from otto/microservices:product_refact into product_refact 2025-02-17 17:08:10 +08:00
OTTO a55a4985d9 fix(产品模块): 模块处的需求数量统计错误
固定模块、其他需求需要和配置项模块同级

Signed-off-by: OTTO <731554297@qq.com>
2025-02-17 16:50:10 +08:00
OTTO 03edc8ac49 fix(制品库优化): 通过产品库下载文档,中文名称乱码
通过修正请求Nexus参数的编码,修复中文乱码问题

Signed-off-by: OTTO <731554297@qq.com>
2025-02-17 10:43:54 +08:00
OTTO c50f157682 fix(制品库优化): 单独下载产品制品,实际下载结果与预期不符
修复前端传参错误导致打包失败的问题

Signed-off-by: OTTO <731554297@qq.com>
2025-02-17 09:51:05 +08:00
OTTO bda485b970 Merge branch 'product_refact' of code.gitlink.org.cn:otto/microservices into product_refact 2025-02-12 11:46:09 +08:00
OTTO bc183b6c25 Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact 2025-02-12 11:45:50 +08:00
OTTO 3dea48610d fix(制品库优化): 优化制品移入产品库逻辑
制品文件下载成功后,同时将制品文件标识更新到制品assetId相同的制品中

Signed-off-by: OTTO <731554297@qq.com>
2025-02-12 11:45:31 +08:00
OTTO e5c3e2d999 fix(制品库优化): 修复制品移入产品库逻辑
制品文件下载成功后,同时将制品文件标识更新到制品assetId相同的制品中

Signed-off-by: OTTO <731554297@qq.com>
2025-02-12 11:45:14 +08:00
otto ed33e52aaa Merge pull request 'fix(制品库优化): 优化制品移入产品库逻辑' (#820) from otto/microservices:product_refact into product_refact 2025-02-12 11:43:37 +08:00
OTTO 2d4392bfb2 fix(制品库优化): 修复制品移入产品库逻辑
当需要移入的制品文件未存在于文件服务中时,通过文件服务下载该文件,并返回文件标识,通过文件标识再将文件上传到nexus

Signed-off-by: OTTO <731554297@qq.com>
2025-02-12 11:34:21 +08:00
OTTO 294e60a961 Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact 2025-02-12 09:07:53 +08:00
OTTO 8ad3f51ce8 feat(产品需求调整): 用户需求调整为原始需求
Signed-off-by: OTTO <731554297@qq.com>
2025-02-12 09:07:14 +08:00
otto 911205db54 Merge pull request 'feat(产品需求调整): 用户需求调整为原始需求' (#819) from otto/microservices:product_refact into product_refact 2025-02-12 09:05:01 +08:00
OTTO 74112e2f35 feat(产品需求调整): 需求规格调整为需求
Signed-off-by: OTTO <731554297@qq.com>
2025-02-11 17:18:02 +08:00
otto abd7ef7e82 Merge pull request 'feat(产品需求调整): 需求规格调整为需求' (#818) from otto/microservices:product_refact into product_refact 2025-02-11 17:14:54 +08:00
OTTO 20ecc7157f fix(制品库优化): 软件包调整为制品
Signed-off-by: OTTO <731554297@qq.com>
2025-02-11 16:57:58 +08:00
otto 68fdfdcd5c Merge pull request 'fix(制品库优化): 软件包调整为制品' (#817) from otto/microservices:product_refact into product_refact 2025-02-11 16:55:19 +08:00
OTTO ba1e16337d fix(制品库优化): 修复异步打包逻辑
异步打包时未打包完成就错误的删除了redis中的键值导致打包失败

Signed-off-by: OTTO <731554297@qq.com>
2025-02-11 16:17:49 +08:00
otto 7a0ca0bef4 Merge pull request '异步打包时未打包完成就错误的删除了redis中的键值导致打包失败' (#816) from otto/microservices:product_refact into product_refact 2025-02-11 16:15:21 +08:00
OTTO d58e359798 Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact
# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java
2025-02-11 15:51:02 +08:00
OTTO f72c3684fe feat(流水线功能完善): 提供流水线id查询接口
Signed-off-by: OTTO <731554297@qq.com>
2025-02-11 15:49:58 +08:00
otto 9870f0f376 Merge pull request 'feat(流水线功能完善): 提供流水线id查询接口' (#815) from otto/microservices:product_refact into product_refact 2025-02-11 15:49:24 +08:00
OTTO 1000c7fed5 feat(制品库优化): 获取制品列表时若制品来源于流水线需展示相关信息
获取制品列表时若制品来源于流水线则设置制品的来源标签

Signed-off-by: OTTO <731554297@qq.com>
2025-02-10 15:53:19 +08:00
otto 5d05da7d03 Merge pull request 'feat(制品库优化): 获取制品列表时若制品来源于流水线需展示相关信息' (#814) from otto/microservices:product_refact into product_refact 2025-02-10 15:50:43 +08:00
OTTO c271179b43 feat(制品库优化): 获取制品列表时若制品来源于流水线需展示相关信息
raw类型制品上传时设置制品在Nexus的AssetId

Signed-off-by: OTTO <731554297@qq.com>
2025-02-10 15:15:28 +08:00
xxq250 9e898e64c8 增加流水线执行详情查询,查询 2025-01-24 08:58:45 +08:00
xxq250 ef8590c387 增加流水线执行详情查询,取值键值 2025-01-24 08:51:08 +08:00
xxq250 8c97e600a1 增加流水线执行详情查询,文件名拼接url 2025-01-24 08:25:40 +08:00
xxq250 4ae505ae40 增加流水线执行详情查询,文件名拼接 2025-01-23 17:43:02 +08:00
xxq250 9cdc4622ad 增加流水线执行详情查询,排序 2025-01-23 17:36:46 +08:00
xxq250 ef9c77e842 增加流水线执行详情查询,排序 2025-01-23 17:26:52 +08:00
OTTO 573c97f4d9 feat(产品库优化): 受控库列表的制品要识别是否为流水线生成
通过fromType和attributes设置来源为流水线的相关数据

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124516

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 17:09:50 +08:00
xxq250 79fe1c2515 Merge remote-tracking branch 'origin/product_refact' into product_refact 2025-01-23 16:59:13 +08:00
xxq250 6fc19138bb 增加流水线执行详情查询sql 2025-01-23 16:59:09 +08:00
OTTO b197668782 feat(产品库优化): 受控库列表的制品要识别是否为流水线生成
通过fromType和attributes设置来源为流水线的相关数据

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124516

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 16:51:22 +08:00
otto adba40d1b5 Merge pull request '受控库列表的制品要识别是否为流水线生成' (#813) from otto/microservices:product_refact into product_refact 2025-01-23 16:50:06 +08:00
xxq250 cc679fed0a Merge remote-tracking branch 'origin/product_refact' into product_refact 2025-01-23 16:48:46 +08:00
xxq250 782e2e7e5a 增加流水线执行详情查询 2025-01-23 16:48:40 +08:00
OTTO e3e6d37fd4 feat(产品库优化): 产品库应当区分文档与制品
修复当打包文件标识异常或打包异常时无法将文件标识置空的bug

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124517

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 16:34:25 +08:00
otto 3268dc9fb8 Merge pull request '修复当打包文件标识异常或打包异常时无法将文件标识置空的bug' (#812) from otto/microservices:product_refact into product_refact 2025-01-23 16:32:04 +08:00
OTTO b6e5742188 feat(产品库优化): 产品库应当区分文档与制品
产品库打包支持打包所有文件、打包软件包和打包文档

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124517

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 16:11:22 +08:00
otto a528956dd5 Merge pull request '产品库打包支持打包所有文件、打包软件包和打包文档' (#811) from otto/microservices:product_refact into product_refact 2025-01-23 16:08:52 +08:00
OTTO 366118bca0 feat(产品库优化): 产品库应当区分文档与制品
产品库打包接口新增node参数代表打包节点(Software:打包软件包;Document:打包文档;不传或传其他值:打包所有)

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124517

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 15:00:51 +08:00
otto f484b14bcd Merge pull request '产品库应当区分文档与制品' (#810) from otto/microservices:product_refact into product_refact 2025-01-23 14:59:45 +08:00
OTTO 8e6620ad2e feat(产品库优化): 优化产品库打包功能
1. 文件服务开始打包时创建redis key(0:代表打包未完成;1:代表打包已完成;-1:代表打包失败,需要重新打包)
2. 异步执行打包任务时,若发生任何异常则将key值设置为-1,若打包完成则将key值设为1
3. 调用获取打包文件下载接口时,检查redis key值;若键值不存在或键值为1,代表打包成功,通过远程接口获取文件信息;若键值为-1,代表打包失败,需要重新打包;若调用远程接口获取文件信息失败仍提示用户打包失败需要重新打包

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 14:28:32 +08:00
OTTO 0d63456fb9 feat(产品库优化): 产品库应当区分文档与制品
1. 普通制品和Docker制品移入产品库时默认添加前缀Software
2. 文档制品移入产品库时默认添加前缀Document

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124517

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 11:19:17 +08:00
OTTO 9a1b5e0125 feat(产品库优化): 产品库应当区分文档与制品
1. 产品库/制品库增加字段:来源类型
2. 产品库移入文档时将来源类型设置为文档

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124517

Signed-off-by: OTTO <731554297@qq.com>
2025-01-23 11:01:24 +08:00
otto 5b8524936a Merge pull request '修复产品库移入制品时若制品为中文会被urlEncode两次导致中文无法正常显示' (#809) from otto/microservices:product_refact into product_refact 2025-01-22 11:33:29 +08:00
OTTO a56a63ca78 fix(产品库优化): 修复产品库移入制品时若制品为中文会被urlEncode两次导致中文无法正常显示
修复方案:urlEncode前判断字符串是否已经被urlEncode过
1. 使用URLDecoder.decode对字符串进行解码。
2. 再使用URLEncoder.encode对解码后的字符串重新编码。
3. 如果重新编码后的字符串与原始字符串相同,则说明原始字符串是经过URL编码的

Signed-off-by: OTTO <731554297@qq.com>
2025-01-22 11:15:33 +08:00
OTTO bf5e152432 feat(产品需求重构): 产品需求(用户需求+需求规格)评审时间错误
关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124540

Signed-off-by: OTTO <731554297@qq.com>
2025-01-21 11:38:36 +08:00
otto 2b915c52a2 Merge pull request '产品需求(用户需求+需求规格)评审时间错误' (#808) from otto/microservices:product_refact into product_refact 2025-01-21 11:36:37 +08:00
wanjia9506 bdb9b6ea6d Merge pull request '产品需求、产品规格默认值' (#807) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-21 11:21:24 +08:00
wanjia a0a1ec3d3d fix(组织工作台):产品需求、产品规格默认值 2025-01-21 11:23:21 +08:00
wanjia 67dae46b22 fix(知识库):校验组织内是否存在同名知识库逻辑修复 2025-01-21 09:59:12 +08:00
wanjia9506 83f65cfd3d Merge pull request '校验组织内是否存在同名知识库逻辑修复' (#806) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-21 09:57:28 +08:00
wanjia 40bc06fc11 fix(知识库):校验组织内是否存在同名知识库逻辑修复 2025-01-21 09:56:38 +08:00
wanjia 1d99323465 fix(知识库):我收藏的知识库筛选问题 2025-01-21 09:25:34 +08:00
wanjia9506 de1832bdd8 Merge pull request '我收藏的知识库筛选问题' (#805) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-21 09:23:07 +08:00
otto 8d4c00c9a0 Merge pull request '需求规格模块中无所属模块调整为其他需求' (#804) from otto/microservices:product_refact into product_refact 2025-01-16 14:00:40 +08:00
OTTO ef476d06a8 feat(产品需求重构): 需求规格模块中无所属模块调整为其他需求
关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/demand/124520

Signed-off-by: OTTO <731554297@qq.com>
2025-01-16 14:00:24 +08:00
wanjia 730b8b30ed fix(组织工作台):我负责的产品数统计 2025-01-16 11:45:43 +08:00
wanjia9506 9cb2ca13cb Merge pull request '我负责的产品数统计' (#803) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-16 11:43:19 +08:00
OTTO 01bf425689 feat(产品需求重构): 产品需求关联项目不允许修改
Signed-off-by: OTTO <731554297@qq.com>
2025-01-16 11:22:03 +08:00
otto e488744927 Merge pull request '产品需求关联项目不允许修改' (#802) from otto/microservices:product_refact into product_refact 2025-01-16 11:19:57 +08:00
wanjia c28437cdd0 Merge remote-tracking branch 'main/product_refact' into kanban_refact 2025-01-16 10:51:32 +08:00
wanjia9506 9a43dd80fe Merge pull request '用户需求、需求规格统计完成率修正' (#801) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-16 10:49:35 +08:00
wanjia 9c89e97287 fix(组织工作台):用户需求、需求规格统计完成率修正 2025-01-16 10:48:23 +08:00
OTTO 4ea5406c48 feat(产品计划重构): 产品计划修改为产品里程碑
Signed-off-by: OTTO <731554297@qq.com>
2025-01-16 09:27:47 +08:00
otto 6235bb6fe0 Merge pull request '产品计划修改为产品里程碑' (#800) from otto/microservices:product_refact into product_refact 2025-01-16 09:26:54 +08:00
wanjia9506 85905bb92d Merge pull request '问题修复' (#797) from wanjia9506/microservices:kanban_refact into product_refact 2025-01-15 09:55:56 +08:00
wanjia 8707f0ee89 Merge remote-tracking branch 'main/product_refact' into kanban_refact 2025-01-15 09:55:05 +08:00
wanjia 182db3e872 feat(组织工作台):#124149 我的产品 需求规格统计数修正 2025-01-15 09:27:31 +08:00
wanjia a9a75dc100 feat(组织工作台):产品统计状态修正 2025-01-15 09:05:06 +08:00
otto cc455e7d9f Merge pull request '产品库的产品版本调整产品版本标识逻辑' (#796) from otto/microservices:product_refact into product_refact 2025-01-14 15:48:52 +08:00
OTTO a71d14b570 feat(制品库调整): 产品库的产品版本调整产品版本标识逻辑
版本标识生成规则调整为(产品标识-产品版本号-产品版本标签)

Signed-off-by: OTTO <731554297@qq.com>
2025-01-14 15:47:38 +08:00
otto 96dfb1d856 Merge pull request '查询产品列表时返回自定义标识' (#793) from otto/microservices:product_refact into product_refact 2025-01-08 14:36:21 +08:00
OTTO 6bb968ec5e fix(Bug修复): 修复产品标识由用户自定义后可能在不同组织下存在相同产品标识的问题
查询产品列表时返回自定义标识

Signed-off-by: OTTO <731554297@qq.com>
2025-01-08 14:39:00 +08:00
OTTO 33ffe1bfb4 fix(Bug修复): 修复产品标识由用户自定义后可能在不同组织下存在相同产品标识的问题
1. 新增字段:自定义标识,用户输入的自定义标识填充到该字段中,原产品标识还是自动生成
2. 需求规格标识根据自定义标识来生成

Signed-off-by: OTTO <731554297@qq.com>
2025-01-08 14:34:37 +08:00
otto feb40410f8 Merge pull request 'fix(Bug修复): 修复产品标识由用户自定义后可能在不同组织下存在相同产品标识的问题' (#792) from otto/microservices:product_refact into product_refact 2025-01-08 14:33:06 +08:00
OTTO 24c1bfedba fix(Bug修复): 修复项目经理无权限创建项目的bug
Signed-off-by: OTTO <731554297@qq.com>
2025-01-06 13:56:48 +08:00
otto beac1b54bb Merge pull request '修复项目经理无权限创建项目的bug' (#791) from otto/microservices:product_refact into product_refact 2025-01-06 13:54:33 +08:00
OTTO f695700777 feat(软件发展新技术课题联调): 产品库逻辑调整
产品库不限制名称是否重复

Signed-off-by: OTTO <731554297@qq.com>
2024-12-27 16:14:45 +08:00
otto 7956e028a9 Merge pull request '产品库不限制名称是否重复' (#788) from otto/microservices:product_refact into product_refact 2024-12-27 16:14:38 +08:00
OTTO 0d27d82964 feat(软件发展新技术课题联调): 产品库逻辑调整
产品版本列表返回关联产品详情

Signed-off-by: OTTO <731554297@qq.com>
2024-12-25 15:50:07 +08:00
otto e85f79e67e Merge pull request '产品版本列表返回关联产品详情' (#787) from otto/microservices:product_refact into product_refact 2024-12-25 15:48:02 +08:00
OTTO 5a20b86f8b feat(软件发展新技术课题联调): 产品库逻辑调整
产品版本列表返回关联产品详情

Signed-off-by: OTTO <731554297@qq.com>
2024-12-25 13:47:27 +08:00
otto bd8e09598f Merge pull request '产品库逻辑调整' (#786) from otto/microservices:product_refact into product_refact 2024-12-25 13:45:13 +08:00
OTTO a53437d060 feat(软件发展新技术课题联调): 产品库逻辑调整
产品版本(原产品库)新增产品版本号和关联产品标识字段

Signed-off-by: OTTO <731554297@qq.com>
2024-12-25 11:33:36 +08:00
otto 74d2fd9979 Merge pull request '更新需求时不需要检查需求优先级' (#785) from otto/microservices:product_refact into product_refact 2024-12-20 14:07:22 +08:00
OTTO ec209cb0e0 feat(项目管理产品需求重构): 完善产品需求规格逻辑
更新需求时不需要检查需求优先级

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 14:04:31 +08:00
OTTO 9a4e79098c feat(项目管理产品需求重构): 完善产品需求规格逻辑
全部模块和无所属模块需求数量统计错误

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 11:53:01 +08:00
otto 0076b07114 Merge pull request '全部模块和无所属模块需求数量统计错误' (#784) from otto/microservices:product_refact into product_refact 2024-12-20 11:51:06 +08:00
OTTO 25ce8e1e7c feat(项目管理产品需求重构): 完善产品需求规格逻辑
统计计划下需规数据时需根据需规状态统计

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 10:58:10 +08:00
otto 0d3539a669 Merge pull request '统计模块下需规数据时需根据需规状态统计' (#783) from otto/microservices:product_refact into product_refact 2024-12-20 10:55:47 +08:00
OTTO fa69d53648 feat(项目管理产品需求重构): 完善产品需求规格逻辑
统计模块下需规数据时需根据需规状态统计

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 10:54:51 +08:00
OTTO 0265c2bd08 feat(项目管理产品需求重构): 完善产品需求规格逻辑
修复测试单获取模块树报错的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 09:36:29 +08:00
otto d491612296 Merge pull request '修复测试单获取模块树报错的问题' (#782) from otto/microservices:product_refact into product_refact 2024-12-20 09:34:18 +08:00
OTTO e2c802ceef feat(项目管理产品需求重构): 完善产品需求规格逻辑
产品需求固定模块排序到最后面

Signed-off-by: OTTO <731554297@qq.com>
2024-12-20 08:47:46 +08:00
otto 3371917732 Merge pull request '产品需求固定模块排序到最后面' (#781) from otto/microservices:product_refact into product_refact 2024-12-20 08:45:40 +08:00
OTTO a59591b5a5 feat(项目管理产品需求重构): 完善产品需求规格逻辑
已完成、已拒绝的需求规格仍然可以移入产品里程碑

Signed-off-by: OTTO <731554297@qq.com>
2024-12-18 16:00:39 +08:00
otto 08a6720443 Merge pull request '已完成、已拒绝的需求规格仍然可以移入产品里程碑' (#780) from otto/microservices:product_refact into product_refact 2024-12-18 16:00:32 +08:00
otto 1c3806ebf8 Merge pull request '产品固定模块开发' (#779) from otto/microservices:product_refact into product_refact 2024-12-18 15:23:49 +08:00
OTTO 3bd42cd20e feat(项目管理产品需求重构): 完善产品需求规格逻辑
新建产品时初始化固定模块

Signed-off-by: OTTO <731554297@qq.com>
2024-12-18 14:04:43 +08:00
OTTO 5ae947073b feat(项目管理产品需求重构): 完善产品需求规格逻辑
固定模块不允许编辑不允许删除

Signed-off-by: OTTO <731554297@qq.com>
2024-12-18 14:00:50 +08:00
OTTO 76f8f05147 feat(项目管理产品需求重构): 完善产品需求规格逻辑
查询模块树时设置固定模块值

Signed-off-by: OTTO <731554297@qq.com>
2024-12-18 11:54:44 +08:00
OTTO f3ce62e437 feat(项目管理产品需求重构): 完善产品需求规格逻辑
产品需求模块增加固定模块

Signed-off-by: OTTO <731554297@qq.com>
2024-12-18 11:21:33 +08:00
xxq250 f25cefe93f 增加流水线执行测试报告结果查询Get 2024-12-18 11:03:31 +08:00
xxq250 7a124aa4d0 增加流水线执行测试报告结果查询Get 2024-12-18 10:59:14 +08:00
OTTO 248aa2cb6c fix(项目管理产品需求重构): 完善产品需求规格逻辑
历史数据中未关联产品需求规格的计划不报错

Signed-off-by: OTTO <731554297@qq.com>
2024-12-17 17:18:40 +08:00
otto c4748ba4c1 Merge pull request '完善产品需求规格逻辑' (#778) from otto/microservices:product_refact into product_refact 2024-12-17 17:16:33 +08:00
OTTO 0f85f633d8 fix(项目管理产品需求重构): 完善产品需求规格逻辑
需求规格支持批量更新模块和计划

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124131

Signed-off-by: OTTO <731554297@qq.com>
2024-12-17 16:13:41 +08:00
otto 87debbe223 Merge pull request '完善产品需求规格逻辑' (#777) from otto/microservices:product_refact into product_refact 2024-12-17 16:12:04 +08:00
OTTO 87c17a2c7d fix(项目管理产品需求重构): 完善产品需求规格逻辑
当附件标识字段为Null时代表附件未更新

关联Issue:
https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124100

Signed-off-by: OTTO <731554297@qq.com>
2024-12-17 16:05:49 +08:00
OTTO feba3b82ed fix(项目管理产品需求重构): 完善产品里程碑逻辑
支持根据创建人搜索需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-12-17 09:02:55 +08:00
otto 18b5545d88 Merge pull request '支持根据创建人搜索需求规格' (#775) from otto/microservices:product_refact into product_refact 2024-12-17 09:01:07 +08:00
OTTO 9e236c206d fix(项目管理产品需求重构): 完善产品需求规格逻辑
需求规格变更时需校验附件置空的情况

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 17:18:25 +08:00
wanjia 15e656fb4d feat(项目文档):权限重构 2024-12-16 15:12:57 +08:00
otto 4b357605e5 Merge pull request '完善产品里程碑逻辑' (#771) from otto/microservices:product_refact into product_refact 2024-12-16 11:18:50 +08:00
OTTO dbd21d9aa8 fix(项目管理产品需求重构): 完善产品里程碑逻辑
修复删除里程碑报错的问题

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124039

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 11:16:13 +08:00
OTTO db27fac652 fix(项目管理产品需求重构): 完善需求规格逻辑
变更时内容未调整提示优化

关联Issue:https://pm.gitlink.org、
.cn/Gitlink/projects/228/bug/124100

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 10:50:38 +08:00
OTTO f4bbc53d65 fix(项目管理产品需求重构): 完善需求规格逻辑
查询需求规格详情时需查询项目计划,不校验用户的数据权限

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 09:30:06 +08:00
otto f71e7450dd Merge pull request '完善需求规格逻辑' (#770) from otto/microservices:product_refact into product_refact 2024-12-16 09:28:23 +08:00
OTTO 55c0d58722 feat(项目管理产品需求重构): 完善产品里程碑
查询需求规格列表时返回关联的产品计划

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 08:51:07 +08:00
OTTO 0fbd7abc10 feat(项目管理产品需求重构): 完善产品里程碑
查询需求规格列表时返回关联的产品计划

Signed-off-by: OTTO <731554297@qq.com>
2024-12-16 08:49:14 +08:00
otto 11c43c7510 Merge pull request '完善产品里程碑' (#769) from otto/microservices:product_refact into product_refact 2024-12-16 08:49:13 +08:00
OTTO e063d79c50 fix(项目管理产品需求重构): 完善产品里程碑
修复产品里程碑下获取到错误的需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-12-14 17:19:25 +08:00
OTTO 56fc58cf3b style(项目管理产品需求重构): 完善产品里程碑
优化接口命名

Signed-off-by: OTTO <731554297@qq.com>
2024-12-14 16:29:57 +08:00
OTTO 0e71af317b feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规列表返回创建人

Signed-off-by: OTTO <731554297@qq.com>
2024-12-13 15:17:57 +08:00
otto c19bc29443 Merge pull request '完善产品中的需求规格功能开发' (#767) from otto/microservices:product_refact into product_refact 2024-12-13 15:16:38 +08:00
OTTO 3e97db926c feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
关联里程碑和关联模块前端限制为必须传值

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124019

Signed-off-by: OTTO <731554297@qq.com>
2024-12-13 09:28:45 +08:00
otto 07dcaec093 Merge pull request '关联里程碑和关联模块前端限制为必须传值' (#766) from otto/microservices:product_refact into product_refact 2024-12-13 09:26:32 +08:00
otto 6bffcc147f Merge pull request '完善产品中的需求规格功能开发' (#765) from otto/microservices:product_refact into product_refact 2024-12-13 09:25:26 +08:00
OTTO 7edccfc637 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
关联里程碑和关联模块前端限制为必须传值

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124019

Signed-off-by: OTTO <731554297@qq.com>
2024-12-13 09:15:03 +08:00
wanjia9506 c68a4c4459 Merge pull request '公告返回操作者头像' (#764) from wanjia9506/microservices:kanban_refact into product_refact 2024-12-12 15:38:43 +08:00
wanjia e6efd421d4 Merge remote-tracking branch 'main/product_refact' into kanban_refact 2024-12-12 15:40:35 +08:00
wanjia 33f0d37136 feat(项目概览):公告返回操作者头像 2024-12-12 15:39:54 +08:00
otto fee590430e Merge pull request '查看需规详情时通过非鉴权接口获取关联项目信息' (#763) from otto/microservices:product_refact into product_refact 2024-12-12 14:45:12 +08:00
OTTO 92f0b0bd5a feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
纳入计划时使用了错误的项目id

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 14:26:24 +08:00
OTTO 6456fa4976 Merge branch 'product_refact' of code.gitlink.org.cn:Gitlink/microservices into product_refact
# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/project/service/IPmsProjectService.java
2024-12-12 11:42:00 +08:00
OTTO 156a32c6ac feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
查看需规详情时通过非鉴权接口获取关联项目信息

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 11:41:12 +08:00
OTTO 81234a1d23 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复查看需规关联计划数据没有权限

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 11:13:20 +08:00
otto e7a3f47115 Merge pull request '完善产品中的需求规格功能开发' (#762) from otto/microservices:product_refact into product_refact 2024-12-12 11:11:46 +08:00
OTTO 16c14e9c44 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复:更新需求规格时,无法正确更新模块

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/124019

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 10:25:52 +08:00
otto ec27bfb786 Merge pull request 'bug修复' (#761) from otto/microservices:product_refact into product_refact 2024-12-12 10:24:51 +08:00
otto 9b75b09f1a Merge pull request '完善产品中的需求规格功能开发' (#760) from otto/microservices:product_refact into product_refact 2024-12-12 10:12:54 +08:00
wanjia9506 f7c68e3c14 Merge pull request 'feat(工作台统计): 我的产品、我的产品数据统计' (#759) from liuhuazhong/microservices:product_refact_stat into product_refact 2024-12-12 09:58:24 +08:00
liuhuazhong ffbe18645c Merge remote-tracking branch 'upstream/product_refact' into product_refact_stat
# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/dashboard/controller/PmsDashboardController.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/product/mapper/PmsProductRequirementMapper.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/product/service/IPmsProductRequirementService.java
2024-12-12 09:57:32 +08:00
OTTO e2a592a799 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规和用户需求标题长度最大调整为200

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 09:43:50 +08:00
OTTO f93f802671 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需求规格纳入计划可选的项目 必须是关联了该产品的项目

关联Issue:https://pm.gitlink.org.cn/Gitlink/projects/228/bug/123983

Signed-off-by: OTTO <731554297@qq.com>
2024-12-12 09:10:58 +08:00
otto acfda75cf3 Merge pull request '完善产品中的需求规格功能开发' (#758) from otto/microservices:product_refact into product_refact 2024-12-12 09:09:28 +08:00
liuhuazhong ffc71ba7b6 feat(工作台统计): 我的产品、我的产品数据统计 2024-12-11 16:37:02 +08:00
wanjia dd05fb00cf feat(项目概览):迭代关联测试单数修正 2024-12-11 16:22:20 +08:00
wanjia9506 fbb84122ab Merge pull request '迭代关联测试单数修正' (#757) from wanjia9506/microservices:kanban_refact into product_refact 2024-12-11 16:20:27 +08:00
wanjia ee9fbf2328 feat(项目概览):项目总览-开启中的迭代数和近一周新增数 2024-12-11 16:10:44 +08:00
wanjia9506 d9fb54e364 Merge pull request '项目总览-开启中的迭代数和近一周新增数' (#756) from wanjia9506/microservices:kanban_refact into product_refact 2024-12-11 16:08:47 +08:00
OTTO cd68826944 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规变更评审通过时应取消项目计划不允许修改的限制条件

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 16:04:42 +08:00
otto f8b066ac54 Merge pull request '需规变更评审通过时应取消项目计划不允许修改的限制条件' (#755) from otto/microservices:product_refact into product_refact 2024-12-11 16:02:52 +08:00
wanjia 614651327d Merge remote-tracking branch 'main/product_refact' into kanban_refact 2024-12-11 15:50:16 +08:00
wanjia9506 2dcb7146ed Merge pull request '项目概览、组织工作台改版' (#754) from wanjia9506/microservices:kanban_refact into product_refact 2024-12-11 15:50:02 +08:00
wanjia 421b0f7e40 feat(项目概览):动态 2024-12-11 15:44:45 +08:00
OTTO 87de8b7f90 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
查询用户需求和需规评审人以及评审时间时应查询最新一条已通过评审的记录

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 15:37:28 +08:00
otto 4b5e075d52 Merge pull request '完善产品中的需求规格功能开发' (#753) from otto/microservices:product_refact into product_refact 2024-12-11 15:35:41 +08:00
OTTO 3f9fd173c6 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
用户和需规评审时将评审时间记录到操作内容中(Content),防止用户填写了一个过早的时间导致操作记录列表混乱

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 15:31:19 +08:00
OTTO fe8ce59629 fix(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规操作记录应该根据创建时间排序

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 15:22:38 +08:00
OTTO 7efd45c462 fix(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复需规拒绝变更时操作记录异常的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 15:20:05 +08:00
otto 3e8a2d4c8b Merge pull request '完善需规对应的项目计划逻辑' (#752) from otto/microservices:product_refact into product_refact 2024-12-11 14:46:59 +08:00
OTTO be55a0d4e5 feat(项目管理产品需求重构): 完善需规对应的项目计划逻辑
优化Forge异常时错误提示

Signed-off-by: OTTO <731554297@qq.com>
2024-12-11 14:45:35 +08:00
wanjia 8ae43e5dc2 feat(组织工作台):我的项目、我的仓库、我的待办 2024-12-11 14:45:11 +08:00
wanjia 413c11d98c feat(组织工作台):我的工作项 2024-12-11 10:07:00 +08:00
OTTO 464ce4e286 feat(项目管理产品需求重构): 完善需规对应的项目计划逻辑
1. 项目计划仅能基于产品需求规格创建
2. 项目计划不允许编辑标题、正文和附件
3. 项目计划状态值仅能为进行中、已完成、已关闭
4. 如果状态发生变更,需同步产品需规的状态变更:
- 项目计划修改为进行中将需规调整为已计划
- 项目计划修改为已完成或已关闭将需规调整为已完成
- 限制需求规格变更中,项目计划不能调整为已完成或已关闭状态

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 17:26:30 +08:00
OTTO 4cca1bf205 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规纳入计划时计划状态需设置为进行中

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 15:18:11 +08:00
OTTO 63c5fc1b7f fix(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复待评审的需规查询不到变更记录的bug

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 14:36:53 +08:00
OTTO c7cc7a9111 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复附件无法下载的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 14:22:28 +08:00
OTTO d596005853 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
测试用例新增拷贝接口

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 11:41:31 +08:00
otto 6d92f87851 Merge pull request '测试用例新增拷贝接口' (#751) from otto/microservices:product_refact into product_refact 2024-12-10 11:39:22 +08:00
otto 298a74075a Merge pull request '完善产品中的需求规格功能开发' (#750) from otto/microservices:product_refact into product_refact 2024-12-10 11:34:18 +08:00
OTTO 22c5efd140 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
获取需规列表时支持通过多状态查询

Signed-off-by: OTTO <731554297@qq.com>
2024-12-10 11:05:24 +08:00
wanjia 168f60234d feat(项目概览):开启中的迭代数、近一周新增迭代数 2024-12-09 17:32:38 +08:00
wanjia 0417d51f25 feat(项目概览):迭代列表返回关联测试单数 2024-12-09 16:57:17 +08:00
OTTO b0f325370f feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
根据需规类型搜索需规

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 15:53:49 +08:00
otto d836f0f95d Merge pull request '完善产品中的需求规格功能开发' (#749) from otto/microservices:product_refact into product_refact 2024-12-09 15:52:35 +08:00
OTTO 59cb39ee83 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修复需规评审相关信息不存在导致报错的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 15:51:29 +08:00
OTTO dbceb01ce0 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需求操作记录使用中文逗号

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 15:39:15 +08:00
OTTO c67da2401c feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
限制评审人和评审意见长度

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 14:59:22 +08:00
OTTO 96c5a2b687 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
生成需规标识时去掉标题中特殊字符

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 14:58:20 +08:00
otto 0eb2ab2786 Merge pull request '项目管理产品需求重构' (#748) from otto/microservices:product_refact into product_refact 2024-12-09 14:57:24 +08:00
OTTO e1b377ceef feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需求规格标识不允许重复,存在重复的在最后面添加数字

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 14:49:25 +08:00
OTTO 95ad6b83b4 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
产品标识不允许重复

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 14:25:14 +08:00
OTTO 42b5dd4530 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需求规格详情返回评审相关信息

Signed-off-by: OTTO <731554297@qq.com>
2024-12-09 14:13:33 +08:00
OTTO c7c3f53f91 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
已拒绝的需求规格允许用户删除

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 15:14:29 +08:00
otto 83e86c89ad Merge pull request '完善产品中的需求规格功能开发' (#746) from otto/microservices:product_refact into product_refact 2024-12-06 15:12:44 +08:00
OTTO 290b42333f feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修正需求规格纳入计划时修改了错误的状态

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 15:11:20 +08:00
OTTO 0af814be0d feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
新增查询需求规格关联的计划接口

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 15:10:03 +08:00
OTTO 5bc5185882 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
修正评审状态判断错误的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 14:23:09 +08:00
otto 8398ec6966 Merge pull request '完善产品中的需求规格功能开发' (#745) from otto/microservices:product_refact into product_refact 2024-12-06 14:21:43 +08:00
OTTO a46d7e65cf feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
变更中的需求规格返回变更人和变更时间

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 14:19:17 +08:00
OTTO 44069a7c55 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
新增需求规格关联测试用例及其执行结果查询

Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 11:13:35 +08:00
otto 643a0fdb47 Merge pull request '新增需求规格关联测试用例及其执行结果查询' (#744) from otto/microservices:product_refact into product_refact 2024-12-06 11:12:03 +08:00
OTTO f3f051dc5b feat(项目管理产品需求重构): 测试用例支持关联产品需求规格
Signed-off-by: OTTO <731554297@qq.com>
2024-12-06 10:26:32 +08:00
OTTO 2c2870b71b feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
支持通过评审时间排序

Signed-off-by: OTTO <731554297@qq.com>
2024-12-05 15:59:00 +08:00
otto 454f992a98 Merge pull request '支持通过评审时间排序' (#743) from otto/microservices:product_refact into product_refact 2024-12-05 15:57:06 +08:00
otto 9564179914 Merge pull request '修复获取用户详情时评审记录可能为Null的情况' (#742) from otto/microservices:product_refact into product_refact 2024-12-05 14:34:04 +08:00
OTTO 7026580e8b feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
修复获取用户详情时评审记录可能为Null的情况

Signed-off-by: OTTO <731554297@qq.com>
2024-12-05 14:31:22 +08:00
OTTO 306a7c2558 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增查询需求规格类型列表接口

Signed-off-by: OTTO <731554297@qq.com>
2024-12-04 17:28:23 +08:00
otto 85d4a23ef6 Merge pull request '新增查询需求规格类型列表接口' (#741) from otto/microservices:product_refact into product_refact 2024-12-04 17:26:19 +08:00
otto 57daea3681 Merge pull request '新增用户需求和需求规格状态获取接口' (#740) from otto/microservices:product_refact into product_refact 2024-12-04 16:05:27 +08:00
OTTO e2dfb6a5d7 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增用户需求和需求规格状态获取接口

Signed-off-by: OTTO <731554297@qq.com>
2024-12-04 16:03:48 +08:00
OTTO 33a7f4c069 Merge branch 'master' of code.gitlink.org.cn:Gitlink/microservices into product_refact 2024-12-04 13:56:22 +08:00
otto dc7dfaf463 Merge pull request '项目管理产品需求重构' (#739) from otto/microservices:product_refact into product_refact 2024-12-04 13:54:34 +08:00
OTTO 4c7ffcc5d6 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
完善需求评审接口:
评审通过时若原需求为计划中需同步更新计划详情

Signed-off-by: OTTO <731554297@qq.com>
2024-12-04 13:48:26 +08:00
OTTO f3b2b8cc01 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
完善需求跟踪相关接口:
1. 查询用户需求变更记录
   - 根据用户需求id查询用户需求变更记录列表
   - 根据产品需求操作类型生成记录描述
2. 查询需求规格变更记录:
   - 根据需求规格id和fromId查询需求规格相关的所有需求规格相关的变更记录列表
   - 根据产品需求操作类型生成记录描述

Signed-off-by: OTTO <731554297@qq.com>
2024-12-04 09:34:10 +08:00
OTTO 3d59e04e09 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
查询用户需求详情时返回评审相关信息

Signed-off-by: OTTO <731554297@qq.com>
2024-12-03 15:07:00 +08:00
OTTO bccc9b8e12 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
1. 增加用户需求和操作记录的关联查询操作,查询需求最新的评审情况
2. 查询用户需求列表时返回评审人、评审时间和评审意见
3. 修正部分评审记录异常的问题

Signed-off-by: OTTO <731554297@qq.com>
2024-12-03 14:44:04 +08:00
OTTO 05a7dab7bd feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
删除无效废弃方法

Signed-off-by: OTTO <731554297@qq.com>
2024-12-03 11:09:22 +08:00
OTTO f12fac99e7 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需求规格纳入计划接口开发:
1. 限制仅已评审状态的需求规格才能纳入计划
2. 将需求规格文件上传至forge
3. 在对应项目中创建计划
4. 更新需规状态,记录计划id
5. 记录需规纳入计划操作

Signed-off-by: OTTO <731554297@qq.com>
2024-12-03 11:02:34 +08:00
OTTO f50d4ef1a8 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
需规修改接口拆分为修改接口和变更接口:
1. 限制已评审或计划中的需求规格请通过需求变更调整需求内容(标题、正文、附件)
2. 限制变更需求规格时,变更内容不能为空
3. 已评审或已计划的需规需要进行变更:调整原需规状态、创建变更后的需规、更新需求唯一标识、原需求评论需迁移至变更后的需求、记录变更评审记录

Signed-off-by: OTTO <731554297@qq.com>
2024-12-02 15:17:37 +08:00
OTTO 1e222677d2 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格评审接口:
1. 限制只有待审核和变更中状态的需求规格才能进行审核
2. 变更中的需求规格通过评审后设置状态为原需规状态
3. 变更中的需规通过审核时需将原需求状态调整为已变更
4. 变更中的需求规格拒绝评审后设置状态为已拒绝变更状态
5. 变更中的需规通过审核时需将原需求状态调整为来源状态
6. 需求评论对象还原为原需求id
7. 原需规记录评审意见
8. 记录评审意见并更新需规

Signed-off-by: OTTO <731554297@qq.com>
2024-12-02 14:00:24 +08:00
OTTO ab971d7278 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格删除接口:
1. 限制只有待审核和变更中状态的需求规格才能被删除
2. 变更中需求规格被删除时需将原需求还原状态
3. 需求评论对象还原为原需求id
4. 记录取消变更
5. 删除需求规格时,删除需求规格与需求评论的关联关系
6. 更新产品更新时间
7. 删除需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-12-02 09:52:22 +08:00
OTTO a4662b16f6 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格修改接口:原需求评论需迁移至变更后的需求

Signed-off-by: OTTO <731554297@qq.com>
2024-12-02 09:46:06 +08:00
OTTO 553d4a1887 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善用户需求评审接口:用户需求评审通过时创建一条对应的需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 17:03:39 +08:00
OTTO a2b1e49610 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格修改接口

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 16:09:31 +08:00
OTTO 3b9ba3e395 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
产品标识调整为用户手动输入

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 15:30:16 +08:00
OTTO e2e603267f feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
生成需求规格唯一标识

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 15:28:38 +08:00
OTTO 4d0c043197 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格更新接口:修改需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 14:47:11 +08:00
OTTO 882dd33346 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
完善需求规格新增接口:校验需求规格类型是否输入正确

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 10:38:04 +08:00
OTTO 895be1aefe feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
新增接口:新增需求规格

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 10:13:46 +08:00
OTTO be54bc56d8 feat(项目管理产品需求重构): 完善产品中的需求规格功能开发
1. 新增接口:查询需求规格列表
2. 新增接口:获取需求规格详细信息

Signed-off-by: OTTO <731554297@qq.com>
2024-11-30 09:19:40 +08:00
OTTO 8f69ef0d20 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
对用户需求的创建和编辑操作进行记录

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 16:30:39 +08:00
OTTO 85388b896e feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:评审用户需求

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 16:11:24 +08:00
OTTO 56a4621aff feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增产品需求操作记录对象相关代码

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 14:40:21 +08:00
OTTO 99cd28b6b6 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增产品需求操作记录对象相关代码

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 14:40:04 +08:00
OTTO 52e4c771fa feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:删除用户需求

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 13:38:06 +08:00
OTTO 804309d5d7 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:修改用户需求

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 11:47:25 +08:00
OTTO b764f24b8e feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:新增用户需求

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 11:19:42 +08:00
OTTO da27fed59d feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:获取用户需求详细信息

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 10:20:00 +08:00
OTTO 6347cb1680 feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
新增接口:获取用户需求详细信息

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 10:17:15 +08:00
OTTO b987518add feat(项目管理产品需求重构): 完善产品中的用户需求功能开发
1. 新增接口:查询用户需求列表
2. 新增产品需求状态枚举类(支持用户需求和需求规格)
3. 产品需求新增字段:需求来源用户、需求来源单位

Signed-off-by: OTTO <731554297@qq.com>
2024-11-29 09:59:34 +08:00
OTTO 60cf5b9cba feat(项目管理产品需求重构): 调整产品需求数据库字段
Signed-off-by: OTTO <731554297@qq.com>
2024-11-28 09:35:31 +08:00
187 changed files with 6038 additions and 1153 deletions

View File

@ -107,4 +107,24 @@ public interface RemoteFileService {
@RequestParam("type") String type,
@RequestParam("hierarchy") String hierarchy,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过Url下载文件到本地
*/
@PostMapping(value = "/common/downloadFileByUrl")
R<String> downloadFileByUrl(
@RequestParam("fileUrl") String fileUrl
, @RequestParam("type") String type
, @RequestParam("hierarchy") String hierarchy,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 上传本地文件到Forge
*
* @param fileIdentifiers 文件标识列表逗号分隔
* @return Forge文件标识列表
*/
@PostMapping(value = "/common/uploadFileToForge/{fileIdentifiers}")
R<List<String>> uploadFileToForge(@PathVariable("fileIdentifiers") String fileIdentifiers,
@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@ -70,6 +70,16 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
public R<String> packagedFile(HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy, String source) {
return R.fail("打包文件失败:" + throwable.getMessage());
}
@Override
public R<String> downloadFileByUrl(String fileUrl, String type, String hierarchy, String source) {
return R.fail("通过Url下载文件到本地失败:" + throwable.getMessage());
}
@Override
public R<List<String>> uploadFileToForge(String fileIdentifiers, String source) {
return R.fail("上传本地文件到Forge失败:" + throwable.getMessage());
}
};
}
}

View File

@ -202,7 +202,7 @@ public class CacheConstants {
/**
* Gitlink组织开通企业是否完成 Key前缀
*/
public final static String GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY = "gitlink_org_id_open_enterprise_key:";
private final static String GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY = "gitlink_org_id_open_enterprise_key:";
public static String getGitlinkOrgIdOpenEnterpriseKey(Long gitlinkOrgId) {
return GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY + gitlinkOrgId;
@ -227,11 +227,11 @@ public class CacheConstants {
/**
* 专区项目Gitlink信息 Key前缀
*/
public final static String ZONE_PROJECT_GITLINK_INFO = "zone_project_gitlink_info:";
private final static String ZONE_PROJECT_GITLINK_INFO = "zone_project_gitlink_info:";
/**
* 专区下项目分数排序 Key前缀
*/
public final static String ZONE_PROJECT_SORT_BY_SCORE = "zone_project_sort_by_score:";
private final static String ZONE_PROJECT_SORT_BY_SCORE = "zone_project_sort_by_score:";
public static String getZoneProjectGitlinkInfo(Long gitlinkProjectId) {
return ZONE_PROJECT_GITLINK_INFO + gitlinkProjectId;
@ -245,6 +245,15 @@ public class CacheConstants {
return ZONE_PROJECT_SORT_BY_SCORE + "*:" + zoneId + ":*";
}
/**
* 文件打包是否完成0代表未完成1代表已完成-1代表打包失败需要重新打包
*/
private final static String PACKAGE_FILE_IS_FINISH = "packageFileIsFinish:";
public static String getPackageFileIsFinish(String fileIdentifier) {
return PACKAGE_FILE_IS_FINISH + fileIdentifier;
}
// 全局资源数据缓存最近一年统计数据
public final static String GLOBAL_RESOURCES_DATA_KEY = "GLOBAL_RESOURCES_DATA:";

View File

@ -1,5 +1,6 @@
package com.microservices.common.core.utils;
import com.microservices.common.core.exception.ServiceException;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
@ -29,7 +30,7 @@ public class PinYinStringUtils {
try {
pinyinStr += PinyinHelper.toHanyuPinyinStringArray(newChar[i], defaultFormat)[0].charAt(0);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
throw new ServiceException("转换拼音失败");
}
} else {
pinyinStr += newChar[i];
@ -55,7 +56,7 @@ public class PinYinStringUtils {
try {
pinyinStr += PinyinHelper.toHanyuPinyinStringArray(newChar[i], defaultFormat)[0];
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
throw new ServiceException("转换拼音失败");
}
} else {
pinyinStr += newChar[i];
@ -88,8 +89,7 @@ public class PinYinStringUtils {
}
return result.toString();
} catch (BadHanyuPinyinOutputFormatCombination e1) {
e1.printStackTrace();
throw new ServiceException("转换拼音失败");
}
return result.toString();
}
}

View File

@ -218,17 +218,18 @@ public class ServletUtils {
}
/**
* 内容编码(排除斜杠)
* 内容编码(排除斜杠并且支持重复编码)
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncodeExcludeSlashes(String str) {
public static String urlEncodeExcludeSlashesApplyDuplicate(String str) {
try {
StringBuilder stringBuffer = new StringBuilder();
String[] strings = str.split("/");
for (String string : strings) {
stringBuffer.append("/").append(URLEncoder.encode(string, Constants.UTF8));
string = URLEncoder.encode(string, Constants.UTF8);
stringBuffer.append("/").append(string);
}
return stringBuffer.toString().replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
@ -236,6 +237,22 @@ public class ServletUtils {
}
}
/**
* 判断字符串是否经过URLEncode
* 1. 使用URLDecoder.decode对字符串进行解码
* 2. 再使用URLEncoder.encode对解码后的字符串重新编码
* 3. 如果重新编码后的字符串与原始字符串相同则说明原始字符串是经过URL编码的
*
* @param encodedString 需encode的字符串
* @return 是否经过URLEncode
* @throws UnsupportedEncodingException 编码异常
*/
public static boolean isUrlEncoded(String encodedString) throws UnsupportedEncodingException {
String decodedString = URLDecoder.decode(encodedString, "UTF-8");
String reencodedString = URLEncoder.encode(decodedString, "UTF-8");
return encodedString.equalsIgnoreCase(reencodedString);
}
/**
* 内容解码
*

View File

@ -3,6 +3,7 @@ package com.microservices.common.core.web.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.microservices.common.core.utils.DateUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -63,4 +64,12 @@ public class BaseEntity implements Serializable
}
return params;
}
public void setCreateAndUpdate(String username) {
Date nowDate = DateUtils.getNowDate();
this.createBy = username;
this.updateBy = username;
this.createTime = nowDate;
this.updateTime = nowDate;
}
}

View File

@ -5,6 +5,7 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.Constants;
import com.microservices.common.core.constant.HttpStatus;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.httpClient.domain.CustomHttpDelete;
import com.microservices.system.api.domain.SysFileBytes;
import org.apache.commons.collections4.MapUtils;
@ -281,6 +282,10 @@ public class HttpAPIService {
long length = httpEntity.getContentLength();
if (length != 0L) {
String result = EntityUtils.toString(httpEntity);
if (!JSON.isValid(result)) {
logger.error("平台接口响应格式异常,状态码:{},响应内容:{}", httpStatusCode, result);
throw new ServiceException("平台接口响应格式异常");
}
Object resultObj = JSON.parse(result);
if (resultObj instanceof JSONArray) {
JSONObject jsonObject = new JSONObject();

View File

@ -23,7 +23,6 @@ public class MakerSpaceDataController extends BaseController {
@ApiOperation("创客空间全局资源获取")
@GetMapping(value = "/total")
@GitlinkAdminAccessRequired
public AjaxResult getTotalData() {
return success(tasksService.getTotalStatisticalData());
}
@ -45,10 +44,16 @@ public class MakerSpaceDataController extends BaseController {
@ApiOperation("创客任务最新操作日志")
@GetMapping(value = "/task/operLog")
@GitlinkAdminAccessRequired
public AjaxResult getPaperTrendData(@ApiParam("获取最新操作日志的数量") @RequestParam Integer topNum) {
public AjaxResult getOperLogData(@ApiParam("获取最新操作日志的数量") @RequestParam Integer topNum) {
return success(tasksService.getTaskOperLogTopN(topNum));
}
@ApiOperation("创客任务最新操作日志——首页展示")
@GetMapping(value = "/task/userOperLog")
public AjaxResult getUserOperLogData(@ApiParam("获取最新操作日志的数量") @RequestParam Integer topNum) {
return success(tasksService.getTaskUserOperLogTopN(topNum));
}
@ApiOperation("创客任务奖金分布")
@GetMapping(value = "/task/bountyDistribution")
@GitlinkAdminAccessRequired
@ -79,10 +84,13 @@ public class MakerSpaceDataController extends BaseController {
@ApiOperation("创客任务-所有任务类型分布")
@GetMapping(value = "/task/categoryDistribution")
@GitlinkAdminAccessRequired
public AjaxResult getAllTaskCategoryDistribution() {
return success(tasksService.getAllTaskCategoryDistribution());
}
@ApiOperation("创客任务-各状态任务数据统计")
@GetMapping(value = "/task/statisticByStatus")
public AjaxResult getTaskStatisticsByStatus() {
return success(tasksService.getTaskStatisticsByStatus());
}
}

View File

@ -14,6 +14,8 @@ public class MakerSpaceTotalDataVo {
private int currentTotalAwardAmount;
private float paidAwardAmount;
private List<Object> taskPublishedCountsByYear;
private List<Object> taskBountyCountsByYear;

View File

@ -40,4 +40,10 @@ public interface TasksMapper{
List<TaskHeatInfoVo> getTaskInfoByVisits(@Param("topNum") Integer topNum);
List<Map<String, String>> getTaskModeStatistic();
float getPaidAwardAmount();
Map<String, String> getTaskStatisticsByStatus(@Param("status") Integer status);
List<Map<String, String>> getTaskUserOperLogTopN(@Param("topNum") Integer topNum, @Param("taskLogOperations") String[] taskLogOperations);
}

View File

@ -25,4 +25,8 @@ public interface ITasksService {
List<TaskHeatInfoVo> getTaskHeatTopN(Integer topNum);
List<Map<String, String>> getTaskModeStatisticalData();
List<Map<String, String>> getTaskStatisticsByStatus();
List<Map<String, String>> getTaskUserOperLogTopN(Integer topNum);
}

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -27,6 +28,10 @@ public class TasksServiceImpl implements ITasksService {
private static final Logger logger = LoggerFactory.getLogger(TasksServiceImpl.class);
private static final String[] taskLogOperations = {"添加需求", "添加成果", "审核成果", "管理员审核评选结果及佐证",
"上传委托协议", "胜出者上传协议", "平台方上传签订表", "平台方上传协议"};
@Resource
private TasksMapper tasksMapper;
@ -36,6 +41,7 @@ public class TasksServiceImpl implements ITasksService {
makerSpaceTotalDataVo.setTotalTasks(tasksMapper.getTotalTaskCount());
makerSpaceTotalDataVo.setTotalApplicants(tasksMapper.getTotalApplicantCount());
makerSpaceTotalDataVo.setCurrentTotalAwardAmount(tasksMapper.getCurrentTotalAwardAmount()/10000);
makerSpaceTotalDataVo.setPaidAwardAmount(tasksMapper.getPaidAwardAmount()/10000);
makerSpaceTotalDataVo.setTaskPublishedCountsByYear(tasksMapper.getTaskPublishedCountsByYear());
makerSpaceTotalDataVo.setTaskBountyCountsByYear(tasksMapper.getTaskBountyCountsByYear());
return makerSpaceTotalDataVo;
@ -110,6 +116,22 @@ public class TasksServiceImpl implements ITasksService {
return tasksMapper.getTaskModeStatistic();
}
@Override
public List<Map<String, String>> getTaskStatisticsByStatus() {
List<Map<String, String>> result = new ArrayList<>();
result.add(tasksMapper.getTaskStatisticsByStatus(DssTaskStatus.PAPER_COLLECT.getKey()));
result.add(tasksMapper.getTaskStatisticsByStatus(DssTaskStatus.PAPER_SELECT.getKey()));
result.add(tasksMapper.getTaskStatisticsByStatus(DssTaskStatus.PUBLICITY.getKey()));
result.add(tasksMapper.getTaskStatisticsByStatus(DssTaskStatus.CONTRACT.getKey()));
result.add(tasksMapper.getTaskStatisticsByStatus(DssTaskStatus.COMPLETE.getKey()));
return result;
}
@Override
public List<Map<String, String>> getTaskUserOperLogTopN(Integer topNum) {
return tasksMapper.getTaskUserOperLogTopN(topNum, taskLogOperations);
}
private int[] getNewAddedTasksByMonth(String startTime, String endTime) throws ParseException, JsonProcessingException {
int monthDiff = 12;
Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);

View File

@ -26,14 +26,12 @@ public class ProjectDataController extends BaseController {
@ApiOperation("开源项目全局资源获取")
@GetMapping(value = "/global-resources")
@GitlinkAdminAccessRequired
public AjaxResult getGlobalResourcesData() throws ParseException, JsonProcessingException {
return success(projectGlobalResourcesService.getProjectGlobalResourcesData());
}
@ApiOperation("开源项目最新动态获取")
@GetMapping(value = "/latestActivities")
@GitlinkAdminAccessRequired
public AjaxResult getLatestActivitiesData(@ApiParam("分页数") @RequestParam(value = "page", defaultValue = "1") int page,
@ApiParam("分页大小") @RequestParam(value = "limit", defaultValue = "6") int limit){
return success(projectGlobalResourcesService.getLatestActivitiesData(page, limit));

View File

@ -67,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
is_delete = 0
AND STATUS BETWEEN 3 AND 8
AND YEAR(created_at) IN (YEAR(CURDATE()) - 1, YEAR(CURDATE()))
AND YEAR(created_at) IN (YEAR(CURDATE()) - 2, YEAR(CURDATE()),YEAR(CURDATE()) - 1, YEAR(CURDATE()))
GROUP BY
YEAR(created_at)
ORDER BY
@ -82,7 +82,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
is_delete = 0
AND STATUS BETWEEN 3 AND 8
AND YEAR(created_at) IN (YEAR(CURDATE()) - 1, YEAR(CURDATE()))
AND YEAR(created_at) IN (YEAR(CURDATE()) - 2, YEAR(CURDATE()),YEAR(CURDATE()) - 1, YEAR(CURDATE()))
GROUP BY
YEAR(created_at)
ORDER BY
@ -207,5 +207,123 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE is_delete = 0 AND `status` BETWEEN 3 AND 8
GROUP BY publish_mode
</select>
<select id="getPaidAwardAmount" resultType="java.lang.Float">
SELECT SUM(bounty)
FROM tasks
WHERE is_delete = 0 AND `status` = 8 and except_closed_boolean = 0;
</select>
<select id="getTaskStatisticsByStatus" resultType="java.util.Map">
<if test = "status == 3">
select '成果征集中' AS status,sub1.total_tasks, sub1.total_bounty, sub2.total_applied_papers
from
(select count(t.id) as 'total_tasks', sum(t.bounty) as 'total_bounty'
from tasks t where t.status = 3 and t.is_delete = 0) sub1,
(select count(p.id) as 'total_applied_papers'
from papers p left join tasks t on t.id = p.task_id and p.parent_id = 0 and p.check_status = 1
WHERE t.status =3 AND t.is_delete =0) sub2
</if>
<if test = "status == 4">
select '成果评选中' AS status,
sub1.total_tasks,
sub2.total_selected_papers,
sub3.total_participated_experts
from
(select count(t.id) as 'total_tasks'
from tasks t where t.status = 4 and t.is_delete = 0) sub1,
(select count(p.id) as 'total_selected_papers'
from papers p
left join tasks t on p.task_id = t.id and p.parent_id = 0 and p.check_status = 1) sub2,
(select count(e.expert_id) as 'total_participated_experts'
from tasks t
left join
(select distinct tega.expert_id , teg.container_id
from task_expert_group_assignments tega
left join task_expert_groups teg on tega.group_id = teg.id
left join task_scoring_rule str on teg.container_id = str.container_id
where teg.container_type = 2 and str.status in (-1,1,2)) e
on t.id = e.container_id
where t.status = 4 and t.is_delete = 0) sub3
</if>
<if test = "status == 5">
SELECT
'公示中' AS status,
sub1.total_tasks,
sub2.total_won_papers,
sub1.total_bounty
FROM
(
SELECT
COUNT(DISTINCT t.id) AS 'total_tasks',
SUM(t.bounty) AS 'total_bounty'
FROM
tasks t
WHERE
t.status = 5 AND t.is_delete = 0
) sub1,
(
SELECT
COUNT(p.id) AS 'total_won_papers'
FROM
papers p
LEFT JOIN tasks t ON t.id = p.task_id AND p.parent_id = 0 AND p.status = 2
WHERE
t.status = 5 AND t.is_delete = 0
) sub2;
</if>
<if test = "status == 6">
select
'协议签订中' AS status,
sub1.total_tasks,
sub2.total_signed_tasks,
sub3.total_unsigned_tasks
from
(select count(t.id) as 'total_tasks'
from tasks t where t.status = 6 and t.is_delete = 0) sub1,
(select count(p.id) as 'total_signed_tasks'
from papers p
left join tasks t on t.id = p.task_id and p.parent_id = 0 and p.status = 2 and p.is_sign = 1
where t.status = 6 and t.is_delete = 0) sub2,
(select count(p.id) as 'total_unsigned_tasks'
from papers p
left join tasks t on t.id = p.task_id and p.parent_id = 0 and p.status = 2 and p.is_sign = 0
where t.status = 6 and t.is_delete = 0) sub3
</if>
<if test = "status == 8">
select '已完成' AS status, sub1.total_tasks, sub2.total_paid_bounty, sub3.total_won_applicants
from
(select count(t.id) as 'total_tasks'
from tasks t where t.status = 8 and t.is_delete = 0) sub1,
(select sum(t.bounty) as 'total_paid_bounty'
from tasks t where t.status = 8 and t.is_delete = 0) sub2,
(select count(p.id) as 'total_won_applicants'
from papers p
left join tasks t on t.id = p.task_id and p.parent_id = 0 and p.status = 2
where t.status = 8 and t.is_delete = 0) sub3
</if>
</select>
<select id="getTaskUserOperLogTopN" resultType="java.util.Map">
SELECT
log_desc as log_desc,
CASE
WHEN TIMESTAMPDIFF(MINUTE, oper_time, NOW()) = 0 THEN CONCAT(TIMESTAMPDIFF(SECOND, oper_time, NOW()), '秒前')
WHEN TIMESTAMPDIFF(HOUR, oper_time, NOW()) = 0 THEN CONCAT(TIMESTAMPDIFF(MINUTE, oper_time, NOW()), '分钟前')
WHEN TIMESTAMPDIFF(DAY, oper_time, NOW()) = 0 THEN CONCAT(TIMESTAMPDIFF(HOUR, oper_time, NOW()), '小时前')
ELSE CONCAT(TIMESTAMPDIFF(DAY, oper_time, NOW()), '天前')
END AS time_ago,
task_id
FROM
task_oper_log
WHERE
oper_title in
<foreach item="item" collection="taskLogOperations" open="(" separator="," close=")">
#{item}
</foreach>
AND log_desc NOT LIKE '%未通过%'
AND log_desc NOT LIKE '%驳回%'
AND log_desc NOT LIKE '%失败%'
ORDER BY
id DESC
LIMIT #{topNum};
</select>
</mapper>

View File

@ -88,6 +88,18 @@ public class CommonController extends BaseController {
return R.ok(sysFileInfoService.packagedFile(packagedStructure, zipFileName, type, hierarchy));
}
/**
* 通过Url下载文件到本地
*/
@PostMapping(value = "/downloadFileByUrl")
@InnerAuth
public R<String> downloadFileByUrl(
@RequestParam("fileUrl") String fileUrl
, @RequestParam("type") String type
, @RequestParam("hierarchy") String hierarchy) {
return R.ok(sysFileInfoService.downloadFileByUrl(fileUrl, type, hierarchy));
}
/**
* 通用下载请求
*
@ -210,4 +222,17 @@ public class CommonController extends BaseController {
sysFileInfo.setFilePath("");
return R.ok(sysFileInfo);
}
/**
* 上传本地文件到Forge
*
* @param fileIdentifiers 文件标识列表逗号分隔
* @return Forge文件标识列表
*/
@InnerAuth
@PostMapping(value = "/uploadFileToForge/{fileIdentifiers}")
@ApiOperation(value = "上传本地文件到Forge", hidden = true)
R<List<String>> uploadFileToForge(@PathVariable("fileIdentifiers") String fileIdentifiers) {
return R.ok(sysFileInfoService.uploadFileToForge(fileIdentifiers));
}
}

View File

@ -1,18 +1,19 @@
package com.microservices.file.controller;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.file.service.ISysFileInfoService;
import com.microservices.system.api.domain.SysFileInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -107,4 +108,31 @@ public class OpenController {
sysFileInfo.setFilePath("");
return R.ok(sysFileInfo);
}
/**
* 通用上传请求
*/
@PostMapping("/upload")
@ApiOperation("公开上传请求")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件实体", paramType = "form", dataType = "_file"),
@ApiImplicitParam(name = "type", value = "文件类型zone-identifier专区下支持文件标识的附件cms内容管理resource专区资源pms项目管理pms-gitlink项目管理gitlink附件gitlinkgitlink附件", paramType = "query", dataType = "String"),
@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) {
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

@ -171,4 +171,8 @@ public interface ISysFileInfoService {
* @return 压缩包文件标识
*/
String packagedFile(HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy);
List<String> uploadFileToForge(String fileIdentifiers);
String downloadFileByUrl(String fileUrl, String type, String hierarchy);
}

View File

@ -1,9 +1,11 @@
package com.microservices.file.service.impl;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.ServletUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.redis.service.RedisService;
import com.microservices.file.service.ISysFileInfoAsyncService;
import com.microservices.file.service.ISysFileInfoService;
import com.microservices.file.utils.CustomExecutorFactory;
@ -41,10 +43,13 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
*/
@Value("${file.path}")
private String localFilePath;
@Autowired
private RedisService redisService;
@Override
public void asyncPackagedFile(String fileIdentifier, HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy) {
CustomExecutorFactory.threadPoolExecutor.execute(() -> {
logger.info("开始打包文件(压缩文件标识[{}])输出Zip文件名称为{}", fileIdentifier, zipFileName);
Path localPath = Paths.get(localFilePath);
// 输出目录
String datePath = DateUtils.datePath();
@ -70,6 +75,7 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
String filePath = localFilePath + fileInfo.getFilePath();
File file = new File(filePath);
if (!file.exists()) {
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
throw new IOException("该文件不存在");
}
// 拷贝文件到打包目录
@ -82,7 +88,8 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
org.apache.commons.io.FileUtils.copyURLToFile(new URL(fileSource), packagedFilePath.toFile());
}
} catch (IOException e) {
logger.error("打包文件时出现异常,需压缩文件处理失败:{}", e.getMessage());
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
logger.error("打包文件时出现异常(压缩文件标识[{}]),需压缩文件处理失败:{}", fileIdentifier, e.getMessage());
throw new ServiceException("打包文件时出现异常,需压缩文件处理失败!");
}
});
@ -91,7 +98,8 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
ZipUtils.toZip(tempPackagedPath.toString(), Files.newOutputStream(zipFilePath), true);
File zipFile = zipFilePath.toFile();
if (!zipFile.exists()) {
throw new ServiceException("打包文件时出现异常:文件压缩失败");
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
throw new ServiceException("打包文件时出现异常:压缩文件不存在");
}
String filePath = EscapeUtil.removeExtraSlashOfUrl("/" + type + "/" + hierarchy + "/" + datePath + "/" + fullZipFileName);
SysFileInfo sysFileInfo = new SysFileInfo(fileIdentifier, zipFile, filePath);
@ -101,9 +109,12 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
org.apache.commons.io.FileUtils.deleteDirectory(tempPackagedPath.toFile());
}
} catch (IOException e) {
logger.error("打包文件时出现异常:{}", e.getMessage());
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
logger.error("打包文件时出现异常(压缩文件标识[{}]):{}", fileIdentifier, e.getMessage());
throw new ServiceException("打包文件时出现异常!");
}
logger.info("打包完成(压缩文件标识[{}])输出Zip文件名称为{}", fileIdentifier, zipFileName);
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), 1);
});
}
}

View File

@ -4,6 +4,7 @@ package com.microservices.file.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.Constants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
@ -14,6 +15,7 @@ import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.utils.uuid.IdUtils;
import com.microservices.common.httpClient.domain.GitLinkRequestUrl;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.file.mapper.SysFileInfoMapper;
import com.microservices.file.service.ISysFileInfoAsyncService;
@ -34,6 +36,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Pattern;
@ -84,6 +88,8 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
*/
@Value("${file.domain}")
public String domain;
@Autowired
private RedisService redisService;
@Override
public SysFileInfo selectSysFileInfoByFileObjectName(String fileObjectName) {
@ -499,10 +505,62 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Override
public String packagedFile(HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy) {
String fileIdentifier = genFileIdentifier();
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), 0);
fileInfoAsyncService.asyncPackagedFile(fileIdentifier, packagedStructure, zipFileName, type, hierarchy);
return fileIdentifier;
}
@Override
public List<String> uploadFileToForge(String fileIdentifiers) {
List<SysFileInfo> fileInfoList = getFileListByIdentifier(fileIdentifiers);
try {
List<String> forgeFileIdentifierList = new ArrayList<>();
for (SysFileInfo fileInfo : fileInfoList) {
String filePath = localFilePath + fileInfo.getFilePath();
File file = new File(filePath);
if (!file.exists()) {
throw new ServiceException("该文件不存在");
}
// 拷贝文件到打包目录
FileInputStream fileInputStream = new FileInputStream(file);
MultipartFile multipartFile = FileUtils.createMultipartFile(fileInputStream, fileInfo.getFileOriginName());
SysFileInfo sysFileInfo = upload(multipartFile, "pms-gitlink", null);
forgeFileIdentifierList.add(sysFileInfo.getFileIdentifier());
}
return forgeFileIdentifierList;
} catch (IOException e) {
logger.error("上传本地文件到Forge失败{}", e.getMessage());
throw new ServiceException("上传本地文件到Forge失败");
}
}
@Override
public String downloadFileByUrl(String fileUrl, String type, String hierarchy) {
String fileIdentifier = genFileIdentifier();
try {
String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
Path localPath = Paths.get(localFilePath);
// 下载目录
String datePath = DateUtils.datePath();
Path downloadPath = localPath
.resolve(type)
.resolve(hierarchy)
.resolve(datePath);
Path packagedFilePath = downloadPath.resolve(fileName);
org.apache.commons.io.FileUtils.copyURLToFile(new URL(fileUrl), packagedFilePath.toFile());
File downloadFile = packagedFilePath.toFile();
if (!downloadFile.exists()) {
throw new ServiceException("下载文件时出现异常");
}
String filePath = EscapeUtil.removeExtraSlashOfUrl("/" + type + "/" + hierarchy + "/" + datePath + "/" + fileName);
SysFileInfo sysFileInfo = new SysFileInfo(fileIdentifier, downloadFile, filePath);
insertSysFileInfo(sysFileInfo);
} catch (IOException e) {
throw new ServiceException("下载文件失败");
}
return fileIdentifier;
}
private void fileDownload(SysFileInfo sysFileInfo, HttpServletResponse response) {
try {
String fileName = sysFileInfo.getFileOriginName();

View File

@ -3,15 +3,18 @@ package com.microservices.pms.common.controller;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.pms.product.domain.vo.ProductUserReqInputVo;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.specialArea.service.SoftwareFactStatisticsServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* @author otto
@ -27,7 +30,9 @@ public class OpenController extends BaseController {
@Autowired
private SoftwareFactStatisticsServiceImpl softwareFactStatisticsService;
@Autowired
private IPmsProductRequirementService pmsProductRequirementService;
/**
* 查询项目管理企业列表
*/
@ -39,6 +44,18 @@ public class OpenController extends BaseController {
);
}
@ApiOperation(value = "获取指定组织的项目研发状态")
@GetMapping("/{enterpriseIdentifier}/specialArea/softwareFact/statis/projectSituation")
public AjaxResult theEnterpriseProjectSituation(@PathVariable String enterpriseIdentifier) {
return AjaxResult.success(softwareFactStatisticsService.projectSituation(enterpriseIdentifier));
}
@ApiOperation(value = "获取指定组织的产品里程碑状态")
@GetMapping("/{enterpriseIdentifier}/specialArea/softwareFact/statis/productPlanSituation")
public AjaxResult theEnterpriseProductPlanSituation(@PathVariable String enterpriseIdentifier) {
return AjaxResult.success(softwareFactStatisticsService.productPlanSituation(enterpriseIdentifier));
}
@ApiOperation(value = "今日工作态势")
@GetMapping("/specialArea/softwareFact/statis/todayWorkSituation")
public AjaxResult todayWorkSituation(){
@ -57,4 +74,16 @@ public class OpenController extends BaseController {
return AjaxResult.success(softwareFactStatisticsService.projectSituation());
}
/**
* 新增需求
*/
@Log(title = "需求", businessType = BusinessType.INSERT)
@PostMapping("/{enterpriseIdentifier}/productUserRequirement")
@ApiOperation(value = "新增需求")
public AjaxResult add(@PathVariable String enterpriseIdentifier,
@RequestBody @Validated ProductUserReqInputVo productUserReqInputVo) {
productUserReqInputVo.setEnterpriseIdentifier(enterpriseIdentifier);
return success(pmsProductRequirementService.insertUserReqWithoutAuth(productUserReqInputVo));
}
}

View File

@ -160,7 +160,7 @@ public class PmsCommonAsyncServiceImpl implements IPmsCommonAsyncService {
List<String> tagIds = new ArrayList<>(Arrays.asList(tagIdsStr.split(",")));
tagIds.remove(tagIdStr);
pmsProductRequirement.setTags(String.join(",", tagIds));
pmsProductRequirementService.updatePmsProductRequirement(pmsProductRequirement);
pmsProductRequirementService.updateRequirement(pmsProductRequirement);
}
});
}

View File

@ -1,6 +1,7 @@
package com.microservices.pms.dashboard.controller;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.web.controller.BaseController;
@ -9,28 +10,32 @@ import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.dashboard.domain.vo.MyDashboardVo;
import com.microservices.pms.dashboard.domain.vo.MyProjectIssuesSearchVo;
import com.microservices.pms.dashboard.domain.vo.MyTodoProjectIssuesSearchVo;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.vo.PmsProductSearchVo;
import com.microservices.pms.product.domain.PmsProductStatus;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductPlanService;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.product.service.IPmsProductService;
import com.microservices.pms.product.service.IPmsProductStatusService;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.project.service.IPmsProjectSprintService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.microservices.pms.utils.PmsConstants.PRODUCT_PLAN_CLOSED_STATUS_NAME;
@RestController
@RequestMapping("/{enterpriseIdentifier}/dashboard")
@ -53,6 +58,12 @@ public class PmsDashboardController extends BaseController {
@Autowired
private IPmsProductService pmsProductService;
@Autowired
private IPmsProductPlanService pmsProductPlanService;
@Autowired
private IPmsProductStatusService pmsProductStatusService;
/**
* 我的工作台统计信息
@ -73,8 +84,13 @@ public class PmsDashboardController extends BaseController {
PmsProductRequirement pmsProductRequirement = new PmsProductRequirement();
pmsProductRequirement.setProductIdentifierList(pmsProductList.stream().map(PmsProduct::getProductIdentifier).collect(Collectors.toList()));
pmsProductRequirement.setCreateBy(SecurityUtils.getUsername());
Integer requirementCount = pmsProductRequirementService.selectPmsProductRequirementCount(pmsProductRequirement);
Integer requirementCount = pmsProductRequirementService.selectProductReqSpecsCount(pmsProductRequirement);
myDashboardVo.setProductRequirementCount(requirementCount);
long assignedMeProductCount = pmsProductList.stream()
.filter(pmsProduct -> pmsProduct.getProductAssigneeGitlinkIds().contains(String.valueOf(SecurityUtils.getGitlinkUserId())))
.count();
myDashboardVo.setAssignedMeProductCount((int) assignedMeProductCount);
}
return success(myDashboardVo);
}
@ -85,16 +101,13 @@ public class PmsDashboardController extends BaseController {
@GetMapping("/myProjectIssues")
@ApiOperation(value = "我的工作项")
public AjaxResult myProjectIssues(MyProjectIssuesSearchVo myProjectIssuesSearchVo) {
PmsProjectIssuesSearchVo pmsProjectIssuesSearchVo = new PmsProjectIssuesSearchVo();
BeanUtils.copyProperties(myProjectIssuesSearchVo, pmsProjectIssuesSearchVo);
List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
if(projectList.isEmpty()){
return success();
}
pmsProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
// 不包含周报
pmsProjectIssuesSearchVo.setPmIssueTypes("1,2,3");
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssuesList(pmsProjectIssuesSearchVo);
myProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
JSONObject result = pmsProjectIssuesService.selectMyPmsProjectIssuesList(myProjectIssuesSearchVo);
return success(result);
}
@ -108,6 +121,24 @@ public class PmsDashboardController extends BaseController {
return pmsProjectService.selectPmsProjectList(pmsProjectSearchVo);
}
/**
* 我的项目-项目情况统计
*/
@ApiOperation(value = "我的项目-项目统计")
@GetMapping("/myProjects/statistics")
public AjaxResult myProjectStatistics(@ApiParam("项目id") @RequestParam Long pmProjectId) {
return success(pmsProjectService.getMyProjectStatistics(pmProjectId));
}
/**
* 我的仓库-仓库情况统计
*/
@ApiOperation(value = "我的仓库-仓库情况统计")
@GetMapping("/myRepositories/statistics")
public AjaxResult myRepositoriesStatistics(@ApiParam("仓库id") @RequestParam Long repositoryId) {
return success(pmsProjectService.getMyRepositoriesStatistics(repositoryId));
}
/**
* 我的迭代
@ -128,4 +159,170 @@ public class PmsDashboardController extends BaseController {
pmsProjectSprintSearchVo.setPmsProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
return pmsProjectSprintService.selectAllPmsProjectSprintList(pmsProjectSprintSearchVo);
}
/**
* 我的待办
*/
@GetMapping("/todo")
@ApiOperation(value = "我的待办")
public AjaxResult todoProjectIssues(MyTodoProjectIssuesSearchVo todoProjectIssuesSearchVo) {
List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
if(projectList.isEmpty()){
return success();
}
todoProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
JSONObject result = pmsProjectIssuesService.selectMyTodoPmsProjectIssuesList(todoProjectIssuesSearchVo);
return success(result);
}
/**
* 我的产品
*/
@ApiOperation(value = "我的产品")
@GetMapping("/myProduct")
public GenericsTableDataInfo<PmsProductStatVo> myProduct(@PathVariable String enterpriseIdentifier,
@Validated PmsProductSearchVo pmsProductSearchVo) {
startPage();
pmsProductSearchVo.setPmsEnterpriseIdentifier(enterpriseIdentifier);
//获取组织下所有的产品信息
GenericsTableDataInfo<PmsProductDataVo> productsInfo = pmsProductService.selectPmsProductPageList(pmsProductSearchVo);
List<PmsProductDataVo> rows = productsInfo.getRows();
// 统计需求数量
List<PmsProductStatVo> statVos = rows.stream().map(e -> {
PmsProductStatVo statVo = new PmsProductStatVo();
String pmsProductIdentifier = e.getProductIdentifier();
Integer requirementCount = pmsProductRequirementService.countByIdentifierAndStatus(pmsProductIdentifier, getUserReqList());
Integer reqSpecsCount = pmsProductRequirementService.countByIdentifierAndStatus(pmsProductIdentifier, getTotalReqSpecsList());
BeanUtils.copyProperties(e, statVo);
statVo.setReqSpecsCount(reqSpecsCount);
statVo.setUserReqCount(requirementCount);
return statVo;
}).collect(Collectors.toList());
GenericsTableDataInfo<PmsProductStatVo> result = new GenericsTableDataInfo<>();
result.setRows(statVos);
result.setTotal(productsInfo.getTotal());
return result;
}
@ApiOperation(value = "我的产品数据统计-原始需求统计")
@ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
@GetMapping("/userRequirementStat")
public R<PmsRequirementStatResVo> UserRequirementStat(String productIdentifier){
PmsRequirementStatResVo pmsRequirementStatResVo = buildPmsRequirementStatResVo(
productIdentifier,
getUserReqList(),
ProductReqStatus.REVIEWED_USER_REQ);
return R.ok(pmsRequirementStatResVo);
}
@ApiOperation(value = "我的产品数据统计-需求统计")
@ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
@GetMapping("/productRequirementSpecsStat")
public R<PmsRequirementStatResVo> ProductRequirementSpecsStat(String productIdentifier){
PmsRequirementStatResVo pmsRequirementStatResVo = buildPmsRequirementStatResVo(
productIdentifier,
getReqSpecsList(),
ProductReqStatus.COMPLETED_REQ_SPECS);
return R.ok(pmsRequirementStatResVo);
}
@ApiOperation(value = "我的产品数据统计-里程碑状态分布统计")
@ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
@GetMapping("/milestoneStatusStat")
public R<PmsRequirementStatResVo> milestoneStatusStat(String productIdentifier){
Map<String, Integer> status2NumMap = pmsProductPlanService.countPmsProductPlanGroupByStatus(productIdentifier)
.stream().collect(Collectors.toMap(EnumCommonVo::getKey, ReqStatusStatVo::getNum));
PmsProductStatus pmsProductStatus = new PmsProductStatus();
pmsProductStatus.setType(1);
List<PmsTypeDataVo> pmsTypeDataVos = pmsProductStatusService.selectPmsProductStatusList(pmsProductStatus);
List<ReqStatusStatVo> statusStatVos = pmsTypeDataVos.stream().filter(e -> !PRODUCT_PLAN_CLOSED_STATUS_NAME.equals(e.getName())).map(e -> {
ReqStatusStatVo vo = new ReqStatusStatVo();
vo.setKey(String.valueOf(e.getId()));
vo.setNum(status2NumMap.getOrDefault(String.valueOf(e.getId()), 0));
vo.setName(e.getName());
return vo;
}).collect(Collectors.toList());
PmsRequirementStatResVo resVo = new PmsRequirementStatResVo();
resVo.setPmsProductStatVos(statusStatVos);
resVo.setRatio(0);
return R.ok(resVo);
}
/**
* 获取 统计饼图所需的需求状态list
* @return 需求状态list
*/
private List<String> getReqSpecsList() {
return Stream.of(ProductReqStatus.PENDING_REVIEW_REQ_SPECS.getKey(),
ProductReqStatus.PLANNED_REQ_SPECS.getKey(),
ProductReqStatus.REJECTED_REQ_SPECS.getKey(),
ProductReqStatus.REVIEWED_REQ_SPECS.getKey(),
ProductReqStatus.COMPLETED_REQ_SPECS.getKey())
.collect(Collectors.toList());
}
/**
* 获取Count总数时需求的状态list
* @return 需求状态list
*/
private List<String> getTotalReqSpecsList() {
return Stream.of(ProductReqStatus.PENDING_REVIEW_REQ_SPECS.getKey(),
ProductReqStatus.PLANNED_REQ_SPECS.getKey(),
ProductReqStatus.REJECTED_REQ_SPECS.getKey(),
ProductReqStatus.REVIEWED_REQ_SPECS.getKey(),
ProductReqStatus.COMPLETED_REQ_SPECS.getKey(),
ProductReqStatus.CHANGING_REQ_SPECS.getKey())
.collect(Collectors.toList());
}
/**
* 获取 原始需求状态list
* @return 原始需求状态list
*/
private List<String> getUserReqList() {
return Stream.of(ProductReqStatus.PENDING_REVIEW_USER_REQ.getKey(),
ProductReqStatus.REJECTED_USER_REQ.getKey(),
ProductReqStatus.REVIEWED_USER_REQ.getKey())
.collect(Collectors.toList());
}
/**
* 拼接统计返回结果
* @param productIdentifier 产品标识
* @param statusList 状态列表
* @param productReqStatus x
* @return
*/
private PmsRequirementStatResVo buildPmsRequirementStatResVo(String productIdentifier,List<String> statusList, ProductReqStatus productReqStatus) {
Map<String, Integer> status2NumMap = pmsProductRequirementService
.selectReqCountGroupByStatus(productIdentifier, statusList)
.stream().collect(Collectors.toMap(EnumCommonVo::getKey, ReqStatusStatVo::getNum));
//组装各个状态的数量
List<ReqStatusStatVo> statusStatVos = statusList.stream().map(e -> {
ReqStatusStatVo vo = new ReqStatusStatVo();
vo.setKey(e);
vo.setNum(status2NumMap.getOrDefault(e, 0));
vo.setName(ProductReqStatus.getByKey(e).getName());
return vo;
}).collect(Collectors.toList());
PmsRequirementStatResVo resVo = new PmsRequirementStatResVo();
resVo.setPmsProductStatVos(statusStatVos);
resVo.setRatio(0);
//计算 各自的比率
int sum = statusStatVos.stream().mapToInt(ReqStatusStatVo::getNum).sum();
if (sum > 0) {
Integer completedReqSpecsCount = status2NumMap.getOrDefault(productReqStatus.getKey(), 0);
double ratioDouble = (double) completedReqSpecsCount / sum * 100;
int ratio = (int) Math.round(ratioDouble);
resVo.setRatio(ratio);
}
return resVo;
}
}

View File

@ -11,4 +11,7 @@ public class MyDashboardVo extends IssueTypeTotalCountVo {
@ApiModelProperty(value = "产品需求数")
private int productRequirementCount;
@ApiModelProperty(value = "我负责的产品数")
private int assignedMeProductCount;
}

View File

@ -8,10 +8,10 @@ import lombok.Data;
@ApiModel("我的工作项搜索对象")
public class MyProjectIssuesSearchVo {
@ApiModelProperty(value = "疑修类型all 全部 opened 开启中 closed 已关闭", required = true)
@ApiModelProperty(value = "疑修类型all 全部 opened 开启中 closed 已关闭")
private String category;
@ApiModelProperty(value = "参与类型all 全部 aboutme 关于我的 authoredme 我创建的 assignedme 我负责的 atme @我的", required = true)
@ApiModelProperty(value = "参与类型all 全部 aboutme 关于我的 authoredme 我创建的 assignedme 我负责的 atme @我的")
private String participantCategory;
@ApiModelProperty(value = "工作项名称搜索关键词")
@ -30,6 +30,9 @@ public class MyProjectIssuesSearchVo {
private String limit;
@ApiModelProperty(value = "按pmProjectId集合查询,逗号隔开", hidden = true)
private String pmsProjectIds;
private String pmProjectIds;
@ApiModelProperty(value = "工作项类型计划1 任务2 缺陷3多个用逗号隔开", required = true)
private String pmIssueTypes;
}

View File

@ -0,0 +1,35 @@
package com.microservices.pms.dashboard.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("我的待办工作项搜索对象")
public class MyTodoProjectIssuesSearchVo {
@ApiModelProperty(value = "日期格式yyyy-MM-dd示例值:2024-12-11")
private String date;
@ApiModelProperty(value = "工作项名称搜索关键词")
private String keyword;
@ApiModelProperty(value = "排序方式: issues.updated_on 更新时间 issues.created_on 创建时间 issue_priorities.position 优先级")
private String sortBy;
@ApiModelProperty(value = "排序方向:asc 正序 desc 倒序")
private String sortDirection;
@ApiModelProperty(value = "页码", required = true)
private String page;
@ApiModelProperty(value = "分页数", required = true)
private String limit;
@ApiModelProperty(value = "按pmProjectId集合查询,逗号隔开", hidden = true)
private String pmProjectIds;
@ApiModelProperty(value = "工作项类型计划1 任务2 缺陷3多个用逗号隔开")
private String pmIssueTypes;
}

View File

@ -36,10 +36,10 @@ public class PmsDocumentUserFavoriteController extends BaseController
* 查询用户收藏文档列表
*/
@GetMapping("/list")
public GenericsTableDataInfo<PmsDocumentVo> list(PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo)
public GenericsTableDataInfo<PmsDocumentVo> list(@PathVariable String enterpriseIdentifier, PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo)
{
return pmsDocumentUserFavoriteService.selectPmsDocumentUserFavoriteList(pmsDocumentFavoriteSearchVo);
return pmsDocumentUserFavoriteService.selectPmsDocumentUserFavoriteList(enterpriseIdentifier, pmsDocumentFavoriteSearchVo);
}
/**

View File

@ -1,5 +1,6 @@
package com.microservices.pms.document.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.microservices.common.core.annotation.Excel;
import com.microservices.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -56,6 +57,7 @@ public class PmsDocument extends BaseEntity
/** 权限 1-私有 2-全员读 3-全员读写 */
@Excel(name = "权限 1-私有 2-全员读 3-全员读写")
@JsonIgnore
private Integer permission;
public void setId(Long id)

View File

@ -60,7 +60,7 @@ public class PmsDocumentDetailVo
private Integer isTop;
/** 权限 1-私有 2-全员读 3-全员读写 */
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写")
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", hidden = true)
private Integer permission;
@ApiModelProperty(value = "文档创建者")

View File

@ -30,4 +30,8 @@ public class PmsDocumentFavoriteSearchVo extends BaseEntity
@JsonIgnore
@ApiModelProperty(value = "用户id", hidden = true)
private Long currentUserId;
@JsonIgnore
@ApiModelProperty(value = "企业id", hidden = true)
private Long pmsEnterpriseId;
}

View File

@ -60,9 +60,8 @@ public class PmsDocumentInputVo
private Integer isTop;
/** 权限 1-私有 2-全员读 3-全员读写 */
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", required = true)
@NotNull
private Integer permission;
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", hidden = true)
private Integer permission = 3;
public PmsDocument toPmsDocument() {
PmsDocument pmsDocument = new PmsDocument();

View File

@ -47,8 +47,8 @@ public class PmsDocumentUpdateVo
private Integer isTop;
/** 权限 1-私有 2-全员读 3-全员读写 */
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写")
private Integer permission;
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", hidden = true)
private Integer permission = 3;
public PmsDocument toPmsDocument() {
PmsDocument pmsDocument = new PmsDocument();

View File

@ -55,7 +55,7 @@ public class PmsDocumentVo
private Integer isTop;
/** 权限 1-私有 2-全员读 3-全员读写 */
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写")
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", hidden = true)
private Integer permission;
@ApiModelProperty(value = "文档创建者")

View File

@ -45,7 +45,6 @@ public class PmsFileTypeDocumentInputVo
private String[] attachmentIdentifiers;
/** 权限 1-私有 2-全员读 3-全员读写 */
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", required = true)
@NotNull
private Integer permission;
@ApiModelProperty(value = "权限 1-私有 2-全员读 3-全员读写", hidden = true)
private Integer permission = 3;
}

View File

@ -79,7 +79,7 @@ public interface PmsDocumentMapper
int countChildDocByIds(@Param("ids") Long[] ids);
int countDocumentByNameAndTypeAndParenId(@Param("name") String name, @Param("docType") Integer docType, @Param("parenId") Long parenId, @Param("pmsProjectId") Long pmsProjectId);
int countDocumentByNameAndTypeAndParenId(@Param("name") String name, @Param("docType") Integer docType, @Param("parenId") Long parenId, @Param("pmsProjectId") Long pmsProjectId, @Param("pmsEnterpriseId") Long pmsEnterpriseId);
int deletePmsDocumentByIdWithoutAuthCheck(@Param("docId") Long docId);

View File

@ -29,5 +29,5 @@ public interface IPmsDocumentUserFavoriteService
*/
public int deletePmsDocumentUserFavoriteByDocId(Long documentId);
GenericsTableDataInfo<PmsDocumentVo> selectPmsDocumentUserFavoriteList(PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo);
GenericsTableDataInfo<PmsDocumentVo> selectPmsDocumentUserFavoriteList(String enterpriseIdentifier, PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo);
}

View File

@ -150,7 +150,7 @@ public class PmsDocumentServiceImpl implements IPmsDocumentService
checkPmsProjectById(pmsDocument.getPmsProjectId());
checkAuthAndReturnAdminStatus(pmsDocument.getPmsEnterpriseId());
String currentUserName = SecurityUtils.getUsername();
checkForSameDocumentExistence(pmsDocument.getName(), pmsDocument.getDocType(), pmsDocument.getParentId(), pmsDocument.getPmsProjectId());
checkForSameDocumentExistence(pmsDocument.getName(), pmsDocument.getDocType(), pmsDocument.getParentId(), pmsDocument.getPmsProjectId(), pmsDocument.getPmsEnterpriseId());
pmsDocument.setCreateTime(DateUtils.getNowDate());
pmsDocument.setCreateBy(currentUserName);
return pmsDocumentMapper.insertPmsDocument(pmsDocument);
@ -311,7 +311,7 @@ public class PmsDocumentServiceImpl implements IPmsDocumentService
pmsDocument.setCreateTime(DateUtils.getNowDate());
pmsDocument.setUpdateTime(DateUtils.getNowDate());
pmsDocument.setCreateBy(currentUserName);
checkForSameDocumentExistence(pmsDocument.getName(), pmsDocument.getDocType(), pmsDocument.getParentId(), pmsDocument.getPmsProjectId());
checkForSameDocumentExistence(pmsDocument.getName(), pmsDocument.getDocType(), pmsDocument.getParentId(), pmsDocument.getPmsProjectId(), pmsDocument.getPmsEnterpriseId());
pmsDocumentList.add(pmsDocument);
}
return pmsDocumentMapper.batchInsertPmsDocument(pmsDocumentList);
@ -324,8 +324,8 @@ public class PmsDocumentServiceImpl implements IPmsDocumentService
}
}
private void checkForSameDocumentExistence(String name, Integer docType, Long parentId, Long pmsProjectId) {
if (pmsDocumentMapper.countDocumentByNameAndTypeAndParenId(name, docType, parentId, pmsProjectId) > 0) {
private void checkForSameDocumentExistence(String name, Integer docType, Long parentId, Long pmsProjectId, Long pmsEnterpriseId) {
if (pmsDocumentMapper.countDocumentByNameAndTypeAndParenId(name, docType, parentId, pmsProjectId, pmsEnterpriseId) > 0) {
throw new ServiceException("当前目录已存在同名文档:[%s]", name);
}
}

View File

@ -11,6 +11,8 @@ import com.microservices.pms.document.domain.vo.PmsDocumentVo;
import com.microservices.pms.document.mapper.PmsDocumentMapper;
import com.microservices.pms.document.mapper.PmsDocumentUserFavoriteMapper;
import com.microservices.pms.document.service.IPmsDocumentUserFavoriteService;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.enterprise.service.impl.PmsEnterpriseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -36,6 +38,9 @@ public class PmsDocumentUserFavoriteServiceImpl implements IPmsDocumentUserFavor
@Autowired
private PmsDocumentServiceImpl pmsDocumentService;
@Autowired
private IPmsEnterpriseService pmsEnterpriseService;
/**
* 新增用户收藏文档
*
@ -67,8 +72,9 @@ public class PmsDocumentUserFavoriteServiceImpl implements IPmsDocumentUserFavor
}
@Override
public GenericsTableDataInfo<PmsDocumentVo> selectPmsDocumentUserFavoriteList(PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo) {
public GenericsTableDataInfo<PmsDocumentVo> selectPmsDocumentUserFavoriteList(String enterpriseIdentifier, PmsDocumentFavoriteSearchVo pmsDocumentFavoriteSearchVo) {
pmsDocumentFavoriteSearchVo.setCurrentUserId(SecurityUtils.getUserId());
pmsDocumentFavoriteSearchVo.setPmsEnterpriseId(pmsEnterpriseService.selectPmsEnterpriseByIdentifier(enterpriseIdentifier).getId());
List<PmsDocument> pmsDocumentList = pmsDocumentMapper.selectPmsFavoriteDocumentList(pmsDocumentFavoriteSearchVo);
return toPage(pmsDocumentList,pmsDocumentService::buildPmsDocumentVo);
}

View File

@ -60,6 +60,8 @@ public interface IPmsEnterpriseService {
PmsEnterprise selectPmsEnterpriseByIdentifier(String identifier);
PmsEnterprise selectPmsEnterpriseByIdentifierWithoutAuth(String identifier);
/**
* 获取企业下用户列表
*

View File

@ -136,6 +136,27 @@ public class PmsEnterpriseServiceImpl implements IPmsEnterpriseService {
return pmsEnterprise;
}
@Override
public PmsEnterprise selectPmsEnterpriseByIdentifierWithoutAuth(String identifier) {
// 企业信息在项目管理的每次接口请求中都会执行查询加入到Redis缓存减少数据库查询次数
String enterpriseRedisKey = CacheConstants.getEnterpriseIdentifierKey(identifier);
PmsEnterprise pmsEnterprise;
if (redisService.hasKey(enterpriseRedisKey)) {
pmsEnterprise = redisService.getCacheObject(enterpriseRedisKey);
} else {
pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseByIdentifier(identifier);
if (pmsEnterprise == null) {
throw new ServiceException("该企业不存在(企业标识[%s])", identifier);
}
redisService.setCacheObject(enterpriseRedisKey, pmsEnterprise);
}
if (!checkEnterpriseInitComplete(pmsEnterprise.getGitlinkOrgId())) {
throw new ServiceException("当前组织初始化未完成,不允许进行操作!");
}
pmsEnterprise.setGitlinkUrl(gitLinkRequestHelper.gitLinkUrl);
return pmsEnterprise;
}
private void clearPmsEnterpriseForRedis(PmsEnterprise pmsEnterprise) {
redisService.deleteObject(CacheConstants.getEnterpriseIdentifierKey(pmsEnterprise.getEnterpriseIdentifier()));
redisService.deleteObject(CacheConstants.getEnterpriseIdKey(pmsEnterprise.getId()));

View File

@ -0,0 +1,141 @@
package com.microservices.pms.enums;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
/**
* @author OTTO
*/
@Getter
@ApiModel("产品库制品路径前缀")
public enum ProductLibraryComponentPathEnum {
ALL("_All", "所有"),
SOFTWARE("Software", "制品"),
DOC("Document", "文档");
private final String key;
private final String name;
ProductLibraryComponentPathEnum(String key, String name) {
this.key = key;
this.name = name;
}
public static ProductLibraryComponentPathEnum getByKey(String key) {
for (ProductLibraryComponentPathEnum typeEnum : ProductLibraryComponentPathEnum.values()) {
if (typeEnum.key.equals(key)) {
return typeEnum;
}
}
throw new ServiceException("该产品库制品路径前缀不存在(产品库制品路径前缀[%s])", key);
}
public static String getSoftwareFixedPath(String directory) {
return EscapeUtil.removeExtraSlashOfUrl(SOFTWARE.key + "/" + directory);
}
public static String getDocFixedPath(String directory) {
return EscapeUtil.removeExtraSlashOfUrl(DOC.key + "/" + directory);
}
public static String getChineseFixedPath(String path) {
if (path.startsWith(SOFTWARE.key)) {
return path.replaceFirst(SOFTWARE.key, SOFTWARE.name);
}
if (path.startsWith(DOC.key)) {
return path.replaceFirst(DOC.key, DOC.name);
}
return path;
}
public static boolean pathIsNeedPackaged(String node, String path) {
if (StringUtils.isNotEmpty(node)) {
if (node.equals(SOFTWARE.key)) {
return path.startsWith(SOFTWARE.key);
}
if (node.equals(DOC.key)) {
return path.startsWith(DOC.key);
}
}
return true;
}
public static String getPackagedFileJson(String node, String packagedFileIdentifiersJson, String fileIdentifier) {
JSONObject packagedFileIdentifiersJsonObj;
if (StringUtils.isNotEmpty(packagedFileIdentifiersJson) && JSON.isValid(packagedFileIdentifiersJson)) {
packagedFileIdentifiersJsonObj = JSONObject.parseObject(packagedFileIdentifiersJson);
} else {
packagedFileIdentifiersJsonObj = new JSONObject();
}
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
packagedFileIdentifiersJsonObj.put(SOFTWARE.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
if (DOC.key.equals(node)) {
packagedFileIdentifiersJsonObj.put(DOC.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
}
packagedFileIdentifiersJsonObj.put(ALL.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
public static String getPackagedFileIdentifierFromJson(String node, JSONObject packagedFileIdentifiersJsonObj) {
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
return packagedFileIdentifiersJsonObj.getString(SOFTWARE.key);
}
if (DOC.key.equals(node)) {
return packagedFileIdentifiersJsonObj.getString(DOC.key);
}
}
return packagedFileIdentifiersJsonObj.getString(ALL.key);
}
public static String getPackagedFileTag(String node) {
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
return "(" + SOFTWARE.name + ")";
}
if (DOC.key.equals(node)) {
return "(" + DOC.name + ")";
}
}
return "";
}
public static String setPackagedFileIdentifierNull(String node, String packagedFileIdentifiersJson) {
JSONObject packagedFileIdentifiersJsonObj;
if (StringUtils.isNotEmpty(packagedFileIdentifiersJson) && JSON.isValid(packagedFileIdentifiersJson)) {
packagedFileIdentifiersJsonObj = JSONObject.parseObject(packagedFileIdentifiersJson);
} else {
packagedFileIdentifiersJsonObj = new JSONObject();
}
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
if (packagedFileIdentifiersJsonObj.containsKey(SOFTWARE.key)) {
packagedFileIdentifiersJsonObj.remove(SOFTWARE.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
if (DOC.key.equals(node)) {
if (packagedFileIdentifiersJsonObj.containsKey(DOC.key)) {
packagedFileIdentifiersJsonObj.remove(DOC.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
}
if (packagedFileIdentifiersJsonObj.containsKey(ALL.key)) {
packagedFileIdentifiersJsonObj.remove(ALL.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
}

View File

@ -0,0 +1,34 @@
package com.microservices.pms.enums;
import com.microservices.common.core.exception.ServiceException;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
/**
* @author OTTO
*/
@Getter
@ApiModel("来源类型")
public enum ProductLibraryRepoFromTypeEnum {
COMMON("common", "普通类型"),
PIPELINE("pipeline", "流水线类型"),
DOC("doc", "文档类型");
private final String key;
private final String name;
ProductLibraryRepoFromTypeEnum(String key, String name) {
this.key = key;
this.name = name;
}
public static ProductLibraryRepoFromTypeEnum getByKey(String key) {
for (ProductLibraryRepoFromTypeEnum typeEnum : ProductLibraryRepoFromTypeEnum.values()) {
if (typeEnum.key.equals(key)) {
return typeEnum;
}
}
throw new ServiceException("该来源类型不存在(来源类型[%s])", key);
}
}

View File

@ -79,4 +79,6 @@ public interface PmsJournalsMapper
* @param journalId 评论对象Id
*/
void deletePmsJournalsByTypeAndJournalId(@Param("type") String type, @Param("journalId") Long journalId);
void updateJournalsIdByTypeAndOldId(@Param("type") String type, @Param("oldJournalId") Long oldJournalId, @Param("journalId") Long journalId);
}

View File

@ -68,4 +68,13 @@ public interface IPmsJournalsService
* @param journalId 评论对象Id
*/
void deletePmsJournalsByTypeAndJournalId(String type, Long journalId);
/**
* 更新评论对象id
*
* @param type 类型
* @param oldJournalId 原评论对象Id
* @param journalId 评论对象Id
*/
void updateJournalsIdByTypeAndOldId(String type, Long oldJournalId, Long journalId);
}

View File

@ -228,4 +228,9 @@ public class PmsJournalsServiceImpl implements IPmsJournalsService
public void deletePmsJournalsByTypeAndJournalId(String type, Long journalId) {
pmsJournalsMapper.deletePmsJournalsByTypeAndJournalId(type, journalId);
}
@Override
public void updateJournalsIdByTypeAndOldId(String type, Long oldJournalId, Long journalId) {
pmsJournalsMapper.updateJournalsIdByTypeAndOldId(type, oldJournalId, journalId);
}
}

View File

@ -5,32 +5,25 @@ import com.microservices.common.core.web.domain.AjaxResult;
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.pms.pipeline.domain.PmsCiPipelines;
import com.microservices.pms.pipeline.domain.vo.*;
import com.microservices.pms.pipeline.service.IPmsCiPipelinesService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.pms.pipeline.service.IPmsCiPipelinesService;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import javax.servlet.http.HttpServletResponse;
/**
* 流水线Controller
*
*
* @author wanjia
* @date 2024-03-02
*/
@RestController
@RequestMapping("/{enterpriseIdentifier}/pipelines")
@Api(tags = "项目管理-流水线相关接口")
public class PmsCiPipelinesController extends BaseController
{
public class PmsCiPipelinesController extends BaseController {
@Autowired
private IPmsCiPipelinesService pmsCiPipelinesService;
@ -47,11 +40,30 @@ public class PmsCiPipelinesController extends BaseController
})
@ApiOperation("流水线列表")
public GenericsTableDataInfo<PmsCiPipelinesDetailVo> list(@ApiParam(name = "enterpriseIdentifier", value = "企业标识") @PathVariable String enterpriseIdentifier,
@ApiParam("流水线名称搜索") @RequestParam(required = false) String pipelineName,
@ApiParam("流水线构建类型 1-声明式流水线 2-图形化流水线") @RequestParam(required = false) Integer pipelineType) {
return pmsCiPipelinesService.selectPmsCiPipelinesList(enterpriseIdentifier, pipelineName, pipelineType);
}
/**
* 查询流水线卡片列表
*/
// @RequiresPermissions("pms:pipelines:list")
@GetMapping("/cardList")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "orderByColumn", value = "排序列更新时间updateTime创建时间createTime", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "isAsc", value = "排序的方向desc或者asc,默认asc", paramType = "query", dataType = "String")
})
@ApiOperation("流水线卡片列表")
public GenericsTableDataInfo<PmsCiPipelinesCardVo> cardList(@ApiParam(name = "enterpriseIdentifier", value = "企业标识") @PathVariable String enterpriseIdentifier,
@ApiParam("流水线名称搜索") @RequestParam(required = false) String pipelineName,
@ApiParam("流水线构建类型 1-声明式流水线 2-图形化流水线") @RequestParam(required = false) Integer pipelineType)
{
return pmsCiPipelinesService.selectPmsCiPipelinesList(enterpriseIdentifier, pipelineName, pipelineType);
return pmsCiPipelinesService.selectPmsCiPipelinesCardList(enterpriseIdentifier, pipelineName, pipelineType);
}
/**
@ -60,8 +72,7 @@ public class PmsCiPipelinesController extends BaseController
// @RequiresPermissions("pms:pipelines:query")
@GetMapping(value = "/{id}")
@ApiOperation("获取流水线详情")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
public AjaxResult getInfo(@PathVariable("id") Long id) {
return success(pmsCiPipelinesService.selectPmsCiPipelinesById(id));
}
@ -73,8 +84,7 @@ public class PmsCiPipelinesController extends BaseController
@PostMapping
@ApiOperation("新增流水线")
public AjaxResult add(@ApiParam(name = "enterpriseIdentifier", value = "企业标识") @PathVariable String enterpriseIdentifier,
@RequestBody @Validated PmsCiPipelinesInputVo pmsCiPipelinesInputVo)
{
@RequestBody @Validated PmsCiPipelinesInputVo pmsCiPipelinesInputVo) {
return success(pmsCiPipelinesService.insertPmsCiPipelines(pmsCiPipelinesInputVo, enterpriseIdentifier));
}
@ -85,8 +95,7 @@ public class PmsCiPipelinesController extends BaseController
@Log(title = "流水线", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("编辑流水线")
public AjaxResult edit(@RequestBody PmsCiPipelinesUpdateVo pmsCiPipelinesUpdateVo)
{
public AjaxResult edit(@RequestBody PmsCiPipelinesUpdateVo pmsCiPipelinesUpdateVo) {
return toAjax(pmsCiPipelinesService.updatePmsCiPipelines(pmsCiPipelinesUpdateVo.toPmsCiPipelines()));
}
@ -98,8 +107,7 @@ public class PmsCiPipelinesController extends BaseController
@PostMapping(value = "/settingFile")
@ApiOperation("编辑流水线配置文件")
public AjaxResult editPipelineFile(@ApiParam(name = "enterpriseIdentifier", value = "企业标识") @PathVariable String enterpriseIdentifier,
@RequestBody PmsCiPipelineFileInputVo pmsCiPipelineFileInputVo)
{
@RequestBody PmsCiPipelineFileInputVo pmsCiPipelineFileInputVo) {
return toAjax(pmsCiPipelinesService.createOrUpdatePmsCiPipelineFile(pmsCiPipelineFileInputVo));
}
@ -108,9 +116,8 @@ public class PmsCiPipelinesController extends BaseController
*/
// @RequiresPermissions("pms:pipelines:remove")
@Log(title = "流水线", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(pmsCiPipelinesService.deletePmsCiPipelinesByIds(ids));
}
@ -131,8 +138,7 @@ public class PmsCiPipelinesController extends BaseController
// @RequiresPermissions("pms:pipelines:list")
@GetMapping(value = "/{id}/actions/runs")
@ApiOperation("流水线执行记录列表")
public AjaxResult getPipelineRunsList(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id, PmsCiPipelinePageVo pmsCiPipelinePageVo)
{
public AjaxResult getPipelineRunsList(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id, PmsCiPipelinePageVo pmsCiPipelinePageVo) {
return success(pmsCiPipelinesService.selectPipelineRunsList(id, pmsCiPipelinePageVo));
}
@ -142,11 +148,10 @@ public class PmsCiPipelinesController extends BaseController
// @RequiresPermissions("pms:pipelines:query")
@PostMapping(value = "/{id}/actions/runs/{run}/jobs/{job}")
@ApiOperation("流水线执行记录任务详情")
public AjaxResult getPipelineRunsJob(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号")@PathVariable String run,
@ApiParam(name = "job", value = "执行任务序号")@PathVariable String job,
@RequestBody @Validated PmsCiPipelineLogCursorsVo pmsCiPipelineLogCursorsVo)
{
public AjaxResult getPipelineRunsJob(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号") @PathVariable String run,
@ApiParam(name = "job", value = "执行任务序号") @PathVariable String job,
@RequestBody @Validated PmsCiPipelineLogCursorsVo pmsCiPipelineLogCursorsVo) {
return success(pmsCiPipelinesService.getPipelineRunsJob(id, run, job, pmsCiPipelineLogCursorsVo));
}
@ -157,8 +162,7 @@ public class PmsCiPipelinesController extends BaseController
@Log(title = "流水线", businessType = BusinessType.UPDATE)
@PutMapping(value = "/{id}/actions/enable")
@ApiOperation("启用流水线")
public AjaxResult enablePipeline(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id)
{
public AjaxResult enablePipeline(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id) {
return success(pmsCiPipelinesService.enablePipeline(id));
}
@ -169,38 +173,33 @@ public class PmsCiPipelinesController extends BaseController
@Log(title = "流水线", businessType = BusinessType.UPDATE)
@PutMapping(value = "/{id}/actions/disable")
@ApiOperation("禁用流水线")
public AjaxResult disablePipeline(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id)
{
public AjaxResult disablePipeline(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id) {
return success(pmsCiPipelinesService.disablePipeline(id));
}
@GetMapping(value = "/actions/nodes")
@ApiOperation("节点列表")
public AjaxResult getActionNodes()
{
public AjaxResult getActionNodes() {
return success(pmsCiPipelinesService.selectNodes());
}
@GetMapping(value = "/actions/templates")
@ApiOperation("流水线模版列表")
public AjaxResult getActionTemplates()
{
public AjaxResult getActionTemplates() {
return success(pmsCiPipelinesService.selectTemplates());
}
@PostMapping(value = "/{id}/graphJsonToYaml")
@ApiOperation("流水线图形json构建声明式yaml")
public AjaxResult buildPipelineYaml(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@RequestBody @Validated PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo)
{
public AjaxResult buildPipelineYaml(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@RequestBody @Validated PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo) {
return success(pmsCiPipelinesService.buildPipelineYamlByGraphJson(id, pmsCiPipelineBuildInputVo));
}
@PostMapping(value = "/{id}/savePipelineYaml")
@ApiOperation("流水线图形构建声明式yaml并保存")
public AjaxResult savePipelineYaml(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@RequestBody @Validated PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo)
{
public AjaxResult savePipelineYaml(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@RequestBody @Validated PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo) {
return success(pmsCiPipelinesService.savePipelineYamlByGraphicJson(id, pmsCiPipelineBuildInputVo));
}
@ -219,8 +218,7 @@ public class PmsCiPipelinesController extends BaseController
@ApiOperation("启动流水线执行记录任务")
public AjaxResult runPipelineRunsJob(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@ApiParam(name = "workflow", value = "流水线文件名称", required = true) @RequestParam String workflow,
@ApiParam(name = "ref", value = "分支名称", required = true) @RequestParam String ref)
{
@ApiParam(name = "ref", value = "分支名称", required = true) @RequestParam String ref) {
return success(pmsCiPipelinesService.runPipelineRunsJob(id, workflow, ref));
}
@ -229,10 +227,9 @@ public class PmsCiPipelinesController extends BaseController
*/
@PostMapping(value = "/{id}/actions/runs/{run}/jobs/{job}/rerun")
@ApiOperation("重启流水线执行记录任务")
public AjaxResult reRunPipelineRunsJob(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号")@PathVariable String run,
@ApiParam(name = "job", value = "执行任务序号")@PathVariable String job)
{
public AjaxResult reRunPipelineRunsJob(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号") @PathVariable String run,
@ApiParam(name = "job", value = "执行任务序号") @PathVariable String job) {
return success(pmsCiPipelinesService.reRunPipelineRunsJob(id, run, job));
}
@ -241,9 +238,8 @@ public class PmsCiPipelinesController extends BaseController
*/
@PostMapping(value = "/{id}/actions/runs/{run}/rerun")
@ApiOperation("重启所有流水线执行记录任务")
public AjaxResult reRunAllJobsInPipelineRun(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号")@PathVariable String run)
{
public AjaxResult reRunAllJobsInPipelineRun(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号") @PathVariable String run) {
return success(pmsCiPipelinesService.reRunAllJobsInPipelineRun(id, run));
}
@ -264,11 +260,22 @@ public class PmsCiPipelinesController extends BaseController
*/
@GetMapping(value = "/{id}/actions/runs/{run}/results")
@ApiOperation("流水线执行测试报告结果查询")
public AjaxResult getPipelineRunResults(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号")@PathVariable String run)
{
public AjaxResult getPipelineRunResults(@ApiParam(name = "id", value = "流水线id") @PathVariable Long id,
@ApiParam(name = "run", value = "执行记录序号") @PathVariable String run) {
return success(pmsCiPipelinesService.getPipelineRunResults(id, run));
}
@GetMapping(value = "/getPipelineRubyId/{javaId}")
@ApiOperation("查询流水线Id根据JavaId查询RubyId")
public AjaxResult getPipelineRubyIdByJavaId(@ApiParam(name = "javaId", value = "JavaId") @PathVariable Long javaId) {
return success(pmsCiPipelinesService.getPipelineRubyIdByJavaId(javaId));
}
@GetMapping(value = "/{repoOwner}/{repoIdentifier}/getPipelineId/{fileName}")
@ApiOperation("查询流水线Id根据JavaId查询RubyId")
public AjaxResult getPipelineId(@ApiParam(name = "repoOwner", value = "仓库所有者") @PathVariable String repoOwner,
@ApiParam(name = "repoIdentifier", value = "仓库标识") @PathVariable String repoIdentifier,
@ApiParam(name = "fileName", value = "流水线文件名") @PathVariable String fileName) {
return success(pmsCiPipelinesService.getPipelineId(repoOwner, repoIdentifier, fileName));
}
}

View File

@ -0,0 +1,53 @@
package com.microservices.pms.pipeline.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 流水线卡片执行详情对象
*
* @author xxq
* @date 2025-01-23
*/
@Data
@ApiModel("流水线卡片执行详情对象")
public class PmsCiPipelinesCardRunVo {
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "总执行数量")
private Long total;
@ApiModelProperty(value = "成功执行数量")
private Long success;
@ApiModelProperty(value = "失败执行数量")
private Long failure;
@ApiModelProperty(value = "是否定时任务")
private Boolean schedule;
@ApiModelProperty(value = "执行状态")
private Long status;
@ApiModelProperty(value = "开始时间")
private Long started;
@ApiModelProperty(value = "结束时间")
private Long stopped;
@ApiModelProperty(value = "执行时长")
private Long length;
@ApiModelProperty(value = "创建时间")
private Long created;
@ApiModelProperty(value = "更新时间")
private Long updated;
}

View File

@ -0,0 +1,43 @@
package com.microservices.pms.pipeline.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 流水线卡片详情对象 pms_ci_pipelines
*
* @author xxq
* @date 2025-01-23
*/
@Data
@ApiModel("流水线卡片详情对象")
public class PmsCiPipelinesCardVo {
private Long id;
/**
* 仓库owner
*/
@ApiModelProperty(value = "仓库owner")
private String owner;
/**
* 仓库标识
*/
@ApiModelProperty(value = "仓库标识")
private String repoIdentifier;
@ApiModelProperty(value = "仓库名")
private String repoName;
@ApiModelProperty(value = "url")
private String url;
@ApiModelProperty(value = "流水线列表")
private List<PmsCiPipelinesDetailVo> pipelinesList;
}

View File

@ -77,4 +77,6 @@ public class PmsCiPipelinesDetailVo
@ApiModelProperty(value = "流水线模板JSON")
private JSONObject pipelineTemplateJson;
@ApiModelProperty(value = "流水线执行详情")
private PmsCiPipelinesCardRunVo pmsCiPipelinesCardRunVo;
}

View File

@ -30,6 +30,7 @@ public interface PmsCiPipelinesMapper
* @return 流水线集合
*/
public List<PmsCiPipelines> selectPmsCiPipelinesList(PmsCiPipelines pmsCiPipelines);
public List<PmsCiPipelines> selectPmsCiPipelinesCardList(PmsCiPipelines pmsCiPipelines);
/**
* 新增流水线
@ -64,4 +65,6 @@ public interface PmsCiPipelinesMapper
public int deletePmsCiPipelinesByIds(Long[] ids);
int selectCountByPipelineNameAndRepoInfo(@Param("pipelineName") String pipelineName, @Param("owner") String owner, @Param("repoIdentifier") String repoIdentifier, @Param("branch") String branch);
PmsCiPipelines selectPmsCiPipelinesByRepoAndFileName(@Param("repoOwner") String repoOwner, @Param("repoIdentifier") String repoIdentifier, @Param("fileName") String fileName);
}

View File

@ -32,6 +32,7 @@ public interface IPmsCiPipelinesService
* @return 流水线集合
*/
public GenericsTableDataInfo<PmsCiPipelinesDetailVo> selectPmsCiPipelinesList(String enterpriseIdentifier, String pipelineName, Integer pipelineType);
public GenericsTableDataInfo<PmsCiPipelinesCardVo> selectPmsCiPipelinesCardList(String enterpriseIdentifier, String pipelineName, Integer pipelineType);
/**
* 新增流水线
@ -102,4 +103,8 @@ public interface IPmsCiPipelinesService
JSONObject runPipelineRunsJob(Long id, String workflow, String ref);
JSONObject getPipelineRunResults(Long id, String run);
JSONObject getPipelineRubyIdByJavaId(Long javaId);
JSONObject getPipelineId(String repoOwner, String repoIdentifier, String fileName);
}

View File

@ -8,6 +8,7 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -15,6 +16,7 @@ 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.core.utils.YamlValidatorUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.httpClient.domain.EntryDto;
import com.microservices.common.httpClient.domain.FileEntryDto;
@ -24,9 +26,11 @@ import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.pipeline.domain.PmsCiPipelineGraphics;
import com.microservices.pms.pipeline.domain.PmsCiPipelines;
import com.microservices.pms.pipeline.domain.vo.*;
import com.microservices.pms.pipeline.mapper.PmsCiPipelinesMapper;
import com.microservices.pms.pipeline.service.IPmsCiPipelineGraphicsService;
import com.microservices.pms.utils.PmsConstants;
import com.microservices.pms.pipeline.service.IPmsCiPipelinesService;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import com.microservices.pms.utils.YamlUtil;
import org.slf4j.Logger;
@ -34,12 +38,18 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.microservices.pms.pipeline.mapper.PmsCiPipelinesMapper;
import com.microservices.pms.pipeline.domain.PmsCiPipelines;
import com.microservices.pms.pipeline.service.IPmsCiPipelinesService;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.List;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.microservices.common.core.utils.JSONUtils.convertObjectToJSONObject;
import static com.microservices.common.core.utils.PageUtils.startPage;
@ -50,7 +60,7 @@ import static com.microservices.pms.utils.PmsConstants.*;
/**
* 流水线Service业务层处理
*
*
* @author wanjia
* @date 2024-03-02
*/
@ -110,6 +120,28 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
return toPage(pipelinesList, this::buildPmsCiPipelinesDetailVo);
}
/**
* 查询流水线卡片列表
*
* @param enterpriseIdentifier 企业标识
* @param pipelineName 流水线名
* @param pipelineType
* @return 流水线
*/
@Override
public GenericsTableDataInfo<PmsCiPipelinesCardVo> selectPmsCiPipelinesCardList(String enterpriseIdentifier, String pipelineName, Integer pipelineType) {
PmsEnterprise pmsEnterprise = pmsEnterpriseService.selectPmsEnterpriseByIdentifier(enterpriseIdentifier);
PmsCiPipelines pmsCiPipelines = new PmsCiPipelines();
pmsCiPipelines.setPipelineName(pipelineName);
pmsCiPipelines.setPmsEnterpriseId(pmsEnterprise.getId());
pmsCiPipelines.setPipelineType(pipelineType);
startPage();
List<PmsCiPipelines> pipelinesList = pmsCiPipelinesMapper.selectPmsCiPipelinesCardList(pmsCiPipelines);
String workflows = pipelinesList.size() == 0 ? "" : Optional.ofNullable(pipelinesList).orElse(Collections.emptyList()).stream().map(PmsCiPipelines::getFileName).collect(Collectors.joining(","));
List<PmsCiPipelinesCardRunVo> result = pipelinesList.size() == 0 ? Collections.emptyList() : gitLinkRequestHelper.doGetToObjectList(PmsGitLinkRequestUrl.GET_ACTION_RUN_DATA(pipelinesList.get(0).getOwner(), workflows), PmsCiPipelinesCardRunVo.class);
return toPage(pipelinesList, x -> this.buildPmsCiPipelinesCardDetailVo(x, result));
}
private PmsCiPipelinesDetailVo buildPmsCiPipelinesDetailVo(PmsCiPipelines pmsCiPipelines) {
PmsCiPipelinesDetailVo pmsCiPipelinesDetailVo = new PmsCiPipelinesDetailVo();
BeanUtils.copyProperties(pmsCiPipelines, pmsCiPipelinesDetailVo);
@ -117,6 +149,20 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
return pmsCiPipelinesDetailVo;
}
private PmsCiPipelinesCardVo buildPmsCiPipelinesCardDetailVo(PmsCiPipelines pmsCiPipelines, List<PmsCiPipelinesCardRunVo> result) {
PmsCiPipelinesCardVo pmsCiPipelinesCardVo = new PmsCiPipelinesCardVo();
BeanUtils.copyProperties(pmsCiPipelines, pmsCiPipelinesCardVo);
pmsCiPipelinesCardVo.setUrl(EscapeUtil.removeExtraSlashOfUrl(gitLinkRequestHelper.gitLinkUrl + "/" + pmsCiPipelines.getOwner() + "/" + pmsCiPipelines.getRepoIdentifier()));
PmsCiPipelines queryCiPipelines = new PmsCiPipelines();
queryCiPipelines.setRepoIdentifier(pmsCiPipelines.getRepoIdentifier());
queryCiPipelines.setOwner(pmsCiPipelines.getOwner());
queryCiPipelines.setPmsEnterpriseId(pmsCiPipelines.getPmsEnterpriseId());
List<PmsCiPipelines> pipelinesList = pmsCiPipelinesMapper.selectPmsCiPipelinesList(queryCiPipelines);
pmsCiPipelinesCardVo.setPipelinesList(Optional.ofNullable(pipelinesList).orElse(Collections.emptyList()).stream().map(this::buildPmsCiPipelinesDetailVo).collect(Collectors.toList()));
pmsCiPipelinesCardVo.getPipelinesList().forEach(x -> x.setPmsCiPipelinesCardRunVo(result.stream().filter(a -> a.getName().equals(x.getFileName())).findFirst().orElse(null)));
return pmsCiPipelinesCardVo;
}
/**
* 新增流水线
*
@ -404,9 +450,9 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
throw new ServiceException("该项目流水线不存在(流水线ID[%s])", id);
}
return gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.RERUN_PIPELINE_RUNS_JOB(pmsCiPipelines.getOwner(),
pmsCiPipelines.getRepoIdentifier(),
run,
job), null);
pmsCiPipelines.getRepoIdentifier(),
run,
job), null);
}
@Override
@ -416,9 +462,9 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
throw new ServiceException("该项目流水线不存在(流水线ID[%s])", id);
}
return gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.RUN_PIPELINE_RUNS_JOB(pmsCiPipelines.getOwner(),
pmsCiPipelines.getRepoIdentifier(),
workflow,
ref), null);
pmsCiPipelines.getRepoIdentifier(),
workflow,
ref), null);
}
@Override
@ -456,7 +502,7 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
throw new ServiceException("该项目流水线不存在(流水线ID[%s])", id);
}
try {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_PIPELINE_RUN_RESULTS(pmsCiPipelines.getOwner(),
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_PIPELINE_RUN_RESULTS(pmsCiPipelines.getOwner(),
pmsCiPipelines.getRepoIdentifier(),
run));
} catch (Exception e) {
@ -465,6 +511,39 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService {
}
}
@Override
public JSONObject getPipelineRubyIdByJavaId(Long javaId) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("pipelineRubyId", null);
PmsCiPipelines pmsCiPipelines = pmsCiPipelinesMapper.selectPmsCiPipelinesById(javaId);
if (pmsCiPipelines != null) {
JSONObject rubyResultData = gitLinkRequestHelper.doGet(
PmsGitLinkRequestUrl.GET_PIPELINE_ACTIONS(pmsCiPipelines.getOwner(), pmsCiPipelines.getRepoIdentifier(), pmsCiPipelines.getFileName()
));
if (rubyResultData != null) {
JSONArray rubyResultList = rubyResultData.getJSONArray("data");
if (!rubyResultList.isEmpty()) {
JSONObject rubyResult = rubyResultList.getJSONObject(0);
jsonObject.put("pipelineRubyId", rubyResult.getLong("id"));
}
}
}
return jsonObject;
}
@Override
public JSONObject getPipelineId(String repoOwner, String repoIdentifier, String fileName) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("pipelineId", null);
PmsCiPipelines pmsCiPipelines = pmsCiPipelinesMapper.selectPmsCiPipelinesByRepoAndFileName(repoOwner, repoIdentifier, fileName);
if (pmsCiPipelines == null) {
return jsonObject;
}
jsonObject.put("pipelineId", pmsCiPipelines.getId());
return jsonObject;
}
private void saveOrUpdateGraphicJsonToLocal(Long id, PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo) {
PmsCiPipelineGraphics existentialPmsCiPipelineGraphics = pmsCiPipelineGraphicsService.selectPmsCiPipelineGraphicsByPmsCiPipelineId(id);
PmsCiPipelineGraphics pmsCiPipelineGraphics = new PmsCiPipelineGraphics();

View File

@ -21,83 +21,77 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 产品计划Controller
* 产品里程碑Controller
*
* @author microservices
* @date 2023-10-10
*/
@RestController
@Api(tags = "项目管理-产品计划相关接口")
@Api(tags = "项目管理-产品里程碑相关接口")
@RequestMapping("/{enterpriseIdentifier}/pmsProductPlan")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class PmsProductPlanController extends BaseController
{
public class PmsProductPlanController extends BaseController {
@Autowired
private IPmsProductPlanService pmsProductPlanService;
/**
* 查询产品计划列表
* 查询产品里程碑列表
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/list")
@ApiOperation(value = "查询产品计划列表")
@ApiOperation(value = "查询产品里程碑列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "orderByColumn", value = "排序列开始时间startTime结束时间endTime产品需求数productRequirementCount优先级priorityId", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "isAsc", value = "排序的方向desc或者asc,默认asc", paramType = "query", dataType = "String")
})
public GenericsTableDataInfo<PmsProductPlanDataVo> list(@Validated PmsProductPlanSearchVo pmsProductPlanSearchVo)
{
public GenericsTableDataInfo<PmsProductPlanDataVo> list(@Validated PmsProductPlanSearchVo pmsProductPlanSearchVo) {
return pmsProductPlanService.selectPmsProductPlanList(pmsProductPlanSearchVo.toPmsProductPlan());
}
/**
* 获取产品计划详细信息
* 获取产品里程碑详细信息
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取产品计划详细信息")
public GenericsAjaxResult<PmsProductPlanDataVo> getInfo(@PathVariable("id") Long id)
{
@ApiOperation(value = "获取产品里程碑详细信息")
public GenericsAjaxResult<PmsProductPlanDataVo> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(pmsProductPlanService.selectPmsProductPlanDataById(id));
}
/**
* 新增产品计划
* 新增产品里程碑
*/
@RequiresPermissions("pms:pmsProductPlan:add")
@Log(title = "产品计划", businessType = BusinessType.INSERT)
@Log(title = "产品里程碑", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增产品计划")
public AjaxResult add(@RequestBody @Validated PmsProductPlanInputVo pmsProductPlanInputVo)
{
@ApiOperation(value = "新增产品里程碑")
public AjaxResult add(@RequestBody @Validated PmsProductPlanInputVo pmsProductPlanInputVo) {
return success(pmsProductPlanService.insertPmsProductPlan(pmsProductPlanInputVo.toPmsProductPlan()));
}
/**
* 修改产品计划
* 修改产品里程碑
*/
@RequiresPermissions("pms:pmsProductPlan:edit")
@Log(title = "产品计划", businessType = BusinessType.UPDATE)
@Log(title = "产品里程碑", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改产品计划")
public AjaxResult edit(@RequestBody @Validated PmsProductPlanUpdateVo pmsProductPlanUpdateVo)
{
@ApiOperation(value = "修改产品里程碑")
public AjaxResult edit(@RequestBody @Validated PmsProductPlanUpdateVo pmsProductPlanUpdateVo) {
return toAjax(pmsProductPlanService.updatePmsProductPlan(pmsProductPlanUpdateVo.toPmsProductPlan()));
}
/**
* 删除产品计划
* 删除产品里程碑
*/
@RequiresPermissions("pms:pmsProductPlan:remove")
@Log(title = "产品计划", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除产品计划")
public AjaxResult remove(@PathVariable Long[] ids)
{
@Log(title = "产品里程碑", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除产品里程碑")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(pmsProductPlanService.deletePmsProductPlanByIds(ids));
}
}

View File

@ -1,145 +0,0 @@
package com.microservices.pms.product.controller;
import com.alibaba.fastjson2.JSONObject;
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.Logical;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductModuleService;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import io.swagger.annotations.*;
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 2023-10-10
*/
@RestController
@Api(tags = "项目管理-产品需求相关接口")
@RequestMapping("/{enterpriseIdentifier}/pmsProductRequirement")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class PmsProductRequirementController extends BaseController
{
@Autowired
private IPmsProductRequirementService pmsProductRequirementService;
@Autowired
private IPmsProductModuleService pmsProductModuleService;
/**
* 查询产品需求列表
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/list")
@ApiOperation(value = "查询产品需求列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "orderByColumn", value = "排序列更新时间updateTime创建时间createTime,优先级priorityId开始时间startTime结束时间endTime", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "isAsc", value = "排序的方向desc或者asc,默认asc", paramType = "query", dataType = "String")
})
public GenericsTableDataInfo<PmsProductRequirementDataVo> list(@Validated PmsProductRequirementSearchVo pmsProductRequirementSearchVo)
{
PmsProductRequirement pmsProductRequirementSearch=pmsProductRequirementSearchVo.toPmsProductRequirement();
if (pmsProductRequirementSearch.getPmsProductModuleId() != null && pmsProductRequirementSearch.getPmsProductModuleId() != 0) {
List<Long> moduleIdList=pmsProductModuleService.selectChildrenPmsProductModuleIdList(pmsProductRequirementSearch.getPmsProductModuleId());
pmsProductRequirementSearch.setChildrenModuleIdList(moduleIdList);
}
return pmsProductRequirementService.selectPmsProductRequirementPageList(pmsProductRequirementSearch);
}
/**
* 获取产品需求详细信息
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取产品需求详细信息")
public GenericsAjaxResult<PmsProductRequirementDetailVo> getInfo(@PathVariable("id") Long id)
{
return genericsSuccess(pmsProductRequirementService.selectPmsProductRequirementDetailById(id));
}
/**
* 根据产品标识和需求索引获取产品需求详细信息
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping(value = "/ProductIdentifier/{productIdentifier}/index/{index}")
@ApiOperation(value = "根据产品标识和需求索引获取产品需求详细信息")
public GenericsAjaxResult<PmsProductRequirementDetailVo> getInfo(@PathVariable("productIdentifier") String productIdentifier, @PathVariable("index") Long index)
{
return genericsSuccess(pmsProductRequirementService.selectPmsProductRequirementDetailByProductIdentifierAndIndex(productIdentifier, index));
}
/**
* 新增产品需求
*/
@RequiresPermissions("pms:pmsProductRequirement:add")
@Log(title = "产品需求", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增产品需求")
public AjaxResult add(@RequestBody @Validated PmsProductRequirementInputVo pmsProductRequirementInputVo)
{
return success(pmsProductRequirementService.insertPmsProductRequirement(pmsProductRequirementInputVo.toPmsProductRequirement()));
}
/**
* 修改产品需求
*/
@RequiresPermissions(value = {"pms:pmsProductRequirement:edit", "pms:pmsProductPlan:edit"}, logical = Logical.OR)
@Log(title = "产品需求", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改产品需求")
public AjaxResult edit(@RequestBody @Validated PmsProductRequirementUpdateVo pmsProductRequirementUpdateVo)
{
return toAjax(pmsProductRequirementService.updatePmsProductRequirement(pmsProductRequirementUpdateVo.toPmsProductRequirement()));
}
/**
* 批量修改产品需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "产品需求", businessType = BusinessType.UPDATE)
@PutMapping("/batch")
@ApiOperation(value = "批量修改产品需求")
public AjaxResult batchEdit(
@ApiParam(name = "pmsProductRequirementBatchUpdateVo",
value = "【字段说明】(非必填字段不传递则代表不更新传null则代表置空):\n" +
"idList:需求Id列表必填,示例:[1,2,3];\n" +
"priorityId:关联优先级ID;\n" +
"statusId:关联状态ID;\n" +
"pmsProductModuleId:关联产品模块ID;\n" +
"pmsProductPlanId:关联产品计划ID;\n" +
"tags:标记Id列表使用逗号分割的字符串;\n" +
"requirementAssigneeGitlinkIds:需求负责人Gitlink ID列表逗号分隔;\n" +
"pmsProjectId:关联项目ID\n")
@RequestBody JSONObject pmsProductRequirementBatchUpdateVo)
{
return toAjax(pmsProductRequirementService.batchUpdatePmsProductRequirement(pmsProductRequirementBatchUpdateVo));
}
/**
* 删除产品需求
*/
@RequiresPermissions("pms:pmsProductRequirement:remove")
@Log(title = "产品需求", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除产品需求")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(pmsProductRequirementService.deletePmsProductRequirementByIds(ids));
}
}

View File

@ -0,0 +1,171 @@
package com.microservices.pms.product.controller;
import com.alibaba.fastjson2.JSONObject;
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.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.project.domain.PmsProject;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 产品需求相关接口
*
* @author otto
* @date 2023-10-10
*/
@RestController
@Api(tags = "项目管理-需求相关接口")
@RequestMapping("/{enterpriseIdentifier}/productRequirementSpecs")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class ProductReqSpecsController extends BaseController {
@Autowired
private IPmsProductRequirementService pmsProductRequirementService;
/**
* 查询产品需求列表
*/
@ApiOperation(value = "查询需求列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/list")
public GenericsTableDataInfo<ProductReqSpecsDataVo> list(@PathVariable String enterpriseIdentifier, @Validated ProductReqSpecsSearchVo productReqSpecsSearchVo) {
return pmsProductRequirementService.selectReqSpecsList(productReqSpecsSearchVo);
}
/**
* 获取需求详细信息
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取需求详细信息")
public GenericsAjaxResult<ProductReqSpecsDetailVo> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(pmsProductRequirementService.selectReqSpecsDetailById(id));
}
/**
* 新增需求
*/
@RequiresPermissions("pms:pmsProductRequirement:add")
@Log(title = "需求", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增需求")
public AjaxResult add(@PathVariable String enterpriseIdentifier,
@RequestBody @Validated ProductReqSpecsInputVo productReqSpecsInputVo) {
productReqSpecsInputVo.setEnterpriseIdentifier(enterpriseIdentifier);
return success(pmsProductRequirementService.insertReqSpecs(productReqSpecsInputVo));
}
/**
* 修改需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改需求")
public AjaxResult edit(@RequestBody @Validated ProductReqSpecsUpdateVo productReqSpecsUpdateVo) {
return toAjax(pmsProductRequirementService.updateReqSpecs(productReqSpecsUpdateVo));
}
/**
* 变更需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求", businessType = BusinessType.UPDATE)
@PutMapping("/change")
@ApiOperation(value = "变更需求")
public AjaxResult change(@RequestBody @Validated ProductReqSpecsChangeVo productReqSpecsChangeVo) {
return toAjax(pmsProductRequirementService.changeReqSpecs(productReqSpecsChangeVo));
}
/**
* 删除需求
*/
@RequiresPermissions("pms:pmsProductRequirement:remove")
@Log(title = "需求", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除需求")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(pmsProductRequirementService.deleteReqSpecsByIds(ids));
}
/**
* 评审需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求", businessType = BusinessType.UPDATE)
@PutMapping("/review")
@ApiOperation(value = "评审需求")
public AjaxResult review(@RequestBody @Validated ProductReqReviewVo productReqReviewVo) {
return toAjax(pmsProductRequirementService.reviewReqSpecs(productReqReviewVo));
}
/**
* 需求纳入计划
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求", businessType = BusinessType.UPDATE)
@PutMapping("/activePlan")
@ApiOperation(value = "需求纳入计划")
public AjaxResult activePlan(@RequestBody @Validated ProductReqSpecsActivePlanVo productReqSpecsActivePlanVo) {
return toAjax(pmsProductRequirementService.activePlan(productReqSpecsActivePlanVo));
}
/**
* 纳入计划时可选择项目列表
*/
@ApiOperation(value = "纳入计划时可选择项目列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{productIdentifier}/projectList")
public List<PmsProject> projectList(@PathVariable("productIdentifier") String productIdentifier) {
return pmsProductRequirementService.selectReqSpecsProjectList(productIdentifier);
}
/**
* 查询需求状态列表
*/
@ApiOperation(value = "查询需求状态列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/statusList")
public List<ReqStatusCommonVo> statusList() {
return pmsProductRequirementService.selectReqSpecsStatusList();
}
/**
* 查询需求类型列表
*/
@ApiOperation(value = "查询需求类型列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/typeList")
public List<EnumCommonVo> typeList() {
return pmsProductRequirementService.selectReqSpecsTypeList();
}
/**
* 批量修改产品需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求", businessType = BusinessType.UPDATE)
@PutMapping("/batch")
@ApiOperation(value = "批量修改产品需求")
public AjaxResult batchEdit(
@ApiParam(name = "pmsProductRequirementBatchUpdateVo",
value = "【字段说明】(非必填字段不传递则代表不更新传null则代表置空):\n" +
"idList:需求Id列表必填,示例:[1,2,3];\n" +
"pmsProductModuleId:关联产品模块ID;\n" +
"pmsProductPlanId:关联产品里程碑ID;\n")
@RequestBody JSONObject pmsProductRequirementBatchUpdateVo) {
return toAjax(pmsProductRequirementService.batchUpdatePmsProductRequirement(pmsProductRequirementBatchUpdateVo));
}
}

View File

@ -0,0 +1,80 @@
package com.microservices.pms.product.controller;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.pms.product.domain.vo.ProductReqOperationRecordDataVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsAssociatedTestcaseDataVo;
import com.microservices.pms.product.service.IPmsProductReqOperationRecordService;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.project.service.IPmsProjectTestcaseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 产品需求相关接口
*
* @author otto
* @date 2023-10-10
*/
@RestController
@Api(tags = "项目管理-需求跟踪相关接口")
@RequestMapping("/{enterpriseIdentifier}/productRequirementTracking")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class ProductReqTrackingController extends BaseController {
@Autowired
private IPmsProductReqOperationRecordService pmsProductReqOperationRecordService;
@Autowired
private IPmsProjectTestcaseService pmsProjectTestcaseService;
@Autowired
private IPmsProductRequirementService pmsProductRequirementService;
/**
* 查询原始需求变更记录
*/
@ApiOperation(value = "查询原始需求变更记录")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{userReqId}/userReqChangeRecord")
public GenericsTableDataInfo<ProductReqOperationRecordDataVo> getUserReqChangeRecordList(
@PathVariable("userReqId") Long userReqId) {
return getGenericsDataTable(pmsProductReqOperationRecordService.selectUserReqChangeRecordList(userReqId));
}
/**
* 查询原始需求变更记录
*/
@ApiOperation(value = "查询需求变更记录")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{reqSpecsId}/reqSpecsChangeRecord")
public GenericsTableDataInfo<ProductReqOperationRecordDataVo> getReqSpecsChangeRecordList(
@PathVariable("reqSpecsId") Long reqSpecsId) {
return getGenericsDataTable(pmsProductReqOperationRecordService.selectReqSpecsChangeRecordList(reqSpecsId));
}
@ApiOperation(value = "查询需求关联的测试用例")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{reqSpecsId}/associatedTestcase")
public GenericsTableDataInfo<ProductReqSpecsAssociatedTestcaseDataVo> getReqSpecsAssociatedTestcaseList(
@PathVariable("reqSpecsId") Long reqSpecsId) {
return getGenericsDataTable(pmsProjectTestcaseService.selectReqSpecsAssociatedTestcaseList(reqSpecsId));
}
@ApiOperation(value = "查询需求关联的计划")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{reqSpecsId}/associatedPlan")
public GenericsAjaxResult<JSONObject> getReqSpecsAssociatedPlanData(
@PathVariable("reqSpecsId") Long reqSpecsId) {
return GenericsAjaxResult.success(pmsProductRequirementService.selectReqSpecsAssociatedPlanData(reqSpecsId));
}
}

View File

@ -0,0 +1,113 @@
package com.microservices.pms.product.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.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 产品原始需求相关接口
*
* @author otto
* @date 2023-10-10
*/
@RestController
@Api(tags = "项目管理-原始需求相关接口")
@RequestMapping("/{enterpriseIdentifier}/productUserRequirement")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class ProductUserReqController extends BaseController {
@Autowired
private IPmsProductRequirementService pmsProductRequirementService;
/**
* 查询产品原始需求列表
*/
@ApiOperation(value = "查询原始需求列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/list")
public GenericsTableDataInfo<ProductUserReqDataVo> list(@Validated ProductUserReqSearchVo productUserReqSearchVo) {
return pmsProductRequirementService.selectUserReqList(productUserReqSearchVo);
}
/**
* 获取原始需求详细信息
*/
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取原始需求详细信息")
public GenericsAjaxResult<ProductUserReqDetailVo> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(pmsProductRequirementService.selectUserReqDetailById(id));
}
/**
* 新增原始需求
*/
@RequiresPermissions("pms:pmsProductRequirement:add")
@Log(title = "原始需求", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation(value = "新增原始需求")
public AjaxResult add(@PathVariable String enterpriseIdentifier,
@RequestBody @Validated ProductUserReqInputVo productUserReqInputVo) {
productUserReqInputVo.setEnterpriseIdentifier(enterpriseIdentifier);
return success(pmsProductRequirementService.insertUserReq(productUserReqInputVo));
}
/**
* 修改原始需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "原始需求", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "修改原始需求")
public AjaxResult edit(@RequestBody @Validated ProductUserReqUpdateVo productUserReqUpdateVo) {
return toAjax(pmsProductRequirementService.updateUserReq(productUserReqUpdateVo));
}
/**
* 删除原始需求
*/
@RequiresPermissions("pms:pmsProductRequirement:remove")
@Log(title = "原始需求", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation(value = "删除原始需求")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(pmsProductRequirementService.deleteUserReqByIds(ids));
}
/**
* 评审原始需求
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "原始需求", businessType = BusinessType.UPDATE)
@PutMapping("/review")
@ApiOperation(value = "评审原始需求")
public AjaxResult review(@RequestBody @Validated ProductReqReviewVo productReqReviewVo) {
return toAjax(pmsProductRequirementService.reviewUserReq(productReqReviewVo));
}
/**
* 查询原始需求状态列表
*/
@ApiOperation(value = "查询原始需求状态列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/statusList")
public List<ReqStatusCommonVo> statusList() {
return pmsProductRequirementService.selectUserReqStatusList();
}
}

View File

@ -66,16 +66,13 @@ public class PmsProduct extends BaseEntity
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 预留字段1 */
@ApiModelProperty(value = "自定义标识")
private String customIdentifier;
@ApiModelProperty(value = "预留字段1")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField1;
/** 预留字段2 */
@ApiModelProperty(value = "预留字段2")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField2;
public PmsProductDataVo toPmsProductDataVo() {
PmsProductDataVo target = new PmsProductDataVo();

View File

@ -83,6 +83,9 @@ public class PmsProductModule extends BaseEntity
@ApiModelProperty(value = "关联项目ID")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Long pmsProjectId;
@ApiModelProperty(value = "是否为固定模块")
private Boolean isFixedModule;
/**
* 子模块
*/

View File

@ -12,22 +12,26 @@ import lombok.Data;
import java.util.Date;
/**
* 产品计划对象 pms_product_plan
* 产品里程碑对象 pms_product_plan
*
* @author microservices
* @date 2023-10-10
*/
@Data
@ApiModel("产品计划对象")
@ApiModel("产品里程碑对象")
public class PmsProductPlan extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 产品计划ID */
/**
* 产品里程碑ID
*/
private Long id;
/** 计划标题 */
@ApiModelProperty(value = "计划标题")
/**
* 里程碑标题
*/
@ApiModelProperty(value = "里程碑标题")
private String planTitle;
/** 关联产品标识 */
@ -52,8 +56,10 @@ public class PmsProductPlan extends BaseEntity
@ApiModelProperty(value = "结束时间")
private Date endTime;
/** 计划描述 */
@ApiModelProperty(value = "计划描述")
/**
* 里程碑描述
*/
@ApiModelProperty(value = "里程碑描述")
private String planDescription;
/** 工作量 */

View File

@ -26,8 +26,10 @@ public class PmsProductPriority extends BaseEntity
@ApiModelProperty(value = "优先级名称")
private String name;
/** 优先级类型1产品计划 2产品需求 */
@ApiModelProperty(value = "优先级类型1=产品计划,2=产品需求)")
/**
* 优先级类型1产品里程碑 2产品需求
*/
@ApiModelProperty(value = "优先级类型1=产品里程碑,2=产品需求)")
private Integer type;
/** 删除标志0代表存在 2代表删除 */

View File

@ -0,0 +1,79 @@
package com.microservices.pms.product.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.microservices.common.core.web.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 项目管理-产品需求操作记录对象 pms_product_req_operation_record
*
* @author otto
* @date 2024-11-29
*/
@Data
public class PmsProductReqOperationRecord extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 操作记录ID
*/
private Long id;
/**
* 操作人用户名
*/
@ApiModelProperty(value = "操作人用户名")
private String operator;
/**
* 类型
*/
@ApiModelProperty(value = "类型")
private String type;
/**
* 操作
*/
@ApiModelProperty(value = "操作")
private String operation;
/**
* 操作时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "操作时间")
private Date operatingTime;
/**
* 关联需求ID
*/
@ApiModelProperty(value = "关联需求ID")
private Long productRequirementId;
/**
* 操作内容
*/
@ApiModelProperty(value = "操作内容")
private String content;
/**
* 删除标志0代表存在 2代表删除
*/
private String delFlag;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField1;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField2;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField3;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField4;
}

View File

@ -2,9 +2,14 @@ package com.microservices.pms.product.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.web.domain.BaseEntity;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.domain.vo.PmsProductRequirementDataVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsChangeVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsDataVo;
import com.microservices.pms.product.domain.vo.ProductUserReqDataVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -35,9 +40,8 @@ public class PmsProductRequirement extends BaseEntity
@ApiModelProperty(value = "标题")
private String title;
/** 关联状态ID */
@ApiModelProperty(value = "关联状态ID")
private Long statusId;
@ApiModelProperty(value = "产品需求状态")
private String status;
/** 关联优先级ID */
@ApiModelProperty(value = "关联优先级ID")
@ -47,8 +51,10 @@ public class PmsProductRequirement extends BaseEntity
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
/** 关联产品计划ID */
@ApiModelProperty(value = "关联产品计划ID")
/**
* 关联产品里程碑ID
*/
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
/** 关联产品标识 */
@ -115,7 +121,7 @@ public class PmsProductRequirement extends BaseEntity
private Long pmsProjectId;
/** 关联项目ID */
@ApiModelProperty(value = "关联项目ID")
@ApiModelProperty(value = "关联模块ID")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Long> childrenModuleIdList;
@ -124,9 +130,78 @@ public class PmsProductRequirement extends BaseEntity
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<String> productIdentifierList;
/**
* 原需求id
*/
@ApiModelProperty(value = "原需求id")
private Long fromId;
/**
* 原需求id
*/
@ApiModelProperty(value = "关联项目需求id")
private Long projectReqId;
@ApiModelProperty(value = "产品需求类型")
private String type;
@ApiModelProperty(value = "需求来源用户")
private String sourceUser;
@ApiModelProperty(value = "需求来源单位")
private String sourceCompany;
@ApiModelProperty(value = "需求标识")
private String identifier;
@ApiModelProperty(value = "评审时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date reviewTime;
@ApiModelProperty(value = "评审内容")
private String reviewContent;
public PmsProductRequirementDataVo toPmsProductRequirementDataVo(){
PmsProductRequirementDataVo target = new PmsProductRequirementDataVo();
BeanUtils.copyProperties(this, target);
return target;
}
public ProductUserReqDataVo toProductUserReqDataVo() {
ProductUserReqDataVo target = new ProductUserReqDataVo();
BeanUtils.copyProperties(this, target);
return target;
}
public ProductReqSpecsDataVo toProductReqSpecsDataVo() {
ProductReqSpecsDataVo target = new ProductReqSpecsDataVo();
BeanUtils.copyProperties(this, target);
return target;
}
public PmsProductRequirement userReqToReqSpecs() {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
target.setId(null);
target.setFromId(this.id);
target.setStatus(ProductReqStatus.REVIEWED_REQ_SPECS.getKey());
return target;
}
public PmsProductRequirement toChangeReqSpecs(ProductReqSpecsChangeVo productReqSpecsChangeVo) {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
target.setId(null);
target.setFromId(this.id);
target.setStatus(ProductReqStatus.CHANGING_REQ_SPECS.getKey());
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getTitle())) {
target.setTitle(productReqSpecsChangeVo.getTitle());
}
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getContent())) {
target.setContent(productReqSpecsChangeVo.getContent());
}
if (productReqSpecsChangeVo.getFileIdentifiers() != null) {
target.setFileIdentifiers(productReqSpecsChangeVo.getFileIdentifiers());
}
return target;
}
}

View File

@ -26,8 +26,10 @@ public class PmsProductStatus extends BaseEntity
@ApiModelProperty(value = "状态名称")
private String name;
/** 状态类型1产品计划 2产品需求 */
@ApiModelProperty(value = "状态类型1=产品计划,2=产品需求)")
/**
* 状态类型1产品里程碑 2产品需求
*/
@ApiModelProperty(value = "状态类型1=产品里程碑,2=产品需求)")
private Integer type;
/** 删除标志0代表存在 2代表删除 */

View File

@ -0,0 +1,32 @@
package com.microservices.pms.product.domain.enums;
import lombok.Getter;
/**
* 产品需求状态
*
* @author OTTO
*/
@Getter
public enum ProductContentModifyOperation {
CHANGING_REQ("changingReq", "进行需求变更"),
CANCEL_CHANGE_REQ("cancelChangeReq", "取消需求变更"),
CREATE("create", "创建"),
EDIT("edit", "编辑");
private final String key;
private final String name;
ProductContentModifyOperation(String key, String name) {
this.key = key;
this.name = name;
}
public static String getNameByKey(String key) {
for (ProductContentModifyOperation operation : ProductContentModifyOperation.values()) {
if (operation.getKey().equals(key)) {
return operation.getName();
}
}
return null;
}
}

View File

@ -0,0 +1,69 @@
package com.microservices.pms.product.domain.enums;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.system.api.domain.SimpleSysUser;
import lombok.Getter;
import java.text.SimpleDateFormat;
/**
* 产品需求操作类型
*
* @author OTTO
*/
@Getter
public enum ProductReqOperationType {
CONTENT_MODIFY("contentModify", "内容修改"),
REVIEW_USER_REQ("reviewUserReq", "原始需求评审"),
ACTIVE_PLAN("activePlan", "纳入计划"),
REVIEW_REQ_SPECS("reviewReqSpecs", "需求评审");
private final String key;
private final String name;
ProductReqOperationType(String key, String name) {
this.key = key;
this.name = name;
}
public static String genRecordStr(SimpleSysUser operator, PmsProductReqOperationRecord record) {
ProductReqOperationType type = getByKey(record.getType());
if (type == null) {
throw new ServiceException("需求操作记录类型错误");
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String operationTimeStr = formatter.format(record.getCreateTime());
switch (type) {
case CONTENT_MODIFY:
return String.format("%s由【%s】%s",
operationTimeStr,
operator.getNickName(),
ProductContentModifyOperation.getNameByKey(record.getOperation()));
case REVIEW_USER_REQ:
return String.format("%s由【%s】进行了原始需求评审评审结果为【%s】",
operationTimeStr,
operator.getNickName(),
ProductReqReviewStatus.getNameByKey(record.getOperation()));
case ACTIVE_PLAN:
return String.format("%s由【%s】将需求纳入了计划",
operationTimeStr,
operator.getNickName());
case REVIEW_REQ_SPECS:
return String.format("%s由【%s】进行了需求评审评审结果为【%s】",
operationTimeStr,
operator.getNickName(),
ProductReqReviewStatus.getNameByKey(record.getOperation()));
default:
throw new ServiceException("需求操作记录类型错误");
}
}
public static ProductReqOperationType getByKey(String key) {
for (ProductReqOperationType type : ProductReqOperationType.values()) {
if (type.getKey().equals(key)) {
return type;
}
}
return null;
}
}

View File

@ -0,0 +1,30 @@
package com.microservices.pms.product.domain.enums;
import lombok.Getter;
/**
* 产品需求状态
*
* @author OTTO
*/
@Getter
public enum ProductReqReviewStatus {
PASS("pass", "已通过"),
REJECTED("rejected", "未通过");
private final String key;
private final String name;
ProductReqReviewStatus(String key, String name) {
this.key = key;
this.name = name;
}
public static String getNameByKey(String operation) {
for (ProductReqReviewStatus status : values()) {
if (status.getKey().equals(operation)) {
return status.getName();
}
}
return null;
}
}

View File

@ -0,0 +1,42 @@
package com.microservices.pms.product.domain.enums;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.pms.product.domain.vo.EnumCommonVo;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
/**
* @author OTTO
*/
@Getter
public enum ProductReqSpecsType {
PERFORMANCE_REQ("performanceReq", "性能需求"),
FUNCTIONAL_REQ("functionalReq", "功能需求");
private final String key;
private final String name;
ProductReqSpecsType(String key, String name) {
this.key = key;
this.name = name;
}
public static void checkKey(String key) {
for (ProductReqSpecsType type : ProductReqSpecsType.values()) {
if (type.getKey().equals(key)) {
return;
}
}
throw new ServiceException("错误的需求类型(需求类型[%s])", key);
}
public static List<EnumCommonVo> getReqSpecsTypeList() {
List<EnumCommonVo> typeCommonVoList = new ArrayList<>();
for (ProductReqSpecsType productReqSpecsType : ProductReqSpecsType.values()) {
typeCommonVoList.add(new EnumCommonVo(productReqSpecsType.key, productReqSpecsType.name));
}
return typeCommonVoList;
}
}

View File

@ -0,0 +1,109 @@
package com.microservices.pms.product.domain.enums;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.pms.product.domain.vo.ReqStatusCommonVo;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
/**
* 产品需求状态
*
* @author OTTO
*/
@Getter
public enum ProductReqStatus {
PENDING_REVIEW_USER_REQ("pendingReviewUserReq", "待评审", "待评审的原始需求", "#FF6F00"),
REJECTED_USER_REQ("rejectedUserReq", "未通过", "已拒绝的原始需求", "#FF0000"),
REVIEWED_USER_REQ("reviewedUserReq", "已评审", "已评审的原始需求", "#13B33E"),
PENDING_REVIEW_REQ_SPECS("pendingReviewReqSpecs", "待评审", "待评审的需求", "#FF6F00"),
CHANGING_REQ_SPECS("changingReqSpecs", "变更中", "变更中的需求", "#FF0000"),
CHANGED_REQ_SPECS("changedReqSpecs", "已变更", "已变更的需求", null),
REJECTED_CHANGE_REQ_SPECS("rejectedChangeReqSpecs", "已拒绝变更", "已拒绝变更的需求", null),
REVIEWED_REQ_SPECS_CHANGING("reviewedReqSpecsChanging", "已评审(变更中)", "已评审的需求(变更中)", null),
PLANNED_REQ_SPECS_CHANGING("plannedReqSpecsChanging", "计划中(变更中)", "计划中的需求(变更中)", null),
PLANNED_REQ_SPECS("plannedReqSpecs", "计划中", "计划中的需求", "#0D5EF8"),
REJECTED_REQ_SPECS("rejectedReqSpecs", "已拒绝", "已拒绝的需求", "#B1AAA5"),
REVIEWED_REQ_SPECS("reviewedReqSpecs", "已评审", "已评审的需求", "#13B33E"),
COMPLETED_REQ_SPECS("completedReqSpecs", "已完成", "已完成的需求", "#13B33E");
private final String key;
private final String name;
private final String remark;
private final String color;
ProductReqStatus(String key, String name, String remark, String color) {
this.key = key;
this.name = name;
this.remark = remark;
this.color = color;
}
public static ProductReqStatus getByKey(String key) {
for (ProductReqStatus status : ProductReqStatus.values()) {
if (status.getKey().equals(key)) {
return status;
}
}
throw new ServiceException("需求状态错误(需求状态[%s])", key);
}
public static ReqStatusCommonVo getTypeByKey(String status) {
for (ProductReqStatus productReqStatus : ProductReqStatus.values()) {
if (productReqStatus.getKey().equals(status)) {
return new ReqStatusCommonVo(productReqStatus);
}
}
return null;
}
// 获取来源状态
public static ProductReqStatus getFromStatus(String status) {
ProductReqStatus productReqStatus = getByKey(status);
if (REVIEWED_REQ_SPECS_CHANGING == productReqStatus) {
return REVIEWED_REQ_SPECS;
} else if (PLANNED_REQ_SPECS_CHANGING == productReqStatus) {
return PLANNED_REQ_SPECS;
} else {
throw new ServiceException("获取需求的来源状态失败");
}
}
// 获取将改成的状态
public static ProductReqStatus getToStatus(String status) {
ProductReqStatus productReqStatus = getByKey(status);
if (REVIEWED_REQ_SPECS == productReqStatus) {
return REVIEWED_REQ_SPECS_CHANGING;
} else if (PLANNED_REQ_SPECS == productReqStatus) {
return PLANNED_REQ_SPECS_CHANGING;
} else {
throw new ServiceException("获取需求的更新状态失败");
}
}
public static boolean isUserReqStatus(String key) {
return PENDING_REVIEW_USER_REQ.getKey().equals(key)
|| REJECTED_USER_REQ.getKey().equals(key)
|| REVIEWED_USER_REQ.getKey().equals(key);
}
public static List<ReqStatusCommonVo> getUserReqStatusList() {
List<ReqStatusCommonVo> statusCommonVoList = new ArrayList<>();
for (ProductReqStatus productReqStatus : ProductReqStatus.values()) {
if (isUserReqStatus(productReqStatus.getKey()) && productReqStatus.getColor() != null) {
statusCommonVoList.add(new ReqStatusCommonVo(productReqStatus));
}
}
return statusCommonVoList;
}
public static List<ReqStatusCommonVo> getReqSpecsStatusList() {
List<ReqStatusCommonVo> statusCommonVoList = new ArrayList<>();
for (ProductReqStatus productReqStatus : ProductReqStatus.values()) {
if (!isUserReqStatus(productReqStatus.getKey()) && productReqStatus.getColor() != null) {
statusCommonVoList.add(new ReqStatusCommonVo(productReqStatus));
}
}
return statusCommonVoList;
}
}

View File

@ -0,0 +1,20 @@
package com.microservices.pms.product.domain.vo;
import lombok.Data;
/**
* @author OTTO
*/
@Data
public class EnumCommonVo {
protected String key;
protected String name;
public EnumCommonVo() {
}
public EnumCommonVo(String key, String name) {
this.key = key;
this.name = name;
}
}

View File

@ -48,6 +48,9 @@ public class PmsProductDataVo {
@ApiModelProperty(value = "产品标识")
private String productIdentifier;
@ApiModelProperty(value = "产品自定义标识")
private String customIdentifier;
/**
* 是否置顶0否1是
*/

View File

@ -7,6 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
@ -41,6 +42,11 @@ public class PmsProductInputVo
@ApiModelProperty(value = "关联企业标识", hidden = true)
private String pmsEnterpriseIdentifier;
@ApiModelProperty(value = "产品自定义标识", required = true)
@NotNull
@Size(max = 50, message = "长度需要小于50")
private String customIdentifier;
public PmsProduct toPmsProduct(String pmsEnterpriseIdentifier) {
PmsProduct target = new PmsProduct();
BeanUtils.copyProperties(this, target);

View File

@ -31,4 +31,7 @@ public class PmsProductModuleDataVo
/** 关联产品ID */
@ApiModelProperty(value = "关联产品ID")
private String pmsProductIdentifier;
@ApiModelProperty(value = "是否为固定模块")
private Boolean isFixedModule;
}

View File

@ -9,16 +9,18 @@ import lombok.Data;
import java.util.Date;
/**
* 产品计划对象 pms_product_plan
* 产品里程碑对象 pms_product_plan
*
* @author microservices
* @date 2023-10-10
*/
@Data
@ApiModel("产品计划数据对象")
@ApiModel("产品里程碑数据对象")
public class PmsProductPlanDataVo
{
/** 产品计划ID */
/**
* 产品里程碑ID
*/
private Long id;
/** 计划标题 */

View File

@ -13,13 +13,13 @@ import javax.validation.constraints.Size;
import java.util.Date;
/**
* 产品计划对象 pms_product_plan
* 产品里程碑对象 pms_product_plan
*
* @author microservices
* @date 2023-10-10
*/
@Data
@ApiModel("产品计划输入对象")
@ApiModel("产品里程碑输入对象")
public class PmsProductPlanInputVo
{

View File

@ -9,13 +9,13 @@ import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 产品计划对象 pms_product_plan
* 产品里程碑对象 pms_product_plan
*
* @author microservices
* @date 2023-10-10
*/
@Data
@ApiModel("产品计划搜索对象")
@ApiModel("产品里程碑搜索对象")
public class PmsProductPlanSearchVo
{
@ -28,9 +28,8 @@ public class PmsProductPlanSearchVo
@NotBlank(message = "产品标识不能为空")
private String pmsProductIdentifier;
/** 关联状态ID */
@ApiModelProperty(value = "关联状态ID")
private Long statusId;
@ApiModelProperty(value = "产品需求状态")
private String status;
/** 关联优先级ID */
@ApiModelProperty(value = "关联优先级ID")

View File

@ -12,18 +12,20 @@ import javax.validation.constraints.Size;
import java.util.Date;
/**
* 产品计划对象 pms_product_plan
* 产品里程碑对象 pms_product_plan
*
* @author microservices
* @date 2023-10-10
*/
@Data
@ApiModel("产品计划更新对象")
@ApiModel("产品里程碑更新对象")
public class PmsProductPlanUpdateVo
{
/** 产品计划ID */
/**
* 产品里程碑ID
*/
@NotNull
@ApiModelProperty(value = "产品计划ID")
@ApiModelProperty(value = "产品里程碑ID")
private Long id;
/** 计划标题 */

View File

@ -29,18 +29,15 @@ public class PmsProductRequirementBatchUpdateVo
private Long priorityId;
private Boolean priorityIdIsChange = false;
/** 关联状态ID */
@ApiModelProperty(value = "关联状态ID")
private Long statusId;
private Boolean statusIdIsChange = false;
/** 关联产品模块ID */
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
private Boolean pmsProductModuleIdIsChange = false;
/** 关联产品计划ID */
@ApiModelProperty(value = "关联产品计划ID")
/**
* 关联产品里程碑ID
*/
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
private Boolean pmsProductPlanIdIsChange = false;
@ -76,7 +73,6 @@ public class PmsProductRequirementBatchUpdateVo
public Boolean thisIsChange() {
return priorityIdIsChange
|| statusIdIsChange
|| pmsProductModuleIdIsChange
|| pmsProductPlanIdIsChange
|| tagIdsIsChange

View File

@ -5,6 +5,7 @@ import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.PmsProductModule;
import com.microservices.pms.product.domain.PmsProductPlan;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.project.domain.vo.BaseEntityVo;
import com.microservices.system.api.domain.SimpleSysUser;
import io.swagger.annotations.ApiModel;
@ -42,7 +43,7 @@ public class PmsProductRequirementDataVo extends BaseEntityVo
/** 关联状态 */
@ApiModelProperty(value = "关联状态")
private PmsTypeDataVo status;
private ProductReqStatus status;
/** 关联产品模块 */
@ApiModelProperty(value = "关联产品模块")
@ -53,9 +54,9 @@ public class PmsProductRequirementDataVo extends BaseEntityVo
private PmsProduct pmsProduct;
/**
* 关联产品计划
* 关联产品里程碑
*/
@ApiModelProperty(value = "关联产品计划")
@ApiModelProperty(value = "关联产品里程碑")
private PmsProductPlan pmsProductPlan;
/** 标记名称,使用逗号分割的字符 */

View File

@ -29,8 +29,8 @@ public class PmsProductRequirementDetailVo extends PmsProductRequirementDataVo
private List<SysFileInfo> fileList;
/**
* 关联产品计划
* 关联产品里程碑
*/
@ApiModelProperty(value = "关联产品计划")
@ApiModelProperty(value = "关联产品里程碑")
private PmsProductPlan pmsProductPlan;
}

View File

@ -38,7 +38,7 @@ public class PmsProductRequirementInputVo
private Long pmsProductModuleId;
/** 关联产品模块标识 */
@ApiModelProperty(value = "关联产品模块标识")
@ApiModelProperty(value = "关联产品标识")
@NotNull
private String pmsProductIdentifier;
@ -78,8 +78,10 @@ public class PmsProductRequirementInputVo
@ApiModelProperty(value = "关联项目ID")
private Long pmsProjectId;
/** 关联产品计划ID */
@ApiModelProperty(value = "关联产品计划ID")
/**
* 关联产品里程碑ID
*/
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
public PmsProductRequirement toPmsProductRequirement(){

View File

@ -26,8 +26,10 @@ public class PmsProductRequirementSearchVo
@ApiModelProperty(value = "关联产品模块ID传0查询不属于任何模块的需求")
private Long pmsProductModuleId;
/** 关联产品计划ID */
@ApiModelProperty(value = "关联产品计划ID")
/**
* 关联产品里程碑ID
*/
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
/** 关联产品模块标识 */
@ -39,9 +41,8 @@ public class PmsProductRequirementSearchVo
@ApiModelProperty(value = "需求负责人Gitlink ID")
private String requirementAssigneeGitlinkId;
/** 关联状态ID */
@ApiModelProperty(value = "关联状态ID")
private Long statusId;
@ApiModelProperty(value = "产品需求状态")
private String status;
/** 创建者 */
@ApiModelProperty(value = "发布者用户名")

View File

@ -34,16 +34,14 @@ public class PmsProductRequirementUpdateVo
@ApiModelProperty(value = "关联优先级ID")
private Long priorityId;
/** 关联状态ID */
@ApiModelProperty(value = "关联状态ID")
private Long statusId;
/** 关联产品模块ID */
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
/** 关联产品计划ID */
@ApiModelProperty(value = "关联产品计划ID")
/**
* 关联产品里程碑ID
*/
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
/** 正文 */

View File

@ -0,0 +1,18 @@
package com.microservices.pms.product.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel("我的产品统计对象")
public class PmsProductStatVo extends PmsProductDataVo{
@ApiModelProperty(value = "原始需求数量")
private Integer userReqCount;
@ApiModelProperty(value = "规格需求数量")
private Integer ReqSpecsCount;
}

View File

@ -0,0 +1,15 @@
package com.microservices.pms.product.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class PmsRequirementStatResVo {
@ApiModelProperty(value = "数据统计列表")
private List<ReqStatusStatVo> pmsProductStatVos;
@ApiModelProperty(value = "统计的比率")
private Integer ratio=0;
}

View File

@ -18,7 +18,7 @@ public class PmsTypeDataVo
@ApiModelProperty(value = "名称")
private String name;
/** 类型 */
@ApiModelProperty(value = "类型1=产品计划2=产品需求)")
@ApiModelProperty(value = "类型1=产品里程碑2=产品需求)")
private Integer type;
/** 颜色 */

View File

@ -20,7 +20,7 @@ import javax.validation.constraints.NotNull;
public class PmsTypeSearchVo
{
/** 类型 */
@ApiModelProperty(value = "类型1=产品计划2=产品需求)")
@ApiModelProperty(value = "类型1=产品里程碑2=产品需求)")
@NotNull
private Integer type;

View File

@ -0,0 +1,21 @@
package com.microservices.pms.product.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求变更记录数据对象")
public class ProductReqOperationRecordDataVo {
@ApiModelProperty(value = "操作记录")
private String record;
@ApiModelProperty(value = "操作内容内容为JSON字符串")
private String content;
}

View File

@ -0,0 +1,74 @@
package com.microservices.pms.product.domain.vo;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求评审对象")
public class ProductReqReviewVo {
@ApiModelProperty(value = "需求Id", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "评审状态", required = true)
@NotNull
private String reviewStatus;
@ApiModelProperty(value = "评审时间(前端默认取当前时间)", required = true)
@NotNull
private Date reviewTime;
@ApiModelProperty(value = "评审人", required = true)
@NotNull
@Size(max = 100, message = "长度需要小于100")
private String reviewUser;
@ApiModelProperty(value = "评审意见", required = true)
@NotNull
@Size(max = 1000, message = "长度需要小于1000")
private String reviewContent;
public PmsProductReqOperationRecord toUserReqRecord(String operator) {
PmsProductReqOperationRecord record = toRecord(operator);
record.setType(ProductReqOperationType.REVIEW_USER_REQ.getKey());
return record;
}
public PmsProductReqOperationRecord toReqSpecsRecord(String operator) {
PmsProductReqOperationRecord record = toRecord(operator);
record.setType(ProductReqOperationType.REVIEW_REQ_SPECS.getKey());
return record;
}
private PmsProductReqOperationRecord toRecord(String operator) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(id);
record.setOperation(reviewStatus);
record.setOperator(operator);
record.setOperatingTime(reviewTime);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String reviewTimeStr = formatter.format(reviewTime);
JSONObject contentJson = new JSONObject();
contentJson.put("reviewUser", reviewUser);
contentJson.put("reviewContent", reviewContent);
contentJson.put("reviewTime", reviewTimeStr);
record.setContent(contentJson.toJSONString());
return record;
}
}

View File

@ -0,0 +1,55 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.pms.enums.ProjectIssuePriority;
import com.microservices.pms.enums.ProjectIssueStatus;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import com.microservices.pms.project.domain.vo.PmsProjectIssuesInputVo;
import com.microservices.pms.utils.PmsConstants;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求纳入计划对象")
public class ProductReqSpecsActivePlanVo {
@ApiModelProperty(value = "需求Id", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "项目Id", required = true)
@NotNull
private Long projectId;
public PmsProjectIssuesInputVo toPmsProjectIssuesInputVo(PmsProductRequirement reqSpecs, List<String> forgeFileIdentifierList) {
PmsProjectIssuesInputVo issue = new PmsProjectIssuesInputVo();
issue.setSubject(reqSpecs.getTitle());
issue.setPmProjectId(projectId);
issue.setStatusId(ProjectIssueStatus.RESOLVING.getId());
issue.setPmIssueType(Integer.valueOf(PmsConstants.PROJECT_ISSUE_TYPE_REQUIREMENT));
issue.setPriorityId(ProjectIssuePriority.NORMAL.getId());
issue.setDescription(reqSpecs.getContent());
issue.setAttachmentIds(forgeFileIdentifierList);
return issue;
}
public PmsProductReqOperationRecord toPmsProductReqOperationRecord(PmsProductRequirement pmsProductRequirement) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(pmsProductRequirement.getId());
record.setType(ProductReqOperationType.ACTIVE_PLAN.getKey());
record.setOperation("激活");
record.setOperator(pmsProductRequirement.getUpdateBy());
record.setOperatingTime(pmsProductRequirement.getUpdateTime());
return record;
}
}

View File

@ -0,0 +1,55 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.pms.enums.TestCaseStatus;
import com.microservices.pms.project.domain.PmsProjectTestsheetCases;
import com.microservices.system.api.domain.SimpleSysUser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求关联测试用例数据对象")
public class ProductReqSpecsAssociatedTestcaseDataVo {
private Long id;
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "用例维护人")
private SimpleSysUser assigneeUser;
@ApiModelProperty(value = "执行次数")
private Long executeCount;
@ApiModelProperty(value = "未执行次数")
private Long unExecuteCount;
@ApiModelProperty(value = "通过次数")
private Long executePassCount;
@ApiModelProperty(value = "跳过次数")
private Long executeSkipCount;
@ApiModelProperty(value = "阻塞次数")
private Long executeBlockCount;
@ApiModelProperty(value = "失败次数")
private Long executeFailCount;
public void setCountData(List<PmsProjectTestsheetCases> testsheetCasesList) {
this.setUnExecuteCount(testsheetCasesList.stream().filter(x -> TestCaseStatus.INIT.ordinal() == x.getTestStatus().intValue()).count());
this.setExecutePassCount(testsheetCasesList.stream().filter(x -> TestCaseStatus.PASS.ordinal() == x.getTestStatus().intValue()).count());
this.setExecuteFailCount(testsheetCasesList.stream().filter(x -> TestCaseStatus.FAIL.ordinal() == x.getTestStatus().intValue()).count());
this.setExecuteBlockCount(testsheetCasesList.stream().filter(x -> TestCaseStatus.BLOCKING.ordinal() == x.getTestStatus().intValue()).count());
this.setExecuteSkipCount(testsheetCasesList.stream().filter(x -> TestCaseStatus.SKIP.ordinal() == x.getTestStatus().intValue()).count());
this.setExecuteCount((long) testsheetCasesList.size());
}
}

View File

@ -0,0 +1,67 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductContentModifyOperation;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Objects;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("变更需求变更对象")
public class ProductReqSpecsChangeVo {
@ApiModelProperty(value = "需求Id", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "标题")
@Size(max = 200, message = "长度需要小于200")
private String title;
@ApiModelProperty(value = "正文")
private String content;
@ApiModelProperty(value = "附件标识列表")
private String fileIdentifiers;
// 需求变更记录应记录在原需求下
public PmsProductReqOperationRecord toReqSpecsChangeRecord(Long oldReqSpecsId, PmsProductRequirement changeReqSpecs) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(oldReqSpecsId);
record.setType(ProductReqOperationType.CONTENT_MODIFY.getKey());
record.setOperation(ProductContentModifyOperation.CHANGING_REQ.getKey());
record.setOperator(changeReqSpecs.getUpdateBy());
record.setOperatingTime(changeReqSpecs.getUpdateTime());
return record;
}
public boolean isReqChange(PmsProductRequirement oldPmsProductRequirement) {
if (this.getContent() != null && !this.content.equals(oldPmsProductRequirement.getContent())) {
return true;
}
if (StringUtils.isNotEmpty(this.getTitle()) && !this.title.equals(oldPmsProductRequirement.getTitle())) {
return true;
}
return this.getFileIdentifiers() != null && !Objects.equals(this.getFileIdentifiers(), oldPmsProductRequirement.getFileIdentifiers());
}
public PmsProductRequirement toPmsProductRequirement() {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
return target;
}
}

View File

@ -0,0 +1,55 @@
package com.microservices.pms.product.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductModule;
import com.microservices.pms.product.domain.PmsProductPlan;
import com.microservices.system.api.domain.SimpleSysUser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求数据对象")
public class ProductReqSpecsDataVo {
private Long id;
@ApiModelProperty(value = "需求标识")
private String identifier;
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "需求状态")
private ReqStatusCommonVo status;
@ApiModelProperty(value = "产品需求类型")
private String type;
@ApiModelProperty(value = "创建人")
private SimpleSysUser createBy;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@ApiModelProperty(value = "关联产品模块")
private PmsProductModule pmsProductModule;
@ApiModelProperty(value = "关联产品里程碑")
private PmsProductPlan pmsProductPlan;
public ProductReqSpecsDetailVo toProductReqSpecsDetailVo() {
ProductReqSpecsDetailVo target = new ProductReqSpecsDetailVo();
BeanUtils.copyProperties(this, target);
return target;
}
}

View File

@ -0,0 +1,60 @@
package com.microservices.pms.product.domain.vo;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.system.api.domain.SimpleSysUser;
import com.microservices.system.api.domain.SysFileInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求详细数据对象")
public class ProductReqSpecsDetailVo extends ProductReqSpecsDataVo {
@ApiModelProperty(value = "正文")
private String content;
@ApiModelProperty(value = "附件列表")
private List<SysFileInfo> fileList;
@ApiModelProperty(value = "关联计划(原项目需求)")
private JSONObject projectIssue;
@ApiModelProperty(value = "关联项目")
private PmsProject project;
@ApiModelProperty(value = "创建人")
private SimpleSysUser createBy;
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "变更人")
private SimpleSysUser changeBy;
@ApiModelProperty(value = "变更")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date changeTime;
@ApiModelProperty(value = "评审时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date reviewTime;
@ApiModelProperty(value = "评审人")
private String reviewUser;
@ApiModelProperty(value = "评审意见")
private String reviewContent;
}

View File

@ -0,0 +1,69 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductContentModifyOperation;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
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;
/**
* 原始需求输入对象
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求输入对象")
public class ProductReqSpecsInputVo {
@ApiModelProperty(value = "标题", required = true)
@NotBlank
@Size(max = 200, message = "长度需要小于200")
private String title;
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
@ApiModelProperty(value = "关联产品标识", required = true)
@NotNull
private String pmsProductIdentifier;
@ApiModelProperty(value = "正文", required = true)
@NotBlank
private String content;
@ApiModelProperty(value = "附件标识列表")
private String fileIdentifiers;
@ApiModelProperty(value = "企业标识", hidden = true)
private String enterpriseIdentifier;
@ApiModelProperty(value = "产品需求类型")
private String type;
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
public PmsProductRequirement toPmsProductRequirement() {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
return target;
}
public PmsProductReqOperationRecord toPmsProductReqOperationRecord(PmsProductRequirement pmsProductRequirement) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(pmsProductRequirement.getId());
record.setType(ProductReqOperationType.CONTENT_MODIFY.getKey());
record.setOperation(ProductContentModifyOperation.CREATE.getKey());
record.setOperator(pmsProductRequirement.getCreateBy());
record.setOperatingTime(pmsProductRequirement.getCreateTime());
return record;
}
}

View File

@ -0,0 +1,57 @@
package com.microservices.pms.product.domain.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("原始需求搜索对象")
public class ProductReqSpecsSearchVo {
/**
* 标题
*/
@ApiModelProperty(value = "模糊搜索标题")
private String title;
/**
* 关联产品模块标识
*/
@ApiModelProperty(value = "关联产品标识", required = true)
@NotNull
private String pmsProductIdentifier;
@ApiModelProperty(value = "关联产品模块ID传0查询不属于任何模块的需求")
private Long pmsProductModuleId;
@ApiModelProperty(value = "关联产品里程碑ID")
private Long pmsProductPlanId;
@ApiModelProperty(value = "产品需求状态(全部状态请传空)(可通过逗号分割传多个状态)")
private String status;
@ApiModelProperty(value = "产品需求状态(数组)", hidden = true)
private String[] statusList;
@ApiModelProperty(value = "产品需求类型")
private String type;
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 关联项目ID
*/
@ApiModelProperty(value = "关联模块ID", hidden = true)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Long> childrenModuleIdList;
}

View File

@ -0,0 +1,47 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductContentModifyOperation;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("需求更新对象")
public class ProductReqSpecsUpdateVo extends ProductReqSpecsChangeVo {
@ApiModelProperty(value = "关联产品模块ID无论用户是否修改该字段前端均需要传值置空则传Null")
private Long pmsProductModuleId;
@ApiModelProperty(value = "产品需求类型")
private String type;
@ApiModelProperty(value = "关联产品里程碑ID无论用户是否修改该字段前端均需要传值置空则传Null")
private Long pmsProductPlanId;
public PmsProductReqOperationRecord toPmsProductReqOperationRecord(PmsProductRequirement pmsProductRequirement) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(pmsProductRequirement.getId());
record.setType(ProductReqOperationType.CONTENT_MODIFY.getKey());
record.setOperation(ProductContentModifyOperation.EDIT.getKey());
record.setOperator(pmsProductRequirement.getUpdateBy());
record.setOperatingTime(pmsProductRequirement.getUpdateTime());
return record;
}
public PmsProductRequirement toPmsProductRequirement() {
PmsProductRequirement target = super.toPmsProductRequirement();
BeanUtils.copyProperties(this, target);
return target;
}
}

View File

@ -0,0 +1,57 @@
package com.microservices.pms.product.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductModule;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("原始需求数据对象")
public class ProductUserReqDataVo {
private Long id;
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "需求状态")
private ReqStatusCommonVo status;
@ApiModelProperty(value = "从属产品模块")
private PmsProductModule pmsProductModule;
@ApiModelProperty(value = "需求来源用户")
private String sourceUser;
@ApiModelProperty(value = "需求来源单位")
private String sourceCompany;
@ApiModelProperty(value = "需求提出时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "评审时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date reviewTime;
@ApiModelProperty(value = "评审人")
private String reviewUser;
@ApiModelProperty(value = "评审意见")
private String reviewContent;
public ProductUserReqDetailVo toProductReqUserDetailVo() {
ProductUserReqDetailVo target = new ProductUserReqDetailVo();
BeanUtils.copyProperties(this, target);
return target;
}
}

View File

@ -0,0 +1,30 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.system.api.domain.SysFileInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("原始需求详细数据对象")
public class ProductUserReqDetailVo extends ProductUserReqDataVo {
/**
* 正文
*/
@ApiModelProperty(value = "正文")
private String content;
/**
* 附件列表
*/
@ApiModelProperty(value = "附件列表")
private List<SysFileInfo> fileList;
}

View File

@ -0,0 +1,86 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductContentModifyOperation;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
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;
/**
* 原始需求输入对象
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("原始需求输入对象")
public class ProductUserReqInputVo {
/**
* 标题
*/
@ApiModelProperty(value = "标题", required = true)
@NotBlank
@Size(max = 200, message = "长度需要小于200")
private String title;
/**
* 关联产品模块ID
*/
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
/**
* 关联产品模块标识
*/
@ApiModelProperty(value = "关联产品标识", required = true)
@NotNull
private String pmsProductIdentifier;
/**
* 正文
*/
@ApiModelProperty(value = "正文", required = true)
@NotBlank
private String content;
/**
* 附件标识列表
*/
@ApiModelProperty(value = "附件标识列表")
private String fileIdentifiers;
@ApiModelProperty(value = "需求来源用户(需前端默认填充当前用户昵称)", required = true)
@NotBlank
private String sourceUser;
@ApiModelProperty(value = "需求来源单位(需前端默认填充当前企业名称)", required = true)
@NotBlank
private String sourceCompany;
@ApiModelProperty(value = "企业标识", hidden = true)
private String enterpriseIdentifier;
public PmsProductRequirement toPmsProductRequirement() {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
return target;
}
public PmsProductReqOperationRecord toPmsProductReqOperationRecord(PmsProductRequirement pmsProductRequirement) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(pmsProductRequirement.getId());
record.setType(ProductReqOperationType.CONTENT_MODIFY.getKey());
record.setOperation(ProductContentModifyOperation.CREATE.getKey());
record.setOperator(pmsProductRequirement.getCreateBy().isEmpty() ? pmsProductRequirement.getSourceUser() : pmsProductRequirement.getCreateBy());
record.setOperatingTime(pmsProductRequirement.getCreateTime());
return record;
}
}

View File

@ -0,0 +1,33 @@
package com.microservices.pms.product.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("原始需求搜索对象")
public class ProductUserReqSearchVo {
/**
* 标题
*/
@ApiModelProperty(value = "模糊搜索标题、提出人或需求来源")
private String search;
/**
* 关联产品模块标识
*/
@ApiModelProperty(value = "关联产品标识", required = true)
@NotNull
private String pmsProductIdentifier;
@ApiModelProperty(value = "产品需求状态(全部状态请传空)")
private String status;
}

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