Compare commits
21 Commits
0d206f61de
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| bc590497bd | |||
| 8d43a61451 | |||
| df9df3144b | |||
| e8ab8252f8 | |||
|
|
8550367f45 | ||
|
|
d0f0e926f2 | ||
|
|
2ef64a6254 | ||
|
|
268b138790 | ||
|
|
e1a28e2c2b | ||
|
|
8e236965a7 | ||
|
|
81aa338873 | ||
|
|
c157542ec1 | ||
| 345b0d1025 | |||
| b80202cff4 | |||
| bd4158ae5d | |||
| 8d316e22ab | |||
| e2354d6960 | |||
| 734437b001 | |||
| b59fcedcde | |||
| 528efc81f9 | |||
| d3334b11cf |
@@ -4,10 +4,9 @@ NODE_ENV=development
|
|||||||
VITE_DEV=true
|
VITE_DEV=true
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
# VITE_BASE_URL='http://172.16.214.222:48080'
|
# VITE_BASE_URL='http://192.168.2.21:48080'
|
||||||
VITE_BASE_URL='http://192.168.1.144:48080'
|
VITE_BASE_URL='https://backstageapi.yolozs.com'
|
||||||
# VITE_BASE_URL='http://47.79.98.113:48080'
|
# VITE_BASE_URL='https://testapi.tknb.net'
|
||||||
# VITE_BASE_URL='https://backstageapi.yolozs.com'
|
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||||
VITE_UPLOAD_TYPE=server
|
VITE_UPLOAD_TYPE=server
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ VITE_DEV=false
|
|||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='https://backstageapi.yolozs.com'
|
VITE_BASE_URL='https://backstageapi.yolozs.com'
|
||||||
|
# VITE_BASE_URL='https://testapi.tknb.net'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
VITE_UPLOAD_TYPE=server
|
VITE_UPLOAD_TYPE=server
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ NODE_ENV=production
|
|||||||
VITE_DEV=false
|
VITE_DEV=false
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://localhost:48080'
|
VITE_BASE_URL='http://testapi.tknb.net'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
VITE_UPLOAD_TYPE=server
|
VITE_UPLOAD_TYPE=server
|
||||||
|
|||||||
110
package-lock.json
generated
110
package-lock.json
generated
@@ -198,6 +198,7 @@
|
|||||||
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
|
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
@@ -1796,7 +1797,6 @@
|
|||||||
"integrity": "sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==",
|
"integrity": "sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.3.1",
|
"@codemirror/language": "^6.3.1",
|
||||||
"@codemirror/view": "^6.5.1",
|
"@codemirror/view": "^6.5.1",
|
||||||
@@ -1834,7 +1834,6 @@
|
|||||||
"integrity": "sha512-Unc4CSyMgDg5c2C3E3ehEbJZfyo5W9Zrq74C8cp7mjFbb3if6rTBaw3ZCZeiC06zsm881sI5P8zWHFdIhKo/vA==",
|
"integrity": "sha512-Unc4CSyMgDg5c2C3E3ehEbJZfyo5W9Zrq74C8cp7mjFbb3if6rTBaw3ZCZeiC06zsm881sI5P8zWHFdIhKo/vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bpmn-io/feel-lint": "^1.4.0",
|
"@bpmn-io/feel-lint": "^1.4.0",
|
||||||
"@codemirror/autocomplete": "^6.16.2",
|
"@codemirror/autocomplete": "^6.16.2",
|
||||||
@@ -1857,7 +1856,6 @@
|
|||||||
"integrity": "sha512-1bsdR/9vPD7RQVqWWPk0X0tpjLsYTDrCxIzOVtN/h32o4nPGl0dZBU5m07qaFUGD4wG3eOH4Qim1wexHG8YkBw==",
|
"integrity": "sha512-1bsdR/9vPD7RQVqWWPk0X0tpjLsYTDrCxIzOVtN/h32o4nPGl0dZBU5m07qaFUGD4wG3eOH4Qim1wexHG8YkBw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.10.8",
|
"@codemirror/language": "^6.10.8",
|
||||||
"lezer-feel": "^1.7.0"
|
"lezer-feel": "^1.7.0"
|
||||||
@@ -1892,7 +1890,6 @@
|
|||||||
"integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
|
"integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
@@ -1906,7 +1903,6 @@
|
|||||||
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
|
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.4.0",
|
"@codemirror/state": "^6.4.0",
|
||||||
@@ -1920,7 +1916,6 @@
|
|||||||
"integrity": "sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==",
|
"integrity": "sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.23.0",
|
"@codemirror/view": "^6.23.0",
|
||||||
@@ -1936,7 +1931,6 @@
|
|||||||
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.35.0",
|
"@codemirror/view": "^6.35.0",
|
||||||
@@ -1949,7 +1943,6 @@
|
|||||||
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@marijn/find-cluster-break": "^1.0.0"
|
"@marijn/find-cluster-break": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -1960,7 +1953,6 @@
|
|||||||
"integrity": "sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==",
|
"integrity": "sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.5.0",
|
"@codemirror/state": "^6.5.0",
|
||||||
"style-mod": "^4.1.0",
|
"style-mod": "^4.1.0",
|
||||||
@@ -2240,6 +2232,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
@@ -2263,6 +2256,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
@@ -3408,8 +3402,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@lezer/common/-/common-1.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/@lezer/common/-/common-1.2.3.tgz",
|
||||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/highlight": {
|
"node_modules/@lezer/highlight": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
@@ -3417,7 +3410,6 @@
|
|||||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -3428,7 +3420,6 @@
|
|||||||
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -3439,7 +3430,6 @@
|
|||||||
"integrity": "sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==",
|
"integrity": "sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0",
|
"@lezer/common": "^1.0.0",
|
||||||
"@lezer/highlight": "^1.0.0"
|
"@lezer/highlight": "^1.0.0"
|
||||||
@@ -3450,8 +3440,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@microsoft/fetch-event-source": {
|
"node_modules/@microsoft/fetch-event-source": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@@ -4763,6 +4752,7 @@
|
|||||||
"integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==",
|
"integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "*",
|
"@types/estree": "*",
|
||||||
"@types/json-schema": "*"
|
"@types/json-schema": "*"
|
||||||
@@ -4805,6 +4795,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
||||||
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/lodash": "*"
|
"@types/lodash": "*"
|
||||||
}
|
}
|
||||||
@@ -4815,6 +4806,7 @@
|
|||||||
"integrity": "sha512-3dLX0Upo1v7RvUimvxLeXqwrfyKxUINk0EAM83swP2mlSUcwV73sZy8XhNz8bcZ3VbsfQyC/y6jRdL5tgCNpDQ==",
|
"integrity": "sha512-3dLX0Upo1v7RvUimvxLeXqwrfyKxUINk0EAM83swP2mlSUcwV73sZy8XhNz8bcZ3VbsfQyC/y6jRdL5tgCNpDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.19.2"
|
"undici-types": "~6.19.2"
|
||||||
}
|
}
|
||||||
@@ -4910,6 +4902,7 @@
|
|||||||
"integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==",
|
"integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "7.18.0",
|
"@typescript-eslint/scope-manager": "7.18.0",
|
||||||
"@typescript-eslint/types": "7.18.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
@@ -6467,6 +6460,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz",
|
"resolved": "https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz",
|
||||||
"integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
|
"integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@transloadit/prettier-bytes": "0.0.7",
|
"@transloadit/prettier-bytes": "0.0.7",
|
||||||
"@uppy/store-default": "^2.1.1",
|
"@uppy/store-default": "^2.1.1",
|
||||||
@@ -6498,6 +6492,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
|
"resolved": "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
|
||||||
"integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
|
"integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uppy/companion-client": "^2.2.2",
|
"@uppy/companion-client": "^2.2.2",
|
||||||
"@uppy/utils": "^4.1.2",
|
"@uppy/utils": "^4.1.2",
|
||||||
@@ -6998,6 +6993,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
|
"resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
|
||||||
"integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
|
"integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-url": "^1.2.4"
|
"is-url": "^1.2.4"
|
||||||
},
|
},
|
||||||
@@ -7030,6 +7026,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz",
|
"resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz",
|
||||||
"integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
|
"integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/event-emitter": "^0.3.3",
|
"@types/event-emitter": "^0.3.3",
|
||||||
"event-emitter": "^0.3.5",
|
"event-emitter": "^0.3.5",
|
||||||
@@ -7060,6 +7057,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz",
|
"resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz",
|
||||||
"integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
|
"integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uppy/core": "^2.1.1",
|
"@uppy/core": "^2.1.1",
|
||||||
"@uppy/xhr-upload": "^2.0.3",
|
"@uppy/xhr-upload": "^2.0.3",
|
||||||
@@ -7191,6 +7189,7 @@
|
|||||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -7707,6 +7706,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001716",
|
"caniuse-lite": "^1.0.30001716",
|
||||||
"electron-to-chromium": "^1.5.149",
|
"electron-to-chromium": "^1.5.149",
|
||||||
@@ -7871,7 +7871,8 @@
|
|||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/camunda-bpmn-moddle/-/camunda-bpmn-moddle-7.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/camunda-bpmn-moddle/-/camunda-bpmn-moddle-7.0.1.tgz",
|
||||||
"integrity": "sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==",
|
"integrity": "sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001718",
|
"version": "1.0.30001718",
|
||||||
@@ -7966,8 +7967,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz",
|
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz",
|
||||||
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
|
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cli-cursor": {
|
"node_modules/cli-cursor": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
@@ -8404,6 +8404,7 @@
|
|||||||
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
|
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"import-fresh": "^3.3.0",
|
"import-fresh": "^3.3.0",
|
||||||
@@ -8448,8 +8449,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/crelt/-/crelt-1.0.6.tgz",
|
"resolved": "https://registry.npmmirror.com/crelt/-/crelt-1.0.6.tgz",
|
||||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cropperjs": {
|
"node_modules/cropperjs": {
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
@@ -8948,6 +8948,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -9154,6 +9155,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/diagram-js/-/diagram-js-12.8.1.tgz",
|
"resolved": "https://registry.npmmirror.com/diagram-js/-/diagram-js-12.8.1.tgz",
|
||||||
"integrity": "sha512-LF9BiwjbOPpZd0ez5VSlYRbdbEA59YQX43bWvNDp1rLMv0xwZ5yIg4oaYDK82nIQ0kH1tjvoQRpNevMTCgQVyw==",
|
"integrity": "sha512-LF9BiwjbOPpZd0ez5VSlYRbdbEA59YQX43bWvNDp1rLMv0xwZ5yIg4oaYDK82nIQ0kH1tjvoQRpNevMTCgQVyw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bpmn-io/diagram-js-ui": "^0.2.2",
|
"@bpmn-io/diagram-js-ui": "^0.2.2",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
@@ -9256,6 +9258,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz",
|
||||||
"integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
|
"integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ssr-window": "^3.0.0-alpha.1"
|
"ssr-window": "^3.0.0-alpha.1"
|
||||||
}
|
}
|
||||||
@@ -9370,6 +9373,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
|
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
|
||||||
"integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
|
"integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "2.3.0",
|
"tslib": "2.3.0",
|
||||||
"zrender": "5.6.1"
|
"zrender": "5.6.1"
|
||||||
@@ -9800,6 +9804,7 @@
|
|||||||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.6.1",
|
"@eslint-community/regexpp": "^4.6.1",
|
||||||
@@ -9856,6 +9861,7 @@
|
|||||||
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
|
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"eslint-config-prettier": "bin/cli.js"
|
"eslint-config-prettier": "bin/cli.js"
|
||||||
},
|
},
|
||||||
@@ -10480,7 +10486,6 @@
|
|||||||
"integrity": "sha512-CGa/7ILuqoqTaeYeoKsg/4tzu2es9sEEJTmSjdu0lousZBw4V9gcYhHYFNmbrSrKmbAVfOzj6/DsymGJWFIOeg==",
|
"integrity": "sha512-CGa/7ILuqoqTaeYeoKsg/4tzu2es9sEEJTmSjdu0lousZBw4V9gcYhHYFNmbrSrKmbAVfOzj6/DsymGJWFIOeg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bpmn-io/cm-theme": "^0.1.0-alpha.2",
|
"@bpmn-io/cm-theme": "^0.1.0-alpha.2",
|
||||||
"@bpmn-io/feel-lint": "^1.2.0",
|
"@bpmn-io/feel-lint": "^1.2.0",
|
||||||
@@ -10513,7 +10518,6 @@
|
|||||||
"integrity": "sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==",
|
"integrity": "sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
@@ -10527,7 +10531,6 @@
|
|||||||
"integrity": "sha512-GaKUlguMAofd3OJsB0OkP17i5kucKqErgVCJxPawO9l5NwIPnr28SAr99zzlzMCWWljISBYrnZVWdE2Q92YGFQ==",
|
"integrity": "sha512-GaKUlguMAofd3OJsB0OkP17i5kucKqErgVCJxPawO9l5NwIPnr28SAr99zzlzMCWWljISBYrnZVWdE2Q92YGFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domify": "^2.0.0",
|
"domify": "^2.0.0",
|
||||||
"min-dash": "^4.2.1"
|
"min-dash": "^4.2.1"
|
||||||
@@ -10539,7 +10542,6 @@
|
|||||||
"integrity": "sha512-GFDbHsTYk7YXO1tyw1dOjb7IODeAZvNIosdGZThUwPx5XcD/XhO0hnPZXsIbAzSsIdrgGlTEEdby9fZ2gixysA==",
|
"integrity": "sha512-GFDbHsTYk7YXO1tyw1dOjb7IODeAZvNIosdGZThUwPx5XcD/XhO0hnPZXsIbAzSsIdrgGlTEEdby9fZ2gixysA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/lr": "^1.4.2",
|
"@lezer/lr": "^1.4.2",
|
||||||
"lezer-feel": "^1.4.0",
|
"lezer-feel": "^1.4.0",
|
||||||
@@ -10707,7 +10709,6 @@
|
|||||||
"integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==",
|
"integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tabbable": "^6.2.0"
|
"tabbable": "^6.2.0"
|
||||||
}
|
}
|
||||||
@@ -11561,7 +11562,8 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz",
|
||||||
"integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==",
|
"integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/is-number": {
|
"node_modules/is-number": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
@@ -12049,7 +12051,6 @@
|
|||||||
"integrity": "sha512-cotBfyBP710udy3Tm7s4NyNZPSSLXkVV/rrfmM4NVbuzB9WGL7CbMWUzfSn6GZ+qFnh8/xbkeDHfAvPM90oENA==",
|
"integrity": "sha512-cotBfyBP710udy3Tm7s4NyNZPSSLXkVV/rrfmM4NVbuzB9WGL7CbMWUzfSn6GZ+qFnh8/xbkeDHfAvPM90oENA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.18.4",
|
"@codemirror/autocomplete": "^6.18.4",
|
||||||
"@codemirror/language": "^6.10.8",
|
"@codemirror/language": "^6.10.8",
|
||||||
@@ -12080,7 +12081,6 @@
|
|||||||
"integrity": "sha512-UC8h3Nu4llRPISEUhv+Ne7bNkdxjf4+/DcU4KfO8zKxycWxev8d2BoVnGlG17zbQDtQJBD39ZQvWtjCeTFm69g==",
|
"integrity": "sha512-UC8h3Nu4llRPISEUhv+Ne7bNkdxjf4+/DcU4KfO8zKxycWxev8d2BoVnGlG17zbQDtQJBD39ZQvWtjCeTFm69g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@lezer/lr": "^1.4.2",
|
"@lezer/lr": "^1.4.2",
|
||||||
@@ -12324,13 +12324,15 @@
|
|||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash-es": {
|
"node_modules/lodash-es": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash-unified": {
|
"node_modules/lodash-unified": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
@@ -12347,32 +12349,37 @@
|
|||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.clonedeep": {
|
"node_modules/lodash.clonedeep": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.debounce": {
|
"node_modules/lodash.debounce": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.foreach": {
|
"node_modules/lodash.foreach": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
||||||
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==",
|
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.isequal": {
|
"node_modules/lodash.isequal": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||||
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.isplainobject": {
|
"node_modules/lodash.isplainobject": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
@@ -12420,13 +12427,15 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
|
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.toarray": {
|
"node_modules/lodash.toarray": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
|
||||||
"integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==",
|
"integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.truncate": {
|
"node_modules/lodash.truncate": {
|
||||||
"version": "4.4.2",
|
"version": "4.4.2",
|
||||||
@@ -12698,7 +12707,6 @@
|
|||||||
"integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==",
|
"integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -12745,6 +12753,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/markmap-common/-/markmap-common-0.16.0.tgz",
|
"resolved": "https://registry.npmmirror.com/markmap-common/-/markmap-common-0.16.0.tgz",
|
||||||
"integrity": "sha512-q3nlNDMKuWXTm3VwZFY9V5zteL/+iBLZanUK5vS+e26bUbzTSG5VtAzsyJbmgJm1WhwmIIAxbXEnp6JdvtTduA==",
|
"integrity": "sha512-q3nlNDMKuWXTm3VwZFY9V5zteL/+iBLZanUK5vS+e26bUbzTSG5VtAzsyJbmgJm1WhwmIIAxbXEnp6JdvtTduA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.6",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@gera2ld/jsx-dom": "^2.2.2",
|
"@gera2ld/jsx-dom": "^2.2.2",
|
||||||
@@ -13151,6 +13160,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"nanoid": "bin/nanoid.cjs"
|
"nanoid": "bin/nanoid.cjs"
|
||||||
},
|
},
|
||||||
@@ -13780,6 +13790,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.8",
|
"nanoid": "^3.3.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@@ -13920,6 +13931,7 @@
|
|||||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin/prettier.cjs"
|
"prettier": "bin/prettier.cjs"
|
||||||
},
|
},
|
||||||
@@ -14719,6 +14731,7 @@
|
|||||||
"integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==",
|
"integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.7"
|
"@types/estree": "1.0.7"
|
||||||
},
|
},
|
||||||
@@ -14836,6 +14849,7 @@
|
|||||||
"integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==",
|
"integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
"immutable": "^5.0.2",
|
"immutable": "^5.0.2",
|
||||||
@@ -15044,6 +15058,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz",
|
"resolved": "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz",
|
||||||
"integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
|
"integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"immer": "^9.0.6",
|
"immer": "^9.0.6",
|
||||||
"is-plain-object": "^5.0.0",
|
"is-plain-object": "^5.0.0",
|
||||||
@@ -15097,6 +15112,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.6.2.tgz",
|
"resolved": "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.6.2.tgz",
|
||||||
"integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==",
|
"integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.17.0"
|
"node": ">=12.17.0"
|
||||||
}
|
}
|
||||||
@@ -15340,8 +15356,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/style-mod/-/style-mod-4.1.2.tgz",
|
"resolved": "https://registry.npmmirror.com/style-mod/-/style-mod-4.1.2.tgz",
|
||||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/stylelint": {
|
"node_modules/stylelint": {
|
||||||
"version": "16.19.1",
|
"version": "16.19.1",
|
||||||
@@ -15359,6 +15374,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-parser-algorithms": "^3.0.4",
|
"@csstools/css-parser-algorithms": "^3.0.4",
|
||||||
"@csstools/css-tokenizer": "^3.0.3",
|
"@csstools/css-tokenizer": "^3.0.3",
|
||||||
@@ -15598,6 +15614,7 @@
|
|||||||
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
|
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
"util-deprecate": "^1.0.2"
|
"util-deprecate": "^1.0.2"
|
||||||
@@ -15763,8 +15780,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.2.0.tgz",
|
||||||
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
|
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/table": {
|
"node_modules/table": {
|
||||||
"version": "6.9.0",
|
"version": "6.9.0",
|
||||||
@@ -15855,6 +15871,7 @@
|
|||||||
"integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==",
|
"integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
"acorn": "^8.14.0",
|
"acorn": "^8.14.0",
|
||||||
@@ -16013,6 +16030,7 @@
|
|||||||
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -16566,6 +16584,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/video.js/-/video.js-7.21.7.tgz",
|
"resolved": "https://registry.npmmirror.com/video.js/-/video.js-7.21.7.tgz",
|
||||||
"integrity": "sha512-T2s3WFAht7Zjr2OSJamND9x9Dn2O+Z5WuHGdh8jI5SYh5mkMdVTQ7vSRmA5PYpjXJ2ycch6jpMjkJEIEU2xxqw==",
|
"integrity": "sha512-T2s3WFAht7Zjr2OSJamND9x9Dn2O+Z5WuHGdh8jI5SYh5mkMdVTQ7vSRmA5PYpjXJ2ycch6jpMjkJEIEU2xxqw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@videojs/http-streaming": "2.16.3",
|
"@videojs/http-streaming": "2.16.3",
|
||||||
@@ -16603,6 +16622,7 @@
|
|||||||
"integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==",
|
"integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.19.3",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.35",
|
||||||
@@ -16882,6 +16902,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.12.tgz",
|
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.12.tgz",
|
||||||
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
|
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.12",
|
"@vue/compiler-dom": "3.5.12",
|
||||||
"@vue/compiler-sfc": "3.5.12",
|
"@vue/compiler-sfc": "3.5.12",
|
||||||
@@ -17162,8 +17183,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
"resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/wangeditor": {
|
"node_modules/wangeditor": {
|
||||||
"version": "4.7.15",
|
"version": "4.7.15",
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ export const BigBrotherApi = {
|
|||||||
deleteBigBrother: async (id: number) => {
|
deleteBigBrother: async (id: number) => {
|
||||||
return await request.delete({ url: `/server/big-brother/delete?id=` + id })
|
return await request.delete({ url: `/server/big-brother/delete?id=` + id })
|
||||||
},
|
},
|
||||||
|
// 批量删除大哥数据
|
||||||
|
deleteBigBrotherList: async (ids: number[]) => {
|
||||||
|
return await request.delete({ url: `/server/big-brother/delete-list` , params: { ids: ids.join(',') } })
|
||||||
|
},
|
||||||
|
|
||||||
// 导出大哥数据 Excel
|
// 导出大哥数据 Excel
|
||||||
exportBigBrother: async (params) => {
|
exportBigBrother: async (params) => {
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ export const EmployeeBigBrotherApi = {
|
|||||||
deleteEmployeeBigBrother: async (id: number) => {
|
deleteEmployeeBigBrother: async (id: number) => {
|
||||||
return await request.delete({ url: `/server/employee-big-brother/delete?id=` + id })
|
return await request.delete({ url: `/server/employee-big-brother/delete?id=` + id })
|
||||||
},
|
},
|
||||||
|
// 批量删除大哥数据员工业务
|
||||||
|
deleteEmployeeBigBrotherList: async (ids: number[]) => {
|
||||||
|
return await request.delete({ url: `/server/employee-big-brother/delete-list` , params: { ids: ids.join(',') } })
|
||||||
|
},
|
||||||
|
|
||||||
// 导出大哥数据员工业务 Excel
|
// 导出大哥数据员工业务 Excel
|
||||||
exportEmployeeBigBrother: async (params) => {
|
exportEmployeeBigBrother: async (params) => {
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ export interface EmployeeHostsVO {
|
|||||||
uid: string // 用户id
|
uid: string // 用户id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 员工分配主播 API
|
// 员工分配主播 API
|
||||||
export const EmployeeHostsApi = {
|
export const EmployeeHostsApi = {
|
||||||
// 查询员工分配主播分页
|
// 查询员工分配主播分页
|
||||||
@@ -34,10 +32,25 @@ export const EmployeeHostsApi = {
|
|||||||
getEmployeeHostsPage: async (params: any) => {
|
getEmployeeHostsPage: async (params: any) => {
|
||||||
return await request.get({ url: `/server/employee-hosts/self_page`, params })
|
return await request.get({ url: `/server/employee-hosts/self_page`, params })
|
||||||
},
|
},
|
||||||
// 查询员工分配主播分页
|
// 查询员工分配大哥分页
|
||||||
employeeCompleteBarChart: async (params: number[]) => {
|
getEmployeeHostsPageDsec: async (params: any) => {
|
||||||
return await request.post({ url: `/server/employee-hosts/employeeCompleteBarChart`, data: params })
|
return await request.get({ url: `/server/employee-big-brother/self_complete` })
|
||||||
},
|
},
|
||||||
|
// 查询爬主播建联
|
||||||
|
employeeCompleteBarChart: async (params: number[], days: number) => {
|
||||||
|
return await request.post({
|
||||||
|
url: `/server/employee-hosts/employeeCompleteBarChart`,
|
||||||
|
data: { userId: params, days: days }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 查询爬大哥建联
|
||||||
|
employeeCompleteBarChartDsec: async (params: number[], days: number) => {
|
||||||
|
return await request.post({
|
||||||
|
url: `/server/employee-big-brother/employeeCompleteBarChart`,
|
||||||
|
data: { userId: params, days: days }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
// 查询管理员工分配主播分页
|
// 查询管理员工分配主播分页
|
||||||
getMeangeEmployeeHostsPage: async (params: any) => {
|
getMeangeEmployeeHostsPage: async (params: any) => {
|
||||||
return await request.get({ url: `server/employee-hosts/page`, params })
|
return await request.get({ url: `server/employee-hosts/page`, params })
|
||||||
@@ -67,7 +80,10 @@ export const EmployeeHostsApi = {
|
|||||||
},
|
},
|
||||||
// 删除员工分配主播
|
// 删除员工分配主播
|
||||||
deleteEmployeeHostsList: async (ids: number[]) => {
|
deleteEmployeeHostsList: async (ids: number[]) => {
|
||||||
return await request.delete({ url: `/server/employee-hosts/delete-list`, params: { ids: ids.join(',') } })
|
return await request.delete({
|
||||||
|
url: `/server/employee-hosts/delete-list`,
|
||||||
|
params: { ids: ids.join(',') }
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 导出员工分配主播 Excel
|
// 导出员工分配主播 Excel
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ export interface TenantExportReqVO {
|
|||||||
export const getTenantPage = (params: TenantPageReqVO) => {
|
export const getTenantPage = (params: TenantPageReqVO) => {
|
||||||
return request.get({ url: '/system/tenant/page', params })
|
return request.get({ url: '/system/tenant/page', params })
|
||||||
}
|
}
|
||||||
|
// 查询租户列表(代理)
|
||||||
|
export const getTenantPageSelf = (params: TenantPageReqVO) => {
|
||||||
|
return request.get({ url: '/system/tenant/page_self', params })
|
||||||
|
}
|
||||||
|
// 查询下级租户列表(代理)
|
||||||
|
export const getTenantChildren = (params: TenantPageReqVO) => {
|
||||||
|
return request.get({ url: '/system/tenant/get-children', params })
|
||||||
|
}
|
||||||
|
|
||||||
// 查询租户详情
|
// 查询租户详情
|
||||||
export const getTenant = (id: number) => {
|
export const getTenant = (id: number) => {
|
||||||
@@ -70,3 +78,12 @@ export const deleteTenantList = (ids: number[]) => {
|
|||||||
export const exportTenant = (params: TenantExportReqVO) => {
|
export const exportTenant = (params: TenantExportReqVO) => {
|
||||||
return request.download({ url: '/system/tenant/export-excel', params })
|
return request.download({ url: '/system/tenant/export-excel', params })
|
||||||
}
|
}
|
||||||
|
// 获取租户等级
|
||||||
|
export const getSelfTenantLevel = () => {
|
||||||
|
return request.get({ url: '/system/tenant/getSelfTenantLevel' })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 续费
|
||||||
|
export const renewal = (data) => {
|
||||||
|
return request.put({ url: '/system/tenant/renewal',data})
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ export interface TenantPackageVO {
|
|||||||
updateTime: string
|
updateTime: string
|
||||||
menuIds: number[]
|
menuIds: number[]
|
||||||
createTime: Date
|
createTime: Date
|
||||||
|
packageType: number
|
||||||
|
days: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询租户套餐列表
|
// 查询租户套餐列表
|
||||||
@@ -46,3 +48,7 @@ export const deleteTenantPackageList = (ids: number[]) => {
|
|||||||
export const getTenantPackageList = () => {
|
export const getTenantPackageList = () => {
|
||||||
return request.get({ url: '/system/tenant-package/simple-list' })
|
return request.get({ url: '/system/tenant-package/simple-list' })
|
||||||
}
|
}
|
||||||
|
// 获取非总后台租户套餐精简信息列表
|
||||||
|
export const getTenantPackageListagency = () => {
|
||||||
|
return request.get({ url: '/system/tenant-agency-package/get-simple-list' })
|
||||||
|
}
|
||||||
|
|||||||
49
src/api/system/tenantagencypackage/index.ts
Normal file
49
src/api/system/tenantagencypackage/index.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// 代理租户套餐 VO
|
||||||
|
export interface TenantAgencyPackageVO {
|
||||||
|
id: number // 套餐编号
|
||||||
|
name: string // 套餐名
|
||||||
|
status: number // 租户状态(0正常 1停用)
|
||||||
|
remark: string // 备注
|
||||||
|
menuIds: string // 关联的菜单编号
|
||||||
|
days: number // 套餐天数
|
||||||
|
price: number // 套餐价格
|
||||||
|
hostslClient: number // 爬主播客户端 0 关闭 1 开启
|
||||||
|
brotherClient: number // 爬大哥客户端 0 关闭 1 开启
|
||||||
|
aiClient: number // AI 客户端 0 关闭 1 开启
|
||||||
|
packageType: number // 套餐类型
|
||||||
|
}
|
||||||
|
|
||||||
|
// 代理租户套餐 API
|
||||||
|
export const TenantAgencyPackageApi = {
|
||||||
|
// 查询代理租户套餐分页
|
||||||
|
getTenantAgencyPackagePage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/system/tenant-agency-package/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询代理租户套餐详情
|
||||||
|
getTenantAgencyPackage: async (id: number) => {
|
||||||
|
return await request.get({ url: `/system/tenant-agency-package/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增代理租户套餐
|
||||||
|
createTenantAgencyPackage: async (data: TenantAgencyPackageVO) => {
|
||||||
|
return await request.post({ url: `/system/tenant-agency-package/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改代理租户套餐
|
||||||
|
updateTenantAgencyPackage: async (data: TenantAgencyPackageVO) => {
|
||||||
|
return await request.put({ url: `/system/tenant-agency-package/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除代理租户套餐
|
||||||
|
deleteTenantAgencyPackage: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/system/tenant-agency-package/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出代理租户套餐 Excel
|
||||||
|
exportTenantAgencyPackage: async (params) => {
|
||||||
|
return await request.download({ url: `/system/tenant-agency-package/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/api/system/tenantbalance/index.ts
Normal file
83
src/api/system/tenantbalance/index.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// 租户余额 VO
|
||||||
|
export interface TenantBalanceVO {
|
||||||
|
id: number // 租户 Id
|
||||||
|
balance: number // 当前积分余额
|
||||||
|
version: number // 乐观锁版本号
|
||||||
|
updatedAt: Date // 更新时间
|
||||||
|
}
|
||||||
|
|
||||||
|
// 租户余额 API
|
||||||
|
export const TenantBalanceApi = {
|
||||||
|
// 查询租户余额分页
|
||||||
|
getTenantBalancePage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/system/tenant-balance/page`, params })
|
||||||
|
},
|
||||||
|
// 查询下级租户余额分页
|
||||||
|
getSubordinateaMountPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/system/tenant-balance/get-self-subordinate-amount-page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
//查看当前余额
|
||||||
|
getselfamount: async () => {
|
||||||
|
return await request.get({ url: `/system/tenant-balance/get-self-amount` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询租户余额详情
|
||||||
|
getTenantBalance: async (id: number) => {
|
||||||
|
return await request.get({ url: `/system/tenant-balance/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增租户余额
|
||||||
|
createTenantBalance: async (data: TenantBalanceVO) => {
|
||||||
|
return await request.post({ url: `/system/tenant-balance/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改租户余额
|
||||||
|
updateTenantBalance: async (data: TenantBalanceVO) => {
|
||||||
|
return await request.put({ url: `/system/tenant-balance/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除租户余额
|
||||||
|
deleteTenantBalance: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/system/tenant-balance/delete?id=` + id })
|
||||||
|
},
|
||||||
|
// 转账租户余额
|
||||||
|
tenantTransfer: async (data: TenantBalanceVO) => {
|
||||||
|
return await request.post({ url: `/system/tenant-balance/transfer`, data })
|
||||||
|
},
|
||||||
|
addAmount: async (data: TenantBalanceVO) => {
|
||||||
|
return await request.post({ url: `/system/tenant-balance/addAmount`, data })
|
||||||
|
},
|
||||||
|
// 导出租户余额 Excel
|
||||||
|
exportTenantBalance: async (params) => {
|
||||||
|
return await request.download({ url: `/system/tenant-balance/export-excel`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 子表(租户余额) ====================
|
||||||
|
|
||||||
|
// 获得租户余额分页
|
||||||
|
getTenantPointsPage: async (params) => {
|
||||||
|
return await request.get({ url: `/system/tenant-points/transaction-history/page`, params })
|
||||||
|
},
|
||||||
|
// 新增租户余额
|
||||||
|
createTenantPoints: async (data) => {
|
||||||
|
return await request.post({ url: `/system/tenant-balance/tenant-points/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改租户余额
|
||||||
|
updateTenantPoints: async (data) => {
|
||||||
|
return await request.put({ url: `/system/tenant-balance/tenant-points/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除租户余额
|
||||||
|
deleteTenantPoints: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/system/tenant-balance/tenant-points/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得租户余额
|
||||||
|
getTenantPoints: async (id: number) => {
|
||||||
|
return await request.get({ url: `/system/tenant-balance/tenant-points/get?id=` + id })
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/api/system/tenantpoints/index.ts
Normal file
48
src/api/system/tenantpoints/index.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// 租户积分记录 VO
|
||||||
|
export interface TenantPointsVO {
|
||||||
|
id: number // 主键
|
||||||
|
points: number // 本次变动点数,正加负减
|
||||||
|
balance: number // 变动后余额快照(冗余)
|
||||||
|
type: string // 变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN
|
||||||
|
remark: string // 备注
|
||||||
|
orderId: number // 订单 Id/业务单号
|
||||||
|
bizNo: string // 业务流水号(转账、订单等唯一标识)
|
||||||
|
operatorId: number // 操作人 Id
|
||||||
|
targetTenantId: number // 目标租户 Id(转账使用)
|
||||||
|
createdAt: Date // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
// 租户积分记录 API
|
||||||
|
export const TenantPointsApi = {
|
||||||
|
// 查询租户积分记录分页
|
||||||
|
getTenantPointsPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/system/tenant-points/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询租户积分记录详情
|
||||||
|
getTenantPoints: async (id: number) => {
|
||||||
|
return await request.get({ url: `/system/tenant-points/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增租户积分记录
|
||||||
|
createTenantPoints: async (data: TenantPointsVO) => {
|
||||||
|
return await request.post({ url: `/system/tenant-points/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改租户积分记录
|
||||||
|
updateTenantPoints: async (data: TenantPointsVO) => {
|
||||||
|
return await request.put({ url: `/system/tenant-points/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除租户积分记录
|
||||||
|
deleteTenantPoints: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/system/tenant-points/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出租户积分记录 Excel
|
||||||
|
exportTenantPoints: async (params) => {
|
||||||
|
return await request.download({ url: `/system/tenant-points/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ export interface UserVO {
|
|||||||
bigBrother: number
|
bigBrother: number
|
||||||
tenantId: number
|
tenantId: number
|
||||||
aiChat: number
|
aiChat: number
|
||||||
|
aiReplay: number
|
||||||
|
webAi: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询用户管理列表
|
// 查询用户管理列表
|
||||||
@@ -100,7 +102,6 @@ export const getSimpleUserListPage = (params: PageParam): Promise<UserVO[]> => {
|
|||||||
return request.get({ url: '/system/user/page', params })
|
return request.get({ url: '/system/user/page', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 获取国家
|
// 获取国家
|
||||||
export const getCountry = (country) => {
|
export const getCountry = (country) => {
|
||||||
return request.get({ url: '/server/country-info/get?region=' + country })
|
return request.get({ url: '/server/country-info/get?region=' + country })
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default {
|
|||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
copySuccess: 'Copy Success',
|
copySuccess: 'Copy Success',
|
||||||
copyError: 'Copy Error',
|
copyError: 'Copy Error',
|
||||||
perPage: 'Number page',
|
perPage: 'Number page'
|
||||||
},
|
},
|
||||||
lock: {
|
lock: {
|
||||||
lockScreen: 'Lock screen',
|
lockScreen: 'Lock screen',
|
||||||
@@ -142,9 +142,9 @@ export default {
|
|||||||
qrcode: 'Scan the QR code to log in',
|
qrcode: 'Scan the QR code to log in',
|
||||||
btnRegister: 'Sign up',
|
btnRegister: 'Sign up',
|
||||||
SmsSendMsg: 'code has been sent',
|
SmsSendMsg: 'code has been sent',
|
||||||
resetPassword: "Reset Password",
|
resetPassword: 'Reset Password',
|
||||||
resetPasswordSuccess: "Reset Password Success",
|
resetPasswordSuccess: 'Reset Password Success',
|
||||||
invalidTenantName:"Invalid Tenant Name"
|
invalidTenantName: 'Invalid Tenant Name'
|
||||||
},
|
},
|
||||||
captcha: {
|
captcha: {
|
||||||
verification: 'Please complete security verification',
|
verification: 'Please complete security verification',
|
||||||
@@ -165,7 +165,7 @@ export default {
|
|||||||
BigBrotherManage: 'BigBrotherManage',
|
BigBrotherManage: 'BigBrotherManage',
|
||||||
BigBrotherDataManage: 'BigBrotherDataManage',
|
BigBrotherDataManage: 'BigBrotherDataManage',
|
||||||
BigBrotherList: 'BigBrotherList',
|
BigBrotherList: 'BigBrotherList',
|
||||||
staffBigBrotherManage: 'StaffBigBrotherManage',
|
staffBigBrotherManage: 'StaffBigBrotherManage'
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: 'New user',
|
newUser: 'New user',
|
||||||
@@ -193,7 +193,8 @@ export default {
|
|||||||
allianceAdvertising: 'Alliance advertising',
|
allianceAdvertising: 'Alliance advertising',
|
||||||
videoAdvertising: 'Video advertising',
|
videoAdvertising: 'Video advertising',
|
||||||
searchEngines: 'Search engines',
|
searchEngines: 'Search engines',
|
||||||
weeklyUserActivity: 'Weekly user activity',
|
weeklyUserActivity: 'The number of live-streamers in Jianlian',
|
||||||
|
weeklyUserActivityDesc: 'The number of Jianlian big brothers',
|
||||||
activeQuantity: 'Active quantity',
|
activeQuantity: 'Active quantity',
|
||||||
alreadyJianlian: 'Already alliance',
|
alreadyJianlian: 'Already alliance',
|
||||||
noAlliance: 'No alliance',
|
noAlliance: 'No alliance',
|
||||||
@@ -431,7 +432,7 @@ export default {
|
|||||||
man: 'Man',
|
man: 'Man',
|
||||||
woman: 'Woman',
|
woman: 'Woman',
|
||||||
createTime: 'Created Date',
|
createTime: 'Created Date',
|
||||||
updateTime: 'Update Time',
|
updateTime: 'Update Time'
|
||||||
},
|
},
|
||||||
info: {
|
info: {
|
||||||
title: 'Basic Information',
|
title: 'Basic Information',
|
||||||
@@ -487,9 +488,12 @@ export default {
|
|||||||
hostsKind: 'Host Type',
|
hostsKind: 'Host Type',
|
||||||
placeHostsKind: 'Please enter live type, e.g., game',
|
placeHostsKind: 'Please enter live type, e.g., game',
|
||||||
isAssigned: 'Assigned',
|
isAssigned: 'Assigned',
|
||||||
|
aiOperation: 'Ai Operation',
|
||||||
sortType: 'Sort Type',
|
sortType: 'Sort Type',
|
||||||
sortName: 'Sort Name',
|
sortName: 'Sort Name',
|
||||||
|
isDelete: 'Is Delete',
|
||||||
placeIsAssigned: 'Please select assignment status',
|
placeIsAssigned: 'Please select assignment status',
|
||||||
|
placeaiOperation: 'Please select Ai operation',
|
||||||
createTime: 'Created Time',
|
createTime: 'Created Time',
|
||||||
updateTime: 'Update Time',
|
updateTime: 'Update Time',
|
||||||
invitationType: 'Invitation Type',
|
invitationType: 'Invitation Type',
|
||||||
@@ -507,7 +511,7 @@ export default {
|
|||||||
edit: 'Edit',
|
edit: 'Edit',
|
||||||
delete: 'Del',
|
delete: 'Del',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
confirm: 'Confirm',
|
confirm: 'Confirm'
|
||||||
},
|
},
|
||||||
employee: {
|
employee: {
|
||||||
hostsId: 'Host ID',
|
hostsId: 'Host ID',
|
||||||
@@ -551,8 +555,7 @@ export default {
|
|||||||
flag: 'Flag',
|
flag: 'Flag',
|
||||||
loadNext: 'Next',
|
loadNext: 'Next',
|
||||||
previous: 'Previous',
|
previous: 'Previous',
|
||||||
updateTime: 'Update Time',
|
updateTime: 'Update Time'
|
||||||
|
|
||||||
},
|
},
|
||||||
country: {
|
country: {
|
||||||
greece: 'Greece Region',
|
greece: 'Greece Region',
|
||||||
@@ -589,11 +592,21 @@ export default {
|
|||||||
onlineFans: 'Online Fans',
|
onlineFans: 'Online Fans',
|
||||||
fllowernum: 'Followers',
|
fllowernum: 'Followers',
|
||||||
updateTime: 'Update Time'
|
updateTime: 'Update Time'
|
||||||
|
|
||||||
},
|
},
|
||||||
hostsInvitationType: {
|
hostsInvitationType: {
|
||||||
eliteTicket: 'elite ticket',
|
eliteTicket: 'elite ticket',
|
||||||
regularTicket:'regular ticket',
|
regularTicket: 'regular ticket'
|
||||||
|
|
||||||
},
|
},
|
||||||
|
Assigned: {
|
||||||
|
yes: 'yes',
|
||||||
|
no: 'no'
|
||||||
|
},
|
||||||
|
sortState: {
|
||||||
|
asc: 'asc',
|
||||||
|
desc: 'desc'
|
||||||
|
},
|
||||||
|
operational: {
|
||||||
|
contact: 'contact',
|
||||||
|
noContact: 'noContact'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BigBrotherApi } from "@/api/server/bigbrother";
|
import { BigBrotherApi } from '@/api/server/bigbrother'
|
||||||
import Search from "@/components/Search/src/Search.vue";
|
import Search from '@/components/Search/src/Search.vue'
|
||||||
import { max } from "lodash-es";
|
import { max } from 'lodash-es'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
common: {
|
common: {
|
||||||
@@ -59,8 +59,7 @@ export default {
|
|||||||
copy: '复制',
|
copy: '复制',
|
||||||
copySuccess: '复制成功',
|
copySuccess: '复制成功',
|
||||||
copyError: '复制失败',
|
copyError: '复制失败',
|
||||||
perPage: '每页',
|
perPage: '每页'
|
||||||
|
|
||||||
},
|
},
|
||||||
lock: {
|
lock: {
|
||||||
lockScreen: '锁定屏幕',
|
lockScreen: '锁定屏幕',
|
||||||
@@ -172,8 +171,7 @@ export default {
|
|||||||
BigBrotherManage: '大哥管理',
|
BigBrotherManage: '大哥管理',
|
||||||
BigBrotherDataManage: '大哥数据管理(管理)',
|
BigBrotherDataManage: '大哥数据管理(管理)',
|
||||||
BigBrotherList: '大哥列表(员工)',
|
BigBrotherList: '大哥列表(员工)',
|
||||||
staffBigBrotherManage: '员工大哥管理(管理)',
|
staffBigBrotherManage: '员工大哥管理(管理)'
|
||||||
|
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: '新增用户',
|
newUser: '新增用户',
|
||||||
@@ -201,7 +199,8 @@ export default {
|
|||||||
allianceAdvertising: '联盟广告',
|
allianceAdvertising: '联盟广告',
|
||||||
videoAdvertising: '视频广告',
|
videoAdvertising: '视频广告',
|
||||||
searchEngines: '搜索引擎',
|
searchEngines: '搜索引擎',
|
||||||
weeklyUserActivity: '当日建联数',
|
weeklyUserActivity: '建联主播数',
|
||||||
|
weeklyUserActivityDesc: '建联大哥数',
|
||||||
activeQuantity: '建联数',
|
activeQuantity: '建联数',
|
||||||
alreadyJianlian: '已建联',
|
alreadyJianlian: '已建联',
|
||||||
noAlliance: '未建联',
|
noAlliance: '未建联',
|
||||||
@@ -487,9 +486,12 @@ export default {
|
|||||||
hostsKind: '主播类型',
|
hostsKind: '主播类型',
|
||||||
placeHostsKind: '请输入直播类型 如:游戏 ',
|
placeHostsKind: '请输入直播类型 如:游戏 ',
|
||||||
isAssigned: '是否分配',
|
isAssigned: '是否分配',
|
||||||
|
aiOperation: '是否AI介入',
|
||||||
sortType: '排序类型',
|
sortType: '排序类型',
|
||||||
sortName: '排序名字',
|
sortName: '排序名字',
|
||||||
|
isDelete: '是否删除',
|
||||||
placeIsAssigned: '请选择是否已经分配给员工',
|
placeIsAssigned: '请选择是否已经分配给员工',
|
||||||
|
placeaiOperation: '请筛选是否AI介入',
|
||||||
createTime: '创建时间',
|
createTime: '创建时间',
|
||||||
updateTime: '更新时间',
|
updateTime: '更新时间',
|
||||||
invitationType: '邀请类型',
|
invitationType: '邀请类型',
|
||||||
@@ -507,7 +509,7 @@ export default {
|
|||||||
edit: '编辑',
|
edit: '编辑',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
confirm: '确定',
|
confirm: '确定'
|
||||||
},
|
},
|
||||||
employee: {
|
employee: {
|
||||||
hostsId: '主播id',
|
hostsId: '主播id',
|
||||||
@@ -551,7 +553,7 @@ export default {
|
|||||||
remark: '备注',
|
remark: '备注',
|
||||||
flag: '旗帜',
|
flag: '旗帜',
|
||||||
loadNext: '下一页',
|
loadNext: '下一页',
|
||||||
previous:'上一页',
|
previous: '上一页'
|
||||||
},
|
},
|
||||||
country: {
|
country: {
|
||||||
greece: '希腊大区',
|
greece: '希腊大区',
|
||||||
@@ -591,8 +593,19 @@ export default {
|
|||||||
},
|
},
|
||||||
hostsInvitationType: {
|
hostsInvitationType: {
|
||||||
eliteTicket: '金票',
|
eliteTicket: '金票',
|
||||||
regularTicket:'普票',
|
regularTicket: '普票'
|
||||||
|
},
|
||||||
|
Assigned: {
|
||||||
|
yes: '是',
|
||||||
|
no: '否'
|
||||||
|
},
|
||||||
|
sortState: {
|
||||||
|
asc: '升序',
|
||||||
|
desc: '降序'
|
||||||
|
},
|
||||||
|
operational: {
|
||||||
|
contact: '转化',
|
||||||
|
noContact: '未转化'
|
||||||
},
|
},
|
||||||
'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
|
'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,9 +250,12 @@ export enum DICT_TYPE {
|
|||||||
INT_TRUE_FLASE = 'int_true_false', // 桥梁类型HOST_LEVEL
|
INT_TRUE_FLASE = 'int_true_false', // 桥梁类型HOST_LEVEL
|
||||||
HOST_LEVEL = 'host_level', // 桥梁类型country_group
|
HOST_LEVEL = 'host_level', // 桥梁类型country_group
|
||||||
COUNTRY_GROUP = 'country_group', // 桥梁类型
|
COUNTRY_GROUP = 'country_group', // 桥梁类型
|
||||||
OPERATION_STATE = 'operational_state', // 桥梁类型operational_state
|
OPERATION_STATE = 'operational_state', // 是否转化
|
||||||
BIGBIOTHER_NEGOTIATION = 'bigBiother_negotiation', // 是否洽谈
|
BIGBIOTHER_NEGOTIATION = 'bigBiother_negotiation', // 是否洽谈
|
||||||
SORT_STATE = 'sort_state', // 升序降序
|
SORT_STATE = 'sort_state', // 升序降序
|
||||||
SORT_TYPE = 'sort_type', // 排序类型
|
SORT_TYPE = 'sort_type', // 排序类型
|
||||||
FLAG_TYPE = 'flag_type', // 旗帜
|
FLAG_TYPE = 'flag_type', // 旗帜
|
||||||
|
HOSTS_KIND = 'hosts_type', // 直播类型
|
||||||
|
|
||||||
|
PAY_TYPE = 'pay_type', // 支付类型
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
<el-card shadow="never" class="mt-8px">
|
<el-card shadow="never" class="mt-8px">
|
||||||
|
|
||||||
<!-- <div style="display: flex; width: 50%;"
|
<!-- <div style="display: flex; width: 50%;"
|
||||||
v-if="wsCache.get('roleRouters').find(item => item.id === 1)?.children.find(item => item.id === 100)">
|
v-if="wsCache.get('roleRouters').find(item => item.id === 5019)?.children.find(item => item.id === 5020)">
|
||||||
|
|
||||||
<el-select v-model="allocationUser" :placeholder="t('newHosts.placeAllocationUser')" clearable
|
<el-select v-model="allocationUser" :placeholder="t('newHosts.placeAllocationUser')" clearable
|
||||||
@change="getUserAccessSource(allocationUser)">
|
@change="getUserAccessSource(allocationUser)">
|
||||||
@@ -93,23 +93,60 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</el-col> -->
|
</el-col> -->
|
||||||
<el-col
|
<el-col
|
||||||
v-if="wsCache.get('roleRouters').find(item => item.id === 1)?.children.find(item => item.id === 100)"
|
v-if="wsCache.get('roleRouters').find(item => item.id === 5019)?.children.find(item => item.id === 5020)"
|
||||||
:xl="14" :lg="20" :md="24" :sm="24" :xs="24">
|
:xl="20" :lg="20" :md="24" :sm="24" :xs="24">
|
||||||
<el-card shadow="hover" class="mb-8px">
|
<el-card shadow="hover" class="mb-8px">
|
||||||
|
<el-select style="width: 200px;" v-model="days" @change="updataDays">
|
||||||
|
<el-option :value="1" label="当日">当日</el-option>
|
||||||
|
<el-option :value="7" label="近7日">近7日</el-option>
|
||||||
|
</el-select>
|
||||||
|
|
||||||
<el-skeleton :loading="loading" animated>
|
<el-skeleton :loading="loading" animated>
|
||||||
<Echart :options="barOptionsData" :height="280" />
|
<Echart style="width: 100%;" :options="barOptionsData" :height="280" />
|
||||||
</el-skeleton>
|
</el-skeleton>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col v-else :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
|
<el-col v-if="tenantLevel != 1" :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
|
||||||
<el-card shadow="hover" class="mb-8px">
|
<el-card shadow="hover" class="mb-8px">
|
||||||
<div>当日建联数量</div>
|
<div>当日建联主播数量</div>
|
||||||
{{ HostsOperationNum }}
|
{{ HostsOperationNum }}
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-skeleton>
|
</el-skeleton>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 当日建联大哥数 -->
|
||||||
|
<el-card shadow="never" class="mt-8px">
|
||||||
|
<el-skeleton :loading="loading" animated>
|
||||||
|
<el-row :gutter="20" justify="space-between">
|
||||||
|
<el-col
|
||||||
|
v-if="wsCache.get('roleRouters').find(item => item.id === 5041)?.children.find(item => item.id === 5042)"
|
||||||
|
:xl="20" :lg="20" :md="24" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-8px">
|
||||||
|
<el-select style="width: 200px;" v-model="daysDsec" @change="updataDaysDsec">
|
||||||
|
<el-option :value="1" label="当日">当日</el-option>
|
||||||
|
|
||||||
|
<el-option :value="7" label="近7日">近7日</el-option>
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<el-skeleton :loading="loading" animated>
|
||||||
|
<Echart style="width: 100%;" :options="barOptionsDataDsec" :height="280" />
|
||||||
|
</el-skeleton>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col v-if="tenantLevel != 1" :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-8px">
|
||||||
|
<div>当日建联大哥数量</div>
|
||||||
|
|
||||||
|
{{ HostsOperationNumDsec }}
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-skeleton>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-8px">
|
<el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-8px">
|
||||||
<!-- 快捷入口 -->
|
<!-- 快捷入口 -->
|
||||||
@@ -172,38 +209,109 @@ import { formatTime } from '@/utils'
|
|||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
// import { useWatermark } from '@/hooks/web/useWatermark'
|
// import { useWatermark } from '@/hooks/web/useWatermark'
|
||||||
import type { WorkplaceTotal, Project, Notice, Shortcut } from './types'
|
import type { WorkplaceTotal, Project, Notice, Shortcut } from './types'
|
||||||
import { pieOptions, barOptions } from './echarts-data'
|
import { pieOptions, barOptions, bigbrotherbarOptions } from './echarts-data'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { getComplete, getEmployeeComplete } from '@/api/system/user'
|
import { getComplete, getEmployeeComplete } from '@/api/system/user'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
import { useCache } from '@/hooks/web/useCache'
|
||||||
import { getSimpleUserListPage, getSimpleUserList } from '@/api/system/user'
|
import { getSimpleUserListPage, getSimpleUserList } from '@/api/system/user'
|
||||||
import { EmployeeHostsApi } from '@/api/server/employeehosts'
|
import { EmployeeHostsApi } from '@/api/server/employeehosts'
|
||||||
import { ref, reactive, onMounted, onActivated } from 'vue'
|
import { ref, reactive, onMounted, onActivated } from 'vue'
|
||||||
let HostsOperationNum = ref(0)
|
import WxMusic from '../mp/components/wx-music'
|
||||||
|
import * as TenantApi from '@/api/system/tenant'
|
||||||
|
|
||||||
|
let HostsOperationNum = ref(0)//当日建联主播数量
|
||||||
|
|
||||||
|
let HostsOperationNumDsec = ref(0)//当日建联大哥数量
|
||||||
|
|
||||||
|
let days = ref(1)//当日
|
||||||
|
|
||||||
|
let daysDsec = ref(1)//当日
|
||||||
|
let tenantLevel = ref(null)//租户等级
|
||||||
|
|
||||||
|
let tenantType = ref(null)//租户类型
|
||||||
|
//初始
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getAllApi()
|
|
||||||
await getAllocationList()
|
// console.log("菜单", wsCache.get('roleRouters'))
|
||||||
if (wsCache.get('roleRouters').find(item => item.id === 1)?.children.find(item => item.id === 100)) {
|
//判断菜单有没有钱包 是用户还是代理总后台
|
||||||
await fetchAllHostsCount()
|
tenantType.value = (wsCache.get('roleRouters').find(item => item.id === 1)?.children.find(item => item.id === 1224)?.children.find(item => item.id === 1224))
|
||||||
} else {
|
//有钱包就是代理或者总后台 有级别
|
||||||
await fetchDailyHostsCount()
|
if (tenantType.value) {
|
||||||
|
await TenantApi.getSelfTenantLevel().then(res => {
|
||||||
|
tenantLevel.value = res.tenantLevel
|
||||||
|
console.log(res.tenantLevel)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tenantLevel.value == 1) {
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log(1321231)
|
||||||
|
await getAllApi()
|
||||||
|
|
||||||
|
await getAllocationList()
|
||||||
|
//判断菜单有没有爬大哥管理中的管理员权限
|
||||||
|
if (wsCache.get('roleRouters').find(item => item.id === 5041)?.children.find(item => item.id === 5042)) {
|
||||||
|
|
||||||
|
await fetchAllHostsCountDesc(1)
|
||||||
|
await fetchDailyHostsCountDesc()
|
||||||
|
}
|
||||||
|
//判断菜单有没有主播管理中的管理员权限
|
||||||
|
if (wsCache.get('roleRouters').find(item => item.id === 5019)?.children.find(item => item.id === 5020)) {
|
||||||
|
await fetchAllHostsCount(1)
|
||||||
|
await fetchDailyHostsCount()
|
||||||
|
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 每次页面“再次显示”时都会触发(前提:该路由组件被 keep-alive 缓存)
|
// 每次页面“再次显示”时都会触发(前提:该路由组件被 keep-alive 缓存)
|
||||||
onActivated(async () => {
|
onActivated(async () => {
|
||||||
await fetchDailyHostsCount()
|
|
||||||
await fetchAllHostsCount()
|
if (tenantType.value) {
|
||||||
|
await TenantApi.getSelfTenantLevel().then(res => {
|
||||||
|
tenantLevel.value = res.tenantLevel
|
||||||
|
console.log(res.tenantLevel)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
if (tenantLevel.value == 1) {
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//判断菜单有没有爬大哥管理中的管理员权限
|
||||||
|
if (wsCache.get('roleRouters').find(item => item.id === 5041)?.children.find(item => item.id === 5042)) {
|
||||||
|
|
||||||
|
await fetchAllHostsCountDesc(1)
|
||||||
|
await fetchDailyHostsCountDesc()
|
||||||
|
}
|
||||||
|
//判断菜单有没有主播管理中的管理员权限
|
||||||
|
if (wsCache.get('roleRouters').find(item => item.id === 5019)?.children.find(item => item.id === 5020)) {
|
||||||
|
await fetchAllHostsCount(1)
|
||||||
|
await fetchDailyHostsCount()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// 天数切换
|
||||||
|
async function updataDays(val) {
|
||||||
|
await fetchAllHostsCount(val)
|
||||||
|
}
|
||||||
|
//大哥天数切换
|
||||||
|
async function updataDaysDsec(val: any) {
|
||||||
|
await fetchAllHostsCountDesc(val)
|
||||||
|
}
|
||||||
|
|
||||||
// import { useGlobalWebSocket } from '@/components/useGlobalWebSocket'
|
// import { useGlobalWebSocket } from '@/components/useGlobalWebSocket'
|
||||||
// let messageList = useGlobalWebSocket().messageList
|
// let messageList = useGlobalWebSocket().messageList
|
||||||
// console.log(messageList.value)
|
// console.log(messageList.value)
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
|
|
||||||
let allocationUser = ref('') //选中的分配用户
|
let allocationUser = ref('') //选中的分配用户
|
||||||
|
|
||||||
let allocationUserList = ref([
|
let allocationUserList = ref([
|
||||||
{
|
{
|
||||||
label: '分配用户1',
|
label: '分配用户1',
|
||||||
@@ -219,14 +327,23 @@ defineOptions({ name: 'Index' })
|
|||||||
|
|
||||||
// console.log(data)
|
// console.log(data)
|
||||||
// const { open } = useGlobalWebSocket()
|
// const { open } = useGlobalWebSocket()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// const { setWatermark } = useWatermark()
|
// const { setWatermark } = useWatermark()
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
|
|
||||||
const avatar = userStore.getUser.avatar
|
const avatar = userStore.getUser.avatar
|
||||||
|
|
||||||
const username = userStore.getUser.nickname
|
const username = userStore.getUser.nickname
|
||||||
|
|
||||||
const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
|
const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
|
||||||
|
|
||||||
// 获取统计数
|
// 获取统计数
|
||||||
let totalSate = reactive<WorkplaceTotal>({
|
let totalSate = reactive<WorkplaceTotal>({
|
||||||
project: 0,
|
project: 0,
|
||||||
@@ -234,6 +351,7 @@ let totalSate = reactive<WorkplaceTotal>({
|
|||||||
todo: 0
|
todo: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const getCount = async () => {
|
const getCount = async () => {
|
||||||
const data = {
|
const data = {
|
||||||
project: 40,
|
project: 40,
|
||||||
@@ -301,6 +419,7 @@ const getProject = async () => {
|
|||||||
|
|
||||||
// 获取通知公告
|
// 获取通知公告
|
||||||
let notice = reactive<Notice[]>([])
|
let notice = reactive<Notice[]>([])
|
||||||
|
|
||||||
const getNotice = async () => {
|
const getNotice = async () => {
|
||||||
const data = [
|
const data = [
|
||||||
// {
|
// {
|
||||||
@@ -373,14 +492,18 @@ const getShortcut = async () => {
|
|||||||
color: '#1a73e8'
|
color: '#1a73e8'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
shortcut = Object.assign(shortcut, data)
|
shortcut = Object.assign(shortcut, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户来源
|
// 用户来源
|
||||||
const getUserAccessSource = async (id) => {
|
const getUserAccessSource = async (id) => {
|
||||||
const res = id ? await getEmployeeComplete(id) : await getComplete()
|
const res = id ? await getEmployeeComplete(id) : await getComplete()
|
||||||
|
|
||||||
const completeData = res ?? { unfinishedNum: 0, finishedNum: 0 }
|
const completeData = res ?? { unfinishedNum: 0, finishedNum: 0 }
|
||||||
|
|
||||||
console.log('completeData', completeData)
|
console.log('completeData', completeData)
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ value: completeData.unfinishedNum, name: 'analysis.noAlliance' },
|
{ value: completeData.unfinishedNum, name: 'analysis.noAlliance' },
|
||||||
{ value: completeData.finishedNum, name: 'analysis.alreadyJianlian' },
|
{ value: completeData.finishedNum, name: 'analysis.alreadyJianlian' },
|
||||||
@@ -388,11 +511,13 @@ const getUserAccessSource = async (id) => {
|
|||||||
// { value: 135, name: 'analysis.videoAdvertising' },
|
// { value: 135, name: 'analysis.videoAdvertising' },
|
||||||
// { value: 1548, name: 'analysis.searchEngines' }
|
// { value: 1548, name: 'analysis.searchEngines' }
|
||||||
]
|
]
|
||||||
|
|
||||||
set(
|
set(
|
||||||
pieOptionsData,
|
pieOptionsData,
|
||||||
'legend.data',
|
'legend.data',
|
||||||
data.map((v) => t(v.name))
|
data.map((v) => t(v.name))
|
||||||
)
|
)
|
||||||
|
|
||||||
pieOptionsData!.series![0].data = data.map((v) => {
|
pieOptionsData!.series![0].data = data.map((v) => {
|
||||||
return {
|
return {
|
||||||
name: t(v.name),
|
name: t(v.name),
|
||||||
@@ -400,21 +525,30 @@ const getUserAccessSource = async (id) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
|
const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
|
||||||
|
|
||||||
|
const barOptionsDataDsec = reactive<EChartsOption>(bigbrotherbarOptions) as EChartsOption
|
||||||
|
|
||||||
type EmpBarItem = {
|
type EmpBarItem = {
|
||||||
userId: number
|
userId: number
|
||||||
finishedNum: number | null
|
finishedNum: number | null
|
||||||
totalNum: number | null
|
totalNum: number | null
|
||||||
unfinishedNum: number | null
|
unfinishedNum: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
// 传入希望展示的用户 id 列表 + 后端原始返回,补齐未返回的用户为 0
|
// 传入希望展示的用户 id 列表 + 后端原始返回,补齐未返回的用户为 0
|
||||||
function mergeZeroUsers(ids: number[], resList: EmpBarItem[]): EmpBarItem[] {
|
function mergeZeroUsers(ids: number[], resList: EmpBarItem[]): EmpBarItem[] {
|
||||||
const map = new Map<number, EmpBarItem>(resList.map(it => [it.userId, it]))
|
const map = new Map<number, EmpBarItem>(resList.map(it => [it.userId, it]))
|
||||||
|
|
||||||
return ids.map(id => {
|
return ids.map(id => {
|
||||||
const it = map.get(id)
|
const it = map.get(id)
|
||||||
|
|
||||||
const finished = it?.finishedNum ?? 0
|
const finished = it?.finishedNum ?? 0
|
||||||
|
|
||||||
// 未建联:优先用后端给的 unfinishedNum;若没有且提供了 totalNum,则用 totalNum - finished;否则 0
|
// 未建联:优先用后端给的 unfinishedNum;若没有且提供了 totalNum,则用 totalNum - finished;否则 0
|
||||||
const total = it?.totalNum ?? 0
|
const total = it?.totalNum ?? 0
|
||||||
|
|
||||||
const unfinished = it?.unfinishedNum ?? (it?.totalNum != null && it?.finishedNum != null
|
const unfinished = it?.unfinishedNum ?? (it?.totalNum != null && it?.finishedNum != null
|
||||||
? Math.max(Number(total) - Number(finished), 0)
|
? Math.max(Number(total) - Number(finished), 0)
|
||||||
: 0)
|
: 0)
|
||||||
@@ -427,23 +561,28 @@ function mergeZeroUsers(ids: number[], resList: EmpBarItem[]): EmpBarItem[] {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 把后端返回的数据渲染到柱状图
|
// 把后端返回的数据渲染到柱状图
|
||||||
function updateEmployeeBarChart(list: EmpBarItem[]) {
|
function updateEmployeeBarChart(list: EmpBarItem[]) {
|
||||||
// 建立 id -> 昵称 的映射
|
// 建立 id -> 昵称 的映射
|
||||||
const id2label = new Map(allocationUserList.value.map(u => [u.value, u.label]))
|
const id2label = new Map(allocationUserList.value.map(u => [u.value, u.label]))
|
||||||
|
|
||||||
const labels = list.map(it => id2label.get(it.userId) || String(it.userId))
|
const labels = list.map(it => id2label.get(it.userId) || String(it.userId))
|
||||||
|
|
||||||
const finished = list.map(it => it.finishedNum ?? 0)
|
const finished = list.map(it => it.finishedNum ?? 0)
|
||||||
|
|
||||||
const unfinished = list.map(it => it.unfinishedNum ?? 0)
|
const unfinished = list.map(it => it.unfinishedNum ?? 0)
|
||||||
|
|
||||||
// legend
|
// legend
|
||||||
const legendNames = []
|
const legendNames = []
|
||||||
|
|
||||||
set(barOptionsData, 'legend.data', legendNames)
|
set(barOptionsData, 'legend.data', legendNames)
|
||||||
|
|
||||||
set(barOptionsData, 'xAxis.data', labels)
|
set(barOptionsData, 'xAxis.data', labels)
|
||||||
|
|
||||||
// 1) 轴标签强制全部显示 + 不自动隐藏
|
// 1) 轴标签强制全部显示 + 不自动隐藏
|
||||||
set(barOptionsData, 'xAxis.axisLabel.interval', 0)
|
set(barOptionsData, 'xAxis.axisLabel.interval', 0)
|
||||||
|
|
||||||
set(barOptionsData, 'xAxis.axisLabel.hideOverlap', false)
|
set(barOptionsData, 'xAxis.axisLabel.hideOverlap', false)
|
||||||
|
|
||||||
// 2) 适当旋转,避免重叠(不想旋转可设为 0)
|
// 2) 适当旋转,避免重叠(不想旋转可设为 0)
|
||||||
@@ -451,9 +590,10 @@ function updateEmployeeBarChart(list: EmpBarItem[]) {
|
|||||||
|
|
||||||
// 3) 防止被裁剪:让 grid 预留标签空间
|
// 3) 防止被裁剪:让 grid 预留标签空间
|
||||||
set(barOptionsData, 'grid.containLabel', true)
|
set(barOptionsData, 'grid.containLabel', true)
|
||||||
set(barOptionsData, 'grid.bottom', 60) // 视情况调大/调小
|
|
||||||
set(barOptionsData, 'xAxis.axisTick.alignWithLabel', true)
|
|
||||||
|
|
||||||
|
set(barOptionsData, 'grid.bottom', 60) // 视情况调大/调小
|
||||||
|
|
||||||
|
set(barOptionsData, 'xAxis.axisTick.alignWithLabel', true)
|
||||||
|
|
||||||
set(barOptionsData, 'series', [
|
set(barOptionsData, 'series', [
|
||||||
{
|
{
|
||||||
@@ -468,17 +608,67 @@ function updateEmployeeBarChart(list: EmpBarItem[]) {
|
|||||||
// }
|
// }
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 周活跃量 大哥图表数据
|
||||||
|
function updateEmployeeBarChartDesc(lists: EmpBarItem[]) {
|
||||||
|
// 建立 id -> 昵称 的映射
|
||||||
|
const id2label = new Map(allocationUserList.value.map(u => [u.value, u.label]))
|
||||||
|
|
||||||
|
const labels = lists.map(it => id2label.get(it.userId) || String(it.userId))
|
||||||
|
|
||||||
|
const finished = lists.map(it => it.finishedNum ?? 0)
|
||||||
|
|
||||||
|
const unfinished = lists.map(it => it.unfinishedNum ?? 0)
|
||||||
|
|
||||||
|
// legend
|
||||||
|
const legendNames = []
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'legend.data', legendNames)
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'xAxis.data', labels)
|
||||||
|
|
||||||
|
// 1) 轴标签强制全部显示 + 不自动隐藏
|
||||||
|
set(barOptionsDataDsec, 'xAxis.axisLabel.interval', 0)
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'xAxis.axisLabel.hideOverlap', false)
|
||||||
|
|
||||||
|
// 2) 适当旋转,避免重叠(不想旋转可设为 0)
|
||||||
|
set(barOptionsDataDsec, 'xAxis.axisLabel.rotate', 30)
|
||||||
|
|
||||||
|
// 3) 防止被裁剪:让 grid 预留标签空间
|
||||||
|
set(barOptionsDataDsec, 'grid.containLabel', true)
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'grid.bottom', 60) // 视情况调大/调小
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'xAxis.axisTick.alignWithLabel', true)
|
||||||
|
|
||||||
|
set(barOptionsDataDsec, 'series', [
|
||||||
|
{
|
||||||
|
name: t('analysis.alreadyJianlian'),
|
||||||
|
type: 'bar',
|
||||||
|
data: finished
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: t('analysis.noAlliance'),
|
||||||
|
// type: 'bar',
|
||||||
|
// data: unfinished
|
||||||
|
// }
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
// 周活跃量 图表数据
|
// 周活跃量 图表数据
|
||||||
const getWeeklyUserActivity = async () => {
|
const getWeeklyUserActivity = async () => {
|
||||||
const data = [
|
const data = [
|
||||||
{ value: HostsOperationNum.value, name: 'analysis.monday' },
|
{ value: HostsOperationNum.value, name: 'analysis.monday' },
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
set(
|
set(
|
||||||
barOptionsData,
|
barOptionsData,
|
||||||
'xAxis.data',
|
'xAxis.data',
|
||||||
data.map((v) => t(v.name))
|
data.map((v) => t(v.name))
|
||||||
)
|
)
|
||||||
|
|
||||||
set(barOptionsData, 'series', [
|
set(barOptionsData, 'series', [
|
||||||
{
|
{
|
||||||
name: t('analysis.activeQuantity'),
|
name: t('analysis.activeQuantity'),
|
||||||
@@ -494,9 +684,10 @@ const getAllApi = async () => {
|
|||||||
getProject(),
|
getProject(),
|
||||||
getNotice(),
|
getNotice(),
|
||||||
getShortcut(),
|
getShortcut(),
|
||||||
getUserAccessSource(null),
|
wsCache.get('roleRouters').find(item => item.id === 5019)?.children.find(item => item.id === 5020) ? getUserAccessSource(null) : null,
|
||||||
getWeeklyUserActivity()
|
getWeeklyUserActivity()
|
||||||
])
|
])
|
||||||
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,10 +702,14 @@ const handleShortcutClick = (url: string) => {
|
|||||||
/** 查询员工 */
|
/** 查询员工 */
|
||||||
const getAllocationList = async () => {
|
const getAllocationList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
allocationUserList.value = []
|
allocationUserList.value = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await getSimpleUserList()
|
const data = await getSimpleUserList()
|
||||||
|
|
||||||
console.log('data', data)
|
console.log('data', data)
|
||||||
|
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
if (wsCache.get('user').user.id == item.id) {
|
if (wsCache.get('user').user.id == item.id) {
|
||||||
|
|
||||||
@@ -524,9 +719,8 @@ const getAllocationList = async () => {
|
|||||||
value: item.id
|
value: item.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(allocationUserList.value)
|
console.log(allocationUserList.value)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@@ -535,6 +729,7 @@ const getAllocationList = async () => {
|
|||||||
// 获取当前日期,格式为 YYYY-MM-DD
|
// 获取当前日期,格式为 YYYY-MM-DD
|
||||||
const getFormattedDate = () => {
|
const getFormattedDate = () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
|
||||||
return now.toISOString().split('T')[0] + ' 00:00:00'
|
return now.toISOString().split('T')[0] + ' 00:00:00'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,16 +742,30 @@ async function fetchDailyHostsCount() {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
updateTime: getFormattedDate()
|
updateTime: getFormattedDate()
|
||||||
})
|
})
|
||||||
|
|
||||||
HostsOperationNum.value = res.total ?? 0
|
HostsOperationNum.value = res.total ?? 0
|
||||||
// 如果柱状图依赖这个值,顺便刷新一次图表数据
|
// 如果柱状图依赖这个值,顺便刷新一次图表数据
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ 抽成函数:每天所有员工数量(用于多人柱状图)
|
async function fetchDailyHostsCountDesc() {
|
||||||
async function fetchAllHostsCount() {
|
const res = await EmployeeHostsApi.getEmployeeHostsPageDsec({
|
||||||
|
operationStatus: 1,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
updateTime: getFormattedDate()
|
||||||
|
})
|
||||||
|
|
||||||
|
HostsOperationNumDsec.value = res.finishedNum ?? 0
|
||||||
|
// 如果柱状图依赖这个值,顺便刷新一次图表数据
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 爬主播建联率
|
||||||
|
async function fetchAllHostsCount(val) {
|
||||||
// 以“传入的用户 id”为准展示(顺序也按这里来)
|
// 以“传入的用户 id”为准展示(顺序也按这里来)
|
||||||
const ids = allocationUserList.value.map(item => item.value)
|
const ids = allocationUserList.value.map(item => item.value)
|
||||||
|
|
||||||
const res = await EmployeeHostsApi.employeeCompleteBarChart(ids)
|
const res = await EmployeeHostsApi.employeeCompleteBarChart(ids, val)
|
||||||
|
|
||||||
const rawList: EmpBarItem[] = Array.isArray(res) ? res : (res?.data ?? [])
|
const rawList: EmpBarItem[] = Array.isArray(res) ? res : (res?.data ?? [])
|
||||||
|
|
||||||
// 补齐后端未返回的用户为 0
|
// 补齐后端未返回的用户为 0
|
||||||
@@ -565,4 +774,23 @@ async function fetchAllHostsCount() {
|
|||||||
// 渲染
|
// 渲染
|
||||||
updateEmployeeBarChart(list)
|
updateEmployeeBarChart(list)
|
||||||
}
|
}
|
||||||
|
// ✅ 爬大哥建联率
|
||||||
|
async function fetchAllHostsCountDesc(val) {
|
||||||
|
// 以“传入的用户 id”为准展示(顺序也按这里来)
|
||||||
|
const idss = allocationUserList.value.map(item => item.value)
|
||||||
|
|
||||||
|
const ress = await EmployeeHostsApi.employeeCompleteBarChartDsec(idss, val)
|
||||||
|
|
||||||
|
console.log('fetchAllHostsCountDesc', ress);
|
||||||
|
|
||||||
|
const rawLists: EmpBarItem[] = Array.isArray(ress) ? ress : (ress?.data ?? [])
|
||||||
|
|
||||||
|
// 补齐后端未返回的用户为 0
|
||||||
|
const lists = mergeZeroUsers(idss, rawLists)
|
||||||
|
|
||||||
|
// 渲染
|
||||||
|
updateEmployeeBarChartDesc(lists)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -108,8 +108,6 @@ export const pieOptions: EChartsOption = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const barOptions: EChartsOption = {
|
export const barOptions: EChartsOption = {
|
||||||
title: {
|
title: {
|
||||||
text: t('analysis.weeklyUserActivity'),
|
text: t('analysis.weeklyUserActivity'),
|
||||||
@@ -152,6 +150,48 @@ export const barOptions: EChartsOption = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
export const bigbrotherbarOptions: EChartsOption = {
|
||||||
|
title: {
|
||||||
|
text: t('analysis.weeklyUserActivityDesc'),
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 50,
|
||||||
|
right: 20,
|
||||||
|
bottom: 20
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: [
|
||||||
|
t('analysis.monday'),
|
||||||
|
t('analysis.tuesday'),
|
||||||
|
t('analysis.wednesday'),
|
||||||
|
t('analysis.thursday'),
|
||||||
|
t('analysis.friday'),
|
||||||
|
t('analysis.saturday'),
|
||||||
|
t('analysis.sunday')
|
||||||
|
],
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: t('analysis.activeQuantity'),
|
||||||
|
data: [0, 0, 0, 0, 0, 0, 0],
|
||||||
|
type: 'bar'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
export const radarOption: EChartsOption = {
|
export const radarOption: EChartsOption = {
|
||||||
legend: {
|
legend: {
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
<el-form
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
|
||||||
ref="formRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="formRules"
|
|
||||||
label-width="100px"
|
|
||||||
v-loading="formLoading"
|
|
||||||
>
|
|
||||||
<el-form-item label="大哥的display_id" prop="displayId">
|
<el-form-item label="大哥的display_id" prop="displayId">
|
||||||
<el-input v-model="formData.displayId" placeholder="请输入大哥的display_id" />
|
<el-input v-model="formData.displayId" placeholder="请输入大哥的display_id" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -98,8 +98,8 @@
|
|||||||
<el-form-item :label="t('newHosts.isAssigned')" prop="isAssigned">
|
<el-form-item :label="t('newHosts.isAssigned')" prop="isAssigned">
|
||||||
<el-select v-model="queryParams.isAssigned" :placeholder="t('newHosts.placeIsAssigned')" clearable
|
<el-select v-model="queryParams.isAssigned" :placeholder="t('newHosts.placeIsAssigned')" clearable
|
||||||
class="!w-240px">
|
class="!w-240px">
|
||||||
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.INT_TRUE_FLASE)" :key="dict.value" :label="dict.label"
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.INT_TRUE_FLASE)" :key="dict.value"
|
||||||
:value="dict.value" />
|
:label="t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -125,6 +125,10 @@
|
|||||||
<el-button @click="dialogAllocation = true">
|
<el-button @click="dialogAllocation = true">
|
||||||
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('newHosts.allocation') }}
|
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('newHosts.allocation') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button type="danger" plain :disabled="checkedIds.length === 0" @click="handleDeleteBatch"
|
||||||
|
v-hasPermi="['server:new-hosts:delete']">
|
||||||
|
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
@@ -154,9 +158,12 @@
|
|||||||
<el-table-column label="该数据所属的账号id" align="center" prop="ownerId" />
|
<el-table-column label="该数据所属的账号id" align="center" prop="ownerId" />
|
||||||
<el-table-column :label="t('newHosts.isAssigned')" align="center" prop="isAssigned">
|
<el-table-column :label="t('newHosts.isAssigned')" align="center" prop="isAssigned">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.INT_TRUE_FLASE" :value="scope.row.isAssigned" />
|
<el-tag size="small" :type="scope.row.isAssigned == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.INT_TRUE_FLASE, scope.row.isAssigned) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
|
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
|
||||||
<el-table-column label="操作" align="center" min-width="120px">
|
<el-table-column label="操作" align="center" min-width="120px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -176,13 +183,17 @@
|
|||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
<!-- 分配弹窗 -->
|
<!-- 分配弹窗 -->
|
||||||
<el-dialog v-model="dialogAllocation" :title="t('newHosts.allocationUser')">
|
<el-dialog v-model="dialogAllocation" :title="t('newHosts.allocationUser')">
|
||||||
<!-- <div style="padding: 0px 0px 30px 0px ;">
|
<div style="display: flex;">
|
||||||
<el-alert title="分配成功数量可能会小于选择数量,同id主播无法被重复分配" type="warning" />
|
<el-select v-if="wsCache.get('roleRouters').find(item => item.id === 1).children.find(item => item.id === 103)"
|
||||||
</div> -->
|
v-model="allocationDept" :placeholder="t('newHosts.placeAllocationDept')" clearable
|
||||||
|
@change="getAllocationUserList">
|
||||||
|
<el-option v-for="(dept, index) in allocationdeptList" :key="index" :label="dept.name" :value="dept.id" />
|
||||||
|
</el-select>
|
||||||
|
|
||||||
<el-select v-model="allocationUser" :placeholder="t('newHosts.placeAllocationUser')" clearable>
|
<el-select v-model="allocationUser" :placeholder="t('newHosts.placeAllocationUser')" clearable>
|
||||||
<el-option v-for="(user, index) in allocationUserList" :key="index" :label="user.label" :value="user.value" />
|
<el-option v-for="(user, index) in allocationUserList" :key="index" :label="user.label" :value="user.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="dialogAllocation = false">{{ t('newHosts.cancel') }}</el-button>
|
<el-button @click="dialogAllocation = false">{{ t('newHosts.cancel') }}</el-button>
|
||||||
@@ -201,10 +212,29 @@ import { getIntDictOptions, DICT_TYPE, getStrDictOptions } from '@/utils/dict'
|
|||||||
import { dateFormatter } from '@/utils/formatTime'
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
import download from '@/utils/download'
|
import download from '@/utils/download'
|
||||||
import { BigBrotherApi, BigBrotherVO } from '@/api/server/bigbrother'
|
import { BigBrotherApi, BigBrotherVO } from '@/api/server/bigbrother'
|
||||||
import { getAllocation, getSimpleUserList } from '@/api/system/user'
|
import * as DeptApi from '@/api/system/dept'
|
||||||
|
import { getAllocation, getSimpleUserList, getSimpleUserListPage } from '@/api/system/user'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
import { useCache } from '@/hooks/web/useCache'
|
||||||
import BigBrotherForm from './BigBrotherForm.vue'
|
import BigBrotherForm from './BigBrotherForm.vue'
|
||||||
|
import { useDictStore } from '@/store/modules/dict' // 如果你项目里有字典 store
|
||||||
|
const dictStore = useDictStore?.() // 有就用;没有的话把 dictStore 相关行删掉
|
||||||
|
|
||||||
|
// 统一用字符串比较,自动识别并翻译 i18n key
|
||||||
|
function dictLabelI18n(type: string, val: any) {
|
||||||
|
const v = val == null ? '' : String(val)
|
||||||
|
|
||||||
|
// 优先从 store 取;若没有,就从你现有的工具取(getIntDictOptions / getStrDictOptions)
|
||||||
|
const opts =
|
||||||
|
(dictStore?.getDictOptions?.(type) as any[]) ||
|
||||||
|
getIntDictOptions(type) ||
|
||||||
|
getStrDictOptions(type) ||
|
||||||
|
[]
|
||||||
|
|
||||||
|
const hit = opts.find(o => String(o.value) === v)
|
||||||
|
const label = hit?.label ?? ''
|
||||||
|
// 形如 a.b 或包含点号的,大概率是 i18n key,则用 t() 翻
|
||||||
|
return label && label.includes('.') ? t(label) : label
|
||||||
|
}
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
/** 大哥数据 列表 */
|
/** 大哥数据 列表 */
|
||||||
defineOptions({ name: 'BigBrother' })
|
defineOptions({ name: 'BigBrother' })
|
||||||
@@ -247,12 +277,19 @@ const exportLoading = ref(false) // 导出的加载中
|
|||||||
let dialogAllocation = ref(false)//分配弹窗
|
let dialogAllocation = ref(false)//分配弹窗
|
||||||
let selectBigList = ref([]) //选中的主播列表
|
let selectBigList = ref([]) //选中的主播列表
|
||||||
let allocationUser = ref('') //选中的分配用户
|
let allocationUser = ref('') //选中的分配用户
|
||||||
|
let allocationDept = ref('') //选中的分配部门
|
||||||
let allocationUserList = ref([
|
let allocationUserList = ref([
|
||||||
{
|
{
|
||||||
label: '分配用户1',
|
label: '分配用户1',
|
||||||
value: 1
|
value: 1
|
||||||
}
|
}
|
||||||
]) //选中的分配用户
|
]) //选中的分配用户
|
||||||
|
let allocationdeptList = ref([
|
||||||
|
{
|
||||||
|
name: '分配用户1',
|
||||||
|
id: 1
|
||||||
|
}
|
||||||
|
]) //选中的分配部门
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -266,7 +303,17 @@ const getList = async () => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/** 查询部门 */
|
||||||
|
const getAlldeptList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await DeptApi.getDeptPage(queryParams)
|
||||||
|
allocationdeptList.value = data
|
||||||
|
// console.log('=========================================', allocationdeptList)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.pageNo = 1
|
queryParams.pageNo = 1
|
||||||
@@ -340,9 +387,22 @@ const getAllocationList = async () => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getAllocationUserList = async () => {
|
||||||
|
const data = await getSimpleUserListPage({ pageSize: 1000, pageNo: 1, deptId: allocationDept.value })
|
||||||
|
allocationUserList.value = []
|
||||||
|
console.log("----------------------------------------------------", data.list)
|
||||||
|
data.list.forEach((item) => {
|
||||||
|
allocationUserList.value.push({
|
||||||
|
label: item.nickname,
|
||||||
|
value: item.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
//分配按钮操作
|
//分配按钮操作
|
||||||
const handleSelectionChange = (val) => {
|
const handleSelectionChange = (val) => {
|
||||||
|
checkedIds.value = val.map((row) => row.id)
|
||||||
selectBigList.value = val
|
selectBigList.value = val
|
||||||
console.log(selectBigList.value)
|
console.log(selectBigList.value)
|
||||||
}
|
}
|
||||||
@@ -421,9 +481,26 @@ function openHtml(item, id) {
|
|||||||
window.open(`https://www.tiktok.com/@${id}`)
|
window.open(`https://www.tiktok.com/@${id}`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/** 批量删除按钮操作 */
|
||||||
|
const checkedIds = ref<number[]>([])
|
||||||
|
const handleDeleteBatch = async () => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起批量删除
|
||||||
|
await BigBrotherApi.deleteBigBrotherList(checkedIds.value)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
getAllocationList();
|
getAllocationList();
|
||||||
|
if (wsCache.get('roleRouters').find(item => item.id === 1).children.find(item => item.id === 103)) {
|
||||||
|
getAlldeptList();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -111,13 +111,22 @@
|
|||||||
<el-button @click="exportAi(2)">
|
<el-button @click="exportAi(2)">
|
||||||
<Icon icon="ep:copy-document" class="mr-5px" /> 批量复制主播id
|
<Icon icon="ep:copy-document" class="mr-5px" /> 批量复制主播id
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
<el-button v-if="!isMobile" :disabled="checkedIds.length === 0" type="danger" @click="handleDeleteList">
|
||||||
|
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
||||||
|
</el-button>
|
||||||
|
<el-button v-else type="danger" @click="handleDeletePageList">
|
||||||
|
<Icon icon="ep:delete" class="mr-5px" /> 删除本页
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-table v-loading="loading" :data="list" :stripe="true" @selection-change="handleSelectionChange">
|
<el-switch v-model="isMobile" size="large" active-text="卡片" inactive-text="列表" />
|
||||||
|
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="大哥的用户id" align="center" prop="displayId">
|
<el-table-column label="大哥的用户id" align="center" prop="displayId">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -163,8 +172,39 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<!-- ···························································································································· -->
|
||||||
|
<div v-else>
|
||||||
|
<div v-for="(item, index) in list" :key="index" class="mobile-card">
|
||||||
|
<div class="card-row" style="color:green;">
|
||||||
|
<b>大哥的用户id:</b><span @click="openHtml(item, item.displayId)"
|
||||||
|
style=" text-decoration: underline;margin-right: 50px;">{{ item.displayId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-row"><b>大哥的uid:</b>{{ item.userIdStr }}</div>
|
||||||
|
<div class="card-row"><b>大哥的用户昵称:</b>{{ item.nickname }}</div>
|
||||||
|
<div class="card-row"><b>大哥的等级:</b>{{ item.level }}</div>
|
||||||
|
<div class="card-row"><b>粉丝团等级:</b>{{ item.fansLevel }}</div>
|
||||||
|
<div class="card-row"><b>大哥打赏的金币:</b>{{ item.hostcoins }}</div>
|
||||||
|
<div class="card-row"><b>大哥的粉丝数:</b>{{ item.followerCount }}</div>
|
||||||
|
<div class="card-row"><b>大哥的关注数:</b>{{ item.followingCount }}</div>
|
||||||
|
<div class="card-row"><b>大哥所在的地区:</b>{{ item.region }}</div>
|
||||||
|
<div class="card-row"><b>大哥打赏的历史最高金币:</b>{{ item.historicHighCoins }}</div>
|
||||||
|
<div class="card-row"><b>大哥历史打赏金币总和:</b>{{ item.totalGiftCoins }}</div>
|
||||||
|
<div class="card-row" style="color:green;">
|
||||||
|
<b>大哥所在的直播间的主播id:</b><span @click="openHtmlbig(item.hostDisplayId)"
|
||||||
|
style=" text-decoration: underline;margin-right: 50px;">{{ item.hostDisplayId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-row"><b>创建时间:</b>{{ formatTimestamp(item.createTime) }}</div>
|
||||||
|
<div class="card-row"><b>是否洽谈:</b>
|
||||||
|
<el-tag size="small" :type="item.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.BIGBIOTHER_NEGOTIATION, item.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MobilePagination v-if="isMobile" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
:total="total" :page-sizes="[10, 20, 30, 50]" @size-change="getList()" @load="getList()" @load-pre="getList()" />
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
<Pagination v-if="!isMobile" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
@pagination="getList" />
|
@pagination="getList" />
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
@@ -227,6 +267,12 @@ let allocationUserList = ref([
|
|||||||
value: 1
|
value: 1
|
||||||
}
|
}
|
||||||
]) //选中的分配用户
|
]) //选中的分配用户
|
||||||
|
|
||||||
|
|
||||||
|
/** 批量删除按钮操作 */
|
||||||
|
const checkedIds = ref<number[]>([])
|
||||||
|
//本页数据
|
||||||
|
const checkedPageIds = ref<number[]>([])
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -234,8 +280,11 @@ const getList = async () => {
|
|||||||
queryParams.createTimeStart = queryParams.createTime?.[0]
|
queryParams.createTimeStart = queryParams.createTime?.[0]
|
||||||
queryParams.createTimeEnd = queryParams.createTime?.[1]
|
queryParams.createTimeEnd = queryParams.createTime?.[1]
|
||||||
const data = await EmployeeBigBrotherApi.getEmployeeBigBrotherPage(queryParams)
|
const data = await EmployeeBigBrotherApi.getEmployeeBigBrotherPage(queryParams)
|
||||||
|
|
||||||
list.value = data.list
|
list.value = data.list
|
||||||
total.value = data.total
|
total.value = data.total
|
||||||
|
checkedPageIds.value = data.list.map((row) => row.id)
|
||||||
|
console.log(checkedPageIds.value)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@@ -246,6 +295,61 @@ const handleQuery = () => {
|
|||||||
queryParams.pageNo = 1
|
queryParams.pageNo = 1
|
||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDeleteList = async () => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await EmployeeBigBrotherApi.deleteEmployeeBigBrotherList(checkedIds.value)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除本页按钮操作 */
|
||||||
|
const handleDeletePageList = async () => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await EmployeeBigBrotherApi.deleteEmployeeBigBrotherList(checkedPageIds.value)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
// 格式化时间戳
|
||||||
|
function formatTimestamp(milliseconds) {
|
||||||
|
const date = new Date(milliseconds); // 直接使用毫秒级时间戳
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
import { useDictStore } from '@/store/modules/dict' // 如果你项目里有字典 store
|
||||||
|
const dictStore = useDictStore?.() // 有就用;没有的话把 dictStore 相关行删掉
|
||||||
|
// 统一用字符串比较,自动识别并翻译 i18n key
|
||||||
|
function dictLabelI18n(type: string, val: any) {
|
||||||
|
const v = val == null ? '' : String(val)
|
||||||
|
|
||||||
|
// 优先从 store 取;若没有,就从你现有的工具取(getIntDictOptions / getStrDictOptions)
|
||||||
|
const opts =
|
||||||
|
(dictStore?.getDictOptions?.(type) as any[]) ||
|
||||||
|
getIntDictOptions(type) ||
|
||||||
|
getStrDictOptions(type) ||
|
||||||
|
[]
|
||||||
|
|
||||||
|
const hit = opts.find(o => String(o.value) === v)
|
||||||
|
const label = hit?.label ?? ''
|
||||||
|
// 形如 a.b 或包含点号的,大概率是 i18n key,则用 t() 翻
|
||||||
|
return label && label.includes('.') ? t(label) : label
|
||||||
|
}
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
@@ -296,7 +400,7 @@ const handleExport = async () => {
|
|||||||
|
|
||||||
//分配按钮操作
|
//分配按钮操作
|
||||||
const handleSelectionChange = (val) => {
|
const handleSelectionChange = (val) => {
|
||||||
|
checkedIds.value = val.map((row) => row.id)
|
||||||
selectBigList.value = val
|
selectBigList.value = val
|
||||||
console.log(selectBigList.value)
|
console.log(selectBigList.value)
|
||||||
}
|
}
|
||||||
@@ -389,9 +493,49 @@ function exportAi(type) {
|
|||||||
|
|
||||||
copyToClipboard(data)
|
copyToClipboard(data)
|
||||||
}
|
}
|
||||||
|
const isMobile = ref(window.innerWidth <= 768)
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
getAllocationList();
|
getAllocationList();
|
||||||
|
//实时监听实际还是电脑
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if ((window.innerWidth <= 768) != isMobile.value) {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
isMobile.value = window.innerWidth <= 768
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.mobile-card {
|
||||||
|
background: #fff;
|
||||||
|
margin: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-row {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-row b {
|
||||||
|
color: #555;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="操作状态" prop="operationStatus">
|
<el-form-item label="操作状态" prop="operationStatus">
|
||||||
<el-select v-model="formData.operationStatus" placeholder="请选择状态" clearable class="!w-240px">
|
<el-select v-model="formData.operationStatus" placeholder="请选择状态" clearable class="!w-240px">
|
||||||
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value" :label="dict.label"
|
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value"
|
||||||
:value="dict.value" />
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<el-input v-model="queryParams.fllowernumMax" :placeholder="$t('employee.max')" clearable
|
<el-input v-model="queryParams.fllowernumMax" :placeholder="$t('employee.max')" clearable
|
||||||
@keyup.enter="handleQuery" class="!w-115px" />
|
@keyup.enter="handleQuery" class="!w-115px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('newHosts.hostsCountry')" prop="region">
|
<el-form-item :label="t('newHosts.hostsCountry')" prop="region">
|
||||||
<el-select v-model="queryParams.region" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
<el-select v-model="queryParams.region" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
||||||
class="!w-240px" @change="changeCountry(queryParams.region)">
|
class="!w-240px" @change="changeCountry(queryParams.region)">
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
:label="$t(dict.label)" :value="dict.value" />
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('newHosts.hostsCountryinfo')" prop="country">
|
<el-form-item :label="t('newHosts.hostsCountryinfo')" prop="country">
|
||||||
<el-select v-model="queryParams.country" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
<el-select v-model="queryParams.country" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
||||||
class="!w-240px">
|
class="!w-240px">
|
||||||
@@ -57,14 +59,20 @@
|
|||||||
:value="dict.countryName" />
|
:value="dict.countryName" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('employee.hostsKind')" prop="hostsKind">
|
<el-form-item :label="$t('employee.hostsKind')" prop="hostsKind">
|
||||||
<el-input v-model="queryParams.hostsKind" :placeholder="$t('employee.placeHostsKind')" clearable
|
<el-select v-model="queryParams.hostsKind" :placeholder="t('newHosts.placeHostsKind')" clearable
|
||||||
@keyup.enter="handleQuery" class="!w-240px" />
|
class="!w-240px" @change="changeCountry(queryParams.hostsKind)">
|
||||||
|
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.HOSTS_KIND)" :key="dict.value"
|
||||||
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('employee.createTime')" prop="createTime">
|
<el-form-item :label="$t('employee.createTime')" prop="createTime">
|
||||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
||||||
class="!w-240px" />
|
class="!w-240px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('employee.updataTime')" prop="updataTime">
|
<el-form-item :label="$t('employee.updataTime')" prop="updataTime">
|
||||||
<el-date-picker v-model="queryParams.updateTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
<el-date-picker v-model="queryParams.updateTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
||||||
class="!w-240px" />
|
class="!w-240px" />
|
||||||
@@ -95,7 +103,7 @@
|
|||||||
<el-select v-model="queryParams.operationStatus" :placeholder="$t('employee.placeOperationStatus')"
|
<el-select v-model="queryParams.operationStatus" :placeholder="$t('employee.placeOperationStatus')"
|
||||||
clearable class="!w-240px">
|
clearable class="!w-240px">
|
||||||
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value"
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value"
|
||||||
:label="dict.label" :value="dict.value" />
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('newHosts.sortName')" prop="sortName">
|
<el-form-item :label="t('newHosts.sortName')" prop="sortName">
|
||||||
@@ -126,29 +134,33 @@
|
|||||||
<!-- <el-button type="success" plain @click="handleExport" v-hasPermi="['server:new-hosts:export']">
|
<!-- <el-button type="success" plain @click="handleExport" v-hasPermi="['server:new-hosts:export']">
|
||||||
<Icon icon="ep:download" class="mr-5px" /> {{ t('newHosts.export') }}
|
<Icon icon="ep:download" class="mr-5px" /> {{ t('newHosts.export') }}
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
<el-button v-if="!isMobile" type="danger" @click="handleDeleteList">
|
<el-button v-if="!isMobile" :disabled="checkedIds.length === 0" type="danger" @click="handleDeleteList">
|
||||||
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else type="danger" @click="handleDeletePageList">
|
<el-button v-else type="danger" @click="handleDeletePageList">
|
||||||
<Icon icon="ep:delete" class="mr-5px" /> 删除本页
|
<Icon icon="ep:delete" class="mr-5px" /> 删除本页
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-switch style="margin-left: 20px;" v-model="isUpdata" />复制且转化
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<div class="center-justify" style="margin-top: -15px;">
|
|
||||||
<el-button type="primary" @click="isShowSearch = !isShowSearch">{{ isShowSearch ? $t('employee.showSearch') :
|
|
||||||
$t('employee.hideSearch') }}</el-button>
|
|
||||||
<div v-if="isMobile">
|
|
||||||
<el-switch v-model="simpleModel" />
|
|
||||||
简化列表
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 列表区域 -->
|
<!-- 列表区域 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
|
<div style="display: flex;align-items: center;gap: 20px;">
|
||||||
|
<el-switch v-model="isMobile" size="large" active-text="卡片" inactive-text="列表" />
|
||||||
|
|
||||||
|
<el-switch v-model="Simplify" size="large" active-text="简表" inactive-text="全表" />
|
||||||
|
|
||||||
|
<div class="center-justify">
|
||||||
|
<el-button type="primary" @click="isShowSearch = !isShowSearch">{{ isShowSearch ? $t('employee.showSearch') :
|
||||||
|
$t('employee.hideSearch') }}</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ✅ PC 端使用 table -->
|
<!-- ✅ PC 端使用 table -->
|
||||||
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
||||||
@selection-change="handleSelectionChange">
|
@selection-change="handleSelectionChange">
|
||||||
@@ -160,14 +172,17 @@
|
|||||||
{{ scope.row.hostsId }}</div>
|
{{ scope.row.hostsId }}</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column align="center" prop="hostsId" width="75">
|
<el-table-column align="center" prop="hostsId" width="75">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-link type="primary" @click="handleCopy(scope.row.hostsId)">复制</el-link>
|
<el-link type="primary" @click="handleCopy(scope.row.hostsId, scope.row)">复制</el-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.hostsLevel')" align="center" prop="hostsLevel" />
|
|
||||||
<el-table-column :label="t('newHosts.invitationType')" align="center" prop="invitationType" width="200">
|
<el-table-column v-if="!Simplify" :label="$t('employee.hostsLevel')" align="center" prop="hostsLevel" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="t('newHosts.invitationType')" align="center" prop="invitationType"
|
||||||
|
width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag size="small" :type="scope.row.invitationType == 1 ? 'primary' : 'warning'">
|
<el-tag size="small" :type="scope.row.invitationType == 1 ? 'primary' : 'warning'">
|
||||||
{{ dictLabelI18n(DICT_TYPE.HOSTS_INVITATION_TYPE, scope.row.invitationType) || '-' }}
|
{{ dictLabelI18n(DICT_TYPE.HOSTS_INVITATION_TYPE, scope.row.invitationType) || '-' }}
|
||||||
@@ -175,36 +190,50 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="uid" align="center" prop="uid" />
|
<el-table-column v-if="!Simplify" label="uid" align="center" prop="uid" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.hostsCoins')" align="center" prop="hostsCoins" />
|
||||||
|
|
||||||
<el-table-column :label="$t('employee.hostsCoins')" align="center" prop="hostsCoins" />
|
|
||||||
<!-- <el-table-column :label="$t('employee.invitationType')" align="center" prop="invitationType" /> -->
|
<!-- <el-table-column :label="$t('employee.invitationType')" align="center" prop="invitationType" /> -->
|
||||||
<el-table-column :label="$t('employee.onlineFans')" align="center" prop="onlineFans" />
|
<el-table-column v-if="!Simplify" :label="$t('employee.onlineFans')" align="center" prop="onlineFans" />
|
||||||
<el-table-column :label="$t('employee.fans')" align="center" prop="fans" />
|
|
||||||
<el-table-column :label="$t('employee.fllowernum')" align="center" prop="fllowernum" />
|
<el-table-column v-if="!Simplify" :label="$t('employee.fans')" align="center" prop="fans" />
|
||||||
<el-table-column :label="$t('employee.yesterdayCoins')" align="center" prop="yesterdayCoins" />
|
|
||||||
<el-table-column :label="$t('employee.hostsCountry')" align="center" prop="country">
|
<el-table-column v-if="!Simplify" :label="$t('employee.fllowernum')" align="center" prop="fllowernum" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.yesterdayCoins')" align="center" prop="yesterdayCoins" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.hostsCountry')" align="center" prop="country">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ t('newHosts.min') == '最小值' ? scope.row.country : scope.row.countryEng }}
|
{{ t('newHosts.min') == '最小值' ? scope.row.country : scope.row.countryEng }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.hostsKind')" align="center" prop="hostsKind" />
|
|
||||||
<el-table-column :label="$t('employee.remark')" align="center" prop="remake" />
|
<el-table-column v-if="!Simplify" :label="$t('employee.hostsKind')" align="center" prop="hostsKind" />
|
||||||
<el-table-column :label="$t('employee.flag')" align="center" prop="flag">
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.remark')" align="center" prop="remake" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.flag')" align="center" prop="flag">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.FLAG_TYPE" :value="scope.row.flag" />
|
<dict-tag :type="DICT_TYPE.FLAG_TYPE" :value="scope.row.flag" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.OPERATION_STATE" :value="scope.row.operationStatus" />
|
<el-tag size="small" :type="scope.row.operationStatus == 1 ? 'primary' : 'warning'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.OPERATION_STATE, scope.row.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.createTime')" align="center" prop="createTime" :formatter="dateFormatter"
|
|
||||||
width="180px" />
|
<el-table-column v-if="!Simplify" :label="$t('employee.createTime')" align="center" prop="createTime"
|
||||||
<el-table-column :label="$t('employee.updateTime')" align="center" prop="updateTime" :formatter="dateFormatter"
|
:formatter="dateFormatter" width="180px" />
|
||||||
width="180px" />
|
|
||||||
<el-table-column :label="$t('employee.action')" align="center" min-width="120px">
|
<el-table-column v-if="!Simplify" :label="$t('employee.updateTime')" align="center" prop="updateTime"
|
||||||
|
:formatter="dateFormatter" width="180px" />
|
||||||
|
|
||||||
|
<el-table-column v-if="!Simplify" :label="$t('employee.action')" align="center" min-width="120px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="openForm('update', scope.row.id)">{{ $t('employee.edit') }}</el-button>
|
<el-button link type="primary" @click="openForm('update', scope.row.id)">{{ $t('employee.edit') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -226,7 +255,9 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.OPERATION_STATE" :value="scope.row.operationStatus" />
|
<el-tag size="small" :type="scope.row.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.OPERATION_STATE, scope.row.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.remark')" align="center" prop="remake" />
|
<el-table-column :label="$t('employee.remark')" align="center" prop="remake" />
|
||||||
@@ -249,7 +280,7 @@
|
|||||||
<div class="card-row" style="color:green;">
|
<div class="card-row" style="color:green;">
|
||||||
<b>{{ $t('employee.hostsId') }}:</b><span @click="openHtml(item, item.hostsId)"
|
<b>{{ $t('employee.hostsId') }}:</b><span @click="openHtml(item, item.hostsId)"
|
||||||
style=" text-decoration: underline;margin-right: 50px;">{{ item.hostsId }}</span>
|
style=" text-decoration: underline;margin-right: 50px;">{{ item.hostsId }}</span>
|
||||||
<el-link @click="handleCopy(item.hostsId)" type="primary">复制id</el-link>
|
<el-link @click="handleCopy(item.hostsId, item)" type="primary">复制id</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="card-row"><b>{{ $t('employee.userId') }}:</b>{{ item.userId }}</div> -->
|
<!-- <div class="card-row"><b>{{ $t('employee.userId') }}:</b>{{ item.userId }}</div> -->
|
||||||
@@ -264,7 +295,9 @@
|
|||||||
:value="item.flag" />
|
:value="item.flag" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-row"><b>{{ $t('employee.operationStatus') }}:</b>
|
<div class="card-row"><b>{{ $t('employee.operationStatus') }}:</b>
|
||||||
<dict-tag :type="DICT_TYPE.OPERATION_STATE" :value="item.operationStatus" />
|
<el-tag size="small" :type="item.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.OPERATION_STATE, item.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-row"><b>{{ $t('employee.createTime') }}:</b>{{ formatTimestamp(item.createTime) }}</div>
|
<div class="card-row"><b>{{ $t('employee.createTime') }}:</b>{{ formatTimestamp(item.createTime) }}</div>
|
||||||
<div class="card-row"><b>{{ $t('employee.updateTime') }}:</b>{{ formatTimestamp(item.updateTime) }}</div>
|
<div class="card-row"><b>{{ $t('employee.updateTime') }}:</b>{{ formatTimestamp(item.updateTime) }}</div>
|
||||||
@@ -278,7 +311,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MobilePagination v-if="isMobile" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
<MobilePagination v-if="isMobile" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
:total="total" :page-sizes="[10, 20, 30, 50]" @size-change="getList()" @load="getList()" @loadPre="getList()" />
|
:total="total" :page-sizes="[10, 20, 30, 50]" @size-change="getList()" @load="getList()" @load-pre="getList()" />
|
||||||
|
|
||||||
<!-- ✅ PC 显示分页,移动端隐藏 -->
|
<!-- ✅ PC 显示分页,移动端隐藏 -->
|
||||||
<Pagination v-if="!isMobile" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
<Pagination v-if="!isMobile" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
@@ -303,6 +336,7 @@ import MobilePagination from '@/components/MobilePagination.vue'
|
|||||||
import { useDictStore } from '@/store/modules/dict' // 如果你项目里有字典 store
|
import { useDictStore } from '@/store/modules/dict' // 如果你项目里有字典 store
|
||||||
const dictStore = useDictStore?.() // 有就用;没有的话把 dictStore 相关行删掉
|
const dictStore = useDictStore?.() // 有就用;没有的话把 dictStore 相关行删掉
|
||||||
|
|
||||||
|
let isUpdata = ref(false)
|
||||||
// 统一用字符串比较,自动识别并翻译 i18n key
|
// 统一用字符串比较,自动识别并翻译 i18n key
|
||||||
function dictLabelI18n(type: string, val: any) {
|
function dictLabelI18n(type: string, val: any) {
|
||||||
const v = val == null ? '' : String(val)
|
const v = val == null ? '' : String(val)
|
||||||
@@ -611,7 +645,7 @@ function AllocationFun() {
|
|||||||
console.log(selectHostList.value)
|
console.log(selectHostList.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCopy(text) {
|
function handleCopy(text, data) {
|
||||||
// fallback 兼容方案
|
// fallback 兼容方案
|
||||||
const textarea = document.createElement('textarea')
|
const textarea = document.createElement('textarea')
|
||||||
textarea.value = text
|
textarea.value = text
|
||||||
@@ -623,6 +657,12 @@ function handleCopy(text) {
|
|||||||
const result = document.execCommand('copy')
|
const result = document.execCommand('copy')
|
||||||
if (result) {
|
if (result) {
|
||||||
ElMessage.success('✅复制成功 ')
|
ElMessage.success('✅复制成功 ')
|
||||||
|
if (isUpdata.value) {
|
||||||
|
EmployeeHostsApi.updateEmployeeHosts({ id: data.id, userId: data.userId, hostsId: data.hostsId, operationStatus: 1 }).then(res => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('❌复制失败')
|
ElMessage.error('❌复制失败')
|
||||||
}
|
}
|
||||||
@@ -636,6 +676,8 @@ function handleCopy(text) {
|
|||||||
|
|
||||||
const isMobile = ref(window.innerWidth <= 768)
|
const isMobile = ref(window.innerWidth <= 768)
|
||||||
|
|
||||||
|
const Simplify = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
// getAllocationList()
|
// getAllocationList()
|
||||||
|
|||||||
@@ -121,7 +121,9 @@
|
|||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-table v-loading="loading" :data="list" :stripe="true" @selection-change="handleSelectionChange">
|
<el-switch v-model="isMobile" size="large" active-text="卡片" inactive-text="列表" />
|
||||||
|
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="大哥的用户id" align="center" prop="displayId">
|
<el-table-column label="大哥的用户id" align="center" prop="displayId">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -160,8 +162,40 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<div v-else>
|
||||||
|
<div v-for="(item, index) in list" :key="index" class="mobile-card">
|
||||||
|
<div class="card-row" style="color:green;">
|
||||||
|
<b>大哥的用户id:</b><span @click="openHtml(item, item.displayId)"
|
||||||
|
style=" text-decoration: underline;margin-right: 50px;">{{ item.displayId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-row"><b>大哥的uid:</b>{{ item.userIdStr }}</div>
|
||||||
|
<div class="card-row"><b>大哥的用户昵称:</b>{{ item.nickname }}</div>
|
||||||
|
<div class="card-row"><b>大哥的等级:</b>{{ item.level }}</div>
|
||||||
|
<div class="card-row"><b>粉丝团等级:</b>{{ item.fansLevel }}</div>
|
||||||
|
<div class="card-row"><b>大哥打赏的金币:</b>{{ item.hostcoins }}</div>
|
||||||
|
<div class="card-row"><b>大哥的粉丝数:</b>{{ item.followerCount }}</div>
|
||||||
|
<div class="card-row"><b>大哥的关注数:</b>{{ item.followingCount }}</div>
|
||||||
|
<div class="card-row"><b>大哥所在的地区:</b>{{ item.region }}</div>
|
||||||
|
<div class="card-row"><b>大哥打赏的历史最高金币:</b>{{ item.historicHighCoins }}</div>
|
||||||
|
<div class="card-row"><b>大哥历史打赏金币总和:</b>{{ item.totalGiftCoins }}</div>
|
||||||
|
<div class="card-row" style="color:green;">
|
||||||
|
<b>大哥所在的直播间的主播id:</b><span @click="openHtmlbig(item.hostDisplayId)"
|
||||||
|
style=" text-decoration: underline;margin-right: 50px;">{{ item.hostDisplayId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-row"><b>创建时间:</b>{{ formatTimestamp(item.createTime) }}</div>
|
||||||
|
<div class="card-row"><b>是否洽谈:</b>
|
||||||
|
<el-tag size="small" :type="item.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.BIGBIOTHER_NEGOTIATION, item.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<MobilePagination v-if="isMobile" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
:total="total" :page-sizes="[10, 20, 30, 50]" @size-change="getList()" @load="getList()" @load-pre="getList()" />
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
<Pagination v-if="!isMobile" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
@pagination="getList" />
|
@pagination="getList" />
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
<el-dialog v-model="dialogAllocation" :title="t('newHosts.allocationUser')">
|
<el-dialog v-model="dialogAllocation" :title="t('newHosts.allocationUser')">
|
||||||
@@ -273,6 +307,37 @@ const resetQuery = () => {
|
|||||||
handleQuery()
|
handleQuery()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 格式化时间戳
|
||||||
|
function formatTimestamp(milliseconds) {
|
||||||
|
const date = new Date(milliseconds); // 直接使用毫秒级时间戳
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
import { useDictStore } from '@/store/modules/dict' // 如果你项目里有字典 store
|
||||||
|
const dictStore = useDictStore?.() // 有就用;没有的话把 dictStore 相关行删掉
|
||||||
|
// 统一用字符串比较,自动识别并翻译 i18n key
|
||||||
|
function dictLabelI18n(type: string, val: any) {
|
||||||
|
const v = val == null ? '' : String(val)
|
||||||
|
|
||||||
|
// 优先从 store 取;若没有,就从你现有的工具取(getIntDictOptions / getStrDictOptions)
|
||||||
|
const opts =
|
||||||
|
(dictStore?.getDictOptions?.(type) as any[]) ||
|
||||||
|
getIntDictOptions(type) ||
|
||||||
|
getStrDictOptions(type) ||
|
||||||
|
[]
|
||||||
|
|
||||||
|
const hit = opts.find(o => String(o.value) === v)
|
||||||
|
const label = hit?.label ?? ''
|
||||||
|
// 形如 a.b 或包含点号的,大概率是 i18n key,则用 t() 翻
|
||||||
|
return label && label.includes('.') ? t(label) : label
|
||||||
|
}
|
||||||
|
|
||||||
/** 添加/修改操作 */
|
/** 添加/修改操作 */
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const openForm = (type: string, id?: number) => {
|
const openForm = (type: string, id?: number) => {
|
||||||
@@ -428,9 +493,50 @@ function exportAi(type) {
|
|||||||
|
|
||||||
copyToClipboard(data)
|
copyToClipboard(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isMobile = ref(window.innerWidth <= 768) //是否是移动端
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
getAllocationList();
|
getAllocationList();
|
||||||
|
//实时监听实际还是电脑
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if ((window.innerWidth <= 768) != isMobile.value) {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
isMobile.value = window.innerWidth <= 768
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.mobile-card {
|
||||||
|
background: #fff;
|
||||||
|
margin: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-row {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-row b {
|
||||||
|
color: #555;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<el-select v-model="queryParams.region" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
<el-select v-model="queryParams.region" :placeholder="t('newHosts.placeHostsCountry')" clearable
|
||||||
class="!w-240px" @change="changeCountry(queryParams.region)">
|
class="!w-240px" @change="changeCountry(queryParams.region)">
|
||||||
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.COUNTRY_GROUP)" :key="dict.value"
|
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.COUNTRY_GROUP)" :key="dict.value"
|
||||||
:label="dict.label" :value="dict.value" />
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('newHosts.hostsCountryinfo')" prop="country">
|
<el-form-item :label="t('newHosts.hostsCountryinfo')" prop="country">
|
||||||
@@ -57,10 +57,15 @@
|
|||||||
:value="dict.countryName" />
|
:value="dict.countryName" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('employee.hostsKind')" prop="hostsKind">
|
<el-form-item :label="$t('employee.hostsKind')" prop="hostsKind">
|
||||||
<el-input v-model="queryParams.hostsKind" :placeholder="$t('employee.placeHostsKind')" clearable
|
<el-select v-model="queryParams.hostsKind" :placeholder="t('newHosts.placeHostsKind')" clearable
|
||||||
@keyup.enter="handleQuery" class="!w-240px" />
|
class="!w-240px" @change="changeCountry(queryParams.hostsKind)">
|
||||||
|
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.HOSTS_KIND)" :key="dict.value"
|
||||||
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('employee.createTime')" prop="createTime">
|
<el-form-item :label="$t('employee.createTime')" prop="createTime">
|
||||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
||||||
class="!w-240px" />
|
class="!w-240px" />
|
||||||
@@ -90,7 +95,7 @@
|
|||||||
<el-select v-model="queryParams.operationStatus" :placeholder="$t('employee.placeOperationStatus')"
|
<el-select v-model="queryParams.operationStatus" :placeholder="$t('employee.placeOperationStatus')"
|
||||||
clearable class="!w-240px">
|
clearable class="!w-240px">
|
||||||
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value"
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.OPERATION_STATE)" :key="dict.value"
|
||||||
:label="dict.label" :value="dict.value" />
|
:label="$t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('newHosts.sortName')" prop="sortName">
|
<el-form-item :label="t('newHosts.sortName')" prop="sortName">
|
||||||
@@ -105,6 +110,13 @@
|
|||||||
:label="t(dict.label)" :value="dict.value" />
|
:label="t(dict.label)" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('newHosts.isDelete')" prop="isDelete">
|
||||||
|
<el-select v-model="queryParams.isDelete" :placeholder="t('newHosts.isDelete')" clearable class="!w-240px">
|
||||||
|
<el-option label="全部" :value="3" />
|
||||||
|
<el-option label="否" :value="0" />
|
||||||
|
<el-option label="是" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button @click="handleQuery">
|
<el-button @click="handleQuery">
|
||||||
<Icon icon="ep:search" class="mr-5px" /> {{ $t('employee.search') }}
|
<Icon icon="ep:search" class="mr-5px" /> {{ $t('employee.search') }}
|
||||||
@@ -125,13 +137,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<div class="center-justify" style="margin-top: -15px;">
|
<!-- 列表区域 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px;">
|
||||||
|
<div class="center-justify">
|
||||||
<el-button type="primary" @click="isShowSearch = !isShowSearch">{{ isShowSearch ? $t('employee.showSearch') :
|
<el-button type="primary" @click="isShowSearch = !isShowSearch">{{ isShowSearch ? $t('employee.showSearch') :
|
||||||
$t('employee.hideSearch') }}</el-button>
|
$t('employee.hideSearch') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<el-switch v-model="isMobile" size="large" active-text="卡片" inactive-text="列表" />
|
||||||
<!-- 列表区域 -->
|
</div>
|
||||||
<ContentWrap>
|
|
||||||
<!-- ✅ PC 端使用 table -->
|
<!-- ✅ PC 端使用 table -->
|
||||||
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
<el-table v-if="!isMobile" v-loading="loading" :data="list" :stripe="true"
|
||||||
@selection-change="handleSelectionChange">
|
@selection-change="handleSelectionChange">
|
||||||
@@ -184,7 +198,9 @@
|
|||||||
|
|
||||||
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
<el-table-column :label="$t('employee.operationStatus')" align="center" prop="operationStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.OPERATION_STATE" :value="scope.row.operationStatus" />
|
<el-tag size="small" :type="scope.row.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.OPERATION_STATE, scope.row.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('employee.createTime')" align="center" prop="createTime" :formatter="dateFormatter"
|
<el-table-column :label="$t('employee.createTime')" align="center" prop="createTime" :formatter="dateFormatter"
|
||||||
@@ -221,7 +237,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-row"><b>{{ $t('employee.operationStatus') }}:</b>
|
<div class="card-row"><b>{{ $t('employee.operationStatus') }}:</b>
|
||||||
<dict-tag :type="DICT_TYPE.OPERATION_STATE" :value="item.operationStatus" />
|
<el-tag size="small" :type="item.operationStatus == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.OPERATION_STATE, item.operationStatus) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-row"><b>{{ $t('employee.createTime') }}:</b>{{ formatTimestamp(item.createTime) }}</div>
|
<div class="card-row"><b>{{ $t('employee.createTime') }}:</b>{{ formatTimestamp(item.createTime) }}</div>
|
||||||
<div class="card-row"><b>{{ $t('employee.updateTime') }}:</b>{{ formatTimestamp(item.updateTime) }}</div>
|
<div class="card-row"><b>{{ $t('employee.updateTime') }}:</b>{{ formatTimestamp(item.updateTime) }}</div>
|
||||||
@@ -232,7 +250,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MobilePagination v-if="isMobile" :page="queryParams.pageNo" :limit="queryParams.pageSize" :total="total"
|
<MobilePagination v-if="isMobile" :page="queryParams.pageNo" :limit="queryParams.pageSize" :total="total"
|
||||||
@update:page="val => queryParams.pageNo = val" @load="loadList" @loadPre="loadpreviousList" />
|
@update:page="val => queryParams.pageNo = val" @load="loadList" @load-pre="loadpreviousList" />
|
||||||
|
|
||||||
|
|
||||||
<!-- ✅ PC 显示分页,移动端隐藏 -->
|
<!-- ✅ PC 显示分页,移动端隐藏 -->
|
||||||
@@ -328,6 +346,7 @@ const queryParams = reactive({
|
|||||||
createTime: [],
|
createTime: [],
|
||||||
userId: undefined,
|
userId: undefined,
|
||||||
operationStatus: undefined,
|
operationStatus: undefined,
|
||||||
|
isDelete: 0,
|
||||||
})
|
})
|
||||||
const queryFormRef = ref() // 搜索的表单
|
const queryFormRef = ref() // 搜索的表单
|
||||||
const exportLoading = ref(false) // 导出的加载中
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
|||||||
@@ -89,17 +89,31 @@
|
|||||||
:value="dict.countryName" />
|
:value="dict.countryName" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('newHosts.hostsKind')" prop="hostsKind">
|
<el-form-item :label="t('newHosts.hostsKind')" prop="hostsKind">
|
||||||
<el-input v-model="queryParams.hostsKind" :placeholder="t('newHosts.placeHostsKind')" clearable
|
<el-select v-model="queryParams.hostsKind" :placeholder="t('newHosts.placeHostsKind')" clearable
|
||||||
@keyup.enter="handleQuery" class="!w-240px" />
|
class="!w-240px" @change="changeCountry(queryParams.hostsKind)">
|
||||||
</el-form-item>
|
<el-option v-for="dict in getStrDictOptions(DICT_TYPE.HOSTS_KIND)" :key="dict.value" :label="$t(dict.label)"
|
||||||
<el-form-item :label="t('newHosts.isAssigned')" prop="isAssigned">
|
|
||||||
<el-select v-model="queryParams.isAssigned" :placeholder="t('newHosts.placeIsAssigned')" clearable
|
|
||||||
class="!w-240px">
|
|
||||||
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.INT_TRUE_FLASE)" :key="dict.value" :label="dict.label"
|
|
||||||
:value="dict.value" />
|
:value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('newHosts.isAssigned')" prop="isAssigned">
|
||||||
|
<el-select v-model="queryParams.isAssigned" :placeholder="t('newHosts.placeIsAssigned')" clearable
|
||||||
|
class="!w-240px">
|
||||||
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.INT_TRUE_FLASE)" :key="dict.value"
|
||||||
|
:label="t(dict.label)" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('newHosts.aiOperation')" prop="aiOperation">
|
||||||
|
<el-select v-model="queryParams.aiOperation" :placeholder="t('newHosts.placeaiOperation')" clearable
|
||||||
|
class="!w-240px">
|
||||||
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.INT_TRUE_FLASE)" :key="dict.value"
|
||||||
|
:label="t(dict.label)" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('newHosts.createTime')" prop="createTime">
|
<el-form-item :label="t('newHosts.createTime')" prop="createTime">
|
||||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="date"
|
||||||
class="!w-240px" />
|
class="!w-240px" />
|
||||||
@@ -159,7 +173,7 @@
|
|||||||
<Icon icon="ep:copy-document" class="mr-5px" /> {{ $t('employee.exportAi') }}
|
<Icon icon="ep:copy-document" class="mr-5px" /> {{ $t('employee.exportAi') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="danger" plain :disabled="checkedIds.length === 0" @click="handleDeleteBatch"
|
<el-button type="danger" plain :disabled="checkedIds.length === 0" @click="handleDeleteBatch"
|
||||||
v-hasPermi="['system:post:delete']">
|
v-hasPermi="['server:new-hosts:delete']">
|
||||||
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -179,7 +193,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="t('newHosts.hostsLevel')" sortable align="center" prop="hostsLevel" />
|
<el-table-column :label="t('newHosts.hostsLevel')" sortable align="center" prop="hostsLevel" />
|
||||||
|
|
||||||
<el-table-column :label="t('newHosts.invitationType')" align="center" prop="invitationType" width="200">
|
<el-table-column :label="t('newHosts.invitationType')" align="center" prop="invitationType">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag size="small" :type="scope.row.invitationType == 1 ? 'primary' : 'warning'">
|
<el-tag size="small" :type="scope.row.invitationType == 1 ? 'primary' : 'warning'">
|
||||||
{{ dictLabelI18n(DICT_TYPE.HOSTS_INVITATION_TYPE, scope.row.invitationType) || '-' }}
|
{{ dictLabelI18n(DICT_TYPE.HOSTS_INVITATION_TYPE, scope.row.invitationType) || '-' }}
|
||||||
@@ -203,9 +217,19 @@
|
|||||||
<el-table-column :label="t('newHosts.hostsKind')" align="center" prop="hostsKind" />
|
<el-table-column :label="t('newHosts.hostsKind')" align="center" prop="hostsKind" />
|
||||||
<el-table-column :label="t('newHosts.isAssigned')" align="center" prop="isAssigned">
|
<el-table-column :label="t('newHosts.isAssigned')" align="center" prop="isAssigned">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.INT_TRUE_FLASE" :value="scope.row.isAssigned" />
|
<el-tag size="small" :type="scope.row.isAssigned == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.INT_TRUE_FLASE, scope.row.isAssigned) || '-' }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="AI介入" align="center" prop="aiOperation">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag size="small" :type="scope.row.aiOperation == 1 ? 'success' : 'info'">
|
||||||
|
{{ dictLabelI18n(DICT_TYPE.INT_TRUE_FLASE, scope.row.aiOperation) || '-' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column :label="t('newHosts.createTime')" align="center" prop="createTime" :formatter="dateFormatter"
|
<el-table-column :label="t('newHosts.createTime')" align="center" prop="createTime" :formatter="dateFormatter"
|
||||||
width="180px" />
|
width="180px" />
|
||||||
<!-- <el-table-column label="员工 Id" align="center" prop="userId" /> -->
|
<!-- <el-table-column label="员工 Id" align="center" prop="userId" /> -->
|
||||||
@@ -321,6 +345,7 @@ const queryParams = reactive({
|
|||||||
country: undefined,
|
country: undefined,
|
||||||
hostsKind: undefined,
|
hostsKind: undefined,
|
||||||
isAssigned: undefined,
|
isAssigned: undefined,
|
||||||
|
aiOperation: undefined,
|
||||||
sortName: "createTime", //排序字段
|
sortName: "createTime", //排序字段
|
||||||
sort: 'desc', //排序方式
|
sort: 'desc', //排序方式
|
||||||
createTime: new Date().toISOString().split('T')[0] + ' 00:00:00',
|
createTime: new Date().toISOString().split('T')[0] + ' 00:00:00',
|
||||||
@@ -509,7 +534,6 @@ const handleSelectionChange = (val) => {
|
|||||||
checkedIds.value = val.map((row) => row.id)
|
checkedIds.value = val.map((row) => row.id)
|
||||||
selectHostList.value = val
|
selectHostList.value = val
|
||||||
console.log(selectHostList.value)
|
console.log(selectHostList.value)
|
||||||
console.log(checkedIds.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//分配确认
|
//分配确认
|
||||||
|
|||||||
@@ -1,46 +1,64 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="50%">
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="50%">
|
||||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="120px">
|
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="120px">
|
||||||
|
<!-- ========== 1. 基础信息 ========== -->
|
||||||
|
<el-divider>基础信息</el-divider>
|
||||||
<el-form-item label="租户名" prop="name">
|
<el-form-item label="租户名" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入租户名" />
|
<el-input v-model="formData.name" placeholder="请输入租户名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="租户套餐" prop="packageId">
|
<el-form-item v-if="tenantLevel <= 1" label="租户类型" prop="tenantType">
|
||||||
<el-select v-model="formData.packageId" clearable placeholder="请选择租户套餐">
|
<el-radio-group v-model="formData.tenantType">
|
||||||
<el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id" />
|
<el-radio value="代理">代理</el-radio>
|
||||||
</el-select>
|
<el-radio value="用户">用户</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
|
||||||
<el-form-item label="联系人" prop="contactName">
|
<el-form-item label="联系人" prop="contactName">
|
||||||
<el-input v-model="formData.contactName" placeholder="请输入联系人" />
|
<el-input v-model="formData.contactName" placeholder="请输入联系人" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="联系手机" prop="contactMobile">
|
<el-form-item label="联系手机" prop="contactMobile">
|
||||||
<el-input v-model="formData.contactMobile" placeholder="请输入联系手机" />
|
<el-input v-model="formData.contactMobile" placeholder="请输入联系手机" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="formData.id === undefined" label="用户名称" prop="username">
|
<el-form-item v-if="formData.id === undefined" label="用户名称" prop="username">
|
||||||
<el-input v-model="formData.username" placeholder="请输入用户名称" />
|
<el-input v-model="formData.username" placeholder="请输入用户名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="formData.id === undefined" label="用户密码" prop="password">
|
<el-form-item v-if="formData.id === undefined" label="用户密码" prop="password">
|
||||||
<el-input v-model="formData.password" placeholder="请输入用户密码" show-password type="password" />
|
<el-input v-model="formData.password" placeholder="请输入用户密码" show-password type="password" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="账号额度" prop="accountCount">
|
<el-form-item label="账号额度" prop="accountCount">
|
||||||
<el-input-number v-model="formData.accountCount" :min="0" controls-position="right" placeholder="请输入账号额度" />
|
<el-input-number v-model="formData.accountCount" :min="0" controls-position="right" placeholder="请输入账号额度" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="AI过期时间" prop="aiExpireTime">
|
|
||||||
|
<el-form-item v-if="tenantLevel == 0" label="AI过期时间" prop="aiExpireTime">
|
||||||
<el-date-picker v-model="formData.aiExpireTime" clearable placeholder="请选择AI过期时间" type="date"
|
<el-date-picker v-model="formData.aiExpireTime" clearable placeholder="请选择AI过期时间" type="date"
|
||||||
value-format="x" />
|
value-format="x" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="爬大哥过期时间" prop="brotherExpireTime">
|
|
||||||
|
<el-form-item v-if="tenantLevel == 0" label="爬大哥过期时间" prop="brotherExpireTime">
|
||||||
<el-date-picker v-model="formData.brotherExpireTime" clearable placeholder="请选择爬大哥过期时间" type="date"
|
<el-date-picker v-model="formData.brotherExpireTime" clearable placeholder="请选择爬大哥过期时间" type="date"
|
||||||
value-format="x" />
|
value-format="x" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="爬虫后台过期时间" prop="expireTime">
|
|
||||||
|
<el-form-item v-if="tenantLevel == 0" label="爬虫后台过期时间" prop="expireTime">
|
||||||
<el-date-picker v-model="formData.expireTime" clearable placeholder="请选择过期时间" type="date" value-format="x" />
|
<el-date-picker v-model="formData.expireTime" clearable placeholder="请选择过期时间" type="date" value-format="x" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-else label="爬虫后台过期时间" prop="expireTime">
|
||||||
|
<el-date-picker v-model="formData.expireTime" clearable placeholder="请选择过期时间" disabled type="date"
|
||||||
|
value-format="x" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="绑定域名" prop="website">
|
<el-form-item label="绑定域名" prop="website">
|
||||||
<el-input v-model="formData.website" placeholder="请输入绑定域名" />
|
<el-input v-model="formData.website" placeholder="请输入绑定域名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="租户状态" prop="status">
|
<el-form-item label="租户状态" prop="status">
|
||||||
<el-radio-group v-model="formData.status">
|
<el-radio-group v-model="formData.status">
|
||||||
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">
|
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">
|
||||||
@@ -48,85 +66,168 @@
|
|||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="formType !== 'create'" label="选择用户" prop="userId">
|
<el-form-item v-if="formType !== 'create'" label="选择用户" prop="userId">
|
||||||
<el-select v-model="userData.id" @change="changeUser" clearable placeholder="请选择租户套餐">
|
<el-select v-model="userData.id" @change="changeUser" clearable placeholder="请选择租户用户">
|
||||||
<el-option v-for="item in userList" :key="item.id" :label="item.username" :value="item.id" />
|
<el-option v-for="item in userList" :key="item.id" :label="item.username" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 爬虫:不受限制 -->
|
||||||
<el-form-item v-if="userData.id" label="爬虫" prop="status">
|
<el-form-item v-if="userData.id" label="爬虫" prop="status">
|
||||||
<el-radio-group v-model="userData.crawl">
|
<el-radio-group v-model="userData.crawl">
|
||||||
<el-radio :value="1">开启</el-radio>
|
<el-radio :value="1">开启</el-radio>
|
||||||
<el-radio :value="0">关闭</el-radio>
|
<el-radio :value="0">关闭</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 爬大哥:依赖爬大哥过期时间 -->
|
||||||
<el-form-item v-if="userData.id" label="爬大哥" prop="status">
|
<el-form-item v-if="userData.id" label="爬大哥" prop="status">
|
||||||
<el-radio-group v-model="userData.bigBrother">
|
<el-radio-group v-model="userData.bigBrother" :disabled="!formData.brotherExpireTime">
|
||||||
<el-radio :value="1">开启</el-radio>
|
<el-radio :value="1">开启</el-radio>
|
||||||
<el-radio :value="0">关闭</el-radio>
|
<el-radio :value="0">关闭</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- ai自动化:依赖 AI 过期时间 -->
|
||||||
<el-form-item v-if="userData.id" label="ai自动化" prop="status">
|
<el-form-item v-if="userData.id" label="ai自动化" prop="status">
|
||||||
<el-radio-group v-model="userData.aiChat">
|
<el-radio-group v-model="userData.aiChat" :disabled="!formData.aiExpireTime">
|
||||||
<el-radio :value="1">开启</el-radio>
|
<el-radio :value="1">开启</el-radio>
|
||||||
<el-radio :value="0">关闭</el-radio>
|
<el-radio :value="0">关闭</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- ai回复:依赖 AI 过期时间 -->
|
||||||
|
<el-form-item v-if="userData.id" label="ai回复" prop="status">
|
||||||
|
<el-radio-group v-model="userData.aiReplay" :disabled="!formData.aiExpireTime">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!--WEB回复:依赖 AI 过期时间 -->
|
||||||
|
<el-form-item v-if="userData.id" label="WEB客户端" prop="status">
|
||||||
|
<el-radio-group v-model="userData.webAi" :disabled="!formData.aiExpireTime">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- ========== 2. 套餐 & 权限 ========== -->
|
||||||
|
<el-divider>套餐 & 权限</el-divider>
|
||||||
|
<el-form-item label="租户套餐" prop="packageId">
|
||||||
|
<!-- 顶层租户或无 parentId,走原来的下拉选择 -->
|
||||||
|
<el-select v-if="(formData.parentId == 1 || formData.parentId == null) && tenantLevel == 0"
|
||||||
|
v-model="formData.packageId" clearable placeholder="请选择租户套餐">
|
||||||
|
<el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<!-- 代理租户:用功能勾选 + 套餐单选 -->
|
||||||
|
<div v-else style="display: block;">
|
||||||
|
<!-- 功能勾选:1=爬大哥,2=爬主播,3=AI套餐 -->
|
||||||
|
<el-checkbox-group v-model="selectedFeatures">
|
||||||
|
<el-checkbox :label="1">爬主播</el-checkbox>
|
||||||
|
<el-checkbox :label="2">爬大哥</el-checkbox>
|
||||||
|
<el-checkbox :label="3">AI套餐</el-checkbox>
|
||||||
|
<el-checkbox :label="9">代理</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
|
||||||
|
<!-- 按天数过滤:30 / 180 / 360 天 -->
|
||||||
|
<div style="margin-top: 8px;">
|
||||||
|
<el-radio-group v-model="selectedDays">
|
||||||
|
<el-radio-button :label="30">30 天</el-radio-button>
|
||||||
|
<el-radio-button :label="180">180 天</el-radio-button>
|
||||||
|
<el-radio-button :label="365">365 天</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<!-- 根据勾选结果筛选套餐,用单选框选择一个套餐 -->
|
||||||
|
<div class="package-radio-wrapper">
|
||||||
|
<el-radio-group v-model="formData.packageId">
|
||||||
|
<el-radio-button v-for="item in filteredAgencyPackages" :key="item.id" :label="item.id"
|
||||||
|
class="package-radio">
|
||||||
|
|
||||||
|
{{ item.name }}
|
||||||
|
|
||||||
|
</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
|
||||||
|
<div v-if="filteredAgencyPackages.length === 0" class="package-empty-tip">
|
||||||
|
暂无匹配套餐,请调整上方功能勾选
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch, computed } from 'vue'
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
import * as TenantApi from '@/api/system/tenant'
|
import * as TenantApi from '@/api/system/tenant'
|
||||||
import { getUserByTenant, updateRoleUser } from '@/api/system/user'
|
import { getUserByTenant, updateRoleUser } from '@/api/system/user'
|
||||||
import { CommonStatusEnum } from '@/utils/constants'
|
import { CommonStatusEnum } from '@/utils/constants'
|
||||||
import * as TenantPackageApi from '@/api/system/tenantPackage'
|
import * as TenantPackageApi from '@/api/system/tenantPackage'
|
||||||
import * as userApi from '@/api/system/user'
|
import * as userApi from '@/api/system/user'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
defineOptions({ name: 'SystemTenantForm' })
|
defineOptions({ name: 'SystemTenantForm' })
|
||||||
|
const tenantLevel = ref(3)
|
||||||
const { t } = useI18n() // 国际化
|
TenantApi.getSelfTenantLevel().then(res => {
|
||||||
const message = useMessage() // 消息弹窗
|
tenantLevel.value = res.tenantLevel
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
console.log(tenantLevel.value)
|
||||||
const dialogTitle = ref('') // 弹窗的标题
|
})
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const { t } = useI18n()
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
const message = useMessage()
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const dialogTitle = ref('')
|
||||||
|
const formLoading = ref(false)
|
||||||
|
const formType = ref<'create' | 'update'>('create')
|
||||||
|
const userStore = useUserStore()
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
id: 0,
|
id: 0,
|
||||||
name: undefined,
|
name: undefined as string | undefined,
|
||||||
packageId: undefined,
|
packageId: undefined as number | undefined,
|
||||||
contactName: undefined,
|
contactName: undefined as string | undefined,
|
||||||
contactMobile: undefined,
|
contactMobile: undefined as string | undefined,
|
||||||
accountCount: undefined,
|
accountCount: undefined as number | undefined,
|
||||||
expireTime: undefined,
|
expireTime: Date.now() as number | undefined,
|
||||||
website: undefined,
|
website: undefined as string | undefined,
|
||||||
status: CommonStatusEnum.ENABLE,
|
status: CommonStatusEnum.ENABLE,
|
||||||
// 新增专属
|
username: undefined as string | undefined,
|
||||||
username: undefined,
|
password: undefined as string | undefined,
|
||||||
password: undefined,
|
remark: undefined as string | undefined,
|
||||||
remark: undefined,
|
aiExpireTime: undefined as number | undefined,
|
||||||
aiExpireTime: undefined,
|
brotherExpireTime: undefined as number | undefined,
|
||||||
brotherExpireTime: undefined,
|
tenantType: undefined as number | undefined,
|
||||||
|
parentId: undefined as number | undefined,
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const userData = ref({} as userApi.UserVO)
|
const userData = ref({} as userApi.UserVO)
|
||||||
|
|
||||||
let userList = ref([{
|
const userList = ref<userApi.UserVO[]>([
|
||||||
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
aiChat: 0,
|
aiChat: 0,
|
||||||
bigBrother: 0,
|
bigBrother: 0,
|
||||||
crawl: 0
|
crawl: 0
|
||||||
}])
|
} as any
|
||||||
|
])
|
||||||
|
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
name: [{ required: true, message: '租户名不能为空', trigger: 'blur' }],
|
name: [{ required: true, message: '租户名不能为空', trigger: 'blur' }],
|
||||||
packageId: [{ required: true, message: '租户套餐不能为空', trigger: 'blur' }],
|
packageId: [{ required: true, message: '租户套餐不能为空', trigger: 'blur' }],
|
||||||
contactName: [{ required: true, message: '联系人不能为空', trigger: 'blur' }],
|
contactName: [{ required: true, message: '联系人不能为空', trigger: 'blur' }],
|
||||||
// contactMobile: [
|
|
||||||
// { required: true, message: '手机号不能为空', trigger: 'blur' },
|
|
||||||
// { pattern: /^1[3-9]\d{9}$/, message: '请输入有效的 11 位手机号', trigger: ['blur', 'change'] }
|
|
||||||
// ],
|
|
||||||
status: [{ required: true, message: '租户状态不能为空', trigger: 'blur' }],
|
status: [{ required: true, message: '租户状态不能为空', trigger: 'blur' }],
|
||||||
accountCount: [{ required: true, message: '账号额度不能为空', trigger: 'blur' }],
|
accountCount: [{ required: true, message: '账号额度不能为空', trigger: 'blur' }],
|
||||||
expireTime: [{ required: true, message: '过期时间不能为空', trigger: 'blur' }],
|
expireTime: [{ required: true, message: '过期时间不能为空', trigger: 'blur' }],
|
||||||
@@ -137,46 +238,110 @@ const formRules = reactive({
|
|||||||
],
|
],
|
||||||
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }]
|
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }]
|
||||||
})
|
})
|
||||||
const formRef = ref() // 表单 Ref
|
|
||||||
const packageList = ref([] as TenantPackageApi.TenantPackageVO[]) // 租户套餐
|
const formRef = ref()
|
||||||
|
const packageList = ref([] as TenantPackageApi.TenantPackageVO[])
|
||||||
|
const packageAgencyList = ref([] as TenantPackageApi.TenantPackageVO[])
|
||||||
|
// 代理套餐功能勾选:1=爬大哥,2=爬主播,3=AI套餐
|
||||||
|
const selectedFeatures = ref<number[]>([])
|
||||||
|
// 按套餐天数筛选:30 / 180 / 360(不选则不过滤)
|
||||||
|
const selectedDays = ref<number | null>(null)
|
||||||
|
// 二级代理套餐的 ID
|
||||||
|
const SECOND_AGENT_PACKAGE_ID = 10001
|
||||||
|
// 根据 selectedFeatures + packageAgencyList 计算可选套餐
|
||||||
|
const filteredAgencyPackages = computed(() => {
|
||||||
|
// 1. 根据创建/编辑确定基础套餐列表
|
||||||
|
let list: any[] = []
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
list = packageList.value || []
|
||||||
|
} else {
|
||||||
|
list = packageAgencyList.value || []
|
||||||
|
}
|
||||||
|
if (!list.length) return []
|
||||||
|
|
||||||
|
const selected = selectedFeatures.value
|
||||||
|
|
||||||
|
// 2. 先按功能勾选过滤(保持你原来的逻辑)
|
||||||
|
let result: any[] = []
|
||||||
|
if (!selected.length) {
|
||||||
|
// 一个功能都没勾选时,直接返回全部套餐
|
||||||
|
result = list
|
||||||
|
} else {
|
||||||
|
// 有勾选时才进行过滤
|
||||||
|
result = list.filter((item: any) => {
|
||||||
|
const typeStr = String(item.packageType ?? '')
|
||||||
|
// 要求选中的功能全部包含在 packageType 里
|
||||||
|
// 例如勾选 [1,2] -> 匹配 '12'、'123' 等
|
||||||
|
return selected.every(flag => typeStr.includes(String(flag)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 按天数过滤:item.days === 30 / 180 / 360
|
||||||
|
if (selectedDays.value != null) {
|
||||||
|
result = result.filter((item: any) => item.days === selectedDays.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 再根据租户类型进行限制
|
||||||
|
const tenantType = formData.value.tenantType
|
||||||
|
if (tenantType === '代理') {
|
||||||
|
// 只能选二级代理套餐(10001)
|
||||||
|
result = result.filter(item => item.id === SECOND_AGENT_PACKAGE_ID)
|
||||||
|
} else if (tenantType === '租户') {
|
||||||
|
// 租户不能选二级代理套餐
|
||||||
|
result = result.filter(item => item.id !== SECOND_AGENT_PACKAGE_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: 'create' | 'update', id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = t('action.' + type)
|
dialogTitle.value = t('action.' + type)
|
||||||
formType.value = type
|
formType.value = type
|
||||||
resetForm()
|
resetForm()
|
||||||
// 修改时,设置数据
|
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
|
// 1. 租户基础信息
|
||||||
formData.value = await TenantApi.getTenant(id)
|
formData.value = await TenantApi.getTenant(id)
|
||||||
getUserByTenant(id).then(res => {
|
|
||||||
console.log(res)
|
// 2. 拉取租户用户列表
|
||||||
userList.value = res
|
const res = await getUserByTenant(id)
|
||||||
})
|
userList.value = res || []
|
||||||
|
|
||||||
|
// 3. 默认选中第一个用户(有的话)
|
||||||
|
if (userList.value.length > 0) {
|
||||||
|
userData.value = userList.value[0]
|
||||||
|
; (userData.value as any).tenantId = formData.value.id
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 加载套餐列表
|
|
||||||
|
// 套餐列表
|
||||||
packageList.value = await TenantPackageApi.getTenantPackageList()
|
packageList.value = await TenantPackageApi.getTenantPackageList()
|
||||||
|
if (userStore.getUser.id === 1) {
|
||||||
|
packageAgencyList.value = await TenantPackageApi.getTenantPackageListagency()
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
}
|
||||||
|
defineExpose({ open })
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success'])
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
// 校验表单
|
if (!formRef.value) return
|
||||||
if (!formRef) return
|
|
||||||
const valid = await formRef.value.validate()
|
const valid = await formRef.value.validate()
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
// 提交请求
|
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = formData.value as unknown as TenantApi.TenantVO
|
const data = formData.value as unknown as TenantApi.TenantVO
|
||||||
if (formType.value === 'create') {
|
if (formType.value === 'create') {
|
||||||
//下次更改内容,创建账号 给一个权限 爬大哥和AI
|
|
||||||
await TenantApi.createTenant(data)
|
await TenantApi.createTenant(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
} else {
|
} else {
|
||||||
@@ -185,7 +350,6 @@ const submitForm = async () => {
|
|||||||
message.success(t('common.updateSuccess'))
|
message.success(t('common.updateSuccess'))
|
||||||
}
|
}
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
// 发送操作成功的事件
|
|
||||||
emit('success')
|
emit('success')
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
@@ -195,31 +359,97 @@ const submitForm = async () => {
|
|||||||
/** 重置表单 */
|
/** 重置表单 */
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
id: undefined,
|
id: undefined as any,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
packageId: undefined,
|
packageId: undefined,
|
||||||
contactName: undefined,
|
contactName: undefined,
|
||||||
contactMobile: undefined,
|
contactMobile: undefined,
|
||||||
accountCount: undefined,
|
accountCount: undefined,
|
||||||
expireTime: undefined,
|
expireTime: Date.now(),
|
||||||
website: undefined,
|
website: undefined,
|
||||||
status: CommonStatusEnum.ENABLE,
|
status: CommonStatusEnum.ENABLE,
|
||||||
username: undefined,
|
username: undefined,
|
||||||
password: undefined,
|
password: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
aiExpireTime: undefined,
|
||||||
|
brotherExpireTime: undefined
|
||||||
}
|
}
|
||||||
userData.value = {}
|
userData.value = {} as any
|
||||||
formRef.value?.resetFields()
|
userList.value = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
aiChat: 0,
|
||||||
|
bigBrother: 0,
|
||||||
|
crawl: 0
|
||||||
|
} as any
|
||||||
|
]
|
||||||
|
// ⭐ 每次打开弹窗时都清空功能选择
|
||||||
|
selectedFeatures.value = []
|
||||||
|
|
||||||
|
formRef.value?.resetFields?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeUser(val) {
|
|
||||||
userList.value.forEach(item => {
|
/** 切换用户 */
|
||||||
|
function changeUser(val: number) {
|
||||||
|
userList.value.forEach((item) => {
|
||||||
if (item.id === val) {
|
if (item.id === val) {
|
||||||
userData.value = item
|
userData.value = item
|
||||||
userData.value.tenantId = formData.value.id
|
; (userData.value as any).tenantId = formData.value.id
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 联动:AI 过期时间 -> AI 权限 */
|
||||||
|
watch(
|
||||||
|
() => formData.value.aiExpireTime,
|
||||||
|
(val) => {
|
||||||
|
if (!val && userData.value) {
|
||||||
|
userData.value.aiChat = 0
|
||||||
|
userData.value.aiReplay = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 联动:爬大哥过期时间 -> bigBrother 权限 */
|
||||||
|
watch(
|
||||||
|
() => formData.value.brotherExpireTime,
|
||||||
|
(val) => {
|
||||||
|
if (!val && userData.value) {
|
||||||
|
userData.value.bigBrother = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.package-radio-wrapper {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 让按钮自动换行,并留点间隔 */
|
||||||
|
.package-radio-wrapper :deep(.el-radio-group) {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 美化每个 radio-button 的外观(胶囊 + 内边距) */
|
||||||
|
.package-radio-wrapper :deep(.el-radio-button__inner) {
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中状态可以稍微加粗/加边框,Element Plus 自带选中样式,这里可选 */
|
||||||
|
.package-radio-wrapper :deep(.is-active .el-radio-button__inner) {
|
||||||
|
border-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空数据提示 */
|
||||||
|
.package-empty-tip {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
104
src/views/system/tenant/TenantRenewForm.vue
Normal file
104
src/views/system/tenant/TenantRenewForm.vue
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="'租户续费'" v-model="dialogVisible">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
|
||||||
|
<!-- id:选中租户的 id,只读展示 -->
|
||||||
|
<el-form-item label="租户 ID" prop="id">
|
||||||
|
<el-input v-model="formData.id" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- packageId:套餐选择框 -->
|
||||||
|
<el-form-item label="续费套餐" prop="packageId">
|
||||||
|
<el-select v-model="formData.packageId" placeholder="请选择套餐" class="w-240px">
|
||||||
|
<el-option v-for="pkg in packageList" :key="pkg.id" :label="pkg.name" :value="pkg.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- remark:备注 -->
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" :rows="3" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="formLoading" @click="submitForm">
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { useMessage } from '@/hooks/web/useMessage'
|
||||||
|
import * as TenantApi from '@/api/system/tenant'
|
||||||
|
import * as TenantPackageApi from '@/api/system/tenantPackage'
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const emit = defineEmits(['success'])
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const formRef = ref()
|
||||||
|
const formLoading = ref(false)
|
||||||
|
|
||||||
|
// 表单数据:id / packageId / remark
|
||||||
|
const formData = reactive<{
|
||||||
|
id: number | null
|
||||||
|
packageId: number | null
|
||||||
|
remark: string
|
||||||
|
}>({
|
||||||
|
id: null,
|
||||||
|
packageId: null,
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
packageId: [{ required: true, message: '请选择续费套餐', trigger: 'change' }],
|
||||||
|
// 如果备注必填就放开下面这一条
|
||||||
|
// remark: [{ required: true, message: '请输入备注', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 套餐列表
|
||||||
|
const packageList = ref<TenantPackageApi.TenantPackageVO[]>([])
|
||||||
|
|
||||||
|
// 对外暴露的 open 方法:传入租户 id
|
||||||
|
const open = async (id: number) => {
|
||||||
|
// 重置表单
|
||||||
|
formData.id = id
|
||||||
|
formData.packageId = null
|
||||||
|
formData.remark = ''
|
||||||
|
dialogVisible.value = true
|
||||||
|
|
||||||
|
// 需要时再加载套餐列表
|
||||||
|
if (!packageList.value.length) {
|
||||||
|
packageList.value = await TenantPackageApi.getTenantPackageList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
// 🔴 根据你原来续费的接口改这里的调用
|
||||||
|
// 假设后端有一个 TenantApi.renewTenant
|
||||||
|
await TenantApi.renewal({
|
||||||
|
id: formData.id,
|
||||||
|
packageId: formData.packageId,
|
||||||
|
remark: formData.remark
|
||||||
|
})
|
||||||
|
|
||||||
|
message.success('续费成功')
|
||||||
|
dialogVisible.value = false
|
||||||
|
emit('success') // 通知父组件刷新列表
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<!-- 搜索 -->
|
<!-- 搜索 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
|
||||||
<el-form-item label="租户名" prop="name">
|
<el-form-item label="租户名" prop="name">
|
||||||
<el-input v-model="queryParams.name" placeholder="请输入租户名" clearable @keyup.enter="handleQuery"
|
<el-input v-model="queryParams.name" placeholder="请输入租户名" clearable @keyup.enter="handleQuery"
|
||||||
class="!w-240px" />
|
class="!w-240px" />
|
||||||
@@ -31,7 +31,21 @@
|
|||||||
start-placeholder="开始日期" end-placeholder="结束日期"
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="AI到期时间" prop="aiExpireTime">
|
||||||
|
<el-date-picker v-model="queryParams.aiExpireTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||||
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="大哥到期时间" prop="brotherExpireTime">
|
||||||
|
<el-date-picker v-model="queryParams.brotherExpireTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||||
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="爬虫到期时间" prop="expireTime">
|
||||||
|
<el-date-picker v-model="queryParams.expireTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||||
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button @click="handleQuery">
|
<el-button @click="handleQuery">
|
||||||
<Icon icon="ep:search" class="mr-5px" />
|
<Icon icon="ep:search" class="mr-5px" />
|
||||||
@@ -59,24 +73,25 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-table v-loading="loading" :data="list" @selection-change="handleRowCheckboxChange">
|
<el-table v-loading="loading" :data="list" row-key="id" lazy :load="loadChildren"
|
||||||
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren', checkStrictly: false }"
|
||||||
|
@selection-change="handleRowCheckboxChange" :row-class-name="rowClassName">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="租户编号" align="center" prop="id" />
|
<el-table-column label="租户编号" prop="id" width="100" />
|
||||||
<el-table-column label="租户名" align="center" prop="name" />
|
<el-table-column label="租户名" align="center" prop="name" />
|
||||||
|
<el-table-column label="租户类型" align="center" prop="tenantType" />
|
||||||
<el-table-column label="租户套餐" align="center" prop="packageId">
|
<el-table-column label="租户套餐" align="center" prop="packageId">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.packageId === 0" type="danger">系统租户</el-tag>
|
<el-tag :type="scope.row.packageId === 0 ? 'danger' : 'success'">
|
||||||
<template v-else v-for="item in packageList">
|
{{ getPackageName(scope.row.packageId) }}
|
||||||
<el-tag type="success" :key="item.id" v-if="item.id === scope.row.packageId">
|
|
||||||
{{ item.name }}
|
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="联系人" align="center" prop="contactName" />
|
<el-table-column label="联系人" align="center" prop="contactName" />
|
||||||
<el-table-column label="联系手机" align="center" prop="contactMobile" />
|
<el-table-column label="联系手机" align="center" prop="contactMobile" />1
|
||||||
<el-table-column label="账号额度" align="center" prop="accountCount">
|
<el-table-column label="账号额度" align="center" prop="accountCount">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag>{{ scope.row.accountCount }}</el-tag>
|
<el-tag>{{ scope.row.accountCount }}</el-tag>
|
||||||
@@ -84,7 +99,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="AI时间" align="center" prop="aiExpireTime" width="180" :formatter="dateFormatter" />
|
<el-table-column label="AI时间" align="center" prop="aiExpireTime" width="180" :formatter="dateFormatter" />
|
||||||
<el-table-column label="爬大哥时间" align="center" prop="brotherExpireTime" width="180" :formatter="dateFormatter" />
|
<el-table-column label="爬大哥时间" align="center" prop="brotherExpireTime" width="180" :formatter="dateFormatter" />
|
||||||
<el-table-column label="爬虫后台过期时间" align="center" prop="expireTime" width="180" :formatter="dateFormatter" />
|
<el-table-column label="后台管理过期时间" align="center" prop="expireTime" width="180" :formatter="dateFormatter" />
|
||||||
<el-table-column label="绑定域名" align="center" prop="website" width="180" />
|
<el-table-column label="绑定域名" align="center" prop="website" width="180" />
|
||||||
<el-table-column label="租户状态" align="center" prop="status">
|
<el-table-column label="租户状态" align="center" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -93,12 +108,16 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" align="center" prop="remark" />
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180" :formatter="dateFormatter" />
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180" :formatter="dateFormatter" />
|
||||||
<el-table-column label="操作" align="center" min-width="110" fixed="right">
|
<el-table-column label="操作" align="center" min-width="160" fixed="right">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||||
v-hasPermi="['system:tenant:update']">
|
v-hasPermi="['system:tenant:update']">
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button v-if="userStore.getUser.id != 1" link type="warning" @click="openRenewForm(scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant:renewal']">
|
||||||
|
续费
|
||||||
|
</el-button>
|
||||||
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['system:tenant:delete']">
|
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['system:tenant:delete']">
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -110,8 +129,10 @@
|
|||||||
@pagination="getList" />
|
@pagination="getList" />
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 -->
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
<TenantForm ref="formRef" @success="getList" />
|
<TenantForm ref="formRef" @success="getList" />
|
||||||
|
<TenantRenewForm ref="renewFormRef" @success="getList" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
@@ -120,9 +141,12 @@ import download from '@/utils/download'
|
|||||||
import * as TenantApi from '@/api/system/tenant'
|
import * as TenantApi from '@/api/system/tenant'
|
||||||
import * as TenantPackageApi from '@/api/system/tenantPackage'
|
import * as TenantPackageApi from '@/api/system/tenantPackage'
|
||||||
import TenantForm from './TenantForm.vue'
|
import TenantForm from './TenantForm.vue'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import { toRaw } from 'vue' // 🔴 新增
|
||||||
|
import TenantRenewForm from './TenantRenewForm.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'SystemTenant' })
|
defineOptions({ name: 'SystemTenant' })
|
||||||
|
const userStore = useUserStore()
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
const { t } = useI18n() // 国际化
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
@@ -136,26 +160,47 @@ const queryParams = reactive({
|
|||||||
contactName: undefined,
|
contactName: undefined,
|
||||||
contactMobile: undefined,
|
contactMobile: undefined,
|
||||||
status: undefined,
|
status: undefined,
|
||||||
|
tenantType: undefined,
|
||||||
remark: undefined,
|
remark: undefined,
|
||||||
|
createTime: [],
|
||||||
createTime: []
|
aiExpireTime: [],
|
||||||
|
brotherExpireTime: [],
|
||||||
|
expireTime: [],
|
||||||
})
|
})
|
||||||
const queryFormRef = ref() // 搜索的表单
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
const renewFormRef = ref() // 续费弹窗
|
||||||
|
|
||||||
|
const openRenewForm = (id: number) => {
|
||||||
|
renewFormRef.value.open(id)
|
||||||
|
}
|
||||||
const exportLoading = ref(false) // 导出的加载中
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
const packageList = ref([] as TenantPackageApi.TenantPackageVO[]) //租户套餐列表
|
const packageList = ref([] as TenantPackageApi.TenantPackageVO[]) //租户套餐列表
|
||||||
|
const packageAgencyList = ref([] as TenantPackageApi.TenantPackageVO[]) //租户套餐列表
|
||||||
|
|
||||||
|
/** 查询列表 */
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const data = await TenantApi.getTenantPage(queryParams)
|
let data: any = ''
|
||||||
list.value = data.list
|
if (userStore.getUser.id === 1) {
|
||||||
|
data = await TenantApi.getTenantPage(queryParams)
|
||||||
|
} else {
|
||||||
|
data = await TenantApi.getTenantPageSelf(queryParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 给顶级节点加 level = 1
|
||||||
|
list.value = (data.list || []).map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
level: 1
|
||||||
|
}))
|
||||||
total.value = data.total
|
total.value = data.total
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.pageNo = 1
|
queryParams.pageNo = 1
|
||||||
@@ -170,7 +215,7 @@ const resetQuery = () => {
|
|||||||
|
|
||||||
/** 添加/修改操作 */
|
/** 添加/修改操作 */
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const openForm = (type: string, id?: number) => {
|
const openForm = (type: 'create' | 'update' | 'renew', id?: number) => {
|
||||||
formRef.value.open(type, id)
|
formRef.value.open(type, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,11 +264,96 @@ const handleExport = async () => {
|
|||||||
exportLoading.value = false
|
exportLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const getPackageName = (packageId: number) => {
|
||||||
|
if (userStore.getUser.id === 0) return '系统租户'
|
||||||
|
|
||||||
|
// 先从 packageList 找
|
||||||
|
const pkg = packageList.value.find((p) => p.id === packageId)
|
||||||
|
if (pkg) return pkg.name
|
||||||
|
|
||||||
|
// packageList 未找到,并且 packageId !== 1 时,再从 packageAgencyList 找
|
||||||
|
if (packageId !== 1) {
|
||||||
|
const agency = packageAgencyList.value.find((a) => a.id === packageId)
|
||||||
|
if (agency) return agency.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return '未知套餐'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 懒加载子租户(树形表格用)
|
||||||
|
const loadChildren = async (
|
||||||
|
row: TenantApi.TenantVO & { level?: number },
|
||||||
|
treeNode: unknown,
|
||||||
|
resolve: (data: TenantApi.TenantVO[]) => void
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const baseParams = toRaw(queryParams) as any
|
||||||
|
const params = {
|
||||||
|
...baseParams,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 999,
|
||||||
|
id: row.id
|
||||||
|
}
|
||||||
|
|
||||||
|
let data: any
|
||||||
|
data = await TenantApi.getTenantChildren(params)
|
||||||
|
|
||||||
|
const parentLevel = row.level ?? 1
|
||||||
|
|
||||||
|
// 子节点 level = 父节点 level + 1
|
||||||
|
const children = (data || []).map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
level: parentLevel + 1
|
||||||
|
}))
|
||||||
|
|
||||||
|
resolve(children)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('loadChildren error', e)
|
||||||
|
resolve([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 行样式 class
|
||||||
|
const rowClassName = ({ row }: { row: any }) => {
|
||||||
|
if (row.level === 2) return 'row-level-2'
|
||||||
|
if (row.level >= 3) return 'row-level-3'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getList()
|
await getList()
|
||||||
// 获取租户套餐列表
|
// 获取租户套餐列表
|
||||||
packageList.value = await TenantPackageApi.getTenantPackageList()
|
packageList.value = await TenantPackageApi.getTenantPackageList()
|
||||||
|
if (userStore.getUser.id === 1) {
|
||||||
|
packageAgencyList.value = await TenantPackageApi.getTenantPackageListagency()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
/* 二级行背景色 */
|
||||||
|
:deep(.row-level-2) {
|
||||||
|
background-color: #fdf6ec;
|
||||||
|
/* 浅橙色,你可以自己换 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 三级及以下行背景色 */
|
||||||
|
:deep(.row-level-3) {
|
||||||
|
background-color: #dedeff;
|
||||||
|
/* 浅灰色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 可选:加个左边彩色竖条,更醒目 */
|
||||||
|
:deep(.row-level-2 td:first-child),
|
||||||
|
:deep(.row-level-3 td:first-child) {
|
||||||
|
border-left: 4px solid #e6a23c;
|
||||||
|
/* 二级竖条 */
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.row-level-3 td:first-child) {
|
||||||
|
border-left-color: #3636e0;
|
||||||
|
/* 三级竖条 */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||||
<el-form
|
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px">
|
||||||
ref="formRef"
|
|
||||||
v-loading="formLoading"
|
|
||||||
:model="formData"
|
|
||||||
:rules="formRules"
|
|
||||||
label-width="80px"
|
|
||||||
>
|
|
||||||
<el-form-item label="套餐名" prop="name">
|
<el-form-item label="套餐名" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入套餐名" />
|
<el-input v-model="formData.name" placeholder="请输入套餐名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -14,39 +8,19 @@
|
|||||||
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
|
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
全选/全不选:
|
全选/全不选:
|
||||||
<el-switch
|
<el-switch v-model="treeNodeAll" active-text="是" inactive-text="否" inline-prompt
|
||||||
v-model="treeNodeAll"
|
@change="handleCheckedTreeNodeAll" />
|
||||||
active-text="是"
|
|
||||||
inactive-text="否"
|
|
||||||
inline-prompt
|
|
||||||
@change="handleCheckedTreeNodeAll"
|
|
||||||
/>
|
|
||||||
全部展开/折叠:
|
全部展开/折叠:
|
||||||
<el-switch
|
<el-switch v-model="menuExpand" active-text="展开" inactive-text="折叠" inline-prompt
|
||||||
v-model="menuExpand"
|
@change="handleCheckedTreeExpand" />
|
||||||
active-text="展开"
|
|
||||||
inactive-text="折叠"
|
|
||||||
inline-prompt
|
|
||||||
@change="handleCheckedTreeExpand"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<el-tree
|
<el-tree ref="treeRef" :data="menuOptions" :props="defaultProps" empty-text="加载中,请稍候" node-key="id"
|
||||||
ref="treeRef"
|
show-checkbox />
|
||||||
:data="menuOptions"
|
|
||||||
:props="defaultProps"
|
|
||||||
empty-text="加载中,请稍候"
|
|
||||||
node-key="id"
|
|
||||||
show-checkbox
|
|
||||||
/>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
<el-radio-group v-model="formData.status">
|
<el-radio-group v-model="formData.status">
|
||||||
<el-radio
|
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
|
||||||
:key="dict.value"
|
|
||||||
:value="dict.value"
|
|
||||||
>
|
|
||||||
{{ dict.label }}
|
{{ dict.label }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
|
|||||||
249
src/views/system/tenantagencypackage/TenantAgencyPackageForm.vue
Normal file
249
src/views/system/tenantagencypackage/TenantAgencyPackageForm.vue
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
|
||||||
|
<el-form-item label="套餐名" prop="name">
|
||||||
|
<el-input v-model="formData.name" placeholder="请输入套餐名" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="租户状态" prop="status">
|
||||||
|
<el-radio-group v-model="formData.status">
|
||||||
|
<el-radio :value="0">正常</el-radio>
|
||||||
|
<el-radio :value="1">停用</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- ✅ 改成树形菜单选择 -->
|
||||||
|
<el-form-item label="菜单权限" prop="menuIds">
|
||||||
|
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
全选/全不选:
|
||||||
|
<el-switch v-model="treeNodeAll" active-text="是" inactive-text="否" inline-prompt
|
||||||
|
@change="handleCheckedTreeNodeAll" />
|
||||||
|
全部展开/折叠:
|
||||||
|
<el-switch v-model="menuExpand" active-text="展开" inactive-text="折叠" inline-prompt
|
||||||
|
@change="handleCheckedTreeExpand" />
|
||||||
|
</template>
|
||||||
|
<el-tree ref="treeRef" :data="menuOptions" :props="defaultProps" empty-text="加载中,请稍候" node-key="id"
|
||||||
|
show-checkbox />
|
||||||
|
</el-card>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="套餐天数" prop="days">
|
||||||
|
<el-input v-model="formData.days" placeholder="请输入套餐天数" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="套餐价格" prop="price">
|
||||||
|
<el-input v-model="formData.price" placeholder="请输入套餐价格" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 爬大哥:必须先选“爬大哥过期时间” -->
|
||||||
|
<el-form-item label="爬大哥">
|
||||||
|
<el-radio-group v-model="formData.brotherClient">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- ai自动化:必须先选“AI过期时间” -->
|
||||||
|
<el-form-item label="爬主播">
|
||||||
|
<el-radio-group v-model="formData.hostslClient">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- ai回复:必须先选“AI过期时间” -->
|
||||||
|
<el-form-item label="AI客户端">
|
||||||
|
<el-radio-group v-model="formData.aiClient">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- ai回复:必须先选“AI过期时间” -->
|
||||||
|
<el-form-item label="AI回复">
|
||||||
|
<el-radio-group v-model="formData.aiReplay">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- WEB回复:必须先选“AI过期时间” -->
|
||||||
|
<el-form-item label="WEB客户端">
|
||||||
|
<el-radio-group v-model="formData.webAi">
|
||||||
|
<el-radio :value="1">开启</el-radio>
|
||||||
|
<el-radio :value="0">关闭</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="套餐类型" prop="packageType">
|
||||||
|
<el-input v-model="formData.packageType" placeholder="请输入套餐类型" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TenantAgencyPackageApi, TenantAgencyPackageVO } from '@/api/system/tenantagencypackage'
|
||||||
|
import * as MenuApi from '@/api/system/menu'
|
||||||
|
import { defaultProps, handleTree } from '@/utils/tree'
|
||||||
|
import { ElTree } from 'element-plus'
|
||||||
|
|
||||||
|
/** 代理租户套餐 表单 */
|
||||||
|
defineOptions({ name: 'TenantAgencyPackageForm' })
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const dialogTitle = ref('')
|
||||||
|
const formLoading = ref(false)
|
||||||
|
const formType = ref<'create' | 'update' | string>('')
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
id: undefined as number | undefined,
|
||||||
|
name: undefined as string | undefined,
|
||||||
|
status: 0 as 0 | 1 | undefined, // 默认正常
|
||||||
|
remark: undefined as string | undefined,
|
||||||
|
menuIds: [] as number[], // ✅ 改成数组
|
||||||
|
days: undefined as number | undefined,
|
||||||
|
price: undefined as number | undefined,
|
||||||
|
hostslClient: undefined as number | undefined,
|
||||||
|
brotherClient: undefined as number | undefined,
|
||||||
|
aiClient: undefined as number | undefined,
|
||||||
|
aiReplay: undefined as number | undefined,
|
||||||
|
webAi: undefined as number | undefined,
|
||||||
|
packageType: undefined as string | undefined
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRules = reactive({
|
||||||
|
name: [{ required: true, message: '套餐名不能为空', trigger: 'blur' }],
|
||||||
|
status: [{ required: true, message: '租户状态不能为空', trigger: 'change' }],
|
||||||
|
// menuIds: [{ required: true, message: '关联的菜单编号不能为空', trigger: 'change' }], // ✅ 校验菜单
|
||||||
|
days: [{ required: true, message: '套餐天数不能为空', trigger: 'blur' }],
|
||||||
|
price: [{ required: true, message: '套餐价格不能为空', trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
const formRef = ref()
|
||||||
|
|
||||||
|
// ✅ 菜单树相关
|
||||||
|
const menuOptions = ref<any[]>([])
|
||||||
|
const menuExpand = ref(false)
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>()
|
||||||
|
const treeNodeAll = ref(false)
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
await resetForm()
|
||||||
|
|
||||||
|
// 先加载菜单树数据(一定要先有数据,后 setChecked)
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const menus = await MenuApi.getSimpleMenusList()
|
||||||
|
menuOptions.value = handleTree(menus)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑:回显数据并勾选
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = await TenantAgencyPackageApi.getTenantAgencyPackage(id)
|
||||||
|
formData.value = {
|
||||||
|
...formData.value,
|
||||||
|
...data,
|
||||||
|
menuIds: Array.isArray(data.menuIds) ? data.menuIds : []
|
||||||
|
}
|
||||||
|
// 勾选已有关联
|
||||||
|
formData.value.menuIds.forEach((mid: number) => {
|
||||||
|
treeRef.value?.setChecked(mid, true, false)
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open })
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success'])
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 1. 先做表单校验
|
||||||
|
await formRef.value.validate()
|
||||||
|
|
||||||
|
// 2. 从树组件拿选中的菜单 id(包含半选)
|
||||||
|
const checked = (treeRef.value?.getCheckedKeys(false) || []) as number[]
|
||||||
|
const half = (treeRef.value?.getHalfCheckedKeys() || []) as number[]
|
||||||
|
const menuIds = Array.from(new Set([...checked, ...half])) // 去重一下
|
||||||
|
|
||||||
|
// 3. 把 menuIds 塞回 formData(或者直接合并到 data 里)
|
||||||
|
formData.value.menuIds = menuIds
|
||||||
|
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
// 4. 组装真正发给后端的参数
|
||||||
|
const data = {
|
||||||
|
...(formData.value as any),
|
||||||
|
menuIds // ✅ 确保有这个字段
|
||||||
|
} as TenantAgencyPackageVO
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await TenantAgencyPackageApi.createTenantAgencyPackage(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await TenantAgencyPackageApi.updateTenantAgencyPackage(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogVisible.value = false
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = async () => {
|
||||||
|
treeNodeAll.value = false
|
||||||
|
menuExpand.value = false
|
||||||
|
formData.value = {
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
status: 0,
|
||||||
|
remark: undefined,
|
||||||
|
menuIds: [], // ✅ 清空
|
||||||
|
days: undefined,
|
||||||
|
price: undefined,
|
||||||
|
hostslClient: undefined,
|
||||||
|
brotherClient: undefined,
|
||||||
|
aiClient: undefined,
|
||||||
|
aiReplay: undefined,
|
||||||
|
packageType: undefined
|
||||||
|
}
|
||||||
|
treeRef.value?.setCheckedNodes([])
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 全选/全不选 */
|
||||||
|
const handleCheckedTreeNodeAll = () => {
|
||||||
|
treeRef.value?.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开/折叠全部 */
|
||||||
|
const handleCheckedTreeExpand = () => {
|
||||||
|
const nodes = (treeRef.value as any)?.store?.nodesMap
|
||||||
|
if (!nodes) return
|
||||||
|
for (const key in nodes) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(nodes, key)) {
|
||||||
|
nodes[key].expanded = menuExpand.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
201
src/views/system/tenantagencypackage/index.vue
Normal file
201
src/views/system/tenantagencypackage/index.vue
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
<template>
|
||||||
|
<ContentWrap>
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
|
||||||
|
<el-form-item label="套餐名" prop="name">
|
||||||
|
<el-input v-model="queryParams.name" placeholder="请输入套餐名" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="租户状态 " prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="请选择租户状态 " clearable class="!w-240px">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="创建时间" prop="createTime">
|
||||||
|
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||||
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="套餐天数" prop="days">
|
||||||
|
<el-input v-model="queryParams.days" placeholder="请输入套餐天数" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="套餐价格" prop="price">
|
||||||
|
<el-input v-model="queryParams.price" placeholder="请输入套餐价格" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="爬主播客户端 " prop="hostslClient">
|
||||||
|
<el-input v-model="queryParams.hostslClient" placeholder="请输入爬主播客户端 " clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="爬大哥客户端 " prop="brotherClient">
|
||||||
|
<el-input v-model="queryParams.brotherClient" placeholder="请输入爬大哥客户端 " clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="AI 客户端 " prop="aiClient">
|
||||||
|
<el-input v-model="queryParams.aiClient" placeholder="请输入AI 客户端 " clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="套餐类型" prop="packageType">
|
||||||
|
<el-select v-model="queryParams.packageType" placeholder="请选择套餐类型" clearable class="!w-240px">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="handleQuery">
|
||||||
|
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="resetQuery">
|
||||||
|
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" plain @click="openForm('create')"
|
||||||
|
v-hasPermi="['system:tenant-agency-package:create']">
|
||||||
|
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||||
|
v-hasPermi="['system:tenant-agency-package:export']">
|
||||||
|
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||||
|
<el-table-column label="套餐编号" align="center" prop="id" />
|
||||||
|
<el-table-column label="套餐名" align="center" prop="name" width="200px" />
|
||||||
|
<!-- <el-table-column label="租户状态 " align="center" prop="status" /> -->
|
||||||
|
<!-- <el-table-column label="关联的菜单编号" align="center" prop="menuIds" /> -->
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
|
||||||
|
<el-table-column label="套餐天数" align="center" prop="days" />
|
||||||
|
<el-table-column label="套餐价格" align="center" prop="price" />
|
||||||
|
<!-- <el-table-column label="爬主播客户端 " align="center" prop="hostslClient" />
|
||||||
|
<el-table-column label="爬大哥客户端 " align="center" prop="brotherClient" />
|
||||||
|
<el-table-column label="AI 客户端 " align="center" prop="aiClient" /> -->
|
||||||
|
<el-table-column label="套餐类型" align="center" prop="packageType" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" min-width="50px" />
|
||||||
|
|
||||||
|
<el-table-column label="操作" align="center" min-width="120px">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-agency-package:update']">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-agency-package:delete']">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
<TenantAgencyPackageForm ref="formRef" @success="getList" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
|
import download from '@/utils/download'
|
||||||
|
import { TenantAgencyPackageApi, TenantAgencyPackageVO } from '@/api/system/tenantagencypackage'
|
||||||
|
import TenantAgencyPackageForm from './TenantAgencyPackageForm.vue'
|
||||||
|
|
||||||
|
/** 代理租户套餐 列表 */
|
||||||
|
defineOptions({ name: 'TenantAgencyPackage' })
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中
|
||||||
|
const list = ref<TenantAgencyPackageVO[]>([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
name: undefined,
|
||||||
|
status: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
menuIds: undefined,
|
||||||
|
createTime: [],
|
||||||
|
days: undefined,
|
||||||
|
price: undefined,
|
||||||
|
hostslClient: undefined,
|
||||||
|
brotherClient: undefined,
|
||||||
|
aiClient: undefined,
|
||||||
|
packageType: undefined
|
||||||
|
})
|
||||||
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
|
||||||
|
/** 查询列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await TenantAgencyPackageApi.getTenantAgencyPackagePage(queryParams)
|
||||||
|
list.value = data.list
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value.resetFields()
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加/修改操作 */
|
||||||
|
const formRef = ref()
|
||||||
|
const openForm = (type: string, id?: number) => {
|
||||||
|
formRef.value.open(type, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await TenantAgencyPackageApi.deleteTenantAgencyPackage(id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
// 导出的二次确认
|
||||||
|
await message.exportConfirm()
|
||||||
|
// 发起导出
|
||||||
|
exportLoading.value = true
|
||||||
|
const data = await TenantAgencyPackageApi.exportTenantAgencyPackage(queryParams)
|
||||||
|
download.excel(data, '代理租户套餐.xls')
|
||||||
|
} catch {
|
||||||
|
} finally {
|
||||||
|
exportLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 **/
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
169
src/views/system/tenantbalance/TenantBalanceForm.vue
Normal file
169
src/views/system/tenantbalance/TenantBalanceForm.vue
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
|
<el-form v-if="formType === 'update'" ref="formRef" :model="formData" :rules="formRules" label-width="100px"
|
||||||
|
v-loading="formLoading">
|
||||||
|
<el-form-item label="充值用户" prop="id">
|
||||||
|
<el-input v-model="formData.id" placeholder="请输入充值用户" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="formType === 'update'" label="充值金额" prop="amount">
|
||||||
|
<!-- 改为 el-input-number,仅允许数值输入,且最小 0 -->
|
||||||
|
<el-input-number v-model.number="formData.amount" :min="0" controls-position="right" placeholder="请输入充值金额" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 只有 transfer 类型时显示 -->
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
|
||||||
|
<el-form v-if="formType === 'transfer'" ref="formRef" :model="formData" :rules="formRules" label-width="100px"
|
||||||
|
v-loading="formLoading">
|
||||||
|
<el-form-item label="转账用户" prop="targetTenantId">
|
||||||
|
<el-input v-model="formData.targetTenantId" placeholder="请输入转账用户" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="formType === 'transfer'" label="转账金额" prop="transferAmount">
|
||||||
|
<!-- 改为 el-input-number,仅允许数值输入,且最小 0 -->
|
||||||
|
<el-input-number v-model.number="formData.transferAmount" :min="0" controls-position="right"
|
||||||
|
placeholder="请输入转账金额" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="formType === 'transfer'" label="登录密码" prop="password">
|
||||||
|
<el-input v-model="formData.password" type="password" show-password placeholder="请输入登录密码" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 只有 transfer 类型时显示 -->
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="submitForm" type="primary" :disabled="formLoading">
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, reactive } from 'vue'
|
||||||
|
import { TenantBalanceApi, TenantBalanceVO } from '@/api/system/tenantbalance'
|
||||||
|
|
||||||
|
/** 租户余额 表单 */
|
||||||
|
defineOptions({ name: 'TenantBalanceForm' })
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改;transfer - 转账等
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
tenantId: undefined as number | undefined,
|
||||||
|
id: undefined as number | undefined,
|
||||||
|
amount: undefined as number | undefined,
|
||||||
|
transferAmount: undefined as number | undefined,
|
||||||
|
targetTenantId: undefined as number | undefined,
|
||||||
|
remark: undefined as string | undefined, // 变动表述
|
||||||
|
password: undefined as string | undefined // 登录密码
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 校验规则:transfer 时才要求 remark 必填 */
|
||||||
|
const formRules = computed(() => {
|
||||||
|
const baseRules: any = {
|
||||||
|
id: [{ required: true, message: '用户不能为空', trigger: 'blur' }],
|
||||||
|
amount: [{ required: true, message: '金额不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formType.value === 'transfer') {
|
||||||
|
|
||||||
|
baseRules.password = [
|
||||||
|
{ required: true, message: '登录密码不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
baseRules.transferAmount = [
|
||||||
|
{ required: true, message: '转账金额不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseRules
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
|
// 修改时,设置数据
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = await TenantBalanceApi.getTenantBalance(id)
|
||||||
|
// 保证有 remark 和 password 字段(接口没有的话就保持 undefined)
|
||||||
|
formData.value = {
|
||||||
|
tenantId: data.tenantId,
|
||||||
|
id: data.id,
|
||||||
|
amount: data.amount,
|
||||||
|
targetTenantId: data.id,
|
||||||
|
remark: undefined,
|
||||||
|
password: undefined,
|
||||||
|
transferAmount: undefined
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
|
const submitForm = async () => {
|
||||||
|
console.log(formData.value)
|
||||||
|
// 校验表单
|
||||||
|
await formRef.value.validate()
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = formData.value as unknown as TenantBalanceVO
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await TenantBalanceApi.createTenantBalance(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else if (formType.value === 'transfer') {
|
||||||
|
await TenantBalanceApi.tenantTransfer(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
} else {
|
||||||
|
await TenantBalanceApi.addAmount(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
formData.value = {
|
||||||
|
tenantId: undefined,
|
||||||
|
id: undefined,
|
||||||
|
amount: undefined,
|
||||||
|
transferAmount: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
password: undefined
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
132
src/views/system/tenantbalance/components/TenantPointsForm.vue
Normal file
132
src/views/system/tenantbalance/components/TenantPointsForm.vue
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
|
||||||
|
<el-form-item label="本次变动点数,正加负减" prop="points">
|
||||||
|
<el-input v-model="formData.points" placeholder="请输入本次变动点数,正加负减" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变动后余额快照(冗余)" prop="balance">
|
||||||
|
<el-input v-model="formData.balance" placeholder="请输入变动后余额快照(冗余)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN" prop="type">
|
||||||
|
<el-select v-model="formData.type" placeholder="请选择变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<Editor v-model="formData.remark" height="150px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="订单 Id/业务单号" prop="orderId">
|
||||||
|
<el-input v-model="formData.orderId" placeholder="请输入订单 Id/业务单号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="业务流水号(转账、订单等唯一标识)" prop="bizNo">
|
||||||
|
<el-input v-model="formData.bizNo" placeholder="请输入业务流水号(转账、订单等唯一标识)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="操作人 Id" prop="operatorId">
|
||||||
|
<el-input v-model="formData.operatorId" placeholder="请输入操作人 Id" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="目标租户 Id(转账使用)" prop="targetTenantId">
|
||||||
|
<el-input v-model="formData.targetTenantId" placeholder="请输入目标租户 Id(转账使用)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间" prop="createdAt">
|
||||||
|
<el-date-picker v-model="formData.createdAt" type="date" value-format="x" placeholder="选择创建时间" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TenantBalanceApi } from '@/api/system/tenantbalance'
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
const formData = ref({
|
||||||
|
id: undefined,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
type: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
orderId: undefined,
|
||||||
|
bizNo: undefined,
|
||||||
|
operatorId: undefined,
|
||||||
|
targetTenantId: undefined,
|
||||||
|
createdAt: undefined,
|
||||||
|
remark: undefined
|
||||||
|
})
|
||||||
|
const formRules = reactive({
|
||||||
|
points: [{ required: true, message: '本次变动点数,正加负减不能为空', trigger: 'blur' }],
|
||||||
|
createdAt: [{ required: true, message: '创建时间不能为空', trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number, tenantId: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
|
formData.value.tenantId = tenantId
|
||||||
|
// 修改时,设置数据
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
formData.value = await TenantBalanceApi.getTenantPoints(id)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 校验表单
|
||||||
|
await formRef.value.validate()
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = formData.value
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await TenantBalanceApi.createTenantPoints(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await TenantBalanceApi.updateTenantPoints(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
formData.value = {
|
||||||
|
id: undefined,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
type: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
orderId: undefined,
|
||||||
|
bizNo: undefined,
|
||||||
|
operatorId: undefined,
|
||||||
|
targetTenantId: undefined,
|
||||||
|
createdAt: undefined,
|
||||||
|
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
112
src/views/system/tenantbalance/components/TenantPointsList.vue
Normal file
112
src/views/system/tenantbalance/components/TenantPointsList.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<!-- <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['system:tenant-balance:create']">
|
||||||
|
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||||
|
</el-button> -->
|
||||||
|
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||||
|
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
|
||||||
|
<el-table-column label="金额" align="center" prop="points" />
|
||||||
|
<el-table-column label="变动后余额" align="center" prop="balance" />
|
||||||
|
<el-table-column label="类型" align="center" prop="type" />
|
||||||
|
<el-table-column label="描述" align="center" prop="description" />
|
||||||
|
<el-table-column label="订单 Id/业务单号" align="center" prop="orderId" />
|
||||||
|
<el-table-column label="业务流水号" align="center" prop="bizNo" />
|
||||||
|
<el-table-column label="操作人 Id" align="center" prop="operatorId" />
|
||||||
|
<el-table-column label="目标租户Id" align="center" prop="targetTenantId" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createdAt" :formatter="dateFormatter" width="180px" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-balance:update']">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-balance:delete']">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</ContentWrap>
|
||||||
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
<TenantPointsForm ref="formRef" @success="getList" />
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
|
import { TenantBalanceApi } from '@/api/system/tenantbalance'
|
||||||
|
import TenantPointsForm from './TenantPointsForm.vue'
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
tenantId?: number // 租户 Id(主表的关联字段)
|
||||||
|
}>()
|
||||||
|
const loading = ref(false) // 列表的加载中
|
||||||
|
const list = ref([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
tenantId: undefined as unknown
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||||
|
watch(
|
||||||
|
() => props.tenantId,
|
||||||
|
(val: number) => {
|
||||||
|
if (!val) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
queryParams.tenantId = val
|
||||||
|
handleQuery()
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 查询列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await TenantBalanceApi.getTenantPointsPage(queryParams)
|
||||||
|
list.value = data.list
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加/修改操作 */
|
||||||
|
const formRef = ref()
|
||||||
|
const openForm = (type: string, id?: number) => {
|
||||||
|
if (!props.tenantId) {
|
||||||
|
message.error('请选择一个租户余额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formRef.value.open(type, id, props.tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await TenantBalanceApi.deleteTenantPoints(id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
</script>
|
||||||
220
src/views/system/tenantbalance/index.vue
Normal file
220
src/views/system/tenantbalance/index.vue
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
<template>
|
||||||
|
<ContentWrap>
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
|
<el-form-item label="积分余额" prop="balance">
|
||||||
|
<el-input v-model="queryParams.balance" placeholder="请输入当前积分余额" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="租户id" prop="id">
|
||||||
|
<el-input v-model="queryParams.id" placeholder="请输入租户id" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="租户名" prop="tenantName">
|
||||||
|
<el-input v-model="queryParams.tenantName" placeholder="请输入租户id" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="更新时间" prop="updatedAt">
|
||||||
|
<el-date-picker v-model="queryParams.updatedAt" value-format="YYYY-MM-DD" type="date" placeholder="选择更新时间"
|
||||||
|
clearable class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item style="width: 100%;">
|
||||||
|
<div class="center-align">
|
||||||
|
<div>
|
||||||
|
<el-button @click="handleQuery">
|
||||||
|
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="resetQuery">
|
||||||
|
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['system:tenant-balance:create']">
|
||||||
|
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||||
|
v-hasPermi="['system:tenant-balance:export']">
|
||||||
|
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="userStore.getUser.id !== 1" class="balance-text">余额:{{ mount.balance }} 测试号:{{
|
||||||
|
mount.testAccountNum }}</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" highlight-current-row
|
||||||
|
@current-change="handleCurrentChange">
|
||||||
|
<el-table-column label="当前积分余额" align="center" prop="balance" />
|
||||||
|
<el-table-column label="租户名" align="center" prop="tenantName" />
|
||||||
|
<el-table-column label="租户id" align="center" prop="id" />
|
||||||
|
<el-table-column label="更新时间" align="center" prop="updatedAt" :formatter="dateFormatter" width="180px" />
|
||||||
|
<el-table-column label="描述" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" min-width="120px">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-balance:update']">
|
||||||
|
充值
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="userStore.getUser.id !== 1" link type="primary" @click="openForm('transfer', scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-balance:transfer']">
|
||||||
|
转账
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-balance:delete']">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
<TenantBalanceForm ref="formRef" @success="getList" />
|
||||||
|
<!-- 子表的列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-tabs model-value="tenantPoints">
|
||||||
|
<el-tab-pane label="变动记录" name="tenantPoints">
|
||||||
|
<TenantPointsList :tenant-id="currentRow.id" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
|
import download from '@/utils/download'
|
||||||
|
import { TenantBalanceApi, TenantBalanceVO } from '@/api/system/tenantbalance'
|
||||||
|
import TenantBalanceForm from './TenantBalanceForm.vue'
|
||||||
|
import TenantPointsList from './components/TenantPointsList.vue'
|
||||||
|
import { checkPermi } from '@/utils/permission'
|
||||||
|
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
const userStore = ref(useUserStore())
|
||||||
|
/** 租户余额 列表 */
|
||||||
|
defineOptions({ name: 'TenantBalance' })
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中
|
||||||
|
const list = ref<TenantBalanceVO[]>([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
balance: undefined,
|
||||||
|
version: undefined,
|
||||||
|
updatedAt: undefined,
|
||||||
|
updatedAt: []
|
||||||
|
})
|
||||||
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
const mount = ref({})
|
||||||
|
/** 查询列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
let data = {}
|
||||||
|
console.log(checkPermi(['system:tenant-balance:self-subordinate']))
|
||||||
|
if (userStore.value.getUser.id !== 1) {
|
||||||
|
getMount()
|
||||||
|
data = await TenantBalanceApi.getSubordinateaMountPage(queryParams)
|
||||||
|
} else {
|
||||||
|
data = await TenantBalanceApi.getTenantBalancePage(queryParams)
|
||||||
|
}
|
||||||
|
// if (checkPermi(['system:tenant-balance:self-subordinate'])) {
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
list.value = data.list
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 查询列表 */
|
||||||
|
const getMount = async () => {
|
||||||
|
const data = await TenantBalanceApi.getselfamount()
|
||||||
|
mount.value = data
|
||||||
|
|
||||||
|
}
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value.resetFields()
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加/修改操作 */
|
||||||
|
const formRef = ref()
|
||||||
|
const openForm = (type: string, id?: number) => {
|
||||||
|
formRef.value.open(type, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await TenantBalanceApi.deleteTenantBalance(id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
// 导出的二次确认
|
||||||
|
await message.exportConfirm()
|
||||||
|
// 发起导出
|
||||||
|
exportLoading.value = true
|
||||||
|
const data = await TenantBalanceApi.exportTenantBalance(queryParams)
|
||||||
|
download.excel(data, '租户余额.xls')
|
||||||
|
} catch {
|
||||||
|
} finally {
|
||||||
|
exportLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选中行操作 */
|
||||||
|
const currentRow = ref({}) // 选中行
|
||||||
|
const handleCurrentChange = (row) => {
|
||||||
|
currentRow.value = row
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 **/
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.center-align {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-text {
|
||||||
|
margin-left: auto;
|
||||||
|
/* 把余额顶到最右边 */
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
129
src/views/system/tenantpoints/TenantPointsForm.vue
Normal file
129
src/views/system/tenantpoints/TenantPointsForm.vue
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
|
||||||
|
<el-form-item label="本次变动点数,正加负减" prop="points">
|
||||||
|
<el-input v-model="formData.points" placeholder="请输入本次变动点数,正加负减" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变动后余额快照(冗余)" prop="balance">
|
||||||
|
<el-input v-model="formData.balance" placeholder="请输入变动后余额快照(冗余)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN" prop="type">
|
||||||
|
<el-select v-model="formData.type" placeholder="请选择变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="description">
|
||||||
|
<Editor v-model="formData.remark" height="150px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="订单 Id/业务单号" prop="orderId">
|
||||||
|
<el-input v-model="formData.orderId" placeholder="请输入订单 Id/业务单号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="业务流水号(转账、订单等唯一标识)" prop="bizNo">
|
||||||
|
<el-input v-model="formData.bizNo" placeholder="请输入业务流水号(转账、订单等唯一标识)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="操作人 Id" prop="operatorId">
|
||||||
|
<el-input v-model="formData.operatorId" placeholder="请输入操作人 Id" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="目标租户 Id(转账使用)" prop="targetTenantId">
|
||||||
|
<el-input v-model="formData.targetTenantId" placeholder="请输入目标租户 Id(转账使用)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间" prop="createdAt">
|
||||||
|
<el-date-picker v-model="formData.createdAt" type="date" value-format="x" placeholder="选择创建时间" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TenantPointsApi, TenantPointsVO } from '@/api/system/tenantpoints'
|
||||||
|
|
||||||
|
/** 租户积分记录 表单 */
|
||||||
|
defineOptions({ name: 'TenantPointsForm' })
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
const formData = ref({
|
||||||
|
id: undefined,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
type: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
orderId: undefined,
|
||||||
|
bizNo: undefined,
|
||||||
|
operatorId: undefined,
|
||||||
|
targetTenantId: undefined,
|
||||||
|
createdAt: undefined
|
||||||
|
})
|
||||||
|
const formRules = reactive({
|
||||||
|
points: [{ required: true, message: '本次变动点数,正加负减不能为空', trigger: 'blur' }],
|
||||||
|
createdAt: [{ required: true, message: '创建时间不能为空', trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
|
// 修改时,设置数据
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
formData.value = await TenantPointsApi.getTenantPoints(id)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 校验表单
|
||||||
|
await formRef.value.validate()
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = formData.value as unknown as TenantPointsVO
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await TenantPointsApi.createTenantPoints(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await TenantPointsApi.updateTenantPoints(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
formData.value = {
|
||||||
|
id: undefined,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
type: undefined,
|
||||||
|
description: undefined,
|
||||||
|
orderId: undefined,
|
||||||
|
bizNo: undefined,
|
||||||
|
operatorId: undefined,
|
||||||
|
targetTenantId: undefined,
|
||||||
|
createdAt: undefined
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
198
src/views/system/tenantpoints/index.vue
Normal file
198
src/views/system/tenantpoints/index.vue
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<template>
|
||||||
|
<ContentWrap>
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="120px">
|
||||||
|
<!-- <el-form-item label="金额" prop="points">
|
||||||
|
<el-input v-model="queryParams.points" placeholder="请输入金额(正加负减)" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变动后余额" prop="balance">
|
||||||
|
<el-input v-model="queryParams.balance" placeholder="请输入变动后余额(冗余)" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item label="类型" prop="type">
|
||||||
|
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable class="!w-240px">
|
||||||
|
<el-option v-for="(dict, index) in getIntDictOptions(DICT_TYPE.PAY_TYPE)" :key="index" :label="dict.label"
|
||||||
|
:value="dict.label" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="订单 Id" prop="orderId">
|
||||||
|
<el-input v-model="queryParams.orderId" placeholder="请输入订单 Id / 业务单号" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="业务流水号" prop="bizNo">
|
||||||
|
<el-input v-model="queryParams.bizNo" placeholder="请输入业务流水号(转账、订单等唯一标识)" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="操作人 Id" prop="operatorId">
|
||||||
|
<el-input v-model="queryParams.operatorId" placeholder="请输入操作人 Id" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="目标租户 Id" prop="targetTenantId">
|
||||||
|
<el-input v-model="queryParams.targetTenantId" placeholder="请输入目标租户 Id(转账使用)" clearable
|
||||||
|
@keyup.enter="handleQuery" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间" prop="createdAt">
|
||||||
|
<el-date-picker v-model="queryParams.createdAt" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||||
|
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- <el-form-item label="描述/备注" prop="remark">
|
||||||
|
<el-input v-model="queryParams.remark" placeholder="请输入描述或备注" clearable @keyup.enter="handleQuery"
|
||||||
|
class="!w-240px" />
|
||||||
|
</el-form-item> -->
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="handleQuery">
|
||||||
|
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="resetQuery">
|
||||||
|
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||||
|
</el-button>
|
||||||
|
<!-- <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['system:tenant-points:create']">
|
||||||
|
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||||
|
</el-button> -->
|
||||||
|
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||||
|
v-hasPermi="['system:tenant-points:export']">
|
||||||
|
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||||
|
<!-- 列头按你给的短名称展示,prop 对应后端字段 -->
|
||||||
|
<el-table-column label="变动" align="center" prop="points" />
|
||||||
|
<el-table-column label="变动后余额" align="center" prop="balance" />
|
||||||
|
<el-table-column label="测试号余额" align="center" prop="testAccountNum" />
|
||||||
|
<el-table-column label="类型" align="center" prop="type" />
|
||||||
|
<el-table-column label="描述" align="center" prop="description" />
|
||||||
|
<el-table-column label="订单 Id/业务单号" align="center" prop="orderId" />
|
||||||
|
<el-table-column label="业务流水号" align="center" prop="bizNo" />
|
||||||
|
<el-table-column label="操作人 Id" align="center" prop="operatorId" />
|
||||||
|
<el-table-column label="目标租户Id" align="center" prop="targetTenantId" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createdAt" :formatter="dateFormatter" width="180px" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<!-- <el-table-column label="操作" align="center" min-width="120px">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-points:update']">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||||
|
v-hasPermi="['system:tenant-points:delete']">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column> -->
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
<TenantPointsForm ref="formRef" @success="getList" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
|
import download from '@/utils/download'
|
||||||
|
import { TenantPointsApi, TenantPointsVO } from '@/api/system/tenantpoints'
|
||||||
|
import TenantPointsForm from './TenantPointsForm.vue'
|
||||||
|
|
||||||
|
/** 租户积分记录 列表 */
|
||||||
|
defineOptions({ name: 'TenantPoints' })
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中
|
||||||
|
const list = ref<TenantPointsVO[]>([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
type: undefined,
|
||||||
|
remark: undefined, // 兼容后端的 remark 字段
|
||||||
|
description: undefined, // 如果后端有 description,可用于搜索过滤
|
||||||
|
orderId: undefined,
|
||||||
|
bizNo: undefined,
|
||||||
|
operatorId: undefined,
|
||||||
|
targetTenantId: undefined,
|
||||||
|
createdAt: undefined,
|
||||||
|
createdAtArr: [] // 保留原来的数组字段名兼容用(如果你用范围)
|
||||||
|
})
|
||||||
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
|
||||||
|
/** 查询列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
|
||||||
|
const data = await TenantPointsApi.getTenantPointsPage(queryParams)
|
||||||
|
list.value = data.list
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value.resetFields()
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加/修改操作 */
|
||||||
|
const formRef = ref()
|
||||||
|
const openForm = (type: string, id?: number) => {
|
||||||
|
formRef.value.open(type, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.delConfirm()
|
||||||
|
// 发起删除
|
||||||
|
await TenantPointsApi.deleteTenantPoints(id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
// 导出的二次确认
|
||||||
|
await message.exportConfirm()
|
||||||
|
// 发起导出
|
||||||
|
exportLoading.value = true
|
||||||
|
const data = await TenantPointsApi.exportTenantPoints(queryParams)
|
||||||
|
download.excel(data, '租户积分记录.xls')
|
||||||
|
} catch {
|
||||||
|
} finally {
|
||||||
|
exportLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 **/
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user