Compare commits

..

145 Commits

Author SHA1 Message Date
lcw
2ea84f248c lcw 2026-01-06 22:09:05 +08:00
lcw
953cb9943d lcw 2025-12-27 22:09:13 +08:00
lcw
3fb06e3847 lcw 2025-12-27 11:10:31 +08:00
lcw
596c9f99e4 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-26 09:39:28 +08:00
lcw
e59b401828 lcw 2025-12-26 09:39:22 +08:00
669c8cb3b5 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-25 11:07:09 +08:00
22c3e0253b 更新 2025-12-25 11:07:03 +08:00
lcw
6999c36c3a lcw 2025-12-25 10:38:17 +08:00
lcw
709ce4a1e9 lcw 2025-12-25 10:35:00 +08:00
23cc528707 更新 2025-12-25 09:45:07 +08:00
bc92cfa735 更新 2025-12-25 09:37:17 +08:00
1a7b27209f 更新 2025-12-24 09:27:05 +08:00
5ae5dc7224 更新 2025-12-23 18:58:47 +08:00
039e0ce421 提交 2025-12-23 11:42:42 +08:00
369fb4c00a 提交 2025-12-22 17:22:18 +08:00
ab9249479c 提交 2025-12-22 16:04:33 +08:00
c18dde1b43 大屏调整 2025-12-20 16:48:23 +08:00
d3110fb7b9 调整大屏跳转 2025-12-20 15:45:11 +08:00
a9959ce537 调整数据监测 2025-12-20 15:32:44 +08:00
d0b7e6c768 feat: 样式菜单更新 2025-12-19 15:54:20 +08:00
56000fdbdf feat: 文字调整 2025-12-19 14:12:57 +08:00
32d5e53b59 feat:战略研判修改 2025-12-19 14:11:16 +08:00
f6ce1455da feat: 增加一个blur事件 2025-12-19 13:21:56 +08:00
f9af7e060d feaet: 调整报告接口 2025-12-19 13:21:27 +08:00
198ee8f734 更新 2025-12-19 13:15:06 +08:00
97f7736081 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-19 11:41:50 +08:00
f0910016ae 更新 2025-12-19 11:41:05 +08:00
fb9d399598 feat: 接口调整 2025-12-19 11:20:19 +08:00
7e61b43e5c feat: 战术研判-增加创建报告 2025-12-19 10:33:26 +08:00
05524353f4 feat:增加自建研判 2025-12-19 10:07:17 +08:00
c1fc037cdf feat:战术研判更新一次 2025-12-19 10:07:00 +08:00
9c179c71ca feat: jsdoc微调 2025-12-18 21:38:50 +08:00
26dfe3d6c0 feat: 更新 2025-12-18 21:29:33 +08:00
463051f109 feat: 更新 2025-12-18 21:26:39 +08:00
cfd6b5b140 feat: 按钮权限 2025-12-18 20:36:23 +08:00
901d7bab71 feat: 增加处置下发 2025-12-18 20:30:35 +08:00
3b8697e744 feat: 避免卡住 2025-12-18 20:14:32 +08:00
2ba8ac607e feat: 优化跳转 2025-12-18 20:08:37 +08:00
186d1e0d53 feat: 大屏-战术,战略研判对接 2025-12-18 19:58:12 +08:00
571518f1e5 feat:增加查看反馈 2025-12-18 19:33:13 +08:00
cc2bf59a19 feat:增加反馈内容 2025-12-18 19:20:57 +08:00
6ddecd72af 更新 2025-12-18 18:46:37 +08:00
34a1e4aefb Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 18:44:57 +08:00
244fcc1703 更新 2025-12-18 18:44:20 +08:00
bdde65f1c4 feat: 接口跟新 2025-12-18 18:26:58 +08:00
693695c178 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 18:24:16 +08:00
2241222bb7 新增预警积分排名 2025-12-18 18:24:09 +08:00
a21192c47a feat: 仅格式,方便格式缩进 2025-12-18 18:10:01 +08:00
0c0c35316d feat:更新列表 2025-12-18 17:50:58 +08:00
504f3a328c feat: 接口更新 2025-12-18 17:42:33 +08:00
b18d8e9f25 feat: 更新一次 2025-12-18 17:41:40 +08:00
e581d9d5b3 feat:线索socket地址修改 2025-12-18 17:36:51 +08:00
5a42ab322f feat: 备用 2025-12-18 17:18:53 +08:00
c4f051d82c feat: 更新查询条件 2025-12-18 16:34:49 +08:00
75c34d983f 更新 2025-12-18 15:45:59 +08:00
9319ba65a7 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 15:39:39 +08:00
3426b66dd5 新增本地预警 2025-12-18 15:39:31 +08:00
1b8655d2ee feat: 增加菜单【转会商列表】,【补充/续报列表】,【积分列表】 2025-12-18 15:10:13 +08:00
2bcab2abd6 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 14:37:24 +08:00
783b01a514 更新 2025-12-18 14:36:07 +08:00
7307b6c5da feat: 文字调整 2025-12-18 11:58:26 +08:00
ca8c391d9f feat: 线索编号注释 2025-12-18 11:57:20 +08:00
c9c1bc1b2e Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 11:56:15 +08:00
060f2bedaa 更新 2025-12-18 11:55:54 +08:00
6ad95dcd36 feat: 加回关注部门 2025-12-18 11:32:49 +08:00
33a127ec16 feat: 移除无用,修改菜单名 2025-12-18 11:07:35 +08:00
a83e15ecbd feat: 信息采集-创建改打标签 2025-12-18 10:41:07 +08:00
5c4ca373e3 feat: 权限备用 2025-12-18 10:40:38 +08:00
9da3ae7e3c 更新 2025-12-18 10:24:21 +08:00
9f6f712e3d Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-18 10:23:25 +08:00
b754de7135 feat:增加一个权限判断 2025-12-18 10:23:05 +08:00
7917b9cd44 更新预警 2025-12-18 10:22:42 +08:00
dc5e5e5f43 feat: 内部列表和共享列表只有补充信息和详情 2025-12-18 09:59:34 +08:00
7750f239ec feat: 增加转会商续报功能 2025-12-17 21:20:41 +08:00
45a1a1ea17 feat: 接口更新 2025-12-17 20:07:03 +08:00
963cf54ec1 更新 2025-12-17 19:20:27 +08:00
791fd08277 更新 2025-12-17 19:11:51 +08:00
6f51e0e0d9 更新 2025-12-17 19:04:41 +08:00
299f6b8f02 更新 2025-12-17 19:03:38 +08:00
561aec8a90 更新 2025-12-17 18:53:27 +08:00
acdf6abdea Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-17 18:47:10 +08:00
7853672770 更新页面 2025-12-17 18:46:32 +08:00
ff8b4e5cba feat: 修改按钮权限 2025-12-17 17:32:59 +08:00
c0237acfff feat: 菜单调整 2025-12-17 16:56:48 +08:00
lcw
9fc4d227b3 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-17 16:28:08 +08:00
lcw
6a80bddff3 lcw 2025-12-17 16:27:59 +08:00
032b35ec9e feat: 更细 2025-12-17 11:08:50 +08:00
a965b65dfc feat: 打包更细 2025-12-17 11:07:52 +08:00
9a34edb678 feat: 弄成中文的 2025-12-17 10:46:35 +08:00
5e9248a63f feat: 增加红色名字 2025-12-17 10:15:10 +08:00
69ddc7c007 feat: 增加导出功能 2025-12-16 21:28:17 +08:00
941bd6fe57 feat: 工具更细 2025-12-16 20:41:24 +08:00
d2e394a1bb 调整 2025-12-16 16:44:58 +08:00
82058b9de7 调整菜单 2025-12-16 12:15:09 +08:00
89751eb908 feat: 解决可能出错的地方 2025-12-16 09:57:07 +08:00
bb870644f3 feat: 增加详情 2025-12-15 22:20:23 +08:00
efbc27b7d5 feat: 增加详情 2025-12-15 22:16:02 +08:00
3d83be0c17 feat: 增加详情 2025-12-15 22:04:49 +08:00
ae4db70eed feat: 增加列详情 2025-12-15 21:54:51 +08:00
68f8363a6b feat: 调整接口和内容的问题 2025-12-15 21:44:13 +08:00
cd06aaf1be feat: 注销基础管理 2025-12-15 11:04:36 +08:00
476f711ac8 feat: 菜单备用 2025-12-13 20:35:58 +08:00
6c3134656d feat: 更细一次 2025-12-13 20:34:12 +08:00
5e0c88b70e feat: 菜单更细 2025-12-13 19:08:20 +08:00
185eb452cc feat: 颜色调整 2025-12-13 17:24:54 +08:00
cf431a19b1 feat: 置顶增加精品2字 2025-12-13 17:21:40 +08:00
1c0976eb88 feat: 格式化下 2025-12-13 17:18:20 +08:00
5ab71f95b0 feat:情报论坛-市情报指有置顶功能 2025-12-13 17:17:00 +08:00
93c9715e78 feat:搜索条件修改 2025-12-13 16:26:30 +08:00
cbe9fc9ead feat: 菜单备用 2025-12-13 11:04:17 +08:00
e26bacab0a feat:更细一次 2025-12-12 21:08:46 +08:00
8b56e84690 feat:增加一个车牌号搜索 2025-12-12 20:28:00 +08:00
dcab225362 feat: 再次调整 2025-12-12 19:41:31 +08:00
5fef40a152 feat: 接口调整 2025-12-12 19:39:27 +08:00
f1a1be33aa feat: 接口参数调整 2025-12-12 19:37:21 +08:00
fab2ff778a feat: 类型支持 2025-12-12 19:33:20 +08:00
2b96cd8a53 feat: 增加类型 2025-12-12 19:33:10 +08:00
18249d23a0 feat: 警告移除 2025-12-12 19:32:53 +08:00
29acd58a3d Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-12 18:17:32 +08:00
e73067aa9a 更新 2025-12-12 18:16:55 +08:00
55c066dadb feat: 搜索条件更新 2025-12-12 18:08:51 +08:00
b1e988080a feat: 添加菜单【人像预警】,车辆预警 2025-12-12 17:59:07 +08:00
48f857284e Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-12 17:31:01 +08:00
9699e6ee57 更新 2025-12-12 17:30:54 +08:00
b3bb67c9d2 feat: 警情管理 菜单调整 2025-12-12 16:53:47 +08:00
ef30bcd03c feat: 全息跳转不了的问题调整 2025-12-12 16:53:24 +08:00
ac0d801efb feat: 注释console 2025-12-12 16:36:26 +08:00
3ad392ef2e feat: console注释掉,信息太多了 2025-12-12 16:35:13 +08:00
b1f9d3f4f7 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-12 16:29:42 +08:00
91fdf6dbe5 更新 2025-12-12 16:29:36 +08:00
9ddd9c2326 feat: 优化列表 2025-12-12 16:27:30 +08:00
0ab9216ed8 feat: 情报来源类型-增加表格。优秀信息员,优秀研判的列表 2025-12-12 16:25:24 +08:00
0ec9ead6d3 feat: 更新列表 2025-12-12 16:04:04 +08:00
b904aaba97 feat: 更新package.json 2025-12-12 15:56:31 +08:00
0e2f4806f5 更新 2025-12-12 15:52:45 +08:00
fe232cd046 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-12-12 15:20:17 +08:00
d85214bc62 更新页面 2025-12-12 15:19:45 +08:00
2cd2bedb3c feat: 解决没数据报错的问题 2025-12-12 14:45:18 +08:00
a5e8346a32 feat: 全息档案跳转-地址修改 2025-12-12 12:46:11 +08:00
ffdb0661e2 feat: 修改颜色 2025-12-12 10:32:19 +08:00
bdbde8f267 feat: 打包bat 2025-12-12 10:20:08 +08:00
3fbb4f9d4b feat: 情报流转-解决报错问题 2025-12-12 10:06:08 +08:00
6c08a68d4c feat: 移除pdf下载功能 2025-12-12 09:47:20 +08:00
7062604ba3 更新 2025-12-12 09:05:19 +08:00
383e88e5d2 更新 2025-12-12 09:04:26 +08:00
204 changed files with 16147 additions and 4502 deletions

0
gsxt.zip Normal file
View File

Binary file not shown.

563
package-lock.json generated
View File

@ -298,10 +298,9 @@
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
}, },
"@babel/helper-validator-identifier": { "@babel/helper-validator-identifier": {
"version": "7.18.6", "version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="
"dev": true
}, },
"@babel/helper-validator-option": { "@babel/helper-validator-option": {
"version": "7.18.6", "version": "7.18.6",
@ -344,9 +343,12 @@
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.18.9", "version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==" "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"requires": {
"@babel/types": "^7.28.5"
}
}, },
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.18.6", "version": "7.18.6",
@ -1120,12 +1122,9 @@
} }
}, },
"@babel/runtime": { "@babel/runtime": {
"version": "7.18.9", "version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.4.tgz",
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="
"requires": {
"regenerator-runtime": "^0.13.4"
}
}, },
"@babel/template": { "@babel/template": {
"version": "7.18.6", "version": "7.18.6",
@ -1157,13 +1156,12 @@
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.18.9", "version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.5.tgz",
"integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"dev": true,
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.18.6", "@babel/helper-string-parser": "^7.27.1",
"to-fast-properties": "^2.0.0" "@babel/helper-validator-identifier": "^7.28.5"
} }
}, },
"@ctrl/tinycolor": { "@ctrl/tinycolor": {
@ -1359,10 +1357,9 @@
"dev": true "dev": true
}, },
"@jridgewell/sourcemap-codec": { "@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
"dev": true
}, },
"@jridgewell/trace-mapping": { "@jridgewell/trace-mapping": {
"version": "0.3.14", "version": "0.3.14",
@ -1745,12 +1742,6 @@
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true "dev": true
}, },
"@types/raf": {
"version": "3.4.3",
"resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz",
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
"optional": true
},
"@types/range-parser": { "@types/range-parser": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
@ -2190,51 +2181,6 @@
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true "dev": true
}, },
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"ssri": { "ssri": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
@ -2243,28 +2189,6 @@
"requires": { "requires": {
"minipass": "^3.1.1" "minipass": "^3.1.1"
} }
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
} }
} }
}, },
@ -2313,81 +2237,59 @@
"@babel/parser": "^7.28.0", "@babel/parser": "^7.28.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
},
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="
},
"@babel/parser": {
"version": "7.28.0",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"requires": {
"@babel/types": "^7.28.0"
}
},
"@babel/types": {
"version": "7.28.2",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"requires": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
}
},
"source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
}
} }
}, },
"@vue/compiler-core": { "@vue/compiler-core": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.18.tgz",
"integrity": "sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==", "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==",
"requires": { "requires": {
"@babel/parser": "^7.16.4", "@babel/parser": "^7.28.0",
"@vue/shared": "3.2.37", "@vue/shared": "3.5.18",
"entities": "^4.5.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"source-map": "^0.6.1" "source-map-js": "^1.2.1"
},
"dependencies": {
"entities": {
"version": "4.5.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
}
} }
}, },
"@vue/compiler-dom": { "@vue/compiler-dom": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz",
"integrity": "sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==", "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==",
"requires": { "requires": {
"@vue/compiler-core": "3.2.37", "@vue/compiler-core": "3.5.18",
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
} }
}, },
"@vue/compiler-sfc": { "@vue/compiler-sfc": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz",
"integrity": "sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==", "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==",
"requires": { "requires": {
"@babel/parser": "^7.16.4", "@babel/parser": "^7.28.0",
"@vue/compiler-core": "3.2.37", "@vue/compiler-core": "3.5.18",
"@vue/compiler-dom": "3.2.37", "@vue/compiler-dom": "3.5.18",
"@vue/compiler-ssr": "3.2.37", "@vue/compiler-ssr": "3.5.18",
"@vue/reactivity-transform": "3.2.37", "@vue/shared": "3.5.18",
"@vue/shared": "3.2.37",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.25.7", "magic-string": "^0.30.17",
"postcss": "^8.1.10", "postcss": "^8.5.6",
"source-map": "^0.6.1" "source-map-js": "^1.2.1"
} }
}, },
"@vue/compiler-ssr": { "@vue/compiler-ssr": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz",
"integrity": "sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==", "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==",
"requires": { "requires": {
"@vue/compiler-dom": "3.2.37", "@vue/compiler-dom": "3.5.18",
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
} }
}, },
"@vue/component-compiler-utils": { "@vue/component-compiler-utils": {
@ -2499,57 +2401,46 @@
"dev": true "dev": true
}, },
"@vue/reactivity": { "@vue/reactivity": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.18.tgz",
"integrity": "sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==", "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==",
"requires": { "requires": {
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
}
},
"@vue/reactivity-transform": {
"version": "3.2.37",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz",
"integrity": "sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/compiler-core": "3.2.37",
"@vue/shared": "3.2.37",
"estree-walker": "^2.0.2",
"magic-string": "^0.25.7"
} }
}, },
"@vue/runtime-core": { "@vue/runtime-core": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.18.tgz",
"integrity": "sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==", "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==",
"requires": { "requires": {
"@vue/reactivity": "3.2.37", "@vue/reactivity": "3.5.18",
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
} }
}, },
"@vue/runtime-dom": { "@vue/runtime-dom": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz",
"integrity": "sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==", "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==",
"requires": { "requires": {
"@vue/runtime-core": "3.2.37", "@vue/reactivity": "3.5.18",
"@vue/shared": "3.2.37", "@vue/runtime-core": "3.5.18",
"csstype": "^2.6.8" "@vue/shared": "3.5.18",
"csstype": "^3.1.3"
} }
}, },
"@vue/server-renderer": { "@vue/server-renderer": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.18.tgz",
"integrity": "sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==", "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==",
"requires": { "requires": {
"@vue/compiler-ssr": "3.2.37", "@vue/compiler-ssr": "3.5.18",
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
} }
}, },
"@vue/shared": { "@vue/shared": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.18.tgz",
"integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA=="
}, },
"@vue/web-component-wrapper": { "@vue/web-component-wrapper": {
"version": "1.3.0", "version": "1.3.0",
@ -3212,7 +3103,8 @@
"atob": { "atob": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"dev": true
}, },
"autoprefixer": { "autoprefixer": {
"version": "9.8.8", "version": "9.8.8",
@ -3399,11 +3291,6 @@
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
"dev": true "dev": true
}, },
"base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
},
"base64-js": { "base64-js": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -3717,11 +3604,6 @@
"update-browserslist-db": "^1.0.5" "update-browserslist-db": "^1.0.5"
} }
}, },
"btoa": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/btoa/-/btoa-1.2.1.tgz",
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="
},
"buffer": { "buffer": {
"version": "4.9.2", "version": "4.9.2",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
@ -3936,22 +3818,6 @@
"integrity": "sha512-pJYArGHrPp3TUqQzFYRmP/lwJlj8RCbVe3Gd3eJQkAV8SAC6b19XS9BjMvRdvaS8RMkaTN8ZhoHP6S1y8zzwEQ==", "integrity": "sha512-pJYArGHrPp3TUqQzFYRmP/lwJlj8RCbVe3Gd3eJQkAV8SAC6b19XS9BjMvRdvaS8RMkaTN8ZhoHP6S1y8zzwEQ==",
"dev": true "dev": true
}, },
"canvg": {
"version": "3.0.11",
"resolved": "https://registry.npmmirror.com/canvg/-/canvg-3.0.11.tgz",
"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
"optional": true,
"requires": {
"@babel/runtime": "^7.12.5",
"@types/raf": "^3.4.0",
"core-js": "^3.8.3",
"raf": "^3.4.1",
"regenerator-runtime": "^0.13.7",
"rgbcolor": "^1.0.1",
"stackblur-canvas": "^2.0.0",
"svg-pathdata": "^6.0.3"
}
},
"case-sensitive-paths-webpack-plugin": { "case-sensitive-paths-webpack-plugin": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@ -5011,14 +4877,6 @@
} }
} }
}, },
"css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"requires": {
"utrie": "^1.0.2"
}
},
"css-loader": { "css-loader": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
@ -5288,9 +5146,9 @@
} }
}, },
"csstype": { "csstype": {
"version": "2.6.20", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
}, },
"cyclist": { "cyclist": {
"version": "1.0.1", "version": "1.0.1",
@ -6102,11 +5960,6 @@
"es6-symbol": "^3.1.1" "es6-symbol": "^3.1.1"
} }
}, },
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"es6-symbol": { "es6-symbol": {
"version": "3.1.4", "version": "3.1.4",
"resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz", "resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz",
@ -7054,11 +6907,6 @@
"websocket-driver": ">=0.5.1" "websocket-driver": ">=0.5.1"
} }
}, },
"fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"figgy-pudding": { "figgy-pudding": {
"version": "3.5.2", "version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@ -7870,25 +7718,6 @@
} }
} }
}, },
"html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"requires": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
}
},
"html2pdf.js": {
"version": "0.10.1",
"resolved": "https://registry.npmmirror.com/html2pdf.js/-/html2pdf.js-0.10.1.tgz",
"integrity": "sha512-3onwwhOWsZfNjIZwV6YIJ6FVhXk+X9YxHSqzeS6hup+1dGi2DHI+zZYUJ+iFnvtaYcjlhyrILL1fvRCUOa8Fcg==",
"requires": {
"es6-promise": "^4.2.5",
"html2canvas": "^1.0.0",
"jspdf": "^2.3.1"
}
},
"htmlparser2": { "htmlparser2": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
@ -8950,34 +8779,6 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"jspdf": {
"version": "2.5.2",
"resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.2.tgz",
"integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
"requires": {
"@babel/runtime": "^7.23.2",
"atob": "^2.1.2",
"btoa": "^1.2.1",
"canvg": "^3.0.6",
"core-js": "^3.6.0",
"dompurify": "^2.5.4",
"fflate": "^0.8.1",
"html2canvas": "^1.0.0-rc.5"
},
"dependencies": {
"@babel/runtime": {
"version": "7.28.4",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.4.tgz",
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="
},
"dompurify": {
"version": "2.5.8",
"resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.8.tgz",
"integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==",
"optional": true
}
}
},
"jsprim": { "jsprim": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
@ -9716,11 +9517,11 @@
"integrity": "sha512-3waPBiu0Zw3Uv0qtQQA0lW/dLdzSKg/6aM5FdtNrUFGsv49WxxDllCO91iB/z6xhZCKb5F14vKGiH7xE0DJRcg==" "integrity": "sha512-3waPBiu0Zw3Uv0qtQQA0lW/dLdzSKg/6aM5FdtNrUFGsv49WxxDllCO91iB/z6xhZCKb5F14vKGiH7xE0DJRcg=="
}, },
"magic-string": { "magic-string": {
"version": "0.25.9", "version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"requires": { "requires": {
"sourcemap-codec": "^1.4.8" "@jridgewell/sourcemap-codec": "^1.5.5"
} }
}, },
"make-dir": { "make-dir": {
@ -10130,9 +9931,9 @@
"optional": true "optional": true
}, },
"nanoid": { "nanoid": {
"version": "3.3.4", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
}, },
"nanomatch": { "nanomatch": {
"version": "1.2.13", "version": "1.2.13",
@ -10643,9 +10444,9 @@
"dev": true "dev": true
}, },
"pako": { "pako": {
"version": "2.0.4", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz", "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==" "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
}, },
"parallel-transform": { "parallel-transform": {
"version": "1.2.0", "version": "1.2.0",
@ -10844,12 +10645,13 @@
"performance-now": { "performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"dev": true
}, },
"picocolors": { "picocolors": {
"version": "1.0.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
}, },
"picomatch": { "picomatch": {
"version": "2.3.1", "version": "2.3.1",
@ -10952,13 +10754,13 @@
"dev": true "dev": true
}, },
"postcss": { "postcss": {
"version": "8.4.14", "version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"requires": { "requires": {
"nanoid": "^3.3.4", "nanoid": "^3.3.11",
"picocolors": "^1.0.0", "picocolors": "^1.1.1",
"source-map-js": "^1.0.2" "source-map-js": "^1.2.1"
} }
}, },
"postcss-calc": { "postcss-calc": {
@ -12464,15 +12266,6 @@
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
"integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
}, },
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"optional": true,
"requires": {
"performance-now": "^2.1.0"
}
},
"randombytes": { "randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -12900,12 +12693,6 @@
"integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==", "integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==",
"dev": true "dev": true
}, },
"rgbcolor": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
"optional": true
},
"rimraf": { "rimraf": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@ -13352,6 +13139,11 @@
} }
} }
}, },
"siriwave": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/siriwave/-/siriwave-2.3.0.tgz",
"integrity": "sha512-p/257wib0UPvbI8ZWkm5CrPNlQ9FhLoWLyA+HWLnBCYYRG9/p8UQ4J53o+oPqXaQMjII0svnno8wAgcmQYI+NA=="
},
"slash": { "slash": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
@ -13630,12 +13422,13 @@
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}, },
"source-map-js": { "source-map-js": {
"version": "1.0.2", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
}, },
"source-map-resolve": { "source-map-resolve": {
"version": "0.5.3", "version": "0.5.3",
@ -13666,11 +13459,6 @@
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"dev": true "dev": true
}, },
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"spdx-correct": { "spdx-correct": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
@ -13808,12 +13596,6 @@
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
"dev": true "dev": true
}, },
"stackblur-canvas": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
"optional": true
},
"stackframe": { "stackframe": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
@ -14316,12 +14098,6 @@
} }
} }
}, },
"svg-pathdata": {
"version": "6.0.3",
"resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"optional": true
},
"svg-sprite-loader": { "svg-sprite-loader": {
"version": "6.0.11", "version": "6.0.11",
"resolved": "https://registry.npmjs.org/svg-sprite-loader/-/svg-sprite-loader-6.0.11.tgz", "resolved": "https://registry.npmjs.org/svg-sprite-loader/-/svg-sprite-loader-6.0.11.tgz",
@ -14583,14 +14359,6 @@
"resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz", "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz",
"integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==" "integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA=="
}, },
"text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"requires": {
"utrie": "^1.0.2"
}
},
"text-table": { "text-table": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -14713,12 +14481,6 @@
"integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==",
"dev": true "dev": true
}, },
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
"dev": true
},
"to-object-path": { "to-object-path": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
@ -15220,14 +14982,6 @@
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true "dev": true
}, },
"utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"requires": {
"base64-arraybuffer": "^1.0.2"
}
},
"uuid": { "uuid": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@ -15280,15 +15034,15 @@
"dev": true "dev": true
}, },
"vue": { "vue": {
"version": "3.2.37", "version": "3.5.18",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.2.37.tgz", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.18.tgz",
"integrity": "sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==", "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==",
"requires": { "requires": {
"@vue/compiler-dom": "3.2.37", "@vue/compiler-dom": "3.5.18",
"@vue/compiler-sfc": "3.2.37", "@vue/compiler-sfc": "3.5.18",
"@vue/runtime-dom": "3.2.37", "@vue/runtime-dom": "3.5.18",
"@vue/server-renderer": "3.2.37", "@vue/server-renderer": "3.5.18",
"@vue/shared": "3.2.37" "@vue/shared": "3.5.18"
} }
}, },
"vue-cli-plugin-element-plus": { "vue-cli-plugin-element-plus": {
@ -15384,6 +15138,68 @@
} }
} }
}, },
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-router": { "vue-router": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.3.tgz", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.3.tgz",
@ -15466,7 +15282,7 @@
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==" "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A=="
}, },
"@popperjs/core": { "@popperjs/core": {
"version": "npm:@popperjs/core@2.11.7", "version": "npm:@popperjs/core@npm:@sxzz/popperjs-es@2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
}, },
@ -15513,6 +15329,13 @@
"lodash-unified": "^1.0.3", "lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0", "memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0" "normalize-wheel-es": "^1.2.0"
},
"dependencies": {
"@popperjs/core": {
"version": "npm:@sxzz/popperjs-es@2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
}
} }
}, },
"lodash-unified": { "lodash-unified": {

View File

@ -23,14 +23,13 @@
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^0.26.0", "axios": "^0.26.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"draggable-resizable-vue3": "^1.0.94-beta", "draggable-resizable-vue3": "1.0.94-beta",
"echarts": "^5.3.3", "echarts": "^5.3.3",
"echarts-gl": "^2.0.9", "echarts-gl": "^2.0.9",
"el-table-infinite-scroll": "^3.0.6", "el-table-infinite-scroll": "^3.0.6",
"element-plus": "2.0.2", "element-plus": "2.0.2",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"gifler": "^0.1.0", "gifler": "^0.1.0",
"html2pdf.js": "^0.10.1",
"image-compressor.js": "^1.1.4", "image-compressor.js": "^1.1.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lunar-javascript": "^1.7.5", "lunar-javascript": "^1.7.5",
@ -38,6 +37,7 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"ol": "^6.14.1", "ol": "^6.14.1",
"pinia": "^3.0.1", "pinia": "^3.0.1",
"siriwave": "2.3.0",
"tesseract.js": "^6.0.1", "tesseract.js": "^6.0.1",
"vue": "^3.2.8", "vue": "^3.2.8",
"vue-draggable-plus": "^0.6.0", "vue-draggable-plus": "^0.6.0",

View File

@ -150,5 +150,47 @@ v-deep .el-loading-mask {
left: -10px; left: -10px;
transform: translateY(-50%) translateX(-50%); transform: translateY(-50%) translateX(-50%);
} }
.popupCustomBox{
position: relative;
background: rgba(2, 55, 114, 0.99);
color: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
.popupCustomTitle_title{
padding: 4px;
box-sizing: border-box;
font-size: 12px;
text-transform: none;
margin-bottom: 0;
border-bottom: 1px dashed #ececec;
margin-bottom: 2px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
}
&::after{
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid rgba(2, 55, 114, 0.99);
}
.popupCustomTitle_li{
font-size: 12px;
line-height: 22px;
text-transform: none;
margin-bottom: 0;
span{
display: inline-block;
width: 45px;
text-align: center;
}
}
}
</style> </style>

View File

@ -0,0 +1,36 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
/**
* 岗哨系统-信息采集积分(分页)
* @param {Object} params - 查询参数
* @param {string} [params.xm] - 姓名
* @param {string} [params.sfzh] - 身份证号
* @param {string} [params.jflx] - 积分类型01-优秀信息员、02-优秀研判员
* @param {string} [params.jflylx] - 积分来源类型01-信息采集、02-肯定、03-转会商、04-转合成、05-转线索、06-建模型、07-战术研判、08-战略研判
* @param {number} [params.pageCurrent] - 当前页码
* @param {number} [params.pageSize] - 每页条数
* @returns {Promise<Object>} 返回分页数据对象
* @returns {Array} returns.records - 数据记录数组,每个记录包含以下字段:
* @returns {string} [returns.records[].bz] - 备注
* @returns {string} [returns.records[].hdsj] - 积分获得时间(日期时间格式)
* @returns {string} [returns.records[].id] - 主键ID
* @returns {number} [returns.records[].jf] - 积分(整数)
* @returns {string} [returns.records[].jflx] - 积分类型01-优秀信息员、02-优秀研判员
* @returns {string} [returns.records[].jflylx] - 积分来源类型04-采纳、05-退回、06-打标签、07-转合成、08-转线索、09-转会商
* @returns {string} [returns.records[].sfzh] - 身份证号
* @returns {string} [returns.records[].ssbm] - 所属部门
* @returns {string} [returns.records[].ssbmdm] - 所属部门代码
* @returns {string} [returns.records[].sssgaj] - 所属市公安局
* @returns {string} [returns.records[].sssgajdm] - 所属市公安局代码
* @returns {string} [returns.records[].ssxgaj] - 所属县公安局
* @returns {string} [returns.records[].ssxgajdm] - 所属县公安局代码
* @returns {string} [returns.records[].xm] - 姓名
* @returns {number} returns.total - 总记录数
*/
export const mjjfSelectPage = (params) => {
return request({
url: api + "/xxcj/mjjf/selectPage",
method: "get",
params
});
};

View File

@ -0,0 +1,28 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
/**
* 补充/续报列表查询接口
* @param {Object} params - 查询参数
* @param {string} [params.bcrxm] - 补充人姓名(可选)
* @param {string} [params.czlx] - 操作类型01-续报、02-补充(可选)
* @param {number} [params.pageCurrent] - 当前页码
* @param {number} [params.pageSize] - 每页条数
* @returns {Promise<Object>} 返回分页数据对象
* @returns {Array} returns.records - 数据记录数组,每个记录包含以下字段:
* @returns {string} [returns.records[].bcnr] - 补充内容
* @returns {string} [returns.records[].bcrsfzh] - 补充人身份证号
* @returns {string} [returns.records[].bcrxm] - 补充人姓名
* @returns {string} [returns.records[].bcsj] - 补充时间(日期时间格式)
* @returns {string} [returns.records[].czlx] - 操作类型01-续报、02-补充
* @returns {string} [returns.records[].id] - 主键ID
* @returns {string} [returns.records[].qbid] - 线索情报ID
* @returns {string} [returns.records[].ysnr] - 原始内容
* @returns {number} returns.total - 总记录数
*/
export const zhsSelectPage = (params) => {
return request({
url: api + "/xxcj/bc/selectPage",
method: "get",
params
});
};

View File

@ -0,0 +1,35 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
/**
* 转会商列表查询接口
* @param {Object} params - 查询参数
* @param {string} [params.xsBh] - 信息编号
* @param {string} [params.qbmc] - 情报名称
* @param {string} [params.qbly] - 情报来源,参考字典 D_GS_XS_LY
* @param {number} [params.pageCurrent] - 当前页码
* @param {number} [params.pageSize] - 每页条数
* @returns {Promise<Object>} 返回分页数据对象
* @returns {Array} returns.records - 数据记录数组,每个记录包含以下字段:
* @returns {string} [returns.records[].bz] - 备注
* @returns {string} [returns.records[].hsid] - 会商ID
* @returns {string} [returns.records[].id] - 主键ID
* @returns {string} [returns.records[].qbid] - 线索情报ID
* @returns {string} [returns.records[].qbly] - 情报来源,参考字典 D_GS_XS_LY
* @returns {string} [returns.records[].qbmc] - 情报名称
* @returns {string} [returns.records[].qbnr] - 情报内容
* @returns {string} [returns.records[].ssbm] - 所属部门
* @returns {string} [returns.records[].ssbmdm] - 所属部门代码
* @returns {string} [returns.records[].sssgaj] - 所属市公安局
* @returns {string} [returns.records[].sssgajdm] - 所属市公安局代码
* @returns {string} [returns.records[].ssxgaj] - 所属县公安局
* @returns {string} [returns.records[].ssxgajdm] - 所属县公安局代码
* @returns {string} [returns.records[].xsBh] - 信息编号
* @returns {number} returns.total - 总记录数
*/
export const zhsSelectPage = (params) => {
return request({
url: api + "/xxcj/zhs/selectPage",
method: "get",
params
});
};

View File

@ -109,4 +109,13 @@ export function upImageUploadId(data) {
}) })
} }
/** 发送指令 (网上会议室)*/
export function wshsSendFqzl(data) {
return request({
url: gsxtApi + '/wshs/sendFqzl',
method: 'post',
data
})
}

32
src/api/dataMonitor.js Normal file
View File

@ -0,0 +1,32 @@
import request from '@/utils/request'
const api = "/mosty-api/mosty-gsxt";
/**
* 数据监控相关API接口
*/
/**
* 获取数据监测统计数据
* 接口地址:api+ /gsxt/sjjc/jrsjtj
* @returns {Promise} 统计数据
*/
export function getStatisticsData() {
return request({
url: api + '/gsxt/sjjc/jrsjtj',
method: 'get'
})
}
/**
* 获取数据接入状态列表
* 接口地址:api+ /gsxt/sjjc/selectList
* @param {string} jklx 监控类型01 公安内网数据、02 政务数据、03 社会数据、04 非结构化数据
* @returns {Promise} 监控数据列表
*/
export function getMonitorList(params) {
return request({
url: api + '/gsxt/sjjc/selectList',
method: 'get',
params: params
})
}

View File

@ -0,0 +1,53 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-websocket";
/**
* 获取在线用户数
* @param {Object} params - 查询参数
* @returns {Promise<Array<SysUser>>} 返回在线用户数组
*
* @typedef {Object} SysUser 在线用户对象
* @property {string} [avatar] - 头像
* @property {string} [beginTime] - 用户有效开始时间,默认为当前日期(用户可改)
* @property {string} [birthday] - 出生日期
* @property {string} [bz] - 备注
* @property {string} [email] - 用户邮箱
* @property {string} [endTime] - 用户有效结束时间,默认空
* @property {number} [id] - 用户ID
* @property {string} [idEntityCard] - 身份证号
* @property {string} [inDustRialId] - 行业号码(如:警号)
* @property {string} [isVirtualUser] - 是否虚拟用户1、是 2、不是
* @property {string} [loginName] - 登录账号
* @property {number} [managerOrgId] - 管理部门ID
* @property {string} [managerOrgName] - 管理部门名称
* @property {string} [marital] - 婚姻状态
* @property {string} [mk] - -
* @property {string} [mobile] - 移动电话
* @property {string} [nation] - 民族
* @property {string} [password] - 密码
* @property {string} [politic] - 政治面貌
* @property {number} [positionId] - 岗位ID
* @property {string} [positionName] - 岗位名称
* @property {string} [sex] - 用户性别0男 1女 2未知
* @property {string} [sfrh] - -
* @property {string} [telePhone] - 电话号码
* @property {string} [type] - 人员类别
* @property {string} [typeName] - 人员类别中文
* @property {string} [userId] - -
* @property {string} [userName] - 用户昵称
* @property {string} [userType] - 用户类型00系统用户 01注册用户
* @property {string} [whcd] - 文化程度
* @property {number} [xzcs] - 选择次数
*/
export const socketCurrentUser = (params) => {
return request({
url: api + "/socket/currentUser",
method: "get",
params
});
};
// import {socketCurrentUser} from "@/api/dataWatch/onlineUser.js"

View File

@ -0,0 +1,62 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
/**
* 会商反馈
* @param {Object} data - 反馈参数对象
* @param {string} data.hsid - 会商ID
* @param {string} data.fknr - 反馈内容
* @returns {Promise} 返回请求结果
*/
export const wshsHsfk = (data) => {
return request({
url: api + `/wshs/hsfk`,
method: "post",
data
})
}
/**
* 发送涉嫌种类
* @param {Object} data - 发送涉嫌种类参数对象
* @param {boolean} data.flag - 标志位
* @param {string} data.id - ID
* @param {Object} data.instructionsEntity - 指令实体对象
* @param {string} [data.instructionsEntity.attachmentPath] - 附件路径
* @param {string} [data.instructionsEntity.createdAt] - 创建时间
* @param {string} [data.instructionsEntity.instructionContent] - 指令内容
* @param {string} [data.instructionsEntity.instructionLevel] - 指令级别
* @param {string} [data.instructionsEntity.instructionLevelCode] - 指令级别代码
* @param {string} [data.instructionsEntity.instructionNumber] - 指令编号
* @param {string} [data.instructionsEntity.instructionTime] - 指令时间
* @param {string} [data.instructionsEntity.instructionType] - 指令类型
* @param {string} [data.instructionsEntity.instructionTypeCode] - 指令类型代码
* @param {string} [data.instructionsEntity.issuer] - 发布者
* @param {string} [data.instructionsEntity.issuerCode] - 发布者代码
* @param {string} [data.instructionsEntity.receivingUnit] - 接收单位
* @param {string} [data.instructionsEntity.receivingUnitCode] - 接收单位代码
* @param {string} [data.instructionsEntity.status] - 状态
* @param {string} [data.instructionsEntity.title] - 标题
* @param {string} [data.instructionsEntity.unitCode] - 单位代码
* @param {string} [data.instructionsEntity.unitName] - 单位名称
* @param {string} [data.instructionsEntity.updatedAt] - 更新时间
* @param {Array<Object>} [data.personnelEntity] - 人员实体数组
* @param {string} [data.personnelEntity[].comment] - 备注
* @param {string} [data.personnelEntity[].domicilePlace] - 户籍地
* @param {string} [data.personnelEntity[].idNumber] - 身份证号
* @param {string} [data.personnelEntity[].name] - 姓名
* @param {string} [data.personnelEntity[].orderId] - 订单ID
* @param {string} [data.personnelEntity[].personTypeId] - 人员类型ID
* @param {string} [data.personnelEntity[].personTypeName] - 人员类型名称
* @param {string} [data.personnelEntity[].phoneNumber] - 电话号码
* @param {string} [data.sfzh] - 身份证号
* @returns {Promise} 返回请求结果
*/
export const sendFqzl = (data) => {
return request({
url: api + `/send/fqzl`,
method: "post",
data
})
}

View File

@ -60,3 +60,36 @@ export const strategicPut = (data, url) => {
data data
}) })
} }
//提交研判申请
export const ypbgSjzlTjspId = (id) => {
return request({
url: api + `/ypbg/sjzl/tjsp/${id}`,
method: "get"
})
}
//ypbg/sjzl/queryShList 查询研判内部审核人员列表
export const ypbgSjzlQueryShList = (params) => {
return request({
url: api + `/ypbg/sjzl/queryShList`,
method: "get",
params
})
}
export const ypbgSjzlYpsp = (data) => {
return request({
url: api + `/ypbg/sjzl/ypsp`,
method: "post",
data
})
}
// 提交研判申请
// / mosty - api / mosty - gsxt / ypbg / sjzl / tjsp / id
// 研判内部审核人员查询列表(市情指领导才有权限)
// /mosty-api/mosty - gsxt / ypbg / sjzl / queryShList
// 内部研判审批
// / mosty - api / mosty - gsxt / ypbg / sjzl / ypsp
// 提交上级部门审批
// / mosty - api / mosty - gsxt / ypbg / sjzl / sendFqzl
// 工作流审批回掉
// / mosty - api / mosty - gsxt / ypbg / sjzl / updateBkgzl

View File

@ -26,41 +26,6 @@ export const tacticalGet = (params) => {
}) })
} }
// 战术研判-新增
export const tacticalPost = (data, url) => {
return request({
url: api,
method: "post",
data
})
}
// 战术研判-删除
export const tacticalDelete = (data, url) => {
return request({
url: api,
method: "delete",
data
})
}
// 战术研判-根据ID查询详情
export const tacticalGetInfo = (id) => {
return request({
url: api + `/tactical/${id}`,
method: "get"
})
}
// 战术研判-编辑
export const tacticalPut = (data, url) => {
return request({
url: api,
method: "put",
data
})
}
/** /**
* 开始研判 * 开始研判
@ -85,10 +50,92 @@ export const endJudgment = (id) => {
method: "post" method: "post"
}) })
} }
/**
* 网上会商(新增)
* @param {Object} data 会商数据
* @param {Array<string>} [data.chryList] 参会人员ID列表
* @param {string} [data.czyj] 会商处置意见
* @param {string} [data.glxsid] 关联线索ID(采集ID)
* @param {string} [data.glxsmc] 关联线索名称
* @param {string} [data.hsbt] 会商标题
* @param {string} [data.hsjssj] 会商结束时间 (ISO 8601格式)
* @param {string} [data.hskssj] 会商开始时间 (ISO 8601格式)
* @param {string} [data.hsnr] 会商内容
* @param {string} [data.hybh] 会议编号
* @param {string} [data.id] ID
* @param {string} [data.plnr] 评论内容
* @param {string} [data.tsypid] 态势研判ID
* @returns {Promise} 请求Promise对象
* @returns {Promise} 请求Promise对象
*/
export const wshsAdd = (data) => {
return request({
url: api + `/wshs/add`,
method: "post",
data
})
}
/**
* 新增研判报告
* @param {Object} data 研判报告数据
* @param {string} data.bgmc - 报告名称
* @param {string} data.bgnr - 报告内容
* @param {string} data.bz - 备注
* @param {string} data.cjrsfzh - 创建人身份证号
* @param {string} data.cjrxm - 创建人姓名
* @param {string} data.id - ID
* @param {string} data.scsj - 生成时间
* @param {string} data.ssbm - 所属部门
* @param {string} data.ssbmdm - 所属部门代码
* @param {string} data.sssgaj - 所属市公安局
* @param {string} data.sssgajdm - 所属市公安局代码
* @param {string} data.ssxgaj - 所属县公安局
* @param {string} data.ssxgajdm - 所属县公安局代码
* @param {string} data.ypid - 研判来源ID(数据整理ID)
* @param {string} data.ypmc - 研判名称
* @returns {Promise} 请求Promise对象
*/
export const gsxtYpbgAddEntity = (data) => {
return request({
url: api + `/gsxtYpbg/addEntity`,
method: "post",
data
})
}
/**
* 编辑研判报告
* @param {Object} data 研判报告数据
* @returns {Promise} 请求Promise对象
*/
export const gsxtYpbgEditEntity = (data) => {
return request({
url: api + `/gsxtYpbg/editEntity`,
method: "put",
data
})
}
/** /**
* 自建研判报告 * 自建研判报告
* @param {Object} data 自建研判数据 * @param {Object} data 自建研判数据
* @param {Array<Object>} data.cyypList 自建研判数据列表
* @param {string} data.cyypList[].fj - 附件
* @param {string} data.cyypList[].id - ID
* @param {string} data.cyypList[].scyq - 素材要求
* @param {string} data.cyypList[].sjzlid - 研判数据整理ID
* @param {string} data.cyypList[].wcqk - 完成情况01 准备中、02 已完成)
* @param {string} data.cyypList[].wcsj - 完成时间
* @param {string} data.cyypList[].ypbmdm - 研判部门代码
* @param {string} data.cyypList[].ypbmmc - 研判部门名称
* @param {Object} data.ypbgDto 研判报告DTO
* @param {string} data.ypbgDto.bgmc 报告名称
* @param {string} data.ypbgDto.bgnr 报告内容
* @param {string} data.ypbgDto.ypmc 研判名称
* @param {string} data.bglx 报告类型01 战术研判 02 战略研判)
* @param {string} data.ypyq 研判要求
* @param {string} data.ypyt 研判议题
* @returns {Promise} 请求Promise对象 * @returns {Promise} 请求Promise对象
*/ */
export const selfBuildJudgment = (data) => { export const selfBuildJudgment = (data) => {
@ -102,11 +149,11 @@ export const selfBuildJudgment = (data) => {
/** /**
* 研判指令列表 * 研判指令列表
* @param {Object} params 查询参数 * @param {Object} params 查询参数
* @param {number} [params.pageSize] 每页显示数量 * @param {number} params.pageSize 每页显示数量
* @param {number} [params.pageCurrent] 页码 * @param {number} params.pageCurrent 页码
* @param {string} [params.zlbt] 指令标题 * @param {string} params.zlbt 指令标题
* @param {string} [params.zlnr] 指令内容 * @param {string} params.zlnr 指令内容
* @param {string} [params.fqrxm] 发起人姓名 * @param {string} params.fqrxm 发起人姓名
* @returns {Promise} 请求Promise对象 * @returns {Promise} 请求Promise对象
*/ */
export const getJudgmentCommandList = (params) => { export const getJudgmentCommandList = (params) => {

43
src/api/sjxsgl.js Normal file
View File

@ -0,0 +1,43 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
// 新增系数
export const sjxsglAddEntity = (data) => {
return request({
url: api + "/sjxsgl/addEntity",
method: "POST",
data
});
};
// 删除系数
export const sjxsglDeleteEntity = (data) => {
return request({
url: api + "/sjxsgl/deleteEntity",
method: "DELETE",
data
});
};
// 修改系数
export const sjxsglEditEntity = (data) => {
return request({
url: api + "/sjxsgl/editEntity",
method: "PUT",
data
});
};
// 分页查询
export const sjxsglGetPageList = (params) => {
return request({
url: api + "/sjxsgl/getPageList",
method: "GET",
params
});
};
export const sjxsgId = (id) => {
return request({
url: api + `/sjxsgl/${id}`,
method: "GET",
});
}

View File

@ -106,3 +106,10 @@ export const useStatistics = (data) => {
data data
}); });
}; };
/** 获取是否红色名字,市情指领导、优秀信息员、优秀研判名字要变橙红色 */
export const getUserIsRed = () => {
return request({
url: '/mosty-api/mosty-gsxt' + "/xxcj/mjjf/sfgxys",
method: "GET"
});
};

View File

@ -1,5 +1,6 @@
import request from "@/utils/request"; import request from "@/utils/request";
const api = "/mosty-api/mosty-base"; const api = "/mosty-api/mosty-base";
const fzapi = "/mosty-api/mosty-gsxt";
/* /*
* 登录 * 登录
* return promise 实例对象 * return promise 实例对象
@ -154,3 +155,11 @@ export const deleteSysDictItem = (data) => {
data data
}); });
}; };
// 方正字典
export const fzdict = (params) => {
return request({
url: fzapi + "/xsaj/dict/selectList",
method: "GET",
params
});
}

View File

@ -170,3 +170,36 @@ export const xxcjMjjfSelectPage = (params) => {
params params
}) })
} }
// 情报 续报和补充 参数: czlx 操作类型01 续报、02 补充 id ysnr
export const addEntity = (data) => {
return request({
url: api + `/xxcj/bc/addEntity`,
method: "post",
data
})
}
// 转会商
export const xxcjXxzhs = (data) => {
return request({
url: api + `/xxcj/xxzhs`,
method: "post",
data
})
}
// 线索研判盯办统计
// 线索总数
export const xxcjQbcjSelectPage = (params) => {
return request({
url: api + `/qbcj/selectPage`,
method: "get",
params
})
}
// 下发总数列表
export const xxcjXfxsSelectPage = (params) => {
return request({
url: api + `/zlxx/selectPage`,
method: "get",
params
})
}

View File

@ -78,6 +78,13 @@ export const tbGsxtBqzhSelectList = (params) => {
params params
}) })
} }
// 组合标签详情
export const tbGsxtBqzhId = (id) => {
return request({
url: api + `/tbGsxtBqzh/${id}`,
method: "get",
})
}
// 身份标签 // 身份标签
export const yjzxSfyjSelectList = (params) => { export const yjzxSfyjSelectList = (params) => {
return request({ return request({
@ -210,4 +217,17 @@ export const sjzlQryp = (id) => {
method: "get", method: "get",
}) })
} }
export const xsajSelectPage = (params) => {
return request({
url: api + `/asj/xsaj/selectPage`,
method: "get",
params
})
}
export const xsajDictSelectList = (params) => {
return request({
url: api + ``,
method: "get",
params
})
}

View File

@ -0,0 +1,241 @@
<template>
<el-dialog :title="titleValue" width="1400px" :model-value="modelValue" append-to-body @close="closed">
<div>
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="系数名称">
<el-input placeholder="请输入系数名称" v-model="listQuery.mc" clearable></el-input>
</el-form-item>
<el-form-item label="计算规则">
<el-input placeholder="请输入计算规则" v-model="listQuery.jsgz" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="info" @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
<div class="tabBox" :class="props.Single ? 'tabBoxRadio' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" @selection-change="handleSelectionChange" :data="tableData" border
:row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column prop="mc" align="center" label="系数名称" />
<el-table-column prop="sjbl" align="center" label="衰减比例" />
<el-table-column prop="jsgz" align="center" label="计算规则" />
</el-table>
</div>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination class="pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="listQuery.current" :page-sizes="[10, 20, 50, 100]" :page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper" :total="total"></el-pagination>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { defineProps, watch, ref, onMounted, nextTick } from "vue";
import { selectUnAccreditPage, selectUserDeptPage } from "@/api/user-manage";
import { sjxsglGetPageList } from "@/api/sjxsgl.js";
import { qcckPost } from "@/api/qcckApi.js";
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
titleValue: {
type: String,
default: "选择配置"
},
LeaderType: {
type: String,
default: ""
},
//是否单选
Single: {
type: Boolean,
default: true
},
roleIds: {
type: Array,
default: []
}, url: {
type: String,
default: ""
}, bh: {
type: String,
default: ""
},
chooseJfBh: {
type: String,
default: ""
}
});
const total = ref(0);
const listQuery = ref({
current: 1,
size: 20
});
const form = ref({});
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "choosedUsers"]);
onMounted(() => {
});
watch(() => props.modelValue, (val) => {
if (val) {
nextTick(() => {
getListData();
});
}
}, {
immediate: true
});
// 监听 roleIds 变化,实时更新选择状态
watch(() => props.roleIds, (newVal, oldVal) => {
console.log('roleIds变化:', newVal, oldVal);
// 只要roleIds有变化就尝试回显不需要等待modelValue为true
// 因为可能是在对话框打开后roleIds才变化
nextTick(() => {
multipleUser();
});
}, { deep: true });
const closed = () => {
// 清空新选择的内容
multipleSelectionUser.value = [];
// 取消表格中所有行的选择状态
if (multipleUserRef.value && tableData.value && tableData.value.length > 0) {
tableData.value.forEach(item => {
multipleUserRef.value.toggleRowSelection(item, false);
});
}
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = {
current: 1,
size: 20,
loginName: "",
phone: ""
};
getListData();
};
const keyid = (row) => {
return row.id;
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
console.log(userList);
let promes = {
list: userList.map(item => {
return {
xsid: item.id,
mc: item.mc,
sjbl: item.sjbl,
}
}),
id: props.chooseJfBh
}
qcckPost(promes, `/mosty-gsxt${props.url}`).then(res => {
ElMessage.success('操作成功');
})
closed();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getListData();
};
const getListData = () => {
const params = listQuery.value;
sjxsglGetPageList(params).then((res) => {
tableData.value = res?.records;
total.value = Number(res.total);
// 使用 nextTick 确保表格已经渲染完成后再执行回显
nextTick(() => {
multipleUser();
});
});
};
// 列表回显
function multipleUser() {
// 确保表格引用和数据都存在
if (!multipleUserRef.value || !tableData.value || tableData.value.length === 0) {
console.log('表格引用或数据不存在,无法回显');
return;
}
// 先清空之前的选择,确保选择状态的准确性
tableData.value.forEach(item => {
multipleUserRef.value.toggleRowSelection(item, false);
});
console.log('开始回显roleIds:', props.roleIds);
console.log('表格数据:', tableData.value);
// 根据 roleIds 进行回显,确保类型一致
tableData.value.forEach((item) => {
const itemId = String(item.id);
if (props.roleIds.some((id) => String(id) === itemId)) {
console.log('回显选择:', item);
multipleUserRef.value.toggleRowSelection(item, true);
}
});
}
const handleFilter = () => {
listQuery.value.current = 1;
getListData();
};
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
let del_row = val.shift();
multipleUserRef.value.toggleRowSelection(del_row, false);
}
multipleSelectionUser.value = val;
} else {
multipleSelectionUser.value = val;
}
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -7,10 +7,10 @@
@close="closed" @close="closed"
> >
<div> <div>
<div class="flex" style="margin-bottom: 10px;"> <div class="flex" style="margin-bottom: 10px;">
<el-button :type="bqLb === '01' ? 'success' : 'info'" @click="qihuan('01')">标签大类</el-button> <el-button :type="bqLb === '01' ? 'success' : 'info'" @click="qihuan('01')">标签大类</el-button>
<el-button :type="bqLb === '02' ? 'success' : 'info'" @click="qihuan('02')"> 标签小类 </el-button> <el-button :type="bqLb === '02' ? 'success' : 'info'" @click="qihuan('02')"> 标签小类 </el-button>
</div> </div>
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true"> <el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="标签名称"> <el-form-item label="标签名称">
<el-input <el-input

Binary file not shown.

View File

@ -1,34 +1,49 @@
<template> <template>
<div class="mt20 flex align-center"> <DraggableResizableVue id="call_div" v-model:x="element.x" v-model:y="element.y" v-model:h="element.height" v-model:w="element.width" v-model:active="element.isActive" class="container">
<el-input style="width:200px" class="mr10" v-model="keyWoed" placeholder="输入编号"></el-input> <div>
<el-button @click="handleBtn('无人机视频')">无人机视频</el-button> <el-row justify="space-around">
<el-button @click="handleBtn('音频')">音频</el-button> <el-tag v-for="item in speakers" :key="item.number" bordered color="green">{{ item.alias || item.number }}</el-tag>
</div> </el-row>
<DraggableResizableVue id="call_div" v-model:x="element.x" v-model:y="element.y" v-model:h="element.height" v-model:w="element.width" v-model:active="element.isActive" class="container"> <div id="voice_wave" class="wave"></div>
<div> <audio ref="audioRef" :volume="80 / 100" autoplay controls hidden />
<el-row justify="space-around"> <video id="video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/>
<a-tag v-for="item in speakers" :key="item.number" bordered color="green">{{ item.alias || item.number }}</a-tag> <video id="localvideo" ref="localvideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video"/>
</el-row> <video id="pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video" />
<div id="voice_wave" class="wave"></div> <audio ref="fileAudioRef" autoplay :hidden="true"/>
<audio ref="audioRef" :volume="80 / 100" autoplay controls hidden /> <el-row class="buttonContainer" justify="space-around">
<video id="video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/> <el-button circle @click="setMuteMic">
<video id="localvideo" ref="localvideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video"/> <img v-if="micMuted" src="@/assets/images/webPuc/svgs/microphone.svg" alt="">
<video id="pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video" /> <img v-else src="@/assets/images/webPuc/svgs/microphone_mute.svg" alt="">
<el-row class="buttonContainer" justify="space-around"> </el-button>
<el-button :type="selfGranted ? 'success' : 'pramary'" shape="round" @click="applayFloor">话权</el-button> <el-button circle @click="setMuteEar">
<el-button type="danger" shape="round" @click="hangup">挂断</el-button> <img v-if="earpieceMuted" src="@/assets/images/webPuc/svgs/earpiece.svg" alt="">
</el-row> <img v-else src="@/assets/images/webPuc/svgs/trumpet_mute.svg" alt="">
</div> </el-button>
</DraggableResizableVue> <el-button circle @click="camera">
<img v-if="cameraOff" src="@/assets/images/webPuc/svgs/camera.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/camera_mute.svg" alt="">
</el-button>
<el-button circle @click="transferVideoCall">
<img src="@/assets/images/webPuc/svgs/share_video.svg" alt="">
</el-button>
<el-button :type="selfGranted ? 'success' : 'pramary'" shape="round" @click="applayFloor">话权</el-button>
<el-button type="danger" shape="round" @click="hangup">挂断</el-button>
</el-row>
</div>
</DraggableResizableVue>
</template> </template>
<script setup> <script setup>
import useCallModule from '@/sdk/call'; import useCallModule from '@/components/Consultation/sdk/call';
import useRecorder from '@/hooks/recorder'; import useRecorder from '@/components/Consultation/hooks/recorder';
import DraggableResizableVue from "draggable-resizable-vue3"; import DraggableResizableVue from "draggable-resizable-vue3";
import { nextTick, onMounted, onUnmounted, ref } from "vue"; import { nextTick, onMounted, onUnmounted, ref, defineProps, defineEmits } from "vue";
import SiriWave from "siriwave"; import SiriWave from "siriwave";
import { init } from "echarts"; const props = defineProps({
modelValue:Boolean,
})
const emit = defineEmits(['update:modelValue'])
const baseInfo = localStorage.getItem('rhInfo') ? JSON.parse(localStorage.getItem('rhInfo')) : {};
let waveContainer; let waveContainer;
let audioWave = SiriWave || undefined; let audioWave = SiriWave || undefined;
const element = ref({ const element = ref({
@ -42,16 +57,16 @@ let rootView;
let streamCbId; let streamCbId;
let hangupCbId; let hangupCbId;
let grantCbId; let grantCbId;
const micMuted = ref(false);
const earpieceMuted = ref(false);
const cameraOff = ref(false);
// local video stream // local video stream
let localVideoStream; let localVideoStream;
// remote video stream // remote video stream
let remoteVideoStream; let remoteVideoStream;
const selfGranted = ref(false); const selfGranted = ref(false);
// 54040254001310305009
// 38467417
const keyWoed = ref('38467417') //
// Video true video false 2video // Video true video false 2video
const useOneVideoShow = true; const useOneVideoShow = true;
@ -65,15 +80,38 @@ const showVideo = ref(false);
const localvideoRef = ref(); // Video const localvideoRef = ref(); // Video
const showlocalVideo = ref(false); // const showlocalVideo = ref(false); //
const fileAudioRef = ref();
const pushVideoRef = ref(); const pushVideoRef = ref();
// show push video // show push video
const showPushlVideo = ref(false); const showPushlVideo = ref(false);
const showPanel = ref(false);
const speakers = ref([]); const speakers = ref([]);
const codeId = ref(null) // 54040254001310305009
// 38467417
const keyWoed = ref('38467417') //
const setMuteMic = () => {
CALL.setMuteMic(!micMuted.value).then((resp) => {
console.log('mute mic result ', resp);
micMuted.value = !micMuted.value;
});
};
const setMuteEar = () => {
CALL.setMuteCall(!earpieceMuted.value);
earpieceMuted.value = !earpieceMuted.value;
};
const camera = () => {
CALL.setMuteCamera(!cameraOff.value).then((resp) => {
console.log('mute camera result ', resp);
cameraOff.value = !cameraOff.value;
});
};
const transferVideoCall = () => {
// CALL.forwardVideoCall();
};
// //
@ -83,21 +121,14 @@ const handleBtn = (type) =>{
lemon.basedata.fetchDeviceList(params).then(resp => { lemon.basedata.fetchDeviceList(params).then(resp => {
if(resp.device_list[0].basedata_id){ if(resp.device_list[0].basedata_id){
let basedata_id = resp.device_list[0].basedata_id let basedata_id = resp.device_list[0].basedata_id
debugger
switch(type){ switch(type){
case '无人机视频': case '无人机':
let obj = { basedata_id , video_frame_size: 3, hook_flag: 0 } let obj = { basedata_id , video_frame_size: 3, hook_flag: 0 }
window.lemon.call.makeVideoCall(obj)?.then((resp) => { CALL.makeVideoCall(obj)
console.log('无人机视频', resp);
codeId.value = resp.call_id
});
break; break;
case '音频': case '对讲机':
let obj1 = { basedata_id,"hook_flag":0 } let obj1 = { basedata_id,"hook_flag":0,"duplex_flag":0 }
window.lemon.call.makeVoiceCall(obj1)?.then((resp) => { CALL.makeVoiceCall(obj1)
console.log('音频', resp);
codeId.value = resp.call_id
});
break; break;
} }
} }
@ -108,8 +139,6 @@ const handleBtn = (type) =>{
// register media stream callbackinclude audio and video stream // register media stream callbackinclude audio and video stream
const registerStream = () => { const registerStream = () => {
streamCbId = window.lemon.call.addMediaStream((call_id, stream, type) => { streamCbId = window.lemon.call.addMediaStream((call_id, stream, type) => {
console.log(type,'============监听播放类型');
showPanel.value = true;
rootView.style.display = 'unset'; rootView.style.display = 'unset';
if (type === 'audio_dst') { if (type === 'audio_dst') {
setAudio(stream); setAudio(stream);
@ -140,6 +169,7 @@ const registerStream = () => {
}; };
const setAudio = (stream) => { const setAudio = (stream) => {
console.log(audioRef.value);
if (audioRef.value) { if (audioRef.value) {
audioRef.value.srcObject = stream; audioRef.value.srcObject = stream;
} else { } else {
@ -149,13 +179,13 @@ const setAudio = (stream) => {
} }
}; };
//
const registerhangupEvent = () => { const registerhangupEvent = () => {
hangupCbId = window.lemon.call.addHangupEvt(() => { hangupCbId = window.lemon.call.addHangupEvt(() => {
speakers.value.length = 0; speakers.value.length = 0;
selfGranted.value = false; selfGranted.value = false;
showVideo.value = false; showVideo.value = false;
showlocalVideo.value = false; showlocalVideo.value = false;
showPanel.value = false;
try { try {
videoRef.value.pause(); videoRef.value.pause();
} catch (error) { } catch (error) {
@ -206,13 +236,13 @@ const registerGrantEvent = () => {
const close = () => { const close = () => {
if (rootView) { if (rootView) {
emit('update:modelValue',false)
rootView.style.display = 'none'; rootView.style.display = 'none';
} }
}; };
const applayFloor = () => { const applayFloor = () => {
const self = sessionStorage.getItem('user_id'); const index = speakers.value?.findIndex((item) => item.number === baseInfo.user_id);
const index = speakers.value?.findIndex((item) => item.number === self);
if (index >= 0) { if (index >= 0) {
CALL.releaseFloor(); CALL.releaseFloor();
} else { } else {
@ -221,41 +251,10 @@ const applayFloor = () => {
}; };
const hangup = () => { const hangup = () => {
CALL.hangup(codeId.value); emit('update:modelValue',false)
CALL.hangup();
}; };
const Init = () => {
let token = window.localStorage.getItem("rhToken");
if (!token) {
let userInfo = {
username: "sgxtcs",
password: "123456",
realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888"
};
lemon.login.login(userInfo).then((esacpe) => {
token = esacpe.token;
window.localStorage.setItem("rhToken", esacpe.token);
});
} else {
ConnectWebsocket(token);
}
};
const ConnectWebsocket = (token) => {
lemon.login.reConnectWebsocket({
username: "sgxtcs",
realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888",
token: token
}).then((resp) => {
console.log(resp,"ConnectWebsocket")
window.lemon.call.addMediaStream((call_id, stream, type) => {
console.log(call_id, stream, type);
});
});
};
const initWave = () => { const initWave = () => {
if (!waveContainer) { if (!waveContainer) {
waveContainer = document.getElementById('voice_wave'); waveContainer = document.getElementById('voice_wave');
@ -277,17 +276,17 @@ const initVideo = () => {
onMounted(() => { onMounted(() => {
registerStream();
registerhangupEvent();
registerGrantEvent();
nextTick(() => { nextTick(() => {
Init();
registerStream();
registerhangupEvent();
registerGrantEvent();
videoRef.value.onloadedmetadata = initVideo; videoRef.value.onloadedmetadata = initVideo;
initWave(); initWave();
}); });
rootView = document.getElementById('call_div'); rootView = document.getElementById('call_div');
window.video = pushVideoRef.value; window.video = pushVideoRef.value;
window.audio = fileAudioRef.value;
window.showVideo = showPushlVideo; window.showVideo = showPushlVideo;
window.videoViewRoot = rootView; window.videoViewRoot = rootView;
@ -297,6 +296,7 @@ onUnmounted(() => {
window.lemon.call.removeHangupEvt(hangupCbId); window.lemon.call.removeHangupEvt(hangupCbId);
window.lemon.floor.removeGrantEvt(grantCbId); window.lemon.floor.removeGrantEvt(grantCbId);
}); });
defineExpose({ handleBtn });
</script> </script>

View File

@ -18,7 +18,7 @@
<script setup> <script setup>
import { toRef } from 'vue'; import { toRef } from 'vue';
import { Button } from 'element-plus'; import { Button } from 'element-plus';
import useCallModule from '@/views/consultation/sdk/call'; import useCallModule from '@/components/Consultation/sdk/call';
const props = defineProps({ const props = defineProps({
answer: { answer: {

View File

@ -1,7 +1,7 @@
import { ref, onUnmounted } from 'vue'; import { ref, onUnmounted } from 'vue';
import { ElNotification } from 'element-plus'; import { ElNotification } from 'element-plus';
import emitter from "@/utils/eventBus.js"; import emitter from "@/utils/eventBus.js";
import useConferenceControlModule from '@/views/consultation/sdk/conferenceControl'; import useConferenceControlModule from '@/components/Consultation/sdk/conferenceControl';
import store from '@/store' import store from '@/store'
const sdkConfernceControlModule = useConferenceControlModule(); const sdkConfernceControlModule = useConferenceControlModule();

View File

@ -1,7 +1,7 @@
import { ref, getCurrentInstance, onUnmounted } from 'vue'; import { ref, getCurrentInstance, onUnmounted } from 'vue';
import { ElNotification } from 'element-plus'; import { ElNotification } from 'element-plus';
import { ConferenceCallingNotification } from '@/views/consultation/hooks/callingNotification'; import { ConferenceCallingNotification } from '@/components/Consultation/hooks/callingNotification';
import useConfernceModule from '@/views/consultation/sdk/conference'; import useConfernceModule from '@/components/Consultation/sdk/conference';
import store from '@/store' import store from '@/store'
import emitter from "@/utils/eventBus.js"; import emitter from "@/utils/eventBus.js";

View File

@ -5,164 +5,184 @@
v-model:h="element.height" v-model:h="element.height"
v-model:w="element.width" v-model:w="element.width"
v-model:active="element.isActive" v-model:active="element.isActive"
:draggable="true"
:resizable="true"
:handles="['tl','tr','bl','br']"
handles-type="handles"
:active-on-hover="false"
:prevent-deactivation="true"
class-name-handle="drs-handle"
class="container" class="container"
> >
<div ref="mainContentRef" class="conference-box"> <div ref="mainContentRef" class="conference-box">
<!-- 会议主题 --> <!-- Header Area -->
<div v-show="displaySubject" class="subject"> <div class="conference-header">
<h3 v-if="!editSubject" @click="editSubject = true"> <div class="header-top">
{{ displaySubject }} ({{ activeMeetingConfig?.meeting.number }}) <div class="title-section" v-show="displaySubject">
</h3> <h3 v-if="!editSubject" @click="editSubject = true" class="conference-title">
<el-input v-else v-model="subject" autofocus allow-clear @blur="updateSubject"/> {{ displaySubject }}
</h3>
<el-input v-else v-model="subject" autofocus allow-clear @blur="updateSubject" class="title-input"/>
<div class="meeting-id-tag" @click="copyMeetingNumber" v-if="activeMeetingConfig?.meeting?.number">
<span class="id-label">会议号:</span>
<span class="id-value">{{ activeMeetingConfig?.meeting?.number }}</span>
<el-icon class="copy-icon"><CopyDocument /></el-icon>
</div>
</div>
</div>
<div class="participants-info">
<el-icon><User /></el-icon>
<span class="count-text">参会人员 {{ activeMeetingConfig?.members?.length || 0 }}</span>
</div>
</div> </div>
<div class="top-box"> <!-- Video Content Area -->
<!-- 当前正在讲话 --> <div class="video-content-area">
<el-row justify="space-around"> <div class="top-box">
<el-tag v-for="name in speakingMemberNames" :key="name" bordered color="green" >{{ name }}</el-tag> <!-- 当前正在讲话 -->
</el-row> <el-row justify="space-around">
<el-tag v-for="name in speakingMemberNames" :key="name" bordered color="green" >{{ name }}</el-tag>
</el-row>
<!-- 共享者 -->
<el-tag v-if="activeMeetingConfig?.sharingMember" bordered color="orange">
{{ activeMeetingConfig?.sharingMember?.alias}}正在共享屏幕
</el-tag>
</div>
<!-- 共享者 --> <!-- 会议音视频 -->
<el-tag v-if="activeMeetingConfig?.sharingMember" bordered color="orange"> <audio id="conference_audio" ref="audioRef" :volume="80 / 100" :muted="audioOuputStatus !== 0" autoplay controls hidden />
{{ activeMeetingConfig?.sharingMember?.alias}}正在共享屏幕 <video id="conference_video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/>
</el-tag>
<!-- 广播相关此处借用 video 标签获取对应的流 -->
<video id="conference_localvideo" ref="localVideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video" />
<img v-if="isMicEnable" v-show="activeMeetingConfig?.broadcast" @click="stopBroadcast" src="@/assets/images/webPuc/svgs/img_broadcast.svg" alt="" class="img_broadcast">
<el-upload
v-show="false"
:show-file-list="false"
draggable
accept=".mp4"
:multiple="false"
:auto-upload="false"
:show-remove-button="false"
:show-cancel-button="false"
@change="onFileChanged"
@before-upload="beforeUpload"
/>
<video id="conference_pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video"/>
<audio ref="fileAudioRef" autoplay :hidden="true" />
<div class="control-bar">
<!-- 锁定 -->
<el-button circle @click="lockConference" class="control-btn">
<el-icon size="20px" v-if="activeMeetingConfig?.lockStatus == 1"><Lock/></el-icon>
<el-icon size="20px" v-else ><Unlock/></el-icon>
</el-button>
<!-- 麦克风 -->
<el-button circle @click="setMuteMic" class="control-btn">
<img v-if="isMicEnable" src="@/assets/images/webPuc/svgs/microphone.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/microphone_mute.svg" alt="">
</el-button>
<el-popover title="选择麦克风" trigger="click" position="bottom-end">
<template #reference>
<el-icon class="control-arrow" color="#fff"><ArrowDown/></el-icon>
</template>
<MicPop @changeDevice="changeDevice" />
</el-popover>
<!-- 扬声器 -->
<el-button circle @click="setMuteEar" class="control-btn">
<img v-if="audioOuputStatus == 1" src="@/assets/images/webPuc/svgs/earpiece.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/trumpet_mute.svg" alt="">
</el-button>
<el-popover title="选择扬声器" trigger="click" position="bottom-end">
<template #reference>
<el-icon class="control-arrow" color="#fff"><ArrowDown/></el-icon>
</template>
<!-- <AudioPop @changeDevice="changeDevice" /> -->
</el-popover>
<!-- 摄像头 -->
<el-button circle @click="setCamera" class="control-btn">
<img v-if="userInfo?.camera_status === CAMERA_STATUS_OPEN" src="@/assets/images/webPuc/svgs/camera.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/camera_mute.svg" alt="">
</el-button>
<el-popover title="选择摄像头" trigger="click" position="bottom-end">
<template #reference>
<el-icon class="control-arrow" color="#fff"><ArrowDown/></el-icon>
</template>
<!-- <CameraPop @changeDevice="changeDevice" /> -->
</el-popover>
<!-- 屏幕共享 -->
<el-button circle @click="setShareScreenStatus(1)" class="control-btn">
<img src="@/assets/images/webPuc/svgs/share_video.svg" alt="">
</el-button>
<!-- 结束共享 / 结束会议 (Center) -->
<el-button v-if="activeMeetingConfig?.sharingMember?.basedata_id === userInfo?.basedata_id"
type="danger"
shape="round"
status="danger"
class="hangup-btn"
@click="setShareScreenStatus(0)">
结束共享
</el-button>
<template v-else>
<!-- 结束会议 v-if="globalStore.IS_CURRENT_MEETING_OWNER"-->
<el-button
type="danger"
shape="round"
class="hangup-btn"
@click="endConference">
结束会议
</el-button>
</template>
<!-- 成员管理 -->
<el-button circle @click="showMembers" class="control-btn">
<el-icon color="#fff" size="20"><Auatar/></el-icon>
</el-button>
<!-- 语音激励 -->
<el-button circle @click="setVoiceStimulation()" class="control-btn">
<img v-if="activeMeetingConfig?.voiceStimulation" src="@/assets/images/webPuc/svgs/icon_embrave.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/conference_icom_cancel_voice_stimulation.svg" alt="">
</el-button>
<!-- 布局 -->
<!-- <LaoutType @setConfernceLayoutType="setConfernceLayoutType" /> -->
<!-- 画面抓取-截图 -->
<el-button circle @click="startScreenshot" class="control-btn">
<el-icon color="#fff" size="20"><Scissor/></el-icon>
</el-button>
<!-- 视频广播 -->
<el-button circle @click="broadcastAction" class="control-btn">
<img src="@/assets/images/webPuc/svgs/icon_broadcast.svg" alt="">
</el-button>
<!-- 录屏 -->
<el-button circle @click="!isRecording ? mediaRecorder.start() : mediaRecorder.stop()" class="control-btn">
<el-icon v-if="!isRecording"><Camera/></el-icon>
<el-icon v-else style="color: red"><Videopause/></el-icon>
</el-button>
<el-button circle @click="toggleFullscreen" class="control-btn">
<el-icon v-if="!isFullscreen"><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M384 192H192a64 64 0 00-64 64v192a32 32 0 1064 0V288h192a32 32 0 000-64zm384 64H576a32 32 0 100 64h192v160a32 32 0 1064 0V256a64 64 0 00-64-64zM352 768H192V608a32 32 0 10-64 0v192a64 64 0 0064 64h160a32 32 0 100-64zm544-160a32 32 0 00-32 32v128H704a32 32 0 100 64h160a64 64 0 0064-64V640a32 32 0 00-32-32z"/></svg></el-icon>
<el-icon v-else><svg class="icon" width="200" height="200" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M352 288a32 32 0 010-64h160a32 32 0 0132 32v160a32 32 0 11-64 0V320H352zm320 448a32 32 0 010 64H512a32 32 0 01-32-32V608a32 32 0 1164 0v128h128zM256 672a32 32 0 00-32-32H96a32 32 0 00-32 32v128a32 32 0 1064 0v-96h64a32 32 0 0032-32zm640-384a32 32 0 00-32 32v96h-64a32 32 0 100 64h128a32 32 0 0032-32V288a32 32 0 00-32-32z"/></svg></el-icon>
</el-button>
</div>
</div> </div>
<!-- 会议音视频 -->
<audio id="conference_audio" ref="audioRef" :volume="80 / 100" :muted="audioOuputStatus !== 0" autoplay controls hidden />
<video id="conference_video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/>
<!-- 广播相关此处借用 video 标签获取对应的流 -->
<video id="conference_localvideo" ref="localVideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video" />
<img v-if="isMicEnable" v-show="activeMeetingConfig?.broadcast" @click="stopBroadcast" src="@/assets/images/webPuc/svgs/img_broadcast.svg" alt="">
<el-upload
v-show="false"
:show-file-list="false"
draggable
accept=".mp4"
:multiple="false"
:auto-upload="false"
:show-remove-button="false"
:show-cancel-button="false"
@change="onFileChanged"
@before-upload="beforeUpload"
/>
<video id="conference_pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video"/>
<audio ref="fileAudioRef" autoplay :hidden="true" />
<el-row class="buttonContainer" justify="space-around">
<!-- 锁定 -->
<el-button circle @click="lockConference">
<el-icon size="20px" v-if="activeMeetingConfig?.lockStatus == 1"><Lock/></el-icon>
<el-icon size="20px" v-else ><Unlock/></el-icon>
</el-button>
<!-- 麦克风 -->
<el-button circle @click="setMuteMic">
<img v-if="isMicEnable" src="@/assets/images/webPuc/svgs/microphone.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/microphone_mute.svg" alt="">
</el-button>
<el-popover title="选择麦克风" trigger="click" position="bottom-end">
<template #reference>
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
</template>
<MicPop @changeDevice="changeDevice" />
</el-popover>
<!-- 扬声器 -->
<el-button circle @click="setMuteEar">
<img v-if="audioOuputStatus == 1" src="@/assets/images/webPuc/svgs/earpiece.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/trumpet_mute.svg" alt="">
</el-button>
<el-popover title="选择扬声器" trigger="click" position="bottom-end">
<template #reference>
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
</template>
<!-- <AudioPop @changeDevice="changeDevice" /> -->
</el-popover>
<!-- 摄像头 -->
<el-button circle @click="setCamera">
<img v-if="userInfo?.camera_status === CAMERA_STATUS_OPEN" src="@/assets/images/webPuc/svgs/camera.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/camera_mute.svg" alt="">
</el-button>
<el-popover title="选择摄像头" trigger="click" position="bottom-end">
<template #reference>
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
</template>
<!-- <CameraPop @changeDevice="changeDevice" /> -->
</el-popover>
<!-- 屏幕共享 -->
<el-button circle @click="setShareScreenStatus(1)">
<img src="@/assets/images/webPuc/svgs/share_video.svg" alt="">
</el-button>
<!-- 成员管理 -->
<el-button circle @click="showMembers">
<el-icon color="#84888E" size="20"><Auatar/></el-icon>
</el-button>
<!-- 语音激励 -->
<el-button circle @click="setVoiceStimulation()">
<img v-if="activeMeetingConfig?.voiceStimulation" src="@/assets/images/webPuc/svgs/icon_embrave.svg" alt="">
<img v-else src="@/assets/images/webPuc/svgs/conference_icom_cancel_voice_stimulation.svg" alt="">
</el-button>
<!-- 布局 -->
<!-- <LaoutType @setConfernceLayoutType="setConfernceLayoutType" /> -->
<!-- 画面抓取-截图 -->
<el-button circle @click="startScreenshot">
<el-icon color="#84888E" size="20"><Scissor/></el-icon>
</el-button>
<!-- 视频广播 -->
<el-button circle @click="broadcastAction">
<img src="@/assets/images/webPuc/svgs/icon_broadcast.svg" alt="">
</el-button>
<!-- 录屏 -->
<el-button circle @click="!isRecording ? mediaRecorder.start() : mediaRecorder.stop()">
<el-icon v-if="!isRecording"><Camera/></el-icon>
<el-icon v-else style="color: red"><Videopause/></el-icon>
</el-button>
<!-- 结束共享 -->
<el-button v-if="activeMeetingConfig?.sharingMember?.basedata_id === userInfo?.basedata_id"
type="danger"
shape="round"
status="danger"
@click="setShareScreenStatus(0)">
结束共享
</el-button>
<template v-else>
<!-- 结束会议 v-if="globalStore.IS_CURRENT_MEETING_OWNER"-->
<el-button
type="danger"
shape="round"
@click="endConference">
结束会议
</el-button>
<!-- 退出会议 -->
<!-- <el-button
v-else
type="danger"
shape="round"
@click="hangupCall"
>退出会议</el-button
> -->
</template>
</el-row>
<!-- 关闭按钮 --> <!-- 关闭按钮 -->
<el-button class="close" type="primary" icon="Close" circle @click="close"></el-button> <el-button class="close-card-btn" type="text" circle @click="close">
<el-icon size="20"><Close /></el-icon>
</el-button>
</div> </div>
<!-- 成员管理面板 暂时未改--> <!-- 成员管理面板 暂时未改-->
@ -175,10 +195,10 @@ import MicPop from './micPop.vue';
import emitter from "@/utils/eventBus.js"; import emitter from "@/utils/eventBus.js";
// import MemberMangerModal from '../memberMangerModal/index.vue'; // import MemberMangerModal from '../memberMangerModal/index.vue';
import { nextTick, onMounted,defineEmits,defineExpose,onUnmounted,defineProps, ref, getCurrentInstance, computed, watch } from 'vue'; import { nextTick, onMounted,defineEmits,defineExpose,onUnmounted,defineProps, ref, getCurrentInstance, computed, watch } from 'vue';
import useConferenceControlModule, { CONFERENCE_ROLE_NORMAL, CONFERENCE_ROLE_HOST, MICROPHONE_STATUS_NO, MICROPHONE_STATUS_OPEN, MICROPHONE_STATUS_CLOSE, MUTE_STATUS_Y, PROHIBITION_STATUS_Y, PROHIBITION_STATUS_N, MUTE_STATUS_N, CAMERA_STATUS_NO, CAMERA_STATUS_OPEN, CAMERA_STATUS_CLOSE } from '@/views/consultation/sdk/conferenceControl'; import useConferenceControlModule, { CONFERENCE_ROLE_NORMAL, CONFERENCE_ROLE_HOST, MICROPHONE_STATUS_NO, MICROPHONE_STATUS_OPEN, MICROPHONE_STATUS_CLOSE, MUTE_STATUS_Y, PROHIBITION_STATUS_Y, PROHIBITION_STATUS_N, MUTE_STATUS_N, CAMERA_STATUS_NO, CAMERA_STATUS_OPEN, CAMERA_STATUS_CLOSE } from '@/components/Consultation/sdk/conferenceControl';
import { ElMessage} from "element-plus"; import { ElMessage} from "element-plus";
import DraggableResizableVue from 'draggable-resizable-vue3'; import DraggableResizableVue from 'draggable-resizable-vue3';
import useConferenceModule from '@/views/consultation/sdk/conference'; import useConferenceModule from '@/components/Consultation/sdk/conference';
import useConfernceControlEvent from './js/useConfernceControlEvent'; import useConfernceControlEvent from './js/useConfernceControlEvent';
import { useStore } from "vuex"; import { useStore } from "vuex";
const props = defineProps({ const props = defineProps({
@ -189,9 +209,9 @@ const store = useStore();
const element = ref({ const element = ref({
x: 500, x: 500,
y: -600, y: -600,
width: 500, width: 960,
height: 500, height: 500,
isActive: false, isActive: true,
}); });
const globalStore = store.state.useGlobalStore; const globalStore = store.state.useGlobalStore;
// - // -
@ -241,9 +261,10 @@ const speakers = ref([]);
const selfGranted = ref(false); const selfGranted = ref(false);
const displaySubject = computed(() => { const displaySubject = computed(() => {
const text = globalStore.activeMeetingConfig?.subject || ''; const text = globalStore.activeMeetingConfig?.subject;
subject.value = text; const defaultText = text && String(text).trim() ? text : '会议的标题';
return text; subject.value = defaultText;
return defaultText;
}); });
// 0=1=2= // 0=1=2=
@ -712,6 +733,22 @@ const setAudio = (stream) => {
}; };
}); });
}; };
const isFullscreen = ref(false);
const onFullscreenChange = () => {
isFullscreen.value = !!document.fullscreenElement;
};
const toggleFullscreen = () => {
const el = mainContentRef.value;
if (!document.fullscreenElement) {
if (el && el.requestFullscreen) {
el.requestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
};
// //
const onDeviceListChange = (mediaDeviceInfo) => { const onDeviceListChange = (mediaDeviceInfo) => {
@ -725,6 +762,17 @@ const setAudio = (stream) => {
} }
}; };
const copyMeetingNumber = () => {
const number = activeMeetingConfig.value?.meeting?.number;
if (number) {
navigator.clipboard.writeText(number).then(() => {
ElMessage.success('会议号已复制');
}).catch(() => {
ElMessage.error('复制失败');
});
}
};
onMounted(()=>{ onMounted(()=>{
console.log(globalStore,'=====0000000000000'); console.log(globalStore,'=====0000000000000');
@ -743,6 +791,7 @@ onMounted(()=>{
// //
addVideoOnLoadedMetadataEvnt(); addVideoOnLoadedMetadataEvnt();
document.addEventListener('fullscreenchange', onFullscreenChange);
}); });
@ -750,6 +799,7 @@ onUnmounted(() => {
emitter.off('onMediaStream'); emitter.off('onMediaStream');
emitter.off('onHangup'); emitter.off('onHangup');
removeBroadcastVideoListener(); removeBroadcastVideoListener();
document.removeEventListener('fullscreenchange', onFullscreenChange);
}); });
</script> </script>
@ -759,84 +809,223 @@ onUnmounted(() => {
position: absolute; position: absolute;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center;
margin: 2px; margin: 2px;
background: rgb(28,32,41); background: #fff;
border: 2px dashed #e8e8e8; border: none;
border-radius: 16px; border-radius: 12px;
box-shadow: 0 4px 16px rgba(0,0,0,0.15);
cursor: default;
overflow: visible;
}
.conference-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
}
/* Header Styles */
.conference-header {
padding: 16px 20px 10px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 2px solid #c0c4cc;
}
.title-section {
display: flex;
align-items: center;
gap: 12px;
}
.conference-title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #333;
cursor: pointer; cursor: pointer;
} }
.title-input {
width: 200px;
}
.meeting-id-tag {
display: flex;
align-items: center;
background: #e6f7ff;
color: #1890ff;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
}
.meeting-id-tag:hover {
background: #bae7ff;
}
.id-label {
margin-right: 4px;
}
.copy-icon {
margin-left: 4px;
}
.participants-info {
display: flex;
align-items: center;
color: #666;
font-size: 13px;
gap: 6px;
}
/* Video Area Styles */
.video-content-area {
flex: 1;
position: relative;
background: #000;
margin: 10px;
border-radius: 12px;
overflow: hidden;
}
.video { .video {
width: 100%;
height: 100%;
object-fit: contain;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; pointer-events: none;
height: 100%;
object-fit: scale-down;
}
.buttonContainer {
position: absolute;
bottom: 0;
width: 96%;
margin: 8px;
padding: 5px 3px;
background: #fff;
border-radius: 3px;
}
.speaks {
align-items: center;
}
.wave {
top: 0;
width: 100%;
height: 100px;
}
.close {
position: absolute;
top: 0;
right: 0;
margin: 5px;
}
.subject {
position: absolute;
top: -53px;
padding: 0 5px;
color: #ffff;
background: #1c2029;
border-radius: 5px;
}
.subject .arco-input-wrapper {
margin: 8px 0;
}
.icon_broadcast {
fill: #fff;
}
.img_broadcast {
position: absolute;
right: 20px;
bottom: 60px;
} }
/* Top Box (Tags) */
.top-box { .top-box {
position: absolute; position: absolute;
top: 10px; top: 10px;
left: 0;
right: 0;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
pointer-events: none;
} }
.top-box .arco-tag { .top-box .el-tag {
margin: 5px; margin: 4px;
pointer-events: auto;
} }
::v-deep .el-button.is-circle{ /* Control Bar Styles */
width: 32px; .control-bar {
height: 32px; position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.65);
backdrop-filter: blur(10px);
border-radius: 40px;
padding: 8px 24px;
display: flex;
align-items: center;
gap: 16px;
z-index: 20;
white-space: nowrap;
}
.control-btn {
background: transparent !important;
border: none !important;
color: #fff !important;
width: 40px !important;
height: 40px !important;
padding: 0 !important;
display: flex;
justify-content: center;
align-items: center;
transition: background 0.3s;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.15) !important;
border-radius: 50%;
}
.control-btn img {
width: 24px;
height: 24px;
filter: brightness(0) invert(1); /* Make black icons white */
}
.control-arrow {
margin-left: -12px;
margin-top: 10px;
cursor: pointer;
}
.hangup-btn {
background-color: #f56c6c !important;
border-color: #f56c6c !important;
color: #fff !important;
height: 36px;
padding: 0 20px;
}
.hangup-btn:hover {
background-color: #f78989 !important;
border-color: #f78989 !important;
}
/* Close Card Button */
.close-card-btn {
position: absolute;
top: 10px;
right: 10px;
color: #999;
z-index: 100;
}
.close-card-btn:hover {
color: #666;
background: transparent;
}
/* Misc */
.img_broadcast {
position: absolute;
right: 20px;
bottom: 80px; /* Adjusted to be above control bar */
width: 40px;
height: 40px;
}
::v-deep .el-button.is-circle {
/* Reset element plus styles if needed */
}
::v-deep .drs-handle {
width: 10px;
height: 10px;
background: #1890ff;
border: 2px solid #fff;
border-radius: 2px;
box-shadow: 0 0 0 1px rgba(0,0,0,0.2);
z-index: 1000;
pointer-events: auto;
} }
</style> </style>

View File

@ -1,55 +1,34 @@
<template> <template>
<div class="meeting-box"> <!-- 无人机拖动视频 -->
<ul class="meun"> <DraggerAble v-if="showVideo" v-model="showVideo" ref="RefEqripment"></DraggerAble>
<li class="item"> <!-- 新增音视频会议 -->
<span>会商</span> <AudioAndVoice v-model="showDailog" v-if="showDailog"></AudioAndVoice>
<span class="edg"></span>
</li>
</ul>
<div class="list-box">
<div class="tr">
<el-popover placement="bottom" :width="80" trigger="click">
<template #reference>
<el-button>新增</el-button>
</template>
<div class="lh30 f12 pointer" v-for="item in LIST_DATA" :key="item.value" @click="chooseItem(item)">
{{item.label}}
</div>
</el-popover>
</div>
<div class="list">
<!-- 调度台临时组 -->
<el-collapse v-model="activeName">
<el-collapse-item v-for="item in LIST_DATA_TREE" :key="item.value" :title="item.label" :name="item.label">
<ul>
<li class="lh30" v-for="(it,idx) in meetList" :key="idx" @click="joinMeeting(it)">{{ it.subject }}</li>
</ul>
</el-collapse-item>
</el-collapse>
</div>
</div>
<div class="cnt"></div>
</div>
<!-- 音视频会议 -->
<AudioAndVoice v-model="showDailog" v-if="showDailog" @save="saveData"></AudioAndVoice>
<!-- 音视频会议窗口 --> <!-- 音视频会议窗口 -->
<MeetingView v-model="openMeeting" v-if="openMeeting" ></MeetingView> <MeetingView v-model="openMeeting" v-if="openMeeting" ></MeetingView>
</template> </template>
<script setup> <script setup>
import { timeValidate } from '@/utils/tools'
import DraggerAble from './components/draggerAble.vue'
import useConfernceEvent from './components/js/useConfernceEvent'; import useConfernceEvent from './components/js/useConfernceEvent';
import { ElMessage,ElMessageBox,ElNotification } from "element-plus"; import { ElMessage,ElMessageBox,ElNotification } from "element-plus";
import useBaseDataModule from '@/components/Consultation/sdk/baseData';
import AudioAndVoice from './components/audioAndVoice.vue' import AudioAndVoice from './components/audioAndVoice.vue'
import MeetingView from './components/meetingView.vue' import MeetingView from './components/meetingView.vue'
import { computed , nextTick, onMounted, ref} from 'vue'; import { defineExpose , nextTick, onMounted, onUnmounted, defineEmits, ref} from 'vue';
import { useStore } from "vuex"; import { useStore } from "vuex";
const emit = defineEmits(['update']);
const modleType = ref('')
const store = useStore(); const store = useStore();
const showDailog = ref(false) const sdkBDModule = useBaseDataModule();
const baseInfo = localStorage.getItem('rhInfo') ? JSON.parse(localStorage.getItem('rhInfo')) : {};
const showVideo = ref(false)//
const showDailog = ref(false)//showDailog
const openMeeting = ref(false) // const openMeeting = ref(false) //
const activeName = ref('音视频会议')
const tempModalType = ref('') //
const jsonData = ref(''); const jsonData = ref('');
const loginStatusCallbackId = ref() //token
const RefEqripment = ref()
const meetList = ref([ const meetList = ref([
{ {
"basedata_id": "8180e3882a0c27f4d3ba998b3dc95c0d280d8e2e7a9d53e4ac36c7ade2c76653", "basedata_id": "8180e3882a0c27f4d3ba998b3dc95c0d280d8e2e7a9d53e4ac36c7ade2c76653",
@ -106,117 +85,71 @@ const meetList = ref([
} }
]) ])
// n - 10
// const handleTime = (n=10) =>{
const LIST_DATA = computed(() => { var currentDate = new Date();
return [ var preDate = new Date(currentDate.getTime() + n * 60 * 1000)
// let time = timeValidate(preDate);
{ return new Date(time).toISOString()
label: '音视频会议',
value: 8,
// component: AdvancedConference,
isOpenRoot: ref(false),
isLoading: ref(false),
},
//
{
label: '进入会议',
value: 9,
component: null,
isOpenRoot: ref(false),
isLoading: ref(false),
},
//
{
label: '快速会议',
value: 10,
component: null,
isOpenRoot: ref(false),
isLoading: ref(false),
},
];
});
const LIST_DATA_TREE = computed(() => {
return LIST_DATA.value.filter((v) => ![9, 10].includes(v.value));
});
function chooseItem (val) {
tempModalType.value = val.value;
switch(val.label){
case '音视频会议':
showDailog.value = true
break;
}
} }
function saveData (data){ //
switch(tempModalType.value){
case 8:
console.info('-----------音视频会议-----------');
conferenceActionSDK(data);
break;
}
}
/**
* create or update conference
*/
const conferenceActionSDK = async (record ) => { const conferenceActionSDK = async (record ) => {
//
const createRes = await lemon.conference.createConference({ const createRes = await lemon.conference.createConference({
subject: record.subject, // subject: record.glxsmc, //
type: 1, // 0=1= type: 1, // 0=1=
emergency_flag: 0, // 0 = 1 = emergency_flag: 0, // 0 = 1 =
duration: Number(record.duration), // () duration: 60, // ()
pre_alarm_time: record.alarm, // pre_alarm_time: 10, //
remark: record.remark, remark: '',
appointment: '2025-12-10T14:57:24Z', // start_date start_time UTC appointment: handleTime(), // start_date start_time UTC
members:record.members, members:[
{
alias:baseInfo.dispatcher_name,
basedata_id:baseInfo.basedata_id,
guid:baseInfo.user_guid,
number:baseInfo.user_id,
}
],//
}); });
console.log(createRes,'===========创建的会议');
if (createRes.result === 0) { if (createRes.result === 0) {
ElMessage.success(jsonData.value['data']['conference.book.result.ok']); ElMessage.success(jsonData.value['data']['conference.book.result.ok']);
fetchConferences() record.number = createRes.meeting.number;
emit('update',record);
enterConferenceByNumber(record) //
} else { } else {
ElMessage.error(jsonData.value['errorCode'][createRes?.result]); ElMessage.error(jsonData.value['errorCode'][createRes?.result]);
} }
}; };
// //
const joinMeeting = (it) =>{ const enterConferenceByNumber = (it) =>{
ElMessageBox.confirm('确定开始会议?','提示',{ openMeeting.value = true;
confirmButtonText:'确定', nextTick(()=>{
cancelButtonText:'取消', let params = {
type:'warning', "number": it.number,
}).then(res=>{ "nick": it.glxsmc,
openMeeting.value = true; "mute_status": 0,
nextTick(()=>{ "microphone_status": 1,
let params = { "camera_status": 1
"number": it.number, }
"nick": it.subject, lemon.conference.enterConferenceByNumber(params).then(res=> {
"mute_status": it.status, console.log(res,'加入会议......');
"microphone_status": 1, }).catch(err=> {
"camera_status": 1 console.log(err,' 加入会议失败......');
}
lemon.conference.enterConferenceByNumber(params).then(res=> {
console.log(res,'加入会议......');
}).catch(err=> {
console.log(err,' 加入会议失败......');
})
}) })
}).catch(()=>{
}) })
} }
// //
const fetchConferences = () =>{ const fetchConferences = (it) =>{
lemon.conference.fetchConferences().then(res=> { lemon.conference.fetchConferences().then(res=> {
console.log(res.conferenceList,'获取会议'); console.log(res.conferenceList,'获取会议');
meetList.value = res.conferenceList; meetList.value = res.conferenceList;
activeName.value = '音视频会议' let obj = meetList.value.find(v=>v.number == it.number);
// ? : ;
obj ? enterConferenceByNumber(it) : conferenceActionSDK(it) ;
}).catch(err=> {}) }).catch(err=> {})
} }
@ -225,18 +158,15 @@ const Init = () => {
let token = window.localStorage.getItem("rhToken"); let token = window.localStorage.getItem("rhToken");
if (!token) { if (!token) {
let userInfo = { let userInfo = {
username: "linzhigongan2", username: "sgxtcs",
password: "linzhigongan2", password: "123456",
realm: "puc.com", realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888" webpucUrl: "https://89.40.9.95:16888"
}; };
lemon.login.login(userInfo).then((esacpe) => { lemon.login.login(userInfo).then((esacpe) => {
token = esacpe.token; token = esacpe.token;
window.localStorage.setItem("rhToken", esacpe.token); window.localStorage.setItem("rhToken", esacpe.token);
getLoginAccountInfo(); listenerEvents()
fetchConferences()
//
useConfernceEvent()
}); });
} else { } else {
ConnectWebsocket(token); ConnectWebsocket(token);
@ -245,23 +175,33 @@ const Init = () => {
const ConnectWebsocket = (token) => { const ConnectWebsocket = (token) => {
lemon.login.reConnectWebsocket({ lemon.login.reConnectWebsocket({
username: "linzhigongan2", username: "sgxtcs",
realm: "puc.com", realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888", webpucUrl: "https://89.40.9.95:16888",
token: token token: token
}).then((resp) => { }).then((resp) => {
if(resp.result != 0){ if(resp.result != 0){
ElMessage.error(jsonData.value['errorCode'][resp.result]); localStorage.removeItem('rhToken')
exsit() localStorage.removeItem('user_basedata_id')
}else{ let messge = jsonData.value['errorCode'][resp.result] +',请重新刷新页面'
getLoginAccountInfo() ElMessage.error(messge);
fetchConferences() lemon.login.logout().then(res=> {}).catch(err=> {})
// }else{
useConfernceEvent() listenerEvents();
} }
}); });
}; };
//
const listenerEvents = () =>{
getLoginAccountInfo() //
useConfernceEvent()//
//
window.lemon.call.addMediaStream((call_id, stream, type) => {
console.log(call_id, stream, type,'=======无人机对讲机的监听时事件==');
});
}
const getLoginAccountInfo =() =>{ const getLoginAccountInfo =() =>{
lemon.login.getLoginAccountInfo().then(res => { lemon.login.getLoginAccountInfo().then(res => {
let info = JSON.stringify(res.account_info) let info = JSON.stringify(res.account_info)
@ -272,17 +212,31 @@ const getLoginAccountInfo =() =>{
}) })
} }
const exsit = () =>{ //
lemon.login.logout().then(res=> { const openInit = (it,type) =>{
modleType.value = type;
if(type == '会议'){
//
let into = it.number ? '确定开始会议?' : '没有找到会议,是否创建会议?'
ElMessageBox.confirm(into,'提示',{
confirmButtonText:'确定',
cancelButtonText:'取消',
type:'warning',
}).then(res=>{
// ? : ;
it.number ? fetchConferences(it) : conferenceActionSDK(it);
}).catch(()=>{ })
}).catch(err=> { }
}) if(['对讲机','无人机'].includes(type)){
showVideo.value = true;
nextTick(()=>{
RefEqripment.value.handleBtn(type)
})
}
} }
function changeCooll () {
}
onMounted(()=>{ onMounted(()=>{
jsonData.value = require('./components/zh_CN.json'); jsonData.value = require('./components/zh_CN.json');
@ -290,6 +244,13 @@ onMounted(()=>{
Init(); Init();
}) })
}); });
onUnmounted(()=>{
//
lemon.login.removeLoginStatusChangeListener(loginStatusCallbackId.value);
})
defineExpose({openInit});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,9 +1,9 @@
import { h } from 'vue'; import { h } from 'vue';
import { ElNotification} from "element-plus"; import { ElNotification} from "element-plus";
import { IconClose } from "element-plus" import { IconClose } from "element-plus"
import Content from '@/views/consultation/components/content.vue'; import Content from '@/components/Consultation/components/content.vue';
import Footer from '@/views/consultation/components/footer.vue'; import Footer from '@/components/Consultation/components/footer.vue';
import { formatShowNameFin } from '@/views/consultation/utils/format-show-name'; import { formatShowNameFin } from '@/components/Consultation/utils/format-show-name';
export default function handleCallingNotification(propsObj) { export default function handleCallingNotification(propsObj) {
const { callInfo, text } = propsObj; const { callInfo, text } = propsObj;

View File

@ -79,7 +79,7 @@ div(
<script lang="ts" setup> <script lang="ts" setup>
import tableColAvatar from '@/views/webPuc/org/components/tableColAvatarByNumType.vue'; import tableColAvatar from '@/views/webPuc/org/components/tableColAvatarByNumType.vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { formatShowNameFin } from '@/views/consultation/utils/format-show-name'; import { formatShowNameFin } from '@/components/Consultation/utils/format-show-name';
import { $t } from '@/locale'; import { $t } from '@/locale';
import { useGlobalStore } from '@/store'; import { useGlobalStore } from '@/store';
import { import {
@ -93,7 +93,7 @@ div(
CAMERA_STATUS_CLOSE, CAMERA_STATUS_CLOSE,
CONFERENCE_MEMBER_STATE_CALLING, CONFERENCE_MEMBER_STATE_CALLING,
PROHIBITION_STATUS_N, PROHIBITION_STATUS_N,
} from '@/views/consultation/sdk/conferenceControl'; } from '@/components/Consultation/sdk/conferenceControl';
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();

View File

@ -115,6 +115,7 @@ a-modal(
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
import { $t } from '@/locale'; import { $t } from '@/locale';
import useCallModule from '@/sdk/call'; import useCallModule from '@/sdk/call';
import useBaseDataModule from '@/components/Consultation/sdk/baseData';
import useConferenceControlModule, { import useConferenceControlModule, {
CONFERENCE_ROLE_NORMAL, CONFERENCE_ROLE_NORMAL,
CONFERENCE_ROLE_HOST, CONFERENCE_ROLE_HOST,
@ -126,8 +127,8 @@ a-modal(
CAMERA_STATUS_NO, CAMERA_STATUS_NO,
CAMERA_STATUS_OPEN, CAMERA_STATUS_OPEN,
CAMERA_STATUS_CLOSE, CAMERA_STATUS_CLOSE,
} from '@/views/consultation/sdk/conferenceControl'; } from '@/components/Consultation/sdk/conferenceControl';
import useConferencModule from '@/views/consultation/sdk/conferenceControl'; import useConferencModule from '@/components/Consultation/sdk/conferenceControl';
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
import UserItem from './components/UserItem.vue'; import UserItem from './components/UserItem.vue';
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -191,6 +192,7 @@ a-modal(
const CALL = useCallModule(); const CALL = useCallModule();
const useBDModule = useBaseDataModule();
const conferenceControlModule = useConferenceControlModule(); const conferenceControlModule = useConferenceControlModule();
const conferenceModule = useConferencModule(); const conferenceModule = useConferencModule();

View File

@ -32,7 +32,7 @@ export default function useCallModule() {
const makeVoiceCall = (record ) => { const makeVoiceCall = (record ) => {
if (call_id) return; if (call_id) return;
window.lemon.call.makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 })?.then((resp) => { window.lemon.call.makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 , duplex_flag:0})?.then((resp) => {
call_id = resp.call_id; call_id = resp.call_id;
}); });
}; };
@ -145,9 +145,7 @@ export default function useCallModule() {
* hangup call * hangup call
*/ */
const hangup = (id) => { const hangup = (id) => {
console.log(id,'=====挂断');
window.lemon.call.hangupCall({ call_id: id || call_id })?.then(() => { window.lemon.call.hangupCall({ call_id: id || call_id })?.then(() => {
console.log('00000000000=====挂断');
call_id = undefined; call_id = undefined;
window.calling_conference = undefined; window.calling_conference = undefined;
}) })

View File

@ -154,6 +154,10 @@ onMounted(() => {
emitter.on("showSquire", (obj) => { emitter.on("showSquire", (obj) => {
mapUtil.value.zdySquire(obj); mapUtil.value.zdySquire(obj);
}); });
// 展示气泡框
emitter.on("makerPopup", (obj) => {
mapUtil.value.makerPopup(obj);
});
// 绘制图形 - 回显区域 // 绘制图形 - 回显区域
emitter.on("drawShape", (res) => { emitter.on("drawShape", (res) => {
@ -288,6 +292,7 @@ onUnmounted(() => {
emitter.off("showPoint"); emitter.off("showPoint");
emitter.off("deletePointArea"); emitter.off("deletePointArea");
emitter.off("deletePointAreaOne"); emitter.off("deletePointAreaOne");
emitter.off("makerPopup");
emitter.off("drawShape"); emitter.off("drawShape");
emitter.off("echoPlane"); emitter.off("echoPlane");
emitter.off("removeEara"); emitter.off("removeEara");

View File

@ -167,6 +167,11 @@ onMounted(() => {
mapUtil.value.showPoint(obj); mapUtil.value.showPoint(obj);
}); });
// 展示气泡框
emitter.on("makerPopup", (obj) => {
mapUtil.value.makerPopup(obj);
});
// 清除覆盖物 // 清除覆盖物
emitter.on("deletePointArea", (res) => { emitter.on("deletePointArea", (res) => {
// 只清除与当前地图相关的覆盖物 // 只清除与当前地图相关的覆盖物
@ -325,6 +330,7 @@ onUnmounted(() => {
emitter.off("setMapCenter"); emitter.off("setMapCenter");
emitter.off("addPointArea"); emitter.off("addPointArea");
emitter.off("showPoint"); emitter.off("showPoint");
emitter.off("makerPopup");
emitter.off("deletePointArea"); emitter.off("deletePointArea");
emitter.off("deletePointAreaOne"); emitter.off("deletePointAreaOne");
emitter.off("drawShape"); emitter.off("drawShape");

View File

@ -1,4 +1,5 @@
import emitter from "@/utils/eventBus.js"; import emitter from "@/utils/eventBus.js";
import { ElContainer } from "element-plus";
export function MapUtil(map) { export function MapUtil(map) {
let _that = this; let _that = this;
@ -84,6 +85,7 @@ export function MapUtil(map) {
el.style.width = size ? size : "25px"; el.style.width = size ? size : "25px";
if (flag.includes('jczMap_')) el.style.width = '45px'; if (flag.includes('jczMap_')) el.style.width = '45px';
if (showTitle) _that.makerShowTitle(item, [item.jd, item.wd], flag, '', offset) //展示标题 if (showTitle) _that.makerShowTitle(item, [item.jd, item.wd], flag, '', offset) //展示标题
// if (flag == 'hm') _that.makerPopup({data:item,flag:'hm_pop',type:'Custom'}) //展示气泡框
// 确保坐标格式正确,使用对象格式传递坐标 // 确保坐标格式正确,使用对象格式传递坐标
const marker = map.Marker(el, { lng: item.jd, lat: item.wd }, { anchor: 'bottom', offset: [0, 0] }) const marker = map.Marker(el, { lng: item.jd, lat: item.wd }, { anchor: 'bottom', offset: [0, 0] })
el.addEventListener("click", () => { el.addEventListener("click", () => {
@ -141,23 +143,76 @@ export function MapUtil(map) {
}); });
} }
// 展示气泡框
MapUtil.prototype.makerPopup = (val)=>{
let { data,flag,type = 'Dark'} = val
// Dark Light Custom
let marker;
if(!_that._self[flag]) _that._self[flag] = [];
if(type == 'Dark' || type == 'Light') {
let list = zdyContent(flag,data);// 默认的样式
marker = map.createPopup([data.jd,data.wd],{
style:style, // 气泡框样式:
data:list,
title:data.ssbm,
closeButton:false,
anchor:'bottom',
pixelOffset:[0,-50]
})
}else {
marker = map.createPopup([data.jd,data.wd],{
style:'Custom', // // 自定义样式
attrs:{
class:'popupCustom'
},
container: zdyContentHtml(flag,data),
closeButton:false,
anchor:'bottom',
pixelOffset:[0,-30]
})
}
_that._self[flag].push(marker)
}
// 弹窗自定义默认内容
function zdyContent(flag,item){
switch (flag) {
case 'hm':
return [
{ label:'林安码线索数量',value:item.lamsx },
{ label:'布控预警数量',value:item.bkyj },
{ label:'红色预警数量',value:item.hsyj },
{ label:'信息采集数量',value:item.xxcjsl },
]
}
}
// 弹窗自定义标签内容
function zdyContentHtml(flag,item){
let html = ''
switch (flag) {
case 'hm_pop':
const list = [
{ jb: "一级",sl:'5',ypl:'100%' },
{ jb: "二级",sl:'5',ypl:'100%' },
{ jb: "三级",sl:'3',ypl:'60%' },
{ jb: "四级",sl:'0',ypl:'20%' }
];
html = `
<div class="popupCustomBox">
<div class="popupCustomTitle_title">
<span>${item.ssbm}</span>
<span>今日警情${item.jrzs || 0}</span>
</div>
<ul>
<li class="popupCustomTitle_li"><span>级别</span> <span>数量</span> <span>研判率</span> </li>
${item.jqjb.map(it => `<li class="popupCustomTitle_li"><span>${it.jbmc}</span> <span>${it.jrsl}</span> <span>${it.ypbl}</span></li>`).join('')}
</ul>
</div>
`
break;
}
return html;
}
// 信息框展示 // 信息框展示
MapUtil.prototype.makerShowTitle = (item, points, flag, text, offset) => { MapUtil.prototype.makerShowTitle = (item, points, flag, text, offset) => {
@ -174,6 +229,7 @@ export function MapUtil(map) {
// 设置样式 // 设置样式
const el = document.createElement('div'); const el = document.createElement('div');
if (flag == 'hm') { if (flag == 'hm') {
textTitle = item.ssbm;
// 直接设置元素样式属性,避免对象赋值的兼容性问题 // 直接设置元素样式属性,避免对象赋值的兼容性问题
el.style.fontSize = '12px'; el.style.fontSize = '12px';
el.style.color = '#ffffffff'; el.style.color = '#ffffffff';
@ -565,10 +621,6 @@ export function MapUtil(map) {
_that._self[flag].push(line) _that._self[flag].push(line)
} }
/** /**
* 回显平面- 圆 - 多边形 - 矩形 * 回显平面- 圆 - 多边形 - 矩形
* @param {*} type 回显形状 * @param {*} type 回显形状
@ -755,7 +807,7 @@ export function MapUtil(map) {
// 移除边界 // 移除边界
MapUtil.prototype.createBoundarys = (res) => { MapUtil.prototype.createBoundarys = (res) => {
let { data, color, fillColor, borderColor, label, text, labelPosition } = res let { data, color, fillColor, borderColor, label, text, labelPosition, outLineWidth } = res
if (!data) return false; if (!data) return false;
// 使用传入的颜色参数,如果没有则使用默认值 // 使用传入的颜色参数,如果没有则使用默认值
const fillColorValue = fillColor || 'rgba(27, 205, 211, 0.3)'; const fillColorValue = fillColor || 'rgba(27, 205, 211, 0.3)';
@ -765,7 +817,7 @@ export function MapUtil(map) {
const polygon = map.createPolygon(data, { const polygon = map.createPolygon(data, {
color: fillColorValue, color: fillColorValue,
outLineColor: borderColorValue, outLineColor: borderColorValue,
outLineWidth: 1, outLineWidth: outLineWidth || 1,
highlightColor: highlightColorValue, highlightColor: highlightColorValue,
type: 'solid', type: 'solid',
labelOption: { labelOption: {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="form-item-box" :style="{ width: width }"> <div class="form-item-box" :style="{ width: width }">
<el-checkbox-group v-model="modelValue" @change="handleCheckAllChange"> <el-checkbox-group :model-value="localValue" @change="handleCheckAllChange">
<el-checkbox <el-checkbox
v-for="item in checkList" v-for="item in checkList"
:key="item.value" :key="item.value"
@ -34,15 +34,21 @@ const props = defineProps({
type: String type: String
} }
}); });
const localValue = ref(props.modelValue);
watch( watch(
() => props.modelValue, () => props.modelValue,
(val) => { (val) => {
localValue.value = val;
console.log(val, "val"); console.log(val, "val");
}, },
{ deep: true } { deep: true }
); );
const emits = defineEmits(["update:modelValue"]); const emits = defineEmits(["update:modelValue"]);
const handleCheckAllChange = (e) => { const handleCheckAllChange = (e) => {
localValue.value = e;
emits("update:modelValue", e); emits("update:modelValue", e);
}; };
</script> </script>

View File

@ -130,7 +130,7 @@ const props = defineProps({
default: 180 default: 180
}, },
tableHeight: { tableHeight: {
type: Number type: Number || String,
}, },
isScroll: { isScroll: {
type: Number, type: Number,
@ -287,27 +287,56 @@ const rowcontextmenuHland = (row, column, e) => {
}; };
const timer = ref(null); const timer = ref(null);
const isCloned = ref(false);
const originalBodyHeight = ref(0);
// 鼠标进入 // 鼠标进入
const clearnScroll = () => { const clearnScroll = () => {
clearInterval(timer.value); clearInterval(timer.value);
timer.value = null; timer.value = null;
}; };
watch(() => props.tableData, () => {
nextTick(() => {
if (props.isScroll) createScroll();
})
},{deep:true});
// 鼠标离开 // 鼠标离开
const createScroll = () => { const createScroll = () => {
clearnScroll(); clearnScroll();
// 拿到table nextTick(() => {
const tabel = multipleTableRef.value.layout.table.refs; const refsPath = multipleTableRef.value?.$refs || multipleTableRef.value?.layout?.table?.refs;
// 拿到可以滚动的元素 const scrollEl = refsPath?.bodyWrapper || multipleTableRef.value?.$el?.querySelector('.el-table__body-wrapper');
const tableWrapper = tabel.bodyWrapper.firstElementChild.firstElementChild; const tableEl = scrollEl?.querySelector('table') || multipleTableRef.value?.$el?.querySelector('.el-table__body-wrapper table');
if (props.isScroll) { const bodyEl = tableEl?.tBodies?.[0];
timer.value = setInterval(() => { if (!props.isScroll || !scrollEl || !tableEl || !bodyEl) return;
tableWrapper.scrollTop += 1; if (!props.tableHeight) {
//判断滚动到底部,设置为0(可视高度+距离顶部 = 整个高度) const fixedH = scrollEl.clientHeight || multipleTableRef.value?.$el?.clientHeight || 0;
if ( tableWrapper.clientHeight + tableWrapper.scrollTop == tableWrapper.scrollHeight) { if (fixedH > 0) {
tableWrapper.scrollTop = 0; scrollEl.style.height = fixedH + 'px';
scrollEl.style.overflowY = 'auto';
} }
}, 100); }
} originalBodyHeight.value = bodyEl.offsetHeight;
const oldClone = tableEl.querySelector('tbody[data-clone="true"]');
if (oldClone) {
tableEl.removeChild(oldClone);
isCloned.value = false;
}
if (!isCloned.value) {
const clone = bodyEl.cloneNode(true);
clone.setAttribute('data-clone', 'true');
tableEl.appendChild(clone);
isCloned.value = true;
}
const target = scrollEl.firstElementChild?.firstElementChild || scrollEl;
timer.value = setInterval(() => {
target.scrollTop += 1;
if (target.scrollTop >= originalBodyHeight.value) {
target.scrollTop -= originalBodyHeight.value;
}
}, 20);
});
}; };
// 滚动-触底加载 // 滚动-触底加载
@ -371,3 +400,9 @@ onUnmounted(() => {
white-space: nowrap; white-space: nowrap;
} }
</style> </style>
watch(() => props.isScroll, (val) => {
nextTick(() => {
if (val) createScroll();
else clearnScroll();
});
},{immediate:true});

View File

@ -3,13 +3,13 @@
<el-form-item v-for="(item, idx) in props.formList" :style="item.width && { width: item.width }" :prop="item.prop" :label="item.label" :label-width="item.labelWidth" :key="idx"> <el-form-item v-for="(item, idx) in props.formList" :style="item.width && { width: item.width }" :prop="item.prop" :label="item.label" :label-width="item.labelWidth" :key="idx">
<!-- input表单 input--> <!-- input表单 input-->
<MOSTY.Other v-if="item.type == 'input'" width="100%" clearable v-model="listQuery[item.prop]" :placeholder="`请输入${item.label}`" :disabled="item.disabled" :readonly="item.readonly" /> <MOSTY.Other v-if="item.type == 'input'" width="100%" clearable v-model="listQuery[item.prop]" :placeholder="`请输入${item.label}`" :disabled="item.disabled" :readonly="item.readonly" @blur="inputBlur($event,item)" />
<el-input v-model="listQuery[item.prop]" v-else-if="item.type == 'textarea'" type="textarea" :rows="item.rows || 3" :placeholder="`请输入${item.label}`" :disabled="item.disabled" /> <el-input v-model="listQuery[item.prop]" v-else-if="item.type == 'textarea'" type="textarea" :rows="item.rows || 3" :placeholder="`请输入${item.label}`" :disabled="item.disabled" @blur="inputBlur($event,item)"/>
<!-- 数值 inputNumber--> <!-- 数值 inputNumber-->
<el-input type="number" v-model="listQuery[item.prop]" v-else-if="item.type == 'inputNumber'" :placeholder="`请输入${item.label}`" :disabled="item.disabled" /> <el-input type="number" v-model="listQuery[item.prop]" v-else-if="item.type == 'inputNumber'" :placeholder="`请输入${item.label}`" :disabled="item.disabled" @blur="inputBlur($event,item)"/>
<!-- 数值 number--> <!-- 数值 number-->
<el-input-number v-model="listQuery[item.prop]" v-else-if="item.type == 'number'" style="width: 100%" :min="item.min || 0" :max="item.max || 1000" :disabled="item.disabled" /> <el-input-number v-model="listQuery[item.prop]" v-else-if="item.type == 'number'" :step="item.step || 1" style="width: 100%" :min="item.min || 0" :max="item.max || 1000" :disabled="item.disabled" />
<!--选择 select--> <!--选择 select-->
<MOSTY.Select v-else-if="item.type == 'select'" filterable :multiple="item.multiple" v-model="listQuery[item.prop]" :dictEnum="item.options" width="100%" clearable :placeholder="`请选择${item.label}`" :disabled="item.disabled" /> <MOSTY.Select v-else-if="item.type == 'select'" filterable :multiple="item.multiple" v-model="listQuery[item.prop]" :dictEnum="item.options" width="100%" clearable :placeholder="`请选择${item.label}`" :disabled="item.disabled" />
@ -77,7 +77,7 @@ const props = defineProps({
}); });
const elform = ref(); const elform = ref();
const listQuery = ref({}); const listQuery = ref({});
const emits = defineEmits(["update:modelValue"]); const emits = defineEmits(["update:modelValue", "blur"]);
// 提交 // 提交
const submit = (resfun) => { const submit = (resfun) => {
elform.value.validate((valid) => { elform.value.validate((valid) => {
@ -101,7 +101,12 @@ const reset = () => {
// 修改这里的watch逻辑避免无限循环 // 修改这里的watch逻辑避免无限循环
let isUpdatingFromProps = false; let isUpdatingFromProps = false;
const inputBlur = (e,item) => {
if(typeof item?.blur == 'function') {
item.blur();
}
// emits('blur', e, item);
}
watch(() => listQuery.value, (newVal) => { watch(() => listQuery.value, (newVal) => {
if (newVal && !isUpdatingFromProps) { if (newVal && !isUpdatingFromProps) {
emits("update:modelValue", newVal); emits("update:modelValue", newVal);

View File

@ -68,7 +68,7 @@ const props = defineProps({
default: 180 default: 180
}, },
tableHeight: { tableHeight: {
type: Number || String type: [Number, String]
}, },
treePros: { treePros: {
type: Object, type: Object,

View File

@ -132,10 +132,13 @@
:options="getOptions[item.prop]" :options="getOptions[item.prop]"
:placeholder="item.placeholder" :placeholder="item.placeholder"
/> />
<div v-else-if="item.showType === 'defaultSlot'"> <div v-if="item.showType === 'Slot'">
<slot :name="item.prop"></slot>
</div>
<div v-if="item.showType === 'defaultSlot'">
<slot name="defaultSlot"></slot> <slot name="defaultSlot"></slot>
</div> </div>
<div v-else-if="item.showType === 'nameSlot'"> <div v-if="item.showType === 'nameSlot'">
<slot name="nameSlot"></slot> <slot name="nameSlot"></slot>
</div> </div>
</div> </div>
@ -472,8 +475,8 @@ const reset = () => {
getArr.forEach((item) => { getArr.forEach((item) => {
searchObj[item.prop] = item.defaultVal; searchObj[item.prop] = item.defaultVal;
}); });
emit("reset", true);
emit("submit", searchObj); emit("submit", searchObj);
emit("reset", false);
}; };
watchEffect(() => { watchEffect(() => {
loadingPage.value = true; loadingPage.value = true;

View File

@ -8,22 +8,22 @@
:key="index">{{ item.nodeName }}</el-checkbox> :key="index">{{ item.nodeName }}</el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</div> </div>
<div> <el-button type="success" :icon="Plus" @click="newAdditions" v-if="optional"/></div> <div> <el-button type="success" :icon="Plus" @click="newAdditions" v-if="optional" /></div>
</div> </div>
<div v-if="optional" class="container-box"> <div v-if="optional" class="container-box">
<!-- <div v-if="flwsNode.flwsUserNode?.role.length == 0"> --> <!-- <div v-if="flwsNode.flwsUserNode?.role.length == 0"> -->
<div class="row" v-for="(item, index) in nodeData" :key="index"> <div class="row" v-for="(item, index) in nodeData" :key="index">
<MOSTY.Department filterable v-model="item.deptId" width="100%" <MOSTY.Department filterable v-model="item.deptId" width="100%"
@getDepValue="(obj) => changePostList(index, obj)" clearable placeholder="请选择所属部门" /> @getDepValue="(obj) => changePostList(index, obj)" clearable placeholder="请选择所属部门" />
<el-select class="select-user" v-model="item.userId" filterable placeholder="选择审批人" <el-select class="select-user" v-model="item.userId" filterable placeholder="选择审批人"
@change="changeUser(index)"> @change="changeUser(index)">
<el-option v-for="item in item.listData" :key="item.id" :label="item.userName" :value="item.id" /> <el-option v-for="item in item.listData" :key="item.id" :label="item.userName" :value="item.id" />
</el-select> </el-select>
<div> <div>
<el-button type="danger" @click="newDelitions(index)">删除</el-button> <el-button type="danger" @click="newDelitions(index)">删除</el-button>
</div> </div>
</div> </div>
<!-- </div> --> <!-- </div> -->
</div> </div>
<div class="container-box" v-else> <div class="container-box" v-else>
<div v-for="(item, index) in userList" :key="item.id"> <div v-for="(item, index) in userList" :key="item.id">
@ -59,7 +59,7 @@
<div v-if="showNode && showModel"> <div v-if="showNode && showModel">
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="close">取消</el-button> <el-button @click="close">取消</el-button>
@ -246,7 +246,7 @@ const qcckPostList = async () => {
const item = checkListData.value[i].userList[j] const item = checkListData.value[i].userList[j]
if (item.checkList && item.checkList.length > 0) { if (item.checkList && item.checkList.length > 0) {
data[checkListData.value[i].nodeId] = { data[checkListData.value[i].nodeId] = {
users: transformData(checkListData.value[i]) users: transformData(checkListData.value[i])
} }
} else { } else {
listError.push(checkListData.value[i].nodeName) listError.push(checkListData.value[i].nodeName)
@ -341,7 +341,7 @@ const queryModel = async () => {
) )
const orgId = getItem('deptId')[0].fzOrgId const orgId = getItem('deptId')[0].fzOrgId
if (!orgId) { if (!orgId) {
proxy.$message({ type: "error", message: "查询模型失败,请重试" }) proxy.$message({ type: "error", message: "查询模型失败,请重试" })
return return
} }
if (eventNode) { if (eventNode) {
@ -358,7 +358,7 @@ const queryModel = async () => {
loading.value = false loading.value = false
} }
} }
const optional=ref(false) const optional = ref(false)
// 处理事件节点 // 处理事件节点
const handleEventNode = async (eventNode, orgId) => { const handleEventNode = async (eventNode, orgId) => {
const nodeExtension = JSON.parse(eventNode.nodeExtension) const nodeExtension = JSON.parse(eventNode.nodeExtension)
@ -376,13 +376,13 @@ const handleEventNode = async (eventNode, orgId) => {
orgData = await queryListByEntity({ id: orgId }) orgData = await queryListByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'parent') { } else if (nodeExtension.flwsUserNode.orgType == 'parent') {
console.log(2); console.log(2);
orgData = await querysingleByEntity({ id: orgId }) orgData = await querysingleByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'parents') { } else if (nodeExtension.flwsUserNode.orgType == 'parents') {
console.log(3); console.log(3);
orgData = await queryUporgsByEntity({ id: orgId }) orgData = await queryUporgsByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'appoint') { } else if (nodeExtension.flwsUserNode.orgType == 'appoint') {
console.log(4); console.log(4);
// orgData = await queryUporgsByEntity({ orgcode: orgId }) // orgData = await queryUporgsByEntity({ orgcode: orgId })
console.log(orgData); console.log(orgData);
@ -405,7 +405,7 @@ const handleEventNode = async (eventNode, orgId) => {
userList: userRes.rows[0] userList: userRes.rows[0]
}] }]
} else if (nodeExtension.flwsUserNode.orgType == 'optional') { } else if (nodeExtension.flwsUserNode.orgType == 'optional') {
optional.value=true optional.value = true
} else { } else {
const parentids = orgData.rows.map(item => item.parentid) const parentids = orgData.rows.map(item => item.parentid)
@ -514,37 +514,37 @@ const handleNormalNodes = async (resData, sequenceNode, orgId) => {
}) })
} }
function filterUsersWithOrgInfo(orgsData, checkList) { function filterUsersWithOrgInfo(orgsData, checkList) {
const result = []; const result = [];
// 如果没有数据或检查列表为空,返回空数组
if (!orgsData || !Array.isArray(orgsData) || !checkList || checkList.length === 0) {
return result;
}
// 将checkList转换为Set以提高查找效率
const checkSet = new Set(checkList);
// 遍历所有组织
for (const org of orgsData) {
// 检查组织是否有用户数据
if (org.users && Array.isArray(org.users)) {
// 筛选匹配的用户
for (const user of org.users) {
if (checkSet.has(user.userid)) {
// 创建带组织信息的用户对象
const userWithOrgInfo = {
...user, // 保留所有原始用户属性
orgCode: org.code, // 添加组织code
orgName: org.name, // 添加组织name
orgId: org.id // 添加组织id
};
result.push(userWithOrgInfo);
}
}
}
}
// 如果没有数据或检查列表为空,返回空数组
if (!orgsData || !Array.isArray(orgsData) || !checkList || checkList.length === 0) {
return result; return result;
}
// 将checkList转换为Set以提高查找效率
const checkSet = new Set(checkList);
// 遍历所有组织
for (const org of orgsData) {
// 检查组织是否有用户数据
if (org.users && Array.isArray(org.users)) {
// 筛选匹配的用户
for (const user of org.users) {
if (checkSet.has(user.userid)) {
// 创建带组织信息的用户对象
const userWithOrgInfo = {
...user, // 保留所有原始用户属性
orgCode: org.code, // 添加组织code
orgName: org.name, // 添加组织name
orgId: org.id // 添加组织id
};
result.push(userWithOrgInfo);
}
}
}
}
return result;
} }
//发消息 //发消息
const sendMessage = (gzlid) => { const sendMessage = (gzlid) => {
@ -552,11 +552,11 @@ const sendMessage = (gzlid) => {
let userList = [] let userList = []
for (let i = 0; i < checkListData.value.length; i++) { for (let i = 0; i < checkListData.value.length; i++) {
letDataCheck = [...letDataCheck, ...checkListData.value[i].checkList] letDataCheck = [...letDataCheck, ...checkListData.value[i].checkList]
userList.push(checkListData.value[i].userList) userList.push(checkListData.value[i].userList)
} }
const bkshrSfzh = filterUsersWithOrgInfo(userList, letDataCheck).map(item => { const bkshrSfzh = filterUsersWithOrgInfo(userList, letDataCheck).map(item => {
return { return {
bkshrXm: item.username, bkshrXm: item.username,
bkshrSfzh: item.userid, bkshrSfzh: item.userid,
bkshrSsbmmc: item.orgName, bkshrSsbmmc: item.orgName,
@ -586,6 +586,11 @@ const sendMessage = (gzlid) => {
console.log(res); console.log(res);
}) })
break; break;
case 'YPSH':
qcckPost(promes, '/mosty-gsxt/ypbg/sjzl/updateBkgzl').then(res => {
console.log(res);
})
break;
} }
} }
@ -603,7 +608,7 @@ const close = () => {
orgData: {}, orgData: {},
} }
] ]
optional.value=false optional.value = false
emit('update:modelValue', false) emit('update:modelValue', false)
} }
</script> </script>

View File

@ -91,7 +91,6 @@ const qcckGetCount = () => {
} else { } else {
setCookie('JSRSSIONID', res.substring(10, res.length)) setCookie('JSRSSIONID', res.substring(10, res.length))
} }
qcckGetList() qcckGetList()
}) })
} else { qcckGetList() } } else { qcckGetList() }

View File

@ -0,0 +1,147 @@
<template>
<el-input :style="{ width: inputWidth }" class="mosty-select" readonly v-model="inputName" :disabled="props.disabled" clearable
@click="xgfClick" @clear="clear">
<!-- <template #append>
<el-button title="" class='cursor' :disabled="props.disabled" @click="xgfClick">选择</el-button>
</template> -->
</el-input>
<!-- 相关方 -->
<ChooseUser id="most-user" v-model="isShowDialog" :Single="props.Single" :deptId="props.deptId" :data="userData"
@choosedUsers="userChange"></ChooseUser>
</template>
<script setup>
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
import { ref, defineProps, defineEmits, onMounted, watch, defineExpose, computed } from 'vue'
const props = defineProps({
dataList: {
type: Array,
default: () => ([])
},
disabled: {
type: Boolean,
default: false
},
// relatedid: {
// type: String,
// default: ''
// },
/** 是否单选 默认多选 */
Single: {
type: Boolean,
default: true
},
ids: {
type: String,
default: ''
},
cName: {
type: String,
default: ''
},
stlyrylx: {
type: String,
default: '01'
},
/** 父级部门 (即只选该部门下的单位),
* 如果没有"deptId"会只能选当前登录人的部门,(但是:登录人是安全科可以选所有部门) */
deptId: {
type: String,
},
// xgflx: {
// type: String,
// default: '09,10,15'
// },
/** 输入框宽度 */
width: [String, Number]
})
const emit = defineEmits(['change', 'update:ids', 'update:cName', 'clear'])
const isShowDialog = ref(false)
const xgfMan = ref('')
const xgfRyId = ref('')
const inputName = ref('')
const inputWidth = computed(() => {
if (props.width) {
if (typeof props.width === 'string') {
if (props.width.includes('px')) return props.width
if (!isNaN(Number(props.width))) return props.width + 'px'
return props.width
} else if (typeof props.width === 'number') {
return `${props.width}px`
}
}
})
const userChange = (val) => {
val = Array.isArray(val) ? val : []
val = val.filter(item => {
return !!item
})
const cName = val.map(item => {
// if (item.mobile) {
// return item.userName + '' + item.mobile + ''
// } else {
// }
return item.userName
}).toString();
const ids = val.map(item => {
return item.id
}).toString();
emit('update:ids', ids || '')
emit('update:cName', cName || '')
emit('change', val || {})
}
const xgfClick = () => {
if (props.disabled) return
isShowDialog.value = true
}
const clear = () => {
// xgfMan.value = ''
// xgfRyId.value = ''
emit('update:ids', '')
emit('update:cName', '')
emit('change', {})
}
const closeDialog = (val) => {
isShowDialog.value = val
}
// 数组回显
const userData = computed(() => {
if (!props.ids || !props.ids.length) return []
if (props.Single) return props.ids
if (typeof props.ids === 'string') return props.ids.split(',')
return []
})
// input回显
watch(() => props.cName, (val) => {
inputName.value = val
}, { immediate: true })
onMounted(() => {
// console.log('2332===', props.xgflx);
});
defineExpose({
clear
});
</script>
<style scoped lang="scss">
.mosty-select {
width: 374px;
}
::v-deep .el-form {
margin-top: 0;
margin-bottom: 10px;
}
// ::v-deep #xgfandzzjgry .el-button + .el-button{
// margin-left: 10px;
// }</style>
::v-depp .treeBox {
margin-top: 10px;
}
<style></style>

View File

@ -14,7 +14,7 @@
<script setup> <script setup>
import { reactive, ref, onMounted, watch } from "vue"; import { reactive, ref, onMounted, watch } from "vue";
import { sendFqzl, ZdrfjSendFqzl ,qbcjSendFqzl} from '@/api/commit' import { sendFqzl, ZdrfjSendFqzl ,qbcjSendFqzl, wshsSendFqzl} from '@/api/commit'
import { getItem } from '@/utils/storage' import { getItem } from '@/utils/storage'
import * as MOSTY from "@/components/MyComponents/index"; import * as MOSTY from "@/components/MyComponents/index";
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue" import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue"
@ -86,6 +86,8 @@ const getsendFqzl = () => {
break; break;
case 'qbcj': case 'qbcj':
res = await qbcjSendFqzl(promes) res = await qbcjSendFqzl(promes)
case 'meeting': // 网上会议室
res = await wshsSendFqzl(promes)
break; break;
} }
const str = JSON.parse(res) const str = JSON.parse(res)

View File

@ -52,13 +52,14 @@ import installFilter from "@/filters";
import mitt from "mitt"; import mitt from "mitt";
import { resetForm } from "@/utils/validate"; import { resetForm } from "@/utils/validate";
import { getDict, setCascader } from '@/utils/dict'; import { getDict, setCascader, getFzDict } from '@/utils/dict';
import axios from "axios"; import axios from "axios";
// import fzui from 'fzui-fengqun-vue' // import fzui from 'fzui-fengqun-vue'
//挂载全局方法 //挂载全局方法
app.config.globalProperties.resetForm = resetForm; app.config.globalProperties.resetForm = resetForm;
app.config.globalProperties.$dict = getDict; //字典公共函数 app.config.globalProperties.$dict = getDict; //字典公共函数
app.config.globalProperties.$fzdict = getFzDict; //字典公共函数
app.config.globalProperties.$message = ELMessage; //element提示组件 app.config.globalProperties.$message = ELMessage; //element提示组件
app.config.globalProperties.$set = setCascader; //设置级联选择器回显 app.config.globalProperties.$set = setCascader; //设置级联选择器回显
app.config.globalProperties.mittBus = new mitt(); //配置事件总线 app.config.globalProperties.mittBus = new mitt(); //配置事件总线

View File

@ -21,9 +21,9 @@ router.beforeEach(async (to, from, next) => {
// 存在 token ,进入主页 // 存在 token ,进入主页
// if (store.state.user.token) { // if (store.state.user.token) {
// 快捷访问 // 快捷访问
console.log(store.getters.token); // console.log(store.getters.token);
if (store.getters.token) { if (store.getters.token) {
console.log("路由1"); // console.log("路由1");
// 判断用户资料是否获取 // 判断用户资料是否获取
// 若不存在用户信息,则需要获取用户信息 // 若不存在用户信息,则需要获取用户信息
@ -32,39 +32,39 @@ router.beforeEach(async (to, from, next) => {
// 添加完动态路由之后,需要在进行一次主动跳转 // 添加完动态路由之后,需要在进行一次主动跳转
const afterMenuList = getItem('menusPermission'); const afterMenuList = getItem('menusPermission');
// 处理用户权限,筛选出需要添加的权限 // 处理用户权限,筛选出需要添加的权限
console.log(store.state.permission.routes); // console.log(store.state.permission.routes);
if (store.state.permission.routes.length === 0) { if (store.state.permission.routes.length === 0) {
const filterRoutes = await store.dispatch('permission/filterRoutes', afterMenuList) const filterRoutes = await store.dispatch('permission/filterRoutes', afterMenuList)
filterRoutes.forEach(item => { filterRoutes.forEach(item => {
router.addRoute(item) router.addRoute(item)
}) })
console.log("已添加动态路由"); // console.log("已添加动态路由");
next({ next({
...to, ...to,
replace: true replace: true
}) })
} else { } else {
console.log('已存在路由'); // console.log('已存在路由');
next() next()
} }
// 利用 addRoute 循环添加 // 利用 addRoute 循环添加
} else { } else {
// 没有token的情况下可以进入白名单 // 没有token的情况下可以进入白名单
if (whiteList.indexOf(to.path) > -1) { if (whiteList.indexOf(to.path) > -1) {
console.log("路由2"); // console.log("路由2");
next() next()
} else { } else {
const cookie = getCookie("clientKey"); const cookie = getCookie("clientKey");
if (cookie) { if (cookie) {
console.log("路由3"); // console.log("路由3");
next(`/zeroTrust_login`) next(`/zeroTrust_login`)
} else { } else {
console.log("路由4"); // console.log("路由4");
const isOatuh = getItem('isOatuh') const isOatuh = getItem('isOatuh')
// 没有token的情况下可以进入白名单 // 没有token的情况下可以进入白名单
if (isOatuh) { if (isOatuh) {
console.log("路由5"); // console.log("路由5");
const idEntityCard = getItem('idEntityCard') const idEntityCard = getItem('idEntityCard')
next(`/oatuh_login?token=${Base64.encode(idEntityCard)}`) next(`/oatuh_login?token=${Base64.encode(idEntityCard)}`)
} else { } else {

View File

@ -117,3 +117,4 @@ export function IdCard(IdCard, type) {
} }
return user return user
} }

View File

@ -1,4 +1,9 @@
const url = "ws://80.155.0.82:8006/mosty-api/mosty-websocket/socket/"; //线上 // let url = "ws://80.155.0.82:8006/mosty-api/mosty-websocket/socket/"; //线上
let url = "ws://155.240.22.30:2109/mosty-api/mosty-websocket/socket/"; //线上
if(process.env.NODE_ENV === 'development') {
url = "ws://47.108.232.77:9537/mosty-api/mosty-websocket/socket/"; //本地
}
import { import {
getItem getItem
} from "@/utils/storage"; } from "@/utils/storage";

View File

@ -23,122 +23,6 @@ export const privateRoutes = [
* 公开路由表 * 公开路由表
*/ */
export const publicRoutes = [ export const publicRoutes = [
{
path: "/systemConfig",
component: layout,
name: "systemConfigModel",
redirect: "/dict/index",
meta: {
title: "系统管理",
icon: "article"
},
children: [
{
path: "/user/department-ist",
name: "departmentList",
component: () => import("@/views/backOfficeSystem/systemConfig/department-list/index"),
meta: {
title: "部门管理",
icon: "article-ranking"
}
},
{
path: "/user/userList",
name: "userList",
component: () =>
import("@/views/backOfficeSystem/systemConfig/user-list/index"),
meta: {
title: "用户管理",
icon: "article-ranking"
}
},
{
path: "/user/role",
name: "userRoleIndex",
component: () =>
import("@/views/backOfficeSystem/systemConfig/role-list/index"),
meta: {
title: "角色列表",
icon: "article-ranking"
}
},
{
path: "/user/menuList",
name: "menuList",
component: () =>
import("@/views/backOfficeSystem/systemConfig/menu-list/index"),
meta: {
title: "菜单管理",
icon: "article-ranking"
}
},
{
path: "/dict/detail",
name: "dictDetail",
component: () =>
import("@/views/backOfficeSystem/systemConfig/dict/detail"),
meta: {
title: "字典数据"
}
},
{
path: "/dict/index",
name: "dictIndex",
component: () =>
import("@/views/backOfficeSystem/systemConfig/dict/index"),
meta: {
title: "字典列表",
icon: "article-ranking"
}
},
{
path: "/user/deptAllocationUser/:id",
name: "deptAllocationUser",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/department-list/deptAllocationUser"
),
meta: {
title: "管理用户"
}
},
{
path: "/user/allocationUser/:id",
name: "allocationUser",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/role-list/allocationUser"
),
meta: {
title: "分配用户"
}
},
{
path: "/user/systemConfig",
name: "systemConfig",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/system-config-list/index"
),
meta: {
title: "系统配置",
icon: "article-ranking"
}
}, {
path: "/calendar",
name: "calendar",
component: () => import("@/views/backOfficeSystem/calendar/index.vue"),
meta: {
title: "敏感节点",
icon: "article"
}
},
]
},
{ {
path: "/oatuh_login", path: "/oatuh_login",
name: "oatuh_login", name: "oatuh_login",
@ -159,11 +43,6 @@ export const publicRoutes = [
name: "home", name: "home",
component: () => import("@/views/home/index") //系统登录 component: () => import("@/views/home/index") //系统登录
}, },
{
path: "/consultation",
name: "consultation",
component: () => import("@/views/consultation/demo")
},
{ {
path: "/KeyPopulations", path: "/KeyPopulations",
name: "KeyPopulations", name: "KeyPopulations",
@ -175,6 +54,12 @@ export const publicRoutes = [
name: "deploymentApproval", name: "deploymentApproval",
component: () => import("@/views/backOfficeSystem/ApprovalInformation/deploycontrol/deploymentApproval.vue"), component: () => import("@/views/backOfficeSystem/ApprovalInformation/deploycontrol/deploymentApproval.vue"),
}, },
// 布控审核信息
{
path: "/information",
name: "information",
component: () => import("@/views/backOfficeSystem/JudgmentHome/internalAuditor/information.vue"),
},
// 线索 // 线索
{ {
path: "/clueVerification", path: "/clueVerification",
@ -257,12 +142,18 @@ export const publicRoutes = [
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/index"), // component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/index"),
// meta: { title: "预警中心大屏", icon: "article" }, // meta: { title: "预警中心大屏", icon: "article" },
// }, // },
// { // {
// path: "/warningBk", // path: "/warningBk",
// name: "warningBk", // name: "warningBk",
// meta: { title: "布控预警", icon: "article" }, // meta: { title: "布控预警", icon: "article" },
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/warningBk/index"), // component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/warningBk/index"),
// }, // },
{
path: "/fouColorWarning",
name: "fouColorWarning",
meta: { title: "预警数据整合", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"),
},
{ {
path: "/identityWarning", path: "/identityWarning",
@ -282,20 +173,52 @@ export const publicRoutes = [
name: "combinedWarning", name: "combinedWarning",
meta: { title: "组合预警", icon: "article" }, meta: { title: "组合预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/combinedWarning/index"), component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/combinedWarning/index"),
}, { },
path: "/warningList", // {
name: "warningList", // path: "/warningList",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/index"), // name: "warningList",
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/index"),
// meta: {
// title: "布控预警",
// icon: "article"
// }
// },
{
path: "/portraitWarning",
name: "portraitWarning",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/portraitWarning/index"),
meta: { meta: {
title: "布控预警", title: "人像预警",
icon: "article"
}
},
{
path: "/vehicleWarning",
name: "vehicleWarning",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/vehicleWarning/index"),
meta: {
title: "车辆预警",
icon: "article" icon: "article"
} }
}, },
{ {
path: "/fouColorWarning", path: "/controlWarning",
name: "fouColorWarning", name: "controlWarning",
meta: { title: "四色预警", icon: "article" }, meta: { title: "布控预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"), component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/controlWarning/index"),
},
// {
// path: "/fouColorWarning",
// name: "fouColorWarning",
// meta: { title: "四色预警", icon: "article" },
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"),
// },
{
path: "/scoreRanking",
name: "scoreRanking",
meta: { title: "积分排名", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/scoreRanking/index"),
}, },
// { // {
// path: "/modelWarning", // path: "/modelWarning",
@ -307,163 +230,7 @@ export const publicRoutes = [
] ]
}, },
{
path: "/dataApplication",
name: "dataApplication",
meta: { title: "数据应用", icon: "article" },
children: [
{
path: "/IdentityManage",
name: "IdentityManage",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/IdentityManage/index"
),
meta: {
title: "身份标签管理",
icon: "article"
}
},
{
path: "/BehaviorLabels",
name: "BehaviorLabels",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/BehaviorLabels/index"
),
meta: {
title: "行为标签管理",
icon: "article"
}
},
{
path: "/tagManage",
name: "tagManage",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/tagManage/index"
),
meta: {
title: "标签组合管理",
icon: "article"
}
}, {
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
meta: {
title: "模型管理",
icon: "article"
}
},
{
path: "/RlStatisticalAnalysis",
name: "RlStatisticalAnalysis",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/RlStatisticalAnalysis/index"
),
meta: {
title: "上报统计分析",
icon: "article"
}
},
{
path: "/TaskScheduling",
name: "TaskScheduling",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/TaskScheduling/index"
),
meta: {
title: "上报任务调度",
icon: "article"
}
},
{
path: "/ConstructionManagement",
name: "ConstructionManagement",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/ConstructionManagement/index"
),
meta: {
title: "力量建设管理",
icon: "article"
}
},
{
path: "/JobAppraisal",
name: "JobAppraisal",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/JobAppraisal/index"),
meta: {
title: "工作考核",
icon: "article"
}
},
{
path: "/fileTransfer",
name: "fileTransfer",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/fileTransfer/index"),
meta: {
title: "文件中转",
icon: "article"
}
},
{
path: "/fileOrientation",
name: "fileOrientation",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/fileOrientation/index"),
meta: {
title: "文件定向传输",
icon: "article"
}
},
{
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
meta: {
title: "数据监测",
icon: "article"
}
}, {
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () => import("@/views/backOfficeSystem/SemanticAnalysis/index.vue"),
meta: {
title: "语义分析",
icon: "article"
}
},
{
path: "/StatisticalAnalysis",
name: "StatisticalAnalysis",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/StatisticalAnalysis/index"),
meta: {
title: "情报统计分析",
icon: "article"
}
}, {
path: "/InstructionInformation",
name: "InstructionInformation",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/InstructionInformation/index"),
meta: {
title: "情报指令",
icon: "article"
}
}, {
path: "/RecordsOperations",
name: "RecordsOperations",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/RecordsOperations/index"),
meta: {
title: "操作记录",
icon: "article"
}
}
]
},
{ {
path: "/IntelligentControl", path: "/IntelligentControl",
name: "IntelligentControl", name: "IntelligentControl",
@ -551,23 +318,50 @@ export const publicRoutes = [
path: "/socialInformationCrculated", path: "/socialInformationCrculated",
name: "changeTheClue", name: "changeTheClue",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/FollowLeads/index"), component: () => import("@/views/backOfficeSystem/HumanIntelligence/FollowLeads/index"),
meta: { title: "转线索", icon: "article" }, meta: { title: "转线索列表", icon: "article" },
}, },
{ {
path: "/socialInformationCrculatec", path: "/socialInformationCrculatec",
name: "recombinantSynthesis", name: "recombinantSynthesis",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/ConversionSynthesis/index"), component: () => import("@/views/backOfficeSystem/HumanIntelligence/ConversionSynthesis/index"),
meta: { title: "转合成", icon: "article" }, meta: { title: "转合成列表", icon: "article" },
}, },
// {
// path: "/CollectPoints",
// name: "CollectPoints",
// component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectPoints/index"),
// meta: {
// title: "采集积分",
// icon: "article"
// }
// },
{ {
path: "/CollectPoints", path: "/transferConsultationList",
name: "CollectPoints", name: "transferConsultationList",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectPoints/index"), component: () => import("@/views/backOfficeSystem/transferConsultationList/index.vue"),
meta: { meta: {
title: "采集积分", title: "转会商列表",
icon: "article" icon: "article"
} }
} },
{
path: "/supplementReportList",
name: "supplementReportList",
component: () => import("@/views/backOfficeSystem/supplementReportList/index.vue"),
meta: {
title: "补充/续报列表",
icon: "article"
}
},
{
path: "/integralList",
name: "integralList",
component: () => import("@/views/backOfficeSystem/integralList/index.vue"),
meta: {
title: "积分列表",
icon: "article"
}
},
// { // {
// path: "/MakeAcomment", // path: "/MakeAcomment",
// name: "MakeAcomment", // name: "MakeAcomment",
@ -612,17 +406,25 @@ export const publicRoutes = [
title: "线索管理", title: "线索管理",
icon: "article" icon: "article"
} }
}, {
path: "/InstructionInformation",
name: "InstructionInformation",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/InstructionInformation/index"),
meta: {
title: "线索下发管理",
icon: "article"
}
}, },
{ // {
path: "/InformationFlows", // path: "/InformationFlows",
name: "InformationFlows", // name: "InformationFlows",
meta: { title: "情报流转", icon: "article" }, // meta: { title: "情报流转", icon: "article" },
redirect: "/InformationFlow", // // redirect: "/InformationFlow",
children: [ // // children: [
] // // ]
}, // },
] ]
}, },
@ -681,11 +483,11 @@ export const publicRoutes = [
}, },
children: [ children: [
{ {
path: "/dataReduction", path: "/policeReport",
name: "dataReduction", name: "policeReport",
component: () => import("@/views/backOfficeSystem/JudgmentHome/dataReduction/index"), component: () => import("@/views/backOfficeSystem/policeReport/index.vue"),
meta: { meta: {
title: "数据整理", title: "警情管理",
icon: "article" icon: "article"
} }
}, },
@ -693,40 +495,48 @@ export const publicRoutes = [
path: "/ResearchHome", path: "/ResearchHome",
name: "ResearchHome", name: "ResearchHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/ResearchHome/index"), component: () => import("@/views/backOfficeSystem/JudgmentHome/ResearchHome/index"),
meta: {
title: "智能研判",
icon: "article"
}
},
{
path: "/dataReduction",
name: "dataReduction",
component: () => import("@/views/backOfficeSystem/JudgmentHome/dataReduction/index"),
meta: {
title: "数据整理",
icon: "article"
}
},
// {
// path: "/situationHome",
// name: "situationHome",
// component: () => import("@/views/backOfficeSystem/JudgmentHome/situationHome/index"),
// meta: {
// title: "战略研判",
// icon: "article"
// }
// },
// 后面写的研判
{
path: "/tacticalResearch",
name: "tacticalResearch",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tacticalResearch/index.vue"),
meta: { meta: {
title: "战术研判", title: "战术研判",
icon: "article" icon: "article"
} }
}, },
{ {
path: "/situationHome", path: "/strategicResearch",
name: "situationHome", name: "strategicResearch",
component: () => import("@/views/backOfficeSystem/JudgmentHome/situationHome/index"), component: () => import("@/views/backOfficeSystem/JudgmentHome/strategicResearch/index.vue"),
meta: { meta: {
title: "战略研判", title: "战略研判",
icon: "article" icon: "article"
} }
}, },
// 后面写的研判
// {
// path: "/tacticalResearch",
// name: "tacticalResearch",
// component: () => import("@/views/backOfficeSystem/JudgmentHome/tacticalResearch/index.vue"),
// meta: {
// title: "战术研判",
// icon: "article"
// }
// },
// {
// path: "/strategicResearch",
// name: "strategicResearch",
// component: () => import("@/views/backOfficeSystem/JudgmentHome/strategicResearch/index.vue"),
// meta: {
// title: "战略研判",
// icon: "article"
// }
// },
{ {
path: "/judgmentCommand", path: "/judgmentCommand",
name: "judgmentCommand", name: "judgmentCommand",
@ -736,7 +546,15 @@ export const publicRoutes = [
icon: "article" icon: "article"
} }
}, },
{
path: "/internalAuditor",
name: "internalAuditor",
component: () => import("@/views/backOfficeSystem/JudgmentHome/internalAuditor/index.vue"),
meta: {
title: "内部审核人员",
icon: "article"
}
},
// { // {
// path: "/analysisReport", // path: "/analysisReport",
// name: "AnalysisReport", // name: "AnalysisReport",
@ -823,49 +641,159 @@ export const publicRoutes = [
] ]
}, },
{ {
path: "/BasicManagement", path: "/dataApplication",
name: "BasicManagement", name: "dataApplication",
meta: { meta: { title: "数据应用", icon: "article" },
title: "基础管理",
icon: "article"
},
children: [ children: [
// {
// path: "/surveillanceControl",
// name: "surveillanceControl",
// component: () =>
// import(
// "@/views/backOfficeSystem/BasicManagement/surveillanceControl/index"
// ),
// meta: {
// title: "布控监视",
// icon: "article"
// }
// },
// {
// path: "/experienceShare",
// name: "experienceShare",
// component: () =>
// import("@/views/backOfficeSystem/BasicManagement/experienceShare/index"),
// meta: {
// title: "经验分享",
// icon: "article"
// }
// },
{ {
path: "/policeReport", path: "/IntegralCoefficient",
name: "policeReport", name: "IntegralCoefficient",
component: () => import("@/views/backOfficeSystem/policeReport/index.vue"), component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/IntegralCoefficient/index"
),
meta: { meta: {
title: "警情管理", title: "积分系数配置",
icon: "article" icon: "article"
} }
}, },
{
path: "/IdentityManage",
name: "IdentityManage",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/IdentityManage/index"
),
meta: {
title: "身份标签管理",
icon: "article"
}
},
{
path: "/BehaviorLabels",
name: "BehaviorLabels",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/BehaviorLabels/index"
),
meta: {
title: "行为标签管理",
icon: "article"
}
},
{
path: "/tagManage",
name: "tagManage",
component: () =>
import(
"@/views/backOfficeSystem/fourColorManage/tagManage/index"
),
meta: {
title: "标签组合管理",
icon: "article"
}
}, {
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
meta: {
title: "模型管理",
icon: "article"
}
},
{
path: "/JobAppraisal",
name: "JobAppraisal",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/JobAppraisal/index"),
meta: {
title: "工作考核",
icon: "article"
}
},
{
path: "/fileTransfer",
name: "fileTransfer",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/fileTransfer/index"),
meta: {
title: "文件中转",
icon: "article"
}
},
{
path: "/fileOrientation",
name: "fileOrientation",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/fileOrientation/index"),
meta: {
title: "文件定向传输",
icon: "article"
}
},
{
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () => import("@/views/backOfficeSystem/SemanticAnalysis/index.vue"),
meta: {
title: "语义分析",
icon: "article"
}
},
{
path: "/StatisticalAnalysis",
name: "StatisticalAnalysis",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/StatisticalAnalysis/index"),
meta: {
title: "情报统计分析",
icon: "article"
}
}, {
path: "/RecordsOperations",
name: "RecordsOperations",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/RecordsOperations/index"),
meta: {
title: "操作记录",
icon: "article"
}
}
] ]
}, },
// {
// path: "/BasicManagement",
// name: "BasicManagement",
// meta: {
// title: "基础管理",
// icon: "article"
// },
// children: [
// // {
// // path: "/surveillanceControl",
// // name: "surveillanceControl",
// // component: () =>
// // import(
// // "@/views/backOfficeSystem/BasicManagement/surveillanceControl/index"
// // ),
// // meta: {
// // title: "布控监视",
// // icon: "article"
// // }
// // },
// // {
// // path: "/experienceShare",
// // name: "experienceShare",
// // component: () =>
// // import("@/views/backOfficeSystem/BasicManagement/experienceShare/index"),
// // meta: {
// // title: "经验分享",
// // icon: "article"
// // }
// // },
// ]
// },
{ {
path: "/forumPost", path: "/forumPost",
name: "forumPost", name: "forumPost",
@ -875,6 +803,147 @@ export const publicRoutes = [
icon: "article" icon: "article"
} }
}, },
{
path: "/dataMonitor",
name: "dataMonitor",
meta: { title: "数据监控", icon: "article" },
children: [
{
path: "/resourceMonitoring",
name: "resourceMonitoring",
component: () => import("@/views/backOfficeSystem/dataMonitor/resourceMonitoring/index.vue"),
meta: {
title: "数据资源检测",
icon: "article"
}
},
{
path: "/onlineUserMonitoring",
name: "onlineUserMonitoring",
component: () => import("@/views/backOfficeSystem/dataMonitor/onlineUserMonitoring/index.vue"),
meta: {
title: "在线用户监控",
icon: "article"
}
}
]
},
{
path: "/systemConfig",
// component: layout,
name: "systemConfigModel",
// redirect: "/dict/index",
meta: {
title: "系统管理",
icon: "article"
},
children: [
{
path: "/user/department-ist",
name: "departmentList",
component: () => import("@/views/backOfficeSystem/systemConfig/department-list/index"),
meta: {
title: "部门管理",
icon: "article-ranking"
}
},
{
path: "/user/userList",
name: "userList",
component: () =>
import("@/views/backOfficeSystem/systemConfig/user-list/index"),
meta: {
title: "用户管理",
icon: "article-ranking"
}
},
{
path: "/user/role",
name: "userRoleIndex",
component: () =>
import("@/views/backOfficeSystem/systemConfig/role-list/index"),
meta: {
title: "角色列表",
icon: "article-ranking"
}
},
{
path: "/user/menuList",
name: "menuList",
component: () =>
import("@/views/backOfficeSystem/systemConfig/menu-list/index"),
meta: {
title: "菜单管理",
icon: "article-ranking"
}
},
{
path: "/dict/detail",
name: "dictDetail",
component: () =>
import("@/views/backOfficeSystem/systemConfig/dict/detail"),
meta: {
title: "字典数据"
}
},
{
path: "/dict/index",
name: "dictIndex",
component: () =>
import("@/views/backOfficeSystem/systemConfig/dict/index"),
meta: {
title: "字典列表",
icon: "article-ranking"
}
},
{
path: "/user/deptAllocationUser/:id",
name: "deptAllocationUser",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/department-list/deptAllocationUser"
),
meta: {
title: "管理用户"
}
},
{
path: "/user/allocationUser/:id",
name: "allocationUser",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/role-list/allocationUser"
),
meta: {
title: "分配用户"
}
},
{
path: "/user/systemConfig",
name: "systemConfig",
component: () =>
import(
"@/views/backOfficeSystem/systemConfig/system-config-list/index"
),
meta: {
title: "系统配置",
icon: "article-ranking"
}
}, {
path: "/calendar",
name: "calendar",
component: () => import("@/views/backOfficeSystem/calendar/index.vue"),
meta: {
title: "敏感节点",
icon: "article"
}
},
]
},
{ {
path: "/rests", path: "/rests",
name: "rests", name: "rests",
@ -883,19 +952,67 @@ export const publicRoutes = [
icon: "article" icon: "article"
}, },
children: [ children: [
// {
// path: "/fouColorWarning",
// name: "fouColorWarning",
// meta: { title: "四色预警", icon: "article" },
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"),
// },
{ {
path: "/CollectCrculate", path: "/CollectCrculate",
name: "CollectCrculate", name: "CollectCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"), component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
meta: { title: "信息采集", icon: "article" }, meta: { title: "情报采集", icon: "article" },
}, {
path: "/RlStatisticalAnalysis",
name: "RlStatisticalAnalysis",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/RlStatisticalAnalysis/index"
),
meta: {
title: "上报统计分析",
icon: "article"
}
}, },
{
path: "/TaskScheduling",
name: "TaskScheduling",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/TaskScheduling/index"
),
meta: {
title: "上报任务调度",
icon: "article"
}
},
{
path: "/ConstructionManagement",
name: "ConstructionManagement",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/ConstructionManagement/index"
),
meta: {
title: "力量建设管理",
icon: "article"
}
},
// {
// path: "/ResearchHome",
// name: "ResearchHome",
// component: () => import("@/views/backOfficeSystem/JudgmentHome/ResearchHome/index"),
// meta: {
// title: "战术研判",
// icon: "article"
// }
// },
// {
// path: "/situationHome",
// name: "situationHome",
// component: () => import("@/views/backOfficeSystem/JudgmentHome/situationHome/index"),
// meta: {
// title: "战略研判",
// icon: "article"
// }
// },
] ]
}, },
] ]

View File

@ -1,4 +1,4 @@
import { CONFERENCE_ROLE_NORMAL } from '@/views/consultation/sdk/conferenceControl'; import { CONFERENCE_ROLE_NORMAL } from '@/components/Consultation/sdk/conferenceControl';
export default { export default {
id: 'global', id: 'global',
state: () => ({ state: () => ({

View File

@ -88,7 +88,6 @@ export default {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login({ userName, password: Base64.encode(password), kaptcha }).then((data) => { login({ userName, password: Base64.encode(password), kaptcha }).then((data) => {
if (data.deptList.length === 1) { if (data.deptList.length === 1) {
this.commit("user/setToken", data.jwtToken); this.commit("user/setToken", data.jwtToken);
this.commit("user/setDeptId", data.deptList); this.commit("user/setDeptId", data.deptList);
this.commit("user/setUserName", data.userName); this.commit("user/setUserName", data.userName);

View File

@ -75,3 +75,32 @@ export function spliceString(targetArr){
} }
return currentStr return currentStr
} }
/** 是否是市情指(市情报指挥) */
export function isShiQingZhi() {
const { deptBizType, deptLevel } = getItem('deptId')?.[0] || {}
const Jb = deptLevel?.[0] == '2' ? '01' : deptLevel?.[0] == '3' ? '02' : '03'
return deptBizType == '23' && Jb == '01'
}
/** 获取当前用户角色信息 */
export function getRole() {
const roleList = Array.isArray(getItem('roleList')) ? getItem('roleList') : []
/** 角色配置映射表 */
const ROLE_MAP = [
{ code: 'JS_666666', label: '市情指领导', value: '01', ename: 'shiQzLeader' },
{ code: 'JS_777777', label: '市情指挥人员', value: '02', ename: 'shiQz' },
{ code: 'JS_888888', label: '县情指人员', value: '03', ename: 'xianQz' }
]
/** 按优先级匹配角色 */
for (const role of ROLE_MAP) {
if (roleList.some(item => item.roleCode === role.code)) {
return { label: role.label, value: role.value, ename: role.ename }
}
}
/** 默认返回普通用户 */
return { label: '普通用户', value: '04', ename: 'common' }
}

View File

@ -1,5 +1,5 @@
import { ref, toRefs } from 'vue'; import { ref, toRefs, isRef } from 'vue';
import { getSysDictByCode } from '@/api/sysDict' //引入封装数字字典接口 import { getSysDictByCode, fzdict } from '@/api/sysDict' //引入封装数字字典接口
import { getLocalDic } from "@/utils/localDic/index.js" import { getLocalDic } from "@/utils/localDic/index.js"
/** /**
@ -15,7 +15,7 @@ export function isLocalDict(dictCode) {
D_GS_SSYJ: true, // "岗哨系统四色预警" D_GS_SSYJ: true, // "岗哨系统四色预警"
D_BZ_SF: true, // "是否" D_BZ_SF: true, // "是否"
BD_BK_CLYJBQ: true, // "车辆预警标签" BD_BK_CLYJBQ: true, // "车辆预警标签"
D_YJXX_CZCSLX:true, //常控处置措施类型 D_YJXX_CZCSLX: true, //常控处置措施类型
} }
return localDicObj[dictCode] return localDicObj[dictCode]
} }
@ -24,26 +24,28 @@ export function getDict(...args) {
return (() => { return (() => {
args.forEach((d, index) => { args.forEach((d, index) => {
res.value[d] = []; res.value[d] = [];
// 本地字典拦截,如果本地字典存在,则使用本地字典,否则使用远程字典 // 本地字典拦截,如果本地字典存在,则使用本地字典,否则使用远程字典
if (isLocalDict(d) && getLocalDic(d)) { if (isLocalDict(d) && getLocalDic(d)) {
res.value[d] = getLocalDic(d) res.value[d] = getLocalDic(d)
} else { } else {
getSysDictByCode({ getSysDictByCode({
dictCode: d dictCode: d
}).then(result => { }).then(result => {
result = result || {}
result.itemList = Array.isArray(result.itemList) ? result.itemList : []
result.itemList.forEach(p => { result.itemList.forEach(p => {
p.label = p.zdmc p.label = p.zdmc
p.value = p.dm p.value = p.dm
p.id = p.dm p.id = p.dm
p.elTagType = p.dictType p.elTagType = p.dictType
if (p.itemList && p.itemList.length > 0) { if (p?.itemList && p.itemList?.length > 0) {
getChildren(p) getChildren(p)
} }
p.children = p.itemList p.children = p.itemList
}) })
res.value[d] = result.itemList res.value[d] = result.itemList
// console.log(`${d} - ${result.zdmc} :`, result.itemList); //
}) })
} }
@ -51,7 +53,42 @@ export function getDict(...args) {
return toRefs(res.value); return toRefs(res.value);
})() })()
} }
export function getFzDict(...args) {
const res = ref({});
return (() => {
args.forEach((d, index) => {
res.value[d] = [];
// 本地字典拦截,如果本地字典存在,则使用本地字典,否则使用远程字典
if (isLocalDict(d) && getLocalDic(d)) {
res.value[d] = getLocalDic(d);
} else {
fzdict({
dictLabel: d
}).then(result => {
result = result || {};
// result.itemList = Array.isArray(result.itemList) ? result.itemList : [];
// result.itemList.forEach(p => {
// p.label = p.itemName;
// p.value = p.itemValue;
// p.id = p.itemValue;
// p.elTagType = p.dictType;
// if (p?.itemList && p.itemList?.length > 0) {
// getChildren(p);
// }
// p.children = p.itemList;
// });
// console.log(res.value);
res.value[d] = result
});
}
});
// 使用toRefs确保返回的是响应式对象
return toRefs(res.value);
})()
}
export function getChildren(item) { export function getChildren(item) {
item.label = item.zdmc item.label = item.zdmc
item.value = item.dm item.value = item.dm
@ -140,3 +177,39 @@ export function IdCard(IdCard, type) {
} }
return user return user
} }
/**
*翻译字典数据
* @export
* @param {*} dm
* @param {*} array
*/
export function getDictValue(dm, array) {
let item = array.value.find(item => {
if (item.value) {
return item.value == dm;
} else if (item.dm) {
return item.dm == dm;
}
})
return item ? item.label : ""
}
/** 获取多个字典值(一个值也可以) 字典内容 value-label
* @param {String} 要查的值
* @param {Array} dict 字典内容
*/
export function getMultiDictVal(values, dict) {
if (typeof values === 'string' && values?.length) values = values.split(',')
if (!Array.isArray(values)) return ''
if (isRef(dict)) dict = dict.value
if (!Array.isArray(dict)) return ''
return values.map(v => {
const item = dict.find(item => item.value === v);
return item ? item.label : v;
}).join(',');
}

View File

@ -1,5 +1,5 @@
import { saveAs } from 'file-saver'; import { saveAs } from 'file-saver';
import html2pdf from 'html2pdf.js'; // import html2pdf from 'html2pdf.js';
const isDOM = (obj) => obj instanceof HTMLElement; const isDOM = (obj) => obj instanceof HTMLElement;
@ -9,64 +9,65 @@ const isDOM = (obj) => obj instanceof HTMLElement;
* @param {string} name 文件名 * @param {string} name 文件名
*/ */
export const downloadPDF = async (dom, name = '导出文件') => { export const downloadPDF = async (dom, name = '导出文件') => {
if (!isDOM(dom)) return; // 先不用这个
// if (!isDOM(dom)) return;
try { // try {
// 等待一段时间确保所有图表完全渲染 // // 等待一段时间确保所有图表完全渲染
await new Promise(resolve => setTimeout(resolve, 1500)); // await new Promise(resolve => setTimeout(resolve, 1500));
// 强制重新渲染所有图表 // // 强制重新渲染所有图表
const resizeEvent = new Event('resize'); // const resizeEvent = new Event('resize');
window.dispatchEvent(resizeEvent); // window.dispatchEvent(resizeEvent);
// 再次等待图表重绘完成 // // 再次等待图表重绘完成
await new Promise(resolve => setTimeout(resolve, 1000)); // await new Promise(resolve => setTimeout(resolve, 1000));
// 获取内容的实际高度 // // 获取内容的实际高度
const contentHeight = dom.scrollHeight; // const contentHeight = dom.scrollHeight;
// 计算需要的页面尺寸(单位:毫米) // // 计算需要的页面尺寸(单位:毫米)
// 将像素转换为毫米1px ≈ 0.264583mm // // 将像素转换为毫米1px ≈ 0.264583mm
const a4HeightMm = 297; // A4纸高度 // const a4HeightMm = 297; // A4纸高度
const contentHeightMm = contentHeight * 0.264583; // const contentHeightMm = contentHeight * 0.264583;
const opt = { // const opt = {
margin: [10, 10, 20, 10], // [top, right, bottom, left] 格式 // margin: [10, 10, 20, 10], // [top, right, bottom, left] 格式
filename: name + '.pdf', // filename: name + '.pdf',
image: { // image: {
type: 'png', // type: 'png',
quality: 1 // quality: 1
}, // },
html2canvas: { // html2canvas: {
scale: 1.5, // scale: 1.5,
useCoRs: true, // useCoRs: true,
allowTaint: true, // allowTaint: true,
foreignObjectRendering: false, // foreignObjectRendering: false,
logging: false, // logging: false,
width: dom.scrollWidth, // width: dom.scrollWidth,
height: dom.scrollHeight + 100, // 增加额外高度,包含底部内容 // height: dom.scrollHeight + 100, // 增加额外高度,包含底部内容
scrollX: 0, // scrollX: 0,
scrollY: 0 // scrollY: 0
}, // },
jsPDF: { // jsPDF: {
unit: 'mm', // unit: 'mm',
format: [210, contentHeightMm + 40], // 自定义页面高度,确保所有内容都在一页 // format: [210, contentHeightMm + 40], // 自定义页面高度,确保所有内容都在一页
orientation: "portrait" // orientation: "portrait"
}, // },
pagebreak: { // pagebreak: {
mode: "avoid", // 尽量避免在元素中间分页 // mode: "avoid", // 尽量避免在元素中间分页
before: '.analysis-report-box h2', // 在h2标题前避免分页 // before: '.analysis-report-box h2', // 在h2标题前避免分页
after: '.analysis-report-box h2', // 在h2标题后避免分页 // after: '.analysis-report-box h2', // 在h2标题后避免分页
avoid: '.analysis-report-box p' // 避免在段落中间分页 // avoid: '.analysis-report-box p' // 避免在段落中间分页
} // }
}; // };
await html2pdf().set(opt).from(dom).save(); // await html2pdf().set(opt).from(dom).save();
return true; // return true;
} catch (error) { // } catch (error) {
console.error('PDF导出失败:', error); // console.error('PDF导出失败:', error);
return false; // return false;
} // }
} }

56
src/utils/exportExcel.js Normal file
View File

@ -0,0 +1,56 @@
import * as XLSX from "xlsx";
/**
* 导出Excel(简单的导出)
* @param {Array} data 二维数据
* @param {String} fileName 文件名
*/
export function easyExport(data, fileName = '导出文件') {
const wb = XLSX.utils.book_new();
// 二维数组例子:[ ['姓名', '年龄', '城市'], ['张三', 25, '北京'], ['李四', 30, '上海'] ];
const ws = XLSX.utils.aoa_to_sheet(data); // aoa_to_sheet 方法将二维数组转换为工作表
// 宽度调整
ws['!cols'] = Array(data?.[0]?.length || 0).fill({ wpx: 80 });
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, fileName + '.xlsx');
}
/**
* 根据对象导出Excel
* @param {Object} titleObj 标题对象 {key: '标题', key2: '标题2'}
* @param {Array} dataArr 数据数组 例子 [{key: '张三', key2: '25'}, {key: '李四', key2: '30'}]
* @param {String} fileName 文件名
*/
export function exportExlByObj(titleObj, dataArr, fileName = '导出文件') {
dataArr = Array.isArray(dataArr) ? [...dataArr] : []
/** 列表标题数组 */
const titleArr = [Object.values(titleObj)];
const sheetHead = [fileName]
/** 转二维数据 */
const toNeedArr = (titleObj = {}, tableData = []) => {
return tableData.map(row => {
const rowArr = []
Object.keys(titleObj || {}).map(key => {
const cellVal = row[key] || ''
if (typeof cellVal !== 'string') String(cellVal)
rowArr.push(cellVal)
})
return rowArr
})
}
/** @param {Array} 表格数据 (二维数组) */
const tableData = toNeedArr(titleObj, dataArr);
// 合并标题和数据
const finalData = [...titleArr, ...tableData];
// 合并标题
easyExport(finalData, fileName);
}

View File

@ -5,19 +5,21 @@ import { getItem } from '@/utils/storage'
*/ */
const getChildrenRoutes = (routes) => { const getChildrenRoutes = (routes) => {
const result = []; const result = [];
// const { deptBizType, deptLevel } = getItem('deptId')[0] const { deptBizType, deptLevel } = getItem('deptId')[0]
const roleList = getItem('roleList') ? getItem('roleList').filter(item => item.roleCode == 'JS_666666').length > 0 : false
routes.forEach((route) => { routes.forEach((route) => {
if (route.children && route.children.length > 0) { if (route.children && route.children.length > 0) {
// if (deptBizType == '23') { if (deptBizType == '23' && roleList) {
result.push(...route.children); result.push(...route.children);
// } else { } else {
// if (route.path == '/HumanIntelligence') { // console.log(route.path);
// route.children.splice(0, 1); if (route.path == '/JudgmentHome') {
// result.push(...route.children); route.children.splice(6, 1);
// } else { result.push(...route.children);
// result.push(...route.children); } else {
// } result.push(...route.children);
// } }
}
} }
}); });
return result; return result;

View File

@ -93,6 +93,7 @@ export function timeValidate(date, type) {
const hh = time.getHours().toString().padStart(2, '0') const hh = time.getHours().toString().padStart(2, '0')
const mm = time.getMinutes().toString().padStart(2, '0') const mm = time.getMinutes().toString().padStart(2, '0')
const ss = time.getSeconds().toString().padStart(2, '0') const ss = time.getSeconds().toString().padStart(2, '0')
if (type == 'ymd') { if (type == 'ymd') {
return `${yyyy}-${MM}-${dd}`; return `${yyyy}-${MM}-${dd}`;
} }
@ -379,5 +380,23 @@ export const bqYs = (val) => {
*/ */
export function holographicProfileJump(szhm) { export function holographicProfileJump(szhm) {
if (!szhm) return if (!szhm) return
window.open(`https://tyyy.lz.dsj.xz/profile/people/person-manage?szhm=${szhm}&from=portal`) window.open(`https://tyyy.lz.dsj.xz/profile/people/person-manage?sfzhm=${szhm}&from=portal`)
}
/**
* 获取表单验证错误信息
* @param fields 表单验证错误信息
* @param {Object} msgObj 错误信息Ojb,没有就取message
*/
export function getErrMsg(fields, msgObj) {
if (!fields) return;
if (Object.keys(fields).length === 0) return;
/** 第一个错误字段 */
const firstErrorField = Object.keys(fields)[0];
if (msgObj && msgObj[firstErrorField]) return msgObj[firstErrorField];
if (!firstErrorField) return;
/** 第一个错误字段的内容 @type{<Array>Object} - [message, field, fieldValue] */
let firstErrorFieldObj = fields?.[firstErrorField];
let errMsg = firstErrorFieldObj?.[0]?.message
return errMsg
} }

View File

@ -1,4 +1,9 @@
const url = "ws://89.40.9.89:2109/mosty-api/mosty-websocket/socket/"; //线上 // let url = "ws://89.40.9.89:2109/mosty-api/mosty-websocket/socket/"; //线上
let url = "ws://155.240.22.30:2109/mosty-api/mosty-websocket/socket/"; //线上
if (process.env.NODE_ENV === 'development') {
url = "ws://47.108.232.77:9537/mosty-api/mosty-websocket/socket/"; //本地
}
import { import {
getItem getItem
} from "@/utils/storage"; } from "@/utils/storage";

View File

@ -57,7 +57,7 @@ const rules = ref({
] ]
}) })
const formData = ref([ const formData = ref([
{ label: "关注部门", prop: "ssbmdm", depMc: 'ssbm', type: "department", width: '45%', multiple: true }, { label: "关注部门", prop: "ssbmdm", depMc: 'ssbm', type: "department", width: '45%', multiple: true,isAll: true },
]) ])
const elform = ref(null) const elform = ref(null)
watch(() => props.modelValue, (newVal) => { watch(() => props.modelValue, (newVal) => {

View File

@ -53,7 +53,7 @@ const props = defineProps({
}, },
path: { path: {
type: String, type: String,
default: "/qbcjZhc/sendFqzl" default: "/mosty-gsxt/qbcjZhc/sendFqzl"
} }
@ -101,16 +101,17 @@ const getsendFqzl = () => {
} }
try { try {
const res = await qcckPost(promes,props.path ) const res = await qcckPost(promes,props.path )
// qbcjZhcSendFqzl(promes) // const str = JSON.parse(res)
const str = JSON.parse(res) // if (str.code == 200) {
if (str.code == 200) {
ElMessage.success('发送成功') ElMessage.success('发送成功')
listQuery.value = {} // listQuery.value = {}
listQuery.value.attachmentPath = '' // listQuery.value.attachmentPath = ''
emit('handleClose') emit('handleClose')
} else { close()
ElMessage.error(str.msg)
} // } else {
// ElMessage.error(str.msg)
// }
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@ -13,7 +13,7 @@
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules"> <FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
</FormMessage> </FormMessage>
<!-- </div> --> <!-- </div> -->
<div class="tags-section" v-if="disabled"> <div class="tags-section" v-if="disabled">
<h3 class="tags-title">关注部门</h3> <h3 class="tags-title">关注部门</h3>
<div class="tags-container"> <div class="tags-container">
<div v-for="(tag, index) in listQuery.gzbmList" :key="tag.id || index" class="tag-item"> <div v-for="(tag, index) in listQuery.gzbmList" :key="tag.id || index" class="tag-item">
@ -40,14 +40,14 @@
</div> </div>
</div> </div>
<div class="tags-section" v-if="disabled"> <div class="tags-section" v-if="disabled">
<h3 class="tags-title">信息</h3> <h3 class="tags-title">信息</h3>
<div class="list-container"> <div class="list-container">
<div v-for="(item, index) in dataList.xb" :key="item.id || index" class="list-item"> <div v-for="(item, index) in dataList.xb" :key="item.id || index" class="list-item">
<div class="list-content"> <div class="list-content">
{{ item.bcnr }} {{ item.bcnr }}
</div> </div>
<div class="tag-actions"> <div class="tag-actions">
<el-icon class="action-icon edit-icon" :size="32" @click="openPursue('续信息', item)"> <el-icon class="action-icon edit-icon" :size="32" @click="openPursue('续信息', item)">
<EditPen /> <EditPen />
</el-icon> </el-icon>
<el-icon class="action-icon delete-icon" :size="32" @click="handleDeleteTag(item)"> <el-icon class="action-icon delete-icon" :size="32" @click="handleDeleteTag(item)">
@ -56,7 +56,7 @@
</div> </div>
</div> </div>
<span v-if="!dataList.xb || dataList.xb.length === 0" class="no-tags"> <span v-if="!dataList.xb || dataList.xb.length === 0" class="no-tags">
暂无标签 暂无续报信息
</span> </span>
</div> </div>
</div> </div>
@ -77,7 +77,7 @@
</div> </div>
</div> </div>
<span v-if="!dataList.bc || dataList.bc.length === 0" class="no-tags"> <span v-if="!dataList.bc || dataList.bc.length === 0" class="no-tags">
暂无标签 暂无补充信息
</span> </span>
</div> </div>
</div> </div>
@ -104,15 +104,16 @@
</div> </div>
</div> </div>
</div> </div>
<pursueContent v-model="pursueShow" :dataList="dataVals" :title="processtitle" :updeteBool="true" /> <pursueContent v-model="pursueShow" :dataList="dataVals" :title="processtitle" :updeteBool="true" />
</template> </template>
<script setup> <script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue"; import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { xxcjAddEntity, xxcjUpdateEntity, xxcjSelectByid, xxcjSelectCzlcList, xxcjSelectListBc, xxcjDeletesBc } from "@/api/xxcj.js" import { xxcjAddEntity, xxcjUpdateEntity, xxcjSelectByid, xxcjSelectCzlcList, xxcjSelectListBc, xxcjDeletesBc, addEntity, xxcjXxzhs } from "@/api/xxcj.js"
import { EditPen, Delete } from '@element-plus/icons-vue' import { EditPen, Delete } from '@element-plus/icons-vue'
import { ref, defineExpose, onMounted, defineEmits, watch, getCurrentInstance } from "vue" import { ref, defineExpose, onMounted, defineEmits, watch, getCurrentInstance } from "vue"
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { getItem } from '@//utils/storage.js'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import pursueContent from "@/views/backOfficeSystem/HumanIntelligence/components/pursueContent.vue"; import pursueContent from "@/views/backOfficeSystem/HumanIntelligence/components/pursueContent.vue";
import * as MOSTY from "@/components/MyComponents/index"; import * as MOSTY from "@/components/MyComponents/index";
@ -135,15 +136,23 @@ const formData = ref();
const rules = ref({ const rules = ref({
qbmc: [{ required: true, message: "请输入情报标题", trigger: "blur" }], qbmc: [{ required: true, message: "请输入情报标题", trigger: "blur" }],
qbnr: [{ required: true, message: "请输入情报内容", trigger: "blur" }], qbnr: [{ required: true, message: "请输入情报内容", trigger: "blur" }],
bcnr: [{ required: true, message: "请输入续报内容", trigger: "blur" }],
}) })
watch(() => dialogForm.value, (val) => { watch(() => dialogForm.value, (val) => {
if (val) { if (val) {
formData.value = [ if (formType.value === 'followUpReport') {
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' }, formData.value = [
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%', rows: 100 }, { label: "情报标题", prop: "qbmc", type: "input", width: '45%', disabled: true },
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%', isImg: false }, { label: "续报内容", prop: "bcnr", type: "textarea", width: '100%', rows: 100 },
] ]
} else {
formData.value = [
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%', rows: 100 },
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%', isImg: false },
]
}
} }
}, { deep: true }) }, { deep: true })
const fjdz = ref() const fjdz = ref()
@ -155,13 +164,22 @@ const msgeDat = ref()
const title = ref("") const title = ref("")
const showPj = ref(false) const showPj = ref(false)
const disabled = ref(false) const disabled = ref(false)
/** 类型 add 新增 info 详情 edit 编辑 followUpReport 续报*/
const formType = ref('add')
// 初始化数据 // 初始化数据
const init = (type, row) => { const init = (type, row) => {
title.value = type == "add" ? "新增" : type == "info" ? "详情" : "编辑" const titleObj = {
add: "新增",
info: "详情",
edit: "编辑",
followUpReport: "续报"
}
title.value = titleObj[type]
disabled.value = type == 'info' ? true : false disabled.value = type == 'info' ? true : false
fjdz.value = [] fjdz.value = []
dialogForm.value = true; dialogForm.value = true;
if (type == 'info' || type == 'edit') { formType.value = type
if (type == 'info' || type == 'edit' || type == 'followUpReport') {
showPj.value = true showPj.value = true
msgeDat.value = row msgeDat.value = row
getqbcjPldb(row.id) getqbcjPldb(row.id)
@ -177,7 +195,7 @@ const init = (type, row) => {
// 根据id查询详情 // 根据id查询详情
const getDataById = (id) => { const getDataById = (id) => {
xxcjSelectByid({ id }).then((res) => { xxcjSelectByid({ id }).then((res) => {
console.log(res);
lcList.value = res.czlcList || [] lcList.value = res.czlcList || []
listQuery.value = res; listQuery.value = res;
listQuery.value.fjdz = res.fjdz ? res.fjdz?.split(",") : [] listQuery.value.fjdz = res.fjdz ? res.fjdz?.split(",") : []
@ -187,9 +205,9 @@ const getDataById = (id) => {
// 新增 // 新增
const submitForm = () => { const submitForm = () => {
loading.value = true
elform.value.submit(valid => { elform.value.submit(valid => {
if (valid) { if (valid) {
loading.value = true
const promes = { const promes = {
...listQuery.value, ...listQuery.value,
fjdz: listQuery.value.fjdz && listQuery.value.fjdz.length > 0 ? listQuery.value.fjdz.map(item => { fjdz: listQuery.value.fjdz && listQuery.value.fjdz.length > 0 ? listQuery.value.fjdz.map(item => {
@ -211,6 +229,19 @@ const submitForm = () => {
}).finally(() => { }).finally(() => {
loading.value = false loading.value = false
}) })
} else if (title.value == '续报') {
const params = {
qbid: listQuery.value.id,
czlx: '01',
ysnr: listQuery.value.qbnr,
bcnr: promes.bcnr,
}
addEntity(params).then((res) => {
emit("getList")
close()
}).finally(() => {
loading.value = false
})
} }
} }
}) })
@ -258,18 +289,25 @@ const getxxcjSelectListBc = (id, lx) => {
// 处理标签删除 // 处理标签删除
const handleDeleteTag = (tag) => { const handleDeleteTag = (tag) => {
proxy.$confirm("确定要删除吗?", "警告", { type: "warning" }).then(() => { proxy.$confirm("确定要删除吗?", "警告", { type: "warning" }).then(() => {
const userName = getItem('USERNAME')
if (userName == tag.bcrxm) {
xxcjDeletesBc({ ids: [tag.id] }).then(res => { xxcjDeletesBc({ ids: [tag.id] }).then(res => {
ElMessage({ ElMessage({
message: '删除成功', message: '删除成功',
type: 'success', type: 'success',
showClose: true,
})
getxxcjSelectListBc(msgeDat.value.id, '01')
getxxcjSelectListBc(msgeDat.value.id, '02')
})
} else {
proxy.$message({
message: '您不是该数据的创建人,不能删除',
type: 'warning',
showClose: true, showClose: true,
}) })
getxxcjSelectListBc(msgeDat.value.id, '01') }
getxxcjSelectListBc(msgeDat.value.id, '02')
})
}) })
} }
@ -278,10 +316,19 @@ const pursueShow = ref(false)
const dataVals = ref([]) const dataVals = ref([])
const processtitle = ref() const processtitle = ref()
const openPursue = (title, data) => { const openPursue = (title, data) => {
console.log(title, data); const userName = getItem('USERNAME')
pursueShow.value = true if (userName == data.bcrxm) {
processtitle.value = title pursueShow.value = true
dataVals.value = data processtitle.value = title
dataVals.value = data
} else {
proxy.$message({
message: '您不是该数据的创建人,不能进行操作',
type: 'warning',
showClose: true,
})
}
} }
defineExpose({ init }); defineExpose({ init });
</script> </script>

View File

@ -0,0 +1,236 @@
<template>
<el-dialog v-model="dialogVisible" title="转会商" width="800px" :before-close="handleClose" destroy-on-close>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px" label-position="right">
<!-- 会商标题 -->
<el-form-item label="会商标题" prop="hsbt">
<el-input v-model="formData.hsbt" placeholder="请输入会商标题" clearable />
</el-form-item>
<!-- 会商时间 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="会商开始时间" prop="hskssj">
<el-date-picker v-model="formData.hskssj" type="datetime" placeholder="选择开始时间" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会商结束时间" prop="hsjssj">
<el-date-picker v-model="formData.hsjssj" type="datetime" placeholder="选择结束时间" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<!-- 参会人员 -->
<el-form-item label="参会人员" prop="chryList">
<inputUser v-model:ids="formData.chryList" v-model:cName="formData.chryListCname" :Single="false" width="250"
:multiple="true">
</inputUser>
</el-form-item>
<!-- 会商内容 -->
<el-form-item label="会商内容" prop="hsnr">
<el-input v-model="formData.hsnr" type="textarea" :rows="4" placeholder="请输入会商内容" maxlength="1000"
show-word-limit />
</el-form-item>
<!-- 会商处置意见 -->
<el-form-item label="会商处置意见" prop="czyj">
<el-input v-model="formData.czyj" type="textarea" :rows="3" placeholder="请输入会商处置意见" maxlength="500"
show-word-limit />
</el-form-item>
<!-- 评论内容 -->
<el-form-item label="评论内容" prop="plnr">
<el-input v-model="formData.plnr" type="textarea" :rows="3" placeholder="请输入评论内容" maxlength="500"
show-word-limit />
</el-form-item>
<!-- ID字段通常隐藏 -->
<el-form-item v-if="formData.id" label="ID" prop="id" style="display: none;">
<el-input v-model="formData.id" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import { xxcjXxzhs } from '@/api/xxcj.js'
import inputUser from '@/components/inputCom/inputUser.vue'
// Props
const props = defineProps({
title: {
type: String,
default: '转会商'
},
row: {
type: Object,
default: () => ({})
}
})
// Emits
const emit = defineEmits(['close', 'ok'])
// 响应式数据
const formRef = ref()
const submitLoading = ref(false)
/** 保存DTO对象 - 会商信息表单数据 */
const formData = ref({
/** 主键ID */
// id: '',
/** 会商标题 */
hsbt: '',
/** 关联线索ID(采集ID) */
glxsid: '',
/** 关联线索名称 */
glxsmc: '',
/** 会商开始时间 */
hskssj: '',
/** 会商结束时间 */
hsjssj: '',
/** 参会人员ID数组 */
chryList: [],
/** 会商内容 */
hsnr: '',
/** 会商处置意见 */
czyj: '',
/** 评论内容 */
plnr: ''
})
// 表单验证规则
const rules = reactive({
hsbt: [{ required: true, message: '会商标题不能为空', trigger: 'blur' }],
// glxsid: [
// { required: true, message: '请选择关联线索', trigger: 'change' }
// ],
hsnr: [{ required: true, message: '请输入会商内容', trigger: 'blur' },],
czyj: [
{ required: true, message: '会商处置意见不能为空', trigger: 'blur' }
],
plnr: [{ required: true, message: '评论内容不能为空', trigger: 'blur' },],
hskssj: [
{ required: true, message: '请选择会商开始时间', trigger: 'change' }
],
hsjssj: [
{ validator: validateEndTime, trigger: 'change' }
]
})
const dialogVisible = ref(false)
// 验证结束时间
function validateEndTime(rule, value, callback) {
if (value && formData.value.hskssj) {
const startTime = new Date(formData.value.hskssj)
const endTime = new Date(value)
if (endTime <= startTime) {
callback(new Error('结束时间必须大于开始时间'))
return
}
}
callback()
}
// 初始化表单数据
function initFormData() {
formData.value = {
hsbt: '',
glxsid: props.row.id,
glxsmc: props.row.qbmc,
// tsypid: '',
hskssj: '',
hsjssj: '',
chryList: '',
hsnr: '',
czyj: '',
plnr: ''
}
}
// 重置表单
function resetForm() {
if (formRef.value) {
formRef.value.resetFields()
}
initFormData()
}
function strToArr(str) {
if (!str) return []
if (typeof str === 'string') {
return str.split(',')
}
if (!Array.isArray(str)) return []
return str
}
// 提交表单
function handleSubmit() {
formRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true
const chryList = strToArr(formData.value.chryList)
const params = { ...formData.value, chryList }
xxcjXxzhs(params).then(res => {
emit('close')
emit('ok')
}).finally(() => {
submitLoading.value = false
})
} else {
}
})
}
// 关闭对话框
function handleClose() {
emit('close')
}
onMounted(() => {
resetForm()
dialogVisible.value = true
})
onBeforeUnmount(() => {
dialogVisible.value = false
})
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
.help-text {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
:deep(.el-form-item__label) {
font-weight: 500;
}
:deep(.el-textarea__inner) {
resize: vertical;
}
</style>

View File

@ -72,35 +72,39 @@
<DictTag :tag="false" :value="row.czzt" :options="D_BZ_QBCZZT" /> <DictTag :tag="false" :value="row.czzt" :options="D_BZ_QBCZZT" />
</template> </template>
<template #lczt="{ row }"> <template #lczt="{ row }">
<DictTag :tag="false" :value="row.lczt" :options="D_BZ_LCZT" /> <DictTag :tag="false" :value="row.lczt" :options="D_BZ_LCZT" />
</template> </template>
<!-- 操作 --> <!-- 操作 -->
<template #controls="{ row }"> <template #controls="{ row }">
<!-- 01 提交 02 上报县局 03 上班市局 04 采纳 05 退回 06 打标签 07 转合成 08 转线索 09 转会商v-if="qxkz.deptLevel == '01'" --> <!-- 01 提交 02 上报县局 03 上班市局 04 采纳 05 退回 06 打标签 07 转合成 08 转线索 09 转会商v-if="qxkz.deptLevel == '01'" -->
<!-- 在提交和退回得状态才能进行上报 --> <!-- 在提交和退回得状态才能进行上报 -->
<el-link size="small" type="primary" @click="appearNewspapers(row)">上报</el-link> <el-link v-if="isShowBtn('上报')" size="small" type="primary" @click="appearNewspapers(row)">上报</el-link>
<!-- 只有上报状态才能进行采纳 --> <!-- 只有上报状态才能进行采纳 -->
<el-link size="small" type="primary" @click="cnMsg(row)">采纳</el-link> <el-link v-if="isShowBtn('采纳')" size="small" type="primary" @click="cnMsg(row)">采纳</el-link>
<!-- 只有上报状态才能回退 --> <!-- 只有上报状态才能回退 -->
<el-link size="small" type="primary" @click="rollbackNewspapers(row)">回退</el-link> <el-link v-if="isShowBtn('回退')" size="small" type="primary" @click="rollbackNewspapers(row)">回退</el-link>
<!-- 只有采纳状态才能分组 --> <!-- 只有采纳状态才能分组 -->
<el-link size="small" type="primary" @click="opneMsg(row)">分组</el-link> <el-link v-if="isShowBtn('分组')" size="small" type="primary" @click="opneMsg(row)">分组</el-link>
<!-- 所有状态都能进行转线索 --> <!-- 所有状态都能进行转线索 -->
<el-link size="small" type="primary" @click="FollowUpOnLeads(row)" >转线索</el-link> <el-link v-if="isShowBtn('转线索')" size="small" type="primary" @click="FollowUpOnLeads(row)">转线索</el-link>
<!-- 所有状态都能进行转合成 --> <!-- 所有状态都能进行转合成 -->
<el-link size="small" type="primary" @click="openFkDialogszl(row)">转合成</el-link> <el-link v-if="isShowBtn('转合成')" size="small" type="primary" @click="openFkDialogszl(row)">转合成</el-link>
<!-- 所有状态都能进行转会商 --> <!-- 所有状态都能进行转会商 -->
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转会商</el-link> <el-link v-if="isShowBtn('转会商')" size="small" type="primary"
@click="handleTransferMerchant(row)">转会商</el-link>
<!-- 只有领导有肯定 --> <!-- 只有领导有肯定 -->
<el-link size="small" type="primary" @click="affirm(row)" v-if="qxkz.roleCode">肯定</el-link> <el-link v-if="isShowBtn('肯定')" size="small" type="primary" @click="affirm(row)">肯定</el-link>
<el-link size="small" type="primary" @click="FollowUpOnDept(row)">关注部门</el-link> <el-link v-if="isShowBtn('关注部门')" size="small" type="primary" @click="FollowUpOnDept(row)">关注部门</el-link>
<!-- 市局能给所有数据创建标签 --> <!-- 市局能给所有数据创建标签 -->
<el-link size="small" type="primary" @click="openCustomTag(row)">创建</el-link> <el-link v-if="isShowBtn('打标签')" size="small" type="primary" @click="openCustomTag(row)">打标签</el-link>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link> <el-link v-if="isShowBtn('删除')" size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<el-link v-if="isShowBtn('修改', row)" size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
<el-link v-if="isShowBtn('续报', row)" size="small" type="primary"
@click="addEdit('followUpReport', row)">续报</el-link>
<el-link v-if="isShowBtn('详情')" size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
</template> </template>
</MyTable> </MyTable>
@ -131,7 +135,12 @@
@getList="getList" /> @getList="getList" />
<Fszl v-model="fszlShow" path="/xxcj/sendFqzl" :itemData="dataList" /> <Fszl v-model="fszlShow" path="/xxcj/sendFqzl" :itemData="dataList" />
<CustomTag v-model="customTagShow" :dataList="dataList" @getList="getList" :dict="{ D_XXCJ_BQLX }" /> <CustomTag v-model="customTagShow" :dataList="dataList" @getList="getList" :dict="{ D_XXCJ_BQLX }" />
<Configuration v-model="configurationShow" :dataList="dataList" @getList="getList" /> <Configuration v-model="configurationShow" :dataList="dataList" @getList="getList" />
<!-- 转会商 -->
<transferMerchant v-if="isShowTransferMerchantTc" :row="currRow" ref="transferMerchantRef" title="转会商"
@close="isShowTransferMerchantTc = false" @ok="getList" />
</template> </template>
<script setup> <script setup>
@ -151,6 +160,9 @@ import { getItem } from '@//utils/storage.js'
import Fszl from '@/views/backOfficeSystem/HumanIntelligence/components/fszl.vue' import Fszl from '@/views/backOfficeSystem/HumanIntelligence/components/fszl.vue'
import CustomTag from '../components/customTag.vue' import CustomTag from '../components/customTag.vue'
import Configuration from '../components/configuration.vue' import Configuration from '../components/configuration.vue'
import transferMerchant from "./components/transferMerchant.vue";
import { isShiQingZhi } from "@/utils/auth.js"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_BZ_BQJB, const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_BZ_BQJB,
D_GS_XS_QTLX, D_GS_ZDQT_LB, D_GS_XS_QTLX, D_GS_ZDQT_LB,
@ -169,14 +181,20 @@ const chooseData = (val) => {
}) })
tableList.value = val tableList.value = val
} }
/** 市情指 */
const cityIntelligenceCommand = isShiQingZhi()
const currRow = ref({})
const transferMerchantRef = ref()
const isShowTransferMerchantTc = ref(false)
const isShow = ref(false) const isShow = ref(false)
const searchConfiger = ref([ const searchConfiger = ref([
{ label: "时间", prop: "startTime", placeholder: "请选择时间", showType: "daterange" },
{ label: "所属单位", prop: "ssbmdm", placeholder: "请选择所属单位", showType: "department" },
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" }, { label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
{ label: "标签级别", prop: 'qbjb', placeholder: "请选择标签级别", showType: "select",options:D_BZ_BQJB}, { label: "标签级别", prop: 'qbjb', placeholder: "请选择标签级别", showType: "select", options: D_BZ_BQJB },
{ label: "情报处置状态", prop: 'lczt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_LCZT }, { label: "情报处置状态", prop: 'lczt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_LCZT },
{ label: "线索编号", prop: 'xsBh', placeholder: "请输入线索编号", showType: "input" }, // { label: "线索编号", prop: 'xsBh', placeholder: "请输入线索编号", showType: "input" },
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" }, { label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
]); ]);
const pageData = reactive({ const pageData = reactive({
@ -230,6 +248,16 @@ const cnMsg = (item) => {
} }
// 回退 // 回退
const rollbackNewspapers = (item) => { const rollbackNewspapers = (item) => {
if (item.lczt == '04') {
proxy.$message({
message: '已经采纳的信息无法回退',
type: 'warning',
showClose: true,
})
return
}
if (item.lczt == '03') { if (item.lczt == '03') {
proxy.$message({ proxy.$message({
message: '无法回退市局上报信息', message: '无法回退市局上报信息',
@ -264,13 +292,13 @@ const rollbackNewspapers = (item) => {
} }
// 上报 // 上报
const appearNewspapers = (item) => { const appearNewspapers = (item) => {
if ((item.lczt == '01' || item.lczt == '05') && item.qbjb == '00' && qxkz.deptLevel != '01') { if ((item.lczt == '01' || item.lczt == '05' || item.lczt == '02') && item.qbjb == '00' && qxkz.deptLevel != '01') {
proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => { proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => {
let promes = {} let promes = {}
if (qxkz.deptLevel == '01') { if (qxkz.deptLevel == '02') {
promes = { id: item.id, czzt: '03' } promes = { id: item.id, lczt: '03' }
} else { } else {
promes = { id: item.id, czzt: '02' } promes = { id: item.id, lczt: '02' }
} }
xxcjUpdateCzlc(promes).then(res => { xxcjUpdateCzlc(promes).then(res => {
proxy.$message({ type: "success", message: "上报成功" }); proxy.$message({ type: "success", message: "上报成功" });
@ -279,7 +307,7 @@ const appearNewspapers = (item) => {
}).catch(() => { }); }).catch(() => { });
} else { } else {
proxy.$message({ type: "warning", message: "只能上报提交的情报" }); proxy.$message({ type: "warning", message: "市局无法进行上报" });
} }
} }
// 分组 // 分组
@ -294,8 +322,14 @@ const opneMsg = (item) => {
// 打标签 // 打标签
const customTagShow = ref(false) const customTagShow = ref(false)
const openCustomTag = (item) => { const openCustomTag = (item) => {
customTagShow.value = true if (qxkz.depBool) {
dataList.value = item customTagShow.value = true
dataList.value = item
} else {
proxy.$message.warning('暂无权限')
}
} }
// 肯定 // 肯定
const affirm = (item) => { const affirm = (item) => {
@ -310,8 +344,13 @@ const affirm = (item) => {
// 配置关注部门 // 配置关注部门
const configurationShow = ref(false) const configurationShow = ref(false)
const FollowUpOnDept = (item) => { const FollowUpOnDept = (item) => {
configurationShow.value = true if (qxkz.depBool) {
dataList.value = item configurationShow.value = true
dataList.value = item
} else {
proxy.$message.warning('暂无权限')
}
} }
@ -353,14 +392,12 @@ const handleSumbit = () => {
// 搜索 // 搜索
const onSearch = (val) => { const onSearch = (val) => {
const { lrkssj, zxkssj } = val
const promes = { const promes = {
...pageData.pageConfiger, ...pageData.pageConfiger,
...val, ...val,
lrkssj: lrkssj ? lrkssj[0] : '', startTime: val.startTime ? val.startTime[0] : '',
lrjssj: lrkssj ? lrkssj[1] : '', endTime: val.endTime ? val.endTime[1] : '',
zxkssj: zxkssj ? zxkssj[0] : '',
zxjssj: zxkssj ? zxkssj[1] : '',
} }
queryFrom.value = { ...promes } queryFrom.value = { ...promes }
@ -473,7 +510,7 @@ const tabHeightFn = () => {
} else { } else {
pageData.tableHeight = window.innerHeight - 250; pageData.tableHeight = window.innerHeight - 250;
} }
window.onresize = function () { window.onresize = function() {
tabHeightFn(); tabHeightFn();
}; };
}; };
@ -487,31 +524,75 @@ const FollowUpOnLeads = (row) => {
}) })
return return
} else { } else {
proxy.$confirm("确定要转线索吗?", "警告", { type: "warning" }).then(() => { proxy.$confirm("确定要转线索吗?", "警告", { type: "warning" }).then(() => {
xxcjXxzsx({ ids: Array.isArray(row) ? row.join(',') : row.id }).then(res => { xxcjXxzsx({ ids: Array.isArray(row) ? row.join(',') : row.id }).then(res => {
proxy.$message({ type: "success", message: "转线索成功" }); proxy.$message({ type: "success", message: "转线索成功" });
getList(); getList();
})
}) })
})
} }
} }
// 发送指令 // 发送指令
const fszlShow = ref(false) const fszlShow = ref(false)
const openFkDialogszl = (row) => { const openFkDialogszl = (row) => {
if (!qxkz.depBool) { if (!qxkz.depBool) {
proxy.$message({ proxy.$message({
message: '权限不足', message: '权限不足',
type: 'warning', type: 'warning',
showClose: true, showClose: true,
}) })
return return
} else { } else {
fszlShow.value = true fszlShow.value = true
dataList.value = row dataList.value = row
} }
} }
/** 获取当前角色 */
function getRole() {
const { deptBizType, deptLevel } = getItem('deptId')[0]
/** 是否是市情指领导 */
const isShiQzLeader = getItem('roleList').find(item => item.roleCode == 'JS_666666') != undefined
if (isShiQzLeader) return '市情指领导'
/** 是否是市情指人员 */
const isShiQz = getItem('roleList').find(item => item.roleCode == 'JS_777777') != undefined
if (isShiQz) return '市情指挥人员'
/** 是否是县情指人员 */
const isXianQz = getItem('roleList').find(item => item.roleCode == 'JS_888888') != undefined
if (isXianQz) return '县情指人员'
return '部门'
}
/** 是否展示按钮 */
const isShowBtn = (btnName, row = {}) => {
/** @type {String} 流程状态01 提交 02 上报县局 03 上班市局 04 采纳 05 退回 06 打标签 08 转线索) */
const lczt = row.lczt
/** 按钮权限 */
const buttonPermissions = {
"市情指领导": ["肯定", "采纳", "回退", "分组", "转线索", "转合成", "转会商", "打标签", "修改", "详情", "关注部门"],
"市情指挥人员": ["采纳", "回退", "分组", "转线索", "转合成", "转会商", "打标签", "修改", "详情", "关注部门"],
"县情指人员": ["上报", "回退", "修改", "详情"],
"部门": ["上报", "新增", "修改", "续报", "详情"]
};
const role = getRole(); // 角色
const isHadAuth = buttonPermissions[role]?.includes(btnName) // 当前角色所有会显示的按钮
if (!isHadAuth) return false
// 拦截部分逻辑
if (role === '部门') {
if (btnName === '续报') return lczt != '01'
if (btnName === '修改') return lczt == '01'
// if(btnName === '上报') return lczt == '01'
}
return true
}
const handleTransferMerchant = (row) => {
currRow.value = row
isShowTransferMerchantTc.value = true
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -40,10 +40,10 @@
</template> </template>
<!-- 操作 --> <!-- 操作 -->
<template #controls="{ row }"> <template #controls="{ row }">
<el-link size="small" type="primary" @click="FollowUpOnLeads(row)">转线索</el-link> <!-- <el-link size="small" type="primary" @click="FollowUpOnLeads(row)">转线索</el-link>
<el-link size="small" type="primary" @click="openFszl(row)">转合成</el-link> <el-link size="small" type="primary" @click="openFszl(row)">转合成</el-link> -->
<el-link size="small" type="primary" @click="openCheckProcess(row)">补充信息</el-link> <el-link size="small" type="primary" @click="openCheckProcess(row)">补充信息</el-link>
<el-link size="small" type="primary" @click="openCheckProcessXb(row)"> 续报</el-link> <!-- <el-link size="small" type="primary" @click="openCheckProcessXb(row)"> 续报</el-link> -->
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link> <el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
</template> </template>
</MyTable> </MyTable>
@ -72,7 +72,7 @@
<MakeTag v-model="chooseRow" :dataList="dataList" :dict="{ D_BZ_CJLX, D_BZ_QBCZZT, D_GS_XS_LX, D_BZ_BQJB }" <MakeTag v-model="chooseRow" :dataList="dataList" :dict="{ D_BZ_CJLX, D_BZ_QBCZZT, D_GS_XS_LX, D_BZ_BQJB }"
@getList="getList" /> @getList="getList" />
<pursueContent v-model="pursueShow" :dataList="dataList" :title="processtitle" /> <pursueContent v-model="pursueShow" :dataList="dataList" :title="processtitle" />
<Fszl v-model="fszlShow" :itemData="dataList"/> <Fszl v-model="fszlShow" :itemData="dataList" path="/mosty-gsxt/qbcjZhc/sendFqzl" />
<!-- <SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj" <!-- <SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" /> --> :tacitly="tacitly" /> -->
</template> </template>
@ -106,9 +106,16 @@ const ids = ref([])
const tableList = ref([]); const tableList = ref([]);
onMounted(() => { onMounted(() => {
const { deptBizType, deptLevel } = getItem('deptId')[0] const { deptBizType, deptLevel } = getItem('deptId')[0]
qxkz.userName = getItem('USERNAME')
const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03' const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03'
qxkz.deptBizType = deptBizType qxkz.deptBizType = deptBizType
qxkz.deptLevel = Jb qxkz.deptLevel = Jb
if (deptBizType == '23' && Jb == '01') {
qxkz.depBool = true
} else {
qxkz.depBool = false
}
getRouter() getRouter()
tabHeightFn() tabHeightFn()
if (route.query.id) { if (route.query.id) {
@ -127,7 +134,8 @@ const chooseData = (val) => {
} }
const qxkz = reactive({ const qxkz = reactive({
deptBizType: "", deptBizType: "",
deptLevel: "" deptLevel: "",
userName:''
}) })
const list = ref() const list = ref()
const searchConfiger = ref(); const searchConfiger = ref();
@ -146,7 +154,7 @@ watch(() => D_BZ_BQJB, val => {
searchConfiger.value = [ searchConfiger.value = [
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" }, { label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
{ label: "情报处置状态", prop: 'lczt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_LCZT }, { label: "情报处置状态", prop: 'lczt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_LCZT },
{ label: "线索编号", prop: 'xsBh', placeholder: "请输入线索编号", showType: "input" }, // { label: "线索编号", prop: 'xsBh', placeholder: "请输入线索编号", showType: "input" },
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" }, { label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
] ]
}, { deep: true, immediate: true }) }, { deep: true, immediate: true })
@ -179,14 +187,6 @@ const queryFrom = ref({});
const chooseRow = ref(false) const chooseRow = ref(false)
const dataList = ref() const dataList = ref()
// 批量打标
const batchMark = () => {
chooseRow.value = true
dataList.value = tableList.value
}
// 搜索 // 搜索
const onSearch = (val) => { const onSearch = (val) => {
const { lrkssj, zxkssj } = val const { lrkssj, zxkssj } = val
@ -218,8 +218,6 @@ const changeSize = (val) => {
const getList = () => { const getList = () => {
pageData.tableConfiger.loading = true; pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...queryFrom.value, qbjb: routerMate.value.qbjbList }; let data = { ...pageData.pageConfiger, ...queryFrom.value, qbjb: routerMate.value.qbjbList };
xxcjSelectPage(data).then(res => { xxcjSelectPage(data).then(res => {
pageData.tableData = res.records || []; pageData.tableData = res.records || [];
pageData.total = res.total; pageData.total = res.total;
@ -273,18 +271,18 @@ const openCheckProcess = (item) => {
} }
// 续报 // 续报
const openCheckProcessXb = (item) => { const openCheckProcessXb = (item) => {
processtitle.value = '信息续报' if (qxkz.userName == item.xssbr) {
processtitle.value = '信息续报'
pursueShow.value = true pursueShow.value = true
dataList.value = item dataList.value = item
} } else {
// 转线索 proxy.$message({
const instQbcjZxs = (item) => { message: '您不是该情报的上报人,不能续报',
proxy.$confirm("确定要转线索吗?", "警告", { type: "warning" }).then(() => { type: 'warning',
qbcjZxs({ qbid: item.id }).then(res => { showClose: true,
proxy.$message({ type: "success", message: "转线索成功" });
getList();
}) })
}) }
} }
// 转线索 // 转线索
@ -295,7 +293,6 @@ const FollowUpOnLeads = (row) => {
type: 'warning', type: 'warning',
showClose: true, showClose: true,
}) })
return
} else { } else {
proxy.$confirm("确定要转线索吗?", "警告", { type: "warning" }).then(() => { proxy.$confirm("确定要转线索吗?", "警告", { type: "warning" }).then(() => {
xxcjXxzsx({ ids: Array.isArray(row) ? row.join(',') : row.id }).then(res => { xxcjXxzsx({ ids: Array.isArray(row) ? row.join(',') : row.id }).then(res => {
@ -309,8 +306,15 @@ const FollowUpOnLeads = (row) => {
// 转合成 // 转合成
const fszlShow = ref(false) const fszlShow = ref(false)
const openFszl = (item) => { const openFszl = (item) => {
fszlShow.value = true if (!qxkz.depBool) {
dataList.value = item proxy.$message({
message: '权限不足',
type: 'warning',
showClose: true,
})
} else { fszlShow.value = true
dataList.value = item }
} }
</script> </script>

View File

@ -76655,12 +76655,14 @@ export const bm = {
export const centralPoint = [ export const centralPoint = [
{ {
name: '墨脱县', name: '墨脱县',
ssbmdm:'540423000000',
point: [ point: [
95.33050808900407, 95.33050808900407,
29.322011545645807 29.322011545645807
] ]
}, { }, {
name: '巴宜区', name: '巴宜区',
ssbmdm:'540402000000',
point: [ point: [
94.36040092147607, 94.36040092147607,
29.637028970765996 29.637028970765996
@ -76668,30 +76670,35 @@ export const centralPoint = [
}, },
{ {
name: '波密县', name: '波密县',
ssbmdm:'540424000000',
point: [ point: [
95.7692249914358, 95.7692249914358,
29.85943760031867 29.85943760031867
] ]
}, { }, {
name: '察隅县', name: '察隅县',
ssbmdm:'540425000000',
point: [ point: [
97.46698612723947, 97.46698612723947,
28.661228694163327 28.661228694163327
] ]
}, { }, {
name: '工布江达县', name: '工布江达县',
ssbmdm:'540421000000',
point: [ point: [
93.24660931130188, 93.24660931130188,
29.88459424127838 29.88459424127838
] ]
}, { }, {
name: '朗县', name: '朗县',
ssbmdm:'540426000000',
point: [ point: [
93.07449497318652, 93.07449497318652,
29.045416229209337 29.045416229209337
] ]
}, { }, {
name: '米林县', name: '米林县',
ssbmdm:'540422000000',
point: [ point: [
94.21305189935441, 94.21305189935441,
29.21583429482142 29.21583429482142

View File

@ -46,17 +46,22 @@ import Footer from './footer.vue'
// import useCallModule from '../sdk/call.js' // import useCallModule from '../sdk/call.js'
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
// const Call = useCallModule() // const Call = useCallModule()
window.lemon.login.login({ try {
username: "linzhigongan1", window.lemon.login.login({
password: "linzhigongan1", username: "linzhigongan1",
realm: "puc.com", password: "linzhigongan1",
webpucUrl: "https://192.168.0.1:16888", realm: "puc.com",
}).then(res => { webpucUrl: "https://192.168.0.1:16888",
console.log(res,"登录成功"); }).then(res => {
}).catch(err => { console.log(res,"登录成功");
console.log(err,"登录失败"); }).catch(err => {
console.log(err,"登录失败");
}) })
} catch (error) {
console.log('error: ', error);
}
const props = defineProps({ const props = defineProps({

View File

@ -0,0 +1,104 @@
<template>
<el-dialog v-model="dialogVisible" title="会商反馈" width="600px" :before-close="handleClose" destroy-on-close>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="反馈内容" prop="fknr">
<el-input v-model="form.fknr" type="textarea" :rows="6" placeholder="请输入反馈内容" maxlength="500" show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" :loading="loading" @click="handleSave">
保存
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { wshsHsfk } from '@/api/huiShangyp/onlineConsultationRoom.js'
const emit = defineEmits(['success'])
const dialogVisible = ref(false)
const loading = ref(false)
const formRef = ref()
const currentHsid = ref('')
const form = reactive({
fknr: ''
})
const rules = {
fknr: [
{ required: true, message: '请输入反馈内容', trigger: 'blur' },
{ min: 2, message: '反馈内容至少2个字符', trigger: 'blur' }
]
}
// 打开弹框
const open = (hsid) => {
currentHsid.value = hsid
form.fknr = ''
dialogVisible.value = true
}
// 关闭弹框
const handleClose = () => {
dialogVisible.value = false
form.fknr = ''
currentHsid.value = ''
if (formRef.value) {
formRef.value.resetFields()
}
}
// 保存反馈
const handleSave = async () => {
if (!formRef.value) return
try {
const valid = await formRef.value.validate()
if (!valid) return
loading.value = true
const params = {
hsid: currentHsid.value,
fknr: form.fknr
}
await wshsHsfk(params)
ElMessage.success('反馈保存成功')
handleClose()
emit('success') // 通知父组件刷新列表
} catch (error) {
ElMessage.error('保存失败,请重试')
} finally {
loading.value = false
}
}
defineExpose({
open
})
</script>
<style scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
:deep(.el-textarea__inner) {
resize: vertical;
}
</style>

View File

@ -0,0 +1,197 @@
<template>
<el-dialog
v-model="dialogVisible"
title="查看反馈"
width="800px"
:before-close="handleClose"
>
<div class="feedback-container" v-loading="loading">
<!-- 反馈列表 -->
<div class="feedback-list" v-if="currFkListList.length > 0">
<div
v-for="(feedback, index) in currFkListList"
:key="index"
class="feedback-item"
>
<div class="feedback-header">
<div class="user-info">
<el-avatar :size="32" :src="feedback.avatar">
{{ feedback.fkrxm?.charAt(0) || '用' }}
</el-avatar>
<span class="username">{{ feedback.fkrxm || '匿名用户' }}</span>
</div>
<div class="feedback-time" v-if="feedback.fksj">
{{ formatTime(feedback.fksj) }}
</div>
</div>
<div class="feedback-content">
{{ feedback.fknr }}
</div>
</div>
</div>
<!-- 暂无反馈 -->
<el-empty
v-else
description="暂无反馈信息"
:image-size="120"
/>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">关闭</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, computed } from 'vue'
const dialogVisible = ref(false)
const loading = ref(false)
const currFkListList = ref([])
// // 计算所有反馈列表
// const currFkListList = computed(() => {
// let allFeedbacks = []
// if (currFkListList.value && Array.isArray(currFkListList.value)) {
// currFkListList.value.forEach(item => {
// if (item.fkList && Array.isArray(item.fkList)) {
// item.fkList.forEach(feedback => {
// allFeedbacks.push({
// ...feedback,
// // 如果有评论内容,也一并显示
// plnr: item.plnr
// })
// })
// }
// })
// }
// // 按时间排序(如果有时间字段)
// return allFeedbacks.sort((a, b) => {
// if (a.fksj && b.fksj) {
// return new Date(b.fksj) - new Date(a.fksj)
// }
// return 0
// })
// })
// 打开弹框
const open = (fkList) => {
currFkListList.value = fkList || []
dialogVisible.value = true
}
// 关闭弹框
const handleClose = () => {
dialogVisible.value = false
currFkListList.value = []
}
// 格式化时间
const formatTime = (timeStr) => {
if (!timeStr) return ''
try {
const date = new Date(timeStr)
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
} catch (error) {
return timeStr
}
}
defineExpose({
open
})
</script>
<style scoped>
.feedback-container {
max-height: 500px;
overflow-y: auto;
}
.feedback-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.feedback-item {
border: 1px solid #e4e7ed;
border-radius: 8px;
padding: 16px;
background-color: #fafafa;
transition: all 0.3s ease;
}
.feedback-item:hover {
border-color: #409eff;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}
.feedback-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.user-info {
display: flex;
align-items: center;
gap: 8px;
}
.username {
font-weight: 500;
color: #303133;
font-size: 14px;
}
.feedback-time {
font-size: 12px;
color: #909399;
}
.feedback-content {
color: #606266;
line-height: 1.6;
font-size: 14px;
white-space: pre-wrap;
word-break: break-word;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
/* 滚动条样式 */
.feedback-container::-webkit-scrollbar {
width: 6px;
}
.feedback-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.feedback-container::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.feedback-container::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style>

View File

@ -50,9 +50,9 @@ const formData = ref([
{ label: "会商开始时间", prop: "hskssj", type: "datetime" }, { label: "会商开始时间", prop: "hskssj", type: "datetime" },
{ label: "会商结束时间", prop: "hsjssj", type: "datetime" }, { label: "会商结束时间", prop: "hsjssj", type: "datetime" },
{ label: "会商内容", prop: "hsnr", type: "textarea", width: "100%" }, { label: "会商内容", prop: "hsnr", type: "textarea", width: "100%" },
{ label: "关联线索", prop: "glxsmc", type: "slot", }, // { label: "关联线索", prop: "glxsmc", type: "slot", },
{ label: "会商标题", prop: "hsbt", type: "input" }, { label: "会商标题", prop: "hsbt", type: "input" },
{ label: "参会人员", prop: "chryList", type: "slot" ,width:'100%'}, // { label: "参会人员", prop: "chryList", type: "slot" ,width:'100%'},
]); ]);
const listQuery = ref({}); //表单 const listQuery = ref({}); //表单
const loading = ref(false); const loading = ref(false);

View File

@ -2,12 +2,11 @@
<div class="titleBox"> <div class="titleBox">
<PageTitle title="网上会议室"> <PageTitle title="网上会议室">
<el-button type="primary" @click="addEdit('add', '')"> <el-button type="primary" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon> <el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">新增</span> <span style="vertical-align: middle">新增</span>
</el-button> </el-button>
<el-button type="primary" @click="openDemo">
<span style="vertical-align: middle">DEMO</span>
</el-button>
</PageTitle> </PageTitle>
</div> </div>
<div ref="searchBox"> <div ref="searchBox">
@ -26,44 +25,54 @@
</div> </div>
<div class="mid"> <div class="mid">
<div class="left"> <div class="left">
<div class="title ellipsis">参会人员{{ item.chry }}</div> <!-- <div class="title ellipsis">参会人员{{ item.chry }}</div> -->
<div class="desc"> <div class="desc">
<div class="info ellipsis" v-for="(el, i) in item.xsplList" :key="i">{{ i + 1 }}{{ el.plnr }}</div> <div class="info ellipsis" v-for="(el, i) in item.xsplList" :key="i">{{ i + 1 }}{{ el.plnr }}</div>
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<el-button type="primary" size="small" @click="joinMeeting(item)">加入会议</el-button> <el-button type="primary" size="small" @click="joinMeeting(item, '会议')">加入会议</el-button>
<el-button type="primary" size="small">反馈情况</el-button> <el-button type="primary" size="small" @click="feedBack(item)">反馈情况</el-button>
<el-button type="primary" size="small">处置下发</el-button> <el-button v-if="cityIntelligenceCommand" type="primary" size="small"
@click="disposeIssue(item)">处置下发</el-button>
</div> </div>
</div> </div>
<div class="bottom"> <div class="bottom">
<el-popover placement="top" :visible="item.visible" :width="400" trigger="click"> <el-link type="primary" @click="viewFeedback(item)">
<el-icon>
<View />
</el-icon>查看反馈
</el-link>
<el-popover placement="top" :visible="item.visible" :width="400" trigger="click">
<template #reference> <template #reference>
<el-link type="primary"><el-icon><ChatDotSquare /></el-icon>评论</el-link> <el-link type="primary"><el-icon>
<ChatDotSquare />
</el-icon>评论</el-link>
</template> </template>
<MOSTY.Other filterable style="width: 100%;" v-model="comments" type="textarea" rows="3" clearable placeholder="发表评论"/> <MOSTY.Other filterable style="width: 100%;" v-model="comments" type="textarea" rows="3" clearable
placeholder="发表评论" />
<div class="mt10 flex just-center"> <div class="mt10 flex just-center">
<el-button size="small" type="primary" @click.stop="handleSumbit(item)">发送</el-button> <el-button size="small" type="primary" @click.stop="handleSumbit(item)">发送</el-button>
</div> </div>
</el-popover> </el-popover>
<el-link type="primary" ><el-icon><VideoPlay /></el-icon>会议回放</el-link> <el-link type="primary"><el-icon>
<el-link type="primary" @click="addEdit('edit', item)"><el-icon><Edit /></el-icon>编辑</el-link> <VideoPlay />
<el-link type="danger" @click="delDictItem(item.id)"><el-icon><Delete /></el-icon>删除</el-link> </el-icon>会议回放</el-link>
<el-link type="primary" @click="addEdit('edit', item)"><el-icon>
<Edit />
</el-icon>编辑</el-link>
<el-link type="danger" @click="delDictItem(item.id)"><el-icon>
<Delete />
</el-icon>删除</el-link>
</div> </div>
</li> </li>
<MOSTY.Empty :show="!pageData.loading && pageData.list.length <= 0"></MOSTY.Empty> <MOSTY.Empty :show="!pageData.loading && pageData.list.length <= 0"></MOSTY.Empty>
</ul> </ul>
<Pages <Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
@changeNo="changeNo" ...pageData.pageConfiger,
@changeSize="changeSize" total: pageData.total
:tableHeight="pageData.tableHeight" }"></Pages>
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div> </div>
<!-- 详情 --> <!-- 详情 -->
<DetailForm ref="detailDiloag" @updateDate="getList" /> <DetailForm ref="detailDiloag" @updateDate="getList" />
@ -71,339 +80,332 @@
<ConferenceRoom v-model="conferenceRoomVisible" titleValue="会议详情" /> <ConferenceRoom v-model="conferenceRoomVisible" titleValue="会议详情" />
<!-- 音视频会议窗口 --> <!-- 音视频会议窗口 -->
<MeetingView v-model="openMeeting" v-if="openMeeting" ></MeetingView> <MeetingView ref="refMeetingView" :update="updateItem"></MeetingView>
<!-- 反馈弹窗 -->
<FeedbackForm ref="feedbackFormRef" @success="getList" />
<!-- 查看反馈弹窗 -->
<ViewFeedback ref="viewFeedbackRef" />
<Information v-model="showDialog" title="发送指令" @submit="seedFqzl" @close='close'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="meeting"
:tacitly="tacitly" />
</Information>
</template> </template>
<script setup> <script setup>
import { ElMessageBox } from "element-plus"; import MeetingView from '@/components/Consultation/demo.vue'
import * as MOSTY from "@/components/MyComponents/index"; import { ElMessageBox } from "element-plus";
import MeetingView from "@/views/consultation/components/meetingView.vue"; import * as MOSTY from "@/components/MyComponents/index";
import PageTitle from "@/components/aboutTable/PageTitle.vue"; import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Pages from "@/components/aboutTable/Pages.vue"; import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue"; import Search from "@/components/aboutTable/Search.vue";
import DetailForm from "./components/detailForm.vue"; import DetailForm from "./components/detailForm.vue";
import RoomDetail from "./components/roomDetail.vue"; import RoomDetail from "./components/roomDetail.vue";
import { useRoute, useRouter } from 'vue-router'; import FeedbackForm from "./components/FeedbackForm.vue";
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js"; import ViewFeedback from "./components/ViewFeedback.vue";
import { reactive, ref, onMounted, getCurrentInstance,nextTick } from "vue"; import { useRoute, useRouter } from 'vue-router';
import ConferenceRoom from "./components/Communications/conferenceRoom.vue"; import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
const router = useRouter(); import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
const route = useRoute(); import ConferenceRoom from "./components/Communications/conferenceRoom.vue";
const { proxy } = getCurrentInstance(); import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
const detailDiloag = ref(); import Information from "@/views/home/model/information.vue";
const searchBox = ref(); //搜索框 import { isShiQingZhi } from "@/utils/auth.js"
const openMeeting = ref(false); // 打开会议窗口
const searchConfiger = ref([
{
label: "会议主题",
prop: "hsbt",
placeholder: "请输入会议主题",
showType: "input"
},
{
label: "会议时间",
prop: "daterange",
showType: "datetimerange"
},
]);
const comments = ref(''); // 评论内容
const queryFrom = ref({});
const pageData = reactive({
list: [],
loading: false,
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
});
const jsonData = ref('')
onMounted(() => {
jsonData.value = require('@/views/consultation/components/zh_CN.json');
nextTick(()=>{
Init();
})
getList();
tabHeightFn();
});
const Init = () => { const router = useRouter();
let token = window.localStorage.getItem("rhToken"); const route = useRoute();
if (!token) { const { proxy } = getCurrentInstance();
let userInfo = { const detailDiloag = ref();
username: "linzhigongan2", const searchBox = ref(); //搜索框
password: "linzhigongan2", const openMeeting = ref(false); // 打开会议窗口
realm: "puc.com", const refMeetingView = ref()
webpucUrl: "https://89.40.9.95:16888" const feedbackFormRef = ref() // 反馈弹窗引用
}; const viewFeedbackRef = ref() // 查看反馈弹窗引用
lemon.login.login(userInfo).then((esacpe) => { const semdFqzlRef = ref()
token = esacpe.token; /** 发送指令Item */
window.localStorage.setItem("rhToken", esacpe.token); const itemData = ref({})
getLoginAccountInfo(); /** 市情指 */
fetchConferences() const cityIntelligenceCommand = ref(isShiQingZhi())
// 注册会议管理相关事件 /** 下发指令 */
useConfernceEvent() const showDialog = ref(false)
}); const tacitly = {
// title:'ryXm'
}
const searchConfiger = ref([
{
label: "会议主题",
prop: "hsbt",
placeholder: "请输入会议主题",
showType: "input"
},
{
label: "会议时间",
prop: "daterange",
showType: "datetimerange"
},
]);
const comments = ref(''); // 评论内容
const queryFrom = ref({});
const pageData = reactive({
list: [],
loading: false,
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
});
const jsonData = ref('')
/** 当前行数据 */
const currRow = ref({})
onMounted(() => {
jsonData.value = require('@/components/Consultation/components/zh_CN.json');
getList();
tabHeightFn();
});
const updateItem = (item) => {
qcckPost(item, '/mosty-gsxt/wshs/update').then(res => {
getList();
})
}
// 搜索
const onSearch = (val) => {
queryFrom.value = { ...val };
if (val.daterange && val.daterange.length > 0) {
queryFrom.value.startTime = val.daterange[0];
queryFrom.value.endTime = val.daterange[1];
} else { } else {
ConnectWebsocket(token); delete queryFrom.value.startTime;
delete queryFrom.value.endTime;
} }
pageData.pageConfiger.pageCurrent = 1;
getList();
}; };
const ConnectWebsocket = (token) => { const changeNo = (val) => {
lemon.login.reConnectWebsocket({ pageData.pageConfiger.pageCurrent = val;
username: "linzhigongan2", getList();
realm: "puc.com", };
webpucUrl: "https://89.40.9.95:16888", const changeSize = (val) => {
token: token pageData.pageConfiger.pageSize = val;
}).then((resp) => { getList();
if(resp.result != 0){
ElMessage.error(jsonData.value['errorCode'][resp.result]);
exsit()
}else{
getLoginAccountInfo()
fetchConferences()
// 注册会议管理相关事件
useConfernceEvent()
}
});
}; };
const getLoginAccountInfo =() =>{ // 获取列表
lemon.login.getLoginAccountInfo().then(res => { const getList = () => {
let info = JSON.stringify(res.account_info) pageData.loading = true;
window.localStorage.setItem("rhInfo",info); let data = { ...pageData.pageConfiger, ...queryFrom.value };
window.localStorage.setItem("user_basedata_id",res.account_info.basedata_id); delete data.daterange; // 删除daterange字段
}).catch(err => { if (route.query.tsypid) data.tsypid = route.query.tsypid;
qcckGet(data, '/mosty-gsxt/wshs/selectPage').then(res => {
let arr = res.records || [];
arr.forEach(item => {
item.chry = item.chryList ? item.chryList.map(el => el.chryxm).join('、') : '';
item.sjry = item.xsryList ? item.xsryList.map(el => el.xm).join('、') : '';
});
pageData.list = arr;
pageData.total = res.total;
pageData.loading = false;
}).catch(() => { pageData.loading = false; })
};
}) // 提交评论
} const handleSumbit = (item) => {
if (!comments.value) return proxy.$message({ type: "warning", message: "评论内容不能为空" });
const exsit = () =>{ proxy.$message({ type: "success", message: "评论已发送" });
lemon.login.logout().then(res=> { qcckPost({ id: item.id, plnr: comments.value }, '/mosty-gsxt/wshs/addWshyPl').then((res) => {
}).catch(err=> {
})
}
function openDemo() {
const NPShref = router.resolve({ path: '/consultation', query: {}});
window.open(NPShref.href, "_blank");
}
// 搜索
const onSearch = (val) => {
queryFrom.value = { ...val };
if (val.daterange && val.daterange.length > 0) {
queryFrom.value.startTime = val.daterange[0];
queryFrom.value.endTime = val.daterange[1];
} else {
delete queryFrom.value.startTime;
delete queryFrom.value.endTime;
}
pageData.pageConfiger.pageCurrent = 1;
getList(); getList();
}; item.visible = false; // 关闭评论弹窗
comments.value = ''; // 清空评论内容
})
};
// 加入会议
const joinMeeting = (item, type) => {
item.number = item.hybh;
refMeetingView.value.openInit(item, type)
};
// 反馈情况
const feedBack = (item) => {
feedbackFormRef.value.open(item.id);
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
// 获取列表 // 查看反馈
const getList = () => { const viewFeedback = (item) => {
pageData.loading = true; viewFeedbackRef.value.open(item.fkList || []);
let data = { ...pageData.pageConfiger, ...queryFrom.value }; };
delete data.daterange; // 删除daterange字段
if(route.query.tsypid) data.tsypid = route.query.tsypid;
qcckGet(data,'/mosty-gsxt/wshs/selectPage').then(res=>{
let arr = res.records || [];
arr.forEach(item => {
item.chry = item.chryList ? item.chryList.map(el => el.chryxm).join('、') : '';
item.sjry = item.xsryList ? item.xsryList.map(el => el.xm).join('、') : '';
});
pageData.list = arr;
pageData.total = res.total;
pageData.loading = false;
}).catch(()=>{ pageData.loading = false; })
};
// 提交评论 // 删除
const handleSumbit = (item) => { const delDictItem = (id) => {
if (!comments.value) return proxy.$message({ type: "warning", message: "评论内容不能为空" }); proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
proxy.$message({ type: "success", message: "评论已发送" }); qcckPost({ id }, '/mosty-gsxt/wshs/delete').then(() => {
qcckPost({id:item.id,plnr:comments.value},'/mosty-gsxt/wshs/addWshyPl').then((res)=>{ proxy.$message({ type: "success", message: "删除成功" });
getList();
item.visible = false; // 关闭评论弹窗
comments.value = ''; // 清空评论内容
})
};
// 加入会议
const joinMeeting = (item) => {
console.log(item.hybh,'===========00');
ElMessageBox.confirm('确定开始会议?','提示',{ confirmButtonText:'确定', cancelButtonText:'取消', type:'warning' }).then(res=>{
openMeeting.value = true;
nextTick(()=>{
let params = {
"number": it.number,
"nick": it.subject,
"mute_status": it.status,
"microphone_status": 1,
"camera_status": 1
}
// lemon.conference.enterConferenceByNumber(params).then(res=> {
// console.log(res,'加入会议......');
// }).catch(err=> {
// console.log(err,' 加入会议失败......');
// })
})
}).catch(()=>{
})
// conferenceRoomVisible.value = true;
// qcckPost({id:item.id},'/mosty-gsxt/wshs/addWshyRy').then((res)=>{
// getList();
// })
};
// 删除
const delDictItem = (id) =>{
proxy.$confirm("确定要删除", "警告", {type: "warning"}).then(() => {
qcckPost({id},'/mosty-gsxt/wshs/delete').then(()=>{
proxy.$message({ type: "success", message: "删除成功" });
getList(); getList();
}) })
}).catch(() => {}); }).catch(() => { });
} }
// 详情 // 详情
const addEdit = (type, row) => { const addEdit = (type, row) => {
detailDiloag.value.init(type, row); detailDiloag.value.init(type, row);
}; };
// 表格高度计算 // 表格高度计算
const tabHeightFn = () => { const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250; pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () { window.onresize = function() {
tabHeightFn(); tabHeightFn();
}; };
}; };
// 会议详情弹窗 // 会议详情弹窗
const conferenceRoomVisible = ref(false); const conferenceRoomVisible = ref(false);
const seedFqzl = () => {
semdFqzlRef.value.getsendFqzl()
}
const handleClose = () => {
showDialog.value = false;
}
// 处置下发
const disposeIssue = (item) => {
showDialog.value = true;
itemData.value = item
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.el-loading-mask { .el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important; background: rgba(0, 0, 0, 0.5) !important;
} }
.tabBox {
.pageSearch { .tabBox {
margin-bottom: 0 !important; .pageSearch {
.box { margin-bottom: 0 !important;
align-items: center !important;
} .box {
} align-items: center !important;
:deep(.pageSearch .box .item) {
margin-bottom: 0 !important;
} }
} }
.btns {
padding: 10px 20px; :deep(.pageSearch .box .item) {
margin-bottom: 0 !important;
} }
.list { }
height: calc(100% - 10px);
gap: 10px; .btns {
margin: 0 15px; padding: 10px 20px;
overflow: auto; }
.list-item {
display: inline-block; .list {
border: 1px solid #ccc; height: calc(100% - 10px);
height: 296px; gap: 10px;
width: 380px; margin: 0 15px;
box-sizing: border-box; overflow: auto;
border-radius: 5px;
.list-item {
display: inline-block;
border: 1px solid #ccc;
height: 296px;
width: 380px;
box-sizing: border-box;
border-radius: 5px;
padding: 10px;
margin: 10px 5px;
&:hover {
border-color: rgb(124, 195, 253);
background-color: rgba(190, 233, 255, 0.582);
}
&:hover .mid {
border-color: rgb(124, 195, 253);
}
&:hover .desc {
background-color: rgb(190, 233, 255);
}
.title {
color: black;
font-size: 14px;
font-weight: 700;
margin-bottom: 5px;
}
.info {
color: #a5a1a1;
font-size: 12px;
line-height: 1.5;
}
.desc {
margin-top: 5px;
background-color: rgb(242, 242, 242);
width: 260px;
height: 80px;
padding: 10px; padding: 10px;
margin: 10px 5px; box-sizing: border-box;
&:hover { overflow: hidden;
border-color: rgb(124, 195, 253); overflow-y: auto;
background-color: rgba(190, 233, 255, 0.582); }
}
&:hover .mid {
border-color: rgb(124, 195, 253);
}
&:hover .desc {
background-color: rgb(190, 233, 255);
}
.title {
color: black;
font-size: 14px;
font-weight: 700;
margin-bottom: 5px;
}
.info {
color: #a5a1a1;
font-size: 12px;
line-height: 1.5; .mid {
} border: 1px dashed rgb(124, 195, 253);
.desc { border-left: 0;
margin-top: 5px; border-right: 0;
background-color: rgb(242, 242, 242); padding: 10px 0;
width: 260px; display: flex;
height: 80px; justify-content: space-between;
padding: 10px;
box-sizing: border-box; .left {
overflow: hidden; width: calc(100% - 80px);
overflow-y: auto;
} .title {
.mid { font-size: 14px;
border: 1px dashed rgb(124, 195, 253); color: black;
border-left: 0; margin-bottom: 5px;
border-right: 0;
padding: 10px 0;
display: flex;
justify-content: space-between;
.left {
width: calc(100% - 80px);
.title {
font-size: 14px;
color: black;
margin-bottom: 5px;
}
.info {
font-size: 12px;
color: #a5a1a1;
line-height: 1.5;
}
} }
.right { .info {
width: 80px; font-size: 12px;
.el-button + .el-button { color: #a5a1a1;
margin-left: 0; line-height: 1.5;
margin-top: 5px;
}
} }
} }
.bottom {
display: flex; .right {
justify-content: flex-end; width: 80px;
:deep(.el-link--inner) {
display: flex; .el-button+.el-button {
align-items: center; margin-left: 0;
gap: 2px; margin-top: 5px;
} }
} }
} }
.bottom {
display: flex;
justify-content: flex-end;
:deep(.el-link--inner) {
display: flex;
align-items: center;
gap: 2px;
}
}
} }
}
</style> </style>

View File

@ -1,714 +0,0 @@
// import { Notification } from '@arco-design/web-vue';
import { ElNotification, ElMessage } from 'element-plus'
import emitter from "@/utils/eventBus.js";
// import handleCallingNotification from '../hooks/callingNotification';
let call_id;
let hangup_event_cb_id;
let force_hangup_event_cb_id;
let answer_ack_cb_id;
let incoming_cb_id;
let floor_grant_cb_id;
// Whether it is a pushVideoFile call
// 是否为视频推送的呼叫
let pushing_video = false;
// monitor call list
// 值守呼叫列表
const monitor_call_list = [];
export default function useCallModule() {
// we allow only one call exist in demo.but actually,sdk supports more
/**
* make private vioce call,return nothing,receive result in callback
* This interface has been expanded to support makeGroupVoiceCall、makeDispatcherVoiceCall、makeConferenceVoiceCall、makeCrosspatchVoiceCall
* 这个接口已扩展,除了支持语音单呼外,还支持语音组呼、语音呼叫调度员、语音会议、群组呼叫。
* @param record who you wanna call
* @returns
*/
const makeVoiceCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 })
?.then((resp) => {
call_id = resp.call_id;
console.info('makeVoiceCall succ,registerCallEstablishEvent', call_id);
});
// test
// window.lemon.call.changeCamera({ call_id, target_camera: 0 });
// also can use this makecall method,the method provides the most comprehensive call capability
// For example, Voice private call, ensure that the basedata_id is a private
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 0,
// call_mode: 0,
// duplex_flag: 0,
// },
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
// For example, Voice group call,ensure that the basedata_id is a group
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 1,
// call_mode: 0,
// duplex_flag: 0, // group call ,the value must be 0
// },
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
};
/**
* make private video call,call with vioce and video,return nothing,receive result in callback
* This interface has been expanded to support makeGroupVideoCall、makeDispatcherVideoCall、makeConferenceVideoCall
* 这个接口已扩展,除了支持视频单呼外,还支持视频组呼、视频呼叫调度员、视频会议
* @param record who you wanna call
* @returns
*/
const makeVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3 })
?.then((resp) => {
call_id = resp.call_id;
console.warn('makeVideoCall succ,call_id=', call_id);
});
// also can use this makecall method,the method provides the most comprehensive call capability
// For example, Video private call (with voice), ensure that the basedata_id is a private
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 11,
// call_mode: 2,
// duplex_flag: 1,
// },
// video_frame_size: window.lemon.call.getMaxFrameSize(),
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
// For example, Video group call,ensure that the basedata_id is a group
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 13,
// call_mode: 2,
// duplex_flag: 0, // group call ,the value must be 0
// },
// video_frame_size: window.lemon.call.getMaxFrameSize(),
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
};
const makeGroupVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeGroupVideoCall({
basedata_id: record.basedata_id,
video_frame_size: 3,
})
?.then((resp) => {
console.log('makeGroupVideoCall call_id = ', call_id);
call_id = resp.call_id;
});
};
const makeGroupVoiceCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeGroupVoiceCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
const makeCrosspatchVoiceCall = (record) => {
window.lemon.call
.makeCrosspatchVoiceCall({ basedata_id: record.basedata_id })
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 视频上拉
* make pure video call,only video, no voice
* @param record who you wanna call
* @returns
*/
const pureVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.pullVideo({ basedata_id: record.basedata_id, hook_flag: 0 })
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 环境监听
* @param record
*/
const voiceDetect = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 0,
call_mode: 0,
duplex_flag: 0,
ambience_flag: 1,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 环境监视
* @param record
*/
const videoDetect = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 11,
call_mode: 2,
duplex_flag: 0,
ambience_flag: 1,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 音频会议
* @param record
*/
const makeConferenceVoiceCall = (record) => {
window.lemon.call
.makeConferenceVoiceCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 音视频会议
* @param record
*/
const makeConferenceVideoCall = (record) => {
window.lemon.call
.makeConferenceVideoCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
// 广播呼叫
// Broadcast Call
const makeBroadcastCall = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 3,
call_mode: 0,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* hangup call
*/
const hangup = (id) => {
console.info('try hangup,call_id=', call_id);
console.info('try hangup,id=', id);
window.lemon.call
.hangupCall({ call_id: id || call_id })
?.then(() => {
call_id = undefined;
window.calling_conference = undefined;
// console.log('22222registerCallEstablishEven');
})
.catch((err) => {
console.error('hangup call error,', err);
});
};
/**
* 接听呼叫
* answer call
*/
const answerCall = () => {
ElNotification.close(call_id);
window.lemon.call
.answerCall({ call_id })
?.then(() => {
// display alert ui
ElNotification.close(call_id);
})
.catch((err) => {
console.error('answer call error,', err);
});
};
// 禁麦
// mute the microphone
const setMuteMic = (mute) => {
return window.lemon.call.muteMic({
call_id,
is_mute: mute,
});
};
// 禁摄像头
// disable the camera
const setMuteCamera = (mute) => {
return window.lemon.call.muteCamera({
call_id,
is_mute: mute,
});
};
// 静音
// mute call
const setMuteCall = (mute) => {
return window.lemon.call.muteCall({
call_id,
is_mute: mute,
});
};
const removeMonitorCall = (callId) => {
const index = monitor_call_list.findIndex(
(item) => item.call_id === callId
);
if (index >= 0) {
monitor_call_list.splice(index, 1);
emitter.emit('monitorUpdate');
}
};
const getMonitorCallList = () => {
return monitor_call_list;
};
// 添加 挂断 回调
// After hanging up the call, you can receive a notification and process the style of the current page based on the notification
const registerhangupEvent = () => {
if (hangup_event_cb_id !== undefined) {
return;
}
hangup_event_cb_id = window.lemon.call.addHangupEvt((data) => {
console.info('receive hangup event');
console.info(
'receive hangup event receive call id',
String(data.call_id)
);
console.info('receive hangup event local call id', String(call_id));
if (data.call_id === call_id) {
// remove display alert ui
ElNotification.close(call_id);
call_id = undefined;
window.calling_conference = undefined;
// console.log('2222211111registerCallEstablishEvent');
}
// pushVideoFile uninit
// 如果是视频推送的,挂断是反初始化一些东西。
if (pushing_video) {
window.video.src = undefined;
window.showVideo.value = false;
pushing_video = false;
window.videoViewRoot.style.display = 'none';
}
removeMonitorCall(data.call_id);
});
};
// 添加强拆事件
const registerForceHangupEvent = () => {
if (force_hangup_event_cb_id !== undefined) {
return;
}
force_hangup_event_cb_id = window.lemon.call.addForceHangupEvt((data) => {
// 目前强拆成功,都是走挂断通知事件。 当失败了,才走强拆事件通知。
if (data.result === 0) {
if (data.call_id === call_id) {
ElNotification.close(call_id);
call_id = undefined;
window.calling_conference = undefined;
}
removeMonitorCall(data.call_id);
} else {
// 强拆失败 fail
ElMessage.error("强拆失败");
}
});
};
// 添加接听回调通知 代表呼叫建立
// receive the answer acknowledgement asynchronously after the call is established
const registerCallEstablishEvent = () => {
if (answer_ack_cb_id !== undefined) {
return;
}
answer_ack_cb_id = window.lemon.call.addAnswerAckEvt((data) => {
// console.info('registerCallEstablishEvent0', call_id);
console.info('registerCallEstablishEvent', String(data.call_id));
console.info('registerCallEstablishEvent', JSON.stringify(data));
call_id = data.call_id;
// pushVideoFile init
// 接通后,视频推送的文件开始播放
if (pushing_video) {
window.videoViewRoot.style.display = 'unset';
window.showVideo.value = true;
window.video.play();
}
});
};
// 注册来电通知回调
// add the incoming call callback
const registerReceiveCallEvent = () => {
if (incoming_cb_id !== undefined) {
return;
}
incoming_cb_id = window.lemon.call.addIncomingEvt((session) => {
console.log('receive call------>', session);
call_id = session.call_id;
const callingReq = {
callInfo: session,
equipment: undefined,
text: {
calling: '队列',
answer: '接听',
hangUp: '挂断',
},
};
console.log('receive this------>', useCallModule());
if (session.listen_flag) {
// monitor call,auto answer call
// 值守的来电呼叫,自动接听
window.lemon.call.answerCall({ call_id: session.call_id });
monitor_call_list.push(session);
emitter.emit('monitorUpdate');
} else {
// normal call
// 正常来电,弹框询问接听
// handleCallingNotification(callingReq);
}
});
};
// 申请话权
// apply floor
const applyFloor = () => {
console.info('try applyFloor,call_id=', call_id);
if (!call_id) {
console.warn('no call exits');
return undefined;
}
return window.lemon.floor
.applySpeak({ call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('applyFloor request sucess');
} else {
ElMessage.error("申请话权失败");
}
})
.catch((err) => {
console.error('applyFloor error,', err);
});
};
// 释放话权
// release floor
const releaseFloor = () => {
console.info('try releaseFloor,call_id=', call_id);
return window.lemon.floor
.releaseSpeak({ call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('releaseSpeak request sucess');
} else {
ElMessage.error("释放话权失败");
}
})
.catch((err) => {
console.error('releaseSpeak error,', err);
});
};
// add floor event
// 添加话权通知事件
const registerFloorGrantEvent = () => {
if (floor_grant_cb_id !== undefined) {
return;
}
floor_grant_cb_id = window.lemon.floor.addGrantEvt((grantInfo) => {
console.log('registerFloorGrantEvent', grantInfo);
if (grantInfo.result !== 0) {
ElMessage.error("话权申请失败");
}
});
};
// 强拆
// override the call
const forceHangupCall = (callId) => {
return window.lemon.call
.forceHangupCall({ call_id: callId || call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('forceHangupCall request sucess');
} else {
ElMessage.error("强拆失败");
}
call_id = undefined;
window.calling_conference = undefined;
// console.log('2222233registerCallEstablishEven');
})
.catch((err) => {
console.error('forceHangupCall error,', err);
});
};
// 强插
// interrupt the call during monitoring
const forceApplySpeak = (callId) => {
return window.lemon.floor
.forceApplySpeak({ call_id: callId || call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('forceApplySpeak request sucess');
call_id = callId;
} else {
ElMessage.error("强插失败");
}
})
.catch((err) => {
console.error('forceApplySpeak error,', err);
});
};
/**
* 会议成员禁言
* mute or unmute a conference member
* @param param
* @param param.conference_basedata_id
*/
const muteMemberInConference = (
conference_basedata_id,
member_basedata_id,
mute
) => {
return window.lemon.call.conferenceMemberSpeakSet({
conference_call_id: call_id,
conference_basedata_id,
member_setting: {
member_basedata_id,
forbid: mute ? 1 : 0,
},
});
};
/**
* 视频推送
* select a local video file and play then push the stream to remote
* @param record
* @param file
* @returns
*/
const pushVideoFile = (record, url) => {
console.info('try pushVideoFile,call_id=', call_id);
if (call_id) {
console.warn('call exits');
return;
}
console.warn('window.video', window.video);
// set the file to video tag
if (window.video) {
const canPlayListener = () => {
window.video.removeEventListener('canplay', canPlayListener);
// capture stream
const stream = (window.video)?.captureStream();
console.info('pushVideoFile,inited stream=', stream);
// register hook listner ,play the video when remote hooked
registerCallEstablishEvent();
// init the call
window.lemon.call
.pushVideoFile({
basedata_id: record?.basedata_id,
stream,
})
?.then((resp) => {
pushing_video = true;
call_id = resp.call_id;
});
};
const endListener = () => {
console.info('pushVideoFile,video play end');
window.video.removeEventListener('ended', endListener);
hangup();
};
// maybe did't finish the video,so that we has listener already,remove it
window.video.removeEventListener('ended', endListener);
console.info('pushVideoFile,add canplay Event Listener', canPlayListener);
window.video.addEventListener('canplay', canPlayListener);
// hangup the call when video finished
console.info('pushVideoFile,add ended Event Listener', endListener);
window.video.addEventListener('ended', endListener);
window.video.autoplay = false;
window.video.src = url;
}
};
/**
* 视频转发
* share a exist call to another device
* @param record
* @param stop
* @returns
*/
const forwardVideoCall = (record, stop) => {
console.info('try forwardVideoCall,call_id=', call_id);
if (!call_id) {
console.warn('no call exits,can not forward');
ElMessage.warning('no call exits');
return undefined;
}
return window.lemon.call
.forwardVideoCall({
basedata_id: record?.basedata_id,
call_id,
action: stop ? 1 : 0,
})
?.then((resp) => {
if (resp.result === 0) {
console.log('forwardVideoCall request sucess');
} else {
ElMessage.error("视频转发失败");
}
})
.catch((err) => {
console.error('forwardVideoCall error,', err);
});
};
const getEmitter = () => {
return emitter;
};
// call sdk unInit
const unInit = () => {
call_id = undefined;
if (hangup_event_cb_id) {
window.lemon.call.removeHangupEvt(hangup_event_cb_id);
hangup_event_cb_id = undefined;
}
if (force_hangup_event_cb_id) {
window.lemon.call.removeForceHangupEvt(force_hangup_event_cb_id);
force_hangup_event_cb_id = undefined;
}
if (answer_ack_cb_id) {
window.lemon.call.removeAnswerAckEvt(answer_ack_cb_id);
answer_ack_cb_id = undefined;
}
if (incoming_cb_id) {
window.lemon.call.removeIncomingEvt(incoming_cb_id);
incoming_cb_id = undefined;
}
if (floor_grant_cb_id) {
window.lemon.floor.removeGrantEvt(floor_grant_cb_id);
floor_grant_cb_id = undefined;
}
monitor_call_list.length = 0;
};
return {
makeVoiceCall,
makeVideoCall,
pureVideoCall,
registerhangupEvent,
registerReceiveCallEvent,
answerCall,
makeGroupVoiceCall,
makeGroupVideoCall,
makeBroadcastCall,
hangup,
voiceDetect,
videoDetect,
applyFloor,
releaseFloor,
setMuteCamera,
setMuteMic,
setMuteCall,
muteMemberInConference,
makeConferenceVoiceCall,
makeConferenceVideoCall,
makeCrosspatchVoiceCall,
registerCallEstablishEvent,
pushVideoFile,
forwardVideoCall,
forceHangupCall,
getMonitorCallList,
getEmitter,
forceApplySpeak,
registerFloorGrantEvent,
registerForceHangupEvent,
unInit,
};
}

View File

@ -1,37 +0,0 @@
// import { h } from 'vue';
// import { Notification } from '@arco-design/web-vue';
// import { IconClose } from '@arco-design/web-vue/es/icon';
// import Content from '@/views/webPuc/callingNotification/components/content.vue';
// import Footer from '@/views/webPuc/callingNotification/components/footer.vue';
// import { formatShowNameFin } from './format-show-name';
// export default function handleCallingNotification(propsObj) {
// const { callInfo, text } = propsObj;
// const { calling, answer = 'answer', hangUp = 'hang up' } = text;
// Notification.info({
// id: callInfo.call_id,
// showIcon: false,
// position: 'bottomLeft',
// closable: true,
// closeIconElement: () => {
// return h(IconClose);
// },
// title: () =>
// h(Content, {
// callInfo,
// calling,
// getName: formatShowNameFin(
// callInfo.caller_alias,
// callInfo.caller_number
// ),
// }),
// content: () =>
// h(Footer, {
// callInfo,
// answer,
// hangUp,
// }),
// duration: 0,
// style: { width: '260px' },
// });
// }

View File

@ -174,67 +174,67 @@ const tabHeightFn = () => {
}; };
/** 以pdf形式下载 */ /** 以pdf形式下载 */
const downLoadPdf = async () => { const downLoadPdf = async () => {
downLoading.value = true; // downLoading.value = true;
ElMessage.info('下载界面会展开,是正常的。'); // ElMessage.info('下载界面会展开,是正常的。');
try { // try {
// 强制刷新所有图表 // // 强制刷新所有图表
const resizeEvent = new Event('resize'); // const resizeEvent = new Event('resize');
window.dispatchEvent(resizeEvent); // window.dispatchEvent(resizeEvent);
// 等待图表重绘 // // 等待图表重绘
await new Promise(resolve => setTimeout(resolve, 1000)); // await new Promise(resolve => setTimeout(resolve, 1000));
// 保存原始样式 // // 保存原始样式
const originalOverflow = tableBox.value.style.overflow; // const originalOverflow = tableBox.value.style.overflow;
const originalHeight = tableBox.value.style.height; // const originalHeight = tableBox.value.style.height;
const originalPaddingBottom = tableBox.value.style.paddingBottom; // const originalPaddingBottom = tableBox.value.style.paddingBottom;
const originalMarginBottom = tableBox.value.style.marginBottom; // const originalMarginBottom = tableBox.value.style.marginBottom;
// 确保所有内容都可见,并增加底部间距 // // 确保所有内容都可见,并增加底部间距
tableBox.value.style.overflow = 'visible'; // tableBox.value.style.overflow = 'visible';
tableBox.value.style.height = 'auto'; // tableBox.value.style.height = 'auto';
tableBox.value.style.paddingBottom = '50px'; // 增加底部内边距 // tableBox.value.style.paddingBottom = '50px'; // 增加底部内边距
tableBox.value.style.marginBottom = '30px'; // 增加底部外边距 // tableBox.value.style.marginBottom = '30px'; // 增加底部外边距
// 为最后的总结分析部分添加特殊样式,避免分页截断 // // 为最后的总结分析部分添加特殊样式,避免分页截断
const summaryElements = tableBox.value.querySelectorAll('h2'); // const summaryElements = tableBox.value.querySelectorAll('h2');
const lastH2 = summaryElements[summaryElements.length - 1]; // const lastH2 = summaryElements[summaryElements.length - 1];
if (lastH2 && lastH2.textContent.includes('总结分析')) { // if (lastH2 && lastH2.textContent.includes('总结分析')) {
lastH2.style.pageBreakBefore = 'always'; // lastH2.style.pageBreakBefore = 'always';
lastH2.style.pageBreakInside = 'avoid'; // lastH2.style.pageBreakInside = 'avoid';
// 确保总结分析的段落不被分页截断 // // 确保总结分析的段落不被分页截断
const nextP = lastH2.nextElementSibling; // const nextP = lastH2.nextElementSibling;
if (nextP && nextP.tagName === 'P') { // if (nextP && nextP.tagName === 'P') {
nextP.style.pageBreakInside = 'avoid'; // nextP.style.pageBreakInside = 'avoid';
nextP.style.marginBottom = '30px'; // nextP.style.marginBottom = '30px';
} // }
} // }
await downloadPDF(tableBox.value, '警情分析报告'); // await downloadPDF(tableBox.value, '警情分析报告');
// 恢复原始样式 // // 恢复原始样式
tableBox.value.style.overflow = originalOverflow; // tableBox.value.style.overflow = originalOverflow;
tableBox.value.style.height = originalHeight; // tableBox.value.style.height = originalHeight;
tableBox.value.style.paddingBottom = originalPaddingBottom; // tableBox.value.style.paddingBottom = originalPaddingBottom;
tableBox.value.style.marginBottom = originalMarginBottom; // tableBox.value.style.marginBottom = originalMarginBottom;
// 恢复总结分析部分的样式 // // 恢复总结分析部分的样式
if (lastH2) { // if (lastH2) {
lastH2.style.pageBreakBefore = ''; // lastH2.style.pageBreakBefore = '';
lastH2.style.pageBreakInside = ''; // lastH2.style.pageBreakInside = '';
const nextP = lastH2.nextElementSibling; // const nextP = lastH2.nextElementSibling;
if (nextP && nextP.tagName === 'P') { // if (nextP && nextP.tagName === 'P') {
nextP.style.pageBreakInside = ''; // nextP.style.pageBreakInside = '';
nextP.style.marginBottom = ''; // nextP.style.marginBottom = '';
} // }
} // }
} catch (error) { // } catch (error) {
console.error('下载失败:', error); // console.error('下载失败:', error);
} finally { // } finally {
downLoading.value = false; // downLoading.value = false;
} // }
} }
const downloadWithStyles = async () => { const downloadWithStyles = async () => {
if (!tableBox.value?.innerHTML) return; if (!tableBox.value?.innerHTML) return;

View File

@ -104,11 +104,12 @@ import LineEcharts from "@/views/home/echarts/moreLineEcharts.vue";
import MyTable from "@/components/aboutTable/DarkTable.vue"; import MyTable from "@/components/aboutTable/DarkTable.vue";
import Pages from "@/components/aboutTable/Pages.vue"; import Pages from "@/components/aboutTable/Pages.vue";
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import {tbJqGetPageList } from '@/api/yj.js' import {tbJqGetPageList,xsajSelectPage } from '@/api/yj.js'
const router = useRouter(); const router = useRouter();
import { nextTick, onMounted, reactive, getCurrentInstance, ref, watch } from 'vue'; import { nextTick, onMounted, reactive, getCurrentInstance, ref, watch } from 'vue';
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const { JQLB } = proxy.$dict("JQLB"); //获取字典数据 const { JQLB } = proxy.$dict("JQLB"); //获取字典数据
const {GA_D_XSAJXALBDM} = proxy.$fzdict("GA_D_XSAJXALBDM"); //获取字典数据
const readonly_lx = ref(false) const readonly_lx = ref(false)
const readonly_ry = ref(false) const readonly_ry = ref(false)
const readonly_dd = ref(false) const readonly_dd = ref(false)
@ -195,10 +196,11 @@ const list = reactive([
pageSize: 6, pageSize: 6,
}, },
tableColumn: [ tableColumn: [
{ label: "案件编号", prop: "ajbh", showOverflowTooltip: true }, { label: "案件编号", prop: "asjbh", showOverflowTooltip: true },
{ label: "案件内容", prop: "ajnr", showOverflowTooltip: true }, { label: "案件标题", prop: "ajmc", showOverflowTooltip: true },
{ label: "案件类型", prop: "ajlx", showOverflowTooltip: true }, { label: "简要案情", prop: "jyaq", showOverflowTooltip: true },
{ label: "案件时间", prop: "ajsj", showOverflowTooltip: true }, { label: "案件类型", prop: "ajxlbDmbcms", showOverflowTooltip: true },
{ label: "案件时间", prop: "asjfssjAsjfskssj", showOverflowTooltip: true },
], ],
}, },
{ {
@ -243,11 +245,20 @@ watch(() => JQLB.value, (val) => {
deep: true, immediate: true deep: true, immediate: true
}) })
onMounted(() => { onMounted(() => {
// getCount(); //获取统计数据 // getCount(); //获取统计数据
tabHeightFn() tabHeightFn()
getJqList() //警情列表 getJqList() //警情列表
getAjList()//案件列表
}); });
// 获取字典
const getxsajDictSelectList = () => {
xsajDictSelectList().then(res => {
console.log(res);
})
}
const getCount = () => { const getCount = () => {
// 获取处置状态统计 // 获取处置状态统计
qcckPost({}, '/mosty-gsxt/qbcj/getXscjTjByXslx').then(res => { qcckPost({}, '/mosty-gsxt/qbcj/getXscjTjByXslx').then(res => {
@ -275,12 +286,13 @@ const changeNo = (e, type) => {
break; break;
case '案件': case '案件':
list[2].pageConfiger.page = e; list[2].pageConfiger.page = e;
getAjList()
break; break;
case '风险隐患': case '风险隐患':
list[3].pageConfiger.page = e; list[3].pageConfiger.page = e;
break; break;
} }
getJqList() // getJqList()
} }
const changeSize = (e, type) => { const changeSize = (e, type) => {
switch (type) { switch (type) {
@ -293,6 +305,7 @@ const changeSize = (e, type) => {
break; break;
case '案件': case '案件':
list[2].pageConfiger.pageSize = e; list[2].pageConfiger.pageSize = e;
getAjList()
break; break;
case '风险隐患': case '风险隐患':
list[3].pageConfiger.pageSize = e; list[3].pageConfiger.pageSize = e;
@ -316,6 +329,26 @@ const getJqList = () => {
obj.data_hstj.list = [{ label: '总数', val: [0, res.total, 0, 0] }]; obj.data_hstj.list = [{ label: '总数', val: [0, res.total, 0, 0] }];
}) })
} }
const getAjList = () => {
let params = {
pageCurrent: list[2].pageConfiger.page,
pageSize: list[2].pageConfiger.pageSize,
}
console.log("执行");
xsajSelectPage(params).then(res => {
list[2].tableList = res.records || [];
list[2].pageConfiger.total = res.total;
// //模拟的统计警情接口
// obj.data_lxtj.list = [{ label: '总数', val: [0, res.total, 0, 0] }];
// obj.data_hstj.list = [{ label: '总数', val: [0, res.total, 0, 0] }];
})
}
// xsajSelectPage(promes).then(res => {
// list[2].tableList = res.records || [];
// list[2].pageConfiger.total = res.total;
// })
@ -420,7 +453,6 @@ const onSearch = () => {
}) })
} else { } else {
ElMessage.warning('请选择查询条件') ElMessage.warning('请选择查询条件')
} }

View File

@ -0,0 +1,206 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="内部审核" />
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #bglx="{ row }">
<DictTag :tag="false" :value="row.bglx" :options="D_BZ_YPLX" />
</template>
<template #ypfs="{ row }">
<DictTag :tag="false" :value="row.ypfs" :options="D_BZ_YPFS" />
</template>
<template #shzt="{ row }">
<span v-if="row.shzt == '01'">审批中</span>
<span v-if="row.shzt == '02'">已审批</span>
<span v-if="row.shzt == '03'">已驳回</span>
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="danger" @click="internalAudit(row.id)">内部审批</el-link>
<el-link size="small" type="primary" @click="createProcess(row)">提交上级</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
<SubmissionProcess v-model="showSp" :data="rowData" :userData="{ ajmc: '研判审核', flowType: 'YPSH', modelName: '研判' }"
:path="fixedValue" @getList="getList" />
<Ypdolog v-model="showYpdolog" :dataList="dataList" @getList="getList" />
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { useRoute, useRouter } from 'vue-router'
import { reactive, ref, onMounted, getCurrentInstance, watch, computed, nextTick } from "vue";
import { ypbgSjzlQueryShList } from "@/api/huiShangyp/strategicApi.js";
import SubmissionProcess from '@/components/flowPath/submissionProcess.vue'
import Ypdolog from './ypdolog.vue'
const { proxy } = getCurrentInstance();
const { D_BZ_YPFS, D_BZ_YPLX, D_GS_BQ_LX } = proxy.$dict("D_BZ_YPFS", "D_BZ_YPLX", "D_GS_BQ_LX")
const searchBox = ref(); //搜索框
const router = useRouter();
const route = useRoute();
onMounted(() => {
tabHeightFn()
if (route.query.id) {
nextTick(() => {
addForm.value && addForm.value.init('edit', {
id: route.query.id
});
router.replace({ path: '/tacticalResearch' })// 移除id 避免刷新一直带参数
})
}
getList()
});
const searchConfiger = ref([
{ label: "研判议题", prop: 'ypyt', placeholder: "请输入研判议题", showType: "input" },
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 240,
tableColumn: [
{ label: "研判议题", prop: "ypyt" },
{ label: "报告类型", prop: "bglx", showSolt: true },
{ label: "审核状态", prop: "shzt", showSolt: true },
{ label: "研判时间", prop: "ypsj" },
{ label: "研判要求", prop: "ypyq" },
{ label: "发起部门", prop: "ssbm" },
{ label: "研判方式", prop: "ypfs", showSolt: true },
]
});
const queryFrom = ref({});
// 搜索
const onSearch = (val) => {
const promes = {
...val,
...pageData.pageConfiger,
}
queryFrom.value = { ...promes }
pageData.pageConfiger.pageCurrent = 1;
getList()
}
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList()
}
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList()
}
// 获取列表
const getList = () => {
pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...queryFrom.value };
ypbgSjzlQueryShList(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => { pageData.tableConfiger.loading = false; })
}
// 工作流
const showSp = ref(false);
const rowData = ref()
// 固定值
const fixedValue = {
clueVerification: 'information',
byMeansOf: 'ypbg/sjzl/sendFqzl',
nobyMeansOf: 'ypbg/sjzl/sendFqzl',
recycle: 'ypbg/sjzl/sendFqzl',
}
const createProcess = (row) => {
if (row.shzt == '02') {
showSp.value = true;
rowData.value = row
} else {
proxy.$message({
message: '请先内部审批',
type: 'warning'
})
}
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
// 内部审核
const showYpdolog = ref(false)
const dataList = ref({})
const internalAudit = (row) => {
dataList.value = row
showYpdolog.value = true
};
</script>
<style lang="scss" scoped>
.label-pop {
position: relative;
&::before {
position: absolute;
content: '*';
top: 0;
left: -7px;
color: red;
}
}
</style>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
:v-deep .el-dialog {
width: 90% !important;
}
.zdy-model-dialogs {
/* background-color: rgb(50, 148, 214); */
background: url("~@/assets/images/bg46.png") no-repeat center center;
background-size: 100% 100%;
padding: 8px 10px;
box-sizing: border-box;
pointer-events: auto !important;
height: calc(100% - 50px);
overflow: auto;
}
</style>

View File

@ -0,0 +1,186 @@
<template>
<div class="information-container">
<h2 class="page-title">研判详情</h2>
<div class="info-section">
<div class="info-row">
<div class="info-item">
<span class="label">研判议题</span>
<span class="value">{{ detail.ypyt || '暂无' }}</span>
</div>
<div class="info-item">
<span class="label">研判方式</span>
<span class="value">
<DictTag v-if="detail.ypfs && D_BZ_YPFS" :tag="false" :value="detail.ypfs" :options="D_BZ_YPFS" />
<span v-else>暂无</span>
</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">报告类型</span>
<span class="value">
<DictTag v-if="detail.bglx && D_BZ_YPLX" :tag="false" :value="detail.bglx" :options="D_BZ_YPLX" />
<span v-else>暂无</span>
</span>
</div>
<div class="info-item">
<span class="label">研判时间</span>
<span class="value">{{ detail.ypsj || '暂无' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">研判要求</span>
<span class="value">{{ detail.ypyq || '暂无' }}</span>
</div>
<div class="info-item">
<span class="label">发起部门</span>
<span class="value">{{ detail.ssbm || '暂无' }}</span>
</div>
</div>
</div>
<!-- 新增数据展示模块 -->
<div class="data-section">
<h3 class="section-title">研判部门详情</h3>
<el-table :data="detail.cyypList" stripe style="width: 100%" border>
<el-table-column prop="ypbmmc" label="研判部门" min-width="150" />
<el-table-column prop="scyq" label="上传要求" min-width="200" />
<el-table-column prop="fj" label="附件" min-width="150" show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.fj">
<span v-for="(file, index) in JSON.parse(scope.row.fj)" :key="index">
{{ file.name }}<span v-if="index < JSON.parse(scope.row.fj).length - 1"></span>
</span>
</span>
<span v-else>暂无</span>
</template>
</el-table-column>
<el-table-column prop="wcqk" label="完成情况" min-width="120">
<template #default="scope">
{{ scope.row.wcqk == '01' ? '准备中' : '已完成' }}
</template>
</el-table-column>
<el-table-column prop="wcsj" label="完成时间" min-width="180" />
</el-table>
</div>
</div>
</template>
<script setup>
import DictTag from '@/components/DictTag/index.vue';
import { onMounted ,ref,getCurrentInstance} from 'vue';
import { useRoute } from 'vue-router'
import {sjzlGetInfo} from '@/api/yj'
const props = defineProps({
/** 字典数据 */
dict: {
type: Object,
default: () => ({})
}
});
const route = useRoute();
const { proxy } = getCurrentInstance();
const {D_BZ_YPFS, D_BZ_YPLX}=proxy.$dict("D_BZ_YPFS","D_BZ_YPLX");
const detail=ref({});
// 新增:存储用户提供的研判部门详情数据
const departmentData=ref([
{
"id": "ae9c8db058fc4bc6b18bc98ab6ef0abd",
"sjzlid": "1d538226c8c94577ab3e97f67e7e90bf",
"ypbmdm": "540421000000",
"ypbmmc": "工布江达县",
"scyq": "测试",
"fj": "[{\"id\":null,\"name\":\"app登录接口.txt\"}]",
"wcqk": "02",
"wcsj": "2025-12-26 15:12:29"
},
{
"id": "eef7b85a85784ea4b5211e4330162720",
"sjzlid": "1d538226c8c94577ab3e97f67e7e90bf",
"ypbmdm": "540402000000",
"ypbmmc": "巴宜区",
"scyq": "测试",
"fj": "[{\"id\":null,\"name\":\"Mosty888.csr\"}]",
"wcqk": "02",
"wcsj": "2025-12-26 15:12:29"
}
]);
onMounted(() => {
console.log(route.query.id);
sjzlGetInfo(route.query.id).then(res => {
detail.value=res;
console.log(res);
})
});
// /ypbg/sjzl/{id}
</script>
<style lang="scss" scoped>
.information-container {
width: 100%;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.page-title {
color: #303133;
font-size: 18px;
font-weight: bold;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e8e8e8;
}
.info-section {
width: 100%;
}
.info-row {
display: flex;
flex-wrap: wrap;
margin-bottom: 15px;
}
.info-item {
flex: 1;
min-width: 300px;
margin-bottom: 10px;
display: flex;
align-items: flex-start;
}
.label {
font-weight: bold;
color: #606266;
margin-right: 12px;
width: 100px;
text-align: right;
line-height: 32px;
}
.value {
color: #303133;
flex: 1;
line-height: 32px;
word-break: break-word;
}
/* 新增:数据展示模块样式 */
.data-section {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #e8e8e8;
}
.section-title {
color: #303133;
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
}
</style>

View File

@ -0,0 +1,92 @@
<template>
<el-dialog v-model="modelValue" title="内部审核" width="35%" @close="closeDialog" destroy-on-close append-to-body>
<div style="height: 15vh; overflow: auto;">
<el-form ref="ruleFormRef" :rules="rules" :model="form" label-width="auto" style="max-width: 600px">
<el-form-item label="审核状态" prop="shzt">
<el-radio-group v-model="form.shzt">
<el-radio label="02">通过</el-radio>
<el-radio label="03">拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审核意见" prop="shyj">
<el-input v-model="form.shyj" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog(ruleFormRef)">取消</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)">确认 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
import { ref, reactive, getCurrentInstance, watch } from "vue";
import { ypbgSjzlYpsp } from '@/api/huiShangyp/strategicApi.js'
const { proxy } = getCurrentInstance()
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dataList: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['update:modelValue','getList'])
const closeDialog = (formEl) => {
if (!formEl) return
formEl.resetFields()
emit('update:modelValue', false)
}
const rules = reactive({
shzt: [
{ required: true, message: '请选择审核状态', trigger: 'blur' }
],
shyj: [
{ required: true, message: '请输入审核意见', trigger: 'blur' }
]
})
const ruleFormRef = ref(null)
const form = reactive({
shzt: '',
shyj: ''
})
const submitForm = async (formEl) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
const promise = {
...form,
ypid: props.dataList
}
ypbgSjzlYpsp(promise).then(res => {
proxy.$message({
message: '操作成功',
type: 'success'
})
emit('getList')
formEl.resetFields()
emit('update:modelValue', false)
})
} else {
console.log('error submit!', fields)
}
})
}
</script>
<style scoped></style>

View File

@ -8,20 +8,19 @@
</div> </div>
</div> </div>
<div style="padding-bottom: 0px;" class="form_cnt"> <div style="padding-bottom: 0px;" class="form_cnt">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules"> <FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules" :disabled="title === '详情'">
<template #bmList> <template #bmList>
<div class="table-box"> <div class="table-box">
<el-table :data="tableList" border style="width: 100%"> <el-table :data="tableList" border style="width: 100%">
<el-table-column prop="ypbmmc" label="部门" width="150" align="center" /> <el-table-column prop="ypbmmc" label="部门" width="150" align="center" />
<el-table-column label="研判素材" width="280" align="center"> <el-table-column label="研判素材" width="380" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-input v-model="row.scyq" :disabled="true" placeholder="请输入研判素材" /> <el-input v-model="row.scyq" placeholder="请输入研判素材" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="附件" width="200" align="center"> <el-table-column label="附件" width="200" align="center">
<template #default="{ row }"> <template #default="{ row }">
<UploadFile v-model="row.fj" :disabled="true" :limit="1" :isImg="false" <UploadFile v-model="row.fj" :limit="1" :isImg="false" :isAll="true" />
:isAll="true" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="wcqk" label="完成状态" width="120" align="center"> <el-table-column prop="wcqk" label="完成状态" width="120" align="center">
@ -91,17 +90,29 @@
</template> </template>
<script setup> <script setup>
/**
* @typedef {Object} JudgmentDept 研判部门对象
* @property {string} ypbmdm - 研判部门代码
* @property {string} ypbmmc - 研判部门名称
* @property {string} scyq - 素材要求
* @property {Array} fj - 附件数组
* @property {string} wcqk - 完成情况01 准备中、02 已完成)
*/
import FormMessage from "@/components/aboutTable/FormMessage.vue"; import FormMessage from "@/components/aboutTable/FormMessage.vue";
import UploadFile from "@/components/MyComponents/Upload/index.vue"; import UploadFile from "@/components/MyComponents/Upload/index.vue";
// import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue" // import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue"
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, watch, computed } from "vue"; import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, watch, computed } from "vue";
import { sjzlAddEntity, sjzlEditEntity, sjzlGetInfo, sjzlPerfectlnfo, sjzlFstz, sjzlQryp, sjzlPerfectSorce } from '@//api/yj.js' import { sjzlGetInfo, sjzlPerfectlnfo, sjzlFstz, sjzlQryp, sjzlPerfectSorce } from '@//api/yj.js'
import { selfBuildJudgment } from "@/api/huiShangyp/tacticalApi.js"
// import { tacticalGet, strategicDelete } from "@/api/huiShangyp/strategicApi.js"; // import { tacticalGet, strategicDelete } from "@/api/huiShangyp/strategicApi.js";
import { getItem } from '@//utils/storage.js' import { getItem } from '@//utils/storage.js'
const emit = defineEmits(["updateDate", "getList"]); const emit = defineEmits(["updateDate", "getList"]);
const props = defineProps({ const props = defineProps({
dict: Object dict: Object,
/** 报告类型 01 战术研判 02战略研判 */
bglx: String,
}); });
const imgMsg = ref([]) const imgMsg = ref([])
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@ -147,7 +158,7 @@ watch(() => props.dict, (val) => {
formData.value = [ formData.value = [
{ label: "研判议题", prop: "ypyt", type: "input", width: '48%' }, { label: "研判议题", prop: "ypyt", type: "input", width: '48%' },
{ label: "研判时间", prop: "ypsj", type: "datetime", width: '48%' }, { label: "研判时间", prop: "ypsj", type: "datetime", width: '48%' },
{ label: "报告类型", prop: "bglx", type: "radio", options: props.dict.D_BZ_YPLX, width: '48%' }, { label: "报告类型", prop: "bglx", type: "radio", options: props.dict.D_BZ_YPLX, width: '48%', disabled: true },
{ label: "研判方式", prop: "ypfs", type: "radio", options: props.dict.D_BZ_YPFS, width: '48%' }, { label: "研判方式", prop: "ypfs", type: "radio", options: props.dict.D_BZ_YPFS, width: '48%' },
{ label: "参与研判部门", prop: "jsdxBmDm", type: "department", multiple: true, depMc: 'jsdxBmMc', width: '48%' }, { label: "参与研判部门", prop: "jsdxBmDm", type: "department", multiple: true, depMc: 'jsdxBmMc', width: '48%' },
{ label: "研判要求", prop: "ypyq", type: "textarea", width: '100%' }, { label: "研判要求", prop: "ypyq", type: "textarea", width: '100%' },
@ -165,6 +176,8 @@ function updateDis(row) {
const isFinish = row.wcqk === '02' const isFinish = row.wcqk === '02'
return isShiQingBaoZhongXin.value || !iscjr || isFinish return isShiQingBaoZhongXin.value || !iscjr || isFinish
} }
/** 获取附件数组 */
function getFjArr(fj) { function getFjArr(fj) {
if (typeof fj !== 'string' || !fj) return [] if (typeof fj !== 'string' || !fj) return []
let fjArr = [] let fjArr = []
@ -176,15 +189,16 @@ function getFjArr(fj) {
return fjArr return fjArr
} }
watch(() => listQuery.value.jsdxBmDm, (val) => { watch(() => listQuery.value.jsdxBmDm, (val) => {
/** @type {Array<{ypbmdm: string, ypbmmc: string, scyq: string, fj: Array, wcqk: string}>} 参与研判部门数据数组 */ /** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const arr = Array.isArray(val) ? val : [] const arr = Array.isArray(val) ? val : []
/** @type {Array} 参与研判部门*/
const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : [] const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : []
tableList.value = arr.map((item, i) => { tableList.value = arr.map((item, i) => {
/** 找原来的对象 */ /** 找原来的对象 */
const curr = cyypList.find(item2 => item2.ypbmdm == item) || {} const curr = cyypList.find(item2 => item2.ypbmdm == item) || {}
/** 是否是新增 */ /** 是否是新增 */
const isAddForm = !listQuery.value.id const isAddForm = !listQuery.value?.id
return { return {
// id: null, // id: null,
// sjzlid: null, // 研判战略研判ID // sjzlid: null, // 研判战略研判ID
@ -203,13 +217,24 @@ watch(() => listQuery.value.jsdxBmDm, (val) => {
const init = (type, row, wjlb) => { const init = (type, row, wjlb) => {
dialogForm.value = true; dialogForm.value = true;
title.value = type == "add" ? "新增" : type == "edit" ? "编辑" : "详情"; title.value = type == "add" ? "新增" : type == "edit" ? "编辑" : "详情";
outRow.value = row || {} outRow.value = row
if (row) { getDataById(row.id) } if (row) {
getDataById(row.id)
} else {
listQuery.value = {
bglx: props.bglx, // 报告类型 01 战术研判 02战略研判
ypfs: undefined, // 研判方式
ypsj: undefined, // 研判时间
ypyq: undefined, // 研判要求
cyypList: [], // 参与研判部门数据数组
}
}
}; };
// 根据id查询详情 // 根据id查询详情
const getDataById = (id) => { const getDataById = (id) => {
sjzlGetInfo(id).then((res) => { sjzlGetInfo(id).then((res) => {
listQuery.value = res || {}; listQuery.value = res || {};
/** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const cyypList = Array.isArray(res.cyypList) ? res.cyypList : [] const cyypList = Array.isArray(res.cyypList) ? res.cyypList : []
listQuery.value.jsdxBmDm = cyypList.map(item => { listQuery.value.jsdxBmDm = cyypList.map(item => {
return item.ypbmdm return item.ypbmdm
@ -219,17 +244,17 @@ const getDataById = (id) => {
}) })
}); });
}; };
/** 获取附件json字符串 */
function getFjString(arr) { function getFjString(arr) {
arr = Array.isArray(arr) ? arr : [] arr = Array.isArray(arr) ? arr : []
return JSON.stringify(arr) return JSON.stringify(arr)
} }
/**获取下发部门数据 */ /**获取下发部门数据 */
const getXfbmList = () => { const getXfbmList = () => {
/** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : [] const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : []
return tableList.value.map((item, i) => { return tableList.value.map((item, i) => {
/** @type {JudgmentDept} 找原来的对象 */
/** 找原来的对象 */
const curr = cyypList.find(item => item.ypbmdm == item.ypbmdm) || {} const curr = cyypList.find(item => item.ypbmdm == item.ypbmdm) || {}
return { return {
id: curr.id || null, id: curr.id || null,
@ -252,21 +277,14 @@ const submit = () => {
let params = { let params = {
...listQuery.value, ...listQuery.value,
cyypList: xfbmList, cyypList: xfbmList,
// cyypList: listQuery.value.jsdxBmDm.map((item, index) => {
// return {
// ypbmdm: item,
// ypbmmc: listQuery.value.jsdxBmMc[index],
// ypcylx: '01'
// }
// })
}; };
try { try {
loading.value = true; loading.value = true;
let res let res
if (title.value == "新增") { if (title.value == "新增") {
res = await sjzlAddEntity(params) res = await selfBuildJudgment(params)
} else { } else {
res = await sjzlEditEntity(params) // res = await sjzlEditEntity(params)// 目前没有修改
} }
if (res && res > 0) { if (res && res > 0) {
loading.value = false; loading.value = false;
@ -358,7 +376,7 @@ const submitMaterialAction = async () => {
closeMaterialDialog() closeMaterialDialog()
if (outRow.value.id) { getDataById(outRow.value.id) } if (outRow.value.id) { getDataById(outRow.value.id) }
} catch (error) { } catch (error) {
console.log(error)
} finally { } finally {
materialLoading.value = false materialLoading.value = false
} }
@ -384,7 +402,7 @@ const sendNotice = () => {
proxy.$message({ type: "success", message: "下发通知成功" }); proxy.$message({ type: "success", message: "下发通知成功" });
close(); close();
} catch (error) { } catch (error) {
console.log(error);
} finally { } finally {
noticeLoading.value = false; noticeLoading.value = false;
} }
@ -405,7 +423,7 @@ const confirmJudgment = () => {
proxy.$message({ type: "success", message: "确认研判成功" }); proxy.$message({ type: "success", message: "确认研判成功" });
close(); close();
} catch (error) { } catch (error) {
console.log(error);
} finally { } finally {
confirmLoading.value = false; confirmLoading.value = false;
} }

View File

@ -0,0 +1,137 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">创建会议{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<!-- <template #glxsmc>
<el-input placeholder="请选择关联线索" @click="chooseVisiblexS = true" readonly v-model="listQuery.glxsmc"></el-input>
</template> -->
<template #chryList>
<el-input placeholder="请选择参会人员" @click="openMeetings = true" readonly v-model="listQuery.rymc"></el-input>
</template>
</FormMessage>
</div>
</div>
<Personnel v-model="openMeetings" />
<ChooseUser v-model="chooseVisible" :Single="false" @choosedUsers="handleUserSelected" :roleIds="roleIds" />
<Xslist v-model="chooseVisiblexS" @choosed="choosed" :roleIds="roleIdsxs"></Xslist>
</template>
<script setup>
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
// import Xslist from '@/components/ChooseList/ChooseXs/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import Personnel from '@/views/backOfficeSystem/JudgmentHome/MeetingRoom/components/Communications/personnel.vue'
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, } from "vue";
import dayjs from 'dayjs';
const emit = defineEmits(["updateDate"]);
const roleIds = ref([]); //角色id
const chooseVisible = ref(false);
const roleIdsxs = ref([]); //角色id
const chooseVisiblexS = ref(false);
const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗
const rules = reactive({
hskssj: [{ required: true, message: "请选择会商开始时间", trigger: "change" }],
hsjssj: [{ required: true, message: "请选择会商结束时间", trigger: "change" }],
hsnr: [{ required: true, message: "请输入会商内容", trigger: "blur" }],
hsbt: [{ required: true, message: "请输入会商标题", trigger: "blur" }],
// glxsmc: [{ required: true, message: "请选择关联线索", trigger: "change" }],
chryList: [{ required: true, message: "请选择参会人员", trigger: "change" }],
});
const formData = ref([
{ label: "会商开始时间", prop: "hskssj", type: "datetime" },
{ label: "会商结束时间", prop: "hsjssj", type: "datetime" },
{ label: "会商内容", prop: "hsnr", type: "textarea", width: "100%" },
// { label: "关联线索", prop: "glxsmc", type: "slot", },
{ label: "会商标题", prop: "hsbt", type: "input" },
// { label: "参会人员", prop: "chryList", type: "slot" ,width:'100%'},
]);
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();
const title = ref("");
const outRow = ref({})
// 初始化数据
const init = (type, row, outRowObj = {}) => {
outRow.value = outRowObj
dialogForm.value = true;
title.value = type == "add" ? "新增" : "编辑";
if (row) {
getDataById(row.id)
} else {
listQuery.value = {
hskssj: dayjs().format("YYYY-MM-DD HH:mm:ss"),
hsjssj: dayjs().add(1, "hour").format("YYYY-MM-DD HH:mm:ss"),
}
}
};
// 根据id查询详情
const getDataById = (id) => {
qcckGet({ id }, "/mosty-gsxt/wshs/selectByid").then((res) => {
res.rymc = res.chryList ? res.chryList.map(v => v.chryxm).join(",") : '';
res.chryList = res.chryList ? res.chryList.map(item => item.chryid) : [];
roleIds.value = res.chryList;
roleIdsxs.value = res.glxsid ? [res.glxsid] : [];
listQuery.value = res;
});
};
const handleUserSelected = (userData) => {
roleIds.value = userData.map(item => item.id);
listQuery.value.chryList = userData.map(item => item.id)
listQuery.value.rymc = userData.map(item => item.userName).join("、");
};
const choosed = (data) => {
listQuery.value.glxsmc = data[0].xsMc;
listQuery.value.glxsid = data[0].id;
roleIdsxs.value = data.map(item => item.id);
};
// 提交
const submit = () => {
elform.value.submit((data) => {
let url = title.value == "新增" ? "/mosty-gsxt/wshs/add" : "/mosty-gsxt/wshs/update";
let params = {
...data,
glxsid: outRow.value.id,
glxsmc: outRow.value.xsMc,
};
loading.value = true;
qcckPost(params, url).then(() => {
loading.value = false;
proxy.$message({ type: "success", message: title.value + "成功" });
emit("updateDate");
close();
}).catch(() => { loading.value = false; });
});
};
// 关闭
const close = () => {
listQuery.value = {};
roleIds.value = [];
roleIdsxs.value = [];
dialogForm.value = false;
loading.value = false;
};
// 选择参会人员
const openMeetings = ref(false)
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
</style>

View File

@ -0,0 +1,273 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">报告{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage :formList="formData" v-model="listQuery" ref="elform" :rules="rules">
<template #bgnr>
<el-input v-model="listQuery.bgnr" style="width: 100%" placeholder="请输入关键字" class="input-with-select">
<template #append>
<el-button :icon="Search" type="primary">搜索</el-button>
</template>
</el-input>
</template>
<template #fj><el-button type="primary" @click="showText = true">附件上传</el-button></template>
</FormMessage>
<div class="cntBox">
<!-- 工具栏 -->
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig"
:mode="mode" />
<!-- 编辑器 -->
<Editor :style="`height: 480px; overflow-y: hidden`" v-model="textContent" :defaultConfig="editorConfig"
:mode="mode" @onCreated="handleCreated" @onChange="handChange" />
</div>
<div v-if="outRow.id" style="display: flex; justify-content: center;">
<!-- <el-button style="display: block;" type="primary" @click="ConsultationShow = true">网上会商</el-button> -->
<el-button style="display: block;" type="primary" @click="downloadWithStyles(textContent)">下载</el-button>
</div>
</div>
</div>
<!-- 文字解析 -->
<ExtractionText v-model="showText" @change="getText"></ExtractionText>
<!-- 网上会商 -->
<!-- <Consultation v-model="ConsultationShow" /> -->
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
import { timeValidate } from '@/utils/tools.js'
import ExtractionText from "@/components/ExtractionText/index.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import "@wangeditor/editor/dist/css/style.css";
// import Consultation from './consultation.vue'
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, shallowRef, onBeforeUnmount, watch } from "vue";
import { gsxtYpbgAddEntity, gsxtYpbgEditEntity } from "@/api/huiShangyp/tacticalApi.js"
const emit = defineEmits(["updateDate", 'ok']);
const props = defineProps({
dic: Object,
});
const ConsultationShow = ref(false)
const showText = ref(false);
const textContent = ref()
const { proxy } = getCurrentInstance();
const editorRef = shallowRef();
const dialogForm = ref(false); //弹窗
const mode = "default";
const dataBt = ref(`<p class="html_bt">
<h4 style=\"text-align: center;\"><span style=\"color: rgb(225, 60, 57); font-size: 32px; font-family: 标楷体;\">林芝市公安局情指中心</span></h4>
<h4 style=\"text-align: center;\"><span style=\"color: rgb(225, 60, 57); font-size: 32px; font-family: 标楷体;\">研判专刊(初稿)</span></h4></p>
<p style="text-align: center;"><span style="color: rgb(225, 60, 57); font-size: 22px; font-family: 标楷体;">市公安局情指中心编</span></p>
<p style="text-align: center;"><span style="color: rgb(225, 60, 57); font-size: 22px; font-family: 标楷体;"> ${timeValidate(new Date(), 'td')}</span></p>
<hr/>`)
//编辑器配置
const editorConfig = {
withCredentials: true, //允许跨域
placeholder: props.placeholder, //提示语
MENU_CONF: {
uploadImage: {
// 自定义上传图片
async customUpload(file, insertFn) {
let fileBlob = await compressImage(file);
let fileData = new File([fileBlob], fileBlob.name, { type: fileBlob.type });
if (fileData.size > 2 * 1024 * 1024) {
ElMessage({ message: "图片超过2MB", type: "success" });
} else {
await uploadFn(fileData, insertFn);
}
}
},
uploadVideo: {
// 自定义上传视频
async customUpload(file, insertFn) {
await uploadFn(file, insertFn);
}
}
}
};
//工具配置
const toolbarConfig = {
excludeKeys: ["blockquote", "codeBlock"] //清除不必要的工具,引用和代码块
};
const rules = reactive({
jymc: [
{ required: true, message: "请输入经验名称", trigger: "blur" }
],
fbnr: [
{ required: true, message: "请输入经验内容", trigger: "blur" }
]
});
const formData = ref([
{ label: "报告名称", prop: "bgmc", type: "input", width: "100%", blur: setEditorTextContent },
{ label: "报告内容", prop: "bgnr", type: "slot", width: "100%", blur: setEditorTextContent },
// { label: "附件内容", prop: "fj", type: "slot", width: "100%" },
]);
const listQuery = ref({
bgmc: "",
bgnr: "",
fj: ""
}); //表单
const loading = ref(false);
const elform = ref();
const title = ref("");
/** 外面行数据 */
const outRow = ref({})
// 初始化数据
const init = (type, reportData, row) => {
listQuery.value = {
bgmc: reportData.bgmc,
bgnr: reportData.bgnr,
id: reportData.id,
// fj: reportData.fj
}
outRow.value = { ...row }
dialogForm.value = true;
title.value = type == "add" ? "新增" : "编辑";
setEditorTextContent()
};
const getText = (val, row = {}) => {
listQuery.value.fj = val.text;
setEditorTextContent()
}
function setEditorTextContent() {
let html = dataBt.value;
html += `<p style="text-align: center;"><span style="font-size: 22px;">${listQuery.value.bgmc || ''}</span></p>`
html += `<p>${listQuery.value.fj || ''}</p>`
textContent.value = html
}
// watch(() => listQuery.value, (val) => {
// },
// {
// deep: true, immediate: true
// })
// 提交
const submit = () => {
elform.value.submit((data) => {
// let url = title.value == "新增" ? "/mosty-gsxt/gsxt/jyfx/add" : "/mosty-gsxt/gsxt/jyfx/edit";
let params = {
...data,
ypid: outRow.value.id,
ypmc: outRow.value.ypyt
};
const apiFun = !listQuery.value.id ? gsxtYpbgAddEntity : gsxtYpbgEditEntity
if (!listQuery.value.id) delete params.id
apiFun(params).then(() => {
loading.value = false;
proxy.$message({ type: "success", message: title.value + "成功" });
emit("ok");
close();
}).catch(() => {
loading.value = false;
})
});
};
//编辑器创建成功
const handleCreated = (editor) => {
editorRef.value = editor;
};
//内容发生变化
const handChange = (editor) => {
// 判断是否是一个空段落,是空就传空文本
};
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor) editor.destroy();
});
// 关闭
const close = () => {
listQuery.value = {};
loading.value = false;
dialogForm.value = false;
listQuery.value = {}
};
// 带样式的下载方法
const downloadWithStyles = (textContent) => {
const wordDocument = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>富文本导出</title>
<style>
/* 应用两端对齐样式 */
body {
text-align: justify;
text-justify: inter-character; /* 中文文本两端对齐 */
font-family: "Microsoft YaHei", Arial, sans-serif;
}
p {
text-align: justify;
text-justify: inter-character;
}
</style>
</head>
<body>
${textContent}
</body>
</html>
`;
const blob = new Blob([wordDocument], {
type: 'application/msword'
});
saveAs(blob, '战略研判报告.doc');
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.boxlist {
width: 99%;
margin-top: 10px;
}
::v-deep .el-textarea__inner {
min-height: 550px !important;
}
.html_bt>>>p {
color: red;
}
.html_bt {
h4 {
margin: 10px 0 !important;
}
}
.cntBox {
width: 80vw;
margin: 0 auto;
}
</style>

View File

@ -2,12 +2,12 @@
<div> <div>
<div class="titleBox"> <div class="titleBox">
<PageTitle title="战略研判"> <PageTitle title="战略研判">
<!-- <el-button type="primary" @click="getDataById('add', '')"> <el-button type="primary" @click="selfCreateResearch('add')">
<el-icon style="vertical-align: middle"> <el-icon style="vertical-align: middle">
<CirclePlus /> <CirclePlus />
</el-icon> </el-icon>
<span style="vertical-align: middle">新增</span> <span style="vertical-align: middle">自建研判</span>
</el-button> --> </el-button>
</PageTitle> </PageTitle>
</div> </div>
@ -28,7 +28,10 @@
<!-- 操作 --> <!-- 操作 -->
<template #controls="{ row }"> <template #controls="{ row }">
<!-- <el-link size="small" type="primary" @click="getDataById('edit', row)">修改</el-link> --> <!-- <el-link size="small" type="primary" @click="getDataById('edit', row)">修改</el-link> -->
<el-link size="small" type="danger" @click="getypbgSjzlTjspId(row.id)" >提交申请</el-link>
<el-link size="small" type="primary" @click="getDataById('detail', row)">详情</el-link> <el-link size="small" type="primary" @click="getDataById('detail', row)">详情</el-link>
<el-link size="small" type="primary" @click="createReport(row)">{{ row.ypbg?.id ? '编辑' : '创建' }}报告</el-link>
<el-link size="small" type="success" @click="createMeeting(row)">创建会议</el-link>
<el-link size="small" type="danger" @click="deleteFile(row)">删除</el-link> <el-link size="small" type="danger" @click="deleteFile(row)">删除</el-link>
</template> </template>
</MyTable> </MyTable>
@ -38,7 +41,12 @@
}"></Pages> }"></Pages>
</div> </div>
</div> </div>
<AddForm ref="addForm" @getList="getList" :dict="{ D_BZ_YPFS, D_BZ_YPLX }" /> <AddForm ref="addForm" :bglx="bglx" @getList="getList" :dict="{ D_BZ_YPFS, D_BZ_YPLX }" />
<!-- 创建报告 -->
<addReport ref="reportTc" :row="currRow" :dic="{ D_GS_BQ_LX }" @ok="getList" />
<!-- 创建报告 -->
<addMeeting ref="meetingTc" :row="currRow" @updateDate="getList" />
</template> </template>
<script setup> <script setup>
@ -46,21 +54,33 @@ import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue"; import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue"; import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue"; import Search from "@/components/aboutTable/Search.vue";
import { useRoute } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { tacticalGet, strategicDelete } from "@/api/huiShangyp/strategicApi.js"; import { tacticalGet, strategicDelete } from "@/api/huiShangyp/tacticalApi.js";
import { reactive, ref, onMounted, getCurrentInstance, watch,computed } from "vue"; import { reactive, ref, onMounted, getCurrentInstance, watch, computed, nextTick } from "vue";
import {ypbgSjzlTjspId} from "@/api/huiShangyp/strategicApi.js"
import addReport from "./addReport.vue";
import AddForm from "./addForm.vue"; import AddForm from "./addForm.vue";
import addMeeting from "./addMeeting.vue";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const { D_BZ_YPFS, D_BZ_YPLX } = proxy.$dict("D_BZ_YPFS", "D_BZ_YPLX") const { D_BZ_YPFS, D_BZ_YPLX, D_GS_BQ_LX } = proxy.$dict("D_BZ_YPFS", "D_BZ_YPLX", "D_GS_BQ_LX")
const detailDiloag = ref();
/** 报告弹框 */
const reportTc = ref();
/** 会议弹框 */
const meetingTc = ref();
const searchBox = ref(); //搜索框 const searchBox = ref(); //搜索框
const router = useRouter();
const route = useRoute();
onMounted(() => { onMounted(() => {
tabHeightFn() tabHeightFn()
if (route.query.id) { if (route.query.id) {
detailDiloag.value.init('edit', { nextTick(() => {
id: route.query.id addForm.value && addForm.value.init('edit', {
}); id: route.query.id
return });
router.replace({ path: '/tacticalResearch' })// 移除id 避免刷新一直带参数
})
} }
getList() getList()
}); });
@ -98,8 +118,12 @@ const pageData = reactive({
{ label: "发起部门", prop: "ssbm" }, { label: "发起部门", prop: "ssbm" },
] ]
}); });
const queryFrom = ref({});
const isShowReport = ref(false)
const currRow = ref({})
const queryFrom = ref({});
/** 报告类型 01 战术研判 02 战略研判*/
const bglx = ref('02')
// 搜索 // 搜索
const onSearch = (val) => { const onSearch = (val) => {
const promes = { const promes = {
@ -136,11 +160,11 @@ const getList = () => {
// 表格高度计算 // 表格高度计算
const tabHeightFn = () => { const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250; pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () { window.onresize = function() {
tabHeightFn(); tabHeightFn();
}; };
}; };
const route = useRoute() // const route = useRoute()
const addForm = ref(null) const addForm = ref(null)
const getDataById = (type, row) => { const getDataById = (type, row) => {
@ -163,6 +187,39 @@ const deleteFile = (row) => {
proxy.$message.info('已取消删除'); proxy.$message.info('已取消删除');
}); });
} }
const selfCreateResearch = (type = 'add') => {
addForm.value.init(type, null, '01');
}
/** 创建报告 */
const createReport = (row) => {
const type = !row.id ? 'add' : 'edit'
reportTc.value.init(type, row?.ypbg || {}, row)
// currRow.value = { ...row }
// isShowReport.value = true
}
/** 创建会议 */
const createMeeting = (row) => {
meetingTc.value.init('add', null, row)
// currRow.value = { ...row }
// isShowReport.value = true
}
// 提交研判
const getypbgSjzlTjspId = (id) => {
proxy.$confirm('确定提交研判申请吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ypbgSjzlTjspId(id).then((res) => {
proxy.$message.success('提交成功');
getList();
})
}).catch(() => {
proxy.$message.info('已取消提交');
});
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -8,20 +8,19 @@
</div> </div>
</div> </div>
<div style="padding-bottom: 0px;" class="form_cnt"> <div style="padding-bottom: 0px;" class="form_cnt">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules"> <FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules" :disabled="title === '详情'">
<template #bmList> <template #bmList>
<div class="table-box"> <div class="table-box">
<el-table :data="tableList" border style="width: 100%"> <el-table :data="tableList" border style="width: 100%">
<el-table-column prop="ypbmmc" label="部门" width="150" align="center" /> <el-table-column prop="ypbmmc" label="部门" width="150" align="center" />
<el-table-column label="研判素材" width="380" align="center"> <el-table-column label="研判素材" width="380" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-input v-model="row.scyq" type="textarea" :rows="3" :disabled="true" placeholder="请输入研判素材" /> <el-input v-model="row.scyq" placeholder="请输入研判素材" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="附件" width="200" align="center"> <el-table-column label="附件" width="200" align="center">
<template #default="{ row }"> <template #default="{ row }">
<UploadFile v-model="row.fj" :disabled="true" :limit="1" :isImg="false" <UploadFile v-model="row.fj" :limit="1" :isImg="false" :isAll="true" />
:isAll="true" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="wcqk" label="完成状态" width="120" align="center"> <el-table-column prop="wcqk" label="完成状态" width="120" align="center">
@ -91,16 +90,29 @@
</template> </template>
<script setup> <script setup>
/**
* @typedef {Object} JudgmentDept 研判部门对象
* @property {string} ypbmdm - 研判部门代码
* @property {string} ypbmmc - 研判部门名称
* @property {string} scyq - 素材要求
* @property {Array} fj - 附件数组
* @property {string} wcqk - 完成情况01 准备中、02 已完成)
*/
import FormMessage from "@/components/aboutTable/FormMessage.vue"; import FormMessage from "@/components/aboutTable/FormMessage.vue";
import UploadFile from "@/components/MyComponents/Upload/index.vue"; import UploadFile from "@/components/MyComponents/Upload/index.vue";
// import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue" // import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue"
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, watch, computed } from "vue"; import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, watch, computed } from "vue";
import { sjzlAddEntity, sjzlEditEntity, sjzlGetInfo, sjzlPerfectlnfo, sjzlFstz, sjzlQryp, sjzlPerfectSorce } from '@//api/yj.js' import { sjzlGetInfo, sjzlPerfectlnfo, sjzlFstz, sjzlQryp, sjzlPerfectSorce } from '@//api/yj.js'
import { selfBuildJudgment } from "@/api/huiShangyp/tacticalApi.js"
// import { tacticalGet, strategicDelete } from "@/api/huiShangyp/strategicApi.js";
import { getItem } from '@//utils/storage.js' import { getItem } from '@//utils/storage.js'
const emit = defineEmits(["updateDate", "getList"]); const emit = defineEmits(["updateDate", "getList"]);
const props = defineProps({ const props = defineProps({
dict: Object dict: Object,
/** 报告类型 01 战术研判 02战略研判 */
bglx: String,
}); });
const imgMsg = ref([]) const imgMsg = ref([])
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@ -146,7 +158,7 @@ watch(() => props.dict, (val) => {
formData.value = [ formData.value = [
{ label: "研判议题", prop: "ypyt", type: "input", width: '48%' }, { label: "研判议题", prop: "ypyt", type: "input", width: '48%' },
{ label: "研判时间", prop: "ypsj", type: "datetime", width: '48%' }, { label: "研判时间", prop: "ypsj", type: "datetime", width: '48%' },
{ label: "报告类型", prop: "bglx", type: "radio", options: props.dict.D_BZ_YPLX, width: '48%' }, { label: "报告类型", prop: "bglx", type: "radio", options: props.dict.D_BZ_YPLX, width: '48%', disabled: true },
{ label: "研判方式", prop: "ypfs", type: "radio", options: props.dict.D_BZ_YPFS, width: '48%' }, { label: "研判方式", prop: "ypfs", type: "radio", options: props.dict.D_BZ_YPFS, width: '48%' },
{ label: "参与研判部门", prop: "jsdxBmDm", type: "department", multiple: true, depMc: 'jsdxBmMc', width: '48%' }, { label: "参与研判部门", prop: "jsdxBmDm", type: "department", multiple: true, depMc: 'jsdxBmMc', width: '48%' },
{ label: "研判要求", prop: "ypyq", type: "textarea", width: '100%' }, { label: "研判要求", prop: "ypyq", type: "textarea", width: '100%' },
@ -164,6 +176,8 @@ function updateDis(row) {
const isFinish = row.wcqk === '02' const isFinish = row.wcqk === '02'
return isShiQingBaoZhongXin.value || !iscjr || isFinish return isShiQingBaoZhongXin.value || !iscjr || isFinish
} }
/** 获取附件数组 */
function getFjArr(fj) { function getFjArr(fj) {
if (typeof fj !== 'string' || !fj) return [] if (typeof fj !== 'string' || !fj) return []
let fjArr = [] let fjArr = []
@ -175,18 +189,19 @@ function getFjArr(fj) {
return fjArr return fjArr
} }
watch(() => listQuery.value.jsdxBmDm, (val) => { watch(() => listQuery.value.jsdxBmDm, (val) => {
/** @type {Array<{ypbmdm: string, ypbmmc: string, scyq: string, fj: Array, wcqk: string}>} 参与研判部门数据数组 */ /** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const arr = Array.isArray(val) ? val : [] const arr = Array.isArray(val) ? val : []
/** @type {Array} 参与研判部门*/
const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : [] const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : []
tableList.value = arr.map((item, i) => { tableList.value = arr.map((item, i) => {
/** 找原来的对象 */ /** 找原来的对象 */
const curr = cyypList.find(item2 => item2.ypbmdm == item) || {} const curr = cyypList.find(item2 => item2.ypbmdm == item) || {}
/** 是否是新增 */ /** 是否是新增 */
const isAddForm = !listQuery.value.id const isAddForm = !listQuery.value?.id
return { return {
// id: null, // id: null,
// sjzlid: null, // 研判战研判ID // sjzlid: null, // 研判战研判ID
/** 部门代码 */ /** 部门代码 */
ypbmdm: item, ypbmdm: item,
ypbmmc: listQuery.value.jsdxBmMc[i], ypbmmc: listQuery.value.jsdxBmMc[i],
@ -202,13 +217,24 @@ watch(() => listQuery.value.jsdxBmDm, (val) => {
const init = (type, row, wjlb) => { const init = (type, row, wjlb) => {
dialogForm.value = true; dialogForm.value = true;
title.value = type == "add" ? "新增" : type == "edit" ? "编辑" : "详情"; title.value = type == "add" ? "新增" : type == "edit" ? "编辑" : "详情";
outRow.value = row || {} outRow.value = row
if (row) { getDataById(row.id) } if (row) {
getDataById(row.id)
} else {
listQuery.value = {
bglx: props.bglx, // 报告类型 01 战术研判 02战略研判
ypfs: undefined, // 研判方式
ypsj: undefined, // 研判时间
ypyq: undefined, // 研判要求
cyypList: [], // 参与研判部门数据数组
}
}
}; };
// 根据id查询详情 // 根据id查询详情
const getDataById = (id) => { const getDataById = (id) => {
sjzlGetInfo(id).then((res) => { sjzlGetInfo(id).then((res) => {
listQuery.value = res || {}; listQuery.value = res || {};
/** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const cyypList = Array.isArray(res.cyypList) ? res.cyypList : [] const cyypList = Array.isArray(res.cyypList) ? res.cyypList : []
listQuery.value.jsdxBmDm = cyypList.map(item => { listQuery.value.jsdxBmDm = cyypList.map(item => {
return item.ypbmdm return item.ypbmdm
@ -218,21 +244,21 @@ const getDataById = (id) => {
}) })
}); });
}; };
/** 获取附件json字符串 */
function getFjString(arr) { function getFjString(arr) {
arr = Array.isArray(arr) ? arr : [] arr = Array.isArray(arr) ? arr : []
return JSON.stringify(arr) return JSON.stringify(arr)
} }
/**获取下发部门数据 */ /**获取下发部门数据 */
const getXfbmList = () => { const getXfbmList = () => {
/** @type {Array<JudgmentDept>} 参与研判部门数据数组 */
const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : [] const cyypList = Array.isArray(listQuery.value.cyypList) ? listQuery.value.cyypList : []
return tableList.value.map((item, i) => { return tableList.value.map((item, i) => {
/** @type {JudgmentDept} 找原来的对象 */
/** 找原来的对象 */
const curr = cyypList.find(item => item.ypbmdm == item.ypbmdm) || {} const curr = cyypList.find(item => item.ypbmdm == item.ypbmdm) || {}
return { return {
id: curr.id || null, id: curr.id || null,
sjzlid: curr.sjzlid || null, // 研判战研判ID sjzlid: curr.sjzlid || null, // 研判战研判ID
ypbmdm: item.ypbmdm, ypbmdm: item.ypbmdm,
ypbmmc: listQuery.value.jsdxBmMc[i], ypbmmc: listQuery.value.jsdxBmMc[i],
/** 素材要求 */ /** 素材要求 */
@ -251,21 +277,14 @@ const submit = () => {
let params = { let params = {
...listQuery.value, ...listQuery.value,
cyypList: xfbmList, cyypList: xfbmList,
// cyypList: listQuery.value.jsdxBmDm.map((item, index) => {
// return {
// ypbmdm: item,
// ypbmmc: listQuery.value.jsdxBmMc[index],
// ypcylx: '01'
// }
// })
}; };
try { try {
loading.value = true; loading.value = true;
let res let res
if (title.value == "新增") { if (title.value == "新增") {
res = await sjzlAddEntity(params) res = await selfBuildJudgment(params)
} else { } else {
res = await sjzlEditEntity(params) // res = await sjzlEditEntity(params)// 目前没有修改
} }
if (res && res > 0) { if (res && res > 0) {
loading.value = false; loading.value = false;
@ -357,7 +376,7 @@ const submitMaterialAction = async () => {
closeMaterialDialog() closeMaterialDialog()
if (outRow.value.id) { getDataById(outRow.value.id) } if (outRow.value.id) { getDataById(outRow.value.id) }
} catch (error) { } catch (error) {
console.log(error)
} finally { } finally {
materialLoading.value = false materialLoading.value = false
} }
@ -383,7 +402,7 @@ const sendNotice = () => {
proxy.$message({ type: "success", message: "下发通知成功" }); proxy.$message({ type: "success", message: "下发通知成功" });
close(); close();
} catch (error) { } catch (error) {
console.log(error);
} finally { } finally {
noticeLoading.value = false; noticeLoading.value = false;
} }
@ -404,7 +423,7 @@ const confirmJudgment = () => {
proxy.$message({ type: "success", message: "确认研判成功" }); proxy.$message({ type: "success", message: "确认研判成功" });
close(); close();
} catch (error) { } catch (error) {
console.log(error);
} finally { } finally {
confirmLoading.value = false; confirmLoading.value = false;
} }

View File

@ -0,0 +1,137 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">创建会议{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<!-- <template #glxsmc>
<el-input placeholder="请选择关联线索" @click="chooseVisiblexS = true" readonly v-model="listQuery.glxsmc"></el-input>
</template> -->
<template #chryList>
<el-input placeholder="请选择参会人员" @click="openMeetings = true" readonly v-model="listQuery.rymc"></el-input>
</template>
</FormMessage>
</div>
</div>
<Personnel v-model="openMeetings" />
<ChooseUser v-model="chooseVisible" :Single="false" @choosedUsers="handleUserSelected" :roleIds="roleIds" />
<Xslist v-model="chooseVisiblexS" @choosed="choosed" :roleIds="roleIdsxs"></Xslist>
</template>
<script setup>
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
// import Xslist from '@/components/ChooseList/ChooseXs/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import Personnel from '@/views/backOfficeSystem/JudgmentHome/MeetingRoom/components/Communications/personnel.vue'
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, } from "vue";
import dayjs from 'dayjs';
const emit = defineEmits(["updateDate"]);
const roleIds = ref([]); //角色id
const chooseVisible = ref(false);
const roleIdsxs = ref([]); //角色id
const chooseVisiblexS = ref(false);
const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗
const rules = reactive({
hskssj: [{ required: true, message: "请选择会商开始时间", trigger: "change" }],
hsjssj: [{ required: true, message: "请选择会商结束时间", trigger: "change" }],
hsnr: [{ required: true, message: "请输入会商内容", trigger: "blur" }],
hsbt: [{ required: true, message: "请输入会商标题", trigger: "blur" }],
// glxsmc: [{ required: true, message: "请选择关联线索", trigger: "change" }],
chryList: [{ required: true, message: "请选择参会人员", trigger: "change" }],
});
const formData = ref([
{ label: "会商开始时间", prop: "hskssj", type: "datetime" },
{ label: "会商结束时间", prop: "hsjssj", type: "datetime" },
{ label: "会商内容", prop: "hsnr", type: "textarea", width: "100%" },
// { label: "关联线索", prop: "glxsmc", type: "slot", },
{ label: "会商标题", prop: "hsbt", type: "input" },
// { label: "参会人员", prop: "chryList", type: "slot" ,width:'100%'},
]);
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();
const title = ref("");
const outRow = ref({})
// 初始化数据
const init = (type, row, outRowObj = {}) => {
outRow.value = outRowObj
dialogForm.value = true;
title.value = type == "add" ? "新增" : "编辑";
if (row) {
getDataById(row.id)
} else {
listQuery.value = {
hskssj: dayjs().format("YYYY-MM-DD HH:mm:ss"),
hsjssj: dayjs().add(1, "hour").format("YYYY-MM-DD HH:mm:ss"),
}
}
};
// 根据id查询详情
const getDataById = (id) => {
qcckGet({ id }, "/mosty-gsxt/wshs/selectByid").then((res) => {
res.rymc = res.chryList ? res.chryList.map(v => v.chryxm).join(",") : '';
res.chryList = res.chryList ? res.chryList.map(item => item.chryid) : [];
roleIds.value = res.chryList;
roleIdsxs.value = res.glxsid ? [res.glxsid] : [];
listQuery.value = res;
});
};
const handleUserSelected = (userData) => {
roleIds.value = userData.map(item => item.id);
listQuery.value.chryList = userData.map(item => item.id)
listQuery.value.rymc = userData.map(item => item.userName).join("、");
};
const choosed = (data) => {
listQuery.value.glxsmc = data[0].xsMc;
listQuery.value.glxsid = data[0].id;
roleIdsxs.value = data.map(item => item.id);
};
// 提交
const submit = () => {
elform.value.submit((data) => {
let url = title.value == "新增" ? "/mosty-gsxt/wshs/add" : "/mosty-gsxt/wshs/update";
let params = {
...data,
glxsid: outRow.value.id,
glxsmc: outRow.value.xsMc,
};
loading.value = true;
qcckPost(params, url).then(() => {
loading.value = false;
proxy.$message({ type: "success", message: title.value + "成功" });
emit("updateDate");
close();
}).catch(() => { loading.value = false; });
});
};
// 关闭
const close = () => {
listQuery.value = {};
roleIds.value = [];
roleIdsxs.value = [];
dialogForm.value = false;
loading.value = false;
};
// 选择参会人员
const openMeetings = ref(false)
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
</style>

View File

@ -0,0 +1,273 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">报告{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage :formList="formData" v-model="listQuery" ref="elform" :rules="rules">
<template #bgnr>
<el-input v-model="listQuery.bgnr" style="width: 100%" placeholder="请输入关键字" class="input-with-select">
<template #append>
<el-button :icon="Search" type="primary">搜索</el-button>
</template>
</el-input>
</template>
<template #fj><el-button type="primary" @click="showText = true">附件上传</el-button></template>
</FormMessage>
<div class="cntBox">
<!-- 工具栏 -->
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig"
:mode="mode" />
<!-- 编辑器 -->
<Editor :style="`height: 480px; overflow-y: hidden`" v-model="textContent" :defaultConfig="editorConfig"
:mode="mode" @onCreated="handleCreated" @onChange="handChange" />
</div>
<div v-if="outRow.id" style="display: flex; justify-content: center;">
<!-- <el-button style="display: block;" type="primary" @click="ConsultationShow = true">网上会商</el-button> -->
<el-button style="display: block;" type="primary" @click="downloadWithStyles(textContent)">下载</el-button>
</div>
</div>
</div>
<!-- 文字解析 -->
<ExtractionText v-model="showText" @change="getText"></ExtractionText>
<!-- 网上会商 -->
<!-- <Consultation v-model="ConsultationShow" /> -->
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
import { timeValidate } from '@/utils/tools.js'
import ExtractionText from "@/components/ExtractionText/index.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import "@wangeditor/editor/dist/css/style.css";
// import Consultation from './consultation.vue'
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, shallowRef, onBeforeUnmount, watch } from "vue";
import { gsxtYpbgAddEntity, gsxtYpbgEditEntity } from "@/api/huiShangyp/tacticalApi.js"
const emit = defineEmits(["updateDate", 'ok']);
const props = defineProps({
dic: Object,
});
const ConsultationShow = ref(false)
const showText = ref(false);
const textContent = ref()
const { proxy } = getCurrentInstance();
const editorRef = shallowRef();
const dialogForm = ref(false); //弹窗
const mode = "default";
const dataBt = ref(`<p class="html_bt">
<h4 style=\"text-align: center;\"><span style=\"color: rgb(225, 60, 57); font-size: 32px; font-family: 标楷体;\">林芝市公安局情指中心</span></h4>
<h4 style=\"text-align: center;\"><span style=\"color: rgb(225, 60, 57); font-size: 32px; font-family: 标楷体;\">研判专刊(初稿)</span></h4></p>
<p style="text-align: center;"><span style="color: rgb(225, 60, 57); font-size: 22px; font-family: 标楷体;">市公安局情指中心编</span></p>
<p style="text-align: center;"><span style="color: rgb(225, 60, 57); font-size: 22px; font-family: 标楷体;"> ${timeValidate(new Date(), 'td')}</span></p>
<hr/>`)
//编辑器配置
const editorConfig = {
withCredentials: true, //允许跨域
placeholder: props.placeholder, //提示语
MENU_CONF: {
uploadImage: {
// 自定义上传图片
async customUpload(file, insertFn) {
let fileBlob = await compressImage(file);
let fileData = new File([fileBlob], fileBlob.name, { type: fileBlob.type });
if (fileData.size > 2 * 1024 * 1024) {
ElMessage({ message: "图片超过2MB", type: "success" });
} else {
await uploadFn(fileData, insertFn);
}
}
},
uploadVideo: {
// 自定义上传视频
async customUpload(file, insertFn) {
await uploadFn(file, insertFn);
}
}
}
};
//工具配置
const toolbarConfig = {
excludeKeys: ["blockquote", "codeBlock"] //清除不必要的工具,引用和代码块
};
const rules = reactive({
jymc: [
{ required: true, message: "请输入经验名称", trigger: "blur" }
],
fbnr: [
{ required: true, message: "请输入经验内容", trigger: "blur" }
]
});
const formData = ref([
{ label: "报告名称", prop: "bgmc", type: "input", width: "100%", blur: setEditorTextContent },
{ label: "报告内容", prop: "bgnr", type: "slot", width: "100%", blur: setEditorTextContent },
// { label: "附件内容", prop: "fj", type: "slot", width: "100%" },
]);
const listQuery = ref({
bgmc: "",
bgnr: "",
fj: ""
}); //表单
const loading = ref(false);
const elform = ref();
const title = ref("");
/** 外面行数据 */
const outRow = ref({})
// 初始化数据
const init = (type, reportData, row) => {
listQuery.value = {
bgmc: reportData.bgmc,
bgnr: reportData.bgnr,
id: reportData.id,
// fj: reportData.fj
}
outRow.value = { ...row }
dialogForm.value = true;
title.value = type == "add" ? "新增" : "编辑";
setEditorTextContent()
};
const getText = (val, row = {}) => {
listQuery.value.fj = val.text;
setEditorTextContent()
}
function setEditorTextContent() {
let html = dataBt.value;
html += `<p style="text-align: center;"><span style="font-size: 22px;">${listQuery.value.bgmc || ''}</span></p>`
html += `<p>${listQuery.value.fj || ''}</p>`
textContent.value = html
}
// watch(() => listQuery.value, (val) => {
// },
// {
// deep: true, immediate: true
// })
// 提交
const submit = () => {
elform.value.submit((data) => {
// let url = title.value == "新增" ? "/mosty-gsxt/gsxt/jyfx/add" : "/mosty-gsxt/gsxt/jyfx/edit";
let params = {
...data,
ypid: outRow.value.id,
ypmc: outRow.value.ypyt
};
const apiFun = !listQuery.value.id ? gsxtYpbgAddEntity : gsxtYpbgEditEntity
if (!listQuery.value.id) delete params.id
apiFun(params).then(() => {
loading.value = false;
proxy.$message({ type: "success", message: title.value + "成功" });
emit("ok");
close();
}).catch(() => {
loading.value = false;
})
});
};
//编辑器创建成功
const handleCreated = (editor) => {
editorRef.value = editor;
};
//内容发生变化
const handChange = (editor) => {
// 判断是否是一个空段落,是空就传空文本
};
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor) editor.destroy();
});
// 关闭
const close = () => {
listQuery.value = {};
loading.value = false;
dialogForm.value = false;
listQuery.value = {}
};
// 带样式的下载方法
const downloadWithStyles = (textContent) => {
const wordDocument = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>富文本导出</title>
<style>
/* 应用两端对齐样式 */
body {
text-align: justify;
text-justify: inter-character; /* 中文文本两端对齐 */
font-family: "Microsoft YaHei", Arial, sans-serif;
}
p {
text-align: justify;
text-justify: inter-character;
}
</style>
</head>
<body>
${textContent}
</body>
</html>
`;
const blob = new Blob([wordDocument], {
type: 'application/msword'
});
saveAs(blob, '战略研判报告.doc');
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.boxlist {
width: 99%;
margin-top: 10px;
}
::v-deep .el-textarea__inner {
min-height: 550px !important;
}
.html_bt>>>p {
color: red;
}
.html_bt {
h4 {
margin: 10px 0 !important;
}
}
.cntBox {
width: 80vw;
margin: 0 auto;
}
</style>

View File

@ -2,12 +2,12 @@
<div> <div>
<div class="titleBox"> <div class="titleBox">
<PageTitle title="战术研判"> <PageTitle title="战术研判">
<!-- <el-button type="primary" @click="getDataById('add', '')"> <el-button type="primary" @click="selfCreateResearch('add')">
<el-icon style="vertical-align: middle"> <el-icon style="vertical-align: middle">
<CirclePlus /> <CirclePlus />
</el-icon> </el-icon>
<span style="vertical-align: middle">新增</span> <span style="vertical-align: middle">自建研判</span>
</el-button> --> </el-button>
</PageTitle> </PageTitle>
</div> </div>
@ -27,8 +27,11 @@
</template> </template>
<!-- 操作 --> <!-- 操作 -->
<template #controls="{ row }"> <template #controls="{ row }">
<el-link size="small" type="danger" @click="getypbgSjzlTjspId(row.id)" >提交申请</el-link>
<!-- <el-link size="small" type="primary" @click="getDataById('edit', row)">修改</el-link> --> <!-- <el-link size="small" type="primary" @click="getDataById('edit', row)">修改</el-link> -->
<el-link size="small" type="primary" @click="getDataById('detail', row)">详情</el-link> <el-link size="small" type="primary" @click="getDataById('detail', row)">详情</el-link>
<el-link size="small" type="primary" @click="createReport(row)">{{ row.ypbg?.id ? '编辑' : '创建' }}报告</el-link>
<el-link size="small" type="success" @click="createMeeting(row)">创建会议</el-link>
<el-link size="small" type="danger" @click="deleteFile(row)">删除</el-link> <el-link size="small" type="danger" @click="deleteFile(row)">删除</el-link>
</template> </template>
</MyTable> </MyTable>
@ -38,7 +41,12 @@
}"></Pages> }"></Pages>
</div> </div>
</div> </div>
<AddForm ref="addForm" @getList="getList" :dict="{ D_BZ_YPFS, D_BZ_YPLX }" /> <AddForm ref="addForm" :bglx="bglx" @getList="getList" :dict="{ D_BZ_YPFS, D_BZ_YPLX }" />
<!-- 创建报告 -->
<addReport ref="reportTc" :row="currRow" :dic="{ D_GS_BQ_LX }" @ok="getList" />
<!-- 创建报告 -->
<addMeeting ref="meetingTc" :row="currRow" @updateDate="getList" />
</template> </template>
<script setup> <script setup>
@ -46,21 +54,33 @@ import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue"; import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue"; import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue"; import Search from "@/components/aboutTable/Search.vue";
import { useRoute } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { tacticalGet, strategicDelete } from "@/api/huiShangyp/tacticalApi.js"; import { tacticalGet, strategicDelete, } from "@/api/huiShangyp/tacticalApi.js";
import { reactive, ref, onMounted, getCurrentInstance, watch, computed } from "vue"; import {ypbgSjzlTjspId} from "@/api/huiShangyp/strategicApi.js"
import { reactive, ref, onMounted, getCurrentInstance, watch, computed, nextTick } from "vue";
import addReport from "./addReport.vue";
import AddForm from "./addForm.vue"; import AddForm from "./addForm.vue";
import addMeeting from "./addMeeting.vue";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const { D_BZ_YPFS, D_BZ_YPLX } = proxy.$dict("D_BZ_YPFS", "D_BZ_YPLX") const { D_BZ_YPFS, D_BZ_YPLX, D_GS_BQ_LX } = proxy.$dict("D_BZ_YPFS", "D_BZ_YPLX", "D_GS_BQ_LX")
const detailDiloag = ref();
/** 报告弹框 */
const reportTc = ref();
/** 会议弹框 */
const meetingTc = ref();
const searchBox = ref(); //搜索框 const searchBox = ref(); //搜索框
const router = useRouter();
const route = useRoute();
onMounted(() => { onMounted(() => {
tabHeightFn() tabHeightFn()
if (route.query.id) { if (route.query.id) {
detailDiloag.value.init('edit', { nextTick(() => {
id: route.query.id addForm.value && addForm.value.init('edit', {
}); id: route.query.id
return });
router.replace({ path: '/tacticalResearch' })// 移除id 避免刷新一直带参数
})
} }
getList() getList()
}); });
@ -98,8 +118,12 @@ const pageData = reactive({
{ label: "发起部门", prop: "ssbm" }, { label: "发起部门", prop: "ssbm" },
] ]
}); });
const queryFrom = ref({});
const isShowReport = ref(false)
const currRow = ref({})
const queryFrom = ref({});
/** 报告类型 01 战术研判 02 战略研判*/
const bglx = ref('01')
// 搜索 // 搜索
const onSearch = (val) => { const onSearch = (val) => {
const promes = { const promes = {
@ -123,7 +147,7 @@ const changeSize = (val) => {
// 获取列表 // 获取列表
const getList = () => { const getList = () => {
pageData.tableConfiger.loading = true; pageData.tableConfiger.loading = true;
// bglx 报告类型01 战术研判 02 战略研判) // bglx 报告类型01 战术研判 02 战略研判)
let data = { ...pageData.pageConfiger, ...queryFrom.value, bglx: '01' }; let data = { ...pageData.pageConfiger, ...queryFrom.value, bglx: '01' };
tacticalGet(data).then(res => { tacticalGet(data).then(res => {
pageData.tableData = res.records || []; pageData.tableData = res.records || [];
@ -140,7 +164,7 @@ const tabHeightFn = () => {
tabHeightFn(); tabHeightFn();
}; };
}; };
const route = useRoute() // const route = useRoute()
const addForm = ref(null) const addForm = ref(null)
const getDataById = (type, row) => { const getDataById = (type, row) => {
@ -163,6 +187,39 @@ const deleteFile = (row) => {
proxy.$message.info('已取消删除'); proxy.$message.info('已取消删除');
}); });
} }
const selfCreateResearch = (type = 'add') => {
addForm.value.init(type, null, '01');
}
/** 创建报告 */
const createReport = (row) => {
const type = !row.id ? 'add' : 'edit'
reportTc.value.init(type, row?.ypbg || {}, row)
// currRow.value = { ...row }
// isShowReport.value = true
}
/** 创建会议 */
const createMeeting = (row) => {
meetingTc.value.init('add', null, row)
// currRow.value = { ...row }
// isShowReport.value = true
}
// 提交研判
const getypbgSjzlTjspId = (id) => {
proxy.$confirm('确定提交研判申请吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ypbgSjzlTjspId(id).then((res) => {
proxy.$message.success('提交成功');
getList();
})
}).catch(() => {
proxy.$message.info('已取消提交');
});
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -76,22 +76,21 @@ const props = defineProps({
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗 const dialogForm = ref(false); //弹窗
const rules = reactive({ const rules = reactive({
xsMc: [{ required: true, message: "请输入线索名称", trigger: "blur" }], qbmc: [{ required: true, message: "请输入线索名称", trigger: "blur" }],
xlLx: [{ required: true, message: "请选择线索类型", trigger: "change" }], qblx: [{ required: true, message: "请选择线索类型", trigger: "change" }],
qbLy: [{ required: true, message: "请选择情报来源", trigger: "change" }],
}); });
const formData = ref([ const formData = ref([
{ prop: "gapdive", type: "slot", width: '100%' }, { prop: "gapdive", type: "slot", width: '100%' },
{ label: "线索名称", prop: "xsMc", type: "input" }, { label: "线索名称", prop: "qbmc", type: "input" },
{ label: "线索类型", prop: "xlLx", type: "select", options: props.dic.D_GS_XS_LX }, { label: "线索类型", prop: "qblx", type: "select", options: props.dic.D_GS_XS_LX },
{ label: "情报来源", prop: "qbLy", type: "select", options: props.dic.D_GS_XS_LY }, // { label: "情报来源", prop: "qbly", type: "select", options: props.dic.D_GS_XS_LY },
{ label: "指向开始时间", prop: "zxkssj", type: "datetime" }, // { label: "指向开始时间", prop: "zxkssj", type: "datetime" },
{ label: "指向结束时间", prop: "zxjssj", type: "datetime" }, // { label: "指向结束时间", prop: "zxjssj", type: "datetime" },
{ label: "指向地点", prop: "zxdz", type: "input" }, { label: "线索地点", prop: "zxdz", type: "input" },
{ label: "所属专题", prop: "sszt", type: "select", options: props.dic.D_BZ_SSZT }, { label: "所属专题", prop: "sszt", type: "select", options: props.dic.D_BZ_SSZT },
{ prop: "gapline", type: "slot", width: '100%' }, { prop: "gapline", type: "slot", width: '100%' },
{ prop: "scfj", type: "slot", width: '100%' }, { prop: "scfj", type: "slot", width: '100%' },
{ label: "线索内容", prop: "xsNr", type: "textarea", width: '100%' }, { label: "线索内容", prop: "qbnr", type: "textarea", width: '100%' },
]); ]);
const fjdz = ref() const fjdz = ref()
const listQuery = ref({}); //表单 const listQuery = ref({}); //表单

View File

@ -0,0 +1,112 @@
<template>
<el-dialog v-model="modelValue" title="线索下发" width="50%" @close="closeDialog" destroy-on-close append-to-body>
<div style="height: 50vh; overflow: auto;">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="submitForm">确认 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import { ref, reactive, getCurrentInstance, watch } from "vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
const { proxy } = getCurrentInstance()
const { D_GS_XS_ZLLX, D_GS_ZDQT_FXDJ } = proxy.$dict('D_GS_XS_ZLLX', 'D_GS_ZDQT_FXDJ')
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dataList: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['update:modelValue', 'getList'])
const elform = ref(null)
const closeDialog = (formEl) => {
emit('update:modelValue', false)
}
const rules = reactive({
glxs: [{ required: true, message: '请输入线索名称', trigger: 'blur' }],
zlbt: [{ required: true, message: '请输入指令标题', trigger: 'blur' }],
zllx: [{ required: true, message: '请选择指令类型', trigger: 'change' }],
zldj: [{ required: true, message: '请选择指令等级', trigger: 'change' }],
xfbmList: [{ required: true, message: '请选择下发部门集合', trigger: 'change' }],
zsdw: [{ required: true, message: '请选择主送单位', trigger: 'change' }],
csdw: [{ required: true, message: '请选择抄送单位', trigger: 'change' }],
zlnr: [{ required: true, message: '请输入指令内容', trigger: 'blur' }],
})
const listQuery = ref({})
const formData = ref(
[
{ label: "线索名称", prop: "glxs", type: "input" },
{ label: "指令标题", prop: "zlbt", type: "input" },
{ label: "指令类型", prop: "zllx", type: "select", options: D_GS_XS_ZLLX },
{ label: "指令等级", prop: "zldj", type: "select", options: D_GS_ZDQT_FXDJ },
{ label: "指令联系人", prop: "zllxr", type: "input" },
{ label: "指令联系电话", prop: "zllxdh", type: "input" },
{ label: "指令结束时间", prop: "jssj", type: "datetime" },
{ label: "下发部门集合", depMc: 'xfbmListMc', prop: "xfbmList", type: "department", width: "90%", multiple: true },
{ label: "主送单位", prop: "zsdw", type: "department" },
{ label: "抄送单位", prop: "csdw", type: "department" },
{ label: "指令内容", prop: "zlnr", type: "textarea", width: "90%" },
{ label: "附件地址", prop: "fjzd", type: "upload", width: "90%" },
]
)
watch(() => props.modelValue, (newVal, oldVal) => {
if (newVal) {
listQuery.value.xsid = props.dataList.id
listQuery.value.glxsid = props.dataList.id
listQuery.value.glxs = props.dataList.qbmc
}
}, { deep: true })
const submitForm = (formEl) => {
console.log(listQuery.value);
elform.value.submit((valid) => {
if (valid) {
const params = {
...listQuery.value,
fjzd:listQuery.value.fjzd? listQuery.value.fjzd.join(',') : '',
xfbmList: listQuery.value.xfbmList.map((item, index) => {
return {
ssbm: listQuery.value.xfbmListMc[index],
ssbmdm: item,
}
}),
}
qcckPost(params, '/mosty-gsxt/qbcj/xfxs').then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
emit('update:modelValue', false)
// closeDialog(formEl);
}).catch(() => {
proxy.$message({ type: "error", message: "新增失败" });
});
console.log(params);
// emit('getList', listQuery)
// closeDialog(formEl)
} else {
console.log('校验失败');
}
})
// formEl.validate((valid) => {
// if (valid) {
// emit('getList', listQuery)
// closeDialog(formEl)
// } else {
// console.log('校验失败');
// }
// })
}
</script>
<style scoped></style>

View File

@ -3,105 +3,68 @@
<div class="titleBox"> <div class="titleBox">
<PageTitle title="线索数据采集"> <PageTitle title="线索数据采集">
<el-button type="primary" @click="addEdit('add', null)"> <el-button type="primary" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon> <el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">新增</span> <span style="vertical-align: middle">新增</span>
</el-button> </el-button>
<el-button type="danger"> <el-button type="danger" @click="plDelDictItem">
<el-icon style="vertical-align: middle"><Dete /></el-icon> <el-icon style="vertical-align: middle">
<Dete />
</el-icon>
<span style="vertical-align: middle">批量删除</span> <span style="vertical-align: middle">批量删除</span>
</el-button> </el-button>
</PageTitle> </PageTitle>
</div> </div>
<!-- 搜索 --> <!-- 搜索 -->
<div ref="searchBox"> <div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"/> <Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div> </div>
<!-- 表格 --> <!-- 表格 -->
<div class="tabBox"> <div class="tabBox">
<MyTable <MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:tableData="pageData.tableData" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
:tableColumn="pageData.tableColumn" @chooseData="chooseData">
:tableHeight="pageData.tableHeight" <template #qblx="{ row }">
:key="pageData.keyCount" <DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth">
<template #xlLx="{row}">
<DictTag :tag="false" :value="row.xlLx" :options="D_GS_XS_LX" />
</template> </template>
<template #qbLy="{row}"> <template #cjLx="{ row }">
<DictTag :tag="false" :value="row.qbLy" :options="D_GS_XS_LY" /> <DictTag :tag="false" :value="row.cjLx" :options="D_GS_XS_LY" />
</template> </template>
<template #czzt="{row}"> <template #czzt="{ row }">
<DictTag :tag="false" :value="row.czzt" :options="D_GS_XS_CZZT" /> <DictTag :tag="false" :value="row.czzt" :options="D_GS_XS_XSCZZT" />
</template> </template>
<template #zxkssj="{row}">
<span>{{ row.zxkssj }}</span> <template #shzt="{ row }">
<span>{{ row.zxjssj }}</span>
</template>
<template #shzt="{row}">
<!-- 采纳将这条信息推送到情报管理,退回 --> <!-- 采纳将这条信息推送到情报管理,退回 -->
<DictTag :tag="false" :value="row.shzt" :options="D_BZ_XSSHZT" @clickTag="clickTag(row.shzt)" /> <DictTag :tag="false" :value="row.shzt" :options="D_BZ_XSSHZT" @clickTag="clickTag(row.shzt)" />
</template> </template>
<!-- 操作 --> <!-- 操作 -->
<template #controls="{ row }"> <template #controls="{ row }">
<template v-if="row.shzt === '0'"> <el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<template v-if="!row.gzlid">
<el-link size="small" type="success" @click="addEdit('edit', row)">编辑</el-link>
<el-link size="small" type="primary" @click.stop="createProcess(row)">审核</el-link>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
</template> </template>
<el-link size="small" type="warning" @click="openXsxf( row)">线索下发</el-link>
<!-- <el-popover placement="left" :visible="row.visible" :width="400" trigger="click">
<template #reference>
<el-link size="small" type="primary" @click.stop="handleSh(row)">审核</el-link>
</template>
<div class="flex mb10 align-center">
<div class="w70 label-pop">审核状态 :</div>
<div style="flex:1">
<el-radio-group v-model="chooseRow.shzt" @change="rules.bhyy = false">
<el-radio v-for="obj in D_BZ_XSSHZT" :key="obj.value" :label="obj.value" >{{ obj.zdmc }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex" v-if=" chooseRow.shzt == '01'">
<div class="w70 label-pop">驳回原因 :</div>
<div style="flex:1">
<MOSTY.Other filterable style="width: 100%;" v-model="chooseRow.bhyy" type="textarea" rows="3" clearable placeholder="请输入审核原因"/>
<div class="f12" style="color: red;" v-if="rules.bhyy">请输入驳回原因</div>
</div>
</div>
<div class="mt10 flex just-center">
<el-button size="small" @click.stop="cancel(row)">取消</el-button>
<el-button size="small" type="primary" @click.stop="handleSumbit(row)">确定</el-button>
</div>
</el-popover> -->
<template v-if="!row.gzlid">
<el-link size="small" type="success" @click="addEdit('edit', row)">编辑</el-link>
<el-link size="small" type="primary" @click.stop="createProcess(row)">审核</el-link>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
</template>
<el-link size="small" type="danger" @click="addEdit('info', row)">详情</el-link>
<!-- 续报 == 编辑 -->
<el-link size="small" type="warning" @click="addEdit('edit', row)">续报</el-link>
</template> </template>
</MyTable> </MyTable>
<Pages <Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
@changeNo="changeNo" ...pageData.pageConfiger,
@changeSize="changeSize" total: pageData.total
:tableHeight="pageData.tableHeight" }"></Pages>
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div> </div>
<!-- 新增 --> <!-- 新增 -->
<AddForm ref="detailDiloag" @change="getList" v-if="isShow" :dic="{D_BZ_SF,D_BZ_XB,D_GS_XS_LY,D_BZ_SSZT,D_GS_XS_LX ,D_GS_XS_QTLX}" /> <AddForm ref="detailDiloag" @change="getList" v-if="isShow"
:dic="{ D_BZ_SF, D_BZ_XB, D_GS_XS_LY, D_BZ_SSZT, D_GS_XS_LX, D_GS_XS_QTLX }" />
</div> </div>
<SubmissionProcess v-model="showSp" :data="rowData" :userData="{ ajmc: '线索数据采集审批', flowType: 'XSSJCJSP',modelName:'线索' }" <SubmissionProcess v-model="showSp" :data="rowData"
:path="fixedValue" @getList="getList" /> :userData="{ ajmc: '线索数据采集审批', flowType: 'XSSJCJSP', modelName: '线索' }" :path="fixedValue" @getList="getList" />
<Xsxf v-model="xsxfShow" :dataList="rowData"/>
</template> </template>
<script setup> <script setup>
import * as MOSTY from "@/components/MyComponents/index";
import PageTitle from "@/components/aboutTable/PageTitle.vue"; import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue"; import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue"; import Pages from "@/components/aboutTable/Pages.vue";
@ -111,27 +74,20 @@ import SubmissionProcess from '@/components/flowPath/submissionProcess.vue'
import { qcckGet, qcckPost } from "@/api/qcckApi.js"; import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue"; import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import Xsxf from "./components/xsxf.vue";
const router = useRouter(); const router = useRouter();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const {D_GS_XS_CZZT,D_GS_XS_LY, D_BZ_SSZT,D_BZ_SF,D_GS_XS_LX ,D_GS_XS_QTLX,D_BZ_XB,D_BZ_XSSHZT} = proxy.$dict("D_GS_XS_CZZT","D_GS_XS_LY","D_BZ_SSZT","D_BZ_SF","D_GS_XS_LX","D_GS_XS_QTLX","D_BZ_XB","D_BZ_XSSHZT"); //获取字典数据 const { D_GS_XS_XSCZZT, D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_GS_XS_QTLX, D_BZ_XB, D_BZ_XSSHZT } = proxy.$dict("D_GS_XS_XSCZZT", "D_GS_XS_LY", "D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX", "D_BZ_XB", "D_BZ_XSSHZT"); //获取字典数据
const detailDiloag = ref(); const detailDiloag = ref();
const searchBox = ref(); //搜索框 const searchBox = ref(); //搜索框
const isShow = ref(false) const isShow = ref(false)
const searchConfiger = ref([ const searchConfiger = ref([
{ label: "线索名称", prop: 'xsMc', placeholder: "请输入线索名称", showType: "input" }, { label: "线索名称", prop: 'qbmc', placeholder: "请输入线索名称", showType: "input" },
{ label: "内容关键字", prop: 'xsNr', placeholder: "请输入语义关键字", showType: "input" }, { label: "内容关键字", prop: 'qbnr', placeholder: "请输入语义关键字", showType: "input" },
{ label: "线索类型", prop: 'xlLx', placeholder: "请选择线索类型", showType: "select",options:D_GS_XS_LX }, { label: "线索类型", prop: 'qblx', placeholder: "请选择线索类型", showType: "select", options: D_GS_XS_LX },
{ label: "线索来源", prop: 'qbLy', placeholder: "请选择线索来源", showType: "select",options:D_GS_XS_LY }, { label: "线索来源", prop: 'cjLx', placeholder: "请选择线索来源", showType: "select", options: D_GS_XS_LY },
{ label: "开始时间", prop: 'kssj', placeholder: "请选择开始时间", showType: "datetime" },
{ label: "结束时间", prop: 'jssj', placeholder: "请选择结束时间", showType: "datetime" },
{ label: "指向地点", prop: 'zxdz', placeholder: "请输入指向地点", showType: "input" },
]); ]);
const chooseRow = ref({})
const rules = reactive({
bhyy:false,
shzt: false,
})
const pageData = reactive({ const pageData = reactive({
tableData: [], tableData: [],
keyCount: 0, keyCount: 0,
@ -145,18 +101,16 @@ const pageData = reactive({
pageSize: 20, pageSize: 20,
pageCurrent: 1 pageCurrent: 1
}, },
controlsWidth: 220, controlsWidth: 250,
tableColumn: [ tableColumn: [
{ label: "线索编号", prop: "xsBh" }, { label: "线索编号", prop: "xsBh" },
{ label: "线索名称", prop: "xsMc" }, { label: "线索名称", prop: "qbmc" },
{ label: "线索类型", prop: "xlLx",showSolt:true }, { label: "线索类型", prop: "qblx", showSolt: true },
{ label: "线索来源", prop: "qbLy",showSolt:true }, { label: "线索来源", prop: "cjLx", showSolt: true },
{ label: "指向时间", prop: "zxkssj",showSolt:true,showOverflowTooltip:true }, { label: "上报时间", prop: "sxsbsj", showOverflowTooltip: true },
{ label: "上报时间", prop: "sxsbsj",showOverflowTooltip:true }, { label: "线索地点", prop: "zxdz" },
{ label: "指向地点", prop: "zxdz" }, { label: "线索内容", prop: "qbnr" },
{ label: "线索内容", prop: "xsNr"}, { label: "处置状态", prop: "czzt", showSolt: true },
{ label: "处置状态", prop: "czzt",showSolt: true},
{ label: "附件", prop: "fjdz", showSolt: true },
{ label: "审核状态", prop: "shzt", showSolt: true }, { label: "审核状态", prop: "shzt", showSolt: true },
] ]
}); });
@ -168,74 +122,67 @@ onMounted(() => {
tabHeightFn(); tabHeightFn();
}); });
const handleSh = (val) =>{
chooseRow.value = {id:val.id,shzt:'01'}
val.visible = !val.visible;
}
const cancel = (row) =>{
row.visible = false;
rules.bhyy = false;
chooseRow.value = {}
}
const handleSumbit = (row) =>{
rules.bhyy = !chooseRow.value.bhyy ? true :false;
if(chooseRow.value.shzt == '01' && rules.bhyy) return false;
let data = { ...chooseRow.value }
qcckPost(data,'/mosty-gsxt/qbcj/updateByXssh').then(res=>{
row.visible = false;
proxy.$message({ type: "success", message: "审核成功" });
getList();
})
}
// 搜索 // 搜索
const onSearch = (val) =>{ const onSearch = (val) => {
queryFrom.value = {...val} queryFrom.value = { ...val }
pageData.pageConfiger.pageCurrent = 1; pageData.pageConfiger.pageCurrent = 1;
getList() getList()
} }
const changeNo = (val) =>{ const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val; pageData.pageConfiger.pageCurrent = val;
getList() getList()
} }
const changeSize = (val) =>{ const changeSize = (val) => {
pageData.pageConfiger.pageSize = val; pageData.pageConfiger.pageSize = val;
getList() getList()
} }
// 获取列表 // 获取列表
const getList = () =>{ const getList = () => {
pageData.tableConfiger.loading = true; pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...queryFrom.value,cjLx:'0' }; let data = { ...pageData.pageConfiger, ...queryFrom.value, cjLx: '0' };
qcckGet(data,'/mosty-gsxt/qbcj/selectPage').then(res=>{ qcckGet(data, '/mosty-gsxt/qbcj/selectPage').then(res => {
pageData.tableData = res.records || []; pageData.tableData = res.records || [];
pageData.total = res.total; pageData.total = res.total;
pageData.tableConfiger.loading = false; pageData.tableConfiger.loading = false;
}).catch(()=>{ pageData.tableConfiger.loading = false; }) }).catch(() => { pageData.tableConfiger.loading = false; })
} }
// 删除 // 删除
const delDictItem = (id) =>{ const delDictItem = (id) => {
proxy.$confirm("确定要删除", "警告", {type: "warning"}).then(() => { proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
qcckPost({id},'/mosty-gsxt/qbcj/delete').then(()=>{ qcckPost({ id }, '/mosty-gsxt/qbcj/delete').then(() => {
proxy.$message({ type: "success", message: "删除成功" }); proxy.$message({ type: "success", message: "删除成功" });
getList(); getList();
}) })
}).catch(() => {}); }).catch(() => { });
}
const ids = ref()
const chooseData = (val) => {
ids.value = val.map(item => item.id)
}
const plDelDictItem = () => {
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
qcckPost({ ids: ids.value }, '/mosty-gsxt/qbcj/deletes').then(() => {
proxy.$message({ type: "success", message: "删除成功" });
getList();
})
}).catch(() => { });
} }
// 详情 // 详情
const addEdit = (type, row) => { const addEdit = (type, row) => {
isShow.value = true; isShow.value = true;
setTimeout(()=>{ setTimeout(() => {
detailDiloag.value.init(type, row); detailDiloag.value.init(type, row);
},500) }, 500)
}; };
const clickTag = (val) =>{ const clickTag = (val) => {
if(val == '02') router.push('/IntelligenceManagement'); if (val == '02') router.push('/IntelligenceManagement');
} }
// 表格高度计算 // 表格高度计算
@ -251,21 +198,32 @@ const showSp = ref(false);
const rowData = ref() const rowData = ref()
// 固定值 // 固定值
const fixedValue = { const fixedValue = {
clueVerification:'clueVerification', clueVerification: 'clueVerification',
byMeansOf: 'qbcj/callback', byMeansOf: 'qbcj/callback',
nobyMeansOf: 'qbcj/callback', nobyMeansOf: 'qbcj/callback',
recycle:'qbcj/callback', recycle: 'qbcj/callback',
} }
const createProcess = (row) => { const createProcess = (row) => {
showSp.value = true; showSp.value = true;
rowData.value = row rowData.value = row
} }
// 线索下发
const xsxfShow = ref(false)
const openXsxf = (row) => {
xsxfShow.value = true
rowData.value = {...row}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.label-pop{ .label-pop {
position: relative; position: relative;
&::before{
&::before {
position: absolute; position: absolute;
content: '*'; content: '*';
top: 0; top: 0;
@ -279,4 +237,3 @@ const createProcess = (row) => {
background: rgba(0, 0, 0, 0.5) !important; background: rgba(0, 0, 0, 0.5) !important;
} }
</style> </style>

View File

@ -3,19 +3,43 @@
<div class="head_box"> <div class="head_box">
<span class="title">指令{{ title }} </span> <span class="title">指令{{ title }} </span>
<div> <div>
<el-button type="primary" size="small" :loading="loading" @click="submit" >保存</el-button> <el-button type="primary" size="small" :loading="loading" @click="submit" v-if="title != '详情'">保存</el-button>
<el-button size="small" @click="close">关闭</el-button> <el-button size="small" @click="close">关闭</el-button>
</div> </div>
</div> </div>
<div class="form_cnt"> <div class="form_cnt flex-between">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules"> <div class="main-content" :class="{ 'content-with-timeline': title == '详情' }">
<template #glxsid> <FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules" :disabled="title == '详情'">
<div class="box pointer ellipsis" @click="chooseVisible = true"> <template #glxsid>
<span v-if="listQuery.glxs">{{ listQuery.glxs }}</span> <div class="box pointer ellipsis" @click="chooseVisible = true">
<span v-else style="color: #b8b8b8;">请选择关联线索</span> <span v-if="listQuery.glxs">{{ listQuery.glxs }}</span>
</div> <span v-else class="placeholder-text">请选择关联线索</span>
</template> </div>
</FormMessage> </template>
</FormMessage>
</div>
<div v-if="title == '详情'" class="timeline-container">
<el-timeline class="timeline-wrapper" v-if="listQuery.czlcList.length > 0">
<el-timeline-item placement="top" v-for="(activity, index) in listQuery.czlcList" :key="index"
:timestamp="activity.czsj" :color="activity.czlx == '01' ? '#409eff' : '#67c23a'" size="large">
<div class="timeline-content" :class="activity.czlx == '01' ? 'sign-type' : 'feedback-type'">
<div class="content-item">
<span class="label">处置部门</span>
<span class="value">{{ activity.ssbm }}</span>
</div>
<div class="content-item">
<span class="label">处置状态</span>
<span class="value status">{{ activity.czlx == '01' ? '签收' : '反馈' }}</span>
</div>
<div class="content-item">
<span class="label">处置内容</span>
<span class="value content">{{ activity.fknr }}</span>
</div>
</div>
</el-timeline-item>
</el-timeline>
<el-empty description="暂无处置记录" v-else />
</div>
</div> </div>
<!-- 选择线索 --> <!-- 选择线索 -->
<Xslist v-model="chooseVisible" @choosed="choosed" :roleIds="roleIds"></Xslist> <Xslist v-model="chooseVisible" @choosed="choosed" :roleIds="roleIds"></Xslist>
@ -26,7 +50,6 @@
import Xslist from '@/components/ChooseList/ChooseXs/index.vue' import Xslist from '@/components/ChooseList/ChooseXs/index.vue'
import FormMessage from '@/components/aboutTable/FormMessage.vue' import FormMessage from '@/components/aboutTable/FormMessage.vue'
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js"; import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import * as rule from "@/utils/rules.js";
import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue"; import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue";
const emit = defineEmits(["updateDate"]); const emit = defineEmits(["updateDate"]);
const props = defineProps({ const props = defineProps({
@ -38,16 +61,16 @@ const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗 const dialogForm = ref(false); //弹窗
const formData = ref([ const formData = ref([
{ label: "指令标题", prop: "zlbt", type: "input", }, { label: "指令标题", prop: "zlbt", type: "input", },
{ label: "指令类型", prop: "zllx", type: "select", options: props.dic.D_GS_XS_ZLLX }, { label: "指令类型", prop: "zllx", type: "select", options: props.dic.D_GS_XS_ZLLX },
{ label: "指令等级", prop: "zldj", type: "select", options: props.dic.D_GS_ZDQT_FXDJ }, { label: "指令等级", prop: "zldj", type: "select", options: props.dic.D_GS_ZDQT_FXDJ },
{ label: "反馈结束时间", prop: "jssj", type: "datetime" }, { label: "反馈结束时间", prop: "jssj", type: "datetime" },
{ label: "联系人", prop: "zllxr", type: "input" }, { label: "联系人", prop: "zllxr", type: "input" },
{ label: "联系电话", prop: "zllxdh", type: "input" }, { label: "联系电话", prop: "zllxdh", type: "input" },
{ label: "关联线索", prop: "glxsid", type: "slot" }, { label: "关联线索", prop: "glxsid", type: "slot" },
{ label: "主送单位", prop: "zsdw", type: "department" }, { label: "主送单位", prop: "zsdw", type: "department" },
{ label: "抄送单位", prop: "csdw", type: "department" }, { label: "抄送单位", prop: "csdw", type: "department" },
{ label: "指令内容", prop: "zlnr", type: "textarea",width: '100%' }, { label: "指令内容", prop: "zlnr", type: "textarea", width: '100%' },
{ label: "附件", prop: "fjzd", type: "upload",width: '100%' }, { label: "附件", prop: "fjzd", type: "upload", width: '100%' },
]); ]);
const listQuery = ref({}); //表单 const listQuery = ref({}); //表单
const loading = ref(false); const loading = ref(false);
@ -69,14 +92,18 @@ const rules = reactive({
const init = (type, row,) => { const init = (type, row,) => {
listQuery.value.fjzd = null listQuery.value.fjzd = null
dialogForm.value = true; dialogForm.value = true;
title.value = type == 'add' ? "新增" : "编辑"; title.value = type == 'add' ? '新增' : type == 'info' ? '详情' : '编辑';
if (row) getDataById(row.id); if (row) getDataById(row.id);
}; };
// 根据id查询详情 // 根据id查询详情
const getDataById = (id) => { const getDataById = (id) => {
qcckGet({id}, '/mosty-gsxt/zlxx/selectByid').then((res) => { qcckGet({ id }, '/mosty-gsxt/zlxx/selectByid').then((res) => {
res.fjzd = res.fjzd ? res.fjzd.split(','):[]; res.fjzd = res.fjzd ? res.fjzd.split(',') : [];
listQuery.value = res; listQuery.value = {
...res,
czlcList: res.czlcList ? res.czlcList.reverse() : []
};
}); });
}; };
@ -84,22 +111,22 @@ const getDataById = (id) => {
const choosed = (val) => { const choosed = (val) => {
listQuery.value.glxs = val[0].xsMc; listQuery.value.glxs = val[0].xsMc;
listQuery.value.glxsid = val[0].id; listQuery.value.glxsid = val[0].id;
roleIds.value = val.map(v=>v.id) roleIds.value = val.map(v => v.id)
} }
// 提交 // 提交
const submit = () => { const submit = () => {
elform.value.submit((data)=>{ elform.value.submit((data) => {
let url = title.value == "新增" ? '/mosty-gsxt/zlxx/add':'/mosty-gsxt/zlxx/update'; let url = title.value == "新增" ? '/mosty-gsxt/zlxx/add' : '/mosty-gsxt/zlxx/update';
let params = { ...data } let params = { ...data }
loading.value = true; loading.value = true;
params.fjzd = params.fjzd ? params.fjzd.join(','):'' params.fjzd = params.fjzd ? params.fjzd.join(',') : ''
qcckPost(params, url).then((res) => { qcckPost(params, url).then((res) => {
loading.value = false; loading.value = false;
proxy.$message({ type: "success", message: title.value + "成功" }); proxy.$message({ type: "success", message: title.value + "成功" });
emit("updateDate"); emit("updateDate");
close(); close();
}).catch(() => {loading.value = false;}); }).catch(() => { loading.value = false; });
}); });
}; };
@ -115,11 +142,115 @@ defineExpose({ init });
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~@/assets/css/layout.scss"; @import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss"; @import "~@/assets/css/element-plus.scss";
.box{
.box {
width: 100%; width: 100%;
height: 32px; height: 32px;
border-radius: 4px; border-radius: 4px;
border: 1px solid #e9e9e9; border: 1px solid #e9e9e9;
padding-left: 10px; padding-left: 10px;
} }
// 新增类样式
.flex-between {
display: flex;
justify-content: space-between;
}
.main-content {
margin-right: 10px;
width: 100%;
}
.content-with-timeline {
width: 80%;
}
.placeholder-text {
color: #b8b8b8;
}
.timeline-container {
width: 18%;
}
.timeline-wrapper {
max-width: 100%;
padding: 10px;
background-color: #f5f7fa;
border-radius: 8px;
}
// 时间线样式优化
.el-timeline {
.el-timeline-item {
&::before {
height: calc(100% - 20px); // 调整时间线高度
}
.el-timeline-item__content {
min-height: 80px; // 确保内容区域有足够空间
}
.el-timeline-item__timestamp {
font-size: 12px;
color: #909399;
margin-bottom: 8px;
}
}
}
.timeline-content {
padding: 12px;
background-color: white;
border-radius: 6px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
border-left: 3px solid transparent;
&.sign-type {
border-left-color: #409eff;
.status {
color: #409eff;
}
}
&.feedback-type {
border-left-color: #67c23a;
.status {
color: #67c23a;
}
}
}
.content-item {
margin-bottom: 6px;
line-height: 1.5;
&:last-child {
margin-bottom: 0;
}
}
.label {
font-weight: 500;
color: #303133;
margin-right: 5px;
}
.value {
color: #606266;
&.status {
font-weight: 500;
}
&.content {
// display: block;
// margin-top: 5px;
// word-break: break-all;
// white-space: pre-wrap;
}
}
</style> </style>

View File

@ -0,0 +1,78 @@
<template>
<el-dialog v-model="modelValue" title="线索反馈" width="50%" @close="closeDialog" destroy-on-close append-to-body>
<div style="height: 15vh; overflow: auto;">
<FormMessage v-model="listQuery" :formList="formData" ref="elform" :rules="rules" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="submitForm">确认 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import { ref, reactive, getCurrentInstance, watch } from "vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
const { proxy } = getCurrentInstance()
const { D_GS_XS_ZLLX, D_GS_ZDQT_FXDJ } = proxy.$dict('D_GS_XS_ZLLX', 'D_GS_ZDQT_FXDJ')
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dataList: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['update:modelValue', 'getList'])
const elform = ref(null)
const closeDialog = (formEl) => {
elform.value.reset()
emit('update:modelValue', false)
}
const rules = reactive({
fknr: [{ required: true, message: '请输入反馈内容', trigger: 'blur' }],
})
const listQuery = ref({})
const formData = ref(
[
{ label: "反馈内容", prop: "fknr", type: "textarea" ,width:'90%'},
]
)
watch(() => props.modelValue, (newVal, oldVal) => {
if (newVal) {
listQuery.value.zlxxid = props.dataList.id
}
}, { deep: true })
const submitForm = (formEl) => {
console.log(listQuery.value);
elform.value.submit((valid) => {
if (valid) {
const params = {
...listQuery.value,
}
qcckPost(params, '/mosty-gsxt/zlxx/fk').then((res) => {
proxy.$message({ type: "success", message: "反馈成功" });
emit('getList')
closeDialog()
}).catch(() => {
proxy.$message({ type: "error", message: "反馈失败" });
});
console.log(params);
} else {
console.log('校验失败');
}
})
}
</script>
<style scoped></style>

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