迁入ERP的组织结构树组件,作为通讯录的组织结构;接入相关依赖组件,调整通讯录入口及相关样式
This commit is contained in:
parent
d021415568
commit
43541a1187
@ -13,10 +13,14 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@iconify-json/ion": "^1.2.3",
|
||||
"@kangc/v-md-editor": "^2.3.18",
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"@vueuse/core": "^10.7.0",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.6.2",
|
||||
"highlight.js": "^11.5.0",
|
||||
"js-audio-recorder": "^1.0.7",
|
||||
@ -48,6 +52,7 @@
|
||||
"naive-ui": "^2.35.0",
|
||||
"npm-run-all2": "^6.1.1",
|
||||
"prettier": "^3.1.0",
|
||||
"sass": "^1.88.0",
|
||||
"typescript": "~5.2.0",
|
||||
"unocss": "0.58.0",
|
||||
"vite": "^4.5.1",
|
||||
|
453
pnpm-lock.yaml
453
pnpm-lock.yaml
@ -8,18 +8,30 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@ant-design/icons-vue':
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1(vue@3.5.13(typescript@5.2.2))
|
||||
'@highlightjs/vue-plugin':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(highlight.js@11.11.1)(vue@3.5.13(typescript@5.2.2))
|
||||
'@iconify-json/ion':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
'@kangc/v-md-editor':
|
||||
specifier: ^2.3.18
|
||||
version: 2.3.18(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.2.2))
|
||||
'@vicons/ionicons5':
|
||||
specifier: ^0.13.0
|
||||
version: 0.13.0
|
||||
'@vueup/vue-quill':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0(vue@3.5.13(typescript@5.2.2))
|
||||
'@vueuse/core':
|
||||
specifier: ^10.7.0
|
||||
version: 10.11.1(vue@3.5.13(typescript@5.2.2))
|
||||
ant-design-vue:
|
||||
specifier: ^4.2.6
|
||||
version: 4.2.6(vue@3.5.13(typescript@5.2.2))
|
||||
axios:
|
||||
specifier: ^1.6.2
|
||||
version: 1.9.0
|
||||
@ -80,10 +92,10 @@ importers:
|
||||
version: 2.0.0(typescript@5.2.2)
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^4.4.0
|
||||
version: 4.6.2(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))
|
||||
version: 4.6.2(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))
|
||||
'@vitejs/plugin-vue-jsx':
|
||||
specifier: ^3.0.2
|
||||
version: 3.1.0(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))
|
||||
version: 3.1.0(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))
|
||||
'@vue/tsconfig':
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0
|
||||
@ -108,18 +120,21 @@ importers:
|
||||
prettier:
|
||||
specifier: ^3.1.0
|
||||
version: 3.5.3
|
||||
sass:
|
||||
specifier: ^1.88.0
|
||||
version: 1.88.0
|
||||
typescript:
|
||||
specifier: ~5.2.0
|
||||
version: 5.2.2
|
||||
unocss:
|
||||
specifier: 0.58.0
|
||||
version: 0.58.0(postcss@8.5.3)(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))
|
||||
version: 0.58.0(postcss@8.5.3)(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))
|
||||
vite:
|
||||
specifier: ^4.5.1
|
||||
version: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
version: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
vite-plugin-compression:
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.1(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))
|
||||
version: 0.5.1(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))
|
||||
vue-tsc:
|
||||
specifier: ^1.8.25
|
||||
version: 1.8.27(typescript@5.2.2)
|
||||
@ -133,6 +148,17 @@ packages:
|
||||
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
'@ant-design/colors@6.0.0':
|
||||
resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
|
||||
|
||||
'@ant-design/icons-svg@4.4.2':
|
||||
resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==}
|
||||
|
||||
'@ant-design/icons-vue@7.0.1':
|
||||
resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
|
||||
peerDependencies:
|
||||
vue: '>=3.0.3'
|
||||
|
||||
'@antfu/install-pkg@1.1.0':
|
||||
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
|
||||
|
||||
@ -284,9 +310,19 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.0.11
|
||||
|
||||
'@ctrl/tinycolor@3.6.1':
|
||||
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@emotion/hash@0.8.0':
|
||||
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
|
||||
|
||||
'@emotion/hash@0.9.2':
|
||||
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
|
||||
|
||||
'@emotion/unitless@0.8.1':
|
||||
resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
|
||||
engines: {node: '>=12'}
|
||||
@ -437,6 +473,9 @@ packages:
|
||||
peerDependencies:
|
||||
vue: 3.x
|
||||
|
||||
'@iconify-json/ion@1.2.3':
|
||||
resolution: {integrity: sha512-qV9zsuBFjCgU5WRFO2thhhmaw1wr1wpJMliuuwu7pOtFEEoMOPP45Q7edF+k8uYuouFq+94SlCMIsca+v9kt2g==}
|
||||
|
||||
'@iconify/types@2.0.0':
|
||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||
|
||||
@ -477,17 +516,110 @@ packages:
|
||||
resolution: {integrity: sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@nodelib/fs.stat@1.1.3':
|
||||
resolution: {integrity: sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
'@polka/url@1.0.0-next.29':
|
||||
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
|
||||
'@nodelib/fs.stat@2.0.5':
|
||||
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@nodelib/fs.walk@1.2.8':
|
||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@polka/url@1.0.0-next.29':
|
||||
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
|
||||
|
||||
@ -509,6 +641,9 @@ packages:
|
||||
'@sideway/pinpoint@2.0.0':
|
||||
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
|
||||
|
||||
'@simonwep/pickr@1.8.2':
|
||||
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
||||
|
||||
'@tsconfig/node18@18.2.4':
|
||||
resolution: {integrity: sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ==}
|
||||
|
||||
@ -670,6 +805,9 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
'@vicons/ionicons5@0.13.0':
|
||||
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
|
||||
|
||||
'@vitejs/plugin-vue-jsx@3.1.0':
|
||||
resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
@ -860,6 +998,12 @@ packages:
|
||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ant-design-vue@4.2.6:
|
||||
resolution: {integrity: sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
peerDependencies:
|
||||
vue: '>=3.2.0'
|
||||
|
||||
anymatch@3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -882,6 +1026,9 @@ packages:
|
||||
resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
array-tree-filter@2.1.0:
|
||||
resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==}
|
||||
|
||||
array-union@1.0.2:
|
||||
resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -989,6 +1136,10 @@ packages:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
chrome-trace-event@1.0.4:
|
||||
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -1046,6 +1197,9 @@ packages:
|
||||
component-emitter@1.3.1:
|
||||
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
|
||||
|
||||
compute-scroll-into-view@1.0.20:
|
||||
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
||||
|
||||
computeds@0.0.1:
|
||||
resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
|
||||
|
||||
@ -1359,6 +1513,11 @@ packages:
|
||||
destr@2.0.5:
|
||||
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
|
||||
diff@5.2.0:
|
||||
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
@ -1367,6 +1526,12 @@ packages:
|
||||
resolution: {integrity: sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
dom-align@1.12.4:
|
||||
resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==}
|
||||
|
||||
dom-scroll-into-view@2.0.1:
|
||||
resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
|
||||
|
||||
dompurify@3.1.6:
|
||||
resolution: {integrity: sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==}
|
||||
|
||||
@ -1726,6 +1891,9 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
hasBin: true
|
||||
|
||||
immutable@5.1.2:
|
||||
resolution: {integrity: sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==}
|
||||
|
||||
inflight@1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||
@ -1810,6 +1978,10 @@ packages:
|
||||
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-plain-object@3.0.1:
|
||||
resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-regex@1.2.1:
|
||||
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -1957,6 +2129,10 @@ packages:
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
|
||||
lru-cache@5.1.1:
|
||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||
|
||||
@ -2107,6 +2283,10 @@ packages:
|
||||
resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
micromatch@4.0.8:
|
||||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -2171,6 +2351,9 @@ packages:
|
||||
resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
nanopop@2.4.2:
|
||||
resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==}
|
||||
|
||||
needle@3.3.1:
|
||||
resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==}
|
||||
engines: {node: '>= 4.4.x'}
|
||||
@ -2182,6 +2365,9 @@ packages:
|
||||
next-tick@1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
node-fetch-native@1.6.6:
|
||||
resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==}
|
||||
|
||||
@ -2378,6 +2564,10 @@ packages:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
readdirp@4.1.2:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
regex-not@1.0.2:
|
||||
resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -2425,6 +2615,9 @@ packages:
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
rw@1.3.3:
|
||||
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
|
||||
|
||||
@ -2444,6 +2637,11 @@ packages:
|
||||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
sass@1.88.0:
|
||||
resolution: {integrity: sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
sax@1.4.1:
|
||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
||||
|
||||
@ -2451,6 +2649,9 @@ packages:
|
||||
resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
|
||||
scroll-into-view-if-needed@2.2.31:
|
||||
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
||||
|
||||
section-matter@1.0.0:
|
||||
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||
engines: {node: '>=4'}
|
||||
@ -2486,6 +2687,9 @@ packages:
|
||||
resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
shallow-equal@1.2.1:
|
||||
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2610,6 +2814,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
throttle-debounce@5.0.2:
|
||||
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
|
||||
engines: {node: '>=12.22'}
|
||||
|
||||
tinyexec@1.0.1:
|
||||
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
|
||||
|
||||
@ -2817,6 +3025,12 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
|
||||
vue-types@3.0.2:
|
||||
resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
|
||||
engines: {node: '>=10.15.0'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
vue-virtual-scroller@2.0.0-beta.8:
|
||||
resolution: {integrity: sha512-b8/f5NQ5nIEBRTNi6GcPItE4s7kxNHw2AIHLtDp+2QvqdTjVN0FgONwX9cr53jWRgnu+HRLPaWDOR2JPI5MTfQ==}
|
||||
peerDependencies:
|
||||
@ -2845,6 +3059,9 @@ packages:
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
|
||||
warning@4.0.3:
|
||||
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
|
||||
|
||||
watchpack@2.4.2:
|
||||
resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@ -2924,6 +3141,18 @@ snapshots:
|
||||
'@jridgewell/gen-mapping': 0.3.8
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
|
||||
'@ant-design/colors@6.0.0':
|
||||
dependencies:
|
||||
'@ctrl/tinycolor': 3.6.1
|
||||
|
||||
'@ant-design/icons-svg@4.4.2': {}
|
||||
|
||||
'@ant-design/icons-vue@7.0.1(vue@3.5.13(typescript@5.2.2))':
|
||||
dependencies:
|
||||
'@ant-design/colors': 6.0.0
|
||||
'@ant-design/icons-svg': 4.4.2
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@antfu/install-pkg@1.1.0':
|
||||
dependencies:
|
||||
package-manager-detector: 1.3.0
|
||||
@ -3129,8 +3358,14 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@ctrl/tinycolor@3.6.1': {}
|
||||
|
||||
'@emotion/hash@0.8.0': {}
|
||||
|
||||
'@emotion/hash@0.9.2': {}
|
||||
|
||||
'@emotion/unitless@0.8.1': {}
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
@ -3212,6 +3447,10 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@iconify-json/ion@1.2.3':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
|
||||
'@iconify/types@2.0.0': {}
|
||||
|
||||
'@iconify/utils@2.3.0':
|
||||
@ -3278,15 +3517,81 @@ snapshots:
|
||||
call-me-maybe: 1.0.2
|
||||
glob-to-regexp: 0.3.0
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
run-parallel: 1.2.0
|
||||
|
||||
'@nodelib/fs.stat@1.1.3': {}
|
||||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
'@nodelib/fs.stat@2.0.5': {}
|
||||
|
||||
'@quansync/fs@0.1.2':
|
||||
'@nodelib/fs.walk@1.2.8':
|
||||
dependencies:
|
||||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.19.1
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
is-glob: 4.0.3
|
||||
micromatch: 4.0.8
|
||||
node-addon-api: 7.1.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher-android-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-x64': 2.5.1
|
||||
'@parcel/watcher-freebsd-x64': 2.5.1
|
||||
'@parcel/watcher-linux-arm-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm-musl': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-musl': 2.5.1
|
||||
'@parcel/watcher-linux-x64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-x64-musl': 2.5.1
|
||||
'@parcel/watcher-win32-arm64': 2.5.1
|
||||
'@parcel/watcher-win32-ia32': 2.5.1
|
||||
'@parcel/watcher-win32-x64': 2.5.1
|
||||
optional: true
|
||||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
|
||||
'@rollup/pluginutils@5.1.4(rollup@3.29.5)':
|
||||
@ -3305,6 +3610,11 @@ snapshots:
|
||||
|
||||
'@sideway/pinpoint@2.0.0': {}
|
||||
|
||||
'@simonwep/pickr@1.8.2':
|
||||
dependencies:
|
||||
core-js: 3.42.0
|
||||
nanopop: 2.4.2
|
||||
|
||||
'@tsconfig/node18@18.2.4': {}
|
||||
|
||||
'@types/d3-scale-chromatic@3.1.0': {}
|
||||
@ -3372,13 +3682,13 @@ snapshots:
|
||||
|
||||
'@types/web-bluetooth@0.0.20': {}
|
||||
|
||||
'@unocss/astro@0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))':
|
||||
'@unocss/astro@0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))':
|
||||
dependencies:
|
||||
'@unocss/core': 0.58.0
|
||||
'@unocss/reset': 0.58.0
|
||||
'@unocss/vite': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))
|
||||
'@unocss/vite': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))
|
||||
optionalDependencies:
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
|
||||
@ -3509,7 +3819,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@unocss/core': 0.58.0
|
||||
|
||||
'@unocss/vite@0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))':
|
||||
'@unocss/vite@0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))':
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
'@rollup/pluginutils': 5.1.4(rollup@3.29.5)
|
||||
@ -3521,7 +3831,7 @@ snapshots:
|
||||
chokidar: 3.6.0
|
||||
fast-glob: 3.3.3
|
||||
magic-string: 0.30.17
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
|
||||
@ -3533,19 +3843,21 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@vitejs/plugin-vue-jsx@3.1.0(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))':
|
||||
'@vicons/ionicons5@0.13.0': {}
|
||||
|
||||
'@vitejs/plugin-vue-jsx@3.1.0(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))':
|
||||
dependencies:
|
||||
'@babel/core': 7.27.1
|
||||
'@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.1)
|
||||
'@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.1)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@vitejs/plugin-vue@4.6.2(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))':
|
||||
'@vitejs/plugin-vue@4.6.2(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))(vue@3.5.13(typescript@5.2.2))':
|
||||
dependencies:
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@volar/language-core@1.11.1':
|
||||
@ -3823,6 +4135,32 @@ snapshots:
|
||||
|
||||
ansi-styles@6.2.1: {}
|
||||
|
||||
ant-design-vue@4.2.6(vue@3.5.13(typescript@5.2.2)):
|
||||
dependencies:
|
||||
'@ant-design/colors': 6.0.0
|
||||
'@ant-design/icons-vue': 7.0.1(vue@3.5.13(typescript@5.2.2))
|
||||
'@babel/runtime': 7.27.1
|
||||
'@ctrl/tinycolor': 3.6.1
|
||||
'@emotion/hash': 0.9.2
|
||||
'@emotion/unitless': 0.8.1
|
||||
'@simonwep/pickr': 1.8.2
|
||||
array-tree-filter: 2.1.0
|
||||
async-validator: 4.2.5
|
||||
csstype: 3.1.3
|
||||
dayjs: 1.11.13
|
||||
dom-align: 1.12.4
|
||||
dom-scroll-into-view: 2.0.1
|
||||
lodash: 4.17.21
|
||||
lodash-es: 4.17.21
|
||||
resize-observer-polyfill: 1.5.1
|
||||
scroll-into-view-if-needed: 2.2.31
|
||||
shallow-equal: 1.2.1
|
||||
stylis: 4.3.6
|
||||
throttle-debounce: 5.0.2
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
vue-types: 3.0.2(vue@3.5.13(typescript@5.2.2))
|
||||
warning: 4.0.3
|
||||
|
||||
anymatch@3.1.3:
|
||||
dependencies:
|
||||
normalize-path: 3.0.0
|
||||
@ -3840,6 +4178,8 @@ snapshots:
|
||||
|
||||
arr-union@3.1.0: {}
|
||||
|
||||
array-tree-filter@2.1.0: {}
|
||||
|
||||
array-union@1.0.2:
|
||||
dependencies:
|
||||
array-uniq: 1.0.3
|
||||
@ -3981,6 +4321,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
|
||||
chrome-trace-event@1.0.4: {}
|
||||
|
||||
class-utils@0.3.6:
|
||||
@ -4031,6 +4375,8 @@ snapshots:
|
||||
|
||||
component-emitter@1.3.1: {}
|
||||
|
||||
compute-scroll-into-view@1.0.20: {}
|
||||
|
||||
computeds@0.0.1: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
@ -4363,12 +4709,19 @@ snapshots:
|
||||
|
||||
destr@2.0.5: {}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
optional: true
|
||||
|
||||
diff@5.2.0: {}
|
||||
|
||||
dir-glob@2.2.2:
|
||||
dependencies:
|
||||
path-type: 3.0.0
|
||||
|
||||
dom-align@1.12.4: {}
|
||||
|
||||
dom-scroll-into-view@2.0.1: {}
|
||||
|
||||
dompurify@3.1.6: {}
|
||||
|
||||
downloadjs@1.4.7: {}
|
||||
@ -4758,6 +5111,8 @@ snapshots:
|
||||
image-size@0.5.5:
|
||||
optional: true
|
||||
|
||||
immutable@5.1.2: {}
|
||||
|
||||
inflight@1.0.6:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
@ -4833,6 +5188,8 @@ snapshots:
|
||||
dependencies:
|
||||
isobject: 3.0.1
|
||||
|
||||
is-plain-object@3.0.1: {}
|
||||
|
||||
is-regex@1.2.1:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@ -4970,6 +5327,10 @@ snapshots:
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
|
||||
lru-cache@5.1.1:
|
||||
dependencies:
|
||||
yallist: 3.1.1
|
||||
@ -5234,6 +5595,11 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
micromatch@4.0.8:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-types@2.1.35:
|
||||
@ -5318,6 +5684,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
nanopop@2.4.2: {}
|
||||
|
||||
needle@3.3.1:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
@ -5328,6 +5696,9 @@ snapshots:
|
||||
|
||||
next-tick@1.1.0: {}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
optional: true
|
||||
|
||||
node-fetch-native@1.6.6: {}
|
||||
|
||||
node-releases@2.0.19: {}
|
||||
@ -5509,6 +5880,8 @@ snapshots:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
regex-not@1.0.2:
|
||||
dependencies:
|
||||
extend-shallow: 3.0.2
|
||||
@ -5545,6 +5918,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
run-parallel@1.2.0:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
rw@1.3.3: {}
|
||||
|
||||
rxjs@7.8.2:
|
||||
@ -5563,6 +5940,14 @@ snapshots:
|
||||
|
||||
safer-buffer@2.1.2: {}
|
||||
|
||||
sass@1.88.0:
|
||||
dependencies:
|
||||
chokidar: 4.0.3
|
||||
immutable: 5.1.2
|
||||
source-map-js: 1.2.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher': 2.5.1
|
||||
|
||||
sax@1.4.1:
|
||||
optional: true
|
||||
|
||||
@ -5573,6 +5958,10 @@ snapshots:
|
||||
ajv-formats: 2.1.1(ajv@8.17.1)
|
||||
ajv-keywords: 5.1.0(ajv@8.17.1)
|
||||
|
||||
scroll-into-view-if-needed@2.2.31:
|
||||
dependencies:
|
||||
compute-scroll-into-view: 1.0.20
|
||||
|
||||
section-matter@1.0.0:
|
||||
dependencies:
|
||||
extend-shallow: 2.0.1
|
||||
@ -5614,6 +6003,8 @@ snapshots:
|
||||
is-plain-object: 2.0.4
|
||||
split-string: 3.1.0
|
||||
|
||||
shallow-equal@1.2.1: {}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
shebang-regex: 3.0.0
|
||||
@ -5733,6 +6124,8 @@ snapshots:
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
throttle-debounce@5.0.2: {}
|
||||
|
||||
tinyexec@1.0.1: {}
|
||||
|
||||
to-object-path@0.3.0:
|
||||
@ -5800,9 +6193,9 @@ snapshots:
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
unocss@0.58.0(postcss@8.5.3)(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)):
|
||||
unocss@0.58.0(postcss@8.5.3)(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)):
|
||||
dependencies:
|
||||
'@unocss/astro': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))
|
||||
'@unocss/astro': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))
|
||||
'@unocss/cli': 0.58.0(rollup@3.29.5)
|
||||
'@unocss/core': 0.58.0
|
||||
'@unocss/extractor-arbitrary-variants': 0.58.0
|
||||
@ -5821,9 +6214,9 @@ snapshots:
|
||||
'@unocss/transformer-compile-class': 0.58.0
|
||||
'@unocss/transformer-directives': 0.58.0
|
||||
'@unocss/transformer-variant-group': 0.58.0
|
||||
'@unocss/vite': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0))
|
||||
'@unocss/vite': 0.58.0(rollup@3.29.5)(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0))
|
||||
optionalDependencies:
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
transitivePeerDependencies:
|
||||
- postcss
|
||||
- rollup
|
||||
@ -5867,16 +6260,16 @@ snapshots:
|
||||
evtd: 0.2.4
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
vite-plugin-compression@0.5.1(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)):
|
||||
vite-plugin-compression@0.5.1(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)):
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
debug: 4.4.0
|
||||
fs-extra: 10.1.0
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0)
|
||||
vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(terser@5.39.0):
|
||||
vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0):
|
||||
dependencies:
|
||||
esbuild: 0.18.20
|
||||
postcss: 8.5.3
|
||||
@ -5885,6 +6278,7 @@ snapshots:
|
||||
'@types/node': 18.19.99
|
||||
fsevents: 2.3.3
|
||||
less: 4.3.0
|
||||
sass: 1.88.0
|
||||
terser: 5.39.0
|
||||
|
||||
vooks@0.2.12(vue@3.5.13(typescript@5.2.2)):
|
||||
@ -5923,6 +6317,11 @@ snapshots:
|
||||
semver: 7.7.1
|
||||
typescript: 5.2.2
|
||||
|
||||
vue-types@3.0.2(vue@3.5.13(typescript@5.2.2)):
|
||||
dependencies:
|
||||
is-plain-object: 3.0.1
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
vue-virtual-scroller@2.0.0-beta.8(vue@3.5.13(typescript@5.2.2)):
|
||||
dependencies:
|
||||
mitt: 2.1.0
|
||||
@ -5966,6 +6365,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
warning@4.0.3:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
watchpack@2.4.2:
|
||||
dependencies:
|
||||
glob-to-regexp: 0.4.1
|
||||
|
22
src/api/components.js
Normal file
22
src/api/components.js
Normal file
@ -0,0 +1,22 @@
|
||||
import _axios from '@/utils/erpRequest'
|
||||
export default {
|
||||
deleteDataByParams: (url, data) => _axios.fetch(url, data, 'DELETE'),
|
||||
putDataByParams: (url, data) => _axios.fetch(url, data, 'PUT'),
|
||||
postDataByParams: (url, data) => _axios.fetch(url, data, 'POST'),
|
||||
findDates: ( data) => _axios.fetch('/report/find/dates', data, 'GET'),
|
||||
postBlobByParams: (url, data) => _axios.fetch(url, data, 'POST', 'blob'),
|
||||
getDataByParams: (url, data) => _axios.fetch(url, data, 'GET'),
|
||||
getBlobByParams: (url, data) => _axios.fetch(url, data, 'GET', 'blob'),
|
||||
uploadFormData: (url, data) => _axios.fetch(url, data, 'POST', 'json', '', true, true),
|
||||
viewDetails: (data) => _axios.fetch('/health/info', data, 'POST'),
|
||||
healthDelex: (data) => _axios.fetch('/health/delex', data, 'POST'),
|
||||
healthDrde: (data) => _axios.fetch('/health/drde', data, 'POST'),
|
||||
healthEdit: (data) => _axios.fetch('/health/edit', data, 'POST'),
|
||||
healthAdddr: (data) => _axios.fetch('/health/adddr', data, 'POST'),
|
||||
healthEditStreet: (data) => _axios.fetch('/health/editstreet', data, 'POST'),
|
||||
healthIllmessage: (data) => _axios.fetch('/health/illmessage', data, 'POST'),
|
||||
healthCall: (url, data) => _axios.fetch(url, data, 'POST'),
|
||||
promotionDownload: (data) => _axios.fetch('/collections/extend', data, 'POST', 'blob'),
|
||||
//只能看到我所在的组织机构树
|
||||
viewMyTree: (data) => _axios.fetch('/department/v2/tree/my', data, 'POST'),
|
||||
}
|
18
src/api/index.js
Normal file
18
src/api/index.js
Normal file
@ -0,0 +1,18 @@
|
||||
// 使用 `import.meta.glob` 来同步导入所有匹配的模块
|
||||
// 使用 `{ eager: true }` 选项来立即加载这些模块
|
||||
const modules = import.meta.glob('./*.js', { eager: true });
|
||||
|
||||
const HTTP = {};
|
||||
for (const path in modules) {
|
||||
if (Object.hasOwnProperty.call(modules, path)) {
|
||||
// 正确移除 './' 和 '.js',只保留文件名
|
||||
const componentName = path.replace(/^\.\/(.*)\.\w+$/, '$1');
|
||||
if (componentName !== 'index') {
|
||||
// 确保我们只获取模块的默认导出
|
||||
HTTP[componentName] = modules[path]?.default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出 HTTP 对象
|
||||
export default { HTTP };
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 530 B |
@ -9,13 +9,20 @@
|
||||
<template v-else>
|
||||
{{ title }}
|
||||
</template>
|
||||
<div class="custom-close-btn" v-if="customCloseBtn">
|
||||
<img src="@/assets/image/icon/close-btn-grey.png" alt="" @click="handleCloseModal"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<slot name="content"></slot>
|
||||
<template #footer>
|
||||
<div class="custom-modal-btns">
|
||||
<customBtn color="#C7C7C9" style="width: 161px; height: 34px;" @click="handleCancel"
|
||||
<customBtn
|
||||
color="#C7C7C9"
|
||||
style="width: 161px; height: 34px;"
|
||||
@click="handleCancel"
|
||||
v-if="actionBtns.cancelBtn"
|
||||
>取消</customBtn
|
||||
>
|
||||
<customBtn
|
||||
@ -23,6 +30,7 @@
|
||||
style="width: 161px; height: 34px;"
|
||||
@click="handleConfirm"
|
||||
:loading="state.confirmBtnLoading"
|
||||
v-if="actionBtns.confirmBtn"
|
||||
>确定</customBtn
|
||||
>
|
||||
</div>
|
||||
@ -32,17 +40,29 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, computed } from 'vue'
|
||||
import xNModal from '@/components/x-n-modal/index.vue'
|
||||
import xNModal from '@/components/x-naive-ui/x-n-modal/index.vue'
|
||||
import customBtn from '@/components/common/customBtn.vue'
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
// 是否显示模态框
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
// 模态框标题
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
actionBtns: {
|
||||
// 操作按钮
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
customCloseBtn: {
|
||||
// 是否显示自定义关闭按钮
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
@ -70,12 +90,16 @@ const closeLoading = () => {
|
||||
const state = reactive({
|
||||
confirmBtnLoading: false // 确定按钮loading
|
||||
})
|
||||
|
||||
const handleCloseModal = () => {
|
||||
show.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.custom-modal-header {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
margin: 0 30px;
|
||||
margin: 0 12px;
|
||||
|
||||
.header-content {
|
||||
padding: 0 0 15px;
|
||||
@ -84,6 +108,18 @@ const state = reactive({
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
position: relative;
|
||||
|
||||
.custom-close-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
121
src/components/flnlayout/tree/flnindex.vue
Normal file
121
src/components/flnlayout/tree/flnindex.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="fl-tree width-100 fl-mt-md">
|
||||
<n-tree v-if="state.treeLoading"
|
||||
block-line
|
||||
:default-expanded-keys="state.expandedKeys"
|
||||
:default-selected-keys="state.clickKey"
|
||||
label-field="name"
|
||||
key-field="key"
|
||||
:expand-on-click="true"
|
||||
:render-label="renderLabel"
|
||||
:data="state.treeData"
|
||||
@update:selected-keys="handleSelectTree" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
getCurrentInstance,
|
||||
computed,
|
||||
defineEmits,
|
||||
watch,
|
||||
nextTick,
|
||||
h
|
||||
} from "vue";
|
||||
|
||||
import { PlusCircleOutlined, MinusCircleOutlined, EditOutlined, PlusOutlined, MinusOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import treeLabel from "./treelabel.vue";
|
||||
import { NTree } from 'naive-ui';
|
||||
|
||||
const currentInstance = getCurrentInstance();
|
||||
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||
let props = defineProps({
|
||||
data: Object,
|
||||
refreshCount: Number,
|
||||
config: Object,
|
||||
expandedKeys: Array,
|
||||
clickKey: [String, Number]
|
||||
})
|
||||
const state = reactive({
|
||||
expandedKeys: [],
|
||||
editTitle: '',
|
||||
treeData: [],
|
||||
clickKey: [],
|
||||
treeLoading: true
|
||||
});
|
||||
|
||||
watch(() => props.refreshCount, () => {
|
||||
state.clickKey = [props.clickKey]
|
||||
state.treeLoading = false
|
||||
nextTick(() => {
|
||||
state.treeData = props.data
|
||||
calcDefaultConfig(state.treeData, 1)
|
||||
state.treeLoading = true
|
||||
})
|
||||
});
|
||||
|
||||
watch(() => props.expandedKeys, () => {
|
||||
state.clickKey = [props.clickKey]
|
||||
state.expandedKeys = props.expandedKeys
|
||||
}, { deep: true });
|
||||
|
||||
onBeforeMount(() => {
|
||||
state.clickKey = [props.clickKey]
|
||||
state.treeData = props.data
|
||||
calcDefaultConfig(state.treeData, 1);
|
||||
state.expandedKeys = state.treeData.map(item => item.key)
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
});
|
||||
|
||||
const emit = defineEmits(["triggerTreeAction", "triggerTreeClick", "triggerTreeDefaultClick"]);
|
||||
const handleSelectTree = (keys, option, meta) => {
|
||||
if (keys.length === 1) {
|
||||
emit('triggerTreeClick', { selectedKey: keys[0], tree: option[0] })
|
||||
} else {
|
||||
emit('triggerTreeDefaultClick')
|
||||
}
|
||||
}
|
||||
const renderLabel = (option, checked) => {
|
||||
return h(
|
||||
treeLabel,
|
||||
{
|
||||
dataRef: option,
|
||||
checked: checked,
|
||||
config: props.config,
|
||||
clickKey: props.clickKey,
|
||||
onTriggerTreeAction: handleTreeAction
|
||||
},
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
const calcDefaultConfig = (data, level) => {
|
||||
for (let item of data) {
|
||||
if (!item.key) {
|
||||
item.key = item.title + '_' + level;
|
||||
}
|
||||
item.edit = false
|
||||
if (item.children) {
|
||||
calcDefaultConfig(item.children, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const override = ({ option }) => {
|
||||
if (option.children) {
|
||||
return "toggleExpand";
|
||||
}
|
||||
return "default";
|
||||
};
|
||||
const handleTreeAction = ({ type, val }) => {
|
||||
emit('triggerTreeAction', { type, val })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
121
src/components/flnlayout/tree/treelabel.vue
Normal file
121
src/components/flnlayout/tree/treelabel.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="row items-center">
|
||||
<div v-if="state.treeData.edit">
|
||||
<n-input v-model:value="state.editTitle"
|
||||
style="width:120px" />
|
||||
</div>
|
||||
|
||||
<n-popover trigger="hover"
|
||||
v-else>
|
||||
<template #trigger>
|
||||
<div style="width:120px"
|
||||
class="fl-px-sm sf-text-ellipsis">{{ state.treeData.title }}</div>
|
||||
</template>
|
||||
<div>{{ state.treeData.title }}</div>
|
||||
</n-popover>
|
||||
<n-icon :component="CreateOutline"
|
||||
class="fl-ml-sm"
|
||||
size="20"
|
||||
v-if="config?.actions.includes('edit')&&!state.treeData.edit"
|
||||
@click.stop="handleTreeEdit(state.treeData)" />
|
||||
<n-icon :component="Remove"
|
||||
size="20"
|
||||
v-if="config?.actions.includes('subtraction')&&!state.treeData.edit&&visibleFormItem(config.subtractionShow, state.treeData)"
|
||||
class="fl-ml-sm"
|
||||
@click.stop="handleTreeSubtraction(state.treeData)" />
|
||||
<n-icon :component="Add"
|
||||
size="20"
|
||||
v-if="config?.actions.includes('add')&&!state.treeData.edit&&visibleFormItem(config.addShow, state.treeData)"
|
||||
class="fl-ml-sm"
|
||||
@click.stop="handleTreeAdd(state.treeData)" />
|
||||
<drag-outlined v-if="config?.actions.includes('move')&&!state.treeData.edit&&visibleFormItem(config.moveShow, state.treeData)"
|
||||
class="fl-ml-sm"
|
||||
@click.stop="handleTreeMove(state.treeData)" />
|
||||
|
||||
<!-- <n-icon :component="MoveOutline"
|
||||
size="20"
|
||||
v-if="config?.actions.includes('move')&&!state.treeData.edit&&visibleFormItem(config.moveShow, state.treeData)"
|
||||
class="fl-ml-sm"
|
||||
@click.stop="handleTreeMove(state.treeData)" /> -->
|
||||
|
||||
<n-icon :component="Checkmark"
|
||||
size="20"
|
||||
v-if="state.treeData.edit"
|
||||
class="fl-ml-sm"
|
||||
@click.stop="handleTreeSave(state.treeData)" />
|
||||
<n-icon :component="Close"
|
||||
size="20"
|
||||
v-if="state.treeData.edit"
|
||||
class="fl-ml-md"
|
||||
@click.stop="handleTreeNotSave(state.treeData)" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
watch,
|
||||
reactive
|
||||
} from "vue";
|
||||
import {
|
||||
visibleFormItem,
|
||||
} from "@/utils/helper/form";
|
||||
import {
|
||||
UpOutlined,
|
||||
DownOutlined,
|
||||
CloseCircleOutlined,
|
||||
PlusOutlined,
|
||||
DragOutlined,
|
||||
} from "@ant-design/icons-vue";
|
||||
import { Add, Checkmark, Close, CreateOutline, Remove, MoveOutline } from "@vicons/ionicons5";
|
||||
import { NPopover, NInput, NIcon } from "naive-ui";
|
||||
let props = defineProps({
|
||||
dataRef: Object,
|
||||
checked: Boolean,
|
||||
config: Object,
|
||||
clickKey: [String, Number]
|
||||
})
|
||||
const state = reactive({
|
||||
expandedKeys: [],
|
||||
editTitle: '',
|
||||
treeData: [],
|
||||
});
|
||||
onBeforeMount(() => {
|
||||
state.treeData = props.dataRef.option
|
||||
})
|
||||
watch(() => props.dataRef.option, (val) => {
|
||||
state.treeData = props.dataRef.option
|
||||
}, { deep: true })
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
const emit = defineEmits(["triggerTreeAction", "triggerTreeClick"]);
|
||||
|
||||
// const myComponentRef = ref(null);
|
||||
const handleTreeEdit = () => {
|
||||
state.editTitle = state.treeData.title
|
||||
state.treeData.edit = true
|
||||
// myComponentRef.value.$forceUpdate();
|
||||
}
|
||||
const handleTreeAdd = () => {
|
||||
emit('triggerTreeAction', { type: 'add', val: state.treeData })
|
||||
}
|
||||
const handleTreeMove = () => {
|
||||
emit('triggerTreeAction', { type: 'move', val: state.treeData })
|
||||
}
|
||||
|
||||
const handleTreeSubtraction = () => {
|
||||
emit('triggerTreeAction', { type: 'subtraction', val: state.treeData })
|
||||
}
|
||||
const handleTreeSave = () => {
|
||||
state.treeData.title = state.editTitle
|
||||
emit('triggerTreeAction', { type: 'save', val: state.treeData })
|
||||
}
|
||||
const handleTreeNotSave = () => {
|
||||
state.editTitle = ''
|
||||
emit('triggerTreeAction', { type: 'cancel', val: state.treeData })
|
||||
}
|
||||
</script>
|
||||
|
@ -49,7 +49,11 @@ const state = reactive({
|
||||
height: '314px'
|
||||
}, //自定义模态框样式
|
||||
chatSettingOperateHint: '', // 提示信息
|
||||
chatSettingOperateSubHint: '' // 次要提示信息
|
||||
chatSettingOperateSubHint: '', // 次要提示信息
|
||||
actionBtns: {
|
||||
confirmBtn: true,
|
||||
cancelBtn: true
|
||||
}, // 操作按钮
|
||||
})
|
||||
|
||||
const members = ref<any[]>([])
|
||||
@ -382,6 +386,7 @@ const showChatSettingOperateModal = (type: string) => {
|
||||
:style="state.customModalStyle"
|
||||
:closable="false"
|
||||
@confirm="handleModalConfirm"
|
||||
:actionBtns="state.actionBtns"
|
||||
>
|
||||
<template #content>
|
||||
<div class="custom-modal-content">
|
||||
@ -566,6 +571,8 @@ const showChatSettingOperateModal = (type: string) => {
|
||||
gap: 30px;
|
||||
.btn {
|
||||
width: calc(100% - 50px);
|
||||
background-color: #fff;
|
||||
color: #CF3050;
|
||||
}
|
||||
}
|
||||
|
||||
|
142
src/components/x-naive-ui/README.md
Normal file
142
src/components/x-naive-ui/README.md
Normal file
@ -0,0 +1,142 @@
|
||||
# @x-naive-ui 组件库
|
||||
|
||||
基于 Naive UI 的二次封装组件库,旨在提供更高层级的抽象和更便捷的使用方式,同时保持足够的灵活性。
|
||||
|
||||
@x-naive-ui 的设计理念是在易用性和灵活性之间找到平衡点,通过合理的默认值和可配置项,能够快速开发出高质量的页面,同时保留足够的扩展空间应对特殊需求。
|
||||
|
||||
**如发现文档与实际使用有出入或者不完善 可提交修改**
|
||||
## 设计理念
|
||||
|
||||
### 1. 易用性与灵活性的平衡
|
||||
|
||||
- **约定优于配置**:提供合理的默认值,减少基础使用时的配置量
|
||||
- **保持原有能力**:通过属性透传,保留 Naive UI 原组件的所有功能
|
||||
- **渐进式配置**:简单场景可以快速使用,复杂场景仍可深度定制
|
||||
|
||||
### 2. 通用性与特殊性的权衡
|
||||
|
||||
- **场景覆盖**:优先覆盖 80% 的常见业务场景
|
||||
- **扩展机制**:为剩余 20% 的特殊场景预留扩展接口
|
||||
### 3.<span style="background-color: red;color:#fff">避免过度封装:不追求完美覆盖所有场景,保持组件的可维护性</span>。
|
||||
## 组件列表
|
||||
|
||||
### x-n-data-table
|
||||
数据表格组件,增强了以下能力:
|
||||
- ✨ 拖拽排序(支持整行/手柄模式)
|
||||
- ✨ 列级别的插槽系统
|
||||
- 🎯 统一的样式和交互
|
||||
|
||||
**权衡点**:
|
||||
- 牺牲了一定的性能来换取更好的开发体验
|
||||
- 固化了部分样式以确保视觉一致性
|
||||
|
||||
### x-n-modal
|
||||
模态框组件,预设了常用配置:
|
||||
- ✨ 统一的挂载点管理
|
||||
- ✨ 预设的关闭行为
|
||||
- 🎯 居中布局和统一样式
|
||||
|
||||
**权衡点**:
|
||||
- 限制了一些灵活性以确保使用的一致性
|
||||
- 强制了某些最佳实践(如挂载点)
|
||||
|
||||
### x-n-upload
|
||||
文件上传组件,增强了以下功能:
|
||||
- ✨ 统一的文件处理逻辑
|
||||
- ✨ 内置预览能力
|
||||
- 🎯 更友好的类型支持
|
||||
|
||||
**权衡点**:
|
||||
- 上传接口格式固定,需要后端配合
|
||||
- 为了通用性,部分特殊格式需要额外处理
|
||||
|
||||
### x-search-form
|
||||
搜索表单组件,提供了:
|
||||
- ✨ 声明式配置
|
||||
- ✨ 自动布局
|
||||
- 🎯 统一的搜索重置行为
|
||||
|
||||
**权衡点**:
|
||||
- 牺牲了一些布局灵活性换取使用便利性
|
||||
- 配置项相对复杂,但换来了更好的复用性
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 组件使用建议
|
||||
|
||||
```vue
|
||||
<!-- 推荐:使用声明式配置 -->
|
||||
<x-search-form
|
||||
:search-config="searchConfig"
|
||||
:cols="4"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
|
||||
<!-- 不推荐:内联复杂配置 -->
|
||||
<x-search-form
|
||||
:search-config="[
|
||||
{ type: 'input', key: 'name', label: '姓名' },
|
||||
{ type: 'select', key: 'status', label: '状态' }
|
||||
]"
|
||||
/>
|
||||
```
|
||||
|
||||
### 2. 配置管理建议
|
||||
|
||||
```ts
|
||||
// 推荐:将配置抽离到单独的配置文件
|
||||
import { searchConfig } from './config'
|
||||
import { tableConfig } from './config'
|
||||
|
||||
// 不推荐:在组件内部直接定义<E5AE9A><E4B989><EFBFBD>杂配置
|
||||
const searchConfig = [
|
||||
// ... 大量配置
|
||||
]
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **性能考虑**
|
||||
- 大数据量场景下,优先使用原生组件
|
||||
- 合理使用 `shallowRef` 和 `markRaw`
|
||||
- 避免不必要的响应式转换
|
||||
|
||||
2. **扩展性保证**
|
||||
- 使用 `v-bind` 透传原组件属性
|
||||
- 预留合理的插槽接口
|
||||
- 导出必要的类型定义
|
||||
|
||||
3. **代码质量**
|
||||
- 统一的错误处理机制
|
||||
- 完善的类型声明
|
||||
- 详细的文档注释
|
||||
|
||||
## 未来规划
|
||||
|
||||
1. **组件增强**
|
||||
- 添加更多常用预设
|
||||
- 优化性能表现
|
||||
- 增加更多定制选项
|
||||
|
||||
2. **文档完善**
|
||||
- 补充更多使用示例
|
||||
- 添加在线演示
|
||||
- 完善类型声明
|
||||
|
||||
3. **工具支持**
|
||||
- 提供配置生成器
|
||||
- 添加主题定制能力
|
||||
- 集成表单验证工具
|
||||
|
||||
## 贡献指南
|
||||
|
||||
1. **组件开发原则**
|
||||
- 保持简单性
|
||||
- 关注通用性
|
||||
- 预留扩展性
|
||||
|
||||
2. **代码规范**
|
||||
- 遵循项目 ESLint 配置
|
||||
- 编写单元测试
|
||||
- 提供完整文档
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
54
src/components/x-naive-ui/x-address-select/index.vue
Normal file
54
src/components/x-naive-ui/x-address-select/index.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import levelTwo from "./data/pc-code.json";
|
||||
import levelThree from "./data/pca-code.json";
|
||||
import levelFour from "./data/pcas-code.json";
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 3
|
||||
}
|
||||
});
|
||||
const cascaderRef = ref(null);
|
||||
|
||||
const emit = defineEmits(['update:value']);
|
||||
const levelMap = {
|
||||
2: levelTwo,
|
||||
3: levelThree,
|
||||
4: levelFour
|
||||
};
|
||||
|
||||
const options = computed(() => levelMap[props.level] || []);
|
||||
|
||||
const updateValue = (value, option) => {
|
||||
emit("update:value", value);
|
||||
};
|
||||
defineExpose({
|
||||
cascaderRef
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-cascader
|
||||
ref="cascaderRef"
|
||||
:value="value"
|
||||
placeholder="请选择"
|
||||
:options="options"
|
||||
showPath
|
||||
check-strategy="child"
|
||||
value-field="code"
|
||||
label-field="name"
|
||||
filterable
|
||||
@update:value="updateValue"
|
||||
v-bind="{...$attrs}"
|
||||
/>
|
||||
</template>
|
1688
src/components/x-naive-ui/x-n-upload/index.vue
Normal file
1688
src/components/x-naive-ui/x-n-upload/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
144
src/components/x-naive-ui/x-preview-img/index-1.ts
Normal file
144
src/components/x-naive-ui/x-preview-img/index-1.ts
Normal file
@ -0,0 +1,144 @@
|
||||
import { createApp, h, ref } from 'vue'
|
||||
import { NImage, NImageGroup } from 'naive-ui'
|
||||
|
||||
interface PreviewOptions {
|
||||
onStart?: () => void
|
||||
onError?: (e: Event) => void
|
||||
showToolbar?: boolean
|
||||
}
|
||||
|
||||
class ImagePreview {
|
||||
private static instance: {
|
||||
app: any
|
||||
container: HTMLElement
|
||||
} | null = null
|
||||
|
||||
static async preview(
|
||||
sources: string | File | (string | File)[],
|
||||
index = 0,
|
||||
options: PreviewOptions = {},
|
||||
) {
|
||||
try {
|
||||
const urls = await this.normalizeImageSources(
|
||||
Array.isArray(sources) ? sources : [sources]
|
||||
)
|
||||
|
||||
if (!urls.length) {
|
||||
console.warn('[ImagePreview] No valid image sources')
|
||||
return
|
||||
}
|
||||
|
||||
this.destroy()
|
||||
options.onStart?.()
|
||||
|
||||
const container = document.createElement('div')
|
||||
container.style.display = 'none'
|
||||
document.body.appendChild(container)
|
||||
|
||||
const app = createApp({
|
||||
setup() {
|
||||
const imageRef = ref<InstanceType<typeof NImage> | null>(null)
|
||||
|
||||
return () => {
|
||||
if (urls.length === 1) {
|
||||
return h(NImage, {
|
||||
ref: imageRef,
|
||||
src: urls[0],
|
||||
previewDisabled: false,
|
||||
preview: true,
|
||||
showToolbar: options.showToolbar ?? true,
|
||||
style: {
|
||||
display: 'none'
|
||||
},
|
||||
onLoad: () => {
|
||||
imageRef.value?.click()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return h(NImageGroup, {
|
||||
showToolbar: options.showToolbar ?? true,
|
||||
currentIndex: index
|
||||
}, {
|
||||
default: () => urls.map((url, i) => {
|
||||
const imgRef = ref<InstanceType<typeof NImage> | null>(null)
|
||||
return h(NImage, {
|
||||
ref: i === index ? imgRef : undefined,
|
||||
src: url,
|
||||
previewDisabled: false,
|
||||
preview: true,
|
||||
style: {
|
||||
display: 'none'
|
||||
},
|
||||
onLoad: i === index ? () => {
|
||||
imgRef.value?.click()
|
||||
} : undefined
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.mount(container)
|
||||
this.instance = { app, container }
|
||||
|
||||
} catch (error) {
|
||||
console.error('[ImagePreview] Error:', error)
|
||||
options.onError?.(error as Event)
|
||||
}
|
||||
}
|
||||
|
||||
private static async normalizeImageSources(sources: (string | File)[]): Promise<string[]> {
|
||||
const urls: string[] = []
|
||||
|
||||
for (const source of sources) {
|
||||
try {
|
||||
if (typeof source === 'string') {
|
||||
if (source.startsWith('data:') || source.startsWith('http')) {
|
||||
urls.push(source)
|
||||
} else {
|
||||
console.warn('[ImagePreview] Invalid image source:', source)
|
||||
}
|
||||
} else if (source instanceof File) {
|
||||
const url = await this.fileToUrl(source)
|
||||
urls.push(url)
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[ImagePreview] Failed to process source:', source, error)
|
||||
}
|
||||
}
|
||||
|
||||
return urls
|
||||
}
|
||||
|
||||
private static fileToUrl(file: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
reject(new Error('Not an image file'))
|
||||
return
|
||||
}
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = reject
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
|
||||
private static destroy() {
|
||||
if (this.instance) {
|
||||
const { app, container } = this.instance
|
||||
app.unmount()
|
||||
container.remove()
|
||||
this.instance = null
|
||||
}
|
||||
}
|
||||
|
||||
static close() {
|
||||
this.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export const previewImage = ImagePreview.preview.bind(ImagePreview)
|
||||
export const closePreview = ImagePreview.close.bind(ImagePreview)
|
54
src/components/x-naive-ui/x-preview-img/index.ts
Normal file
54
src/components/x-naive-ui/x-preview-img/index.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import Viewer from 'viewerjs';
|
||||
import 'viewerjs/dist/viewer.css';
|
||||
|
||||
interface PreviewOptions {
|
||||
toolbar?: boolean;
|
||||
navbar?: boolean;
|
||||
transition?: boolean;
|
||||
transitionDuration?: number;
|
||||
// 其他选项
|
||||
}
|
||||
|
||||
export function previewImage(
|
||||
sources: string | File | (string | File)[],
|
||||
index = 0,
|
||||
options: PreviewOptions = {}
|
||||
) {
|
||||
const container = document.createElement('div');
|
||||
container.style.display = 'none';
|
||||
document.body.appendChild(container);
|
||||
|
||||
const processSource = async (source: string | File) => {
|
||||
const img = document.createElement('img');
|
||||
img.src = typeof source === 'string'
|
||||
? source
|
||||
: await readFileAsDataURL(source);
|
||||
container.appendChild(img);
|
||||
};
|
||||
|
||||
const readFileAsDataURL = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => resolve(e.target?.result as string);
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.all(
|
||||
(Array.isArray(sources) ? sources : [sources])
|
||||
.map(source => processSource(source))
|
||||
).then(() => {
|
||||
const viewer = new Viewer(container, {
|
||||
zoomRatio: 0.8,
|
||||
transition: false,
|
||||
transitionDuration: 100, // 默认是300,设置更小的值可以加快动画速度
|
||||
...options,
|
||||
hidden() {
|
||||
viewer.destroy();
|
||||
document.body.removeChild(container);
|
||||
},
|
||||
});
|
||||
viewer.view(index);
|
||||
});
|
||||
}
|
272
src/components/x-naive-ui/x-search-form/index.vue
Normal file
272
src/components/x-naive-ui/x-search-form/index.vue
Normal file
@ -0,0 +1,272 @@
|
||||
<script setup>
|
||||
import { cloneDeep, debounce } from "lodash-es";
|
||||
import { computed, onBeforeUnmount, ref } from "vue";
|
||||
import { NButton, NForm, NFormItemGi, NGrid, NInput, NSelect, NDatePicker } from 'naive-ui'
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
cols: {
|
||||
type: [Number, String],
|
||||
default: 4,
|
||||
},
|
||||
searchConfig: {
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
xGap: {
|
||||
type: [Number, String],
|
||||
default: 81,
|
||||
},
|
||||
yGap: {
|
||||
type: [Number, String],
|
||||
default: 20,
|
||||
},
|
||||
autoSearch: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
debounceWait: {
|
||||
type: Number,
|
||||
default: 300,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['change', 'init'])
|
||||
const resetForm = ref({})
|
||||
const formData = ref({})
|
||||
const indexRef = ref(0)
|
||||
const datePickerRef = ref(null)
|
||||
const formRef = ref(null)
|
||||
|
||||
// 防抖搜索函数
|
||||
const debouncedSearch = debounce(() => {
|
||||
emit('change', formData.value)
|
||||
}, props.debounceWait)
|
||||
|
||||
// 清理防抖函数
|
||||
onBeforeUnmount(() => {
|
||||
debouncedSearch.cancel()
|
||||
})
|
||||
|
||||
// 优化计算属性
|
||||
const calculateEmptySpans = computed(() => {
|
||||
const num = props.searchConfig?.reduce((acc, cur) =>
|
||||
acc + (cur.col || 1), 0
|
||||
)
|
||||
const remainder = num % props.cols
|
||||
return remainder === 0 ? props.cols - 1 : props.cols - remainder - 1
|
||||
})
|
||||
|
||||
// 优化表单值变更处理
|
||||
const manualChange = () => {
|
||||
if (props.autoSearch) {
|
||||
debouncedSearch()
|
||||
}
|
||||
}
|
||||
|
||||
const handleInputChange = (value, item) => {
|
||||
// 如果是pair类型的输入
|
||||
if (item.props?.pair && Array.isArray(item.key)) {
|
||||
// 确保value是数组,如果不是则转换为数组
|
||||
const valueArray = Array.isArray(value) ? value : [value, value];
|
||||
|
||||
// 获取默认值来判断数据类型
|
||||
const defaultValues = Array.isArray(item.default) ? item.default : [];
|
||||
|
||||
// 分别赋值给对应的key,并根据default的类型进行转换
|
||||
item.key.forEach((key, index) => {
|
||||
const defaultValue = defaultValues[index];
|
||||
const currentValue = valueArray[index] || '';
|
||||
|
||||
// 如果默认值是数字类型,则转换为数字
|
||||
if (typeof defaultValue === 'number') {
|
||||
formData.value[key] = currentValue === '' ? defaultValue : Number(currentValue);
|
||||
} else {
|
||||
formData.value[key] = currentValue;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 处理普通输入
|
||||
formData.value[item.key] = value;
|
||||
}
|
||||
manualChange();
|
||||
};
|
||||
const handleSelectChange = (value, item) => {
|
||||
formData.value[item.key] = value
|
||||
console.log('formData.value[item.key]',formData.value[item.key]);
|
||||
manualChange()
|
||||
}
|
||||
const handleDateChange = (value, key) => {
|
||||
if (Array.isArray(key)) {
|
||||
key.forEach((k, i) => {
|
||||
formData.value[k] = value?.[i]
|
||||
})
|
||||
} else {
|
||||
formData.value[key] = value
|
||||
}
|
||||
manualChange()
|
||||
}
|
||||
|
||||
const search = async () => {
|
||||
if (!formRef.value) {
|
||||
emit('change', formData.value)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
emit('change', formData.value)
|
||||
} catch (errors) {
|
||||
console.error('表单验证失败:', errors)
|
||||
}
|
||||
}
|
||||
|
||||
// 优化重置函数
|
||||
const reset = () => {
|
||||
formData.value = cloneDeep(resetForm.value)
|
||||
emit('change', formData.value)
|
||||
indexRef.value++
|
||||
if (formRef.value) {
|
||||
formRef.value?.restoreValidation()
|
||||
}
|
||||
}
|
||||
|
||||
// 优化表单对象生成
|
||||
const generateFormObject = (config) => {
|
||||
return config.reduce((formObject, field) => {
|
||||
const defaultValue = field.default ?? undefined;
|
||||
|
||||
if (Array.isArray(field.key)) {
|
||||
if (Array.isArray(defaultValue)) {
|
||||
field.key.forEach((subKey, index) => {
|
||||
// 使用原始默认值,保持类型一致
|
||||
formObject[subKey] = defaultValue[index];
|
||||
});
|
||||
} else {
|
||||
field.key.forEach(subKey => {
|
||||
formObject[subKey] = defaultValue;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
formObject[field.key] = defaultValue;
|
||||
}
|
||||
|
||||
return formObject;
|
||||
}, {});
|
||||
};
|
||||
|
||||
// 初始化函数
|
||||
const initData = () => {
|
||||
const initialData = generateFormObject(props.searchConfig)
|
||||
formData.value = initialData
|
||||
resetForm.value = cloneDeep(initialData)
|
||||
emit('init', initialData)
|
||||
}
|
||||
|
||||
// 初始化
|
||||
initData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="search-form w-[100%] pb-[20px] bg-[#fff] rounded-[3px] overflow-hidden">
|
||||
<div
|
||||
v-if="title"
|
||||
class="search-form__header h-[59px] border-b-[2px] border-[#EAEAEA]"
|
||||
>
|
||||
<div class="text-[#1F2225] text-[18px] font-[600] h-[100%] flex justify-center align-center w-fit border-b-[4px] border-[#46299D]">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<n-form
|
||||
ref="formRef"
|
||||
class="mt-[20px]"
|
||||
:show-feedback="false"
|
||||
label-placement="left"
|
||||
label-align="left"
|
||||
label-width="110"
|
||||
:key="indexRef"
|
||||
>
|
||||
<n-grid :cols="cols" :x-gap="xGap" :y-gap="yGap">
|
||||
<n-form-item-gi
|
||||
v-for="item in searchConfig"
|
||||
:key="item.key"
|
||||
:span="item.col || 1"
|
||||
:label="item.label"
|
||||
:rule="item.rule"
|
||||
>
|
||||
<!-- Input 类型 -->
|
||||
<template v-if="item.type === 'input'">
|
||||
<n-input
|
||||
:value="formData[item.key]"
|
||||
placeholder="请输入"
|
||||
@input="value => handleInputChange(value, item)"
|
||||
clearable
|
||||
v-bind="item.props"
|
||||
/>
|
||||
</template>
|
||||
<!-- Select 类型 -->
|
||||
<template v-else-if="item.type === 'select'">
|
||||
<n-select
|
||||
:value="formData[item.key]"
|
||||
placeholder="请选择"
|
||||
@update:value="value => handleSelectChange(value, item)"
|
||||
clearable
|
||||
v-bind="item.props"
|
||||
/>
|
||||
</template>
|
||||
<!-- DatePicker 类型 -->
|
||||
<template v-else-if="item.type === 'date-picker'">
|
||||
<n-date-picker
|
||||
ref="datePickerRef"
|
||||
class="w-[100%]"
|
||||
clearable
|
||||
:value="formData[item.key]"
|
||||
@update-formatted-value="value => handleDateChange(value, item.key)"
|
||||
v-bind="item.props"
|
||||
/>
|
||||
</template>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 空白占位 -->
|
||||
<n-form-item-gi :span="calculateEmptySpans" />
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<n-form-item-gi :span="1">
|
||||
<div class="flex justify-end w-full">
|
||||
<n-button
|
||||
class="w-[145px] h-[34px] mr-[20px]"
|
||||
@click="search"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
>
|
||||
查询
|
||||
</n-button>
|
||||
<n-button
|
||||
class="w-[145px] h-[34px]"
|
||||
color="#EEE9F8"
|
||||
text-color="#46299D"
|
||||
@click="reset"
|
||||
>
|
||||
重置
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-form {
|
||||
&__header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,10 +1,10 @@
|
||||
// 主题配置
|
||||
export const overrides = {
|
||||
common: {
|
||||
primaryColor: '#1890ff',
|
||||
primaryColorHover: '#1890ff',
|
||||
primaryColorPressed: '#1890ff',
|
||||
primaryColorSuppl: '#1890ff',
|
||||
primaryColor: '#46299D',
|
||||
primaryColorHover: '#46299D',
|
||||
primaryColorPressed: '#46299D',
|
||||
primaryColorSuppl: '#46299D',
|
||||
bodyColor: '#ffffff'
|
||||
},
|
||||
|
||||
|
@ -1,16 +1,20 @@
|
||||
import '@/assets/css/define/theme.less'
|
||||
import '@/assets/css/define/global.less'
|
||||
import '@/assets/css/dropsize.less'
|
||||
import 'uno.css'
|
||||
import { createApp } from 'vue'
|
||||
import router from './router'
|
||||
import App from './App.vue'
|
||||
import * as plugins from './plugins'
|
||||
import request from "@/api/index.js";
|
||||
|
||||
async function bootstrap() {
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
|
||||
app.config.globalProperties.$request = request;
|
||||
|
||||
plugins.setPinia(app)
|
||||
plugins.setHljsVuePlugin(app)
|
||||
plugins.setupNaive(app)
|
||||
|
@ -18,7 +18,7 @@ export function isLoggedIn() {
|
||||
*/
|
||||
export function getAccessToken() {
|
||||
// return storage.get(AccessToken) || ''
|
||||
return JSON.parse(localStorage.getItem('token'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b892000b1d18303354ea8a7c57f91ffb617f5d82513d2af46e6ce5848a80c59c75b9ddf4a552092d70ecda72c97d99cb5d0f114a50ddfd9674f22576675e3390d2367951eb502aa1dd94e8823d528a503fb'
|
||||
return JSON.parse(localStorage.getItem('token'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b891bd3a81a1ac4e73e2aed60deeaec60792c525cc0c96e8f4a666eca6ee7a10716507b402cde5759bbcda1fa681fbe4dcdfe05abbc2b1644c68dc74ebaf8d9c9cc4eb61afaf3de52fa357dbfdfe17acf14'
|
||||
}
|
||||
|
||||
/**
|
||||
|
143
src/utils/erpRequest.js
Normal file
143
src/utils/erpRequest.js
Normal file
@ -0,0 +1,143 @@
|
||||
import axios from "axios";
|
||||
import $router from "../router";
|
||||
import { message } from "ant-design-vue";
|
||||
import { Local } from "@/utils/erpStorage.js";
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_EPR_BASEURL,
|
||||
timeout: 60 * 60 * 1000,
|
||||
authToken: true,
|
||||
responseType: "json", // 请求数据格式
|
||||
});
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
// set header Content-Type
|
||||
if (config.method === "get") {
|
||||
// || config.method === "delete"
|
||||
config.headers["Content-Type"] = "application/x-www-form-urlencoded";
|
||||
} else {
|
||||
config.headers["Content-Type"] = "application/json";
|
||||
}
|
||||
if (config.isFormData) {
|
||||
config.headers["Content-Type"] = "multipart/form-data";
|
||||
config.headers.Authorization = Local.get("token") || "";
|
||||
} else config.headers.Authorization = Local.get("token") || "";
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
let isRefreshing = false;
|
||||
let refreshSubscribers = [];
|
||||
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
let isResourse = response.config.responseType;
|
||||
if (response && response.data.status === 409) {
|
||||
// 账户另一处登录 此处踢下线
|
||||
message.error('您的账号已在其他设备登录')
|
||||
$router.push("/login");
|
||||
return;
|
||||
}
|
||||
if (response && response.data.code === 401) {
|
||||
// 若token过期则态获取RefreshToken重新获取token
|
||||
return getRefreshToken(response);
|
||||
}
|
||||
if (
|
||||
response.status === 200 ||
|
||||
response.status === 201 ||
|
||||
response.status === 204
|
||||
) {
|
||||
return isResourse == "blob" ? response : response.data;
|
||||
} else {
|
||||
message.success(res.msg);
|
||||
Promise.reject(response);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
const getRefreshToken = async (response) => {
|
||||
if (!isRefreshing) {
|
||||
isRefreshing = true;
|
||||
const refreshToken = Local.get("RefreshToken");
|
||||
if (refreshToken) {
|
||||
try {
|
||||
const data = { refreshToken };
|
||||
const res = await fetch(
|
||||
"/user/refresh/token",
|
||||
data,
|
||||
"POST",
|
||||
"json",
|
||||
"application/json",
|
||||
false
|
||||
);
|
||||
if (res.code === 200) {
|
||||
Local.set("token", res.data.Token);
|
||||
Local.set("userInfo", res.data.AccountInfo);
|
||||
Local.set("RefreshToken", res.data.RefreshToken);
|
||||
|
||||
return Promise.resolve(service(response.config));
|
||||
} else {
|
||||
// 跳转登录页
|
||||
$router.push("/login");
|
||||
res.message = res.message || res.msg;
|
||||
return Promise.reject(res);
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
refreshSubscribers.forEach((callback) => callback());
|
||||
refreshSubscribers = [];
|
||||
}
|
||||
} else {
|
||||
$router.push("/login");
|
||||
return Promise.reject(response);
|
||||
}
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
refreshSubscribers.push(() => {
|
||||
resolve(service(response.config));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const fetch = async (
|
||||
url = "",
|
||||
data = {},
|
||||
method = "",
|
||||
responseType = "json",
|
||||
contentType = "",
|
||||
authToken = true,
|
||||
isFormData = false
|
||||
) => {
|
||||
if (!method) {
|
||||
method = "GET";
|
||||
}
|
||||
let args = { url, method };
|
||||
if (method === "GET") {
|
||||
// || method === "DELETE"
|
||||
args.params = data;
|
||||
} else {
|
||||
args.data = data;
|
||||
}
|
||||
if (contentType) {
|
||||
args = Object.assign({}, args, {
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 请求数据格式
|
||||
args.responseType = responseType;
|
||||
args.authToken = authToken;
|
||||
args.isFormData = isFormData;
|
||||
return service(args);
|
||||
};
|
||||
export default { fetch, getRefreshToken };
|
91
src/utils/erpStorage.js
Normal file
91
src/utils/erpStorage.js
Normal file
@ -0,0 +1,91 @@
|
||||
function createStorage(storage) {
|
||||
const cache = new Map();
|
||||
const stringifyCache = new Map();
|
||||
const batchWrites = [];
|
||||
let flushTimer = null;
|
||||
|
||||
// 优化的 JSON 序列化
|
||||
function fastStringify(obj) {
|
||||
const type = typeof obj;
|
||||
if (obj === null) return 'null';
|
||||
if (type === 'string') return `"${obj}"`;
|
||||
if (type === 'number' || type === 'boolean') return String(obj);
|
||||
if (type !== 'object') return '{}';
|
||||
|
||||
const cached = stringifyCache.get(obj);
|
||||
if (cached) return cached;
|
||||
|
||||
try {
|
||||
const result = JSON.stringify(obj);
|
||||
if (result.length < 1000) {
|
||||
stringifyCache.set(obj, result);
|
||||
}
|
||||
return result;
|
||||
} catch {
|
||||
return '{}';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
set(key, val) {
|
||||
if (!key) return;
|
||||
|
||||
try {
|
||||
// 更新缓存
|
||||
cache.set(key, val);
|
||||
|
||||
// 序列化并立即写入
|
||||
const serialized = fastStringify(val);
|
||||
storage.setItem(key, serialized);
|
||||
|
||||
// 批量写入作为备份
|
||||
batchWrites.push([key, serialized]);
|
||||
if (!flushTimer) {
|
||||
flushTimer = setTimeout(() => {
|
||||
batchWrites.forEach(([k, v]) => {
|
||||
try { storage.setItem(k, v); } catch {}
|
||||
});
|
||||
batchWrites.length = 0;
|
||||
flushTimer = null;
|
||||
}, 100);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Storage error:', e);
|
||||
}
|
||||
},
|
||||
|
||||
get(key) {
|
||||
if (!key) return null;
|
||||
|
||||
// 优先读缓存
|
||||
const cached = cache.get(key);
|
||||
if (cached !== undefined) return cached;
|
||||
|
||||
try {
|
||||
const val = JSON.parse(storage.getItem(key));
|
||||
cache.set(key, val);
|
||||
return val;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
remove(key) {
|
||||
cache.delete(key);
|
||||
storage.removeItem(key);
|
||||
},
|
||||
clear() {
|
||||
cache.clear();
|
||||
stringifyCache.clear();
|
||||
storage.clear();
|
||||
batchWrites.length = 0;
|
||||
if (flushTimer) {
|
||||
clearTimeout(flushTimer);
|
||||
flushTimer = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
// 导出单例实例
|
||||
export const Local = createStorage(window.localStorage);
|
||||
export const Session = createStorage(window.sessionStorage);
|
347
src/utils/helper/form.js
Normal file
347
src/utils/helper/form.js
Normal file
@ -0,0 +1,347 @@
|
||||
export const getParamsByObj = (params, paramsConfig, obj) => {
|
||||
if (paramsConfig !== undefined && paramsConfig.length > 0 && obj !== null) {
|
||||
for (let i in paramsConfig) {
|
||||
let paramsItem = paramsConfig[i];
|
||||
if (paramsItem.value !== undefined) {
|
||||
params[paramsItem.label] = paramsItem.value;
|
||||
}
|
||||
if (obj && paramsItem.field !== undefined) {
|
||||
if (
|
||||
obj[paramsItem.field] !== undefined &&
|
||||
obj[paramsItem.field] !== null
|
||||
) {
|
||||
params[paramsItem.label] = obj[paramsItem.field];
|
||||
// 对值数组化
|
||||
params[paramsItem.label] =
|
||||
paramsItem.type === "Array"
|
||||
? [params[paramsItem.label]]
|
||||
: params[paramsItem.label];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
export const getLabelByOptions = (val, options, customEmpty) => {
|
||||
let label = "";
|
||||
let valOpt = {};
|
||||
for (let i in options) {
|
||||
if (options[i].value === val) {
|
||||
valOpt = options[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valOpt.class || valOpt.style) {
|
||||
return `<div class="sf-status-label ${valOpt.class}" style="${
|
||||
valOpt.style
|
||||
}">${valOpt.label || customEmpty}</div>`;
|
||||
}
|
||||
return valOpt.label || customEmpty;
|
||||
};
|
||||
|
||||
export const getFormObj = (formConfig) => {
|
||||
let data = {};
|
||||
formConfig.forEach((item) => {
|
||||
if (item.field) {
|
||||
data[item.field] = item.value;
|
||||
if (item.type === "date") {
|
||||
data[item.field] = item.value ? item.value?.format("YYYY-MM-DD") : "";
|
||||
}
|
||||
}
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
export const setFormObj = (formConfig, data) => {
|
||||
formConfig.forEach((item) => {
|
||||
if (item.field && data[item.field] !== undefined) {
|
||||
item.value = data[item.field];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const clearObj = (formData) => {
|
||||
for (let field in formData) {
|
||||
if (Array.isArray(formData[field])) {
|
||||
formData[field] = [];
|
||||
} else if (
|
||||
Object.prototype.toString.call(formData[field]) === "[object Number]"
|
||||
) {
|
||||
formData[field] = 0;
|
||||
} else if (
|
||||
Object.prototype.toString.call(formData[field]) === "[object Object]"
|
||||
) {
|
||||
formData[field] = {};
|
||||
} else {
|
||||
formData[field] = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const visibleFormItem = (itemshow, formObj = {}) => {
|
||||
let flag = true;
|
||||
if (Object.prototype.toString.call(itemshow) === "[object Function]") {
|
||||
return itemshow(formObj);
|
||||
}
|
||||
if (Object.prototype.toString.call(itemshow) === "[object Boolean]") {
|
||||
return itemshow;
|
||||
}
|
||||
let mathArr = [
|
||||
"+",
|
||||
"-",
|
||||
"/",
|
||||
"*",
|
||||
">",
|
||||
">=",
|
||||
"<",
|
||||
"<=",
|
||||
"==",
|
||||
"===",
|
||||
"!==",
|
||||
"||",
|
||||
"&&",
|
||||
];
|
||||
if (itemshow && Object.keys(formObj).length > 0) {
|
||||
let expression = itemshow
|
||||
.replace(/\[%=/g, "")
|
||||
.replace(/%\]/g, "")
|
||||
.replace(/'/g, "");
|
||||
let cs = expression.split(/(\/|%|\*|\+|-|&&|\|\||>|<|>=|<=|\(|\)|===|!==)/);
|
||||
for (let idx in cs) {
|
||||
let csItem = cs[idx];
|
||||
// 右边为''
|
||||
if (formObj[csItem] === "") {
|
||||
cs[idx] = "'" + formObj[csItem] + "'";
|
||||
// 左边可转为数值计算
|
||||
} else if (
|
||||
formObj[csItem] !== undefined &&
|
||||
Object.prototype.toString.call(formObj[csItem]) === "object String"
|
||||
) {
|
||||
cs[idx] = formObj[csItem];
|
||||
} else if (
|
||||
formObj[csItem] !== undefined &&
|
||||
Object.prototype.toString.call(formObj[csItem]) === "object Number"
|
||||
) {
|
||||
cs[idx] = "'" + formObj[csItem] + "'";
|
||||
// 左边字段不存在 右边字段值字符串化
|
||||
} else if (!mathArr.includes(csItem) && formObj[csItem] === undefined) {
|
||||
cs[idx] = "'" + csItem + "'";
|
||||
// 计算公式
|
||||
} else if (mathArr.includes(csItem)) {
|
||||
cs[idx] = csItem;
|
||||
} else {
|
||||
// 左边 在obj中存在 字符串化
|
||||
cs[idx] = "'" + formObj[csItem] + "'";
|
||||
}
|
||||
}
|
||||
cs = cs.join("");
|
||||
flag = flag && window.eval(cs);
|
||||
}
|
||||
return flag;
|
||||
};
|
||||
|
||||
export const validateItem = (item, itemValue) => {
|
||||
let validate = item.validate;
|
||||
let noErr = true;
|
||||
let message = "";
|
||||
switch (validate) {
|
||||
case "required": {
|
||||
// ADD input type is number is empty is null And dropdowntable,userDropdowntable,dropdownbox is empty is []
|
||||
if (itemValue === null || itemValue.length === 0) {
|
||||
noErr = false;
|
||||
message = "请输入内容";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
// ADD input type is number is empty is null And dropdowntable,userDropdowntable,dropdownbox is empty is []
|
||||
if (itemValue === null || itemValue.length === 0) {
|
||||
noErr = false;
|
||||
message = "请输入内容";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "email": {
|
||||
const regEmail =
|
||||
/^[a-zA-Z0-9_-]+([._\\-]*[a-zA-Z0-9_-])*@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
|
||||
if (regEmail.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入正确邮箱";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "chinese": {
|
||||
const regChinese = /^[^\u4e00-\u9fa5]{0,}$/;
|
||||
if (regChinese.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入中文字符";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "maxDecimals4": {
|
||||
// let regDecimals2 = /^\d+(\.\d{2})?$/
|
||||
const regDecimals4 = /^\d+(?:\.\d{1,4})?$/;
|
||||
if (
|
||||
itemValue !== null &&
|
||||
itemValue !== "" &&
|
||||
regDecimals4.test(itemValue) === false
|
||||
) {
|
||||
noErr = false;
|
||||
message = "最多四位小数";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "english": {
|
||||
// 添加英文支持-
|
||||
const regEnglish = /^[a-zA-Z0-9_@-]{1,}$/;
|
||||
if (regEnglish.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入英文字符";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "datetime": {
|
||||
const regDatetime =
|
||||
/^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/;
|
||||
if (regDatetime.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入正确时间";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
const regDate = /^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/;
|
||||
if (regDate.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入正确日期";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "time": {
|
||||
const regTime = /^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/;
|
||||
if (regTime.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入正确时间";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "interger": {
|
||||
const regInterger = /^[1-9]\d*$/;
|
||||
if (regInterger.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入整数";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "positiveNumber": {
|
||||
// 包括0的正数
|
||||
if (itemValue < 0) {
|
||||
noErr = false;
|
||||
message = "请输入非负数";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "gt0Number": {
|
||||
// 不包括0的正数
|
||||
if (itemValue <= 0) {
|
||||
noErr = false;
|
||||
message = "请输入非零正数";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "telephone": {
|
||||
const telephoneNumber = /^1(3|4|5|6|7|8|9)\d{9}$/;
|
||||
if (telephoneNumber.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入正确手机号码";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "pwdstrong": {
|
||||
const forceRegex = new RegExp("(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z]).{6,20}");
|
||||
if (forceRegex.test(itemValue) === false) {
|
||||
noErr = false;
|
||||
message = "请输入符合格式的密码";
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
noErr = true;
|
||||
}
|
||||
|
||||
if (!noErr) {
|
||||
item.errorMessage = message;
|
||||
} else {
|
||||
item.errorMessage = "";
|
||||
}
|
||||
};
|
||||
export const validataForm = (formConfig) => {
|
||||
if (formConfig) {
|
||||
let formHasErr = false;
|
||||
formConfig.forEach((item) => {
|
||||
if (item.validate !== undefined) {
|
||||
validateItem(item, item.value);
|
||||
}
|
||||
if (item.errorMessage) {
|
||||
formHasErr = true;
|
||||
}
|
||||
});
|
||||
return formHasErr;
|
||||
}
|
||||
};
|
||||
export const calcFormat = (config, val) => {
|
||||
if (val === 0 || val === "0") {
|
||||
return 0;
|
||||
}
|
||||
if (config.format === "w" && val) {
|
||||
return ((Number(val) * 1) / 10000).toFixed(config.toFixed || 2) + "w";
|
||||
}
|
||||
};
|
||||
export const verifyFormat = (config, val) => {
|
||||
// 满足 true
|
||||
if (config.verifyFormat === ".00" && val) {
|
||||
return val.endsWith(".00");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
export const deepCopy = (obj) => {
|
||||
let copy;
|
||||
// 处理非对象类型和函数类型
|
||||
if (obj === null || typeof obj !== "object" || obj instanceof Function) {
|
||||
return obj;
|
||||
}
|
||||
// 处理日期类型
|
||||
if (obj instanceof Date) {
|
||||
copy = new Date();
|
||||
copy.setTime(obj.getTime());
|
||||
return copy;
|
||||
}
|
||||
// 处理数组类型
|
||||
if (obj instanceof Array) {
|
||||
copy = [];
|
||||
for (let i = 0, len = obj.length; i < len; i++) {
|
||||
copy[i] = deepCopy(obj[i]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
// 处理对象类型
|
||||
if (obj instanceof Object) {
|
||||
copy = {};
|
||||
for (let prop in obj) {
|
||||
if (obj.hasOwnProperty(prop)) {
|
||||
copy[prop] = deepCopy(obj[prop]);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
throw new Error("无法复制此对象,因为类型未知: " + obj);
|
||||
};
|
||||
// 数值千分位显示
|
||||
export const formatNumberWithCommas = (num) => {
|
||||
if (!num) return 0;
|
||||
if (typeof num === "string") {
|
||||
num = Number(num);
|
||||
}
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
};
|
9
src/utils/helper/message.js
Normal file
9
src/utils/helper/message.js
Normal file
@ -0,0 +1,9 @@
|
||||
export const processSuccess = (res, time = 3) => {
|
||||
message.success(res, time)
|
||||
}
|
||||
export const processError = (res, time = 3) => {
|
||||
message.error(res, time)
|
||||
}
|
||||
export const processWarning = (res, time = 3) => {
|
||||
message.warning(res, time)
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onMounted,watch } from 'vue'
|
||||
import { computed, ref, onMounted, watch, reactive, onBeforeMount, getCurrentInstance } from 'vue'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
import { useDialogueStore, useTalkStore } from '@/store'
|
||||
import { NDropdown, NIcon, NInput, NPopover } from 'naive-ui'
|
||||
import { NDropdown, NIcon, NInput, NPopover, NTabs, NTab, NCard } from 'naive-ui'
|
||||
import { Search, Plus } from '@icon-park/vue-next'
|
||||
import TalkItem from './TalkItem.vue'
|
||||
import Skeleton from './Skeleton.vue'
|
||||
@ -11,6 +11,13 @@ import GroupLaunch from '@/components/group/GroupLaunch.vue'
|
||||
import { getCacheIndexName } from '@/utils/talk'
|
||||
import { ISession } from '@/types/chat'
|
||||
import { useSessionMenu } from '@/hooks'
|
||||
import customModal from '@/components/common/customModal.vue'
|
||||
import xSearchForm from '@/components/x-naive-ui/x-search-form/index.vue'
|
||||
import flTree from '@/components/flnlayout/tree/flnindex.vue'
|
||||
import { processError, processSuccess } from '@/utils/helper/message.js'
|
||||
|
||||
const currentInstance = getCurrentInstance()
|
||||
const { $request } = currentInstance?.appContext.config.globalProperties
|
||||
|
||||
const {
|
||||
dropdown,
|
||||
@ -27,6 +34,29 @@ const searchKeyword = ref('')
|
||||
const topItems = computed((): ISession[] => talkStore.topItems)
|
||||
const unreadNum = computed(() => talkStore.talkUnreadNum)
|
||||
|
||||
const state = reactive({
|
||||
isShowAddressBookModal: false, // 是否显示通讯录模态框
|
||||
customModalStyle: {
|
||||
width: '1288px',
|
||||
height: '846px',
|
||||
backgroundColor: '#F9F9FD'
|
||||
}, //自定义模态框样式
|
||||
searchConfig: [
|
||||
{
|
||||
label: '姓名',
|
||||
key: 'name',
|
||||
type: 'input',
|
||||
valueType: 'string'
|
||||
}
|
||||
], // 搜索配置
|
||||
|
||||
treeData: [],
|
||||
expandedKeys: [],
|
||||
clickKey: '',
|
||||
treeRefreshCount: 0,
|
||||
treeSelectData: {}
|
||||
})
|
||||
|
||||
const items = computed((): ISession[] => {
|
||||
if (searchKeyword.value.length === 0) {
|
||||
return talkStore.talkItems
|
||||
@ -39,10 +69,13 @@ const items = computed((): ISession[] => {
|
||||
})
|
||||
})
|
||||
|
||||
watch(() => talkStore, (newValue, oldValue) => {
|
||||
console.log(newValue);
|
||||
|
||||
},{deep:true,immediate:true})
|
||||
watch(
|
||||
() => talkStore,
|
||||
(newValue, oldValue) => {
|
||||
console.log(newValue)
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
)
|
||||
|
||||
// 列表加载状态
|
||||
const loadStatus = computed(() => talkStore.loadStatus)
|
||||
@ -100,9 +133,81 @@ const onInitialize = () => {
|
||||
// 路由更新事件
|
||||
onBeforeRouteUpdate(onInitialize)
|
||||
|
||||
onBeforeMount(() => {
|
||||
getTreeData()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onInitialize()
|
||||
})
|
||||
|
||||
// 点击显示通讯录模态框
|
||||
const showAddressBookModal = () => {
|
||||
state.isShowAddressBookModal = true
|
||||
}
|
||||
const handleTreeClick = ({ selectedKey, tree }) => {
|
||||
state.clickKey = tree.key
|
||||
state.treeSelectData = tree
|
||||
}
|
||||
const calcTreeData = (data) => {
|
||||
for (let item of data) {
|
||||
item.key = item.ID
|
||||
item.label = item.name
|
||||
item.title = item.name
|
||||
if (item.sons) {
|
||||
item.children = item.sons
|
||||
calcTreeData(item.children)
|
||||
}
|
||||
delete item.ID
|
||||
delete item.name
|
||||
delete item.sons
|
||||
}
|
||||
}
|
||||
// 获取组织树数据
|
||||
const getTreeData = () => {
|
||||
let url = '/department/v2/tree/filter'
|
||||
let params = {}
|
||||
$request.HTTP.components.postDataByParams(url, params).then(
|
||||
(res) => {
|
||||
if (res.status === 0 && Array.isArray(res.data.nodes)) {
|
||||
let data = res.data.nodes
|
||||
calcTreeData(data)
|
||||
state.treeData = data
|
||||
// // 获取最近点击的部门
|
||||
// let localSelect = Local.get("posimanage_treeSelectData");
|
||||
// if (localSelect && JSON.stringify(localSelect) !== "{}") {
|
||||
// state.treeSelectData = localSelect;
|
||||
// state.expandedKeys = localSelect.pathIds;
|
||||
// state.clickKey = localSelect.key;
|
||||
// } else {
|
||||
// if (JSON.stringify(state.treeSelectData) === "{}") {
|
||||
// state.treeSelectData = data[0];
|
||||
// state.clickKey = data[0].key;
|
||||
// }
|
||||
// if (
|
||||
// state.clickKey === data[0].key &&
|
||||
// !state.expandedKeys.includes(data[0].key)
|
||||
// ) {
|
||||
// state.expandedKeys.push(data[0].key);
|
||||
// }
|
||||
// if (!state.expandedKeys.includes(state.clickKey)) {
|
||||
// state.expandedKeys.push(state.clickKey);
|
||||
// }
|
||||
// }
|
||||
state.treeRefreshCount++
|
||||
// state.tableConfig.refreshCount++;
|
||||
} else {
|
||||
processError(res.msg || '获取失败!')
|
||||
}
|
||||
},
|
||||
() => {
|
||||
processError('获取失败!')
|
||||
},
|
||||
() => {
|
||||
processError('获取失败!')
|
||||
}
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -125,7 +230,7 @@ onMounted(() => {
|
||||
v-model:value.trim="searchKeyword"
|
||||
round
|
||||
clearable
|
||||
style="width: 78%"
|
||||
style="width: 78%;"
|
||||
>
|
||||
<template #prefix>
|
||||
<n-icon :component="Search" />
|
||||
@ -137,6 +242,12 @@ onMounted(() => {
|
||||
<n-icon :component="Plus" />
|
||||
</template>
|
||||
</n-button>
|
||||
<img
|
||||
style="width: 19px; height: 20px;"
|
||||
src="@/assets/image/chatList/addressBook.png"
|
||||
alt=""
|
||||
@click="showAddressBookModal"
|
||||
/>
|
||||
</header>
|
||||
|
||||
<!-- 置顶栏目 -->
|
||||
@ -196,6 +307,37 @@ onMounted(() => {
|
||||
</section>
|
||||
|
||||
<GroupLaunch v-if="isShowGroup" @close="isShowGroup = false" @on-submit="onReload" />
|
||||
|
||||
<customModal
|
||||
v-model:show="state.isShowAddressBookModal"
|
||||
title="通讯录"
|
||||
:style="state.customModalStyle"
|
||||
:customCloseBtn="true"
|
||||
:closable="false"
|
||||
>
|
||||
<template #content>
|
||||
<div class="custom-modal-content">
|
||||
<n-card>
|
||||
<n-tabs type="line">
|
||||
<n-tab name="employeeAddressBook">员工通讯录</n-tab>
|
||||
<n-tab name="groupChatList">群聊列表</n-tab>
|
||||
</n-tabs>
|
||||
<xSearchForm :search-config="state.searchConfig"></xSearchForm>
|
||||
<div class="addressBook-content">
|
||||
<div class="addressBook-tree">
|
||||
<fl-tree
|
||||
:data="state.treeData"
|
||||
:expandedKeys="state.expandedKeys"
|
||||
:refreshCount="state.treeRefreshCount"
|
||||
:clickKey="state.clickKey"
|
||||
@triggerTreeClick="handleTreeClick"
|
||||
></fl-tree>
|
||||
</div>
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
</customModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -299,4 +441,21 @@ html[theme-mode='dark'] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-modal-content {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 0 12px;
|
||||
.addressBook-content {
|
||||
.addressBook-tree {
|
||||
width: 328px;
|
||||
height: 524px;
|
||||
overflow: auto;
|
||||
border: 1px solid #efeff5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { defineConfig } from 'unocss'
|
||||
import { presetAttributify, presetIcons } from 'unocss'
|
||||
import { defineConfig, presetUno, presetAttributify, presetIcons } from 'unocss'
|
||||
|
||||
export default defineConfig({
|
||||
// 预设
|
||||
presets: [
|
||||
presetUno(), // 添加核心预设
|
||||
presetAttributify(), // 启用属性模式
|
||||
presetIcons(), // 启用图标
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user