294 Commits

Author SHA1 Message Date
zhangkaihuai
4371ccb5e7 更新 .drone.yml 2025-06-14 15:25:22 +00:00
zhangkaihuai
f9ef5c7087 更新 .drone.yml 2025-06-14 15:20:57 +00:00
zhangkaihuai
f42eacd06e 更新 .drone.yml 2025-06-14 14:56:50 +00:00
861a6489c7 Merge pull request 'test : ci/cd' (#1080) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1080
2025-06-14 11:26:25 +00:00
dj
9133f7a7e3 test : ci/cd 2025-06-14 19:26:13 +08:00
e9be87990c Merge pull request '3' (#1079) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1079
2025-06-14 11:10:24 +00:00
dj
ec8db3c199 test : ci/cd 2025-06-14 19:09:36 +08:00
d2520336cb Merge pull request 'test : ci/cd' (#1078) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1078
2025-06-14 10:59:38 +00:00
dj
e97db1a70d test : ci/cd 2025-06-14 18:59:25 +08:00
afd27e38b5 Merge pull request 'test : ci/cd' (#1077) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1077
2025-06-14 10:50:02 +00:00
dj
7dd5120133 test : ci/cd 2025-06-14 18:49:22 +08:00
75da0633e5 Merge pull request 'test : ci/cd' (#1076) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1076
2025-06-14 10:43:23 +00:00
dj
41b498066f test : ci/cd 2025-06-14 18:43:10 +08:00
c852448089 Merge pull request 'test : ci/cd' (#1075) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1075
2025-06-14 10:40:34 +00:00
dj
9cd744d44e test : ci/cd 2025-06-14 18:40:23 +08:00
a7917137c9 Merge pull request 'test : ci/cd' (#1074) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1074
2025-06-14 10:30:29 +00:00
dj
85346fa343 test : ci/cd 2025-06-14 18:30:04 +08:00
e5b205870d Merge pull request 'test : ci/cd' (#1073) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1073
2025-06-14 10:26:12 +00:00
dj
5ae66763e1 test : ci/cd 2025-06-14 18:26:02 +08:00
9221d27960 Merge pull request 'test : ci/cd' (#1072) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1072
2025-06-14 10:23:34 +00:00
dj
c442b9b2fd test : ci/cd 2025-06-14 18:23:25 +08:00
25c94284ca Merge pull request 'test : ci/cd' (#1071) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1071
2025-06-14 10:18:34 +00:00
dj
5da74960f2 test : ci/cd 2025-06-14 18:18:22 +08:00
cdcb76d009 Merge pull request 'test : ci/cd' (#1070) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1070
2025-06-14 10:14:51 +00:00
dj
c87b5c57a6 test : ci/cd 2025-06-14 18:14:39 +08:00
fd0d70072b Merge pull request '4' (#1069) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1069
2025-06-14 09:39:44 +00:00
dj
747f675cfc test : ci/cd 2025-06-14 17:39:30 +08:00
941b06ab8b Merge pull request 'test : ci/cd' (#1068) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1068
2025-06-14 09:35:23 +00:00
dj
3e6f86abfd test : ci/cd 2025-06-14 17:35:12 +08:00
01ccc1ddcd Merge pull request '12' (#1067) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1067
2025-06-14 08:56:34 +00:00
dj
b6ac47e88b test : ci/cd 2025-06-14 16:56:18 +08:00
707486c69d Merge pull request 'test : ci/cd' (#1066) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1066
2025-06-14 08:50:34 +00:00
dj
2ef726b95b test : ci/cd 2025-06-14 16:50:17 +08:00
697af99240 Merge pull request 'test : ci/cd' (#1065) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1065
2025-06-14 08:46:41 +00:00
dj
ee2f7a9162 test : ci/cd 2025-06-14 16:45:18 +08:00
476f6a794d Merge pull request 'test : ci/cd' (#1064) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1064
2025-06-14 08:40:58 +00:00
dj
0c53ee8392 test : ci/cd 2025-06-14 16:40:48 +08:00
4c1e892d35 Merge pull request 'test : ci/cd' (#1063) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1063
2025-06-14 08:37:07 +00:00
dj
ac6d7863da test : ci/cd 2025-06-14 16:36:56 +08:00
ea33ffb60a Merge pull request 'test : ci/cd' (#1062) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1062
2025-06-14 08:31:16 +00:00
dj
a1ae39cbd7 test : ci/cd 2025-06-14 16:31:03 +08:00
0ada78f180 Merge pull request 'test : ci/cd' (#1061) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1061
2025-06-14 08:29:25 +00:00
dj
60e29aca8d test : ci/cd 2025-06-14 16:29:03 +08:00
3db2901a03 Merge pull request 'test : ci/cd' (#1060) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1060
2025-06-14 08:25:50 +00:00
dj
7428fe43d4 test : ci/cd 2025-06-14 16:25:38 +08:00
18592571a4 Merge pull request 'test : ci/cd' (#1059) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1059
2025-06-14 07:44:49 +00:00
dj
4bb03409f4 test : ci/cd 2025-06-14 15:42:17 +08:00
7fec9c5735 Merge pull request 'test : ci/cd 2' (#1058) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1058
2025-06-14 07:26:53 +00:00
dj
3d9f22d503 test : ci/cd 2 2025-06-14 15:26:40 +08:00
76c9a38718 Merge pull request 'test : ci/cd1' (#1057) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1057
2025-06-14 07:21:25 +00:00
dj
af7d0ac580 test : ci/cd1 2025-06-14 15:21:14 +08:00
4888a7e077 Merge pull request 'test : ci/cd' (#1056) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1056
2025-06-14 07:18:38 +00:00
dj
47a2f61036 test : ci/cd 2025-06-14 15:18:22 +08:00
f26e40df90 Merge pull request 'master' (#1055) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1055
2025-06-14 07:13:11 +00:00
dj
07103258f7 test : ci/cd 2025-06-14 15:12:49 +08:00
dj
8fa0d72cc4 test : ci/cd 2025-06-14 15:09:17 +08:00
7684444e93 Merge pull request 'test : ci/cd' (#1054) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1054
2025-06-14 07:05:25 +00:00
dj
81446971e5 test : ci/cd 2025-06-14 15:04:38 +08:00
5930a2c4b6 Merge pull request 'test : ci/cd' (#1053) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1053
2025-06-14 06:57:14 +00:00
dj
052c0090e3 test : ci/cd 2025-06-14 14:56:46 +08:00
d24892141a Merge pull request 'test : ci/cd' (#1052) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1052
2025-06-14 06:43:28 +00:00
dj
83dc28630b test : ci/cd 2025-06-14 14:43:10 +08:00
086fdb36e9 Merge pull request 'test : ci/cd' (#1051) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1051
2025-06-14 06:35:32 +00:00
dj
ba4c4fccdd test : ci/cd 2025-06-14 14:35:18 +08:00
bc79cfc0bc Merge pull request 'test : ci/cd' (#1050) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1050
2025-06-14 06:17:25 +00:00
dj
35d4d1b7ba test : ci/cd 2025-06-14 14:17:14 +08:00
71324efd0c Merge pull request 'test : 测试ci/cd-5' (#1049) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1049
2025-06-13 10:23:30 +00:00
dj
781e7393e8 test : 测试ci/cd-5 2025-06-13 18:22:50 +08:00
1eea7a377c Merge pull request 'test : 测试ci/cd-4' (#1048) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1048
2025-06-13 10:17:23 +00:00
dj
065eb6cfba test : 测试ci/cd-4 2025-06-13 18:17:01 +08:00
35a2f755a2 Merge pull request 'test : 测试ci/cd-3' (#1047) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1047
2025-06-13 10:10:41 +00:00
dj
9bd9cda872 test : 测试ci/cd-3 2025-06-13 18:10:24 +08:00
dd6181880a Merge pull request 'test : 测试ci/cd-2' (#1046) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1046
2025-06-13 09:59:51 +00:00
dj
cd2bfe8817 test : 测试ci/cd-2 2025-06-13 17:59:33 +08:00
8b6406c4e0 Merge pull request 'test : 测试ci/cd-1' (#1045) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1045
2025-06-13 09:50:39 +00:00
dj
fa3171fecd test : 测试ci/cd-1 2025-06-13 17:50:21 +08:00
177ccee058 Merge pull request 'test : 测试ci/cd' (#1044) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1044
2025-06-13 06:57:28 +00:00
dj
28de3667f5 test : 测试ci/cd 2025-06-13 14:57:15 +08:00
05a5385d87 Merge pull request 'test : 测试ci/cd' (#1043) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1043
2025-06-13 06:39:59 +00:00
dj
529f482bc7 test : 测试ci/cd 2025-06-13 14:39:23 +08:00
20fb592584 Merge pull request 'test : 测试ci/cd' (#1042) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1042
2025-06-13 06:23:55 +00:00
dj
bd35243cbd test : 测试ci/cd 2025-06-13 14:23:37 +08:00
d7ca84a4a0 Merge pull request 'master' (#1041) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1041
2025-06-13 06:19:11 +00:00
6c7eddcf94 Merge pull request 'test : 测试ci/cd' (#1040) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1040
2025-06-13 06:18:59 +00:00
3588257f61 revert 215f7c6bbf
revert feat(expense-management): 添加研发工时超过21.75天的提示功能

- 在保存分配明细时,增加对研发人员总工时的计算
- 如果总工时超过21.75天,系统将发出警告通知- 优化了控制台日志输出,便于调试和监控
2025-06-13 06:18:21 +00:00
6c47337318 Merge pull request 'revert 215f7c6bbf084b0bf6dbee1303a2539a3c21c3ad' (#1039) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1039
2025-06-13 06:14:59 +00:00
bacd397294 revert 215f7c6bbf
revert feat(expense-management): 添加研发工时超过21.75天的提示功能

- 在保存分配明细时,增加对研发人员总工时的计算
- 如果总工时超过21.75天,系统将发出警告通知- 优化了控制台日志输出,便于调试和监控
2025-06-13 06:14:19 +00:00
dj
b3dbb24bb2 test : 测试ci/cd 2025-06-13 14:11:25 +08:00
9e194f5f04 Merge pull request 'test : 测试ci/cd' (#1038) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1038
2025-06-12 07:29:49 +00:00
dj
f448ec47a3 test : 测试ci/cd 2025-06-12 15:26:52 +08:00
f633862434 Merge pull request 'test : 测试ci/cd' (#1037) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1037
2025-06-12 07:19:39 +00:00
dj
a4674d497b test : 测试ci/cd 2025-06-12 15:18:29 +08:00
e8aee6f01c Merge pull request 'test : 测试ci/cd' (#1036) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1036
2025-06-12 06:54:14 +00:00
dj
43e0f98509 test : 测试ci/cd 2025-06-12 14:53:52 +08:00
10b66cbf15 Merge pull request 'master' (#1035) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1035
2025-06-12 06:07:46 +00:00
dj
560bea739c test : 测试cicd 2025-06-12 14:07:25 +08:00
dj
1ed6156117 build(deps): 删除 moment 依赖 2025-06-12 12:08:41 +08:00
4321b42003 Merge pull request 'build(deps): 添加 moment 依赖' (#1034) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1034
2025-06-12 04:05:02 +00:00
dj
7f0f74c844 build(deps): 添加 moment 依赖 2025-06-12 12:04:11 +08:00
c1065cb084 Merge pull request 'refactor(components): 优化文件上传成功提示' (#1033) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1033
2025-06-12 03:42:56 +00:00
dj
579cadd687 refactor(components): 优化文件上传成功提示 2025-06-12 11:42:09 +08:00
78f4135efb Merge pull request 'build: 调整 package.json' (#1032) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1032
2025-06-12 03:29:12 +00:00
dj
1a120418f0 build: 调整 package.json 2025-06-12 11:28:25 +08:00
d3ae1c1205 Merge pull request 'build: 更新 Node.js 版本并调整 package.json 格式' (#1031) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1031
2025-06-12 03:16:06 +00:00
dj
e49b6ef1a3 build: 更新 Node.js 版本并调整 package.json 格式 2025-06-12 11:15:52 +08:00
6fbf37ab78 Merge pull request 'fix(ProjectAttachment): 修改drone' (#1030) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1030
2025-06-12 03:13:47 +00:00
dj
a0d9c58c77 fix(ProjectAttachment): 修改drone 2025-06-12 11:12:52 +08:00
b3900a2a1c Merge pull request 'fix(ProjectAttachment): 修改drone' (#1029) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1029
2025-06-12 03:08:20 +00:00
dj
4bb0c49dc8 fix(ProjectAttachment): 修改drone 2025-06-12 11:08:03 +08:00
4f6c36a20a Merge pull request 'fix(ProjectAttachment): 修改drone' (#1028) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1028
2025-06-12 02:17:12 +00:00
dj
aada3d785b fix(ProjectAttachment): 修改drone 2025-06-12 10:16:35 +08:00
fef4c57bd5 Merge pull request 'fix(ProjectAttachment): 添加依赖' (#1027) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1027
2025-06-12 02:04:22 +00:00
dj
35b332f640 fix(ProjectAttachment): 添加依赖 2025-06-12 10:03:57 +08:00
31da00d7e3 Merge pull request 'fix(ProjectAttachment): 添加依赖' (#1026) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1026
2025-06-12 01:36:07 +00:00
dj
6afac9be28 fix(ProjectAttachment): 添加依赖 2025-06-12 09:35:00 +08:00
b54289a0a5 Merge pull request 'fix(ProjectAttachment): 修改drone.yml' (#1025) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1025
2025-06-12 01:28:38 +00:00
dj
dc064de364 fix(ProjectAttachment): 修改drone.yml 2025-06-12 09:28:02 +08:00
7f656447b2 Merge pull request 'fix(ProjectAttachment): 修改drone.yml' (#1024) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1024
2025-06-12 01:25:35 +00:00
dj
78bafe0a7e fix(ProjectAttachment): 修改drone.yml 2025-06-12 09:24:29 +08:00
ddf5159fbc Merge pull request 'master' (#1023) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1023
2025-06-11 14:49:29 +00:00
dj
d0960f6ad6 feat(FileUpload): 实现多文件批量上传功能
- 添加自定义上传逻辑,支持多文件上传- 优化文件选择和上传流程,实现自动上传
-增加上传进度提示和完成通知
- 修复了一些与上传相关的小问题
2025-06-11 22:48:27 +08:00
dj
e7b982ef6c fix(ProjectAttachment): 移除未使用的上传附件相关代码 2025-06-11 16:34:59 +08:00
dj
b5ada3a1ac feat(FileUpload): 添加文件上传中的 loading 效果 2025-06-11 14:19:55 +08:00
418effdb04 Merge pull request 'feat(expense-management): 添加研发工时超过21.75天的提示功能' (#1022) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1022
2025-06-09 14:28:50 +00:00
dj
215f7c6bbf feat(expense-management): 添加研发工时超过21.75天的提示功能
- 在保存分配明细时,增加对研发人员总工时的计算
- 如果总工时超过21.75天,系统将发出警告通知- 优化了控制台日志输出,便于调试和监控
2025-06-09 22:28:24 +08:00
57a1d2700f Merge pull request 'refactor(expense-management): 注释掉研发人员重复性检查代码' (#1021) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1021
2025-06-08 15:11:01 +00:00
dj
e4025b90e9 refactor(expense-management): 注释掉研发人员重复性检查代码
- 在 add.vue 文件中,注释掉了两段用于检查研发人员重复性的代码
- 此修改可能是为了暂时禁用重复性检查功能,或者准备替换为新的检查逻辑
2025-06-08 23:08:02 +08:00
e44380c000 Merge pull request 'refactor(expense-management): 优化数字输入和附件处理' (#1020) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1020
2025-06-07 01:30:52 +00:00
dj
70d94f3c1d refactor(expense-management): 优化数字输入和附件处理
- 在 ProjectApply 组件中,将多个 el-input 组件替换为 el-input-number 组件,用于限制输入格式
- 在 ProjectAttachment 组件中,优化附件列表获取逻辑,实现附件去重功能
- 在 add.vue 文件中,启用 console.log 输出,用于调试项目 ID 和研发人员 ID 数组
2025-06-06 22:58:48 +08:00
14c6ed1168 Merge pull request 'fix : 修复归档附件bug' (#1019) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1019
2025-05-28 15:53:32 +00:00
dj
05275aed15 fix : 修复归档附件bug 2025-05-28 23:53:10 +08:00
47d5863361 Merge pull request 'fix : 修复归档附件bug' (#1018) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1018
2025-05-28 15:51:11 +00:00
dj
9758981d3f fix : 修复归档附件bug 2025-05-28 23:50:59 +08:00
a946247849 Merge pull request 'master' (#1017) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1017
2025-05-28 15:03:54 +00:00
dj
7c2d713035 fix(components): 优化多个组件的显示逻辑
- 在 ApprovalDetail组件中,改进了多个字段的显示逻辑,增加了对 0值的处理
- 在 AttachmentUpload 组件中,调整了必填项的显示逻辑
- 在 ProjectApply 组件中,修改了前置流程字段的显示条件
- 在 upload 组件中,优化了文件列表的处理逻辑
2025-05-28 23:01:16 +08:00
dj
f4330b60d5 refactor(ProjectApply): 优化归档附件上传逻辑 2025-05-28 16:50:55 +08:00
1a38381ab8 Merge pull request 'refactor(components): 调整文件上传大小限制并优化附件展示逻辑' (#1016) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1016
2025-05-23 01:08:02 +00:00
dj
f61d50dbfc refactor(components): 调整文件上传大小限制并优化附件展示逻辑 2025-05-23 09:07:02 +08:00
f5b9339b36 Merge pull request 'fix(ProjectAttachment): 重新获取附件列表' (#1015) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1015
2025-05-22 15:09:20 +00:00
dj
66dc6df0d9 fix(ProjectAttachment): 重新获取附件列表
在删除附件后,添加了重新获取附件列表的调用,以确保界面上的附件列表是最新的。
2025-05-22 23:08:27 +08:00
a3c7439a7f Merge pull request 'fix(ProjectAttachment): 修复删除附件后未及时更新文件列表的问题- 在删除文件后添加了更新文件列表的逻辑' (#1014) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1014
2025-05-22 14:57:02 +00:00
dj
c7329f2f6d fix(ProjectAttachment): 修复删除附件后未及时更新文件列表的问题- 在删除文件后添加了更新文件列表的逻辑
- 优化了获取本地文件列表的方法
- 调整了文件列表的初始化位置
2025-05-22 22:56:06 +08:00
59699b6118 Merge pull request 'feat(ProjectAttachment): 优化文件上传和管理功能' (#1013) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1013
2025-05-22 08:46:46 +00:00
dj
673e4fa20a feat(ProjectAttachment): 优化文件上传和管理功能
- 新增本地存储功能,暂存未提交的文件
- 优化文件删除逻辑,区分本地和服务器文件
- 添加提交按钮,将本地文件上传到服务器
- 调整标签切换时的文件列表显示逻辑
- 优化代码结构,提高可读性和可维护性
2025-05-22 16:45:58 +08:00
eb2a5581ca Merge pull request 'refactor(project-demand): 优化方案总结提交逻辑' (#1012) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1012
2025-05-22 02:09:05 +00:00
dj
ee5fc2cba3 refactor(project-demand): 优化方案总结提交逻辑
- 移除了不必要的空数组初始化
-简化了 requirementId 的赋值逻辑
- 添加了空行以提高代码可读性
2025-05-22 10:06:44 +08:00
952884a7fe Merge pull request 'fix(project-demand): 修复专项经费选择框逻辑' (#1011) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1011
2025-05-21 15:17:49 +00:00
dj
b7ca97696a fix(project-demand): 修复专项经费选择框逻辑
- 修改了专项经费选择逻辑,确保在选择专项经费时正确处理 specialFund 和 specialFundId 的值
- 优化了代码结构,提高了可读性和维护性
2025-05-21 23:14:00 +08:00
6ba9fa4bee Merge pull request 'master' (#1010) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1010
2025-05-21 14:39:55 +00:00
dj
baea68c52a Merge remote-tracking branch 'origin/master' 2025-05-21 22:39:08 +08:00
dj
a2ed04e144 refactor(project-demand): 优化加载状态管理
- 在获取数据失败时添加 loading.value = false,确保正确更新加载状态
2025-05-21 22:38:53 +08:00
8a218ad270 Merge pull request 'feat(project-demand): 编辑概览页面数据持久化' (#1009) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1009
2025-05-21 06:31:54 +00:00
dj
287d6a3ad0 feat(project-demand): 编辑概览页面数据持久化 2025-05-21 14:31:38 +08:00
9813f8c585 Merge pull request 'fix(project-demand): 修复专项基金选择问题' (#1008) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1008
2025-05-21 04:55:59 +00:00
dj
673a26368a fix(project-demand): 修复专项基金选择问题 2025-05-21 12:55:23 +08:00
9b90dbc649 Merge pull request 'feat(ProjectApply): 科技处用户申请项目时增加部门分管领导必选项' (#1007) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1007
2025-05-19 14:13:55 +00:00
dj
9adea1060c feat(ProjectApply): 科技处用户申请项目时增加部门分管领导必选项 2025-05-19 22:13:03 +08:00
4f471494cc Merge pull request 'refactor(permission): 优化面包屑控制逻辑' (#1006) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1006
2025-05-16 10:15:13 +00:00
dj
4e5a4bb4b9 refactor(permission): 优化面包屑控制逻辑 2025-05-16 18:14:31 +08:00
b4d6d97e27 Merge pull request 'fix : 修复需求上报缓存问题' (#1005) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1005
2025-05-15 08:06:29 +00:00
dj
a5ebab16a6 fix : 修复需求上报缓存问题 2025-05-15 16:06:04 +08:00
6ad76d1571 Merge pull request 'master' (#1004) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1004
2025-05-05 12:15:31 +00:00
dj
0cc1b63ae7 feat(project-management): 优化前置流程选择功能
- 在项目申请详情页面添加基本数据传递
- 实现前置流程的更改和选择功能
- 优化前置流程数据的存储和展示
- 添加对不可重复选择的前置流程的校验
2025-05-05 20:15:13 +08:00
dj
d76ef8ff9c feat(project-demand): 更新项目需求汇总功能
- 新增 getProjectName 方法,用于项目名称关键词匹配- 修改远程搜索方法,使用 getProjectName 替代 getRequirementName
- 更新 ProjectApply 组件,调整专项资金输入框显示逻辑
- 移除 proxy 配置中的注释
2025-05-05 17:53:55 +08:00
dj
f105485714 feat(project-demand): 添加项目名称远程搜索功能并优化前置流程显示逻辑
- 在项目需求概览页面添加项目名称远程搜索功能,提高搜索效率和准确性
- 优化项目申请详情页面的前置流程显示逻辑,根据不同场景调整标签宽度
2025-05-05 14:48:07 +08:00
df99acd638 Merge pull request 'fix : 修复公告问题' (#1003) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1003
2025-04-29 03:29:31 +00:00
dj
af275ea6c4 fix : 修复公告问题 2025-04-29 11:29:06 +08:00
68830daab3 Merge pull request 'master' (#1002) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1002
2025-04-27 06:29:31 +00:00
dj
c27162f918 feat : 项目归档-实施附件 2025-04-27 14:28:59 +08:00
dj
f1b81d86a2 fix : 备份附件 2025-04-27 11:00:38 +08:00
0c24d2cf51 Merge pull request 'fix : 修复单位元' (#1001) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1001
2025-04-24 13:48:41 +00:00
dj
710ccbdf65 fix : 修复单位元 2025-04-24 21:48:23 +08:00
7001261f01 Merge pull request 'refactor(project-management): 统一经费预算单位' (#1000) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1000
2025-04-24 07:30:38 +00:00
dj
7fcfc992fb refactor(project-management): 统一经费预算单位
- 在多个组件中将"预估经费预算"和"实际经费预算"的标签添加单位"(元)"
-调整部分组件的标签宽度以适应新的单位
- 此修改统一了经费预算的显示格式,提高了用户体验
2025-04-24 15:30:14 +08:00
b7be0a34ae Merge pull request 'feat(components): 增加审核意见必填校验' (#999) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/999
2025-04-23 14:47:41 +00:00
dj
a792df80e6 feat(components): 增加审核意见必填校验 2025-04-23 22:46:58 +08:00
b56e5b3544 Merge pull request 'fix : 标签不可编辑' (#998) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/998
2025-04-20 12:32:35 +00:00
dj
5dccaa1ee7 fix : 标签不可编辑 2025-04-20 20:32:16 +08:00
6aa074bfa3 Merge pull request 'feat : 项目验收新增字段' (#997) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/997
2025-04-20 11:50:58 +00:00
dj
8aefca0c82 feat : 项目验收新增字段 2025-04-20 19:49:57 +08:00
e518791ddd Merge pull request 'master' (#996) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/996
2025-04-20 06:44:18 +00:00
dj
afda146103 feat : 项目归档-附件新增项目阶段字段 2025-04-20 14:43:57 +08:00
dj
11f7fa37aa feat : 年度计划新字段 2025-04-20 13:01:43 +08:00
dj
35c2e1d9b4 feat : 需求上报新增字段 2025-04-20 12:46:14 +08:00
dj
fe3a15fcbd fix: 调整详情页面知识产权输出项 2025-04-19 21:03:54 +08:00
dj
9fd97f6ea2 feat :需求上报新增字段 2025-04-19 20:13:11 +08:00
dj
cccd14ec79 fix: 移除预期成果形式相关代码 2025-04-19 19:03:10 +08:00
2ed2cae599 Merge pull request 'fix : 注释立项提交的前置流程' (#995) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/995
2025-04-19 05:43:49 +00:00
dj
958399a32a fix : 注释立项提交的前置流程 2025-04-19 13:43:36 +08:00
745971087c Merge pull request 'fix : 完善需求上报字段页面' (#994) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/994
2025-04-19 02:58:46 +00:00
dj
8ea916c206 fix : 完善需求上报字段页面 2025-04-19 10:58:28 +08:00
e0aefecf50 Merge pull request 'fix: 修复审批白名单中取消事件' (#993) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/993
2025-04-18 14:52:27 +00:00
dj
10e9c9de19 fix: 修复审批白名单中取消事件 2025-04-18 22:51:49 +08:00
950b32270b Merge pull request 'master' (#992) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/992
2025-04-18 14:40:16 +00:00
dj
b032903ed4 fix(project): 调整知识产权相关表述和附件表格样式
- 将"知识产权状况"修改为"知识产权归属"
- 优化附件上传和展示组件的样式- 统一知识产权归属相关的标签和提示信息
- 调整部分组件的显示逻辑和样式
2025-04-18 22:37:22 +08:00
dj
696921243e fix : 首页字体颜色统一 2025-04-18 18:13:03 +08:00
dj
7200592f05 fix : 首页字体颜色统一 2025-04-18 14:04:44 +08:00
dj
963b7b93e3 Merge remote-tracking branch 'origin/master' 2025-04-18 11:22:24 +08:00
dj
86751acbd6 fix : 首页字体颜色统一 2025-04-18 11:22:00 +08:00
c17149235f Merge pull request 'fix: 编辑上报时主项目选项过滤当前项目' (#991) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/991
2025-04-15 16:00:21 +00:00
dj
fda0f4fcde fix: 编辑上报时主项目选项过滤当前项目 2025-04-15 23:56:05 +08:00
560485f255 Merge pull request 'style(article-management): 优化附件列表样式' (#990) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/990
2025-04-15 15:31:31 +00:00
dj
2847c88c61 style(article-management): 优化附件列表样式
- 在 add.vue 和 detail.vue 中为附件列表项添加底部间距,提升可读性
- 保持附件列表样式在不同页面中的一致性
2025-04-15 23:29:30 +08:00
5611fd9f02 Merge pull request 'feat: 费用导入功能' (#989) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/989
2025-04-15 15:14:57 +00:00
dj
2827c5ace6 feat: 费用导入功能 2025-04-15 23:14:46 +08:00
750a4c8178 Merge pull request 'fix: 注释公告附件列表相关代码' (#988) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/988
2025-04-15 14:34:01 +00:00
dj
9941fc14f6 fix: 注释公告附件列表相关代码 2025-04-15 22:33:38 +08:00
8b94f044db Merge pull request 'feat: 抄送成功后刷新功能' (#987) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/987
2025-04-15 03:15:54 +00:00
dj
c71208c3e4 feat: 抄送成功后刷新功能 2025-04-15 11:15:15 +08:00
b2fb3fbb67 Merge pull request 'feat: 项目详情审批流程加立即抄送按钮' (#986) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/986
2025-04-15 02:41:27 +00:00
dj
7e6b48b62a feat: 项目详情审批流程加立即抄送按钮 2025-04-15 10:40:52 +08:00
4aa0b093bb Merge pull request 'fix: 修复附件上传和展示问题' (#985) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/985
2025-04-14 13:20:20 +00:00
dj
e77820e145 fix: 修复附件上传和展示问题 2025-04-14 21:19:55 +08:00
66d2c3c7cf Merge pull request 'master' (#984) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/984
2025-04-14 13:19:48 +00:00
dj
a1422067d0 feat: 审批流程加立即抄送按钮 2025-04-14 16:44:42 +08:00
dj
7579b77b2d feat: 添加导入研发费用明细表和模板下载功能 2025-04-14 15:43:48 +08:00
dj
c6390a8117 feat: 文章管理增加附件上传/删除/下载功能 2025-04-14 15:07:58 +08:00
dj
e20f8cad7f fix: 修复附件上传和展示问题 2025-04-13 21:22:22 +08:00
dj
5cf2e4d208 feat(article-management): 增加文章附件上传功能
- 在文章管理页面添加公告附件列表
- 实现附件上传和展示功能- 优化 Tinymce 组件,支持附件上传事件
2025-04-11 18:21:43 +08:00
4f3a8550eb Merge pull request 'master' (#983) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/983
2025-04-11 06:09:41 +00:00
dj
ad6d7af1a3 Merge remote-tracking branch 'origin/master' 2025-04-11 14:08:25 +08:00
dj
65a4c72fd0 style(mobile): 优化附件文件列表的展示效果 2025-04-11 14:08:02 +08:00
5ea25ae8ae Merge pull request 'fix: 修复附件上传和展示问题' (#982) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/982
2025-04-09 15:11:29 +00:00
dj
810757e828 fix: 修复附件上传和展示问题 2025-04-09 23:11:06 +08:00
e82c6e2316 Merge pull request 'master' (#981) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/981
2025-04-09 04:59:16 +00:00
dj
af593b08da Merge remote-tracking branch 'origin/master' 2025-04-09 12:58:56 +08:00
dj
2b14bd19a4 fix : 修复项目归档附件项目基本信息展示 2025-04-09 12:58:34 +08:00
da69cb4dba Merge pull request 'master' (#980) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/980
2025-04-09 02:59:02 +00:00
cc1d0c8cf2 Merge pull request 'fix : 修复项目实施附件上传功能' (#979) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/979
2025-04-09 02:58:50 +00:00
dj
f3d9ff44a3 fix : 修复项目实施附件上传功能 2025-04-09 10:58:26 +08:00
375a678fc3 Merge pull request 'master' (#978) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/978
2025-04-09 01:42:30 +00:00
a3cbf4d24b Merge pull request 'fix : 修复项目实施附件上传功能' (#977) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/977
2025-04-09 01:42:17 +00:00
dj
d3b12bd64c fix : 修复项目实施附件上传功能 2025-04-09 09:37:53 +08:00
c213b3b41c Merge pull request 'master' (#976) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/976
2025-04-08 16:24:02 +00:00
d0c677cfb4 Merge pull request 'dj' (#975) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/975
2025-04-08 16:23:33 +00:00
dj
e9469439e8 Merge remote-tracking branch 'origin/dj' 2025-04-09 00:16:51 +08:00
62035606c9 Merge pull request 'master' (#974) from master into dj
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/974
2025-04-08 16:16:26 +00:00
dj
b101d70c75 fix: 修复附件上传和展示问题 2025-04-09 00:15:01 +08:00
382bad4cb3 Merge pull request 'master' (#973) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/973
2025-04-08 16:14:37 +00:00
dj
8c5d08874f fix: 修复附件上传和展示问题 2025-04-09 00:14:10 +08:00
dj
25d5b20b65 fix: 修复附件上传和展示问题 2025-04-09 00:13:51 +08:00
dj
2f43919132 fix: 分摊明细导出调整参数 2025-04-08 23:05:42 +08:00
8f5b9fc637 Merge pull request 'fix: 分摊明细导出调整参数' (#972) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/972
2025-04-07 16:30:53 +00:00
dj
7b619a9bef fix: 分摊明细导出调整参数 2025-04-08 00:30:32 +08:00
f33543c540 Merge pull request 'fix: 优化首页通知公告样式' (#971) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/971
2025-04-07 13:57:40 +00:00
dj
a9a2be2c74 fix: 优化首页通知公告样式 2025-04-07 21:57:13 +08:00
3160e86710 Merge pull request 'fix: 优化移动端项目管理功能' (#970) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/970
2025-04-06 14:38:30 +00:00
dj
a307697028 fix: 优化移动端项目管理功能 2025-04-06 22:38:14 +08:00
062f9c7bee Merge pull request 'feat(article-management): 首页通知公告加时间, 将"备注"字段改为"发文单位"' (#969) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/969
2025-04-06 13:26:05 +00:00
dj
e8a5b4e788 feat(article-management): 首页通知公告加时间, 将"备注"字段改为"发文单位" 2025-04-06 21:25:30 +08:00
da9624663e Merge pull request 'master' (#968) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/968
2025-04-06 09:11:03 +00:00
7b8cedcfb0 Merge pull request 'master' (#967) from master into dj
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/967
2025-04-06 09:10:49 +00:00
dj
d3c0b36657 refactor(views/components): 优化首页通知公告展示和项目附件搜索功能
- 首页通知公告:调整公告列表的序号显示逻辑
- 项目附件:改进附件搜索功能,支持按全部文件搜索
- 搜索组件:更新搜索界面文本,根据搜索范围动态显示标签或项目阶段
2025-04-06 17:10:08 +08:00
dj
eabf9cb3d6 refactor(project): 优化项目相关页面显示内容
- 修改项目需求、总结、立项、实施、归档页面中的编号标签
- 更新项目申请组件,根据项目类型动态显示实际专项资金输入框
-调整 API 代理配置
2025-04-06 16:47:23 +08:00
b84c2ce131 Merge pull request 'feat(project-management): 优化文件归档表格状态展示和权限控制' (#966) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/966
2025-04-02 16:34:20 +00:00
dj
348027f355 feat(project-management): 优化文件归档表格状态展示和权限控制 2025-04-03 00:34:04 +08:00
579f2777cf Merge pull request 'master' (#965) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/965
2025-04-02 16:11:32 +00:00
dj
ed22942ab2 fix(project-management): 优化附件启用禁用操作反馈 2025-04-03 00:11:21 +08:00
dj
119e3d8333 feat(ProjectAttachment): 优化文件上传标签逻辑 2025-04-03 00:09:41 +08:00
011566cb22 Merge pull request 'feat(ProjectAttachment): 添加文件下载功能' (#964) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/964
2025-04-02 15:37:56 +00:00
dj
bf34d8aa0c feat(ProjectAttachment): 添加文件下载功能 2025-04-02 23:34:45 +08:00
7f3fedc2f2 Merge pull request 'master' (#963) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/963
2025-04-02 15:28:05 +00:00
dj
69aa6aa0fb refactor(project-demand): 优化需求变更时特殊基金逻辑 2025-04-02 23:26:01 +08:00
dj
e54db551a6 feat(project-demand): 添加需求征集变更逻辑 2025-04-02 23:01:17 +08:00
6c91a0740a Merge pull request 'fix: 修改分摊明细页面路由跳转逻辑' (#962) from master into dj
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/962
2025-04-01 16:06:24 +00:00
f0fe6c8269 Merge pull request 'master' (#961) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/961
2025-04-01 16:06:06 +00:00
dj
9174c09a6b fix: 修改分摊明细页面路由跳转逻辑 2025-04-02 00:05:48 +08:00
dj
4dc5ca40ee feat(share-detail): 添加分摊导出按钮 2025-04-02 00:02:49 +08:00
09705e634a Merge pull request 'feat(expense-management): 新增费用分摊功能并优化项目管理相关页面' (#960) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/960
2025-04-01 15:58:33 +00:00
dj
1e29e6bdc4 feat(expense-management): 新增费用分摊功能并优化项目管理相关页面 2025-04-01 23:57:46 +08:00
e49d8cfb5e Merge pull request 'master' (#959) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/959
2025-04-01 10:19:27 +00:00
a3bb1a9156 Merge pull request 'feat: 支出明细筛选和导出功能' (#958) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/958
2025-04-01 10:19:16 +00:00
dj
e9ced267ed feat: 支出明细筛选和导出功能 2025-04-01 13:04:34 +08:00
ef9a536b5c Merge pull request 'master' (#957) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/957
2025-03-31 15:16:40 +00:00
a87be0e6e2 Merge pull request 'dj' (#956) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/956
2025-03-31 15:16:28 +00:00
dj
98d8ea4805 feat(expense-management): 新增费用分摊功能并优化项目管理相关页面 2025-03-31 23:14:54 +08:00
dj
244f2e72b4 feat: 项目基本信息新增实际经费预算和专项资金相关字段 2025-03-31 14:12:28 +08:00
dj
f9aa6191ce feat(project-manage): 新增项目附件标签功能 2025-03-30 15:06:56 +08:00
dj
ebd7fa3851 feat(project-manage): 新增项目附件标签功能 2025-03-30 15:06:39 +08:00
2941847f54 Merge pull request 'dj' (#955) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/955
2025-03-29 12:25:32 +00:00
dj
ca9e281119 feat(project-manage): 新增项目附件标签功能 2025-03-29 20:24:53 +08:00
dj
a1ed160445 Merge remote-tracking branch 'origin/master' 2025-03-28 19:41:10 +08:00
dj
9db0e8e9ec feat(expense-management): 新增费用分摊功能 2025-03-25 15:17:08 +08:00
fe09ced0bc Merge pull request 'master' (#954) from master into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/954
2025-03-25 06:37:02 +00:00
d73eb49461 Merge pull request 'dj' (#953) from dj into master
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/953
2025-03-25 06:28:09 +00:00
dj
b890372fc5 feat(ProjectAttachment): 优化项目附件组件功能和布局
- 移除了不必要的搜索和上传按钮
- 添加了文件上传功能和单个文件删除功能
- 优化了标签页切换逻辑
-调整了样式和布局
2025-03-25 14:27:48 +08:00
dj
53bab74ea9 feat(project-management): 更新项目管理相关页面文案并优化附件功能 2025-03-22 23:11:09 +08:00
zhangkaihuai
023256630e 更新 Dockerfile 2025-03-19 12:24:06 +00:00
zhangkaihuai
f65663071a 更新 nginx.conf 2025-03-19 12:13:31 +00:00
zhangkaihuai
9a55494da7 更新 nginx.conf 2025-03-19 08:07:37 +00:00
zhangkaihuai
d5a07e772f 更新 nginx.conf 2025-03-19 07:55:07 +00:00
zhangkaihuai
42499bcb22 更新 nginx.conf 2025-03-19 07:40:27 +00:00
zhangkaihuai
0243d6fc56 Merge pull request '更新 nginx.conf' (#952) from gary into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/952
2025-03-19 07:34:21 +00:00
zhangkaihuai
78435bbcac Merge pull request 'gary' (#951) from gary into prod
Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/951
2025-03-19 07:32:49 +00:00
65 changed files with 4603 additions and 697 deletions

View File

@@ -8,7 +8,7 @@ steps:
- name: build-package - name: build-package
image: node:16.20.0 image: node:18.19.0
volumes: volumes:
- name: cache - name: cache
path: /drone/src/node_modules path: /drone/src/node_modules
@@ -23,11 +23,17 @@ steps:
- cp docker.sh /app/build/$DRONE_REPO_NAME/ - cp docker.sh /app/build/$DRONE_REPO_NAME/
- cp nginx.conf /app/build/$DRONE_REPO_NAME/ - cp nginx.conf /app/build/$DRONE_REPO_NAME/
- npm -v - npm -v
- node -v
- mkdir -p ./node_modules - mkdir -p ./node_modules
- export NODE_MODULES_PATH=`pwd`/node_modules - export NODE_MODULES_PATH=`pwd`/node_modules
- npm config set registry https://registry.npmmirror.com - npm config set registry https://registry.npmmirror.com
- set NODE_OPTIONS=--openssl-legacy-provider - set NODE_OPTIONS=--openssl-legacy-provider
- npm install - npm install --legacy-peer-deps
- npm install patch-package
- npx patch-package
# - npm info unplugin-icons
- npm list package-manager-detector
# - npm install unplugin-icons@latest @antfu/install-pkg@latest package-manager-detector@latest
- npm run build - npm run build
- ls /app/build/$DRONE_REPO_NAME/ - ls /app/build/$DRONE_REPO_NAME/
- echo $NODE_MODULES_PATH - echo $NODE_MODULES_PATH

View File

@@ -4,8 +4,8 @@ RUN rm -rf /etc/nginx/conf.d/default.conf
RUN rm -rf /etc/nginx/nginx.conf RUN rm -rf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d COPY default.conf /etc/nginx/conf.d
COPY nginx.conf /etc/nginx/ COPY nginx.conf /etc/nginx/
COPY mosr.feashow.cn_chain.crt /etc/nginx/ #COPY mosr.feashow.cn_chain.crt /etc/nginx/
COPY private.key /etc/nginx/ #COPY private.key /etc/nginx/
#RUN useradd -b /home/clay -m -s /bin/bash clay #RUN useradd -b /home/clay -m -s /bin/bash clay
#RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay #RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay

View File

@@ -25,31 +25,10 @@ http {
keepalive_timeout 65; keepalive_timeout 65;
# HTTP重定向到HTTPS
server { server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
server_name mosr.feashow.cn;
return 301 https://$host$request_uri; # 强制跳转HTTPS
}
# 新增HTTPS服务器块
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name www.abc.com;
# SSL证书配置
ssl_certificate /etc/nginx/mosr.feashow.cn_chain.crt;
ssl_certificate_key /etc/nginx/private.key;
# 优化SSL配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
location /api { location /api {
proxy_pass http://gateway.$PROFILES.svc.cluster.local:8080; proxy_pass http://gateway.$PROFILES.svc.cluster.local:8080;
@@ -69,6 +48,5 @@ http {
index index.html index.htm; index index.html index.htm;
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
} }
}
}
} }

View File

@@ -7,6 +7,11 @@
"build": "vite build", "build": "vite build",
"preview": "vite preview" "preview": "vite preview"
}, },
"overrides": {
"package-manager-detector": "1.0.0",
"@iconify/utils": "2.2.1"
},
"dependencies": { "dependencies": {
"@antv/g6": "^3.5.7", "@antv/g6": "^3.5.7",
"@tinymce/tinymce-vue": "^4.0.7", "@tinymce/tinymce-vue": "^4.0.7",

View File

@@ -9,6 +9,13 @@ export const addAllocation = (data) => {
data data
}); });
}; };
export const addShare = (data) => {
return request({
url:'/workflow/mosr/cost/share',
method: "post",
data
});
};
export const getAllocationDetail = (allocationId) => { export const getAllocationDetail = (allocationId) => {
return request({ return request({
url: `/workflow/mosr/cost/allocation/info/${allocationId}`, url: `/workflow/mosr/cost/allocation/info/${allocationId}`,
@@ -61,6 +68,13 @@ export const editAllocation = (data) => {
data data
}); });
}; };
export const applyCcSend = (data) => {
return request({
url: '/workflow/mosr/cc/send',
method: "post",
data
});
};
export const deleteAllocation = (id) => { export const deleteAllocation = (id) => {
return request({ return request({
url: `/workflow/mosr/cost/allocation/${id}`, url: `/workflow/mosr/cost/allocation/${id}`,
@@ -79,3 +93,15 @@ export const shareExportExcel = (allocationId) => {
} }
); );
}; };
export const shareDetailExport= (data) => {
return axios.post(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/share/export`,
data, {
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};

View File

@@ -25,6 +25,16 @@ export const getRequirementName = (requirementName) => {
method: "get" method: "get"
}); });
}; };
//需求汇总-项目名称关键词匹配
export const getProjectName = (projectName) => {
return request({
url: `workflow/mosr/requirement/collect`,
method: "get",
params:{
projectName:projectName
}
});
};
//获取需求上报 流程信息 //获取需求上报 流程信息
export const getProcessInfo = (specialFund) => { export const getProcessInfo = (specialFund) => {
return request({ return request({

View File

@@ -85,6 +85,35 @@ export const getTags = (projectId) => {
method: "get" method: "get"
}); });
}; };
export const getTagList = (projectId) => {
return request({
url: `/workflow/mosr/file/tag/list`,
method: "get",
params:{
projectId: projectId
}
});
};
export const addTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/add',
method: "post",
data:data
});
};
export const updateTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/update',
method: "post",
data:data
});
};
export const delTag = (tageId) => {
return request({
url: `/workflow/mosr/file/tag/${tageId}`,
method: "delete"
});
};
export const getPhaseProcess = () => { export const getPhaseProcess = () => {
return request({ return request({
url: '/workflow/phase/change/process', url: '/workflow/phase/change/process',
@@ -197,3 +226,15 @@ export const ledgerTemplateDownload = () => {
} }
); );
}; };
//费用明细模板下载
export const costTemplateDownload = () => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/rd/expense/download/template`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};

View File

@@ -479,6 +479,11 @@ html, body, #app, .el-container, .el-aside, .el-main {
height: 1.4em; height: 1.4em;
margin-right: 5px; margin-right: 5px;
} }
.file-svg{
width: 1.4em;
height: 1.4em;
fill: #BEA266;
}
.middle-icon { .middle-icon {
width: 1.4em; width: 1.4em;
height: 1.4em; height: 1.4em;

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-form :model="formData" ref="applyForm" :rules="rules" :label-position="labelPosition" style="margin-left: 5px"> <el-form :model="formData" ref="applyForm" :rules="rules" :label-position="labelPosition" :style="{marginLeft: label==='项目验收附件'?'25px': label==='项目立项附件'?'25px':'5px'}">
<el-row> <el-row>
<!-- <el-col :span="24">--> <!-- <el-col :span="24">-->
<!-- <el-form-item :label="label" prop="attachment" >--> <!-- <el-form-item :label="label" prop="attachment" >-->
@@ -22,12 +22,12 @@
<!-- </el-form-item>--> <!-- </el-form-item>-->
<!-- </el-col>--> <!-- </el-col>-->
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="label" prop="" required> <el-form-item :label="label" prop="" :required="label!='项目归档附件'">
<file-upload @getFile="getOtherFile"/> <file-upload @getFile="getOtherFile"/>
<el-button color="#DED0B2" v-if="templateDownloadBtnShow" @click="handleImportTemplateDownload" <el-button color="#DED0B2" v-if="templateDownloadBtnShow" @click="handleImportTemplateDownload"
style="margin-left: 10px">模板下载 style="margin-left: 10px">模板下载
</el-button> </el-button>
<fvTable style="width: 100%;max-height: 160px;" v-if="showTable" height="160" :tableConfig="tableConfig" <fvTable style="width: 100%;" :height="label=='项目立项附件'?'160':'160'" :scrollbar-always-on="true" :style="{maxHeight:label=='项目立项附件'?'160px':'160px',height:label=='项目立项附件'?'160px':'160px'}" v-if="showTable" :tableConfig="tableConfig"
:data="allFileList" :isSettingCol="false" :pagination="false"> :data="allFileList" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/> <el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
@@ -532,12 +532,10 @@ defineExpose({
}) })
</script> </script>
<style scoped>
:deep(.el-table--fit ) {
height: 300px !important;
}
</style>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-table--fit ) {
height: 160px !important;
}
:deep(.el-table__header) { :deep(.el-table__header) {
.is-leaf:first-child { .is-leaf:first-child {
.cell { .cell {

View File

@@ -28,6 +28,9 @@
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd" style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/> />
</div> </div>
<el-button color="#DED0B2" style="margin-left: 10px"
@click="handleCarbonCopy()">立即抄送
</el-button>
</div> </div>
<div class="process"> <div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram" <operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
@@ -36,6 +39,10 @@
<process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/> <process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/>
</div> </div>
</div> </div>
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
@cancelOrClear="carbonCopyUserPickerOk"/>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" <file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow"
:fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/> :fileType="filePreviewParam.fileType"/>
@@ -49,6 +56,8 @@ import {ElLoading, ElNotification} from 'element-plus';
import {downloadFile} from "@/api/project-demand"; import {downloadFile} from "@/api/project-demand";
import {searchImplementationFileList} from "@/api/project-manage/attachment"; import {searchImplementationFileList} from "@/api/project-manage/attachment";
import {getTags} from "@/api/project-manage"; import {getTags} from "@/api/project-manage";
import {applyCcSend} from "@/api/expense-manage";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
const changeDiagram = ref(false) const changeDiagram = ref(false)
const props = defineProps({ const props = defineProps({
@@ -104,6 +113,8 @@ const props = defineProps({
} }
}) })
const form = ref() const form = ref()
const carbonCopyUserList = ref([])
const carbonCopyUserRef = ref()
const editSingleTableConfig = reactive({ const editSingleTableConfig = reactive({
columns: [ columns: [
@@ -279,23 +290,207 @@ const schema = computed(() => {
// } // }
// }) // })
} else if (props.type == 'execute') { } else if (props.type == 'execute') {
arr = [{ arr = [
label: '部门分管领导',
prop: 'optionalChargeLeadership', {
colProps: { label: '实际专利(项)',
span: 24 prop: 'actualNewPatent',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewPatent ? props.formData.actualNewPatent :props.formData.actualNewPatent==0?0: <span>{'--'}</span>
}
</div>
)
}, },
labelWidth: 'left', {
component: () => ( label: '实际软件著作权(项)',
<div> prop: 'actualSoftwareCopyright',
{ colProps: {
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => { span: 6
return <span>{item.name} </span> },
}) : <span>{'--'}</span> labelWidth: 'left',
} component: () => (
</div> <div>
) {
},] props.formData.actualSoftwareCopyright ? props.formData.actualSoftwareCopyright : props.formData.actualSoftwareCopyright==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际技术标准(项)',
prop: 'actualTechnicalNorms',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualTechnicalNorms ? props.formData.actualTechnicalNorms : props.formData.actualTechnicalNorms==0?0:<span>{'--'}</span>
}
</div>
)
},
{
label: '实际新产品(项)',
prop: 'actualNewProduct',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewProduct ? props.formData.actualNewProduct : props.formData.actualNewProduct==0?0:<span>{'--'}</span>
}
</div>
)
},
{
label: '实际新工艺(项)',
prop: 'actualNewProcess',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewProcess ? props.formData.actualNewProcess : props.formData.actualNewProcess==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新装置(项)',
prop: 'actualNewDevice',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewDevice ? props.formData.actualNewDevice :props.formData.actualNewDevice==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新材料(项)',
prop: 'actualNewMaterials',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewMaterials ? props.formData.actualNewMaterials : props.formData.actualNewMaterials==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际计算机软件(项)',
prop: 'actualComputerSoftware',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualComputerSoftware ? props.formData.actualComputerSoftware : props.formData.actualComputerSoftware==0?0:<span>{'--'}</span>
}
</div>
)
},
{
label: '实际论文论著(项)',
prop: 'actualThesis',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualThesis ? props.formData.actualThesis : props.formData.actualThesis==0?0:<span>{'--'}</span>
}
</div>
)
},
{
label: '实际研究报告(项)',
prop: 'actualResearchReport',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualResearchReport ? props.formData.actualResearchReport : props.formData.actualResearchReport==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际商标(项)',
prop: 'actualTrademark',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualTrademark ? props.formData.actualTrademark :props.formData.actualTrademark==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际其他(项)',
prop: 'actualOther',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div style="white-space: pre-wrap;">
{
props.formData.actualOther ? props.formData.actualOther : props.formData.actualOther==0?0: <span>{'--'}</span>
}
</div>
)
},
{
label: '部门分管领导',
prop: 'optionalChargeLeadership',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => {
return <span>{item.name} </span>
}) : <span>{'--'}</span>
}
</div>
)
}
]
if (props.preProcessShow == 'EDIT') { if (props.preProcessShow == 'EDIT') {
preProcess = { preProcess = {
@@ -334,22 +529,22 @@ const schema = computed(() => {
// }) // })
} else if (props.type == 'archivist') { } else if (props.type == 'archivist') {
arr = [ arr = [
// { // {
// label: '项目归档附件', // label: '项目归档附件',
// prop: 'singleFile', // prop: 'singleFile',
// colProps: { // colProps: {
// span: 24 // span: 24
// }, // },
// labelWidth: 'left', // labelWidth: 'left',
// component: () => { // component: () => {
// let singleFileArray = [props.formData.singleFile] // let singleFileArray = [props.formData.singleFile]
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80" // return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
// tableConfig={editSingleTableConfig} // tableConfig={editSingleTableConfig}
// data={singleFileArray} isSettingCol={false} pagination={false}> // data={singleFileArray} isSettingCol={false} pagination={false}>
// </fvTable> // </fvTable>
// : <span>--</span> // : <span>--</span>
// } // }
// }, // },
] ]
} else if (props.type == 'phase') { } else if (props.type == 'phase') {
arr = [ arr = [
@@ -381,7 +576,7 @@ const filePreviewParam = ref({
}) })
const filePreviewShow = ref(false) const filePreviewShow = ref(false)
const route = useRoute() const route = useRoute()
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value', 'ccSend'])
const _value = computed({ const _value = computed({
get() { get() {
return props.value; return props.value;
@@ -390,6 +585,40 @@ const _value = computed({
emit("update:value", val); emit("update:value", val);
} }
}) })
const handleCarbonCopy = () => {
carbonCopyUserRef.value.showUserPicker()
}
const carbonCopyUserPickerOk = (userList) => {
carbonCopyUserList.value = userList.map(item => item.id)
console.log('localFormData.value', props.data)
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
addUser()
}
const addUser = async () => {
const res = await applyCcSend({
instanceId: props.data.processInstanceId,
// message:props.data.remark,
projectId: route.query.projectId,
state: route.query.step,
userIds: carbonCopyUserList.value
})
console.log('res', res)
if (res.code === 1000) {
ElNotification({
title: '提示',
message: '抄送成功',
type: 'success'
})
emit('ccSend')
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
}
const clickToPreview = (row) => { const clickToPreview = (row) => {
filePreviewShow.value = false filePreviewShow.value = false
filePreviewParam.value = { filePreviewParam.value = {

View File

@@ -3,7 +3,7 @@
<el-form-item :label="title" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :style="{marginTop: '10px',marginLeft: tag!=='需求上报'?'15px':'0'}"> <el-form-item :label="title" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :style="{marginTop: '10px',marginLeft: tag!=='需求上报'?'15px':'0'}">
<file-upload @getFile="getOtherFile" v-if="fileListShow === 'EDIT'"/> <file-upload @getFile="getOtherFile" v-if="fileListShow === 'EDIT'"/>
<!-- :style="{width:isOpenPrint?'610px': '100%'}" table-layout="auto" id="printTable"--> <!-- :style="{width:isOpenPrint?'610px': '100%'}" table-layout="auto" id="printTable"-->
<fvTable style="width:100%;max-height: 160px;" v-if="processViewer" height="160" :tableConfig="tableConfig" <fvTable style="width:100%;" :height="tag=='项目立项'?'160':'160'" :style="{maxHeight:tag=='项目立项'?'160px':'160px',height:tag=='项目立项'?'160px':'160px'}" v-if="processViewer" :scrollbar-always-on="true" :tableConfig="tableConfig"
:data="_value" :isSettingCol="false" :pagination="false"> :data="_value" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/> <el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
@@ -81,7 +81,9 @@ const tableConfig = reactive({
{ {
prop: 'tag', prop: 'tag',
label: '标签', label: '标签',
align: 'center' align: 'center',
showOverflowTooltip: false,
minWidth: props.fileNameTableWidth,
}, },
{ {
prop: 'size', prop: 'size',

View File

@@ -206,6 +206,14 @@ const rollbackHandler = async () => {
} }
const handleAgree = async () => { const handleAgree = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
// const values = form.value.getValues() // const values = form.value.getValues()
const params = { const params = {
taskId: props.taskId, taskId: props.taskId,

View File

@@ -1,11 +1,101 @@
<template> <template>
<div class="apply-block"> <div class="apply-block">
<baseTitle :title="getTitleName(title)+'信息'"></baseTitle> <baseTitle :title="getTitleName(title)+'信息'"></baseTitle>
<el-form :model="localFormData" ref="formRef" label-width="auto" v-if="step!=='50'"> <el-form :model="localFormData" ref="formRef" label-width="auto" v-if="step!=='50'" :rules="rules">
<el-row v-if="title==='apply'">
<el-col :span="6">
<!-- label-width="106"-->
<el-form-item label="实际经费预算(元)" prop="actualEconomicEstimate" label-width="130">
<el-input-number v-model="localFormData.actualEconomicEstimate" placeholder="请输入实际经费预算" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" v-if="isSpecialFund">
<!-- label-width="106" -->
<el-form-item label="实际专项资金(元)" prop="specialFundAmount" label-width="140">
<el-input-number v-model="localFormData.specialFundAmount" placeholder="请输入实际专项资金" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="title==='check'">
<el-col :span="6">
<el-form-item label="实际专利(项)" prop="actualNewPatent" label-width="130">
<el-input-number v-model="localFormData.actualNewPatent" placeholder="请输入实际专利数量" style="margin-right: 20px" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -10px">
<el-form-item label="实际软件著作权(项)" prop="actualSoftwareCopyright" label-width="150">
<el-input-number v-model="localFormData.actualSoftwareCopyright" placeholder="请输入实际软件著作权数量":controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -5px">
<el-form-item label="实际技术标准(项)" prop="actualTechnicalNorms" label-width="150">
<el-input-number v-model="localFormData.actualTechnicalNorms" placeholder="请输入实际技术标准数量":controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="实际新产品(项)" prop="actualNewProduct" label-width="160" style="margin-right: -10px">
<el-input-number v-model="localFormData.actualNewProduct" placeholder="请输入实际新产品数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="实际新工艺(项)" prop="actualNewProcess" label-width="130" >
<el-input-number v-model="localFormData.actualNewProcess" placeholder="请输入实际新工艺数量" style="margin-right: 20px" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -10px">
<el-form-item label="实际新装置(项)" prop="actualNewDevice" label-width="150">
<el-input-number v-model="localFormData.actualNewDevice" placeholder="请输入实际新装置数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -5px">
<el-form-item label="实际新材料(项)" prop="actualNewMaterials" label-width="150">
<el-input-number v-model="localFormData.actualNewMaterials" placeholder="请输入实际新材料数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="实际计算机软件(项)" prop="actualComputerSoftware" label-width="160" style="margin-right: -10px">
<el-input-number v-model="localFormData.actualComputerSoftware" placeholder="请输入实际计算机软件数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="实际论文论著(项)" prop="actualThesis" label-width="130" style="margin-right: 20px">
<el-input-number v-model="localFormData.actualThesis" placeholder="请输入实际论文论著数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -10px">
<el-form-item label="实际研究报告(项)" prop="actualResearchReport" label-width="150">
<el-input-number v-model="localFormData.actualResearchReport" placeholder="请输入实际研究报告数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="6" style="margin-left: -5px">
<el-form-item label="实际商标(项)" prop="actualTrademark" label-width="150">
<el-input-number v-model="localFormData.actualTrademark" placeholder="请输入实际商标数量" :controls="false">
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="实际其他(项)" prop="actualOther" label-width="130" style="margin-right: 10px">
<el-input rows="4" type="textarea" v-model="localFormData.actualOther" placeholder="请输入实际其他项" >
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row> <el-row>
<el-col :span="6" v-if="title==='apply'"> <el-col :span="6" v-if="title==='apply'">
<!-- label-width="106"--> <!-- label-width="106"-->
<el-form-item label="项目负责人" :required="true" prop="" label-width="111"> <el-form-item label="项目负责人" :required="true" prop="" label-width="130">
<el-button style="margin-right: 10px" color="#DED0B2" @click="handleShowProjectChargePersonTable"> <el-button style="margin-right: 10px" color="#DED0B2" @click="handleShowProjectChargePersonTable">
{{ projectChargePersonUserList?.length !== 0 ? '更改' : '请选择' }} {{ projectChargePersonUserList?.length !== 0 ? '更改' : '请选择' }}
</el-button> </el-button>
@@ -13,56 +103,66 @@
{{ item.name }} {{ item.name }}
</div> </div>
<user-picker :multiple="false" ref="projectChargePersonUserPicker" title="请选择项目负责人" <user-picker :multiple="false" ref="projectChargePersonUserPicker" title="请选择项目负责人"
v-model:value="projectChargePersonUserList" @ok="projectChargePersonUserPickerOk" @cancelOrClear="projectChargePersonUserPickerCancel"/> v-model:value="projectChargePersonUserList" @ok="projectChargePersonUserPickerOk"
@cancelOrClear="projectChargePersonUserPickerCancel"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" v-if="title==='apply'"> <el-col :span="6" v-if="title==='apply'">
<el-form-item label="项目成员" :required="true" prop="" label-width="85" <el-form-item label="项目成员" :required="true" prop="" label-width="140"
> >
<el-button color="#DED0B2" style="margin-right: 10px" @click="handleShowProjectPersonTable"> <el-button color="#DED0B2" style="margin-right: 10px" @click="handleShowProjectPersonTable">
{{ projectPersonUserList?.length !== 0 ? '更改' : getProjectPerson(projectPersonUserList) ? '更改' : '请选择' }} {{
projectPersonUserList?.length !== 0 ? '更改' : getProjectPerson(projectPersonUserList) ? '更改' : '请选择'
}}
</el-button> </el-button>
<div v-for="(item,index) in getProjectPerson(projectPersonUserList)" :key="item.id" > <div v-for="(item,index) in getProjectPerson(projectPersonUserList)" :key="item.id">
{{ item.name }}{{index != getProjectPerson(projectPersonUserList)?.length - 1 ? '' : ''}} {{ item.name }}{{ index != getProjectPerson(projectPersonUserList)?.length - 1 ? '' : '' }}
</div> </div>
<user-picker :multiple="true" ref="projectPersonUserPicker" title="请选择项目成员" <user-picker :multiple="true" ref="projectPersonUserPicker" title="请选择项目成员"
v-model:value="projectPersonUserList" @ok="projectPersonUserPickerOk" @cancelOrClear="projectPersonUserPickerCancel"/> v-model:value="projectPersonUserList" @ok="projectPersonUserPickerOk"
@cancelOrClear="projectPersonUserPickerCancel"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" v-if="title==='apply'||title==='check'"> <el-col :span="6" v-if="title==='apply'||title==='check'">
<el-form-item label="部门分管领导" :label-width="title==='check'?110:115"> <el-form-item label="部门分管领导" :label-width="title==='check'?130:115" :required="isKcjUser()">
<el-button color="#DED0B2" style="margin-right: 10px" @click="handleShowOptionalChargeLeadershipPicker"> <el-button color="#DED0B2" style="margin-right: 10px" @click="handleShowOptionalChargeLeadershipPicker">
{{ {{
optionalChargeLeadershipList?.length !== 0 ? '更改' : getOptionalChargeLeadershipList(optionalChargeLeadershipList) ? '更改' : '请选择' optionalChargeLeadershipList?.length !== 0 ? '更改' : getOptionalChargeLeadershipList(optionalChargeLeadershipList) ? '更改' : '请选择'
}} }}
</el-button> </el-button>
<div v-for="(item,index) in getOptionalChargeLeadershipList(optionalChargeLeadershipList)" :key="item.id"> <div v-for="(item,index) in getOptionalChargeLeadershipList(optionalChargeLeadershipList)" :key="item.id">
{{ item.name }}{{index != getOptionalChargeLeadershipList(optionalChargeLeadershipList)?.length - 1 ? '' : ''}} {{
item.name
}}{{ index != getOptionalChargeLeadershipList(optionalChargeLeadershipList)?.length - 1 ? '' : '' }}
</div> </div>
<user-picker :multiple="true" ref="optionalChargeLeadershipPickerRef" title="请选择部门分管领导" <user-picker :multiple="true" ref="optionalChargeLeadershipPickerRef" title="请选择部门分管领导"
v-model:value="optionalChargeLeadershipList" @ok="optionalChargeLeaderPickerOk" @cancelOrClear="optionalChargeLeaderPickerCancel"/> v-model:value="optionalChargeLeadershipList" @ok="optionalChargeLeaderPickerOk"
@cancelOrClear="optionalChargeLeaderPickerCancel"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24" v-if="preProcessShow === 'EDIT'"> <el-col :span="24" v-if="preProcessShow === 'EDIT'||title==='apply'||title==='check'">
<el-form-item label="前置流程" :required="preProcessRequired" prop="preProcess" label-width="125"> <el-form-item label="前置流程" :required="preProcessRequired" prop="preProcess" :label-width="title==='apply'?130:125">
<el-button color="#DED0B2" @click="handleShowPreTable" style="margin-right: 10px"> <select-pre-process :formData="localFormData" :basicData="basicData"/>
{{ <!-- <el-button color="#DED0B2" @click="handleShowPreTable" style="margin-right: 10px">-->
localFormData.preProcess && localFormData.preProcess?.length > 0 ? '更改' : sessionParams.preProcess && sessionParams.preProcess?.length > 0 ? '更改' : '请选择' <!-- {{-->
}} <!-- localFormData.preProcess && localFormData.preProcess?.length > 0 ? '更改' : sessionParams.preProcess && sessionParams.preProcess?.length > 0 ? '更改' : '请选择'-->
</el-button> <!-- }}-->
<div v-for="(item,index) in getRequestName(localFormData.preProcess)" :key="item.requestId"> <!-- </el-button>-->
<a :href="item.baseUrl" target="_blank" <!-- <div v-for="(item,index) in getRequestName(localFormData.preProcess)" :key="item.requestId">-->
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span <!-- <a :href="item.baseUrl" target="_blank"-->
v-if="index != localFormData.preProcess?.length -1"></span> <!-- style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span-->
</a> <!-- v-if="index != localFormData.preProcess?.length -1"></span>-->
</div> <!-- </a>-->
<!-- </div>-->
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<!-- v-if="showAttachment"--> <!-- v-if="showAttachment"-->
<AttachmentUpload ref="attachment" :label="getTitleName(title)+'附件'" :showTable="showTable" <AttachmentUpload ref="attachment" :label="getTitleName(title)+'附件'" :showTable="showTable"
v-model:otherFileList="otherFileList" :tag="getTitleName(props.title)" :templateName="getTemplateName(props.title)" :templateDownloadBtnShow="props.title==='apply'?true:props.title==='check'" v-model:otherFileList="otherFileList" :tag="getTitleName(props.title)"
:templateName="getTemplateName(props.title)"
:templateDownloadBtnShow="props.title==='apply'?true:props.title==='check'"
@getAttachment="getAttachment" v-model:singleList="singleList" :showSingleTable="showSingleTable" @getAttachment="getAttachment" v-model:singleList="singleList" :showSingleTable="showSingleTable"
@getOtherFile="getOtherFile" :showFileList="true" :formData="localFormData" @getOtherFile="getOtherFile" :showFileList="true" :formData="localFormData"
:preview="mode == 'resubmit'"/> :preview="mode == 'resubmit'"/>
@@ -91,8 +191,8 @@
</div> </div>
</div> </div>
<div class="oper-page-btn"> <div class="oper-page-btn">
<el-button color="#DED0B2" v-if="mode === 'submit'" @click="handleSubmit">提交</el-button> <el-button color="#DED0B2" v-if="mode === 'submit'" @click="handleSubmit(formRef)">提交</el-button>
<el-button color="#DED0B2" v-else-if="mode === 'resubmit'" @click="handleSubmit">重新提交</el-button> <el-button color="#DED0B2" v-else-if="mode === 'resubmit'" @click="handleSubmit(formRef)">重新提交</el-button>
<el-button @click="handleBack">返回</el-button> <el-button @click="handleBack">返回</el-button>
</div> </div>
@@ -102,8 +202,8 @@
<el-dialog v-if="showPreTable" title="前置流程" v-model="showPreTable" width="80%"> <el-dialog v-if="showPreTable" title="前置流程" v-model="showPreTable" width="80%">
<el-form :model="preProcessForm" inline @submit.prevent="searchPreProcess"> <el-form :model="preProcessForm" inline @submit.prevent="searchPreProcess">
<el-form-item label="请求名称"> <el-form-item label="请求名称">
<el-input v-model="preProcessForm.requestName" placeholder="请输入请求名称" clearable> <el-input-number v-model="preProcessForm.requestName" placeholder="请输入请求名称" clearable>
</el-input> </el-input-number>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button color="#DED0B2" @click="searchPreProcess">搜索</el-button> <el-button color="#DED0B2" @click="searchPreProcess">搜索</el-button>
@@ -140,7 +240,7 @@
<script setup lang="jsx"> <script setup lang="jsx">
import OperationRender from '@/views/workflow/common/OperationRender.vue' import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'; import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import {ElNotification} from "element-plus"; import {ElLoading, ElNotification} from "element-plus";
import { import {
getApplyProcess, getApplyProcess,
getPreProcess, getPreProcess,
@@ -157,9 +257,14 @@ import {useProcessStore} from '@/stores/processStore.js';
import {useTagsView} from '@/stores/tagsview.js' import {useTagsView} from '@/stores/tagsview.js'
import Paging from "@/components/pagination/index.vue"; import Paging from "@/components/pagination/index.vue";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue"; import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
import {getBaseInfoApi, getMapProjectStateInfo} from "@/components/steps/api";
import {useAuthStore} from "@/stores/userstore";
const authStore = useAuthStore()
const userInfo =ref( authStore.userinfo)
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const formRef = ref()
const changeDiagram = ref(false) const changeDiagram = ref(false)
const showSingleTable = ref(false) const showSingleTable = ref(false)
const projectChargePersonUserList = ref([]) const projectChargePersonUserList = ref([])
@@ -186,6 +291,10 @@ const props = defineProps({
type: Object, type: Object,
default: {} default: {}
}, },
basicData: {
type: Object,
default: {}
},
formData: { formData: {
type: Object, type: Object,
default: {} default: {}
@@ -211,11 +320,24 @@ const pageInfo = reactive({
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
}) })
// const rules = reactive({ const rules = reactive({
// preProcess: [{required: true, message: '请选择前置流程', trigger: 'blur'}], actualEconomicEstimate: [{required: true, message: '请输入实际经费预算', trigger: ['blur', 'change']}],
// projectChargePerson: [{required: true, message: '请选择项目负责人', trigger: 'blur'}], specialFundAmount: [{required: true, message: '请输入实际专项资金', trigger: 'blur'}],
// projectPerson: [{required: true, message: '请选择项目成员', trigger: 'blur'}], // projectPerson: [{required: true, message: '请选择项目成员', trigger: 'blur'}],
// }) actualNewPatent: [{required: true, message: '请输入实际专利数量', trigger: ['blur', 'change']}],
actualTechnicalNorms: [{required: true, message: '请输入实际技术标准数量', trigger: ['blur', 'change']}],
actualSoftwareCopyright: [{required: true, message: '请输入实际软件著作权数量', trigger: ['blur', 'change']}],
actualNewProduct: [{required: true, message: '请输入实际新产品数量', trigger: ['blur', 'change']}],
actualNewProcess: [{required: true, message: '请输入实际新工艺数量', trigger: ['blur', 'change']}],
actualNewMaterials: [{required: true, message: '请输入实际新材料数量', trigger: ['blur', 'change']}],
actualNewDevice: [{required: true, message: '请输入实际新装置数量', trigger: ['blur', 'change']}],
actualComputerSoftware: [{required: true, message: '请输入实际计算机软件数量', trigger: ['blur', 'change']}],
actualThesis: [{required: true, message: '请输入实际论文论著数量', trigger: ['blur', 'change']}],
actualResearchReport: [{required: true, message: '请输入实际研究报告数量', trigger: ['blur', 'change']}],
actualTrademark: [{required: true, message: '请输入实际商标数量', trigger: ['blur', 'change']}],
actualOther: [{required: true, message: '请输入实际其他项数量', trigger: ['blur', 'change']}],
})
const tagsViewStore = useTagsView() const tagsViewStore = useTagsView()
const processStore = useProcessStore() const processStore = useProcessStore()
const localProjectPerson = ref([]) const localProjectPerson = ref([])
@@ -243,6 +365,7 @@ const selectRows = ref([])
const projectId = ref(route.query.projectId) const projectId = ref(route.query.projectId)
const sessionParams = ref({}) const sessionParams = ref({})
const optionalChargeLeadershipPickerRef = ref() const optionalChargeLeadershipPickerRef = ref()
const isSpecialFund = ref(false)
const optionalChargeLeadershipList = ref([]) const optionalChargeLeadershipList = ref([])
const filePreviewParam = ref({ const filePreviewParam = ref({
fileUrl: '', fileUrl: '',
@@ -250,8 +373,55 @@ const filePreviewParam = ref({
fileType: 'pdf' fileType: 'pdf'
}) })
const filePreviewShow = ref(false) const filePreviewShow = ref(false)
const isKcjUser=()=>{
const hasDstiAdmin = userInfo.value.roles?.some(item => item.roleKey != 'dsti_admin');
return hasDstiAdmin;
}
const getSummaryInfo = async () => {
if (props.mode === 'resubmit') return;
if(props.title === 'check'){
const loading = ElLoading.service({fullscreen: true})
try {
const projectId = route.query.projectId
const {code, data, msg} = await getMapProjectStateInfo(projectId, '10')
if (code === 1000) {
localFormData.value.actualNewPatent= data.formData.newPatent
localFormData.value.actualSoftwareCopyright= data.formData.softwareCopyright
localFormData.value.actualTechnicalNorms= data.formData.technicalNorms
localFormData.value.actualNewProduct= data.formData.newProduct
localFormData.value.actualNewProcess= data.formData.newProcess
localFormData.value.actualNewDevice= data.formData.newDevice
localFormData.value.actualNewMaterials= data.formData.newMaterials
localFormData.value.actualComputerSoftware= data.formData.computerSoftware
localFormData.value.actualThesis= data.formData.thesis
localFormData.value.actualResearchReport= data.formData.researchReport
localFormData.value.actualTrademark= data.formData.trademark
localFormData.value.actualOther= data.formData.other
const getTemplateName=(type)=>{ loading.close()
} else {
ElNotification({
title: '提示',
message: msg,
type: 'error'
})
loading.close()
}
} catch {
loading.close()
}
}
}
getSummaryInfo()
const getInfo = async () => {
const {code, data} = await getBaseInfoApi(route.query.projectId)
isSpecialFund.value = data.isSpecialFund
}
getInfo()
const getTemplateName = (type) => {
switch (type) { switch (type) {
case 'apply': case 'apply':
return '科技创新项目立项模板' return '科技创新项目立项模板'
@@ -266,9 +436,9 @@ const handleShowOptionalChargeLeadershipPicker = () => {
const optionalChargeLeaderPickerOk = (userList) => { const optionalChargeLeaderPickerOk = (userList) => {
optionalChargeLeadershipList.value = userList optionalChargeLeadershipList.value = userList
if(userList?.length>0){ if (userList?.length > 0) {
localStorage.setItem('optionalChargeLeadershipList', JSON.stringify(optionalChargeLeadershipList.value)) localStorage.setItem('optionalChargeLeadershipList', JSON.stringify(optionalChargeLeadershipList.value))
}else { } else {
localStorage.removeItem('optionalChargeLeadershipList') localStorage.removeItem('optionalChargeLeadershipList')
} }
} }
@@ -347,27 +517,27 @@ const handleShowProjectChargePersonTable = () => {
} }
const projectChargePersonUserPickerOk = (userList) => { const projectChargePersonUserPickerOk = (userList) => {
projectChargePersonUserList.value = userList projectChargePersonUserList.value = userList
if(userList?.length>0){ if (userList?.length > 0) {
localStorage.setItem('projectChargePersonUserList', JSON.stringify(projectChargePersonUserList.value)) localStorage.setItem('projectChargePersonUserList', JSON.stringify(projectChargePersonUserList.value))
}else { } else {
localStorage.removeItem('projectPersonUserList') localStorage.removeItem('projectPersonUserList')
} }
} }
const handleShowProjectPersonTable = () => { const handleShowProjectPersonTable = () => {
projectPersonUserPicker.value.showUserPicker() projectPersonUserPicker.value.showUserPicker()
} }
const projectChargePersonUserPickerCancel=(userList)=>{ const projectChargePersonUserPickerCancel = (userList) => {
projectChargePersonUserList.value = userList projectChargePersonUserList.value = userList
} }
const projectPersonUserPickerCancel=(userList)=>{ const projectPersonUserPickerCancel = (userList) => {
projectPersonUserList.value = userList projectPersonUserList.value = userList
} }
const projectPersonUserPickerOk = (userList) => { const projectPersonUserPickerOk = (userList) => {
projectPersonUserList.value = userList projectPersonUserList.value = userList
if(userList?.length>0){ if (userList?.length > 0) {
localStorage.setItem('projectPersonUserList', JSON.stringify(userList)) localStorage.setItem('projectPersonUserList', JSON.stringify(userList))
}else { } else {
localStorage.removeItem('projectPersonUserList') localStorage.removeItem('projectPersonUserList')
} }
} }
@@ -404,9 +574,15 @@ const choosePreProcess = () => {
requestName: item.requestName, requestName: item.requestName,
baseUrl: item.baseUrl baseUrl: item.baseUrl
} }
preProcessArray.push(preProcessObj) if(props.mode === 'resubmit'){
localFormData.value.preProcess.push(preProcessObj)
}else{
preProcessArray.push(preProcessObj)
}
}) })
localFormData.value.preProcess = preProcessArray if(props.mode !== 'resubmit'){
localFormData.value.preProcess = preProcessArray
}
showPreTable.value = false showPreTable.value = false
localStorage.setItem('preProcess', JSON.stringify(preProcessArray)) localStorage.setItem('preProcess', JSON.stringify(preProcessArray))
} }
@@ -489,109 +665,182 @@ const getFileParam = (item) => {
tag: item.tag tag: item.tag
} }
} }
const handleSubmit = async () => { const handleSubmit = async (instance) => {
let files = [] if (props.step == 50) {
if (props.mode === 'resubmit') { let files = []
attachment.value.allFileList.forEach(item => {
files.push(getFileParam(item))
})
} else {
otherFileList.value.forEach(item => {
files.push(getFileParam(item))
})
}
// console.info("🚀 ~method:handleSubmit -----", files,attachment.value.isHaveOneFile)
if (!attachment.value.isHaveOneFile) {
attachment.value.validate()
ElNotification({
title: '提示',
message: '请上传附件',
type: 'error'
})
return;
} else {
attachment.value.clearValidate()
}
let projectPersonIds = []
for (const item of projectPersonUserList.value) {
projectPersonIds.push(parseInt(item.id))
}
let params = {
deploymentId: deploymentId.value,
requirementId: route.query.id,
fileList: files,
// singleFile: attachment.value.singleFile,
projectId: projectId.value,
preProcess: JSON.stringify(localFormData.value.preProcess)
}
if (sessionParams.value.preProcess && !localFormData.value.preProcess) {
params.preProcess = JSON.stringify(sessionParams.value.preProcess)
}
// console.log(params.preProcess)
let res
if (props.step === '20') {
if (projectChargePersonUserList.value && projectChargePersonUserList.value.length === 0) {
ElNotification({
title: '提示',
message: '请选择项目负责人!',
type: 'error'
})
return;
}
if (projectPersonUserList.value && projectPersonUserList.value.length === 0) {
ElNotification({
title: '提示',
message: '请选择项目成员!',
type: 'error'
})
return;
}
params.projectChargePerson = parseInt(projectChargePersonUserList.value[0].id)
params.projectPersonIds = projectPersonIds
params.optionalChargeLeadership = optionalChargeLeadershipList.value
if (props.mode === 'resubmit') { if (props.mode === 'resubmit') {
res = await resubmitApply(params) attachment.value.allFileList.forEach(item => {
files.push(getFileParam(item))
})
} else { } else {
res = await projectApply(params) otherFileList.value.forEach(item => {
files.push(getFileParam(item))
})
} }
} else if (props.step === '40') { // console.info("🚀 ~method:handleSubmit -----", files,attachment.value.isHaveOneFile)
params.optionalChargeLeadership = optionalChargeLeadershipList.value // if (!attachment.value.isHaveOneFile) {
if (props.mode === 'resubmit') { // attachment.value.validate()
res = await resubmitCheck(params) // ElNotification({
} else { // title: '提示',
res = await projectCheck(params) // message: '请上传附件',
// type: 'error'
// })
// return;
// } else {
// attachment.value.clearValidate()
// }
let projectPersonIds = []
for (const item of projectPersonUserList.value) {
projectPersonIds.push(parseInt(item.id))
} }
} else if (props.step === '50') { let params = {
...localFormData.value,
deploymentId: deploymentId.value,
requirementId: route.query.id,
fileList: files,
// singleFile: attachment.value.singleFile,
projectId: route.query.projectId,
actualEconomicEstimate: parseFloat(localFormData.value.actualEconomicEstimate),
specialFundAmount: parseFloat(localFormData.value.specialFundAmount),
preProcess: JSON.stringify(localFormData.value.preProcess)
}
if (sessionParams.value.preProcess && !localFormData.value.preProcess) {
params.preProcess = JSON.stringify(sessionParams.value.preProcess)
}
console.log('params', params.fileList)
let res
if (props.mode === 'resubmit') { if (props.mode === 'resubmit') {
res = await resubmitConclusion(params) res = await resubmitConclusion(params)
} else { } else {
res = await projectConclusion(params) res = await projectConclusion(params)
} }
} ElNotification({
ElNotification({ title: '提示',
title: '提示', message: res.msg,
message: res.msg, type: res.code === 1000 ? 'success' : 'error'
type: res.code === 1000 ? 'success' : 'error' })
}) if (res.code === 1000) {
if (res.code === 1000) { tagsViewStore.delVisitedViews(router.currentRoute.value.path)
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
if (props.step === '20') {
await router.push({
name: 'Initiation'
})
} else if (props.step === '40') {
await router.push({
name: 'Implementation'
})
} else if (props.step === '50') {
await router.push({ await router.push({
name: 'Filing' name: 'Filing'
}) })
} }
} else {
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let files = []
if (props.mode === 'resubmit') {
attachment.value.allFileList.forEach(item => {
files.push(getFileParam(item))
})
} else {
otherFileList.value.forEach(item => {
files.push(getFileParam(item))
})
}
// console.info("🚀 ~method:handleSubmit -----", files,attachment.value.isHaveOneFile)
if (!attachment.value.isHaveOneFile) {
attachment.value.validate()
ElNotification({
title: '提示',
message: '请上传附件',
type: 'error'
})
return;
} else {
attachment.value.clearValidate()
}
let projectPersonIds = []
for (const item of projectPersonUserList.value) {
projectPersonIds.push(parseInt(item.id))
}
let params = {
// singleFile: attachment.value.singleFile,
...localFormData.value,
projectId: route.query.projectId,
deploymentId: deploymentId.value,
requirementId: route.query.id,
fileList: files,
actualEconomicEstimate: parseFloat(localFormData.value.actualEconomicEstimate)||null,
specialFundAmount: parseFloat(localFormData.value.specialFundAmount)||null,
preProcess: JSON.stringify(localFormData.value.preProcess)
}
if (sessionParams.value.preProcess && !localFormData.value.preProcess) {
params.preProcess = JSON.stringify(sessionParams.value.preProcess)
}
console.log('params', params)
let res
if (props.step === '20') {
if (projectChargePersonUserList.value && projectChargePersonUserList.value.length === 0) {
ElNotification({
title: '提示',
message: '请选择项目负责人!',
type: 'error'
})
return;
}
if (projectPersonUserList.value && projectPersonUserList.value.length === 0) {
ElNotification({
title: '提示',
message: '请选择项目成员!',
type: 'error'
})
return;
}
if (optionalChargeLeadershipList.value && optionalChargeLeadershipList.value.length === 0&&isKcjUser()) {
ElNotification({
title: '提示',
message: '请选择部门分管领导!',
type: 'error'
})
return;
}
params.projectChargePerson = parseInt(projectChargePersonUserList.value[0].id)
params.projectPersonIds = projectPersonIds
params.optionalChargeLeadership = optionalChargeLeadershipList.value
if (props.mode === 'resubmit') {
res = await resubmitApply(params)
} else {
res = await projectApply(params)
}
} else if (props.step === '40') {
params.optionalChargeLeadership = optionalChargeLeadershipList.value
if (props.mode === 'resubmit') {
res = await resubmitCheck(params)
} else {
res = await projectCheck(params)
}
}
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
if (props.step === '20') {
await router.push({
name: 'Initiation'
})
} else if (props.step === '40') {
await router.push({
name: 'Implementation'
})
}
}
})
} }
} }
const init = async () => { const init = async () => {
let id = projectId.value let id = route.query.projectId
if (!id) return; if (!id) return;
processDiagramViewer.value = false processDiagramViewer.value = false
let res let res
@@ -606,7 +855,7 @@ const init = async () => {
let data = res.data let data = res.data
deploymentId.value = data.deploymentId deploymentId.value = data.deploymentId
deploymentData.value = data deploymentData.value = data
preProcessRequired.value = data.deploymentName === '重大项目立项' || data.deploymentName === '重大项目验收'; // preProcessRequired.value = data.deploymentName === '重大项目立项' || data.deploymentName === '重大项目验收';
processStore.setDesign(data) processStore.setDesign(data)
processStore.runningList.value = data.runningList; processStore.runningList.value = data.runningList;
processStore.endList.value = data.endList; processStore.endList.value = data.endList;
@@ -642,7 +891,6 @@ watchEffect(() => {
// if (props.formData.projectChargePerson != null) { // if (props.formData.projectChargePerson != null) {
// localFormData.value.projectChargePerson = props.formData.projectChargePerson.id // localFormData.value.projectChargePerson = props.formData.projectChargePerson.id
// } // }
if (localStorage.getItem('preProcess')) { if (localStorage.getItem('preProcess')) {
let param = JSON.parse(localStorage.getItem('preProcess')) let param = JSON.parse(localStorage.getItem('preProcess'))
localFormData.value.preProcess = param localFormData.value.preProcess = param

View File

@@ -1,52 +1,92 @@
<template> <template>
<el-row style="padding-bottom: 20px"> <el-row>
<el-col :span="24"> <el-col :span="24">
<baseTitle :title="'项目附件'"></baseTitle> <baseTitle :title="'项目附件'"></baseTitle>
</el-col> </el-col>
<el-form :model="attachmentParam" inline style="margin-left: 15px"> <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick" @tab-remove="tabRemove"
<el-form-item label="标签" prop="tag"> style="margin-left: 15px;margin-top: -10px">
<el-select v-model="attachmentParam.tag" placeholder="请选择标签" clearable filterable style="width: 300px"> <el-tab-pane name="all" :closable="false" label="全部">
<el-option </el-tab-pane>
v-for="item in tagsOption" <el-tab-pane v-for="item in tagsOption" :closable="item.isClose==1&&uploadState"
:key="item.value" :key="item.tagId"
:label="item.label" :label="item.fileTag"
:value="item.value" :name="item.tagId">
/> <div class="tag-title">
</el-select> <div></div>
</el-form-item> {{ item.fileTag }}
<el-form-item> </div>
<el-button @click="handleSearch" color="#DED0B2">搜索</el-button> </el-tab-pane>
<el-button v-if="uploadState&&isLineBtn" color="#DED0B2" @click="handleUpload">上传附件</el-button>
</el-form-item> <el-tab-pane name="plus" v-if="uploadState" :closable="false">
</el-form> <template #label>
<el-col v-if="!isLineBtn" :span="24" style="margin-bottom: 8px;margin-left: 15px"> <div style="margin-top: 4px;">
<el-button v-if="uploadState" color="#DED0B2" @click="handleUpload">上传附件</el-button> <el-icon color="#BEA266">
</el-col> <Plus/>
<fvTable style="width: 100%;min-height:311px;max-height: 311px" v-if="showAttachmentTable" height="311" </el-icon>
:tableConfig="executeTableConfig" class="execute-apply-table" </div>
:data="otherAttachmentList" :isSettingCol="false" :pagination="false"> </template>
<template #empty> </el-tab-pane>
<el-empty :image-size="90" description="暂无数据" style="padding: 0"/> </el-tabs>
</template>
</fvTable>
</el-row> </el-row>
<file-preview ref="filePreviewRef" :fullscreen="false" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl" <div style="margin-top:10px;margin-bottom: 8px;margin-left: 15px;display: flex">
<!-- <el-button color="#DED0B2" @click="handleUpload">上传附件</el-button>-->
<file-upload v-if="!isLineBtn&&uploadState&&activeName!='plus'&&activeName!='all'" @getFile="getFile"/>
<el-button color="#DED0B2" @click="handleEditTag"
v-if="activeName!='all'&&activeName!='plus'&&uploadState&&!isDefault"
style="margin-left: 10px;">编辑
</el-button>
</div>
<fvTable style="width: 100%;min-height:311px;max-height: 311px" v-if="showAttachmentTable" height="311"
:scrollbar-always-on="true"
:tableConfig="executeTableConfig" class="execute-apply-table"
:data="otherAttachmentList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="90" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
<div class="oper-page-btn" style="margin-right: 90px" v-if="uploadState">
<el-button color="#DED0B2" @click="handleSubmit()">提交</el-button>
</div>
<file-preview ref="filePreviewRef" :fullscreen="false" v-if="filePreviewShow" :fileName="filePreviewParam.fileName"
:fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/> :fileType="filePreviewParam.fileType"/>
<el-dialog v-model="tagNameShow" center width="450" top="40vh">
<div style="display: flex;align-items: center">标签
<el-input v-model="fileParam.tagName" placeholder="请输入标签名称" style="width: 335px;" clearable/>
</div>
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
<el-button color="#DED0B2" @click="changeTag()">确定</el-button>
<el-button @click="tagNameShow=false">取消</el-button>
</div>
</el-dialog>
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import {getTags} from "@/api/project-manage"; import {addTag, delTag, getTagList, updateTag} from "@/api/project-manage";
import {ElLoading, ElNotification} from "element-plus"; import {ElLoading, ElMessageBox, ElNotification} from "element-plus";
import {searchImplementationFileList} from "@/api/project-manage/attachment"; import {searchImplementationFileList, uploadFileList} from "@/api/project-manage/attachment";
import {deleteFile, downloadFile} from "@/api/project-demand";
import {nextTick, onActivated} from "vue";
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const attachmentParam = reactive({ const attachmentParam = reactive({
tag: '' tag: ''
}) })
const fileParam = ref({
tagName: ''
})
const uploadState = ref(false) const uploadState = ref(false)
const tagNameShow = ref(false)
const isDefault = ref(false)
const tagsOption = ref([]) const tagsOption = ref([])
const fileList = ref([])
const allFiles = ref([])
const showAttachmentTable = ref(true) const showAttachmentTable = ref(true)
const activeName = ref('all')
const props = defineProps({ const props = defineProps({
fileNameTableWidth: { fileNameTableWidth: {
@@ -72,6 +112,7 @@ const executeTableConfig = reactive({
label: '文件名', label: '文件名',
align: 'center', align: 'center',
width: props.fileNameTableWidth, width: props.fileNameTableWidth,
showOverflowTooltip: false,
currentRender: ({row, index}) => ( currentRender: ({row, index}) => (
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>) <div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
}, },
@@ -79,6 +120,7 @@ const executeTableConfig = reactive({
prop: 'tag', prop: 'tag',
label: '标签', label: '标签',
align: 'center', align: 'center',
showOverflowTooltip: false,
}, },
{ {
prop: 'size', prop: 'size',
@@ -95,12 +137,18 @@ const executeTableConfig = reactive({
return ( return (
<div> <div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button> <el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
{
uploadState.value ?
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => deleteSingleFile(row)}/> : ''
}
</div> </div>
) )
} }
} }
] ]
}) })
// row.newFile ?: ''
const otherAttachmentList = ref([]) const otherAttachmentList = ref([])
const filePreviewParam = ref({ const filePreviewParam = ref({
@@ -109,39 +157,288 @@ const filePreviewParam = ref({
fileType: 'pdf' fileType: 'pdf'
}) })
const filePreviewShow = ref(false) const filePreviewShow = ref(false)
const clickToPreview=(row)=>{ const uploadLoading = ref(false)
const isEdit = ref(false)
const isCloseByList = (index) => {
// otherAttachmentList.length>0?false:true
return otherAttachmentList.value.length == 0;
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const deleteSingleFile = (row) => {
console.log("🚀 ~ file: ", row)
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
if (row.newFile) {
const finalList = getLocalList().filter(item => item.fileId !== row.fileId);
localStorage.setItem(`implementAllFileList-${route.query.projectId}`, JSON.stringify(finalList))
} else {
otherAttachmentList.value.splice(otherAttachmentList.value.findIndex((item) => item.fileId === row.fileId), 1);
}
getAttachmentList()
activeName.value = 'all'
}
});
}
const changeTag = async () => {
let res = null
if (isEdit.value) {
res = await updateTag({
tagId: activeName.value,
fileTag: fileParam.value.tagName,
projectId: route.query.projectId,
})
changeFileList(fileParam.value.tagName, true)
} else {
res = await addTag({
projectId: route.query.projectId,
fileTag: fileParam.value.tagName
})
getAttachmentList()
fileParam.value.tagName = ''
activeName.value = 'all'
}
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagNameShow.value = false;
}
const tabRemove = async (val) => {
if (otherAttachmentList.value && otherAttachmentList.value.length > 0) {
ElNotification({
title: '提示',
message: '该标签下存在文件,不能删除标签。如需删除标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
ElMessageBox.confirm(`确认删除名称为${getTagName(val)}的标签吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
let res = await delTag(val)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
getTagsOption()
otherAttachmentList.value = allFiles.value
}
})
}
const handleEditTag = () => {
fileParam.value.tagName = getTagName(activeName.value)
if (otherAttachmentList.value && otherAttachmentList.value.length > 0) {
ElNotification({
title: '提示',
message: '该标签下存在文件,不能编辑标签。如需编辑标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
tagNameShow.value = true
isEdit.value = true
}
const getTagName = (name) => {
const tagArray = tagsOption.value.filter((item1) => item1.tagId == name)
let tagName = ''
if (tagArray && tagArray.length > 0) {
tagName = tagArray[0].fileTag
}
return tagName
}
const handleTabClick = (item, e) => {
const defaultArray = tagsOption.value.filter(item1 => item1.tagId == item.props.name)
if (defaultArray && defaultArray.length > 0) {
isDefault.value = defaultArray[0].isDefault == 1
} else {
isDefault.value = false
}
tagNameShow.value = item.props.name == 'plus';
if (item.props.name == 'plus') {
isEdit.value = false
fileParam.value.tagName = ''
}
if (item.props.name != 'plus') {
if (item.props.name == 'all') {
changeFileList('all')
} else {
changeFileList(getTagName(item.props.name))
}
// if (item.props.name == 'all') {
// otherAttachmentList.value = allFiles.value
// } else {
// otherAttachmentList.value = allFiles.value.filter(item1 => item1.tag == getTagName(item.props.name))
// }
}
// showAttachmentTable.value = false
// nextTick(() => {
// showAttachmentTable.value = true
// })
}
const compositeParam = (item) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: getTagName(activeName.value) || '项目实施',
}
}
const getFile = (val) => {
console.log('上传文件', val)
fileList.value = getLocalList()
let fileObj = compositeParam(val)
fileList.value.push(fileObj)
localStorage.setItem(`implementAllFileList-${route.query.projectId}`, JSON.stringify(fileList.value))
otherAttachmentList.value.push(fileObj)
// handleSubmit([fileObj])
}
const handleSubmit = async () => {
if (getLocalList().length == 0) {
ElNotification({
title: '提示',
message: '暂无文件可提交',
type: 'warning'
})
return;
} else {
let params = {
fileList: getLocalList(),
projectId: route.query.projectId,
targetState: "30"
}
let res = await uploadFileList(params)
if (res.code !== 1000) {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'success'
})
localStorage.removeItem(`implementAllFileList-${route.query.projectId}`)
// list.forEach(item => {
// otherAttachmentList.value.push(item)
// })
getAttachmentList()
fileList.value = []
}
// changeFileList('all',true)
}
}
const clickToPreview = (row) => {
filePreviewShow.value = false filePreviewShow.value = false
filePreviewParam.value = { filePreviewParam.value = {
fileUrl: row.url, fileUrl: row.url,
fileName: row.originalFileName, fileName: row.originalFileName,
fileType: row.fileType fileType: row.fileType
} }
nextTick(()=>{ nextTick(() => {
filePreviewShow.value = true filePreviewShow.value = true
}) })
} }
const handleSearch = () => { const changeFileList = (tag, flag) => {
let params = {}
if (tag == 'all') {
otherAttachmentList.value = allFiles.value
// params = {
// targetId: route.query.projectId,
// targetState: "30",
// }
otherAttachmentList.value = [...otherAttachmentList.value, ...getLocalList()];
} else {
const filw = getLocalList().filter(item1 => item1.tag === tag);
const filteredAllFiles = allFiles.value.filter(item1 => item1.tag === tag);
// 使用 fileId 作为唯一标识进行去重
const seen = new Set();
const uniqueFiles = [...filteredAllFiles, ...filw].filter(item => {
if (!seen.has(item.fileId)) {
seen.add(item.fileId);
return true;
}
return false;
});
otherAttachmentList.value = uniqueFiles;
// params = {
// targetId: route.query.projectId,
// targetState: "30",
// tag: tag
// }
}
showAttachmentTable.value = false
// searchImplementationFileList(params).then(res => {
// if (res.code === 1000) {
// if(tag == 'all'&&flag){
// // allFiles.value = res.data.fileList
// }else{
// otherAttachmentList.value =res.data.fileList
// }
if (flag) {
getTagsOption(flag)
}
nextTick(() => {
showAttachmentTable.value = true
})
// }
// })
}
const getLocalList = () => {
if (localStorage.getItem(`implementAllFileList-${route.query.projectId}`) && JSON.parse(localStorage.getItem(`implementAllFileList-${route.query.projectId}`))) {
return JSON.parse(localStorage.getItem(`implementAllFileList-${route.query.projectId}`))
} else {
return []
}
}
const getAttachmentList = () => {
const loading = ElLoading.service({fullscreen: true}) const loading = ElLoading.service({fullscreen: true})
let params = { let params = {
targetId: route.query.projectId, targetId: route.query.projectId,
targetState: "30" targetState: "30"
} }
if (attachmentParam.tag) { showAttachmentTable.value = false
tagsOption.value.forEach(item => {
if (item.value === attachmentParam.tag) {
attachmentParam.tag = item.label
}
})
params.tag = attachmentParam.tag
}
searchImplementationFileList(params).then(res => { searchImplementationFileList(params).then(res => {
showAttachmentTable.value = false
if (res.code === 1000) { if (res.code === 1000) {
otherAttachmentList.value = res.data.fileList otherAttachmentList.value = [...res.data.fileList, ...getLocalList()]
allFiles.value = [...res.data.fileList, ...getLocalList()]
uploadState.value = res.data.upload uploadState.value = res.data.upload
getTagsOption()
nextTick(() => { nextTick(() => {
showAttachmentTable.value = true showAttachmentTable.value = true
}) })
activeName.value = 'all'
loading.close() loading.close()
} else { } else {
ElNotification({ ElNotification({
@@ -153,11 +450,56 @@ const handleSearch = () => {
} }
}) })
} }
const getTagsOption = () => { const getTagsOption = (flag) => {
if (!route.query.projectId) return if (!route.query.projectId) return
getTags(route.query.projectId).then(res => { getTagList(route.query.projectId).then(res => {
if (res.code === 1000) { if (res.code === 1000) {
tagsOption.value = res.data
tagsOption.value = res.data.rows
let list = []
if (flag) {
list = allFiles.value
} else {
list = otherAttachmentList.value
}
tagsOption.value.forEach((tag, index) => {
// const filterArray = list.filter(item => tag.fileTag == item.tag)
// console.log("🚀 ~ file:filterArray ", filterArray)
tagsOption.value[index].isClose = 1
// tagsOption.value[index].isClose = filterArray.length > 0 ? 0 : 1
})
console.log("🚀 otherAttachmentList.value", allFiles.value)
console.log("🚀 ~ file:\tagsOption.value ", tagsOption.value)
let defaultArray = [
{
tagId: 'd1',
fileTag: '合同(专项任务书)',
isDefault: 1,
isClose: 2
},
{
tagId: 'd2',
fileTag: '周报',
isDefault: 1,
isClose: 2
},
{
tagId: 'd3',
fileTag: '阶段性验收',
isDefault: 1,
isClose: 2
},
{
tagId: 'd4',
fileTag: '科研成果',
isDefault: 1,
isClose: 2
}
]
tagsOption.value = [...defaultArray, ...tagsOption.value]
// if (!res.data.rows || res.data.rows.length == 0) return;
// activeName.value=res.data.rows[0].tagId
} else { } else {
ElNotification({ ElNotification({
title: '提示', title: '提示',
@@ -178,11 +520,9 @@ const handleUpload = () => {
} }
}) })
} }
handleSearch() getAttachmentList()
getTagsOption() onActivated(() => {
onActivated(()=>{ getAttachmentList()
handleSearch()
getTagsOption()
}) })
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -217,8 +557,52 @@ onActivated(()=>{
} }
} }
</style> </style>
<style scoped> <style scoped lang="scss">
:deep(.el-dialog__body) {
padding: 0 !important;
}
.tag-title {
display: flex;
align-items: center;
margin-top: 15px;
> div {
margin-right: 5px;
width: 4px;
height: 20px;
background-color: #BEA266;
}
}
:deep(.el-table--fit ) { :deep(.el-table--fit ) {
height: 311px !important; height: 311px !important;
} }
:deep(.el-tabs__nav) {
//width: 75vw;
}
:deep(.el-tabs__item) {
flex: none !important;
}
:deep(.el-tabs__header) {
margin-bottom: 0;
}
:deep(.el-tabs__item.is-active) {
color: #BEA266;
}
:deep(.el-tabs__active-bar) {
background-color: #BEA266;
}
.file-tag {
width: 100%;
display: flex;
border-bottom: 2px solid #f6f6f6;
/*align-items: center;*/
}
</style> </style>

View File

@@ -3,41 +3,88 @@
<el-form :model="localFormData" ref="summaryForm" :rules="rules"> <el-form :model="localFormData" ref="summaryForm" :rules="rules">
<baseTitle title="预期知识产权"></baseTitle> <baseTitle title="预期知识产权"></baseTitle>
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px"> <el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px">
<!-- <el-col :span="6">-->
<!-- <el-form-item label="预期成果形式" prop="resultForm">-->
<!-- <span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6"> <el-col :span="6">
<el-form-item label="预期成果形式" prop="resultForm"> <el-form-item label="知识产权归属" prop="intellectualProperty">
<span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="知识产权状况" prop="intellectualProperty">
<span>{{ <span>{{
filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty) filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty)
}}</span> }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="发明专利(项)" prop="inventionPatent"> <el-form-item label="预估专利(项)" prop="newPatent">
<span>{{ localFormData.inventionPatent }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="新型专利(项)" prop="newPatent">
<span>{{ localFormData.newPatent }}</span> <span>{{ localFormData.newPatent }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="软件著作权(项)" prop="softwareCopyright"> <el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
<span>{{ localFormData.softwareCopyright }}</span> <span>{{ localFormData.softwareCopyright }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="著作权(项)" prop="copyright"> <el-form-item label="预估技术标准(项)" prop="technicalNorms">
<span>{{ localFormData.copyright }}</span> <span>{{ localFormData.technicalNorms }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="其他(项)" prop="other"> <el-form-item label="预估新产品(项)" prop="newProduct">
<span>{{ localFormData.other }}</span> <span>{{ localFormData.newProduct }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新工艺(项)" prop="newProcess">
<span>{{ localFormData.newProcess }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新装置(项)" prop="newDevice">
<span>{{ localFormData.newDevice }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新材料(项)" prop="newMaterials">
<span>{{ localFormData.newMaterials }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
<span>{{ localFormData.computerSoftware }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估论文论著(项)" prop="thesis">
<span>{{ localFormData.thesis }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估研究报告(项)" prop="researchReport">
<span>{{ localFormData.researchReport }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估商标(项)" prop="trademark">
<span>{{ localFormData.trademark }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估其他(项)" prop="other">
<span style="white-space: pre-wrap">{{ localFormData.other }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -57,18 +104,18 @@
</el-row> </el-row>
<baseTitle title="需求上报申请书" style="margin-bottom: -3px;"></baseTitle> <baseTitle title="需求上报申请书" style="margin-bottom: -3px;"></baseTitle>
<!-- <el-row gutter="20" style="margin-bottom: -15px;">--> <!-- <el-row gutter="20" style="margin-bottom: -15px;">-->
<!-- <el-col :span="24">--> <!-- <el-col :span="24">-->
<!-- <single-file-component tag="需求上报" v-model:value="localFormData.singleFile" :processViewer="processViewer"/>--> <!-- <single-file-component tag="需求上报" v-model:value="localFormData.singleFile" :processViewer="processViewer"/>-->
<!-- &lt;!&ndash; <el-form-item>&ndash;&gt;--> <!-- &lt;!&ndash; <el-form-item>&ndash;&gt;-->
<!-- &lt;!&ndash; {{localFormData.singleFile}}&ndash;&gt;--> <!-- &lt;!&ndash; {{localFormData.singleFile}}&ndash;&gt;-->
<!-- &lt;!&ndash; <el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">&ndash;&gt;--> <!-- &lt;!&ndash; <el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">&ndash;&gt;-->
<!-- &lt;!&ndash; {{ localFormData.singleFile?.originalFileName }}&ndash;&gt;--> <!-- &lt;!&ndash; {{ localFormData.singleFile?.originalFileName }}&ndash;&gt;-->
<!-- &lt;!&ndash; </el-button>&ndash;&gt;--> <!-- &lt;!&ndash; </el-button>&ndash;&gt;-->
<!-- &lt;!&ndash; </el-form-item>&ndash;&gt;--> <!-- &lt;!&ndash; </el-form-item>&ndash;&gt;-->
<!-- </el-col>--> <!-- </el-col>-->
<!-- </el-row>--> <!-- </el-row>-->
<!--/* <baseTitle title="附件文件" style="margin-bottom: 0"></baseTitle>*/--> <!--/* <baseTitle title="附件文件" style="margin-bottom: 0"></baseTitle>*/-->
<el-row gutter="20" style="margin-bottom: -18px;"> <el-row gutter="20" style="margin-bottom: -18px;">
<el-col :span="24" class="file-table-style"> <el-col :span="24" class="file-table-style">
<file-component tag="需求上报" <file-component tag="需求上报"
@@ -99,8 +146,8 @@
</div> </div>
</div> </div>
<div v-perm="['annual:plan:approve']" v-if="data.state==='4'"> <div v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<baseTitle title="前置流程"></baseTitle> <!-- <baseTitle title="前置流程"></baseTitle>-->
<select-pre-process :formData="localFormData"/> <!-- <select-pre-process :formData="localFormData"/>-->
<baseTitle title="审核意见"></baseTitle> <baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value"> <el-form-item prop="_value">
<el-input <el-input
@@ -123,6 +170,9 @@
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd" style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/> />
</div> </div>
<el-button color="#DED0B2" style="margin-left: 10px"
@click="handleCarbonCopy()">立即抄送
</el-button>
</div> </div>
<div class="process"> <div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram" <operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
@@ -133,6 +183,10 @@
</div> </div>
</div> </div>
</el-form> </el-form>
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
@cancelOrClear="carbonCopyUserPickerOk"/>
<div class="oper-page-btn" v-perm="['annual:plan:approve']" v-if="data.state==='4'"> <div class="oper-page-btn" v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<el-button type="danger" @click="handleRejectPlan">驳回年度计划</el-button> <el-button type="danger" @click="handleRejectPlan">驳回年度计划</el-button>
<el-button color="#DED0B2" @click="handleAgreePlan">通过年度计划</el-button> <el-button color="#DED0B2" @click="handleAgreePlan">通过年度计划</el-button>
@@ -153,8 +207,10 @@ import FileComponent from "./FileComponent.vue";
import {ElNotification} from "element-plus"; import {ElNotification} from "element-plus";
import {approvePlan} from "@/api/project-demand/summary"; import {approvePlan} from "@/api/project-demand/summary";
import SelectPreProcess from "@/components/SelectPreProcess.vue"; import SelectPreProcess from "@/components/SelectPreProcess.vue";
import {applyCcSend} from "@/api/expense-manage";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value','ccSend'])
const tagsViewStore = useTagsView() const tagsViewStore = useTagsView()
const cacheStore = useCacheStore() const cacheStore = useCacheStore()
const props = defineProps({ const props = defineProps({
@@ -192,6 +248,8 @@ const router = useRouter()
const fundOption = ref([]) const fundOption = ref([])
const companyOption = ref([]) const companyOption = ref([])
const dictName = ref({}) const dictName = ref({})
const carbonCopyUserList = ref([])
const carbonCopyUserRef = ref()
const rules = reactive({ const rules = reactive({
auditOpinion: [{required: true, message: '请输入审核意见', trigger: 'blur'}], auditOpinion: [{required: true, message: '请输入审核意见', trigger: 'blur'}],
}) })
@@ -203,6 +261,39 @@ const _value = computed({
emit("update:value", val); emit("update:value", val);
} }
}) })
const handleCarbonCopy = () => {
carbonCopyUserRef.value.showUserPicker()
}
const carbonCopyUserPickerOk = (userList) => {
carbonCopyUserList.value = userList.map(item => item.id)
console.log('localFormData.value', props.data)
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
addUser()
}
const addUser = async () => {
const res = await applyCcSend({
instanceId: props.data.processInstanceId,
projectId: route.query.projectId,
state: route.query.step,
userIds: carbonCopyUserList.value
})
console.log('res', res)
if (res.code === 1000) {
ElNotification({
title: '提示',
message: '抄送成功',
type: 'success'
})
emit('ccSend')
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
}
const handleRejectPlan = async () => { const handleRejectPlan = async () => {
// const values = form.value.getValues() // const values = form.value.getValues()
// console.log('route',route.query.projectId) // console.log('route',route.query.projectId)
@@ -232,6 +323,14 @@ const handleRejectPlan = async () => {
}) })
} }
const handleAgreePlan = async () => { const handleAgreePlan = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = { const params = {
auditOpinion: _value.value, auditOpinion: _value.value,
projectId: parseInt(route.query.projectId), projectId: parseInt(route.query.projectId),
@@ -321,7 +420,8 @@ getFundOptions()
overflow-y: auto; overflow-y: auto;
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }
.file-table-style{
.file-table-style {
:deep(.el-table__header) { :deep(.el-table__header) {
.is-leaf:first-child { .is-leaf:first-child {
.cell { .cell {

View File

@@ -1,13 +1,14 @@
<template> <template>
<el-upload :file-list="_value" <el-upload :file-list="_value" ref="uploadRef"
:action="uploadFileUrl" action="#"
:headers="headers" :headers="headers"
:limit="maxSize" :limit="maxSize"
with-credentials with-credentials
:multiple="multiple" :multiple="multiple"
:data="uploadParams" :data="uploadParams" :on-change="handleChange"
:http-request="customUpload"
:show-file-list="showFileList" :show-file-list="showFileList"
:auto-upload="true" :auto-upload="false"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:on-error="uploadError" :on-error="uploadError"
@@ -19,16 +20,20 @@
</template> </template>
<script setup> <script setup>
import { ElMessageBox, ElNotification} from "element-plus"; import {ElLoading, ElMessage, ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth' import {getToken} from '@/utils/auth'
import {nextTick} from "vue";
import axios from "axios";
const baseURL = import.meta.env.VITE_BASE_URL const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload") const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload")
const headers = reactive({ const headers = reactive({
'Content-Type': 'multipart/form-data',
authorization: getToken() authorization: getToken()
}) })
const loading = ref(false) const loading = ref(false)
const showTable = ref(false) const showTable = ref(false)
const uploadIndex = ref(0)
const uploadParams = ref({}) const uploadParams = ref({})
const props = defineProps({ const props = defineProps({
value: { value: {
@@ -39,7 +44,7 @@ const props = defineProps({
}, },
maxSize: { maxSize: {
type: Number, type: Number,
default: 30 default: 999999
}, },
showFileList: { showFileList: {
type: Boolean, type: Boolean,
@@ -54,8 +59,9 @@ const props = defineProps({
default: true default: true
} }
}) })
const uploadRef = ref(null); // el-upload 的 ref
const emit = defineEmits(["input", "getFile", "delete"]) const uploadPromises = ref([]); // 跟踪每个文件的上传状态
const emit = defineEmits(["input", "beforeUpload","getFile", "delete"])
const fileList = ref([]) const fileList = ref([])
const _value = computed({ const _value = computed({
get() { get() {
@@ -73,9 +79,79 @@ const beforeRemove = (file) => {
}).then(() => true) }).then(() => true)
} }
const uploadLoading = ref(false)
const uploadFile = ref([])
const handleRemove = (file) => { const handleRemove = (file) => {
emit("delete", file.response.data.id) emit("delete", file.response.data.id)
} }
// 文件选择变化时触发
const handleChange = (file, files) => {
console.log(file, files,'files')
uploadIndex.value++
uploadFile.value.push(file)
};
watch(() => uploadIndex.value, (newVal) => {
console.log('newVal',newVal)
startUpload(uploadFile.value); // 自动触发上传
},{
deep: true
})
// 自定义上传逻辑
const customUpload = async (options) => {
const formData = new FormData();
formData.append('file', options.raw);
try {
const response = await axios.post(uploadFileUrl.value, formData, {
headers: headers,
});
fileList.value.push(response.data.data)
emit("getFile", response.data.data)
return response.data; // 成功时返回响应
} catch (error) {
throw new Error('上传失败'); // 失败时抛出错误
}
};
// 触发所有文件上传
const startUpload = (files) => {
uploadLoading.value= ElLoading.service({
fullscreen: true,
text: '文件上传中...',
})
if (files.length === 0) {
return; // 没有文件时直接返回
}
uploadPromises.value = []; // 重置 Promise 数组
files.forEach((file) => {
// 触发每个文件的上传
const promise = new Promise((resolve, reject) => {
customUpload(file).then(resolve)
.catch(reject);
});
uploadPromises.value.push(promise);
});
// 使用 Promise.all 监听所有文件上传完成
Promise.all(uploadPromises.value)
.then(() => {
ElNotification({
title: '提示',
message: '所有文件上传完成!',
type: 'success'
})
files = []; // 清空文件列表
uploadRef.value.clearFiles(); // 清空上传组件
nextTick(() => {
uploadLoading.value.close()
uploadLoading.value=null
})
})
};
const beforeUpload = () => { const beforeUpload = () => {
loading.value = true loading.value = true
return true return true

View File

@@ -0,0 +1,114 @@
<template>
<el-upload :file-list="[]"
:limit="maxSize"
with-credentials
:multiple="multiple"
:http-request="httpRequestHandle"
:data="uploadParams"
:auto-upload="true"
:show-file-list="false"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-button color="#DED0B2" style="margin-right: 10px;" :disabled="disabled">导入</el-button>
</el-upload>
</template>
<script setup>
import {ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
})
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/mosr/rd/expense/import")
const headers = reactive({
authorization: getToken()
})
// const loading = ref(false)
const uploadParams = ref({})
const emit = defineEmits(["input", "getFile", "delete"])
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
const beforeUpload = () => {
// loading.value = true
return true
}
const httpRequestHandle = (param) => {
let file = param.file
axios.post(uploadFileUrl.value, {
file: file
}, {
headers: {
'Content-Type': 'multipart/form-data',
...headers
}
}).then(res => {
handleUploadSuccess(res)
}).catch(error => {
uploadError(error)
})
}
const handleUploadSuccess = (res) => {
let data = res.data
ElNotification({
title: '提示',
message: data.code === 1000 ? '上传成功' : '上传失败',
type: data.code === 1000 ? 'success' : 'error'
})
emit("success")
}
const uploadError = (error) => {
console.log("🚀 ~ file:'error ", error.response.data.msg)
// loading.value = false
ElNotification({
title: '提示',
message: error.response.data.msg,
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
</style>

View File

@@ -4,8 +4,8 @@
<el-form-item label="名称" prop="fileName"> <el-form-item label="名称" prop="fileName">
<el-input v-model="attachment.fileName" placeholder="请输入文件名查询" clearable filterable style="width: 300px"/> <el-input v-model="attachment.fileName" placeholder="请输入文件名查询" clearable filterable style="width: 300px"/>
</el-form-item> </el-form-item>
<el-form-item label="类型" prop="targetState" v-if="allFile"> <el-form-item label="项目阶段" prop="targetState" v-if="allFile">
<el-select v-model="attachment.targetState" placeholder="请选择类型" clearable filterable style="width: 300px"> <el-select v-model="attachment.targetState" placeholder="请选择项目阶段" clearable filterable style="width: 300px">
<el-option <el-option
v-for="item in cacheStore.getDict('archive_file_type')" v-for="item in cacheStore.getDict('archive_file_type')"
:key="item.value" :key="item.value"
@@ -31,7 +31,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-card style="width: 100%;overflow-y: hidden"> <el-card style="width: 100%;overflow-y: hidden">
<fvTable style="width: 100%;max-height: 318px" v-if="showTable" height="318" :tableConfig="tableConfig" <fvTable style="width: 100%;max-height: 318px" v-if="showTable" height="318" :tableConfig="allFile?tableConfigAll:tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false"> :data="fileList" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
<el-empty :image-size="99" description="暂无数据" style="padding: 0"/> <el-empty :image-size="99" description="暂无数据" style="padding: 0"/>
@@ -96,7 +96,67 @@ const tableConfig = reactive({
}, },
{ {
prop: 'tag', prop: 'tag',
label: '标签', label:'标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'createTime',
label: '上传时间',
align: 'center',
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const tableConfigAll = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width:85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'targetState',
label:'项目阶段',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
if (row.targetState&&row.targetState !== null&&row.targetState!==undefined) {
return (<Tag dictType={'archive_file_type'} value={row.targetState}/>)
} else {
return '--'
}
}
},
{
prop: 'tag',
label:'标签',
align: 'center' align: 'center'
}, },
{ {

View File

@@ -28,7 +28,8 @@
</el-form> </el-form>
<el-table :data="preProcessList" v-loading="loading" <el-table :data="preProcessList" v-loading="loading"
@select="handleSelect" @select-all="handleSelect" row-key="requestId" ref="preProcessTable"> @select="handleSelect" @select-all="handleSelect" row-key="requestId" ref="preProcessTable">
<el-table-column type="selection" width="55" :reserve-selection="true"/> <el-table-column type="selection" width="55" :reserve-selection="true"
:selectable="checkSelectable"/>
<el-table-column prop="requestId" label="请求id"></el-table-column> <el-table-column prop="requestId" label="请求id"></el-table-column>
<el-table-column prop="requestName" label="请求名称"></el-table-column> <el-table-column prop="requestName" label="请求名称"></el-table-column>
<el-table-column prop="lastOperatorName" label="最后操作人名称"></el-table-column> <el-table-column prop="lastOperatorName" label="最后操作人名称"></el-table-column>
@@ -70,11 +71,13 @@ const props = defineProps({
}) })
const loading = ref(false) const loading = ref(false)
//暂存数据 //暂存数据
const originalProcess = ref([])
const currentList = ref([]) const currentList = ref([])
const showPreTable = ref(false) const showPreTable = ref(false)
const selectRows = ref([]) const selectRows = ref([])
const preProcessList = ref([]) const preProcessList = ref([])
const total = ref(0) const total = ref(0)
const preProcessTable = ref()
const localFormData = ref({ const localFormData = ref({
projectPersonIds: [], projectPersonIds: [],
projectChargePerson: null, projectChargePerson: null,
@@ -102,7 +105,7 @@ const getPreProcessTag = (impact,basicImpact) => {
} }
if (data == 1) { if (data == 1) {
//一般项目 //一般项目
return '一般项目20万以下要总经理审批' return '研发费用20万元以下科技创新项目报总经理审批'
} else if (data == 2) { } else if (data == 2) {
//重大项目 //重大项目
return '重大项目20万元到500万元之间要总办会审批' return '重大项目20万元到500万元之间要总办会审批'
@@ -118,8 +121,33 @@ const handleReset = () => {
const handleSelect = async (selection) => { const handleSelect = async (selection) => {
selectRows.value = selection selectRows.value = selection
} }
const checkSelectable=(row)=>{
const detailProcessStr = localStorage.getItem('detailProcess');
let preProcessArray = []
if (detailProcessStr) {
try {
preProcessArray = JSON.parse(detailProcessStr)
} catch (e) {
preProcessArray=[]
}
if (preProcessArray&&preProcessArray.length > 0) {
for (let i = 0; i < preProcessArray.length; i++) {
return preProcessArray[i].requestId !== row.requestId;
}
}else{
return true
}
}
}
const handleShowPreTable = () => { const handleShowPreTable = () => {
showPreTable.value = true showPreTable.value = true
nextTick(() => {
localFormData.value.preProcess?.forEach((item) => {
if (preProcessTable.value) {
preProcessTable.value.toggleRowSelection(item, true)
}
})
})
getPreProcessList() getPreProcessList()
} }
const handleCancel = () => { const handleCancel = () => {
@@ -129,17 +157,30 @@ const handleCancel = () => {
const choosePreProcess = () => { const choosePreProcess = () => {
let preProcessObj = {} let preProcessObj = {}
let preProcessArray = [] let preProcessArray = []
const detailProcessStr = localStorage.getItem('detailProcess');
try {
originalProcess.value = JSON.parse(detailProcessStr)
} catch (e) {
originalProcess.value=[]
}
selectRows.value.forEach((item) => { selectRows.value.forEach((item) => {
preProcessObj = { const exists = originalProcess.value?.some(dp => dp.requestId === item.requestId)
requestId: item.requestId, if (!exists) {
requestName: item.requestName, preProcessObj = {
baseUrl: item.baseUrl requestId: item.requestId,
requestName: item.requestName,
baseUrl: item.baseUrl
}
preProcessArray.push(preProcessObj)
} }
preProcessArray.push(preProcessObj)
}) })
localFormData.value.preProcess = preProcessArray if(props.formData.mode === 'view'||props.formData.mode === 'resubmit'){
showPreTable.value = false localFormData.value.preProcess = [...originalProcess.value,...preProcessArray]
}else{
localFormData.value.preProcess = preProcessArray
}
localStorage.setItem('preProcess', JSON.stringify(preProcessArray)) localStorage.setItem('preProcess', JSON.stringify(preProcessArray))
showPreTable.value = false
} }
const getPreProcessList = () => { const getPreProcessList = () => {
@@ -154,13 +195,6 @@ const getPreProcessList = () => {
searchArray.push(item) searchArray.push(item)
} }
}) })
// res.data.forEach((item) => {
// localFormData.value.preProcess.forEach((item1) => {
// if (item.requestId == item1.requestId) {
// preProcessTable.value.toggleRowSelection(item)
// }
// })
// })
total.value = searchArray.length total.value = searchArray.length
currentList.value = searchArray currentList.value = searchArray
preProcessList.value = currentList.value.slice(0, 10) preProcessList.value = currentList.value.slice(0, 10)
@@ -177,6 +211,7 @@ const handleCurrentChange = (val) => {
pageInfo.pageNum = val; pageInfo.pageNum = val;
preProcessList.value = currentList.value.slice((val - 1) * pageInfo.pageSize, val * pageInfo.pageSize) preProcessList.value = currentList.value.slice((val - 1) * pageInfo.pageSize, val * pageInfo.pageSize)
}; };
watchEffect(() => { watchEffect(() => {
return Object.keys(props.formData).length && (localFormData.value = props.formData) return Object.keys(props.formData).length && (localFormData.value = props.formData)
}) })

View File

@@ -38,7 +38,7 @@ import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/autosave' import 'tinymce/plugins/autosave'
import '@/assets/axupimgs/plugin.js'//多图上传插件 import '@/assets/axupimgs/plugin.js'//多图上传插件
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value','getFiles'])
const props = defineProps({ const props = defineProps({
//默认值 //默认值
value: { value: {
@@ -56,7 +56,6 @@ const props = defineProps({
plugins: { plugins: {
type: [String, Array], type: [String, Array],
default: default:
//
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image axupimgs link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave", "preview searchreplace autolink directionality visualblocks visualchars fullscreen image axupimgs link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave",
}, },
toolbar: { toolbar: {
@@ -79,6 +78,7 @@ const props = defineProps({
default: 500 default: 500
} }
}) })
const fileLists=ref([])
const content = ref(props.value); const content = ref(props.value);
const imgUrl = ref(); const imgUrl = ref();
// const apiKey = reactive("v4zo4n22oanvco29ws5drh0pecuf3gh53clx53cccj3grjwg"); // const apiKey = reactive("v4zo4n22oanvco29ws5drh0pecuf3gh53clx53cccj3grjwg");
@@ -169,6 +169,15 @@ const init = reactive({
type: res.code === 1000 ? 'success' : 'error' type: res.code === 1000 ? 'success' : 'error'
}) })
loading.close() loading.close()
console.log("🚀 ~ file:res.data ", res.data)
res.data.originalFileName=res.data.originalFilename
console.log("🚀 ~ file:'meta.filetype ",meta.filetype )
if (res && res.data && res.data.fileType &&
!["png", "jpg", "jpeg","gif", "svg","ico"].includes(res.data.fileType.toLowerCase())){
fileLists.value.push(res.data)
emit('getFiles',fileLists.value)
}
const fileUrl = res.data.url; const fileUrl = res.data.url;
// '?fileId='+res.data.id+ // '?fileId='+res.data.id+
callback(fileUrl + '?fileName=' + res.data.originalFilename, {text: file.name, title: file.name}); callback(fileUrl + '?fileName=' + res.data.originalFilename, {text: file.name, title: file.name});

View File

@@ -279,7 +279,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -294,6 +294,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -334,7 +350,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6

View File

@@ -1,5 +1,8 @@
<template> <template>
<div class="fv-table-container"> <div class="fv-table-container">
<el-button v-if="tableConfig.export && tableConfig.export.open&&changeExportPosition" @click="exportTable" color="#DED0B2"
style="float: left;margin-right: 10px">导出
</el-button>
<!-- 表格头部按钮 --> <!-- 表格头部按钮 -->
<div class="fv-table-btn" v-if="tableConfig.btns"> <div class="fv-table-btn" v-if="tableConfig.btns">
<div class="table-head-btn"> <div class="table-head-btn">
@@ -15,7 +18,7 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<el-button v-if="tableConfig.export && tableConfig.export.open" @click="exportTable" color="#DED0B2" <el-button v-if="tableConfig.export && tableConfig.export.open&&!changeExportPosition" @click="exportTable" color="#DED0B2"
style="margin-bottom: 10px">导出 style="margin-bottom: 10px">导出
</el-button> </el-button>
<!-- 列显示配置 --> <!-- 列显示配置 -->
@@ -121,6 +124,11 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: true default: true
}, },
//是否改变导出位置, 导出在btns前面
changeExportPosition: {
type: Boolean,
default: false
},
// 是否显示列配置 // 是否显示列配置
isSettingCol: { isSettingCol: {
type: Boolean, type: Boolean,

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="link-box"> <div class="link-box">
<el-scrollbar noresize height="34" > <el-scrollbar noresize height="36" >
<!-- style="display: flex"--> <!-- style="display: flex"-->
<div > <div >
<router-link <router-link

View File

@@ -37,9 +37,11 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
if (res.code === 1000) { if (res.code === 1000) {
const sRouter = JSON.parse(JSON.stringify(res.data)) const sRouter = JSON.parse(JSON.stringify(res.data))
const mData = JSON.parse(JSON.stringify(res.data)) const mData = JSON.parse(JSON.stringify(res.data))
// console.log(JSON.parse(JSON.stringify(sRouter)), 'sRouter');
const firstFormat = setRouterLevel(JSON.parse(JSON.stringify(sRouter))) const firstFormat = setRouterLevel(JSON.parse(JSON.stringify(sRouter)))
console.log(firstFormat, 'firstFormat');
asyncRouters.value = formatAsyncRouters(JSON.parse(JSON.stringify(firstFormat))) asyncRouters.value = formatAsyncRouters(JSON.parse(JSON.stringify(firstFormat)))
console.log('asyncRouters.value',firstFormat);
menuList.value = [...menuList.value, ...generateMenu(mData)] menuList.value = [...menuList.value, ...generateMenu(mData)]
addAsyncRouters(asyncRouters.value) addAsyncRouters(asyncRouters.value)
isLoadRoutes.value = false isLoadRoutes.value = false
@@ -52,16 +54,23 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
} }
const setRouterLevel = (routers) => { const setRouterLevel = (routers) => {
return routers.filter(item=>{ return routers.filter(item=>{
if(item.component === 'Layout') { if(item.component === 'Layout') {
if(item.children) { if(item.children) {
// console.log("🚀 ~ file: item.children ", item.children )
item.children.forEach(v=>{ item.children.forEach(v=>{
if(v.children) { if(v.children) {
slRouters.value = [...toRaw(slRouters.value), ...v.children] // console.log("🚀 ~ file:item.children",item.children)
delete v.children // console.log("🚀 ~ file: v.children ", v.children )
// slRouters.value = [ ...toRaw(v.children)]
// delete v.children
// slRouters.value = [ ...v.children]
// return v.children
item.children = [...item.children,...v.children]
} }
}) })
item.children = [...item.children, ...toRaw(slRouters.value)]
} }
} }
return true return true
@@ -81,6 +90,7 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
} }
if (route.children !== null && route.children && route.children.length !== 0) { if (route.children !== null && route.children && route.children.length !== 0) {
route.children = formatAsyncRouters(route.children) route.children = formatAsyncRouters(route.children)
} }
return true return true
}) })
@@ -90,6 +100,8 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
routers.forEach(route => { routers.forEach(route => {
router.addRoute(route) router.addRoute(route)
}) })
console.log("🚀 ~ file: ", routers)
} }
const generateMenu = (routes) => { const generateMenu = (routes) => {

View File

@@ -1,36 +1,68 @@
<template> <template>
<div v-loading="loading" class="add-block"> <div v-loading="loading" class="add-block">
<baseTitle title="文章信息录入"></baseTitle> <baseTitle title="文章信息录入"></baseTitle>
<el-form :model="formData" ref="fundForm" :rules="rules" style="margin-left: 5px;margin-bottom: -18px"> <el-form :model="formData" ref="fundForm" :rules="rules" style="margin-left: 5px;margin-bottom: -18px">
<el-row gutter="30"> <el-row gutter="30">
<el-col :span="6" style="margin-left: 10px"> <el-col :span="6" style="margin-left: 10px">
<el-form-item label="文章标题" prop="articleTitle"> <el-form-item label="文章标题" prop="articleTitle">
<el-input v-model="formData.articleTitle" placeholder="请输入文章标题" clearable></el-input> <el-input v-model="formData.articleTitle" placeholder="请输入文章标题" clearable></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="文章类型" prop="articleType"> <el-form-item label="文章类型" prop="articleType">
<el-select v-model="formData.articleType" placeholder="请选择文章类型" clearable filterable> <el-select v-model="formData.articleType" placeholder="请选择文章类型" clearable filterable>
<el-option <el-option
v-for="item in cacheStore.getDict('article_type')" v-for="item in cacheStore.getDict('article_type')"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" > <el-col :span="6">
<el-form-item label="备注" prop="remarks"> <el-form-item label="发文单位" prop="remarks">
<el-input v-model="formData.remarks" placeholder="请输入备注" clearable></el-input> <el-input v-model="formData.remarks" placeholder="请输入发文单位" clearable></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24" style="margin-left: 10px"> <el-col :span="24" style="margin-left: 10px">
<el-form-item label="文章内容" prop="articleContent"> <el-form-item label="文章内容" prop="articleContent">
<Tinymce v-model:value="formData.articleContent" imageUrl="/workflow/process/file/upload" :height="500" v-if="showTinymce" :toolbar="['undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image axupimgs']" /> <!-- link-->
<Tinymce v-model:value="formData.articleContent"
imageUrl="/workflow/process/file/upload" :height="500" v-if="showTinymce"
:toolbar="['undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image axupimgs']"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24" style="margin-bottom: -10px">
<el-form-item label="附件上传" prop="" style="margin-left: 20px;">
<file-upload @getFile="getFiles"/>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-left:90px;">
<!-- <el-form-item label="公告附件列表" prop=""-->
<!-- style="display: flex;flex-direction: column;justify-content: flex-start;">-->
<!-- <template #label>-->
<!-- <div style="width: 100%;display: flex;align-items: center;justify-content: flex-start">-->
<!-- <el-icon size="16">-->
<!-- <Paperclip/>-->
<!-- </el-icon>-->
<!-- 公告附件列表-->
<!-- </div>-->
<!-- </template>-->
<el-col :span="24" style="margin-left: -15px">
<div style="display: flex;flex-direction: column">
<div v-for="(item,index) in formData.fileList" style="display: flex;align-items: center;margin-bottom: 5px">
附件{{ index + 1 }} <a :href="item.url" style="color: #409eff;" class="a-style" target="_blank">{{ item.originalFileName }}</a>
<el-icon size="18" style="margin:0 20px;cursor: pointer" color="#409eff" @click="handleDelete(item,index)">
<CircleClose/>
</el-icon>
<el-button type="primary" link @click="handleDownload(item)" style="font-size: 16px;margin-left: 10px">下载</el-button>
</div>
</div>
</el-col>
<!-- </el-form-item>-->
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="oper-page-btn"> <div class="oper-page-btn">
@@ -42,10 +74,14 @@
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import {ElNotification} from "element-plus"; import {ElMessageBox, ElNotification} from "element-plus";
import {addArticle, editArticle, getArticleDetail} from "@/api/article"; import {addArticle, editArticle, getArticleDetail} from "@/api/article";
import {useTagsView} from '@/stores/tagsview.js' import {useTagsView} from '@/stores/tagsview.js'
import { useCacheStore } from "@/stores/cache.js"; import {useCacheStore} from "@/stores/cache.js";
import {deleteFile, downloadFile} from "../../api/project-demand";
import FileUpload from "../../components/FileUpload.vue";
import Tinymce from "../../components/Tinymce.vue";
const cacheStore = useCacheStore(); const cacheStore = useCacheStore();
const tagsViewStore = useTagsView() const tagsViewStore = useTagsView()
const router = useRouter() const router = useRouter()
@@ -53,26 +89,79 @@ const route = useRoute()
const loading = ref(false) const loading = ref(false)
const showTinymce = ref(true) const showTinymce = ref(true)
const fundForm = ref() const fundForm = ref()
const formData = ref({}) const formData = ref({
fileList:[]
})
const routerName = ref(router.currentRoute.value.name) const routerName = ref(router.currentRoute.value.name)
const rules = reactive({ const rules = reactive({
articleTitle: [{required: true, message: '请输入文章标题', trigger: ['blur', 'change']}], articleTitle: [{required: true, message: '请输入文章标题', trigger: ['blur', 'change']}],
articleType: [{required: true, message: '请输入文章类型', trigger: ['blur', 'change']}], articleType: [{required: true, message: '请输入文章类型', trigger: ['blur', 'change']}],
articleContent: [{required: true, message: '请输入文章内容', trigger: ['blur', 'change']}], articleContent: [{required: true, message: '请输入文章内容', trigger: ['blur', 'change']}],
}) })
const handleDelete = (row,index) => {
ElMessageBox.confirm(`确认删除名称为${row.originalFileName}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
formData.value.fileList.splice(index, 1)
}
})
})
}
const handleBack = () => { const handleBack = () => {
history.back() history.back()
} }
const getFiles = (val) => {
console.log("🚀 ~ file:val ", val)
val.originalFileName=val.originalFilename
let file = compositeParam(val)
formData.value.fileList.push(file)
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const submitParam = (item) => { const submitParam = (item) => {
console.log("🚀 ~ file:item.fileList ", item.fileList)
item.fileList= item.fileList.map((it)=>{
return {
...it,
articleId:item.articleId
}
})
return { return {
articleContent: item.articleContent, articleContent: item.articleContent,
articleTitle: item.articleTitle, articleTitle: item.articleTitle,
articleType: item.articleType, articleType: item.articleType,
remarks: item.remarks, remarks: item.remarks,
articleId: item.articleId,
fileList: item.fileList
} }
} }
const compositeParam = (item) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: 'article'
}
}
const handleSubmit = async (instance) => { const handleSubmit = async (instance) => {
if (!instance) return if (!instance) return
instance.validate(async (valid) => { instance.validate(async (valid) => {
@@ -104,6 +193,7 @@ const handleResubmit = () => {
articleId: route.query.id, articleId: route.query.id,
...submitParam(formData.value) ...submitParam(formData.value)
} }
console.log('params', params)
editArticle(params).then(res => { editArticle(params).then(res => {
ElNotification({ ElNotification({
title: '提示', title: '提示',
@@ -124,11 +214,11 @@ const getDetailInfo = async () => {
if (res.code === 1000) { if (res.code === 1000) {
formData.value = res.data formData.value = res.data
loading.value = false loading.value = false
showTinymce.value=false showTinymce.value = false
nextTick(() => { nextTick(() => {
showTinymce.value=true showTinymce.value = true
}) })
}else{ } else {
ElNotification({ ElNotification({
title: '提示', title: '提示',
message: res.msg, message: res.msg,
@@ -145,6 +235,9 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.a-style:hover{
text-decoration: underline !important;
}
.company-select { .company-select {
:deep(.el-form-item__content .el-select__wrapper ) { :deep(.el-form-item__content .el-select__wrapper ) {
width: 750px; width: 750px;
@@ -166,6 +259,7 @@ onMounted(async () => {
height: auto; height: auto;
} }
} }
:deep(.el-table--fit ) { :deep(.el-table--fit ) {
height: 300px !important; height: 300px !important;
} }
@@ -176,9 +270,11 @@ onMounted(async () => {
:deep(.el-input-number) { :deep(.el-input-number) {
width: 88.5%; width: 88.5%;
.el-input__wrapper{
padding: 1px 11px!important; .el-input__wrapper {
padding: 1px 11px !important;
} }
.el-input__inner { .el-input__inner {
text-align: left; text-align: left;
} }

View File

@@ -5,7 +5,7 @@
<div class="article-title"> <div class="article-title">
<Tag dictType="article_type" :value="formData.articleType"/> <Tag dictType="article_type" :value="formData.articleType"/>
<span>{{ formData.articleTime }}</span> <span>{{ formData.articleTime }}</span>
<span>备注{{ formData.remarks }}</span> <span>发文单位{{ formData.remarks }}</span>
</div> </div>
<el-row gutter="20"> <el-row gutter="20">
<el-col :span="24"> <el-col :span="24">
@@ -13,6 +13,14 @@
<div class="article-a" v-html="formData.articleContent" @click="clickHandle"></div> <div class="article-a" v-html="formData.articleContent" @click="clickHandle"></div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<div style="display: flex;flex-direction: column">
<div v-for="(item,index) in formData.fileList" style="display: flex;align-items: center;margin-bottom: 5px">
附件{{ index + 1 }} <a :href="item.url" style="color: #409eff;" class="a-style" target="_blank">{{ item.originalFileName }}</a>
<el-button type="primary" link @click="handleDownload(item)" style="font-size: 16px;margin-left: 10px">下载</el-button>
</div>
</div>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
</div> </div>
@@ -43,7 +51,7 @@ const clickHandle = (e) => {
fileName fileName
} }
// handleDownload(fileId,fileName) // handleDownload(fileId,fileName)
download(item) // download(item)
// }else { // }else {
// e.preventDefault() // e.preventDefault()
// } // }
@@ -64,6 +72,15 @@ const clickHandle = (e) => {
// }) // })
// }) // })
// } // }
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const download = (row) => { const download = (row) => {
const x = new window.XMLHttpRequest(); const x = new window.XMLHttpRequest();
x.open('GET', row.url, true); x.open('GET', row.url, true);
@@ -101,6 +118,7 @@ onMounted(async () => {
</script> </script>
<style lang="scss"> <style lang="scss">
.article-a { .article-a {
a { a {
color: #409eff !important; color: #409eff !important;
@@ -112,7 +130,9 @@ onMounted(async () => {
} }
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
.a-style:hover{
text-decoration: underline !important;
}
.article-detail { .article-detail {
padding: 0 30px; padding: 0 30px;
padding-top: 15px; padding-top: 15px;

View File

@@ -93,8 +93,15 @@ const articleTableConfig = reactive({
}, },
{ {
prop: 'remarks', prop: 'remarks',
label: '备注', label: '发文单位',
align: 'center' align: 'center',
currentRender: ({row, index}) => {
if (!row.remarks|| row.remarks == undefined || row.remarks == null) {
return '--'
} else {
return row.remarks
}
}
}, },
{ {
prop: 'oper', prop: 'oper',

View File

@@ -0,0 +1,275 @@
<template>
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 15px"></fvSearchForm>
<div style="float: left">
<import-cost-excel @success="importTheExpenseLedger"/>
</div>
<fvTable ref="tableIns" class="tablte" :tableConfig="tableConfig" @headBtnClick="headBtnClick" :changeExportPosition="true">
<template #empty>
<el-empty description="暂无数据"/>
</template>
</fvTable>
</template>
<script setup lang="jsx">
import {reactive, ref} from "vue";
import {useRoute, useRouter} from "vue-router";
import {costTemplateDownload, exportExcel, ledgerTemplateDownload} from "../../../api/project-manage";
import ImportCostExcel from "@/components/ImportCostExcel.vue";
const router = useRouter()
const route = useRoute()
const searchConfig = ref([
{
label: '主项目',
prop: 'masterProjectName',
component: 'el-input',
props: {
placeholder: '请输入主项目查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
{
label: '子项目',
prop: 'subProjectName',
component: 'el-input',
props: {
placeholder: '请输入子项目查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
{
label: '会计凭证记载金额(元)',
prop: 'recordedAmount',
component: 'el-input',
props: {
placeholder: '请输入会计凭证记载金额查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
{
label: '归集研发费用金额(元)',
prop: 'rdAmount',
component: 'el-input',
props: {
placeholder: '请输入归集研发费用金额查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
// {
// label: '项目类型',
// prop: 'projectType',
// component: shallowRef(fvSelect),
// props: {
// placeholder: '请选择项目类型',
// cacheKey: 'project_type',
// clearable: true,
// filterable: true,
// remote: true
// },
// colProps: {}
// },
// {
// label: '归档时间',
// prop: 'filingTime',
// component: 'el-date-picker',
// props: {
// placeholder: '请选择归档时间',
// clearable: true,
// type:'date',
// format: 'YYYY-MM-DD HH:mm',
// valueFormat:'YYYY-MM-DD HH:mm',
// },
// colProps: {}
// },
])
const tableIns = ref()
const tableConfig = reactive({
columns: [
// {
// prop: 'name',
// type: 'index',
// label: '序号',
// align: 'center',
// width:85,
// index: index => {
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
// }
// },
{
prop: 'rdYear',
label: '年',
align: 'center',
width: 80
},
{
prop: 'rdMonth',
label: '月',
align: 'center',
width: 80
},
{
prop: 'rdDay',
label: '日',
align: 'center',
width: 80
},
{
prop: 'masterProjectName',
label: '主项目',
align: 'center',
width: 120,
},
{
prop: 'subProjectName',
label: '子项目',
align: 'center',
width: 120,
},
{
prop: 'certificateDate',
label: '凭证日期',
align: 'center',
width: 120,
},
{
prop: 'voucherNumber',
label: '凭证号',
align: 'center'
},
{
prop: 'entryNumber',
label: '分录号',
align: 'center',
},
{
prop: 'digest',
label: '摘要',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'accountCode',
label: '科目编码',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'accountName',
label: '科目名称',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'auxiliaryItem',
label: '辅助项',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'recordedAmount',
label: '会计凭证记载金额(元)',
align: 'center',
width: 170
},
{
prop: 'rdAmount',
label: '归集研发费用金额(元)',
align: 'center',
width: 170
},
],
api: '/workflow/mosr/rd/expense/list',
params: {},
btns: [
{name: '模板下载', key: 'down', color: '#DED0B2'},
// {name: '导入', key: 'import', color: '#DED0B2'}
],
export:{
open :true,
fileName:`研发费用明细表`
}
})
const search = (val) => {
tableConfig.params = {...val}
tableIns.value.refresh()
}
const headBtnClick = (key) => {
switch (key) {
case 'down':
handleImportTemplateDownload()
break;
case 'import':
handleAdd()
break;
}
}
const exportTable = () => {
const $e = tableIns.value.$el
let $table = $e.querySelector('.el-table__fixed')
if (!$table) {
$table = $e
}
exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表", 2)
}
//导入模板下载
const handleImportTemplateDownload=()=>{
costTemplateDownload().then(res => {
let link = document.createElement('a')
try {
let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'});
let _fileName = "研发费用明细表模板.xlsx"//文件名,中文无法解析的时候会显示 _(下划线),生产环境获取不到
link.style.display='none';
// 兼容不同浏览器的URL对象
const url = window.URL || window.webkitURL || window.moxURL;
link.href=url.createObjectURL(blob);
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_')+1))
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
url.revokeObjectURL(link.href);//销毁url对象
}catch (e) {
console.log('下载的文件出错',e)
}
})
}
const importTheExpenseLedger = () => {
tableIns.value.refresh()
}
</script>
<style scoped lang="scss">
:deep(.el-form-item__label-wrap){
margin-left: 0!important;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
:deep(.el-date-editor--month){
width: 100%;
}
</style>

View File

@@ -0,0 +1,232 @@
<template>
<fvSearchForm :searchConfig="searchConfig" @search="search" ></fvSearchForm>
<fvTable ref="tableIns" :tableConfig="tableConfig" >
<template #empty>
<el-empty description="暂无数据"/>
</template>
</fvTable>
</template>
<script setup lang="jsx">
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
import {toThousands} from '@/utils/changePrice.js'
import { getSubCompOpt } from '@/api/user/user.js';
const router = useRouter()
const route = useRoute()
const searchConfig = ref(
[
{
label: '主项目',
prop: 'masterProjectName',
component: 'el-input',
props: {
placeholder: '请输入主项目查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
{
label: '子项目',
prop: 'subProjectName',
component: 'el-input',
props: {
placeholder: '请输入子项目查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
{
label: '项目类型',
prop: 'projectType',
component: shallowRef(fvSelect),
props: {
placeholder: '请选择项目类型',
cacheKey: 'project_type',
clearable: true,
filterable: true,
remote: true
},
colProps: {}
},
// {
// label: '归档时间',
// prop: 'filingTime',
// component: 'el-date-picker',
// props: {
// placeholder: '请选择归档时间',
// clearable: true,
// type:'date',
// format: 'YYYY-MM-DD HH:mm',
// valueFormat:'YYYY-MM-DD HH:mm',
// },
// colProps: {}
// },
])
const tableIns = ref()
const tableConfig = reactive({
columns: [
// {
// prop: 'name',
// type: 'index',
// label: '序号',
// align: 'center',
// width:85,
// index: index => {
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
// }
// },
{
prop: 'paymentYear',
label: '支付年份',
align: 'center'
},
{
prop: 'paymentMonth',
label: '支付月份',
align: 'center'
},
{
prop: 'masterProjectName',
label: '主项目',
align: 'center',
width: 120,
},
{
prop: 'subProjectName',
label: '子项目',
align: 'center',
width: 120,
},
{
prop: 'projectType',
label: '项目类型',
align: 'center',
width: 120,
showOverflowTooltip: false,
currentRender: ({row, index}) => {
if (row.projectType&&row.projectType !== null&&row.projectType!==undefined) {
return (<Tag dictType={'project_type'} value={row.projectType}/>)
} else {
return '--'
}
}
},
{
prop: 'rdType',
label: 'R&D统计类型',
align: 'center',
width: 200
},
{
prop: 'rdSub',
label: 'R&D统计子项',
align: 'center',
width: 150
},
{
prop: 'paymentProcessType',
label: '付款流程类型',
align: 'center',
width: 150
},
{
prop: 'processState',
label: '流程状态',
align: 'center',
},
{
prop: 'filingTime',
label: '归档时间',
align: 'center',
width: 180
},
{
prop: 'paymentProcessNum',
label: '付款流程编号',
align: 'center',
width: 150
},
{
prop: 'paymentAmount',
label: '付款金额',
align: 'center',
},
{
prop: 'paymentSubject',
label: '付款/请款事由',
align: 'center',
width: 130
},
{
prop: 'contractNum',
label: '合同编号',
align: 'center',
},
{
prop: 'contractName',
label: '合同名称',
align: 'center',
},
{
prop: 'contractSumAmount',
label: '合同总额(元)',
align: 'center',
width: 130
},
{
prop: 'recipientName',
label: '收款方名称',
align: 'center',
width: 130
},
{
prop: 'remarks',
label: '备注说明',
align: 'center',
},
],
api: '/workflow/mosr/payment/list',
params: {},
export:{
open :true,
fileName:`科研项日现金支出明细表`
}
})
const search = (val) => {
tableConfig.params = {...val}
tableIns.value.refresh()
}
const init = async () => {
const res = await getSubCompOpt()
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyIds').props.data = res.data
}
// init()
</script>
<style scoped lang="scss">
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
:deep(.el-date-editor--month){
width: 100%;
}
</style>

View File

@@ -204,7 +204,7 @@ const tableConfig = reactive({
}, },
{ {
prop: 'economicEstimate', prop: 'economicEstimate',
label: '经费预算(元)', label: '预估经费预算(元)',
align: 'center', align: 'center',
width: 150, width: 150,
currentRender:({row})=>{ currentRender:({row})=>{

View File

@@ -0,0 +1,591 @@
<template>
<div v-loading="loading" style="padding: 0 30px">
<el-form :model="formData" ref="form" :rules="rules" style="margin-left: 5px;margin-top: 18px">
<el-row :gutter="30">
<!-- <el-col :span="6" style="margin-left: -15px">-->
<!-- <el-form-item label="分摊名称" prop="shareName" >-->
<!-- <el-input v-model="formData.shareName" placeholder="请输入分摊名称" clearable>-->
<!-- </el-input>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6" style="margin-left: -10px">
<el-form-item label="分摊月份" prop="apportionmentMonth" label-width="80">
<el-date-picker
v-model="formData.apportionmentMonth"
type="month"
format="YYYY-MM"
value-format="YYYY-MM"
placeholder="选择月"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="3" >
<el-button color="#DED0B2" @click="handleAdd" style="font-size: 16px">添加一行</el-button>
</el-col>
<el-table v-if="showTable" :data="formData.tableData" style="width: 100%">
<el-table-column prop="projectId" label="项目名称" min-width="230">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.projectId?'1':rules.projectId">
<el-select v-model="scope.row.projectId" placeholder="请选择项目名称" clearable filterable @change="selectProject(scope.row,scope.$index)">
<el-option
v-for="item in nameOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="researchPersonnelId" label="研发人员" min-width="180">
<template #default="scope">
<el-form-item prop="researchPersonnelId">
{{ scope.row.researchPersonnel }}
<el-button color="#DED0B2" @click="showPersonnelPicker(scope.row,scope.$index)"
style="margin-left: 10px">
{{ scope.row.researchPersonnel ? '更改' : '请选择研发人员' }}
</el-button>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="wagesPayable" label="当月总工时(天)" min-width="175">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.wagesPayable?'1':rules.wagesPayable">
<div>21.75</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="researchDuration" label="当月研发工时(天)" min-width="175">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.researchDuration?'1':rules.researchDuration">
<el-input-number v-model="scope.row.researchDuration" placeholder="请输入当月研发工时" :controls="false"/>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="oper" label="操作" min-width="130">
<template #default="scope">
<el-button type="primary" @click="handleCopy(scope.row)" link style="font-size: 16px">复制</el-button>
<el-button type="primary" @click="handleDelete(scope.$index)" link style="font-size: 16px">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form>
<user-picker :multiple="false" ref="userPicker" title="请选择研发人员" v-model:value="userList"
@ok="selectedResearchPersonnel" @cancelOrClear="researchPersonnelPickerCancel"
:setNullToSelectList="true" :isResearch="true"/>
<div class="oper-page-btn">
<el-button color="#DED0B2" v-if="routerName==='Sharedetail/add'" @click="handleSubmit(form)">提交</el-button>
<el-button color="#DED0B2" v-else @click="handleResubmit(form)">重新提交</el-button>
<el-button @click="handleBack">返回</el-button>
</div>
</div>
</template>
<script setup lang="jsx">
import {ElNotification} from "element-plus";
import {useTagsView} from '@/stores/tagsview.js'
import {
addAllocation,
getAllocationDetail,
getAllocationProcess,
getResearchUser,
getProjectOption,
editAllocation,
getAllocationDetailList, addShare
} from "@/api/expense-manage";
import {useProcessStore} from '@/stores/processStore.js';
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
localStorage.removeItem('originallySelectedList')
const userList = ref([])
const changeDiagram = ref(false)
const rules = reactive({
// shareName: [{required: true, message: '请输入分摊名称', trigger: ['blur', 'change']}],
apportionmentMonth: [{required: true, message: '请选择月份', trigger: ['blur', 'change']}],
projectId: [{required: true, message: '请选择项目名称', trigger: ['blur', 'change']}],
// researchPersonnelId: [{required: true, message: '请选择研发人员', trigger: ['blur', 'change']}],
// wagesPayable: [{required: true, message: '请输入应发工资', trigger: ['blur', 'change']}],
// performance: [{required: true, message: '请输入绩效', trigger: ['blur', 'change']}],
// reserveFund: [{required: true, message: '请输入公积金', trigger: ['blur', 'change']}],
// socialSecurity: [{required: true, message: '请输入社保', trigger: ['blur', 'change']}],
// annuity: [{required: true, message: '请输入年金', trigger: ['blur', 'change']}],
// workday: [{required: true, message: '请输入工作日', trigger: ['blur', 'change']}],
researchDuration: [{required: true, message: '请输入研发时长', trigger: ['blur', 'change']}],
})
const processStore = useProcessStore()
const opentionData = ref({})
const processInstanceData = ref()
const processDiagramViewer = ref(false)
const loading = ref(false)
const isRepeatResearchPersonnel = ref(false)
const showTable = ref(true)
const route = useRoute()
const router = useRouter()
const routerName = ref(router.currentRoute.value.name)
const tagsViewStore = useTagsView()
const formData = ref({
tableData: [
{
projectId: '',
projectName: '',
// researchPersonnelId: '',
// wagesPayable: null,
// performance: null,
// reserveFund: null,
// socialSecurity: null,
// annuity: null,
workday: '21.75',
researchDuration: null,
}
]
})
const userPicker = ref()
const form = ref()
const currentReachPerson = ref({})
const currentRow = ref()
const currentIndex = ref()
const nameOptions = ref([])
const researchOptions = ref([])
const showPersonnelPicker = (row, index) => {
currentRow.value = row
currentIndex.value = index
if (row.companyName&&row.researchPersonnelId) {
let userObj = {
id: row.researchPersonnelId,
name: row.researchPersonnel,
companyName: row.companyName,
accountType: row.accountType,
}
userList.value = [userObj]
} else if (!row.researchPersonnel) {
userList.value = []
}
nextTick(() => {
userPicker.value.showUserPicker()
})
}
const selectProject=(row,index)=>{
console.log('row,index',row,index)
//先选择人员, 再选择项目: 再添加一行,重复操作
const projectIdArray = formData.value.tableData.map(item => item.projectId)
const researchPersonnelIdArray = formData.value.tableData.map(item => item.researchPersonnelId)
console.log('projectIdArray',projectIdArray)
console.log('researchPersonnelIdArray',researchPersonnelIdArray)
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
let repeatProjectName=getProjectName(row.projectId)
// console.log('currentRow.value',currentRow.value)
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {//先判断人员是否重复
// if(currentRow.value.projectId){
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1){
// ElNotification({
// title: '警告',
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
// type: 'warning',
// })
// row.researchPersonnelId = ''
// row.researchPersonnel = ''
// row.companyName = ''
// row.accountType = ''
// }
// }
//
// }
// for (let projectIdKey in projectNumObj) {
// // console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
// if(projectNumObj[projectIdKey]>1){
// // console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
// repeatProjectName=getProjectName(projectIdKey)
//
// }
// }
}
const researchPersonnelPickerCancel = (select) => {
console.log('select',select)
if(select.length>0){
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = select[0].id
item.researchPersonnel = select[0].name
item.companyName = select[0].companyName
item.accountType = select[0].accountType
}
})
}else{
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = ''
item.researchPersonnel = ''
item.companyName = ''
item.accountType = ''
}
})
}
}
const selectedResearchPersonnel = (select) => {
if(select.length>0){
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = select[0].id
item.researchPersonnel = select[0].name
item.companyName = select[0].companyName
item.accountType = select[0].accountType
}
})
}else{
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = ''
item.researchPersonnel = ''
item.companyName = ''
item.accountType = ''
}
})
}
//以下是为" 同一项目下,同一人不能分摊多次 "
const projectIdArray = formData.value.tableData?.map(item => item.projectId)
const researchPersonnelIdArray = formData.value.tableData?.map(item => item.researchPersonnelId)
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
let repeatProjectName=''
for (let projectIdKey in projectNumObj) {
// console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
if(projectNumObj[projectIdKey]>1){
// console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
repeatProjectName=getProjectName(projectIdKey)
}
}
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {
// // console.log('researchPersonnelIdKey', researchPersonnelIdKey, researchPersonnelNumObj[researchPersonnelIdKey])
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1&&repeatProjectName&&currentRow.value.projectId){
// isRepeatResearchPersonnel.value=true
// ElNotification({
// title: '警告',
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
// type: 'warning',
// })
// formData.value.tableData.forEach((item,index)=>{
// if (index === currentIndex.value) {
// item.researchPersonnelId = ''
// item.researchPersonnel = ''
// item.companyName = ''
// item.accountType = ''
// }
// })
// }else{
// userList.value = select
// }
// }
}
/**
* 获取一个项目/研发人员的选择次数
* @param projectIdArray
* @returns {{}}
*/
const getSelectProjectAndResearchPersonnelNum = (projectIdArray) => {
const obj = {};
for (let i = 0, l = projectIdArray.length; i < l; i++) {
const item = projectIdArray[i];
obj[item] = (obj[item] + 1) || 1;
}
return obj;
}
const getResearchOptions = async () => {
const res = await getResearchUser()
researchOptions.value = res.data
}
const getProjectOptions = async () => {
const res = await getProjectOption()
nameOptions.value = res.data
}
const getProjectName = (id) => {
let label = ''
nameOptions.value.forEach(item => {
if (item.value == id) {
label = item.label
}
})
return label
}
const handleAdd = () => {
let row = {
projectId: '',
projectName: '',
researchPersonnelId: '',
researchPersonnel: '',
wagesPayable: null,
performance: null,
reserveFund: null,
socialSecurity: null,
annuity: null,
workday: '21.75',
researchDuration: null,
}
currentReachPerson.value.name = ''
formData.value.tableData.push(row)
}
const handleCopy = (row) => {
let copyObj = {
projectId: row.projectId,
projectName: '',
// accountType: row.accountType,
// companyName: row.companyName,
// researchPersonnelId: row.researchPersonnelId,
// researchPersonnel: row.researchPersonnel,
wagesPayable: row.wagesPayable,
performance: row.performance,
reserveFund: row.reserveFund,
socialSecurity: row.socialSecurity,
annuity: row.annuity,
workday: '21.75',
researchDuration: row.researchDuration,
}
formData.value.tableData.push(copyObj)
}
const handleDelete = (index) => {
formData.value.tableData.splice(index, 1)
}
const handleSubmit = (instance) => {
console.log('tableData', formData.value.tableData)
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let researchPersonnelId = ''
formData.value.tableData.forEach(item => {
item.projectName = getProjectName(item.projectId)
researchPersonnelId = item.researchPersonnelId
if (item.performance == 0) {
item.performance = null
}
})
if (!researchPersonnelId) {
ElNotification({
title: '提示',
message: '请选择研发人员',
type: 'error'
})
return;
}
let params = {
apportionmentMonth: formData.value.apportionmentMonth,
usrAllocations: formData.value.tableData,
}
console.log('params', params.usrAllocations, formData.value.tableData)
const resultMap = params.usrAllocations.reduce((acc, item) => {
if (!acc[item.researchPersonnelId]) {
acc[item.researchPersonnelId] = [];
}
acc[item.researchPersonnelId].push(item);
return acc;
}, {});
const exceedList = [];
Object.entries(resultMap).forEach(([id, items]) => {
const totalDuration = items.reduce((sum, item) => sum + (item.researchDuration || 0), 0);
const preciseTotalDuration = parseFloat(totalDuration.toFixed(2));
if (preciseTotalDuration > 21.75) {
// 收集超出的研发人员ID及总工时
exceedList.push({ id, totalDuration: preciseTotalDuration });
}
});
// 从 resultMap 中获取 researchPersonnel
const exceedResearchPersonnel = exceedList.map(item => {
const id = item.id;
const personnelItems = resultMap[id];
// 获取第一个对象中的 researchPersonnel假设所有对象的 researchPersonnel 相同)
const researchPersonnel = personnelItems[0].researchPersonnel;
return { id, researchPersonnel, totalDuration: item.totalDuration };
});
console.log('超过21.75的研发人员:', exceedResearchPersonnel);
if (exceedResearchPersonnel.length > 0) {
console.log('以下研发人员的总研发工时超过21.75天:', exceedResearchPersonnel);
ElNotification({
title: '提示',
message: `以下研发人员的总研发工时超过21.75天:${exceedResearchPersonnel.map(e => e.researchPersonnel).join('')}`,
type: 'warning'
});
}
// 调用函数
console.log('是大V',resultMap)
const {code, msg} = await addShare(params)
ElNotification({
title: '提示',
message: msg,
type: code === 1000 ? 'success' : 'error'
})
if (code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Share'
})
}
})
}
const handleResubmit = (instance) => {
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let researchPersonnelId = ''
formData.value.tableData.forEach(item => {
item.allocationId = formData.value.allocationId
item.projectName = getProjectName(item.projectId)
researchPersonnelId = item.researchPersonnelId
if (item.performance == 0) {
item.performance = null
}
})
if (!researchPersonnelId) {
ElNotification({
title: '提示',
message: '请选择研发人员',
type: 'error'
})
return;
}
let params = {
allocationId: formData.value.allocationId,
shareName: formData.value.shareName,
apportionmentMonth: formData.value.apportionmentMonth,
usrAllocations: formData.value.tableData,
deploymentId: processInstanceData.value.deploymentId,
}
// console.log('params', params, formData.value.tableData)
const {code, msg} = await editAllocation(params)
ElNotification({
title: '提示',
message: msg,
type: code === 1000 ? 'success' : 'error'
})
if (code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Share'
})
}
})
}
const getDetailInfo = () => {
loading.value = true
getAllocationDetail(route.query.id).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
getDetailList()
formData.value = res.data.formData
opentionData.value = res.data
loading.value = false
}
})
}
const getDetailList = async () => {
let params = {
allocationId: route.query.id
}
showTable.value = false
const {code, data, msg} = await getAllocationDetailList(params)
if (code === 1000) {
data.rows.forEach(item => {
item.researchPersonnelId = Number(item.researchPersonnelId)
})
formData.value.tableData = data.rows
nextTick(() => {
showTable.value = true
})
} else {
ElNotification({
title: '提示',
message: msg,
type: 'error'
})
}
}
const init = async () => {
processDiagramViewer.value = false
await getResearchOptions()
await getProjectOptions()
getAllocationProcess().then(res => {
if (res.code === 1000) {
let data = res.data
processInstanceData.value = data
processStore.setDesign(data)
processStore.runningList.value = data.runningList;
processStore.endList.value = data.endList;
processStore.noTakeList.value = data.noTakeList;
processStore.refuseList.value = data.refuseList;
processStore.passList.value = data.passList;
nextTick(() => {
processDiagramViewer.value = true
})
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleBack = () => {
history.back()
}
onMounted(() => {
init()
if (route.query.id) {
getDetailInfo()
}
})
</script>
<style scoped lang="scss">
:deep(.el-table--enable-row-transition) {
.el-table__body td.el-table__cell {
.cell {
.el-form-item {
margin-top: 20px;
}
}
}
}
:deep(.el-date-editor--month) {
width: 100% !important;
}
:deep(.el-input-number) {
width: 100%;
.el-input__inner {
text-align: left;
}
}
</style>

View File

@@ -0,0 +1,219 @@
<template>
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 16px"></fvSearchForm>
<!-- <el-button color="#DED0B2" style="float: left;margin: 0 10px 10px 0" @click="exportTable">导出</el-button>-->
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick" style="margin-top: 15px" @selectionChange="selectionChange">
<template #empty>
<el-empty description="暂无数据"/>
</template>
</fvTable>
</template>
<script setup lang="jsx">
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
import { getSubCompOpt } from '@/api/user/user.js';
import {reactive, ref} from "vue";
import {shareDetailExport, shareExportExcel} from "@/api/expense-manage";
import {ElMessage} from "element-plus";
const router = useRouter()
const route = useRoute()
const searchConfig = reactive([
{
label: '子项目',
prop: 'subProjectName',
component: 'el-input',
props: {
placeholder: '请输入子项目查询',
clearable: true,
filterable: true,
checkStrictly: true
}
},
// {
// label: '支付月份',
// prop: 'apportionmentMonth',
// component: 'el-date-picker',
// props: {
// placeholder: '请选择支付月份',
// clearable: true,
// type:'month',
// format: 'YYYY-MM',
// valueFormat:"YYYY-MM"
// },
// colProps: {}
// },
// {
// label: '人员性质',
// prop: 'personnelNature',
// component: shallowRef(fvSelect),
// props: {
// placeholder: '请选择人员性质',
// clearable: true,
// filterable: true,
// cacheKey: 'nature_of_personnel'
// }
// },
])
const tableIns = ref()
const selectData = ref([])
const tableConfig = reactive({
columns: [
{
type: 'selection',
prop: 'selection',
},
// {
// prop: 'name',
// type: 'index',
// label: '序号',
// align: 'center',
// width:85,
// index: index => {
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
// }
// },
{
prop: 'paymentYear',
label: '支付年份',
align: 'center'
},
{
prop: 'paymentMonth',
label: '支付月份',
align: 'center'
},
{
prop: 'masterProjectName',
label: '主项目',
align: 'center',
},
{
prop: 'subProjectName',
label: '子项目',
align: 'center',
},
{
prop: 'researchPersonnel',
label: '研发人员',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'personnelNature',
label: '人员性质',
align: 'center',
width: 120,
showOverflowTooltip: false,
currentRender: ({row, index}) => {
if (row.personnelNature&&row.personnelNature !== null&&row.personnelNature!==undefined) {
return (<Tag dictType={'nature_of_personnel'} value={row.personnelNature}/>)
} else {
return '--'
}
}
},
{
prop: 'researchDuration',
label: '当月研发工时(天)',
align: 'center',
// currentRender:({row})=>{
// return <span>{toThousands(row.afterTax)}</span>
// }
},
{
prop: 'workday',
label: '当月总工时(天)',
align: 'center',
showOverflowTooltip: false,
},
{
prop: 'subtotal',
label: '人工成本分摊(元)',
align: 'center',
},
],
api: '/workflow/mosr/cost/share',
params: {},
btns: [
{name: '添加分摊', key: 'add', color: '#DED0B2'},
{name: '导出', key: 'export', color: '#DED0B2'}
],
export:{
open :false,
}
})
const search = (val) => {
tableConfig.params = {...val}
tableIns.value.refresh()
}
const headBtnClick = (key) => {
switch (key) {
case 'add':
handleAdd()
break;
case 'export':
exportTable()
break;
}
}
const selectionChange = (data) => {
console.log('data', data)
selectData.value=data.map(item=>item.id)
}
const exportTable = () => {
console.log('selectData',selectData.value)
if (selectData.value.length === 0) {
ElMessage.warning('请选择要导出的费用分摊')
return
}
shareDetailExport(selectData.value).then(res => {
console.log(res)
let fileName = `科技研发项目工时及成本分摊汇总表.xlsx`
const blob = new Blob([res.data])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = fileName
a.click()
})
}
const handleAdd = () => {
router.push({
name: 'Sharedetail/add',
query: {}
})
}
const init = async () => {
const res = await getSubCompOpt()
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyIds').props.data = res.data
}
// init()
</script>
<style scoped lang="scss">
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
//margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
//margin-left: -13px !important;
}
}
}
:deep(.el-date-editor--month){
width: 100%;
}
</style>

View File

@@ -4,7 +4,8 @@
<el-col :xs="24" :sm="24" :md="24" :lg="17" :xl="17"> <el-col :xs="24" :sm="24" :md="24" :lg="17" :xl="17">
<div class="top-left" id="topLeft"> <div class="top-left" id="topLeft">
<el-card shadow="never"> <el-card shadow="never">
<div class="notice-title">{{getTimePeriod()}}提醒您<span><span>{{ taskTabList[0].num }}</span>个项目待立项</span></div> <div class="notice-title">{{ getTimePeriod() }}提醒您<span><span>{{ taskTabList[0].num }}</span>个项目待立项</span>
</div>
<el-row class="statistics"> <el-row class="statistics">
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="(item,index) in taskTabList" :key="index"> <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="(item,index) in taskTabList" :key="index">
<div class="block" :style="{'background-image':'url('+getImgUrl(item.icon)+')'}" <div class="block" :style="{'background-image':'url('+getImgUrl(item.icon)+')'}"
@@ -20,7 +21,7 @@
<el-card shadow="never" class="todo-bg" @tab-add="refreshTodoOrDoneList(activeName)"> <el-card shadow="never" class="todo-bg" @tab-add="refreshTodoOrDoneList(activeName)">
<el-tabs v-model="activeName" editable> <el-tabs v-model="activeName" editable>
<template #add-icon> <template #add-icon>
<div @click="refreshTodoOrDoneList" style="margin-left: -50px"> <div @click="refreshTodoOrDoneList" style="margin-left: -50px;font-size: 14px">
刷新一下 刷新一下
<div style="width: 31px"></div> <div style="width: 31px"></div>
</div> </div>
@@ -28,14 +29,14 @@
<el-tab-pane :label="'待办('+(todoList?.length||0) +''" name="first"> <el-tab-pane :label="'待办('+(todoList?.length||0) +''" name="first">
<div class="todo-top"> <div class="todo-top">
<div class="bell"> <div class="bell">
<el-icon size="20" color="#F55815"> <el-icon size="16" color="#F55815">
<BellFilled/> <BellFilled/>
</el-icon> </el-icon>
<span>您有{{ todoList?.length || 0 }}条待办需要处理</span> <span>您有{{ todoList?.length || 0 }}条待办需要处理</span>
</div> </div>
<div class="todo-more" @click="handleTodoList(1)"> <div class="todo-more" @click="handleTodoList(1)">
<span>查看更多</span> <span>查看更多</span>
<el-icon color="#1F63E6" size="18"> <el-icon color="#1F63E6" size="16">
<ArrowRight/> <ArrowRight/>
</el-icon> </el-icon>
</div> </div>
@@ -72,14 +73,14 @@
<el-tab-pane :label="'已办(' + (doneList?.length||0) + ''" name="second"> <el-tab-pane :label="'已办(' + (doneList?.length||0) + ''" name="second">
<div class="todo-top"> <div class="todo-top">
<div class="bell"> <div class="bell">
<el-icon size="20" color="#F55815"> <el-icon size="16" color="#F55815">
<BellFilled/> <BellFilled/>
</el-icon> </el-icon>
<span>您有{{ todoList.length }}条待办需要处理</span> <span>您有{{ todoList.length }}条待办需要处理</span>
</div> </div>
<div class="todo-more" @click="handleTodoList(2)"> <div class="todo-more" @click="handleTodoList(2)">
<span>查看更多</span> <span>查看更多</span>
<el-icon color="#1F63E6" size="18"> <el-icon color="#1F63E6" size="16">
<ArrowRight/> <ArrowRight/>
</el-icon> </el-icon>
</div> </div>
@@ -132,12 +133,16 @@
</el-icon> </el-icon>
</div> </div>
</div> </div>
<div class="notice-block"> <div class="notice-block notice-box">
<div v-if="noticeList&&noticeList.length==0"> <div v-if="noticeList&&noticeList.length==0">
<el-empty image-size="135" description="暂无通知公告~"/> <el-empty image-size="135" description="暂无通知公告~"/>
</div> </div>
<div v-for="(item,index) in noticeList" class="notice" @click="handleGoToArticleDetail(item)"> <div v-for="(item,index) in noticeList" class="notice" @click="handleGoToArticleDetail(item)">
<span>{{ index > 8 ? '' : 0 }}{{ index + 1 }}</span>{{ item.articleTitle }} <span>{{ index > 8 ? '' : 0 }}{{ index + 1 }}</span>
<span>{{ item.articleTitle }}</span>
<span>
{{ item.articleTime }}
</span>
</div> </div>
</div> </div>
</div> </div>
@@ -240,7 +245,7 @@
<!-- <div>--> <!-- <div>-->
<!-- <span>{{ index > 8 ? '' : 0 }}{{ index + 1 }}</span>{{ item.title }}--> <!-- <span>{{ index > 8 ? '' : 0 }}{{ index + 1 }}</span>{{ item.title }}-->
<!-- </div>--> <!-- </div>-->
<div :style="{'color': item.isRead ? '#1F63E6' : 'rgba(0,0,0,0.5)'}"> <div :style="{'color': item.isRead ? '#1F63E6' : '#000'}">
<span>{{ item.articleTitle }}</span> <span>{{ item.articleTitle }}</span>
<span class="dot" v-if="item.isRead"></span> <span class="dot" v-if="item.isRead"></span>
</div> </div>
@@ -379,8 +384,8 @@ const fundPieOption = ref({
align: 'left', align: 'left',
icon: 'circle', icon: 'circle',
textStyle: { textStyle: {
color: 'rgba(0,0,0,0.6)', color: '#000',
fontSize: '12px' fontSize: '14px'
}, },
}, },
graphic: { //图形中间图片 graphic: { //图形中间图片
@@ -393,18 +398,19 @@ const fundPieOption = ref({
}, },
left: 'center', left: 'center',
right: 'center', right: 'center',
top: '42%' top: '45%'
}] }]
}, },
series: [ series: [
{ {
type: 'pie', type: 'pie',
radius: [65, 90], radius: [65, 90],
center: ['50%', '50%'], center: ['50%', '55%'],
top: '10%', top: '10%',
left: '8', left: '8',
label: { label: {
show: true, show: true,
fontSize:14,
formatter: '{b}\n{d}%' formatter: '{b}\n{d}%'
// formatter: params => { // formatter: params => {
// console.log(params) // console.log(params)
@@ -446,12 +452,12 @@ const fundPieOption = ref({
clockWise: false, clockWise: false,
hoverAnimation: false, hoverAnimation: false,
radius: ['70%', '70%'],//边框大小 radius: ['70%', '70%'],//边框大小
center: ['50%', '50%'],//边框位置 center: ['50%', '55%'],//边框位置
tooltip: { tooltip: {
show: false show: false
}, },
label: { label: {
show: false show: false,
}, },
emphasis: { emphasis: {
show: false show: false
@@ -481,6 +487,7 @@ const moneyPieOption = ref({
center: ['50%', '50%'], center: ['50%', '50%'],
label: { label: {
normal: { normal: {
fontSize:14,
show: true, show: true,
position: 'inner', position: 'inner',
formatter: function (data) { formatter: function (data) {
@@ -520,7 +527,7 @@ onMounted(async () => {
helpDocList.value = await getArticleList(2) helpDocList.value = await getArticleList(2)
problemList.value = await getArticleList(3) problemList.value = await getArticleList(3)
}) })
const getTimePeriod=()=>{ const getTimePeriod = () => {
// 获取当前日期和时间 // 获取当前日期和时间
const now = new Date(); const now = new Date();
// 获取当前小时数 // 获取当前小时数
@@ -535,11 +542,11 @@ const getTimePeriod=()=>{
return "中午好"; return "中午好";
} else if (hour >= 14 && hour < 18) { } else if (hour >= 14 && hour < 18) {
return "下午好"; return "下午好";
} else if (hour >= 18 && hour <= 22) { } else if (hour >= 18 && hour <= 22) {
return "晚上好"; return "晚上好";
} else if (hour >= 23 || hour <= 1) { } else if (hour >= 23 || hour <= 1) {
return "午夜好"; return "午夜好";
} else if (hour > 1&& hour <= 5) { } else if (hour > 1 && hour <= 5) {
return "夜深了"; return "夜深了";
} }
} }
@@ -548,7 +555,7 @@ const handleTodoList = (type) => {
router.push({ router.push({
path: '/todolist', path: '/todolist',
}) })
} else if (type == 2){ } else if (type == 2) {
router.push({ router.push({
path: '/donelist', path: '/donelist',
}) })
@@ -562,23 +569,23 @@ const handleGoToArticleDetail = (row) => {
} }
}) })
} }
const goToArticleList = (type,otherHelpType) => { const goToArticleList = (type, otherHelpType) => {
let queryType='' let queryType = ''
if(type){ if (type) {
queryType=type queryType = type
}else{ } else {
console.info("🚀 ~method:'otherHelpType' -----", otherHelpType) console.info("🚀 ~method:'otherHelpType' -----", otherHelpType)
if(otherHelpType=='first'){ if (otherHelpType == 'first') {
queryType= '1' queryType = '1'
}else if(otherHelpType=='second'){ } else if (otherHelpType == 'second') {
queryType= '2' queryType = '2'
}else if(otherHelpType=='third'){ } else if (otherHelpType == 'third') {
queryType= '3' queryType = '3'
} }
} }
router.push({ router.push({
name: 'Manage', name: 'Manage',
query:{ query: {
type: queryType type: queryType
} }
}) })
@@ -783,17 +790,17 @@ const handleView = (row) => {
} }
}) })
} }
// else if (row.targetState == '10' && row.targetId) { // else if (row.targetState == '10' && row.targetId) {
// router.push({ // router.push({
// name: 'Summary/detail', // name: 'Summary/detail',
// query: { // query: {
// projectId: row.targetId, // projectId: row.targetId,
// state: row.state, // state: row.state,
// source: 'home' // source: 'home'
// } // }
// }) // })
// } // }
else if (row.targetState == '10'||row.targetState == '20' || row.targetState == '40' || row.targetState == '50') { else if (row.targetState == '10' || row.targetState == '20' || row.targetState == '40' || row.targetState == '50') {
router.push({ router.push({
name: 'Implementation/detail', name: 'Implementation/detail',
query: { query: {
@@ -834,6 +841,13 @@ const handleView = (row) => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-input){
width: 84px!important;
}
:deep(.el-input__inner){
font-size: 14px;
color: #000;
}
@media (min-width: 1200px) and (max-width: 1918px) { @media (min-width: 1200px) and (max-width: 1918px) {
//.right-top { //.right-top {
// height: 684px !important; // height: 684px !important;
@@ -996,7 +1010,7 @@ const handleView = (row) => {
.total-money { .total-money {
height: 25px; height: 25px;
font-weight: 400; font-weight: 400;
font-size: 15px; font-size: 14px;
color: #000000; color: #000000;
line-height: 18px; line-height: 18px;
} }
@@ -1032,14 +1046,14 @@ const handleView = (row) => {
> div:last-child { > div:last-child {
font-weight: 400; font-weight: 400;
font-size: 15px; font-size: 14px;
color: #000000; color: #000000;
letter-spacing: 1px; letter-spacing: 1px;
margin-left: 28px; margin-left: 28px;
} }
.company-name { .company-name {
font-size: 12px; font-size: 14px;
color: rgba(0, 0, 0, 0.6); color: rgba(0, 0, 0, 0.6);
letter-spacing: 1px; letter-spacing: 1px;
margin-left: 10px; margin-left: 10px;
@@ -1100,7 +1114,7 @@ const handleView = (row) => {
:deep(.el-tabs__new-tab ) { :deep(.el-tabs__new-tab ) {
width: 67px !important; width: 67px !important;
border: none !important; border: none !important;
color: #1476E3; color: #1476E3;
font-size: 14px; font-size: 14px;
line-height: 51px !important; line-height: 51px !important;
height: 51px !important; height: 51px !important;
@@ -1125,11 +1139,11 @@ const handleView = (row) => {
.el-tabs__nav { .el-tabs__nav {
.el-tabs__item { .el-tabs__item {
flex: 1; flex: 1;
font-size: 16px; font-size: 14px;
width: 120px; width: 100px;
//font-weight: 600; //font-weight: 600;
height: 51px; height: 51px;
color: rgba(0, 0, 0, 0.5); color: #000;
} }
.el-tabs__item.is-active { .el-tabs__item.is-active {
@@ -1192,7 +1206,7 @@ const handleView = (row) => {
margin-left: 14px; margin-left: 14px;
color: #000000; color: #000000;
letter-spacing: 1px; letter-spacing: 1px;
font-size: 16px; font-size: 14px;
> span { > span {
color: #F40E0E; color: #F40E0E;
@@ -1255,7 +1269,7 @@ const handleView = (row) => {
flex-direction: column; flex-direction: column;
//align-items: flex-end; //align-items: flex-end;
font-weight: 400; font-weight: 400;
color: rgba(0, 0, 0, 0.5); color:#000;
letter-spacing: 1px; letter-spacing: 1px;
font-size: 12px; font-size: 12px;
@@ -1338,13 +1352,13 @@ const handleView = (row) => {
justify-content: space-between; justify-content: space-between;
font-size: 14px; font-size: 14px;
margin-bottom: 12px; margin-bottom: 12px;
margin-left: 20px; margin-left: 4px;
.bell { .bell {
display: flex; display: flex;
align-items: center; align-items: center;
color: #F55815; color: #F55815;
font-size: 15px; font-size: 15px;
> span { > span {
@@ -1375,13 +1389,13 @@ const handleView = (row) => {
> span:first-child { > span:first-child {
white-space: nowrap; white-space: nowrap;
font-size: 36px; font-size: 34px;
font-weight: bold; font-weight: bold;
margin-bottom: 10px; margin-bottom: 10px;
> span { > span {
margin-left: 10px; margin-left: 10px;
font-size: 13px; font-size: 14px;
} }
} }
@@ -1389,6 +1403,7 @@ const handleView = (row) => {
white-space: nowrap; white-space: nowrap;
color: #fff; color: #fff;
margin-bottom: 10px; margin-bottom: 10px;
font-size: 14px;
} }
} }
} }
@@ -1413,8 +1428,7 @@ const handleView = (row) => {
justify-content: space-between; justify-content: space-between;
height: 47px !important; height: 47px !important;
line-height: 47px !important; line-height: 47px !important;
color: rgba(0, 0, 0, 0.5) !important; color: #000 !important;
> div:first-child { > div:first-child {
position: relative; position: relative;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -1451,7 +1465,35 @@ const handleView = (row) => {
margin-left: 20px; margin-left: 20px;
font-weight: 400; font-weight: 400;
letter-spacing: 1px; letter-spacing: 1px;
color: rgba(0, 0, 0, 0.5) color: #000
}
}
}
.notice-box {
.notice {
display: flex;
justify-content: space-between;
> span:first-child {
margin-right: 10px;
margin-left: 10px;
color: #1476E3;
font-weight: bold;
font-size: 16px;
}
> span:nth-child(2) {
display: block;
width: 65%;
overflow: hidden;
text-overflow: ellipsis;
}
&:hover {
color: #1476E3;
background: #F6FBFE;
} }
} }
} }
@@ -1485,7 +1527,7 @@ const handleView = (row) => {
height: 75px; height: 75px;
line-height: 75px; line-height: 75px;
padding: 0 15px; padding: 0 15px;
font-size: 12px; font-size: 14px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -1493,9 +1535,9 @@ const handleView = (row) => {
> span:first-child { > span:first-child {
margin-right: 10px; margin-right: 10px;
margin-left: 10px; margin-left: 10px;
font-size: 14px;
color: #1476E3; color: #1476E3;
font-weight: bold; font-weight: bold;
font-size: 16px;
} }
&:hover { &:hover {
@@ -1524,8 +1566,8 @@ const handleView = (row) => {
.fund-pie { .fund-pie {
width: 100%; width: 100%;
height: 25px; height: 25px;
font-size: 12px; font-size: 14px;
color: rgba(0, 0, 0, 0.5); color: #000;
text-align: center; text-align: center;
//margin-top: 15px; //margin-top: 15px;
} }
@@ -1543,7 +1585,7 @@ const handleView = (row) => {
.tag { .tag {
width: 7px; width: 7px;
height: 18px; height: 14px;
background: linear-gradient(#1476E3 0%, #99C9FF 100%); background: linear-gradient(#1476E3 0%, #99C9FF 100%);
margin-right: 5px; margin-right: 5px;
border-radius: 2px; border-radius: 2px;
@@ -1553,6 +1595,7 @@ const handleView = (row) => {
> span { > span {
white-space: nowrap; white-space: nowrap;
color: #000000; color: #000000;
font-size: 14px;
//font-weight: 600; //font-weight: 600;
} }
} }

View File

@@ -1,4 +1,5 @@
<template> <template>
<div class="login-box"> <div class="login-box">
<el-form <el-form
:model="loginForm" :model="loginForm"

View File

@@ -79,14 +79,14 @@
<div v-else>--</div> <div v-else>--</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="resultForm" label="预期成果形式" align="center" min-width="100px"> <!-- <el-table-column prop="resultForm" label="预期成果形式" align="center" min-width="100px">-->
<template #default="scope"> <!-- <template #default="scope">-->
<div v-if="scope.row.resultForm !== null"> <!-- <div v-if="scope.row.resultForm !== null">-->
<Tag style="margin-top: 3px" dictType="result_form" v-for="item in scope.row.resultForm" :value="item"/> <!-- <Tag style="margin-top: 3px" dictType="result_form" v-for="item in scope.row.resultForm" :value="item"/>-->
</div> <!-- </div>-->
<div v-else>--</div> <!-- <div v-else>&#45;&#45;</div>-->
</template> <!-- </template>-->
</el-table-column> <!-- </el-table-column>-->
<el-table-column prop="technicalStandard" label="预期技术标准制定" align="center"> <el-table-column prop="technicalStandard" label="预期技术标准制定" align="center">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.technicalStandard !== null"> <div v-if="scope.row.technicalStandard !== null">
@@ -114,15 +114,22 @@
<el-table-column prop="prospectiveIntellectualProperty" label="预期知识产权" align="center" width="190"> <el-table-column prop="prospectiveIntellectualProperty" label="预期知识产权" align="center" width="190">
<template #default="scope"> <template #default="scope">
<div style="text-align: left"> <div style="text-align: left">
发明专利{{ scope.row.inventionPatent ? scope.row.inventionPatent : 0 }}<br> 专利{{ scope.row.newPatent ? scope.row.newPatent : 0 }}<br>
实用新型专利{{ scope.row.newPatent ? scope.row.newPatent : 0 }}<br>
软件著作权{{ scope.row.softwareCopyright ? scope.row.softwareCopyright : 0 }}<br> 软件著作权{{ scope.row.softwareCopyright ? scope.row.softwareCopyright : 0 }}<br>
著作权{{ scope.row.copyright ? scope.row.copyright : 0 }}<br> 技术标准{{ scope.row.technicalNorms ? scope.row.technicalNorms : 0 }}<br>
其他{{ scope.row.other ? scope.row.other : 0 }} 新产品{{ scope.row.newProduct ? scope.row.newProduct : 0 }}<br>
新工艺{{ scope.row.newProcess ? scope.row.newProcess : 0 }}<br>
新装置{{ scope.row.newDevice ? scope.row.newDevice : 0 }}<br>
新材料{{ scope.row.newMaterials ? scope.row.newMaterials : 0 }}<br>
计算机软件{{ scope.row.computerSoftware ? scope.row.computerSoftware : 0 }}<br>
论文论著{{ scope.row.thesis ? scope.row.thesis : 0 }}<br>
研究报告{{ scope.row.researchReport ? scope.row.researchReport : 0 }}<br>
商标{{ scope.row.trademark ? scope.row.trademark : 0 }}<br>
其他项:<br> <span style="white-space: pre-wrap;">{{ scope.row.other ? scope.row.other : 0 }}</span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="intellectualProperty" label="知识产权状况" align="center"> <el-table-column prop="intellectualProperty" label="知识产权归属" align="center">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.intellectualProperty !== null"> <div v-if="scope.row.intellectualProperty !== null">
<Tag dictType="intellectual_property" :value="scope.row.intellectualProperty"/> <Tag dictType="intellectual_property" :value="scope.row.intellectualProperty"/>
@@ -130,12 +137,12 @@
<div v-else>--</div> <div v-else>--</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="intellectualProperty" label="经费预算(元)" align="center"> <el-table-column prop="intellectualProperty" label="预估经费预算(元)" align="center">
<template #default="scope"> <template #default="scope">
<span>{{ toThousands(scope.row.economicEstimate) }}</span> <span>{{ toThousands(scope.row.economicEstimate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="specialFundAmount" label="专项资金(元)" align="center"> <el-table-column prop="specialFundAmount" label="预估专项资金(元)" align="center">
<template #default="scope"> <template #default="scope">
<span>{{ toThousands(scope.row.specialFundAmount) }}</span> <span>{{ toThousands(scope.row.specialFundAmount) }}</span>
</template> </template>

View File

@@ -46,6 +46,11 @@ const tableConfig = reactive({
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1 return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
} }
}, },
{
prop: 'processNumber',
label: '征集编号',
align: 'center',
},
{ {
prop: 'requirementName', prop: 'requirementName',
label: '征集名称', label: '征集名称',

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="detail-block" v-loading="loading" :style="{padding:!formData.isSpecialFund?'0 30px':'0 0 0 30px'}"> <div class="detail-block" v-loading="loading" :style="{padding:!formData.isSpecialFund?'0 30px':'0 0 0 30px'}">
<baseTitle title="项目基本信息"></baseTitle> <baseTitle title="项目基本信息"></baseTitle>
<el-form :model="formData" ref="summaryForm" :rules="rules" :label-width="!formData.isSpecialFund?130:160" <el-form :model="formData" ref="summaryForm" :rules="rules" :label-width="!formData.isSpecialFund?145:160"
:scroll-to-error="true"> :scroll-to-error="true">
<el-row gutter="30" style="margin-bottom: -18px;" <el-row gutter="30" style="margin-bottom: -18px;"
:style="{marginLeft:!formData.isSpecialFund?'-8.5px':'-48.5px'}"> :style="{marginLeft:!formData.isSpecialFund?'-8.5px':'-48.5px'}">
@@ -183,15 +183,15 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" v-if="formData.isSpecialFund"> <el-col :span="6" v-if="formData.isSpecialFund">
<el-form-item label="预估专项资金(元)" prop="specialFundAmount"> <el-form-item label="预估专项资金(元)" prop="forecastSpecialFundAmount">
<el-input <el-input
v-model="formData.specialFundAmount" v-model="formData.forecastSpecialFundAmount"
placeholder="请输入预估专项资金" placeholder="请输入预估专项资金"
clearable clearable
:formatter="(value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ',')" :formatter="(value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
:parser="(value) => value.replace(/\$\s?|(,*)+[^0-9.]/g, '')" @change="changeCollectData" :parser="(value) => value.replace(/\$\s?|(,*)+[^0-9.]/g, '')" @change="changeCollectData"
/> />
<!-- <el-input-number v-model="formData.specialFundAmount" placeholder="请输入预估专项资金" :controls="false"/>--> <!-- <el-input-number v-model="formData.forecastSpecialFundAmount" placeholder="请输入预估专项资金" :controls="false"/>-->
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':'-40px'}"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':'-40px'}">
@@ -232,10 +232,10 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?route.query.id?'-10px':'0':'0'}"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?route.query.id?'-10px':'0':'0'}">
<el-form-item label="需求征集" prop="requirementId" required> <el-form-item label="需求征集" prop="" required>
<template v-if="formData.requirementDefaultName">{{ formData.requirementDefaultName }}</template> <template v-if="requirementDefaultName">{{ requirementDefaultName }}</template>
<el-select v-else v-model="formData.requirementId" clearable placeholder="请选择需求征集" <el-select v-else v-model="formData.requirementId" clearable placeholder="请选择需求征集"
@change="changeCollectData"> @change="changeCollectData();changeRequirement()">
<el-option <el-option
v-for="item in requirementList" v-for="item in requirementList"
:key="item.value" :key="item.value"
@@ -249,23 +249,23 @@
<baseTitle title="预期知识产权"></baseTitle> <baseTitle title="预期知识产权"></baseTitle>
<el-row gutter="30" style="margin-bottom: -18px;" <el-row gutter="30" style="margin-bottom: -18px;"
:style="{marginLeft:!formData.isSpecialFund?'-8.5px':'-48.5px'}"> :style="{marginLeft:!formData.isSpecialFund?'-8.5px':'-48.5px'}">
<el-col :span="12"> <!-- <el-col :span="12">-->
<el-form-item label="预期成果形式" prop="resultForm" <!-- <el-form-item label="预期成果形式" prop="resultForm"-->
:style="{marginRight:!formData.isSpecialFund?'0':route.query.id?'':'40px'}"> <!-- :style="{marginRight:!formData.isSpecialFund?'0':route.query.id?'':'40px'}">-->
<el-select v-model="formData.resultForm" placeholder="请选择预期成果形式" clearable filterable multiple <!-- <el-select v-model="formData.resultForm" placeholder="请选择预期成果形式" clearable filterable multiple-->
@change="changeCollectData"> <!-- @change="changeCollectData">-->
<el-option <!-- <el-option-->
v-for="item in cacheStore.getDict('result_form')" <!-- v-for="item in cacheStore.getDict('result_form')"-->
:key="item.value" <!-- :key="item.value"-->
:label="item.label" <!-- :label="item.label"-->
:value="item.value" <!-- :value="item.value"-->
/> <!-- />-->
</el-select> <!-- </el-select>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':'-40px'}"> <el-col :span="6" >
<el-form-item label="知识产权状况" prop="intellectualProperty"> <el-form-item label="知识产权归属" prop="intellectualProperty">
<el-select v-model="formData.intellectualProperty" placeholder="请选择知识产权状况" clearable filterable <el-select v-model="formData.intellectualProperty" placeholder="请选择知识产权归属" clearable filterable
@change="changeCollectData"> @change="changeCollectData">
<el-option <el-option
v-for="item in cacheStore.getDict('intellectual_property')" v-for="item in cacheStore.getDict('intellectual_property')"
@@ -276,37 +276,80 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':'-40px'}"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'0':'-40px'}" >
<el-form-item label="发明专利(项)" prop="inventionPatent"> <el-form-item label="预估专利(项)" prop="newPatent">
<el-input-number v-model="formData.inventionPatent" placeholder="请输入发明专利数量" :controls="false" <el-input-number v-model="formData.newPatent" placeholder="请输入预估专利数量" :controls="false"
@change="changeCollectData"/> @change="changeCollectData"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="新型专利(项)" prop="newPatent"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'0'}">
<el-input-number v-model="formData.newPatent" placeholder="请输入实用性新型专利数量" :controls="false" <el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
@change="changeCollectData" <el-input-number v-model="formData.softwareCopyright" placeholder="请输入预估软件著作权数量" :controls="false"
style="width: 100%"/> @change="changeCollectData"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'':'-40px'}">
<el-form-item label="软件著作权(项)" prop="softwareCopyright"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'-40px'}">
<el-input-number v-model="formData.softwareCopyright" placeholder="请输入软件著作权数量" :controls="false" <el-form-item label="预估技术标准(项)" prop="technicalNorms">
<el-input-number v-model="formData.technicalNorms" placeholder="请输入预估技术标准数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'0':'0'}">
<el-form-item label="预估新产品(项)" prop="newProduct">
<el-input-number v-model="formData.newProduct" placeholder="请输入预估新产品数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'0':'-40px'}">
<el-form-item label="预估新工艺(项)" prop="newProcess">
<el-input-number v-model="formData.newProcess" placeholder="请输入预估新工艺数量" :controls="false"
@change="changeCollectData"/> @change="changeCollectData"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'0'}"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'0'}">
<el-form-item label="著作权(项)" prop="copyright"> <el-form-item label="预估新装置(项)" prop="newDevice">
<el-input-number v-model="formData.copyright" placeholder="请输入著作权数量" :controls="false" <el-input-number v-model="formData.newDevice" placeholder="请输入预估新装置数量" :controls="false"
@change="changeCollectData"/> @change="changeCollectData"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':'-40px'}"> <el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'-40px'}">
<el-form-item label="其他(项)" prop="other"> <el-form-item label="预估新材料(项)" prop="newMaterials">
<el-input-number v-model="formData.other" placeholder="请输入其他数量" :controls="false" <el-input-number v-model="formData.newMaterials" placeholder="请输入预估新材料数量" :controls="false"
@change="changeCollectData"/> @change="changeCollectData"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'0':'0'}">
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
<el-input-number v-model="formData.computerSoftware" placeholder="请输入预估计算机软件数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'0':route.query.id?'0':'-40px'}">
<el-form-item label="预估论文论著(项)" prop="thesis">
<el-input-number v-model="formData.thesis" placeholder="请输入预估论文论著数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'0'}">
<el-form-item label="预估研究报告(项)" prop="researchReport">
<el-input-number v-model="formData.researchReport" placeholder="请输入预估研究报告数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="6" :style="{marginLeft:!formData.isSpecialFund?'-10px':route.query.id?'-40px':'-40px'}">
<el-form-item label="预估商标(项)" prop="trademark">
<el-input-number v-model="formData.trademark" placeholder="请输入预估商标数量" :controls="false"
@change="changeCollectData"/>
</el-form-item>
</el-col>
<el-col :span="24" >
<el-form-item label="预估其他(项)" prop="other">
<el-input rows="4" type="textarea" v-model="formData.other" placeholder="请输入预估其他项"
@change="changeCollectData" :style="{marginRight:!formData.isSpecialFund?'20px':'80px'}"/>
</el-form-item>
</el-col>
</el-row> </el-row>
<baseTitle title="项目描述"></baseTitle> <baseTitle title="项目描述"></baseTitle>
<el-row gutter="30" style="margin-bottom: -18px;" <el-row gutter="30" style="margin-bottom: -18px;"
@@ -388,9 +431,10 @@ import {useCacheStore} from '@/stores/cache.js'
import {useProcessStore} from '@/stores/processStore.js'; import {useProcessStore} from '@/stores/processStore.js';
import {getSubCompOpt} from "@/api/user/user"; import {getSubCompOpt} from "@/api/user/user";
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'; import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import {getFormInfo} from "@/api/project-demand"; import {getFormInfo, getInfo} from "@/api/project-demand";
import {getFundOption} from "@/api/special-fund"; import {getFundOption} from "@/api/special-fund";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue"; import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
import {nextTick} from "vue";
const authStore = useAuthStore() const authStore = useAuthStore()
const changeDiagram = ref(false) const changeDiagram = ref(false)
@@ -405,6 +449,7 @@ const loading = ref(false)
const processDiagramViewer = ref(false) const processDiagramViewer = ref(false)
const tagsViewStore = useTagsView() const tagsViewStore = useTagsView()
const companyOption = ref([]) const companyOption = ref([])
const requirementDefaultName = ref('')
const summaryForm = ref() const summaryForm = ref()
const deploymentId = ref() const deploymentId = ref()
const optionalChargeLeadershipPickerRef = ref() const optionalChargeLeadershipPickerRef = ref()
@@ -421,6 +466,7 @@ const formData = ref({
isSpecialFund: false, isSpecialFund: false,
industryUniversityResearch: '1', industryUniversityResearch: '1',
governmentDeclaration: '1', governmentDeclaration: '1',
other: '无',
resultForm: [] resultForm: []
}) })
@@ -434,20 +480,31 @@ const rules = reactive({
investmentType: [{required: true, message: '请选择出资类型', trigger: ['blur', 'change']}], investmentType: [{required: true, message: '请选择出资类型', trigger: ['blur', 'change']}],
projectImpact: [{required: true, message: '请选择项目影响', trigger: ['blur', 'change']}], projectImpact: [{required: true, message: '请选择项目影响', trigger: ['blur', 'change']}],
businessSegment: [{required: true, message: '请选择所属业务板块', trigger: ['blur', 'change']}], businessSegment: [{required: true, message: '请选择所属业务板块', trigger: ['blur', 'change']}],
resultForm: [{required: true, message: '请选择预期成果形式', trigger: ['blur', 'change']}], // resultForm: [{required: true, message: '请选择预期成果形式', trigger: ['blur', 'change']}],
technicalStandard: [{required: true, message: '请选择预期技术标准制定', trigger: ['blur', 'change']}], technicalStandard: [{required: true, message: '请选择预期技术标准制定', trigger: ['blur', 'change']}],
industryUniversityResearch: [{required: true, message: '请选择产学研联合', trigger: ['blur', 'change']}], industryUniversityResearch: [{required: true, message: '请选择产学研联合', trigger: ['blur', 'change']}],
governmentDeclaration: [{required: true, message: '请选择开展政府申报', trigger: ['blur', 'change']}], governmentDeclaration: [{required: true, message: '请选择开展政府申报', trigger: ['blur', 'change']}],
intellectualProperty: [{required: true, message: '请选择知识产权状况', trigger: ['blur', 'change']}], intellectualProperty: [{required: true, message: '请选择知识产权归属', trigger: ['blur', 'change']}],
inventionPatent: [{required: true, message: '请输入发明专利数量', trigger: ['blur', 'change']}],
newPatent: [{required: true, message: '请输入实用性新型专利数量', trigger: ['blur', 'change']}],
newPatent: [{required: true, message: '请输入专利数量', trigger: ['blur', 'change']}],
technicalNorms: [{required: true, message: '请输入技术标准数量', trigger: ['blur', 'change']}],
softwareCopyright: [{required: true, message: '请输入软件著作权数量', trigger: ['blur', 'change']}], softwareCopyright: [{required: true, message: '请输入软件著作权数量', trigger: ['blur', 'change']}],
copyright: [{required: true, message: '请输入著作权数量', trigger: ['blur', 'change']}], newProduct: [{required: true, message: '请输入新产品数量', trigger: ['blur', 'change']}],
other: [{required: true, message: '请输入其他数量', trigger: ['blur', 'change']}], newProcess: [{required: true, message: '请输入新工艺数量', trigger: ['blur', 'change']}],
newMaterials: [{required: true, message: '请输入新材料数量', trigger: ['blur', 'change']}],
newDevice: [{required: true, message: '请输入新装置数量', trigger: ['blur', 'change']}],
computerSoftware: [{required: true, message: '请输入计算机软件数量', trigger: ['blur', 'change']}],
thesis: [{required: true, message: '请输入论文论著数量', trigger: ['blur', 'change']}],
researchReport: [{required: true, message: '请输入研究报告数量', trigger: ['blur', 'change']}],
trademark: [{required: true, message: '请输入商标数量', trigger: ['blur', 'change']}],
other: [{required: true, message: '请输入其他项数量', trigger: ['blur', 'change']}],
economicEstimate: [{required: true, message: '请输入预估经费预算', trigger: ['blur', 'change']}], economicEstimate: [{required: true, message: '请输入预估经费预算', trigger: ['blur', 'change']}],
isSpecialFund: [{required: true, message: '请选择是否为专项资金', trigger: ['blur', 'change']}], isSpecialFund: [{required: true, message: '请选择是否为专项资金', trigger: ['blur', 'change']}],
isWithinBudget: [{required: true, message: '请选择是否在预算内', trigger: ['blur', 'change']}], isWithinBudget: [{required: true, message: '请选择是否在预算内', trigger: ['blur', 'change']}],
specialFundAmount: [{required: true, message: '请输入专项资金', trigger: ['blur', 'change']}], forecastSpecialFundAmount: [{required: true, message: '请输入专项资金', trigger: ['blur', 'change']}],
serviceDescription: [{required: true, message: '请输入现有业务描述', trigger: ['blur', 'change']}], serviceDescription: [{required: true, message: '请输入现有业务描述', trigger: ['blur', 'change']}],
contentDescription: [{required: true, message: '请输入研发项目关键内容描述', trigger: ['blur', 'change']}] contentDescription: [{required: true, message: '请输入研发项目关键内容描述', trigger: ['blur', 'change']}]
}) })
@@ -461,6 +518,7 @@ watch(() => singleList.value, (newVal) => {
}, {deep: true}) }, {deep: true})
localStorage.removeItem('originallySelectedList') localStorage.removeItem('originallySelectedList')
if (name.value === 'Summary/edit') { if (name.value === 'Summary/edit') {
} else { } else {
if (localStorage.getItem('collectData')) { if (localStorage.getItem('collectData')) {
let collectData = JSON.parse(localStorage.getItem('collectData')) let collectData = JSON.parse(localStorage.getItem('collectData'))
@@ -473,9 +531,31 @@ if (name.value === 'Summary/edit') {
formData.value = collectData formData.value = collectData
} }
} }
const changeRequirement=async ()=>{
await getInfo(formData.value.requirementId).then(res => {
if (res.code === 1000) {
console.log('formData.requirementId',formData.value.requirementId,res)
formData.value.isSpecialFund = res.data.formData.isSpecialFund
if ( res.data.formData.isSpecialFund) {
formData.value.specialFundId = res.data.formData.specialFundId
formData.value.specialFund = res.data.formData.specialFund
}else{
formData.value.specialFundId = null
formData.value.specialFund = null
}
}
})
}
const changeCollectData = () => { const changeCollectData = () => {
if (name.value === 'Summary/edit') { if (name.value === 'Summary/edit') {
// params.fileList= attachment.value.allFileList // params.fileList= attachment.value.allFileList
let params = {
...formData.value,
deploymentId: deploymentId.value,
requirementId: route.query.id ? route.query.id : formData.value.requirementId ? formData.value.requirementId : null
}
localStorage.setItem(`collectResubmitData-${route.query.projectId}`, JSON.stringify(params))
} else { } else {
let params = { let params = {
...formData.value, ...formData.value,
@@ -507,14 +587,25 @@ const disabledDate = (time) => {
const getProjectList = () => { const getProjectList = () => {
getProjectOption().then(res => { getProjectOption().then(res => {
if (res.code === 1000) { if (res.code === 1000) {
masterProjectList.value = res.data if(name.value === 'Summary/edit'){
masterProjectList.value = res.data.filter(item => item.value!=route.query.projectId)
}else{
masterProjectList.value = res.data
}
} }
}) })
} }
getProjectList() getProjectList()
const getRequirementList = () => { const getRequirementList = () => {
getRequirementOption().then(res => { getRequirementOption().then(res => {
if (res.code === 1000) { if (res.code === 1000) {
res.data= res.data?.map(item=>{
return {
label: item.label,
value: item.value+''
}
})
requirementList.value = res.data requirementList.value = res.data
} }
}) })
@@ -525,7 +616,7 @@ const getIsFund = async () => {
// loading.value = true // loading.value = true
await getFormInfo(route.query.id).then(res => { await getFormInfo(route.query.id).then(res => {
if (res.code === 1000) { if (res.code === 1000) {
formData.value.requirementDefaultName = res.data.requirementName requirementDefaultName.value = res.data.requirementName
// loading.value = false // loading.value = false
formData.value.isSpecialFund = res.data.isSpecialFund formData.value.isSpecialFund = res.data.isSpecialFund
if (res.data.isSpecialFund) { if (res.data.isSpecialFund) {
@@ -636,8 +727,11 @@ const handleSubmit = debounce(async (instance) => {
if (formData.value.singleFile !== undefined) { if (formData.value.singleFile !== undefined) {
formData.value.singleFile = getFileParam(formData.value.singleFile) formData.value.singleFile = getFileParam(formData.value.singleFile)
} }
if (formData.value.isSpecialFund && !formData.value.specialFund) { if (formData.value.isSpecialFund) {
formData.value.specialFund = getFundName(formData.value.specialFundId) formData.value.specialFund = getFundName(formData.value.specialFundId)
}else{
formData.value.specialFundId = 0
formData.value.specialFund=null
} }
if (formData.value.masterProjectId) { if (formData.value.masterProjectId) {
formData.value.masterProjectName = getProjectName(formData.value.masterProjectId) formData.value.masterProjectName = getProjectName(formData.value.masterProjectId)
@@ -696,8 +790,11 @@ const handleResubmit = debounce((instance) => {
}) })
} }
formData.value.optionalChargeLeadership = optionalChargeLeadershipList.value formData.value.optionalChargeLeadership = optionalChargeLeadershipList.value
if (formData.value.isSpecialFund && !formData.value.specialFund) { if (formData.value.isSpecialFund) {
formData.value.specialFund = getFundName(formData.value.specialFundId) formData.value.specialFund = getFundName(formData.value.specialFundId)
}else{
formData.value.specialFundId = 0
formData.value.specialFund=null
} }
if (formData.value.masterProjectId) { if (formData.value.masterProjectId) {
formData.value.masterProjectName = getProjectName(formData.value.masterProjectId) formData.value.masterProjectName = getProjectName(formData.value.masterProjectId)
@@ -722,7 +819,7 @@ const handleResubmit = debounce((instance) => {
fileList: otherFiles, fileList: otherFiles,
requirementId: route.query.id ? route.query.id : formData.value.requirementId ? formData.value.requirementId : '-1' requirementId: route.query.id ? route.query.id : formData.value.requirementId ? formData.value.requirementId : '-1'
} }
// console.log('重新提交params', params, formData.value.specialFund, formData.value.specialFundId) console.log('重新提交params', params)
resubmitReported(params).then(res => { resubmitReported(params).then(res => {
ElNotification({ ElNotification({
title: '提示', title: '提示',
@@ -734,8 +831,8 @@ const handleResubmit = debounce((instance) => {
router.push({ router.push({
name: 'Summary' name: 'Summary'
}) })
// localStorage.removeItem('collectData')
} }
localStorage.removeItem(`collectResubmitData-${route.query.projectId}`)
}) })
}) })
}) })
@@ -752,7 +849,25 @@ const getDetailInfo = async () => {
opentionData.value = res.data opentionData.value = res.data
optionalChargeLeadershipList.value = formData.value.optionalChargeLeadership optionalChargeLeadershipList.value = formData.value.optionalChargeLeadership
loading.value = false loading.value = false
if (name.value === 'Summary/edit') {
if (localStorage.getItem(`collectResubmitData-${route.query.projectId}`)) {
let collectResubmitData = JSON.parse(localStorage.getItem(`collectResubmitData-${route.query.projectId}`))
if(formData.value.projectId==collectResubmitData.projectId){
if (collectResubmitData.fileList) {
otherFileList.value = collectResubmitData.fileList
}
if (collectResubmitData.optionalChargeLeadership) {
optionalChargeLeadershipList.value = collectResubmitData.optionalChargeLeadership
}
formData.value = collectResubmitData
}
}
}
}else{ }else{
loading.value = false
ElNotification({ ElNotification({
title: '提示', title: '提示',
message: res.msg, message: res.msg,

View File

@@ -6,7 +6,7 @@
<script setup lang="jsx"> <script setup lang="jsx">
import fvSelect from '@/fvcomponents/fvSelect/index.vue' import fvSelect from '@/fvcomponents/fvSelect/index.vue'
import {addPlan, getRequirementName} from "@/api/project-demand/summary"; import {addPlan, getProjectName, getRequirementName} from "@/api/project-demand/summary";
import {getSubCompOpt} from "@/api/user/user"; import {getSubCompOpt} from "@/api/user/user";
import {filterRequirementName} from "@/api/project-demand"; import {filterRequirementName} from "@/api/project-demand";
@@ -73,6 +73,36 @@ const searchConfig = ref([
}, },
component: shallowRef(fvSelect), component: shallowRef(fvSelect),
}, },
{
label: '项目名称',
prop: 'projectName',
props: {
placeholder: '请输入项目名称',
clearable: true,
filterable: true,
options: [],
remote: true,
remoteMethod:async (val)=>{
if(val){
const res=await getProjectName(val)
if(res.code==1000){
let optionObj={}
let optionsMap = new Map();
res.data.rows.forEach(item=>{
optionObj={
value:item.projectName,
label:item.projectName
}
optionsMap.set(optionObj.value, optionObj);
})
// 将 Map 转换为数组
searchConfig.value.find(item => item.prop == 'projectName').props.options = Array.from(optionsMap.values())
}
}
}
},
component: shallowRef(fvSelect),
},
{ {
label: '项目类型', label: '项目类型',
prop: 'projectType', prop: 'projectType',
@@ -88,7 +118,7 @@ const searchConfig = ref([
}, },
{ {
label: '承办单位', label: '承办单位',
prop: 'undertaker', prop: 'affiliatedCompanyId',
component: 'el-tree-select', component: 'el-tree-select',
props: { props: {
placeholder: '请输入承办单位查询', placeholder: '请输入承办单位查询',
@@ -218,6 +248,11 @@ const tableConfig = reactive({
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1 return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
} }
}, },
{
prop: 'processNumber',
label: '项目编号',
align: 'center',
},
{ {
prop: 'requirementName', prop: 'requirementName',
label: '征集名称', label: '征集名称',
@@ -441,7 +476,7 @@ const handleDetail = (row) => {
} }
const init = async () => { const init = async () => {
const res = await getSubCompOpt() const res = await getSubCompOpt()
searchConfig.value.find(item=>item.prop == 'undertaker').props.data = res.data searchConfig.value.find(item=>item.prop == 'affiliatedCompanyId').props.data = res.data
} }
init() init()

View File

@@ -157,7 +157,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -171,6 +171,21 @@ const schema = computed(() => {
} }
</div> </div>
) )
}, {
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '产学研联合', label: '产学研联合',
@@ -210,9 +225,24 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},{
label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '申请总部专项资金(元)', label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -249,6 +279,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -11,7 +11,7 @@
import fvSelect from '@/fvcomponents/fvSelect/index.vue' import fvSelect from '@/fvcomponents/fvSelect/index.vue'
import {toThousands} from '@/utils/changePrice.js' import {toThousands} from '@/utils/changePrice.js'
import {switchAttachmentState} from "@/api/project-manage/attachment"; import {switchAttachmentState} from "@/api/project-manage/attachment";
import {ElMessageBox} from "element-plus"; import {ElMessageBox, ElNotification} from "element-plus";
import { getSubCompOpt } from '@/api/user/user.js'; import { getSubCompOpt } from '@/api/user/user.js';
import {filterProjectName} from "@/api/project-manage"; import {filterProjectName} from "@/api/project-manage";
import {filterRequirementName} from "@/api/project-demand"; import {filterRequirementName} from "@/api/project-demand";
@@ -216,6 +216,12 @@ const tableConfig = reactive({
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1 return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
} }
}, },
{
prop: 'processNumber',
label: '项目编号',
align: 'center',
},
{ {
prop: 'requirementName', prop: 'requirementName',
label: '征集名称', label: '征集名称',
@@ -275,7 +281,7 @@ const tableConfig = reactive({
}, },
{ {
prop: 'economicEstimate', prop: 'economicEstimate',
label: '经费预算(元)', label: '预估经费预算(元)',
align: 'center', align: 'center',
width: 150, width: 150,
currentRender:({row})=>{ currentRender:({row})=>{
@@ -312,10 +318,18 @@ const tableConfig = reactive({
width: 100, width: 100,
showOverflowTooltip: false, showOverflowTooltip: false,
currentRender: ({row, index}) => { currentRender: ({row, index}) => {
if (row.state !== null) { let buttons = new Set(Array.from(row.buttons))
return (<Tag dictType={'project_filing'} value={row.state}/>) if (!buttons.has("openFileSwitch")&&row.state!=1) {
} else { console.log('row',row)
return '--' return (<Tag dictType={'project_filing'} value={'0'}/>)
}else if (buttons.has("openFileSwitch")) {
return (<Tag dictType={'project_filing'} value={'4'}/>)
}else{
if (row.state !== null) {
return (<Tag dictType={'project_filing'} value={row.state}/>)
} else {
return '--'
}
} }
} }
}, },
@@ -342,10 +356,10 @@ const tableConfig = reactive({
btn.push({label: '编辑', prem: ['project:management:filing:conclusion'], func: () => handleEdit(row), type: 'primary'}) btn.push({label: '编辑', prem: ['project:management:filing:conclusion'], func: () => handleEdit(row), type: 'primary'})
} }
if (buttons.has("openFileSwitch")) { if (buttons.has("openFileSwitch")) {
btn.push({label: '开启上传', prem: ['project:management:filing:conclusion'], func: () => handleOpenUpload(row,true), type: 'primary'}) btn.push({label: '开启上传', prem: ['filing:attachment:switch'], func: () => handleOpenUpload(row,true), type: 'primary'})
} }
if (buttons.has("closeFileSwitch")) { if (buttons.has("closeFileSwitch")) {
btn.push({label: '关闭上传', prem: ['project:management:filing:conclusion'], func: () => handleOpenUpload(row,false), type: 'primary'}) btn.push({label: '关闭上传', prem: ['filing:attachment:switch'], func: () => handleOpenUpload(row,false), type: 'primary'})
} }
return ( return (
<div style={{width: '100%'}}> <div style={{width: '100%'}}>
@@ -420,6 +434,7 @@ const handleEdit = (row) => {
}) })
} }
const handleOpenUpload=(row,flag)=>{ const handleOpenUpload=(row,flag)=>{
console.log('tableIns',tableIns.value)
ElMessageBox.confirm(`是否确认${flag?'开启':'关闭'}上传文件?`, '提示', { ElMessageBox.confirm(`是否确认${flag?'开启':'关闭'}上传文件?`, '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
@@ -430,7 +445,15 @@ const handleOpenUpload=(row,flag)=>{
projectId: row.projectId projectId: row.projectId
} }
switchAttachmentState(params).then(res=>{ switchAttachmentState(params).then(res=>{
tableIns.value.refresh() if(res.code==1000){
tableIns.value.refresh()
}else{
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
}) })
}) })
} }

View File

@@ -168,7 +168,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -183,6 +183,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -223,7 +239,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -260,6 +292,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -163,7 +163,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -178,6 +178,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
basicData.value?.actualEconomicEstimate ?
<span>{toThousands(basicData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -218,7 +234,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
basicData.value?.forecastSpecialFundAmount ?
<span>{toThousands(basicData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -255,6 +287,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -177,7 +177,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -232,7 +232,7 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6

View File

@@ -13,9 +13,9 @@
:formData="detailData.formData" :formData="detailData.formData"
:data="detailData" :data="detailData"
:processViewer="commonProvessViewer" :processViewer="commonProvessViewer"
:fileListShow="fileListShow" :fileListShow="fileListShow" @ccSend="ccSendRefresh"
v-model:value="auditOpinion"/> v-model:value="auditOpinion"/>
<ApprovalDetail type="approval" <ApprovalDetail type="approval" @ccSend="ccSendRefresh"
v-if="showActive == '20'&&!editShow" v-if="showActive == '20'&&!editShow"
:formData="detailData.formData" :formData="detailData.formData"
:data="detailData" :data="detailData"
@@ -27,7 +27,7 @@
<div v-if="showActive == '30'&&!editShow"> <div v-if="showActive == '30'&&!editShow">
<project-attachment/> <project-attachment/>
</div> </div>
<ApprovalDetail type="execute" <ApprovalDetail type="execute" @ccSend="ccSendRefresh"
v-if="showActive == '40'&&!editShow" v-if="showActive == '40'&&!editShow"
:formData="detailData.formData" :formData="detailData.formData"
:data="detailData" :data="detailData"
@@ -36,7 +36,7 @@
:preProcessShow="preProcessShow" :preProcessShow="preProcessShow"
:basicData="basicData" :basicData="basicData"
v-model:value="auditOpinion"/> v-model:value="auditOpinion"/>
<ApprovalDetail type="archivist" <ApprovalDetail type="archivist" @ccSend="ccSendRefresh"
v-if="showActive == '50'&&!editShow" v-if="showActive == '50'&&!editShow"
:formData="detailData.formData" :formData="detailData.formData"
:data="detailData" :data="detailData"
@@ -50,6 +50,7 @@
:mode="mode" :mode="mode"
:step="showActive" :step="showActive"
:data="detailData" :data="detailData"
:basicData="basicData"
:preProcessShow="preProcessShow" :preProcessShow="preProcessShow"
:formData="detailData.formData"/> :formData="detailData.formData"/>
</template> </template>
@@ -98,7 +99,9 @@ localStorage.removeItem('projectPersonUserList')
localStorage.removeItem('optionalChargeLeadershipList') localStorage.removeItem('optionalChargeLeadershipList')
localStorage.removeItem('originallySelectedList') localStorage.removeItem('originallySelectedList')
const ccSendRefresh=()=>{
getAllInfo(route.query.step)
}
const getAllInfo = async (state) => { const getAllInfo = async (state) => {
const loading = ElLoading.service({fullscreen: true}) const loading = ElLoading.service({fullscreen: true})
detailData.value = { detailData.value = {
@@ -113,6 +116,7 @@ const getAllInfo = async (state) => {
if (code === 1000) { if (code === 1000) {
data.formData.preProcess = data.formData.preProcess ? JSON.parse(data.formData.preProcess) : undefined data.formData.preProcess = data.formData.preProcess ? JSON.parse(data.formData.preProcess) : undefined
detailData.value = data detailData.value = data
localStorage.setItem('detailProcess', JSON.stringify(data.formData.preProcess))
mode.value = data.formData.mode mode.value = data.formData.mode
processStore.setDesign(data) processStore.setDesign(data)
processStore.runningList.value = data.runningList; processStore.runningList.value = data.runningList;

View File

@@ -219,6 +219,12 @@ const tableConfig = reactive({
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1 return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
} }
}, },
{
prop: 'processNumber',
label: '项目编号',
align: 'center',
},
{ {
prop: 'requirementName', prop: 'requirementName',
label: '征集名称', label: '征集名称',
@@ -292,7 +298,7 @@ const tableConfig = reactive({
}, },
{ {
prop: 'economicEstimate', prop: 'economicEstimate',
label: '经费预算(元)', label: '预估经费预算(元)',
align: 'center', align: 'center',
width: 150, width: 150,
currentRender:({row})=>{ currentRender:({row})=>{

View File

@@ -230,7 +230,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -244,6 +244,21 @@ const schema = computed(() => {
} }
</div> </div>
) )
}, {
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '产学研联合', label: '产学研联合',
@@ -283,9 +298,24 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
}, {
label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '申请总部专项资金(元)', label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -322,6 +352,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -170,7 +170,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -184,6 +184,21 @@ const schema = computed(() => {
} }
</div> </div>
) )
},{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '产学研联合', label: '产学研联合',
@@ -223,9 +238,24 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
}, {
label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '申请总部专项资金(元)', label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -262,6 +292,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -145,7 +145,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -159,6 +159,21 @@ const schema = computed(() => {
} }
</div> </div>
) )
}, {
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
}, },
{ {
label: '产学研联合', label: '产学研联合',
@@ -200,7 +215,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -237,6 +268,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -4,22 +4,37 @@
<fvForm :schema="schema" @getInstance="(e)=>baseForm = e" label-position="left" label-width="left" <fvForm :schema="schema" @getInstance="(e)=>baseForm = e" label-position="left" label-width="left"
style="margin-left: 15px;margin-bottom: -18px"></fvForm> style="margin-left: 15px;margin-bottom: -18px"></fvForm>
<baseTitle title="项目实施-上传附件" ></baseTitle> <baseTitle title="项目实施-上传附件" ></baseTitle>
<el-form :model="formData" ref="tagForm" label-width="auto"> <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick" @tab-remove="tabRemove"
<el-form-item label="标签名称" prop="tagName" style="margin-left: 15px;"> style="margin-left: 15px;margin-top: -10px">
<el-input v-model="formData.tagName" placeholder="请输入标签名称" style="width: 300px;margin-right: 10px" v-if="showInput" clearable/> <el-tab-pane name="all" :closable="false" label="全部">
<el-select v-model="formData.tagName" placeholder="请选择标签名称" clearable filterable style="width: 300px;margin-right: 10px" v-else> </el-tab-pane>
<el-option <el-tab-pane v-for="item in tagsOption" :closable="item.isClose==1"
v-for="item in tagsOption" :key="item.tagId"
:key="item.value" :label="item.fileTag"
:label="item.label" :name="item.tagId">
:value="item.value" <div class="tag-title">
/> <div></div>
</el-select> {{ item.fileTag }}
<el-button type="primary" link @click="changeInput">{{ showInput ? '选择' : '输入' }}</el-button> </div>
</el-form-item> </el-tab-pane>
</el-form>
<!-- <baseTitle title="其他文件"></baseTitle>--> <el-tab-pane name="plus" :closable="false">
<file-upload @getFile="getFile" :disabled="!formData.tagName" :title="!formData.tagName?'请先选择/输入标签!':''" style="margin-left: 15px"/> <template #label>
<div style="margin-top: 4px;">
<el-icon color="#BEA266">
<Plus/>
</el-icon>
</div>
</template>
</el-tab-pane>
</el-tabs>
<div style="margin-top:10px;margin-bottom: 8px;margin-left: 15px;display: flex">
<file-upload v-if="activeName!='plus'&&activeName!='all'" @getFile="getFile"/>
<el-button color="#DED0B2" @click="handleEditTag" v-if="activeName!='all'&&activeName!='plus'&&!isDefault"
style="margin-left: 10px;">编辑
</el-button>
</div>
<fvTable style="width: 100%;max-height: 318px;" v-if="showTable" height="318" :tableConfig="tableConfig" <fvTable style="width: 100%;max-height: 318px;" v-if="showTable" height="318" :tableConfig="tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false"> :data="fileList" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
@@ -31,15 +46,25 @@
</div> </div>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl" <file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/> :fileType="filePreviewParam.fileType"/>
<el-dialog v-model="tagNameShow" center width="450" top="40vh">
<div style="display: flex;align-items: center">标签
<el-input v-model="fileParam.tagName" placeholder="请输入标签名称" style="width: 335px;" clearable/>
</div>
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
<el-button color="#DED0B2" @click="changeTag()">确定</el-button>
<el-button @click="tagNameShow=false">取消</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import {getTags} from "@/api/project-manage"; import {addTag, delTag, getTagList, getTags, updateTag} from "@/api/project-manage";
import {ElNotification} from "element-plus"; import {ElMessageBox, ElNotification} from "element-plus";
import {useTagsView} from '@/stores/tagsview.js' import {useTagsView} from '@/stores/tagsview.js'
import {uploadFileList} from "@/api/project-manage/attachment"; import {searchImplementationFileList, uploadFileList} from "@/api/project-manage/attachment";
import {computed, ref} from "vue"; import {computed, nextTick, ref} from "vue";
import {getBaseInfoApi} from "@/components/steps/api"; import {getBaseInfoApi} from "@/components/steps/api";
import {deleteFile, downloadFile} from "@/api/project-demand"; import {deleteFile, downloadFile} from "@/api/project-demand";
@@ -52,7 +77,11 @@ const tagsViewStore = useTagsView()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const fileList = ref([]) const fileList = ref([])
const allFileList = ref([])
const activeName = ref('all')
const tagNameShow = ref(false)
const showInput = ref(false) const showInput = ref(false)
const isDefault = ref(false)
const baseFormData = ref([]) const baseFormData = ref([])
const schema = computed(() => { const schema = computed(() => {
return [ return [
@@ -182,7 +211,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -197,6 +226,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -237,7 +282,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -246,7 +307,7 @@ const schema = computed(() => {
<div> <div>
{ {
baseFormData.value?.specialFundAmount ? baseFormData.value?.specialFundAmount ?
<span>{ toThousands(baseFormData.value?.specialFundAmount )}</span> <span>{toThousands(baseFormData.value?.specialFundAmount)}</span>
: <span>{'--'}</span> : <span>{'--'}</span>
} }
</div> </div>
@@ -274,12 +335,19 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })
const baseForm = ref() const baseForm = ref()
const tagsOption = ref([]) const tagsOption = ref([])
const formData = ref({ const fileParam = ref({
tagName: '' tagName: ''
}) })
const tableConfig = reactive({ const tableConfig = reactive({
@@ -318,8 +386,11 @@ const tableConfig = reactive({
return ( return (
<div> <div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button> <el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'} {
onDelete={() => handleDelete(row)}/> row.oldType ? null : <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
}
</div> </div>
) )
} }
@@ -338,11 +409,147 @@ const filePreviewParam = ref({
fileType: 'pdf' fileType: 'pdf'
}) })
const filePreviewShow = ref(false) const filePreviewShow = ref(false)
const isEdit = ref(false)
const changeTag = async () => {
let res = null
if (isEdit.value) {
res = await updateTag({
tagId: activeName.value,
fileTag: fileParam.value.tagName,
projectId: route.query.projectId,
})
} else {
res = await addTag({
projectId: route.query.projectId,
fileTag: fileParam.value.tagName
})
fileParam.value.tagName = ''
activeName.value = 'all'
}
getTagsOption()
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagNameShow.value = false;
}
const getOldFileList = (tag,flag) => {
let params = {}
if (tag == 'all') {
params = {
targetId: route.query.projectId,
targetState: "30",
}
} else {
params = {
targetId: route.query.projectId,
targetState: "30",
tag: getTagName(activeName.value)
}
}
showTable.value = false
searchImplementationFileList(params).then(res => {
if (res.code === 1000) {
if(tag == 'all'){
res.data.fileList?.forEach(item=>{
item.oldType=true
fileList.value.push(item)
})
}else{
res.data.fileList?.forEach(item=>{
item.oldType=true
if(getTagName(activeName.value)==item.tag){
fileList.value.push(item)
}
})
console.log("🚀 ~ file:'fileList.value ",fileList.value)
}
if(flag){
getTagsOption(flag)
}
nextTick(() => {
showTable.value = true
})
changeImplementFile()
}
})
}
const handleEditTag = () => {
fileParam.value.tagName = getTagName(activeName.value)
if(fileList.value&&fileList.value.length>0){
ElNotification({
title: '提示',
message: '该标签下存在文件,不能编辑标签。如需编辑标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
tagNameShow.value = true
isEdit.value = true
}
const tabRemove = async (val) => {
if(fileList.value&&fileList.value.length>0){
ElNotification({
title: '提示',
message: '该标签下存在文件,不能删除标签。如需删除标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
ElMessageBox.confirm(`确认删除名称为${getTagName(val)}的标签吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
let res = await delTag(val)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
getTagsOption()
}
})
}
const handleTabClick = (item) => {
activeName.value = item.props.name
const defaultArray=tagsOption.value.filter(item1=>item1.tagId==item.props.name)
if(defaultArray&&defaultArray.length>0){
isDefault.value=defaultArray[0].isDefault==1
}else{
isDefault.value=false
}
tagNameShow.value = item.props.name == 'plus';
if (item.props.name == 'plus') {
isEdit.value = false
fileParam.value.tagName = ''
}
const fileArray=JSON.parse(localStorage.getItem('implementFile'))
if (item.props.name != 'plus') {
if (item.props.name == 'all') {
fileList.value=fileArray
getOldFileList('all')
} else {
fileList.value=fileArray.filter(item1 => item1.tag == getTagName(item.props.name))
getOldFileList()
showTable.value = false
nextTick(() => {
showTable.value = true
})
}
}
}
if(localStorage.getItem('implementFile')){ if(localStorage.getItem('implementFile')){
fileList.value=JSON.parse(localStorage.getItem('implementFile')) fileList.value=JSON.parse(localStorage.getItem('implementFile'))
allFileList.value=JSON.parse(localStorage.getItem('implementFile'))
} }
const changeImplementFile=()=>{ const changeImplementFile=()=>{
localStorage.setItem('implementFile', JSON.stringify(fileList.value)) localStorage.setItem('implementFile', JSON.stringify(allFileList.value))
} }
const clickToPreview=(row)=>{ const clickToPreview=(row)=>{
@@ -358,7 +565,7 @@ const clickToPreview=(row)=>{
} }
onActivated(() => { onActivated(() => {
console.log('onActivated') console.log('onActivated')
formData.value.tagName = ''; fileParam.value.tagName = '';
showTable.value = false showTable.value = false
nextTick(() => { nextTick(() => {
showTable.value = true showTable.value = true
@@ -371,7 +578,7 @@ const filterDict = (data, value) => {
let label = '' let label = ''
let result = [] let result = []
if (value instanceof Array) { if (value instanceof Array) {
value.forEach(item1 => { value?.forEach(item1 => {
data.find(item => { data.find(item => {
if (item.value == item1) { if (item.value == item1) {
result.push(item.label) result.push(item.label)
@@ -425,14 +632,54 @@ const getBaseInfo = async () => {
getBaseInfo() getBaseInfo()
const changeInput = () => { const changeInput = () => {
showInput.value = !showInput.value; showInput.value = !showInput.value;
formData.value.tagName = ''; fileParam.value.tagName = '';
}
const getTagName = (name) => {
const tagArray = tagsOption.value.filter((item1) => item1.tagId == name)
let tagName = ''
if (tagArray && tagArray.length > 0) {
tagName = tagArray[0].fileTag
}
return tagName
} }
const getTagsOption = () => { const getTagsOption = () => {
if (!route.query.projectId) return if (!route.query.projectId) return
getTags(route.query.projectId).then(res => { getTagList(route.query.projectId).then(res => {
if (res.code === 1000) { if (res.code === 1000) {
showInput.value = res.data.length === 0; tagsOption.value = res.data.rows
tagsOption.value = res.data console.log("🚀 ~ file: res.data.rows ", res.data.rows)
tagsOption.value?.forEach((tag, index) => {
tagsOption.value[index].isClose =1
})
let defaultArray=[
{
tagId: 'd1',
fileTag: '合同(专项任务书)',
isDefault: 1,
isClose: 2
},
{
tagId: 'd2',
fileTag: '周报',
isDefault: 1,
isClose: 2
},
{
tagId: 'd3',
fileTag: '阶段性验收',
isDefault: 1,
isClose: 2
},
{
tagId: 'd4',
fileTag: '科研成果',
isDefault: 1,
isClose: 2
}
]
tagsOption.value=[...defaultArray,...tagsOption.value]
console.log("🚀 ~ file:tagsOption.value ", tagsOption.value)
}else{ }else{
ElNotification({ ElNotification({
title: '提示', title: '提示',
@@ -444,9 +691,9 @@ const getTagsOption = () => {
} }
const compositeParam = (item) => { const compositeParam = (item) => {
tagsOption.value.forEach(item => { tagsOption.value?.forEach(item => {
if (item.value == formData.value.tagName) { if (item.value == fileParam.value.tagName) {
formData.value.tagName = item.label fileParam.value.tagName = item.label
} }
}) })
return { return {
@@ -456,7 +703,7 @@ const compositeParam = (item) => {
fileType: item.fileType, fileType: item.fileType,
url: item.url, url: item.url,
newFile: true, newFile: true,
tag: formData.value.tagName, tag: getTagName(activeName.value) || '项目实施',
} }
} }
const getFile = (val) => { const getFile = (val) => {
@@ -464,24 +711,17 @@ const getFile = (val) => {
showTable.value = false showTable.value = false
let fileObj = compositeParam(val) let fileObj = compositeParam(val)
fileList.value.push(fileObj) fileList.value.push(fileObj)
allFileList.value.push(fileObj)
nextTick(() => { nextTick(() => {
showTable.value = true showTable.value = true
}) })
changeImplementFile() changeImplementFile()
} }
const handleSubmit = async (instance) => { const handleSubmit = async (instance) => {
if (!instance) return const files=JSON.parse(localStorage.getItem('implementFile'))
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let params = { let params = {
fileList: fileList.value, fileList: files,
projectId: route.query.projectId, projectId: route.query.projectId,
targetState: "30" targetState: "30"
} }
@@ -525,9 +765,9 @@ const handleSubmit = async (instance) => {
} }
localStorage.removeItem('implementFile') localStorage.removeItem('implementFile')
} }
})
} }
getTagsOption() getTagsOption()
getOldFileList('all')
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -550,4 +790,12 @@ getTagsOption()
} }
} }
} }
:deep(.el-tabs__item.is-active) {
color: #BEA266;
}
:deep(.el-tabs__active-bar) {
background-color: #BEA266;
}
</style> </style>

View File

@@ -253,7 +253,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 6 span: 6
@@ -268,6 +268,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -315,7 +331,23 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 6 span: 6
@@ -352,6 +384,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 6 span: 6
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
} }
] ]
}) })

View File

@@ -214,6 +214,11 @@ const tableConfig = reactive({
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1 return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
} }
}, },
{
prop: 'processNumber',
label: '项目编号',
align: 'center',
},
{ {
prop: 'requirementName', prop: 'requirementName',
label: '征集名称', label: '征集名称',
@@ -274,7 +279,7 @@ const tableConfig = reactive({
}, },
{ {
prop: 'economicEstimate', prop: 'economicEstimate',
label: '经费预算(元)', label: '预估经费预算(元)',
align: 'center', align: 'center',
width: 150, width: 150,
currentRender:({row})=>{ currentRender:({row})=>{

View File

@@ -1,16 +1,16 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<baseTitle v-if="type!='phase'" :title="getTagName(type)+'信息'" ></baseTitle> <baseTitle v-if="type!='phase'" :title="getTagName(type)+'信息'"></baseTitle>
<fvForm :schema="schema" @getInstance="(e)=>form = e" style="margin-left: 15px"></fvForm> <fvForm :schema="schema" @getInstance="(e)=>form = e" style="margin-left: 15px"></fvForm>
<el-form :model="formData" label-width="auto"> <el-form :model="formData" label-width="auto">
<file-component <file-component
:title="getTagName(type)+'附件'" :title="getTagName(type)+'附件'"
:fileNameTableWidth="300" :fileNameTableWidth="150"
:tag="getTagName(type)" :tag="getTagName(type)"
v-model:value="formData.fileList" v-model:value="formData.fileList"
:processViewer="processViewer" :processViewer="processViewer"
:file-list-show="fileListShow" :file-list-show="fileListShow"
labelAlign="top" labelAlign="top"
/> />
</el-form> </el-form>
<div v-if="data.taskId"> <div v-if="data.taskId">
@@ -36,7 +36,8 @@
</div> </div>
</div> </div>
<div class="process"> <div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram" :isColumn="true" <operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:isColumn="true"
:operation-list="data.operationList" :operation-list="data.operationList"
:state="data.state"/> :state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/> <process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/>
@@ -115,7 +116,8 @@ const editSingleTableConfig = reactive({
label: '文件名', label: '文件名',
align: 'center', align: 'center',
width: 300, width: 300,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>) currentRender: ({row, index}) => (
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
}, },
{ {
prop: 'tag', prop: 'tag',
@@ -192,7 +194,7 @@ const schema = computed(() => {
colProps: { colProps: {
span: 24 span: 24
}, },
labelWidth:'left', labelWidth: 'left',
component: () => ( component: () => (
<div> <div>
{ {
@@ -209,12 +211,13 @@ const schema = computed(() => {
colProps: { colProps: {
span: 24 span: 24
}, },
labelWidth:'left', labelWidth: 'left',
component: () => ( component: () => (
<div> <div>
{ {
props.formData.projectPersonList ? props.formData.projectPersonList.map((item, index) => { props.formData.projectPersonList ? props.formData.projectPersonList.map((item, index) => {
return <span>{item.name} <span>{index != props.formData.projectPersonList?.length - 1 ? '' : ''}</span></span> return <span>{item.name}
<span>{index != props.formData.projectPersonList?.length - 1 ? '' : ''}</span></span>
}) : <span>{'--'}</span> }) : <span>{'--'}</span>
} }
</div> </div>
@@ -273,7 +276,188 @@ const schema = computed(() => {
// } // }
// }) // })
} else if (props.type == 'execute') { } else if (props.type == 'execute') {
arr = [{ arr = [
{
label: '实际专利(项)',
prop: 'actualNewPatent',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewPatent ? props.formData.actualNewPatent : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际软件著作权(项)',
prop: 'actualSoftwareCopyright',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualSoftwareCopyright ? props.formData.actualSoftwareCopyright : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际技术标准(项)',
prop: 'actualTechnicalNorms',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualTechnicalNorms ? props.formData.actualTechnicalNorms : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新产品(项)',
prop: 'actualNewProduct',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewProduct ? props.formData.actualNewProduct : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新工艺(项)',
prop: 'actualNewProcess',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewProcess ? props.formData.actualNewProcess : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新装置(项)',
prop: 'actualNewDevice',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewDevice ? props.formData.actualNewDevice : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际新材料(项)',
prop: 'actualNewMaterials',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualNewMaterials ? props.formData.actualNewMaterials : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际计算机软件(项)',
prop: 'actualComputerSoftware',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualComputerSoftware ? props.formData.actualComputerSoftware : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际论文论著(项)',
prop: 'actualThesis',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualThesis ? props.formData.actualThesis : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际研究报告(项)',
prop: 'actualResearchReport',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualResearchReport ? props.formData.actualResearchReport : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际商标(项)',
prop: 'actualTrademark',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.actualTrademark ? props.formData.actualTrademark : <span>{'--'}</span>
}
</div>
)
},
{
label: '实际其他(项)',
prop: 'actualOther',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div style="white-space: pre-wrap;">
{
props.formData.actualOther ? props.formData.actualOther : <span>{'--'}</span>
}
</div>
)
},
{
label: '部门分管领导', label: '部门分管领导',
prop: 'optionalChargeLeadership', prop: 'optionalChargeLeadership',
colProps: { colProps: {
@@ -309,22 +493,22 @@ const schema = computed(() => {
} }
arr.push(preProcess) arr.push(preProcess)
// arr.push( // arr.push(
// { // {
// label: '项目验收附件', // label: '项目验收附件',
// prop: 'singleFile', // prop: 'singleFile',
// colProps: { // colProps: {
// span: 24 // span: 24
// }, // },
// labelWidth: 'left', // labelWidth: 'left',
// component: () => { // component: () => {
// let singleFileArray = [props.formData.singleFile] // let singleFileArray = [props.formData.singleFile]
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80" // return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
// tableConfig={editSingleTableConfig} // tableConfig={editSingleTableConfig}
// data={singleFileArray} isSettingCol={false} pagination={false}> // data={singleFileArray} isSettingCol={false} pagination={false}>
// </fvTable> // </fvTable>
// : <span>--</span> // : <span>--</span>
// } // }
// }) // })
} else if (props.type == 'archivist') { } else if (props.type == 'archivist') {
arr = [ arr = [
// { // {
@@ -377,14 +561,14 @@ const _value = computed({
emit("update:value", val); emit("update:value", val);
} }
}) })
const clickToPreview=(row)=>{ const clickToPreview = (row) => {
filePreviewShow.value = false filePreviewShow.value = false
filePreviewParam.value = { filePreviewParam.value = {
fileUrl: row.url, fileUrl: row.url,
fileName: row.originalFileName, fileName: row.originalFileName,
fileType: row.fileType fileType: row.fileType
} }
nextTick(()=>{ nextTick(() => {
filePreviewShow.value = true filePreviewShow.value = true
}) })
} }
@@ -393,7 +577,7 @@ const getTagName = (type) => {
case 'approval': case 'approval':
return '项目立项' return '项目立项'
case 'execute': case 'execute':
return '项目实施' return '项目验收'
case 'archivist': case 'archivist':
return '项目归档' return '项目归档'
case 'phase': case 'phase':

View File

@@ -52,7 +52,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件文件"></baseTitle> <baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件文件"></baseTitle>
<file-component title="" tag="需求征集" :fullscreen="true" :fileNameTableWidth="300" <file-component title="" tag="需求征集" :fullscreen="true" :fileNameTableWidth="150"
v-model:value="formData.fileList" :processViewer="processViewer" v-model:value="formData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/> :file-list-show="fileListShow"/>
</el-col> </el-col>

View File

@@ -201,6 +201,14 @@ const rollbackHandler = async () => {
} }
} }
const handleAgree = async () => { const handleAgree = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
// const values = form.value.getValues() // const values = form.value.getValues()
const params = { const params = {
taskId: props.taskId, taskId: props.taskId,

View File

@@ -21,19 +21,28 @@
<span>{{ toThousands(formData.residualAmount) }}</span> <span>{{ toThousands(formData.residualAmount) }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<baseTitle title="介绍"></baseTitle> <!-- <baseTitle title="介绍"></baseTitle>-->
<!-- <el-col :span="24">-->
<!-- <el-form-item>-->
<!-- <el-card style="width: 100%">-->
<!-- <div v-html="formData.introduce">-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="24"> <el-col :span="24">
<el-form-item> <el-form-item label="专项资金情况说明" >
<el-card style="width: 100%"> <div style="white-space: pre-wrap">{{formData.introduce}}
<div v-html="formData.introduce"> </div>
</div>
</el-card>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row style="margin-top: -18px;" class="projects">
<baseTitle title="关联项目"></baseTitle> <baseTitle title="关联项目"></baseTitle>
<el-col :span="24"> <el-col :span="24">
<el-form-item> <el-form-item>
<fvTable style="width: 100%;max-height:160px" height="160" v-if="showTable" :tableConfig="projectTable" <fvTable style="width: 100%;max-height:160px" height="160" v-if="showTable" :scrollbar-always-on="true" :tableConfig="projectTable"
:data="formData.projects" :isSettingCol="false" :pagination="false"> :data="formData.projects" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/> <el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
@@ -41,10 +50,12 @@
</fvTable> </fvTable>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row style="margin-top: -18px;" class="projects">
<baseTitle title="附件文件"></baseTitle> <baseTitle title="附件文件"></baseTitle>
<el-col :span="24"> <el-col :span="24">
<el-form-item> <el-form-item>
<fvTable style="width: 100%;max-height: 160px;" height="160" v-if="showTable" :tableConfig="fileTable" <fvTable style="width: 100%;max-height: 160px;" height="160" v-if="showTable":scrollbar-always-on="true" :tableConfig="fileTable"
:data="formData.files" :isSettingCol="false" :pagination="false"> :data="formData.files" :isSettingCol="false" :pagination="false">
<template #empty> <template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/> <el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
@@ -123,12 +134,15 @@ const projectTable = reactive({
prop: 'projectName', prop: 'projectName',
label: '项目名称', label: '项目名称',
align: 'center', align: 'center',
showOverflowTooltip: false,
width: 200, width: 200,
}, },
{ {
prop: 'specialFundAmount', prop: 'specialFundAmount',
label: '项目金额', label: '项目金额',
align: 'center', align: 'center',
minWidth: 120,
showOverflowTooltip: false,
currentRender:({row})=>{ currentRender:({row})=>{
return <span>{toThousands(row.specialFundAmount)}</span> return <span>{toThousands(row.specialFundAmount)}</span>
} }
@@ -137,7 +151,7 @@ const projectTable = reactive({
prop: 'startTime', prop: 'startTime',
label: '项目时间', label: '项目时间',
align: 'center', align: 'center',
width: 150, width: 180,
}, },
// { // {
// prop: 'oper', // prop: 'oper',

View File

@@ -211,7 +211,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '所属业务板块', label: '业务板块',
prop: 'businessSegment', prop: 'businessSegment',
colProps: { colProps: {
span: 24 span: 24
@@ -258,8 +258,9 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 24 span: 24
@@ -274,6 +275,22 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 24
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{ {
label: '产学研联合', label: '产学研联合',
prop: 'industryUniversityResearch', prop: 'industryUniversityResearch',
@@ -320,9 +337,27 @@ const schema = computed(() => {
span: 24 span: 24
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'specialFundAmount', prop: 'forecastSpecialFundAmount',
colProps: {
span: 24
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: { colProps: {
span: 24 span: 24
}, },
@@ -336,12 +371,36 @@ const schema = computed(() => {
</div> </div>
) )
}, },
{
label: '是否在预算内',
prop: 'isWithinBudget',
colProps: {
span: 24
},
component: () => (
<div>
{
baseFormData.value?.isWithinBudget!=null ? baseFormData.value?.isWithinBudget?
<span>{'预算内'}</span>
: <span>{'预算外'}</span>:'--'
}
</div>
)
},
{ {
label: '部门分管领导', label: '部门分管领导',
prop: 'optionalChargeLeadership', prop: 'optionalChargeLeadership',
colProps: { colProps: {
span: 24 span: 24
} }
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 24
}
} }
] ]
}) })
@@ -579,6 +638,9 @@ watchEffect(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-step__title){
font-size: 14px;
}
.steps-box { .steps-box {
padding: 10px 0; padding: 10px 0;
} }

View File

@@ -4,12 +4,7 @@
<baseTitle title="预期知识产权"></baseTitle> <baseTitle title="预期知识产权"></baseTitle>
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px"> <el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="预期成果形式" prop="resultForm"> <el-form-item label="知识产权归属" prop="intellectualProperty">
<span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="知识产权状况" prop="intellectualProperty">
<span>{{ <span>{{
filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty) filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty)
}}</span> }}</span>
@@ -17,31 +12,77 @@
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="发明专利(项)" prop="inventionPatent"> <el-form-item label="预估专利(项)" prop="newPatent">
<span>{{ localFormData.inventionPatent }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="新型专利(项)" prop="newPatent">
<span>{{ localFormData.newPatent }}</span> <span>{{ localFormData.newPatent }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="软件著作权(项)" prop="softwareCopyright"> <el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
<span>{{ localFormData.softwareCopyright }}</span> <span>{{ localFormData.softwareCopyright }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="著作权(项)" prop="copyright"> <el-form-item label="预估技术标准(项)" prop="technicalNorms">
<span>{{ localFormData.copyright }}</span> <span>{{ localFormData.technicalNorms }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="其他(项)" prop="other">
<span>{{ localFormData.other }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<el-form-item label="预估新产品(项)" prop="newProduct">
<span>{{ localFormData.newProduct }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估新工艺(项)" prop="newProcess">
<span>{{ localFormData.newProcess }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估新装置(项)" prop="newDevice">
<span>{{ localFormData.newDevice }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估新材料(项)" prop="newMaterials">
<span>{{ localFormData.newMaterials }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
<span>{{ localFormData.computerSoftware }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估论文论著(项)" prop="thesis">
<span>{{ localFormData.thesis }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估研究报告(项)" prop="researchReport">
<span>{{ localFormData.researchReport }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估商标(项)" prop="trademark">
<span>{{ localFormData.trademark }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预估其他(项)" prop="other">
<span style="white-space: pre-wrap">{{ localFormData.other }}</span>
</el-form-item>
</el-col>
</el-row> </el-row>
<baseTitle title="项目描述"></baseTitle> <baseTitle title="项目描述"></baseTitle>
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px;"> <el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px;">
@@ -74,7 +115,7 @@
<!-- </el-col>--> <!-- </el-col>-->
<el-col :span="24"> <el-col :span="24">
<file-component <file-component
tag="需求上报" :fileNameTableWidth="300" :fullscreen="true" tag="需求上报" :fileNameTableWidth="150" :fullscreen="true"
v-model:value="localFormData.fileList" v-model:value="localFormData.fileList"
:processViewer="processViewer" :processViewer="processViewer"
:file-list-show="fileListShow" :file-list-show="fileListShow"
@@ -94,7 +135,7 @@
</el-form-item> </el-form-item>
</div> </div>
<div v-if="data.state==='5'" style="margin-bottom: 15px"> <div v-if="data.state==='5'" style="margin-bottom: 15px">
<baseTitle title="前置流程"></baseTitle> <baseTitle title="前置流程" v-if="localFormData.preProcess"></baseTitle>
<div style="display: flex;align-items: center;flex-wrap: wrap;"> <div style="display: flex;align-items: center;flex-wrap: wrap;">
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId"> <div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
<a :href="item.baseUrl" target="_blank" <a :href="item.baseUrl" target="_blank"
@@ -105,8 +146,8 @@
</div> </div>
</div> </div>
<div v-perm="['annual:plan:approve']" v-if="data.state==='4'"> <div v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<baseTitle title="前置流程"></baseTitle> <!-- <baseTitle title="前置流程"></baseTitle>-->
<select-pre-process :formData="localFormData"/> <!-- <select-pre-process :formData="localFormData"/>-->
<baseTitle title="审核意见"></baseTitle> <baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value"> <el-form-item prop="_value">
<el-input <el-input
@@ -239,6 +280,14 @@ const handleRejectPlan = async () => {
}) })
} }
const handleAgreePlan = async () => { const handleAgreePlan = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = { const params = {
auditOpinion: _value.value, auditOpinion: _value.value,
projectId: parseInt(route.query.projectId), projectId: parseInt(route.query.projectId),

View File

@@ -26,7 +26,7 @@
:preProcessShow="preProcessShow" :preProcessShow="preProcessShow"
v-model:value="auditOpinion"/> v-model:value="auditOpinion"/>
<div v-if="showActive == '30'"> <div v-if="showActive == '30'">
<project-attachment fileNameTableWidth="300" :isLineBtn="true"/> <project-attachment fileNameTableWidth="200" :isLineBtn="true"/>
</div> </div>
<ApprovalDetail type="execute" <ApprovalDetail type="execute"
v-if="showActive == '40'" v-if="showActive == '40'"

View File

@@ -167,7 +167,7 @@ const schema = computed(() => {
) )
}, },
{ {
label: '经费预算(元)', label: '预估经费预算(元)',
prop: 'economicEstimate', prop: 'economicEstimate',
colProps: { colProps: {
span: 24 span: 24
@@ -222,7 +222,7 @@ const schema = computed(() => {
} }
}, },
{ {
label: '申请总部专项资金(元)', label: '预估专项资金(元)',
prop: 'specialFundAmount', prop: 'specialFundAmount',
colProps: { colProps: {
span: 24 span: 24

View File

@@ -1,6 +1,6 @@
<template> <template>
<fvSearchForm :searchConfig="researchFundSearchConfig" @search="searchResearchFund" <fvSearchForm :searchConfig="researchFundSearchConfig" @search="searchResearchFund"
style="margin-left: 16px"></fvSearchForm> ></fvSearchForm>
<fvTable ref="tableIns" :tableConfig="researchFundTableConfig" @headBtnClick="headBtnClick"> <fvTable ref="tableIns" :tableConfig="researchFundTableConfig" @headBtnClick="headBtnClick">
<template #empty> <template #empty>
<el-empty description="暂无数据"/> <el-empty description="暂无数据"/>
@@ -30,7 +30,7 @@ const researchFundSearchConfig = ref([
} }
}, },
{ {
label: '研发资金金额', label: '研发资金金额(元)',
prop: 'rdAmount', prop: 'rdAmount',
component: 'el-input', component: 'el-input',
props: { props: {
@@ -74,7 +74,7 @@ const researchFundTableConfig = reactive({
}, },
{ {
prop: 'rdAmount', prop: 'rdAmount',
label: '研发资金金额', label: '研发资金金额(元)',
align: 'center', align: 'center',
currentRender:({row})=>{ currentRender:({row})=>{
return <span>{toThousands(row.rdAmount)}</span> return <span>{toThousands(row.rdAmount)}</span>

View File

@@ -3,7 +3,7 @@
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick" <fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick"
@selectionChange="selectionChange"></fvTable> @selectionChange="selectionChange"></fvTable>
<user-picker :multiple="true" ref="whiteUserRef" title="请选择人员" <user-picker :multiple="true" ref="whiteUserRef" title="请选择人员"
v-model:value="whiteUserList" @ok="whiteUserPickerOk" @cancelOrClear="whiteUserPickerOk"/> v-model:value="whiteUserList" @ok="whiteUserPickerOk"/>
</template> </template>

View File

@@ -34,7 +34,6 @@
<script setup> <script setup>
import {defineProps,defineEmits} from 'vue' import {defineProps,defineEmits} from 'vue'
// import {timeLength} from '../utils/date' // import {timeLength} from '../utils/date'

View File

@@ -1,5 +1,4 @@
//时间转换为String类型 //时间转换为String类型
const moment = require("moment");
function simpleDateFormat(pattern) { function simpleDateFormat(pattern) {
var fmt = new Object(); var fmt = new Object();
@@ -83,36 +82,36 @@ function consumingTime(dateBegin, dateEnd) {
return dayDiff + "天 " + hours + "小时 " + minutes + " 分钟" + seconds + " 秒"; return dayDiff + "天 " + hours + "小时 " + minutes + " 分钟" + seconds + " 秒";
} }
export function timeLength(start, dateEnd) { // export function timeLength(start, dateEnd) {
// //如果时间格式是正确的,那下面这一步转化时间格式就可以不用了 // // //如果时间格式是正确的,那下面这一步转化时间格式就可以不用了
let mstart = moment(start); // let mstart = moment(start);
let mend = moment(dateEnd); // let mend = moment(dateEnd);
let years = mend.diff(start, "years"); // let years = mend.diff(start, "years");
let months = mend.diff(start, "months"); // let months = mend.diff(start, "months");
let days = mend.diff(start, "days"); // let days = mend.diff(start, "days");
let hours = mend.diff(start, "hours"); // let hours = mend.diff(start, "hours");
let minutes = mend.diff(start, "minutes"); // let minutes = mend.diff(start, "minutes");
minutes = minutes % 60; // minutes = minutes % 60;
hours = hours % 24; // hours = hours % 24;
months = months % 12; // months = months % 12;
//因为每月天不固定,所以天要特殊动态处理 // //因为每月天不固定,所以天要特殊动态处理
if (mstart.date() < mend.date()) { // if (mstart.date() < mend.date()) {
days = mend.date() - mstart.date(); // days = mend.date() - mstart.date();
if (minutes > 0 || hours > 0) { // if (minutes > 0 || hours > 0) {
days--; // days--;
} // }
} // }
//处理超过俩月且天超过31 // //处理超过俩月且天超过31
if (days > 31 && mend.month() - mstart.month() >= 2) { // if (days > 31 && mend.month() - mstart.month() >= 2) {
//将日期推至上月求差 // //将日期推至上月求差
days = mend.diff(mstart.add(mend.month() - mstart.month() - 1, "month"), "days"); // days = mend.diff(mstart.add(mend.month() - mstart.month() - 1, "month"), "days");
} // }
return `${years > 0 ? years + "年 " : " "}` + `${months > 0 ? months + "个月 " : " "}` + `${days > 0 ? days + "天 " : " "}` // return `${years > 0 ? years + "年 " : " "}` + `${months > 0 ? months + "个月 " : " "}` + `${days > 0 ? days + "天 " : " "}`
+ `${hours > 0 ? hours + "小时 " : " "}` + `${minutes > 0 ? minutes + "分钟 " : " "}`; // + `${hours > 0 ? hours + "小时 " : " "}` + `${minutes > 0 ? minutes + "分钟 " : " "}`;
} // }
module.exports = { module.exports = {
formatToYYYYMMDD: simpleDateFormatByMoreLine, formatToYYYYMMDD: simpleDateFormatByMoreLine,
consumingTime: consumingTime, consumingTime: consumingTime,
timeLength: timeLength // timeLength: timeLength
} }

View File

@@ -68,7 +68,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<paging :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :page-sizes="[10, 20, 30, 40,50]" <paging :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :page-sizes="[10, 20, 30, 40,50]"
:total="total" @changeSize="handleSizeChange" @goPage="handleCurrentChange"/> :total="total" @changeSize="handleSizeChange" @goPage="handleCurrentChange"/>
<el-dialog v-model="isVisited" title="历史" width="800px"> <el-dialog v-model="isVisited" title="历史" width="800px">
<div class="table"> <div class="table">
@@ -118,10 +118,12 @@ import {
deleteHistoryVersion deleteHistoryVersion
} from "@/api/workflow/process-definition.js"; } from "@/api/workflow/process-definition.js";
import {Search, Refresh, Delete, Plus, Edit, Download, Document} from '@element-plus/icons-vue' import {Search, Refresh, Delete, Plus, Edit, Download, Document} from '@element-plus/icons-vue'
import {ElMessage, ElMessageBox} from "element-plus"; import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
import {useCacheStore} from '@/stores/cache.js' import {useCacheStore} from '@/stores/cache.js'
import PointTag from "@/components/PointTag.vue"; import PointTag from "@/components/PointTag.vue";
import Paging from "@/components/pagination/index.vue"; import Paging from "@/components/pagination/index.vue";
import UserPicker from "./common/UserPicker.vue";
import {applyCcSend} from "@/api/expense-manage";
const dictStore = useCacheStore() const dictStore = useCacheStore()
dictStore.setCacheKey(['normal_disable']) dictStore.setCacheKey(['normal_disable'])
@@ -144,6 +146,7 @@ const loading = ref(true)
const list = ref([]) const list = ref([])
const queryForm = ref() const queryForm = ref()
const total = ref() const total = ref()
const chooseRow = ref({})
const selectDefinition = ref(null) const selectDefinition = ref(null)
const historyVersionList = ref([]) const historyVersionList = ref([])
const singleTable = ref() const singleTable = ref()
@@ -151,6 +154,8 @@ const isVisited = ref(false)
onActivated(() => { onActivated(() => {
getList() getList()
}) })
//重置搜索 //重置搜索
const handleReset = () => { const handleReset = () => {
queryForm.value.resetFields() queryForm.value.resetFields()
@@ -182,7 +187,6 @@ const handleAdd = () => {
path: '/workflow/process/add', path: '/workflow/process/add',
}) })
} }
const handleEdit = (deploymentId) => { const handleEdit = (deploymentId) => {
router.push({ router.push({
path: `/workflow/process/edit/${deploymentId}`, path: `/workflow/process/edit/${deploymentId}`,

View File

@@ -10,6 +10,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
import Inspect from 'vite-plugin-inspect' import Inspect from 'vite-plugin-inspect'
import viteSvgIcons from 'vite-plugin-svg-icons' import viteSvgIcons from 'vite-plugin-svg-icons'
import path from 'path' import path from 'path'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
@@ -53,6 +54,7 @@ export default defineConfig({
'@': fileURLToPath(new URL('./src', import.meta.url)) '@': fileURLToPath(new URL('./src', import.meta.url))
} }
}, },
build: { build: {
minify: 'esbuild', minify: 'esbuild',
terserOptions: { terserOptions: {
@@ -69,22 +71,22 @@ export default defineConfig({
open: true, open: true,
proxy: { proxy: {
// '/api/workflow': { // '/api/workflow': {
// // target: 'http://frp.feashow.cn:31800/', // target: 'http://frp.feashow.cn:31800/',
// target: 'http://clay.frp.feashow.cn/', // // target: 'http://clay.frp.feashow.cn/',
// // target: 'http://192.168.31.175:8000', // // target: 'http://192.168.31.175:8000',
// changeOrigin: true, // changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '') // rewrite: (path) => path.replace(/^\/api/, '')
// }, // },
// '/api/admin': { // '/api/admin': {
// // target: 'http://frp.feashow.cn:31800/', // target: 'http://frp.feashow.cn:31800/',
// target: 'http://clay.frp.feashow.cn/', // // target: 'http://clay.frp.feashow.cn/',
// // target: 'http://192.168.31.175:8000', // // target: 'http://192.168.31.175:8000',
// changeOrigin: true, // changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '') // rewrite: (path) => path.replace(/^\/api/, '')
// }, // },
// '/api/auth': { // '/api/auth': {
// // target: 'http://frp.feashow.cn:31800/', // target: 'http://frp.feashow.cn:31800/',
// target: 'http://clay.frp.feashow.cn/', // // target: 'http://clay.frp.feashow.cn/',
// // target: 'http://192.168.31.175:8000', // // target: 'http://192.168.31.175:8000',
// changeOrigin: true, // changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '') // rewrite: (path) => path.replace(/^\/api/, '')
@@ -103,5 +105,6 @@ export default defineConfig({
// changeOrigin: true, // changeOrigin: true,
// } // }
} }
} },
}) })