客服模块的新增
This commit is contained in:
533
package-lock.json
generated
533
package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"@codemirror/lang-javascript": "^6.1.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.0",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"axios": "1.8.2",
|
||||
"codemirror": "^6.0.1",
|
||||
"countup.js": "^2.8.0",
|
||||
@@ -1702,12 +1703,24 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@transloadit/prettier-bytes": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz",
|
||||
"integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz",
|
||||
@@ -1941,6 +1954,63 @@
|
||||
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@uppy/companion-client": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz",
|
||||
"integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uppy/utils": "^4.1.2",
|
||||
"namespace-emitter": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/core": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz",
|
||||
"integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@transloadit/prettier-bytes": "0.0.7",
|
||||
"@uppy/store-default": "^2.1.1",
|
||||
"@uppy/utils": "^4.1.3",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"mime-match": "^1.0.2",
|
||||
"namespace-emitter": "^2.0.1",
|
||||
"nanoid": "^3.1.25",
|
||||
"preact": "^10.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/store-default": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz",
|
||||
"integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@uppy/utils": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz",
|
||||
"integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.throttle": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/xhr-upload": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
|
||||
"integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@uppy/companion-client": "^2.2.2",
|
||||
"@uppy/utils": "^4.1.2",
|
||||
"nanoid": "^3.1.25"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@uppy/core": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitejs/plugin-vue": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
|
||||
@@ -2083,6 +2153,157 @@
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/basic-modules": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
|
||||
"integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"is-url": "^1.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"nanoid": "^3.2.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/code-highlight": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz",
|
||||
"integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prismjs": "^1.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/core": {
|
||||
"version": "1.1.19",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.19.tgz",
|
||||
"integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/event-emitter": "^0.3.3",
|
||||
"event-emitter": "^0.3.5",
|
||||
"html-void-elements": "^2.0.0",
|
||||
"i18next": "^20.4.0",
|
||||
"scroll-into-view-if-needed": "^2.2.28",
|
||||
"slate-history": "^0.66.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@uppy/core": "^2.1.1",
|
||||
"@uppy/xhr-upload": "^2.0.3",
|
||||
"dom7": "^3.0.0",
|
||||
"is-hotkey": "^0.2.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.foreach": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"lodash.toarray": "^4.4.0",
|
||||
"nanoid": "^3.2.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/editor": {
|
||||
"version": "5.1.23",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz",
|
||||
"integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uppy/core": "^2.1.1",
|
||||
"@uppy/xhr-upload": "^2.0.3",
|
||||
"@wangeditor/basic-modules": "^1.1.7",
|
||||
"@wangeditor/code-highlight": "^1.0.3",
|
||||
"@wangeditor/core": "^1.1.19",
|
||||
"@wangeditor/list-module": "^1.0.5",
|
||||
"@wangeditor/table-module": "^1.1.4",
|
||||
"@wangeditor/upload-image-module": "^1.0.2",
|
||||
"@wangeditor/video-module": "^1.1.4",
|
||||
"dom7": "^3.0.0",
|
||||
"is-hotkey": "^0.2.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.foreach": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"lodash.toarray": "^4.4.0",
|
||||
"nanoid": "^3.2.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/list-module": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz",
|
||||
"integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/table-module": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz",
|
||||
"integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"nanoid": "^3.2.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/upload-image-module": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz",
|
||||
"integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@uppy/core": "^2.0.3",
|
||||
"@uppy/xhr-upload": "^2.0.3",
|
||||
"@wangeditor/basic-modules": "1.x",
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"lodash.foreach": "^4.5.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@wangeditor/video-module": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.4.tgz",
|
||||
"integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@uppy/core": "^2.1.4",
|
||||
"@uppy/xhr-upload": "^2.0.7",
|
||||
"@wangeditor/core": "1.x",
|
||||
"dom7": "^3.0.0",
|
||||
"nanoid": "^3.2.0",
|
||||
"slate": "^0.72.0",
|
||||
"snabbdom": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
@@ -2344,6 +2565,12 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/compute-scroll-into-view": {
|
||||
"version": "1.0.20",
|
||||
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
|
||||
"integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -2396,6 +2623,19 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
|
||||
},
|
||||
"node_modules/d": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
|
||||
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es5-ext": "^0.10.64",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||
@@ -2474,6 +2714,16 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom7": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz",
|
||||
"integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ssr-window": "^3.0.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
@@ -2613,6 +2863,46 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es5-ext": {
|
||||
"version": "0.10.64",
|
||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
|
||||
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es6-iterator": "^2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"esniff": "^2.0.1",
|
||||
"next-tick": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-symbol": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
|
||||
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.2",
|
||||
"ext": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
|
||||
@@ -2795,6 +3085,21 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/esniff": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||
@@ -2859,6 +3164,25 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"node_modules/ext": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -3251,6 +3575,25 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/html-void-elements": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
|
||||
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "20.6.1",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz",
|
||||
"integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -3260,6 +3603,16 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immer": {
|
||||
"version": "9.0.21",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
|
||||
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz",
|
||||
@@ -3329,6 +3682,13 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-hotkey": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz",
|
||||
"integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
@@ -3347,6 +3707,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
|
||||
@@ -3356,6 +3725,12 @@
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/is-url": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
|
||||
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
@@ -3476,12 +3851,62 @@
|
||||
"lodash-es": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.foreach": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
||||
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.throttle": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.toarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
|
||||
"integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
@@ -3533,6 +3958,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz",
|
||||
"integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wildcard": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
@@ -3570,6 +4004,12 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/namespace-emitter": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
|
||||
"integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
@@ -3580,6 +4020,7 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@@ -3599,6 +4040,12 @@
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/next-tick": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
@@ -3821,6 +4268,16 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.27.2",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz",
|
||||
"integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@@ -3850,6 +4307,15 @@
|
||||
"resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz",
|
||||
"integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg=="
|
||||
},
|
||||
"node_modules/prismjs": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
||||
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
@@ -4087,6 +4553,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/scroll-into-view-if-needed": {
|
||||
"version": "2.2.31",
|
||||
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
|
||||
"integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"compute-scroll-into-view": "^1.0.20"
|
||||
}
|
||||
},
|
||||
"node_modules/select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||
@@ -4207,6 +4682,40 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/slate": {
|
||||
"version": "0.72.8",
|
||||
"resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz",
|
||||
"integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"immer": "^9.0.6",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"tiny-warning": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/slate-history": {
|
||||
"version": "0.66.0",
|
||||
"resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz",
|
||||
"integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-plain-object": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"slate": ">=0.65.3"
|
||||
}
|
||||
},
|
||||
"node_modules/snabbdom": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.3.tgz",
|
||||
"integrity": "sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sortablejs": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz",
|
||||
@@ -4243,6 +4752,12 @@
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ssr-window": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz",
|
||||
"integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
@@ -4295,6 +4810,12 @@
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"node_modules/tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
@@ -4370,6 +4891,12 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
},
|
||||
"node_modules/type": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
|
||||
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -4803,6 +5330,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/wildcard": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
|
||||
"integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@codemirror/lang-javascript": "^6.1.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.0",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"axios": "1.8.2",
|
||||
"codemirror": "^6.0.1",
|
||||
"countup.js": "^2.8.0",
|
||||
|
||||
@@ -97,6 +97,7 @@ export default defineComponent({
|
||||
<style scoped lang="scss">
|
||||
.cropper-warp {
|
||||
display: flex;
|
||||
|
||||
.cropper-warp-left {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
@@ -108,34 +109,42 @@ export default defineComponent({
|
||||
background-repeat: no-repeat;
|
||||
cursor: move;
|
||||
border-radius: var(--el-border-radius-base);
|
||||
|
||||
.cropper-warp-left-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.cropper-warp-right {
|
||||
width: 150px;
|
||||
height: 350px;
|
||||
|
||||
.cropper-warp-right-title {
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.cropper-warp-right-item {
|
||||
margin: 15px 0;
|
||||
|
||||
.cropper-warp-right-value {
|
||||
display: flex;
|
||||
|
||||
.cropper-warp-right-value-img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: var(--el-border-radius-circle);
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.cropper-size {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.cropper-warp-right-label {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -2,20 +2,14 @@
|
||||
<div class="layout-columns-aside">
|
||||
<el-scrollbar>
|
||||
<ul @mouseleave="onColumnsAsideMenuMouseleave()">
|
||||
<li
|
||||
v-for="(v, k) in columnsAsideList"
|
||||
:key="k"
|
||||
@click="onColumnsAsideMenuClick(v, k)"
|
||||
@mouseenter="onColumnsAsideMenuMouseenter(v, k)"
|
||||
:ref="
|
||||
(el) => {
|
||||
<li v-for="(v, k) in columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v, k)"
|
||||
@mouseenter="onColumnsAsideMenuMouseenter(v, k)" :ref="(el) => {
|
||||
if (el) columnsAsideOffsetTopRefs[k] = el;
|
||||
}
|
||||
"
|
||||
:class="{ 'layout-columns-active': liIndex === k, 'layout-columns-hover': liHoverIndex === k }"
|
||||
:title="$t(v.meta.title)"
|
||||
>
|
||||
<div :class="themeConfig.columnsAsideLayout" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)">
|
||||
" :class="{ 'layout-columns-active': liIndex === k, 'layout-columns-hover': liHoverIndex === k }"
|
||||
:title="$t(v.meta.title)">
|
||||
<div :class="themeConfig.columnsAsideLayout"
|
||||
v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)">
|
||||
<SvgIcon :name="v.meta.icon" />
|
||||
<div class="columns-vertical-title font12">
|
||||
{{
|
||||
@@ -31,7 +25,8 @@
|
||||
<div class="columns-vertical-title font12">
|
||||
{{
|
||||
$t(v.meta.title) && $t(v.meta.title).length >= 4
|
||||
? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 : 3)
|
||||
? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 :
|
||||
3)
|
||||
: $t(v.meta.title)
|
||||
}}
|
||||
</div>
|
||||
@@ -232,8 +227,10 @@ export default defineComponent({
|
||||
width: 70px;
|
||||
height: 100%;
|
||||
background: var(--next-bg-columnsMenuBar);
|
||||
|
||||
ul {
|
||||
position: relative;
|
||||
|
||||
li {
|
||||
color: var(--next-bg-columnsMenuBarColor);
|
||||
width: 100%;
|
||||
@@ -243,43 +240,54 @@ export default defineComponent({
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.columns-vertical {
|
||||
margin: auto;
|
||||
|
||||
.columns-vertical-title {
|
||||
padding-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.columns-horizontal {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
|
||||
i {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
|
||||
.columns-horizontal-title {
|
||||
padding-top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--next-bg-columnsMenuBarColor);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-columns-active {
|
||||
color: var(--next-bg-columnsMenuBarColor) !important;
|
||||
transition: 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.layout-columns-hover {
|
||||
color: var(--el-color-primary);
|
||||
|
||||
a {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.columns-round {
|
||||
background: var(--el-color-primary);
|
||||
color: var(--el-color-white);
|
||||
@@ -293,6 +301,7 @@ export default defineComponent({
|
||||
transition: 0.3s ease-in-out;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.columns-card {
|
||||
@extend .columns-round;
|
||||
top: 0;
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
<template>
|
||||
<div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb">
|
||||
<SvgIcon
|
||||
class="layout-navbars-breadcrumb-icon"
|
||||
:name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
|
||||
:size="16"
|
||||
@click="onThemeConfigChange"
|
||||
/>
|
||||
<SvgIcon class="layout-navbars-breadcrumb-icon" :name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
|
||||
:size="16" @click="onThemeConfigChange" />
|
||||
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
|
||||
<el-breadcrumb-item v-for="(v, k) in breadcrumbList"
|
||||
:key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
|
||||
<span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont"
|
||||
v-if="themeConfig.isBreadcrumbIcon" />
|
||||
<div v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div>
|
||||
<div v-else>{{ v.meta.tagsViewName }}</div>
|
||||
</span>
|
||||
<a v-else @click.prevent="onBreadcrumbClick(v)">
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />{{ $t(v.meta.title) }}
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont"
|
||||
v-if="themeConfig.isBreadcrumbIcon" />{{ $t(v.meta.title) }}
|
||||
</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
@@ -128,6 +127,7 @@ export default defineComponent({
|
||||
height: inherit;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.layout-navbars-breadcrumb-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
@@ -135,26 +135,32 @@ export default defineComponent({
|
||||
height: 100%;
|
||||
width: 40px;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-navbars-breadcrumb-span {
|
||||
display: flex;
|
||||
opacity: 0.7;
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
|
||||
.layout-navbars-breadcrumb-iconfont {
|
||||
font-size: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
:deep(.el-breadcrumb__separator) {
|
||||
opacity: 0.7;
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
|
||||
:deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
|
||||
font-weight: unset !important;
|
||||
color: var(--next-bg-topBarColor);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<template>
|
||||
<el-menu
|
||||
router
|
||||
:default-active="defaultActive"
|
||||
background-color="transparent"
|
||||
:collapse="isCollapse"
|
||||
:unique-opened="getThemeConfig.isUniqueOpened"
|
||||
:collapse-transition="false"
|
||||
>
|
||||
<el-menu router :default-active="defaultActive" background-color="transparent" :collapse="isCollapse"
|
||||
:unique-opened="getThemeConfig.isUniqueOpened" :collapse-transition="false">
|
||||
<template v-for="val in menuLists">
|
||||
<el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||
<template #title>
|
||||
@@ -22,7 +16,8 @@
|
||||
<span>{{ $t(val.meta.title) }}</span>
|
||||
</template>
|
||||
<template #title v-else>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener" class="w100">{{ $t(val.meta.title) }}</a>
|
||||
<a :href="val.meta.isLink" target="_blank" rel="opener" class="w100">{{ $t(val.meta.title)
|
||||
}}</a>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
1974
src/router/route.ts
1974
src/router/route.ts
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ThemeConfigStates, ThemeConfigState } from './interface';
|
||||
import { tr } from 'element-plus/es/locale';
|
||||
|
||||
/**
|
||||
* 布局配置
|
||||
@@ -18,35 +19,35 @@ export const useThemeConfig = defineStore('themeConfig', {
|
||||
/**
|
||||
* 全局主题
|
||||
*/
|
||||
// 主色调:莫兰迪蓝
|
||||
primary: '#6D8BA6',
|
||||
// 默认 primary 主题颜色
|
||||
primary: '#409eff',
|
||||
// 是否开启深色模式
|
||||
isIsDark: false,
|
||||
|
||||
/**
|
||||
* 菜单 / 顶栏 - 多彩渐变方案
|
||||
* 菜单 / 顶栏
|
||||
* 注意:v1.0.17 版本去除设置布局切换,重置主题样式(initSetLayoutChange),
|
||||
* 切换布局需手动设置样式,设置的样式自动同步各布局,
|
||||
* 代码位置:/@/layout/navBars/breadcrumb/setings.vue
|
||||
*/
|
||||
// 顶栏:浅杏色
|
||||
topBar: '#F5E8DA',
|
||||
// 顶栏文字:深灰褐
|
||||
topBarColor: '#5D4E3F',
|
||||
// 默认顶栏导航背景颜色
|
||||
topBar: '#ffffff',
|
||||
// 默认顶栏导航字体颜色
|
||||
topBarColor: '#606266',
|
||||
// 是否开启顶栏背景颜色渐变
|
||||
isTopBarColorGradual: false,
|
||||
|
||||
// 侧边栏:灰绿色
|
||||
menuBar: '#A8B8A5',
|
||||
// 菜单文字:深墨绿
|
||||
menuBarColor: '#2C3E2C',
|
||||
// 默认菜单导航背景颜色
|
||||
menuBar: '#354E67',
|
||||
// 默认菜单导航字体颜色
|
||||
menuBarColor: '#eaeaea',
|
||||
// 是否开启菜单背景颜色渐变
|
||||
isMenuBarColorGradual: false,
|
||||
|
||||
// 分栏菜单:淡紫灰
|
||||
columnsMenuBar: '#D4CDDC',
|
||||
// 分栏文字:深紫灰
|
||||
columnsMenuBarColor: '#4A4453',
|
||||
// 默认分栏菜单背景颜色
|
||||
columnsMenuBar: '#545c64',
|
||||
// 默认分栏菜单字体颜色
|
||||
columnsMenuBarColor: '#e6e6e6',
|
||||
// 是否开启分栏菜单背景颜色渐变
|
||||
isColumnsMenuBarColorGradual: false,
|
||||
|
||||
/**
|
||||
* 界面设置
|
||||
*/
|
||||
|
||||
268
src/views/customerService/account/component/editRole.vue
Normal file
268
src/views/customerService/account/component/editRole.vue
Normal file
@@ -0,0 +1,268 @@
|
||||
<template>
|
||||
<div class="system-edit-role-container">
|
||||
<el-dialog :title="(formData.id === 0 ? '添加' : '修改') + '角色'" v-model="isShowDialog" width="769px">
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="客服id" prop="name">
|
||||
<el-input placeholder="987698789" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="客服平台" prop="name">
|
||||
<el-input placeholder="小红书" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="formData.listOrder" :min="0" controls-position="right" placeholder="请输入排序"
|
||||
class="w100" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="客服状态">
|
||||
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" inline-prompt active-text="启"
|
||||
inactive-text="禁"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="角色描述">
|
||||
<el-input v-model="formData.remark" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="菜单权限">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event)">展开/折叠</el-checkbox>
|
||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event)">全选/全不选</el-checkbox>
|
||||
<el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect($event)">父子联动</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-tree :data="menuData" ref="menuRef" :props="menuProps" :default-checked-keys="formData.menuIds"
|
||||
node-key="id" show-checkbox class="menu-data-tree tree-border"
|
||||
:check-strictly="!menuCheckStrictly" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default" :loading="loading">{{ formData.id === 0 ? '新 增' :
|
||||
'修改' }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, defineComponent, ref, getCurrentInstance, unref } from 'vue';
|
||||
import { addRole, editRole, getRole, getRoleParams } from "/@/api/system/role";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { refreshBackEndControlRoutes } from "/@/router/backEnd";
|
||||
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
pid: number;
|
||||
title: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface DialogRow {
|
||||
id: number;
|
||||
name: string;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
remark: string;
|
||||
menuIds: Array<number>
|
||||
}
|
||||
interface RoleState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: DialogRow;
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuExpand: boolean;
|
||||
menuNodeAll: boolean;
|
||||
menuCheckStrictly: boolean;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
rules: object;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditRole',
|
||||
setup(props, { emit }) {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<RoleState>({
|
||||
loading: false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "角色名称不能为空", trigger: "blur" },
|
||||
]
|
||||
},
|
||||
menuData: [],
|
||||
menuExpand: false,
|
||||
menuNodeAll: false,
|
||||
menuCheckStrictly: false,
|
||||
menuProps: {
|
||||
children: 'children',
|
||||
label: 'title',
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: DialogRow) => {
|
||||
resetForm();
|
||||
getMenuData();
|
||||
if (row) {
|
||||
getRole(row.id).then((res: any) => {
|
||||
if (res.data.role) {
|
||||
state.formData = res.data.role;
|
||||
state.formData.menuIds = res.data.menuIds ?? []
|
||||
}
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
// 新增
|
||||
const onSubmit = () => {
|
||||
const formWrap = unref(formRef) as any;
|
||||
if (!formWrap) return;
|
||||
formWrap.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
state.formData.menuIds = getMenuAllCheckedKeys();
|
||||
if (state.formData.id === 0) {
|
||||
//添加
|
||||
addRole(state.formData).then(() => {
|
||||
ElMessage.success('角色添加成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
} else {
|
||||
//修改
|
||||
editRole(state.formData).then(() => {
|
||||
ElMessage.success('角色修改成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取菜单结构数据
|
||||
const getMenuData = () => {
|
||||
getRoleParams().then((res: any) => {
|
||||
state.menuData = proxy.handleTree(res.data.menu, "id", "pid");
|
||||
})
|
||||
};
|
||||
const resetForm = () => {
|
||||
state.menuCheckStrictly = false;
|
||||
state.menuExpand = false;
|
||||
state.menuNodeAll = false;
|
||||
state.formData = {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
}
|
||||
};
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value: any) => {
|
||||
let treeList = state.menuData;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** 树权限(全选/全不选) */
|
||||
const handleCheckedTreeNodeAll = (value: any) => {
|
||||
menuRef.value.setCheckedNodes(value ? state.menuData : []);
|
||||
}
|
||||
|
||||
/** 树权限(父子联动) */
|
||||
const handleCheckedTreeConnect = (value: any) => {
|
||||
state.menuCheckStrictly = value ? true : false;
|
||||
}
|
||||
|
||||
/** 所有菜单节点数据 */
|
||||
function getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
let checkedKeys = menuRef.value.getCheckedKeys();
|
||||
// 半选中的菜单节点
|
||||
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
}
|
||||
|
||||
// 重置菜单session
|
||||
const resetMenuSession = () => {
|
||||
refreshBackEndControlRoutes();
|
||||
};
|
||||
return {
|
||||
openDialog,
|
||||
closeDialog,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
menuRef,
|
||||
formRef,
|
||||
handleCheckedTreeExpand,
|
||||
handleCheckedTreeNodeAll,
|
||||
handleCheckedTreeConnect,
|
||||
resetMenuSession,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7 !important;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.system-edit-role-container {
|
||||
.menu-data-tree {
|
||||
border: var(--el-input-border, var(--el-border-base));
|
||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div class="system-role-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="客服ID">
|
||||
<el-input size="default" v-model="tableData.param.roleName" placeholder="请输入客服ID"
|
||||
class="w-50 m-2" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="客服平台" prop="status" style="width: 200px;">
|
||||
<el-select placeholder="小红书" clearable size="default" style="width: 240px">
|
||||
<el-option :label="'小红书'" />
|
||||
<el-option :label="'抖音'" />
|
||||
<el-option :label="'快手'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" class="ml10" @click="roleList">
|
||||
<el-icon>
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
|
||||
<el-icon>
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增客服
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="name" label="客服id" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="status" label="客服状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="info" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="客服平台" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="key" label="创建人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="key" label="修改人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="修改时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="220">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onOpenEditRole(scope.row)"><el-icon><ele-EditPen /></el-icon>修改</el-button>
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onRowDel(scope.row)"><el-icon><ele-DeleteFilled /></el-icon>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize" @pagination="roleList" />
|
||||
</el-card>
|
||||
<EditRole ref="editRoleRef" @getRoleList="roleList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent, toRaw, getCurrentInstance } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import EditRole from '/@/views/customerService/account/component/editRole.vue';
|
||||
import { deleteRole, getRoleList } from "/@/api/system/role";
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableData {
|
||||
id: number;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
name: string;
|
||||
remark: string;
|
||||
dataScope: number;
|
||||
createdAt: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableData>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
roleName: string;
|
||||
roleStatus: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const dateList = ref([
|
||||
{
|
||||
"id": 1,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "小红书",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:00:15",
|
||||
"key": 'list'
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:01:34",
|
||||
"key": 'list'
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "快手",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"key": '李四'
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"key": '张三'
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"key": 'zhang'
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "快手",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-06 09:53:40",
|
||||
"key": 'list'
|
||||
}
|
||||
])
|
||||
|
||||
export default defineComponent({
|
||||
name: 'apiV1SystemRoleList',
|
||||
components: { EditRole },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const addRoleRef = ref();
|
||||
const editRoleRef = ref();
|
||||
const dataScopeRef = ref();
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
roleName: '',
|
||||
roleStatus: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
roleList()
|
||||
};
|
||||
const roleList = () => {
|
||||
const data: Array<TableData> = [];
|
||||
getRoleList(state.tableData.param).then(res => {
|
||||
const list = res.data.list ?? []
|
||||
list.map((item: TableData) => {
|
||||
data.push({
|
||||
id: item.id,
|
||||
status: item.status,
|
||||
listOrder: item.listOrder,
|
||||
name: item.name,
|
||||
remark: item.remark,
|
||||
dataScope: item.dataScope,
|
||||
createdAt: item.createdAt,
|
||||
});
|
||||
})
|
||||
state.tableData.data = dateList.value;
|
||||
state.tableData.total = dateList.value.length;
|
||||
})
|
||||
};
|
||||
// 打开新增角色弹窗
|
||||
const onOpenAddRole = () => {
|
||||
editRoleRef.value.openDialog();
|
||||
};
|
||||
// 打开修改角色弹窗
|
||||
const onOpenEditRole = (row: Object) => {
|
||||
editRoleRef.value.openDialog(toRaw(row));
|
||||
};
|
||||
|
||||
// 删除角色
|
||||
const onRowDel = (row: any) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除角色:“${row.name}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteRole(row.id).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
proxy.$refs['editRoleRef'].resetMenuSession();
|
||||
roleList();
|
||||
})
|
||||
})
|
||||
.catch(() => { });
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleSizeChange = (val: number) => {
|
||||
state.tableData.param.pageSize = val;
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleCurrentChange = (val: number) => {
|
||||
state.tableData.param.pageNum = val;
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
});
|
||||
return {
|
||||
addRoleRef,
|
||||
editRoleRef,
|
||||
dataScopeRef,
|
||||
onOpenAddRole,
|
||||
onOpenEditRole,
|
||||
onRowDel,
|
||||
onHandleSizeChange,
|
||||
onHandleCurrentChange,
|
||||
roleList,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
244
src/views/customerService/product/component/editRole.vue
Normal file
244
src/views/customerService/product/component/editRole.vue
Normal file
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<div class="system-edit-role-container">
|
||||
<el-dialog title="" v-model="isShowDialog" width="1000px">
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="产品名称" prop="name">
|
||||
<el-input placeholder="xxx" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 新增富文本编辑器 -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="产品详情" prop="content">
|
||||
<Editor height="400px" placeholder="请输入产品详细描述..." />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default" :loading="loading">{{ formData.id === 0 ? '新 增' :
|
||||
'修改' }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, defineComponent, ref, getCurrentInstance, unref, } from 'vue';
|
||||
import { addRole, editRole, getRole, getRoleParams } from "/@/api/system/role";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { refreshBackEndControlRoutes } from "/@/router/backEnd";
|
||||
// 引入富文本编辑器组件
|
||||
import Editor from '/@/components/editor/index.vue';
|
||||
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
pid: number;
|
||||
title: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface DialogRow {
|
||||
id: number;
|
||||
name: string;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
remark: string;
|
||||
menuIds: Array<number>
|
||||
}
|
||||
interface RoleState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: DialogRow;
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuExpand: boolean;
|
||||
menuNodeAll: boolean;
|
||||
menuCheckStrictly: boolean;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
rules: object;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditRole',
|
||||
components: {
|
||||
Editor // 注册富文本组件
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<RoleState>({
|
||||
loading: false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "角色名称不能为空", trigger: "blur" },
|
||||
]
|
||||
},
|
||||
menuData: [],
|
||||
menuExpand: false,
|
||||
menuNodeAll: false,
|
||||
menuCheckStrictly: false,
|
||||
menuProps: {
|
||||
children: 'children',
|
||||
label: 'title',
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: DialogRow) => {
|
||||
resetForm();
|
||||
getMenuData();
|
||||
if (row) {
|
||||
getRole(row.id).then((res: any) => {
|
||||
if (res.data.role) {
|
||||
state.formData = res.data.role;
|
||||
state.formData.menuIds = res.data.menuIds ?? []
|
||||
}
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
// 新增
|
||||
const onSubmit = () => {
|
||||
const formWrap = unref(formRef) as any;
|
||||
if (!formWrap) return;
|
||||
formWrap.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
state.formData.menuIds = getMenuAllCheckedKeys();
|
||||
if (state.formData.id === 0) {
|
||||
//添加
|
||||
addRole(state.formData).then(() => {
|
||||
ElMessage.success('角色添加成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
} else {
|
||||
//修改
|
||||
editRole(state.formData).then(() => {
|
||||
ElMessage.success('角色修改成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取菜单结构数据
|
||||
const getMenuData = () => {
|
||||
getRoleParams().then((res: any) => {
|
||||
state.menuData = proxy.handleTree(res.data.menu, "id", "pid");
|
||||
})
|
||||
};
|
||||
const resetForm = () => {
|
||||
state.menuCheckStrictly = false;
|
||||
state.menuExpand = false;
|
||||
state.menuNodeAll = false;
|
||||
state.formData = {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
}
|
||||
};
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value: any) => {
|
||||
let treeList = state.menuData;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** 树权限(全选/全不选) */
|
||||
const handleCheckedTreeNodeAll = (value: any) => {
|
||||
menuRef.value.setCheckedNodes(value ? state.menuData : []);
|
||||
}
|
||||
|
||||
/** 树权限(父子联动) */
|
||||
const handleCheckedTreeConnect = (value: any) => {
|
||||
state.menuCheckStrictly = value ? true : false;
|
||||
}
|
||||
|
||||
/** 所有菜单节点数据 */
|
||||
function getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
let checkedKeys = menuRef.value.getCheckedKeys();
|
||||
// 半选中的菜单节点
|
||||
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
}
|
||||
|
||||
// 重置菜单session
|
||||
const resetMenuSession = () => {
|
||||
refreshBackEndControlRoutes();
|
||||
};
|
||||
return {
|
||||
openDialog,
|
||||
closeDialog,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
menuRef,
|
||||
formRef,
|
||||
handleCheckedTreeExpand,
|
||||
handleCheckedTreeNodeAll,
|
||||
handleCheckedTreeConnect,
|
||||
resetMenuSession,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7 !important;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.system-edit-role-container {
|
||||
.menu-data-tree {
|
||||
border: var(--el-input-border, var(--el-border-base));
|
||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,236 @@
|
||||
<template>
|
||||
<div class="system-role-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="产品名称">
|
||||
<el-input size="default" v-model="tableData.param.roleName" placeholder="请输入产品名称"
|
||||
class="w-50 m-2" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" class="ml10" @click="roleList">
|
||||
<el-icon>
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
|
||||
<el-icon>
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增产品
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="name" label="产品名称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="remark" label="创建人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="status" label="修改人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="修改时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="220">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onOpenEditRole(scope.row)"><el-icon><ele-EditPen /></el-icon>修改</el-button>
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onRowDel(scope.row)"><el-icon><ele-DeleteFilled /></el-icon>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize" @pagination="roleList" />
|
||||
</el-card>
|
||||
<EditRole ref="editRoleRef" @getRoleList="roleList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent, toRaw, getCurrentInstance } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import EditRole from '/@/views/customerService/product/component/editRole.vue';
|
||||
import { deleteRole, getRoleList } from "/@/api/system/role";
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableData {
|
||||
id: number;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
name: string;
|
||||
remark: string;
|
||||
dataScope: number;
|
||||
createdAt: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableData>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
roleName: string;
|
||||
roleStatus: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const dateList = ref([
|
||||
{
|
||||
"id": 1,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:00:15"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:01:34"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"status": '李四',
|
||||
"listOrder": 0,
|
||||
"name": "xxx药品",
|
||||
"remark": "张三",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-06 09:53:40"
|
||||
}
|
||||
])
|
||||
|
||||
export default defineComponent({
|
||||
name: 'apiV1SystemRoleList',
|
||||
components: { EditRole },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const addRoleRef = ref();
|
||||
const editRoleRef = ref();
|
||||
const dataScopeRef = ref();
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
roleName: '',
|
||||
roleStatus: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
roleList()
|
||||
};
|
||||
const roleList = () => {
|
||||
const data: Array<TableData> = [];
|
||||
getRoleList(state.tableData.param).then(res => {
|
||||
const list = res.data.list ?? []
|
||||
list.map((item: TableData) => {
|
||||
data.push({
|
||||
id: item.id,
|
||||
status: item.status,
|
||||
listOrder: item.listOrder,
|
||||
name: item.name,
|
||||
remark: item.remark,
|
||||
dataScope: item.dataScope,
|
||||
createdAt: item.createdAt,
|
||||
});
|
||||
})
|
||||
state.tableData.data = dateList.value;
|
||||
state.tableData.total = dateList.value.length;
|
||||
})
|
||||
};
|
||||
// 打开新增角色弹窗
|
||||
const onOpenAddRole = () => {
|
||||
editRoleRef.value.openDialog();
|
||||
};
|
||||
// 打开修改角色弹窗
|
||||
const onOpenEditRole = (row: Object) => {
|
||||
editRoleRef.value.openDialog(toRaw(row));
|
||||
};
|
||||
|
||||
// 删除角色
|
||||
const onRowDel = (row: any) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除角色:“${row.name}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteRole(row.id).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
proxy.$refs['editRoleRef'].resetMenuSession();
|
||||
roleList();
|
||||
})
|
||||
})
|
||||
.catch(() => { });
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleSizeChange = (val: number) => {
|
||||
state.tableData.param.pageSize = val;
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleCurrentChange = (val: number) => {
|
||||
state.tableData.param.pageNum = val;
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
});
|
||||
return {
|
||||
addRoleRef,
|
||||
editRoleRef,
|
||||
dataScopeRef,
|
||||
onOpenAddRole,
|
||||
onOpenEditRole,
|
||||
onRowDel,
|
||||
onHandleSizeChange,
|
||||
onHandleCurrentChange,
|
||||
roleList,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
<template>
|
||||
<div class="system-dic-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
|
||||
|
||||
|
||||
|
||||
|
||||
<el-form-item label="客服平台" prop="status" style="width: 200px;">
|
||||
<el-select v-model="tableData.param.status" placeholder="小红书" clearable size="default"
|
||||
style="width: 240px">
|
||||
<el-option :label="'小红书'" />
|
||||
<el-option :label="'抖音'" />
|
||||
<el-option :label="'快手'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
|
||||
<el-form-item label="" prop="dateRange">
|
||||
<el-date-picker v-model="tableData.param.dateRange" size="default" style="width: 240px"
|
||||
value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="请选择开始日期"
|
||||
end-placeholder="请选择结束日期"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" class="ml10" @click="dataList">
|
||||
<el-icon>
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" @click="resetQuery(queryRef)">
|
||||
<el-icon>
|
||||
<ele-Refresh />
|
||||
</el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange">
|
||||
<!-- <el-table-column type="selection" width="55" align="center" /> -->
|
||||
<el-table-column label="日期" align="center" prop="loginTime" width="180" />
|
||||
<el-table-column label="客服平台" align="center" prop="platform" />
|
||||
<el-table-column label="客服ID" align="center" prop="infoId" />
|
||||
<el-table-column label="客服姓名" align="center" prop="loginName" />
|
||||
<el-table-column label="进线人数" align="center" prop="ipaddr" width="130" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="开口人数" align="center" prop="loginLocation" :s0ow-overflow-tooltip="true" />
|
||||
<el-table-column label="留资卡发送数量" align="center" prop="browser" />
|
||||
<el-table-column label="名片发送数" align="center" prop="os" />
|
||||
<!-- <el-table-column label="留资人数" align="center" prop="status" :formatter="statusFormat" /> -->
|
||||
<el-table-column label="留资人数" align="center" prop="status" />
|
||||
<el-table-column label="接待人数" align="center" prop="msg" />
|
||||
<el-table-column label="30秒回复率" alian="center" prop="module" />
|
||||
<el-table-column label="60秒回复率" alian="center" prop="module" />
|
||||
<el-table-column label="3分钟回复率" alian="center" prop="module" />
|
||||
|
||||
|
||||
</el-table>
|
||||
<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize" @pagination="dataList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance, unref } from 'vue';
|
||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
|
||||
import { logList, deleteLog, clearLog } from '/@/api/system/monitor/loginLog';
|
||||
import { log } from 'console';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableDataRow {
|
||||
infoId: number;
|
||||
loginName: string;
|
||||
ipaddr: string;
|
||||
loginLocation: string;
|
||||
browser: string;
|
||||
os: string;
|
||||
status: number;
|
||||
msg: string;
|
||||
loginTime: string;
|
||||
module: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
ids: number[];
|
||||
tableData: {
|
||||
data: Array<TableDataRow>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
dateRange: string[];
|
||||
status: string;
|
||||
ipaddr: string;
|
||||
loginLocation: any;
|
||||
userName: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'apiV1SystemLoginLogList',
|
||||
setup() {
|
||||
|
||||
//模拟数据
|
||||
const dateList = ref([
|
||||
{
|
||||
"infoId": 434569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '抖音'
|
||||
},
|
||||
{
|
||||
"infoId": 424569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
},
|
||||
{
|
||||
"infoId": 414569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '快手'
|
||||
},
|
||||
{
|
||||
"infoId": 404569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
},
|
||||
{
|
||||
"infoId": 394569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
},
|
||||
{
|
||||
"infoId": 384569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '快手'
|
||||
},
|
||||
{
|
||||
"infoId": 374569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
},
|
||||
{
|
||||
"infoId": 364569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '抖音'
|
||||
},
|
||||
{
|
||||
"infoId": 354569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
},
|
||||
{
|
||||
"infoId": 344569527,
|
||||
"loginName": "demo",
|
||||
"ipaddr": "0",
|
||||
"loginLocation": "0",
|
||||
"browser": "0",
|
||||
"os": "0",
|
||||
"status": 0,
|
||||
"msg": "0",
|
||||
"loginTime": "2025-11-22",
|
||||
"module": "0",
|
||||
"platform": '小红书'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const queryRef = ref();
|
||||
const { admin_login_status } = proxy.useDict('admin_login_status')
|
||||
const state = reactive<TableDataState>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
dateRange: [],
|
||||
status: '',
|
||||
ipaddr: '',
|
||||
loginLocation: '',
|
||||
userName: ''
|
||||
},
|
||||
},
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
dataList()
|
||||
};
|
||||
|
||||
|
||||
|
||||
const dataList = () => {
|
||||
// logList(state.tableData.param).then((res: any) => {
|
||||
// state.tableData.data = res.data.list;
|
||||
// console.log(state.tableData.data, '11111');
|
||||
// state.tableData.total = res.data.total;
|
||||
|
||||
// });
|
||||
|
||||
state.tableData.data = dateList.value;
|
||||
console.log(state.tableData.data, '11111');
|
||||
state.tableData.total = dateList.value.length;
|
||||
|
||||
};
|
||||
// 删除日志
|
||||
const onRowDel = (row: TableDataRow) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let ids: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除:“${row.loginName}”,是否继续?`
|
||||
ids = [row.infoId]
|
||||
4569527
|
||||
} else {
|
||||
ids = state.ids
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteLog(ids).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
dataList();
|
||||
})
|
||||
})
|
||||
.catch(() => { });
|
||||
};
|
||||
// 清空日志
|
||||
const onRowClear = () => {
|
||||
ElMessageBox.confirm('你确定要删除所选数据?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
clearLog().then(() => {
|
||||
ElMessage.success('清除成功');
|
||||
dataList();
|
||||
})
|
||||
})
|
||||
.catch(() => { });
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
});
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
dataList()
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: TableDataRow[]) => {
|
||||
state.ids = selection.map(item => item.infoId)
|
||||
4569527
|
||||
};
|
||||
// 登录状态字典翻译
|
||||
const statusFormat = (row: TableDataRow) => {
|
||||
return proxy.selectDictLabel(unref(admin_login_status), row.status);
|
||||
};
|
||||
return {
|
||||
queryRef,
|
||||
onRowDel,
|
||||
dataList,
|
||||
resetQuery,
|
||||
handleSelectionChange,
|
||||
statusFormat,
|
||||
onRowClear,
|
||||
admin_login_status,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
264
src/views/customerService/script/component/editRole.vue
Normal file
264
src/views/customerService/script/component/editRole.vue
Normal file
@@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<div class="system-edit-role-container">
|
||||
<el-dialog title="" v-model="isShowDialog" width="769px">
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="标签" prop="name">
|
||||
<el-input placeholder="小红书" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="formData.listOrder" :min="0" controls-position="right" placeholder="请输入排序"
|
||||
class="w100" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="客服状态">
|
||||
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" inline-prompt active-text="启"
|
||||
inactive-text="禁"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="话术描述">
|
||||
<el-input type="textarea" placeholder="请输入话术" maxlength="150"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="菜单权限">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event)">展开/折叠</el-checkbox>
|
||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event)">全选/全不选</el-checkbox>
|
||||
<el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect($event)">父子联动</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-tree :data="menuData" ref="menuRef" :props="menuProps" :default-checked-keys="formData.menuIds"
|
||||
node-key="id" show-checkbox class="menu-data-tree tree-border"
|
||||
:check-strictly="!menuCheckStrictly" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default" :loading="loading">{{ formData.id === 0 ? '新 增' :
|
||||
'修改' }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, defineComponent, ref, getCurrentInstance, unref } from 'vue';
|
||||
import { addRole, editRole, getRole, getRoleParams } from "/@/api/system/role";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { refreshBackEndControlRoutes } from "/@/router/backEnd";
|
||||
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
pid: number;
|
||||
title: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface DialogRow {
|
||||
id: number;
|
||||
name: string;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
remark: string;
|
||||
menuIds: Array<number>
|
||||
}
|
||||
interface RoleState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: DialogRow;
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuExpand: boolean;
|
||||
menuNodeAll: boolean;
|
||||
menuCheckStrictly: boolean;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
rules: object;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditRole',
|
||||
setup(props, { emit }) {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<RoleState>({
|
||||
loading: false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "角色名称不能为空", trigger: "blur" },
|
||||
]
|
||||
},
|
||||
menuData: [],
|
||||
menuExpand: false,
|
||||
menuNodeAll: false,
|
||||
menuCheckStrictly: false,
|
||||
menuProps: {
|
||||
children: 'children',
|
||||
label: 'title',
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: DialogRow) => {
|
||||
resetForm();
|
||||
getMenuData();
|
||||
if (row) {
|
||||
getRole(row.id).then((res: any) => {
|
||||
if (res.data.role) {
|
||||
state.formData = res.data.role;
|
||||
state.formData.menuIds = res.data.menuIds ?? []
|
||||
}
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
// 新增
|
||||
const onSubmit = () => {
|
||||
const formWrap = unref(formRef) as any;
|
||||
if (!formWrap) return;
|
||||
formWrap.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
state.formData.menuIds = getMenuAllCheckedKeys();
|
||||
if (state.formData.id === 0) {
|
||||
//添加
|
||||
addRole(state.formData).then(() => {
|
||||
ElMessage.success('角色添加成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
} else {
|
||||
//修改
|
||||
editRole(state.formData).then(() => {
|
||||
ElMessage.success('角色修改成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(() => {
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取菜单结构数据
|
||||
const getMenuData = () => {
|
||||
getRoleParams().then((res: any) => {
|
||||
state.menuData = proxy.handleTree(res.data.menu, "id", "pid");
|
||||
})
|
||||
};
|
||||
const resetForm = () => {
|
||||
state.menuCheckStrictly = false;
|
||||
state.menuExpand = false;
|
||||
state.menuNodeAll = false;
|
||||
state.formData = {
|
||||
id: 0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds: []
|
||||
}
|
||||
};
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value: any) => {
|
||||
let treeList = state.menuData;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** 树权限(全选/全不选) */
|
||||
const handleCheckedTreeNodeAll = (value: any) => {
|
||||
menuRef.value.setCheckedNodes(value ? state.menuData : []);
|
||||
}
|
||||
|
||||
/** 树权限(父子联动) */
|
||||
const handleCheckedTreeConnect = (value: any) => {
|
||||
state.menuCheckStrictly = value ? true : false;
|
||||
}
|
||||
|
||||
/** 所有菜单节点数据 */
|
||||
function getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
let checkedKeys = menuRef.value.getCheckedKeys();
|
||||
// 半选中的菜单节点
|
||||
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
}
|
||||
|
||||
// 重置菜单session
|
||||
const resetMenuSession = () => {
|
||||
refreshBackEndControlRoutes();
|
||||
};
|
||||
return {
|
||||
openDialog,
|
||||
closeDialog,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
menuRef,
|
||||
formRef,
|
||||
handleCheckedTreeExpand,
|
||||
handleCheckedTreeNodeAll,
|
||||
handleCheckedTreeConnect,
|
||||
resetMenuSession,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7 !important;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.system-edit-role-container {
|
||||
.menu-data-tree {
|
||||
border: var(--el-input-border, var(--el-border-base));
|
||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,251 @@
|
||||
<template>
|
||||
<div class="system-role-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :inline="true">
|
||||
<!-- <el-form-item label="客服平台" prop="status" style="width: 200px;">
|
||||
<el-select placeholder="小红书" clearable size="default" style="width: 240px">
|
||||
<el-option :label="'小红书'" />
|
||||
<el-option :label="'抖音'" />
|
||||
<el-option :label="'快手'" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item>
|
||||
<!-- <el-button size="default" type="primary" class="ml10" @click="roleList">
|
||||
<el-icon>
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
筛选
|
||||
</el-button> -->
|
||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
|
||||
<el-icon>
|
||||
<ele-FolderAdd />
|
||||
</el-icon>
|
||||
新增话术
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="label" label="标签" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="creator" label="创建人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="creator" label="修改人" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="createdAt" label="修改时间" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="220">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onOpenEditRole(scope.row)"><el-icon><ele-EditPen /></el-icon>修改</el-button>
|
||||
<el-button size="small" text type="primary"
|
||||
@click="onRowDel(scope.row)"><el-icon><ele-DeleteFilled /></el-icon>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize" @pagination="roleList" />
|
||||
</el-card>
|
||||
<EditRole ref="editRoleRef" @getRoleList="roleList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, defineComponent, toRaw, getCurrentInstance } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import EditRole from '/@/views/customerService/script/component/editRole.vue';
|
||||
import { deleteRole, getRoleList } from "/@/api/system/role";
|
||||
// 定义接口来定义对象的类型
|
||||
interface TableData {
|
||||
id: number;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
name: string;
|
||||
remark: string;
|
||||
dataScope: number;
|
||||
createdAt: string;
|
||||
}
|
||||
interface TableDataState {
|
||||
tableData: {
|
||||
data: Array<TableData>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
roleName: string;
|
||||
roleStatus: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const dateList = ref([
|
||||
{
|
||||
"id": 1,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "小红书",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:00:15",
|
||||
"label": '产品介绍',
|
||||
"creator": '张三'
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-28 10:01:34",
|
||||
"label": '公司介绍',
|
||||
"creator": '张三'
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "快手",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"label": '病症询问',
|
||||
"creator": '王五'
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 3,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"label": '资质问题',
|
||||
"creator": '李四'
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "抖音",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-01 11:38:39",
|
||||
"label": '常用沟通',
|
||||
"creator": '张三'
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"status": 1,
|
||||
"listOrder": 0,
|
||||
"name": "987698789",
|
||||
"remark": "快手",
|
||||
"dataScope": 2,
|
||||
"createdAt": "2022-04-01 11:38:39",
|
||||
"updatedAt": "2022-04-06 09:53:40",
|
||||
"label": '公司介绍',
|
||||
"creator": '张三'
|
||||
}
|
||||
])
|
||||
|
||||
export default defineComponent({
|
||||
name: 'apiV1SystemRoleList',
|
||||
components: { EditRole },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const addRoleRef = ref();
|
||||
const editRoleRef = ref();
|
||||
const dataScopeRef = ref();
|
||||
const state = reactive<TableDataState>({
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
roleName: '',
|
||||
roleStatus: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
roleList()
|
||||
};
|
||||
const roleList = () => {
|
||||
const data: Array<TableData> = [];
|
||||
getRoleList(state.tableData.param).then(res => {
|
||||
const list = res.data.list ?? []
|
||||
list.map((item: TableData) => {
|
||||
data.push({
|
||||
id: item.id,
|
||||
status: item.status,
|
||||
listOrder: item.listOrder,
|
||||
name: item.name,
|
||||
remark: item.remark,
|
||||
dataScope: item.dataScope,
|
||||
createdAt: item.createdAt,
|
||||
});
|
||||
})
|
||||
state.tableData.data = dateList.value;
|
||||
state.tableData.total = dateList.value.length;
|
||||
})
|
||||
};
|
||||
// 打开新增角色弹窗
|
||||
const onOpenAddRole = () => {
|
||||
editRoleRef.value.openDialog();
|
||||
};
|
||||
// 打开修改角色弹窗
|
||||
const onOpenEditRole = (row: Object) => {
|
||||
editRoleRef.value.openDialog(toRaw(row));
|
||||
};
|
||||
|
||||
// 删除角色
|
||||
const onRowDel = (row: any) => {
|
||||
ElMessageBox.confirm(`此操作将永久删除角色:“${row.name}”,是否继续?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteRole(row.id).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
proxy.$refs['editRoleRef'].resetMenuSession();
|
||||
roleList();
|
||||
})
|
||||
})
|
||||
.catch(() => { });
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleSizeChange = (val: number) => {
|
||||
state.tableData.param.pageSize = val;
|
||||
};
|
||||
// 分页改变
|
||||
const onHandleCurrentChange = (val: number) => {
|
||||
state.tableData.param.pageNum = val;
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
});
|
||||
return {
|
||||
addRoleRef,
|
||||
editRoleRef,
|
||||
dataScopeRef,
|
||||
onOpenAddRole,
|
||||
onOpenEditRole,
|
||||
onRowDel,
|
||||
onHandleSizeChange,
|
||||
onHandleCurrentChange,
|
||||
roleList,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
<template>
|
||||
<div class="system-edit-role-container">
|
||||
<el-dialog :title="(formData.id===0?'添加':'修改')+'角色'" v-model="isShowDialog" width="769px">
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="角色名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入角色名称" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="formData.listOrder" :min="0" controls-position="right" placeholder="请输入排序" class="w100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="角色状态">
|
||||
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" inline-prompt active-text="启" inactive-text="禁"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="角色描述">
|
||||
<el-input v-model="formData.remark" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="菜单权限">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event)">展开/折叠</el-checkbox>
|
||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event)">全选/全不选</el-checkbox>
|
||||
<el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect($event)">父子联动</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-tree
|
||||
:data="menuData"
|
||||
ref="menuRef"
|
||||
:props="menuProps"
|
||||
:default-checked-keys="formData.menuIds"
|
||||
node-key="id"
|
||||
show-checkbox class="menu-data-tree tree-border"
|
||||
:check-strictly="!menuCheckStrictly"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" size="default" :loading="loading">{{formData.id===0?'新 增':'修 改'}}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, defineComponent,ref,getCurrentInstance,unref } from 'vue';
|
||||
import {addRole, editRole, getRole, getRoleParams} from "/@/api/system/role";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {refreshBackEndControlRoutes} from "/@/router/backEnd";
|
||||
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface MenuDataTree {
|
||||
id: number;
|
||||
pid:number;
|
||||
title: string;
|
||||
children?: MenuDataTree[];
|
||||
}
|
||||
interface DialogRow {
|
||||
id:number;
|
||||
name: string;
|
||||
status: number;
|
||||
listOrder: number;
|
||||
remark: string;
|
||||
menuIds:Array<number>
|
||||
}
|
||||
interface RoleState {
|
||||
loading:boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: DialogRow;
|
||||
menuData: Array<MenuDataTree>;
|
||||
menuExpand:boolean;
|
||||
menuNodeAll:boolean;
|
||||
menuCheckStrictly:boolean;
|
||||
menuProps: {
|
||||
children: string;
|
||||
label: string;
|
||||
};
|
||||
rules: object;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'systemEditRole',
|
||||
setup(props,{emit}) {
|
||||
const {proxy} = getCurrentInstance() as any;
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<RoleState>({
|
||||
loading:false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id:0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds:[]
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name:[
|
||||
{required: true, message: "角色名称不能为空", trigger: "blur"},
|
||||
]
|
||||
},
|
||||
menuData: [],
|
||||
menuExpand:false,
|
||||
menuNodeAll:false,
|
||||
menuCheckStrictly:false,
|
||||
menuProps: {
|
||||
children: 'children',
|
||||
label: 'title',
|
||||
},
|
||||
});
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: DialogRow) => {
|
||||
resetForm();
|
||||
getMenuData();
|
||||
if(row) {
|
||||
getRole(row.id).then((res:any)=>{
|
||||
if(res.data.role){
|
||||
state.formData = res.data.role;
|
||||
state.formData.menuIds = res.data.menuIds??[]
|
||||
}
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
// 新增
|
||||
const onSubmit = () => {
|
||||
const formWrap = unref(formRef) as any;
|
||||
if (!formWrap) return;
|
||||
formWrap.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
state.formData.menuIds = getMenuAllCheckedKeys();
|
||||
if(state.formData.id===0){
|
||||
//添加
|
||||
addRole(state.formData).then(()=>{
|
||||
ElMessage.success('角色添加成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(()=>{
|
||||
state.loading = false;
|
||||
})
|
||||
}else{
|
||||
//修改
|
||||
editRole(state.formData).then(()=>{
|
||||
ElMessage.success('角色修改成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
resetMenuSession()
|
||||
emit('getRoleList')
|
||||
}).finally(()=>{
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取菜单结构数据
|
||||
const getMenuData = () => {
|
||||
getRoleParams().then((res:any)=>{
|
||||
state.menuData = proxy.handleTree(res.data.menu, "id","pid");
|
||||
})
|
||||
};
|
||||
const resetForm = ()=>{
|
||||
state.menuCheckStrictly=false;
|
||||
state.menuExpand = false;
|
||||
state.menuNodeAll = false;
|
||||
state.formData = {
|
||||
id:0,
|
||||
name: '',
|
||||
status: 1,
|
||||
listOrder: 0,
|
||||
remark: '',
|
||||
menuIds:[]
|
||||
}
|
||||
};
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value:any) => {
|
||||
let treeList = state.menuData;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** 树权限(全选/全不选) */
|
||||
const handleCheckedTreeNodeAll = (value:any) => {
|
||||
menuRef.value.setCheckedNodes(value ? state.menuData : []);
|
||||
}
|
||||
|
||||
/** 树权限(父子联动) */
|
||||
const handleCheckedTreeConnect = (value:any) => {
|
||||
state.menuCheckStrictly = value ? true : false;
|
||||
}
|
||||
|
||||
/** 所有菜单节点数据 */
|
||||
function getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
let checkedKeys = menuRef.value.getCheckedKeys();
|
||||
// 半选中的菜单节点
|
||||
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
}
|
||||
|
||||
// 重置菜单session
|
||||
const resetMenuSession = () => {
|
||||
refreshBackEndControlRoutes();
|
||||
};
|
||||
return {
|
||||
openDialog,
|
||||
closeDialog,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
menuRef,
|
||||
formRef,
|
||||
handleCheckedTreeExpand,
|
||||
handleCheckedTreeNodeAll,
|
||||
handleCheckedTreeConnect,
|
||||
resetMenuSession,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7!important;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.system-edit-role-container {
|
||||
.menu-data-tree {
|
||||
border: var(--el-input-border, var(--el-border-base));
|
||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user