This commit is contained in:
许gitee 2025-01-14 21:17:20 +08:00
parent 94725edb22
commit 90f7127318
16 changed files with 1187 additions and 1283 deletions

358
package-lock.json generated
View File

@ -10,6 +10,7 @@
"dependencies": {
"@infectoone/vue-ganttastic": "^2.3.2",
"@pureadmin/utils": "^2.5.0",
"@vueuse/core": "^12.4.0",
"axios": "^1.7.7",
"core-js": "^3.8.3",
"echarts": "^5.5.1",
@ -1909,6 +1910,94 @@
"vue": "^3.2.40"
}
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@infectoone/vue-ganttastic/node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
@ -2373,9 +2462,9 @@
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
"version": "0.0.20",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
},
"node_modules/@types/ws": {
"version": "8.5.12",
@ -2892,49 +2981,49 @@
"dev": true
},
"node_modules/@vue/compiler-core": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.6.tgz",
"integrity": "sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
"integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/shared": "3.5.6",
"@vue/shared": "3.5.13",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.6.tgz",
"integrity": "sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
"integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
"dependencies": {
"@vue/compiler-core": "3.5.6",
"@vue/shared": "3.5.6"
"@vue/compiler-core": "3.5.13",
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.6.tgz",
"integrity": "sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
"integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/compiler-core": "3.5.6",
"@vue/compiler-dom": "3.5.6",
"@vue/compiler-ssr": "3.5.6",
"@vue/shared": "3.5.6",
"@vue/compiler-core": "3.5.13",
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-ssr": "3.5.13",
"@vue/shared": "3.5.13",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
"postcss": "^8.4.47",
"postcss": "^8.4.48",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.6.tgz",
"integrity": "sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
"integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
"dependencies": {
"@vue/compiler-dom": "3.5.6",
"@vue/shared": "3.5.6"
"@vue/compiler-dom": "3.5.13",
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/component-compiler-utils": {
@ -3007,49 +3096,49 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
},
"node_modules/@vue/reactivity": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.6.tgz",
"integrity": "sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
"integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
"dependencies": {
"@vue/shared": "3.5.6"
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.6.tgz",
"integrity": "sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
"integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
"dependencies": {
"@vue/reactivity": "3.5.6",
"@vue/shared": "3.5.6"
"@vue/reactivity": "3.5.13",
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.6.tgz",
"integrity": "sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
"integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
"dependencies": {
"@vue/reactivity": "3.5.6",
"@vue/runtime-core": "3.5.6",
"@vue/shared": "3.5.6",
"@vue/reactivity": "3.5.13",
"@vue/runtime-core": "3.5.13",
"@vue/shared": "3.5.13",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.6.tgz",
"integrity": "sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
"integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
"dependencies": {
"@vue/compiler-ssr": "3.5.6",
"@vue/shared": "3.5.6"
"@vue/compiler-ssr": "3.5.13",
"@vue/shared": "3.5.13"
},
"peerDependencies": {
"vue": "3.5.6"
"vue": "3.5.13"
}
},
"node_modules/@vue/shared": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.6.tgz",
"integrity": "sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA=="
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz",
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
},
"node_modules/@vue/vue-loader-v15": {
"name": "vue-loader",
@ -3093,33 +3182,33 @@
"dev": true
},
"node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"version": "12.4.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.4.0.tgz",
"integrity": "sha512-XnjQYcJwCsyXyIafyA6SvyN/OBtfPnjvJmbxNxQjCcyWD198urwm5TYvIUUyAxEAN0K7HJggOgT15cOlWFyLeA==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
"@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "12.4.0",
"@vueuse/shared": "12.4.0",
"vue": "^3.5.13"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"version": "12.4.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.4.0.tgz",
"integrity": "sha512-AhPuHs/qtYrKHUlEoNO6zCXufu8OgbR8S/n2oMw1OQuBQJ3+HOLQ+EpvXs+feOlZMa0p8QVvDWNlmcJJY8rW2g==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"version": "12.4.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.4.0.tgz",
"integrity": "sha512-9yLgbHVIF12OSCojnjTIoZL1+UA10+O4E1aD6Hpfo/DKVm5o3SZIwz6CupqGy3+IcKI8d6Jnl26EQj/YucnW0Q==",
"dependencies": {
"vue-demi": "*"
"vue": "^3.5.13"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
@ -5497,6 +5586,94 @@
"vue": "^3.2.0"
}
},
"node_modules/element-plus/node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/element-plus/node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/element-plus/node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -9031,9 +9208,9 @@
}
},
"node_modules/picocolors": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz",
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/picomatch": {
"version": "2.3.1",
@ -9099,9 +9276,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.47",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"version": "8.4.49",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.49.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"funding": [
{
"type": "opencollective",
@ -9118,7 +9295,7 @@
],
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
@ -12246,15 +12423,15 @@
}
},
"node_modules/vue": {
"version": "3.5.6",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.6.tgz",
"integrity": "sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==",
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"dependencies": {
"@vue/compiler-dom": "3.5.6",
"@vue/compiler-sfc": "3.5.6",
"@vue/runtime-dom": "3.5.6",
"@vue/server-renderer": "3.5.6",
"@vue/shared": "3.5.6"
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-sfc": "3.5.13",
"@vue/runtime-dom": "3.5.13",
"@vue/server-renderer": "3.5.13",
"@vue/shared": "3.5.13"
},
"peerDependencies": {
"typescript": "*"
@ -12270,31 +12447,6 @@
"resolved": "https://registry.npmmirror.com/vue-count-to/-/vue-count-to-1.0.13.tgz",
"integrity": "sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ=="
},
"node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-hot-reload-api": {
"version": "2.3.4",
"resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",

View File

@ -9,6 +9,7 @@
"dependencies": {
"@infectoone/vue-ganttastic": "^2.3.2",
"@pureadmin/utils": "^2.5.0",
"@vueuse/core": "^12.4.0",
"axios": "^1.7.7",
"core-js": "^3.8.3",
"echarts": "^5.5.1",

View File

@ -23,11 +23,6 @@ const routes = [
component: () => import('../views/home/index'),
},
{
path: '/welcome',
name: 'welcome',
component: () => import('../views/welcome/index')
},
{
path: '/busines',

19
src/util/time.js Normal file
View File

@ -0,0 +1,19 @@
export function formattedDate(timestamp){
const date = new Date(timestamp);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
return formattedDate
}
export function DetailformattedDate(timestamp){
const date = new Date(timestamp);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hour = date.getHours().toString().padStart(2, '0');
const minute = date.getMinutes().toString().padStart(2, '0');
const second = date.getSeconds().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day} ${hour}:${minute}:${second}`;
return formattedDate
}

View File

@ -8,7 +8,7 @@
<el-row :gutter="16">
<el-col :span="6">
<div class="statistic-card">
<el-statistic :value="num0" >
<el-statistic :value="num0">
<template #title>
<div style="display: inline-flex; justify-self: right;align-items: center;width: 100%">
用户人数
@ -138,12 +138,20 @@
import axios from "@/util/axios";
import * as echarts from "echarts";
import {onMounted, ref} from 'vue'
import {formattedDate} from "@/util/time";
let num0=ref()
let num1=ref()
let num2=ref()
let num3=ref()
const num0=ref()
const num1=ref()
const num2=ref()
const num3=ref()
const compete=ref([])
const Xcompete=ref([])
const Ycompete=ref([])
// ====================
// ====================
const total=ref(0)
@ -156,20 +164,28 @@ const formPage=ref({
const initBusinessList=async()=>{
//console.log(formPage.value)
const res1=await axios.post("user/list/page");
num0=res1.data.data.total
num0.value=res1.data.data.total
const res3=await axios.post("orders/list/page");
num2=res3.data.data.total
num2.value=res3.data.data.total
const res4=await axios.post("manicurist/queryAll");
num3=res4.data.data.length
num3.value=res4.data.data.length
const res=await axios.post("business/list/page",formPage.value);
num1=res.data.data.total
num1.value=res.data.data.total
//console.log(res.data.data.records)
tableData.value=res.data.data.records;
total.value=res.data.data.records.length;
// console.log(num0)
// 线
compete.value=res3.data.data.records
compete.value.map(item=>{item.createTime=formattedDate(item.createTime)})
compete.value.forEach(item=>{Xcompete.value.push(item.createTime);Ycompete.value.push(item.totalPrice)})
// console.log(Xcompete.value)
// console.log(Ycompete.value)
// console.log(num0+" "+num1+" "+num2+" "+num3)
setTimeout(() => {hei();shi();}, 500)
}
@ -195,56 +211,73 @@ const handleCurrentChange = (pageNum) => {
// setTimeout(() => {hei();shi();}, 500)
// })
const hei=()=>{
var chartDom = document.getElementById('main1');
var myChart = echarts.init(chartDom);
var option;
// option = {
// tooltip: {
// trigger: 'item'
// },
// legend: {
// top: '5%',
// left: 'center'
// },
// series: [
// {
// name: 'Access From',
// type: 'pie',
// radius: ['40%', '70%'],
// avoidLabelOverlap: false,
// itemStyle: {
// borderRadius: 10,
// borderColor: '#fff',
// borderWidth: 2
// },
// label: {
// show: false,
// position: 'center'
// },
// emphasis: {
// label: {
// show: true,
// fontSize: 40,
// fontWeight: 'bold'
// }
// },
// labelLine: {
// show: false
// },
// data: [
// { value: 1048, name: 'Search Engine' },
// { value: 735, name: 'Direct' },
// { value: 580, name: 'Email' },
// { value: 484, name: 'Union Ads' },
// { value: 300, name: 'Video Ads' }
// ]
// }
// ]
// };
option = {
tooltip: {
trigger: 'item'
xAxis: {
type: 'category',
data:['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
legend: {
top: '5%',
left: 'center'
yAxis: {
type: 'value'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: 40,
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' }
]
data: [10, 52, 200, 334, 390, 330, 220],
type: 'line'
}
]
};
option && myChart.setOption(option);
}
@ -269,7 +302,7 @@ const shi=()=>{
xAxis: [
{
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: Xcompete.value,
axisTick: {
alignWithLabel: true
}
@ -285,7 +318,7 @@ const shi=()=>{
name: 'Direct',
type: 'bar',
barWidth: '60%',
data: [10, 52, 200, 334, 390, 330, 220]
data: Ycompete.value
}
]
};

File diff suppressed because one or more lines are too long

View File

@ -1,135 +1,237 @@
<template>
<el-menu
active-text-color="#ffd04b"
background-color="#2d3a4b"
class="el-menu-vertical-demo"
default-active="home"
text-color="#fff"
router
>
<el-menu-item index="welcome">
<el-icon><home-filled /></el-icon>
<span>Welcome</span>
</el-menu-item>
<el-menu-item index="home">
<el-icon><home-filled /></el-icon>
<span>首页</span>
</el-menu-item>
<!-- <el-menu-item index="display">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>数据展示</span>-->
<!-- </el-menu-item>-->
<el-menu-item index="user">
<el-icon><user /></el-icon>
<span >用户管理</span>
</el-menu-item>
<el-sub-menu index="3">
<template #title >
<el-icon><management /></el-icon>
<span>商家管理</span>
</template>
<el-menu-item index="business">
<el-icon><management /></el-icon>
<span>商家列表</span>
</el-menu-item>
<el-menu-item index="businesVerify" >
<el-icon><management /></el-icon>
<span>审核商家入驻</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="6">
<template #title >
<el-icon><management /></el-icon>
<span>商品管理</span>
</template>
<el-menu-item index="businessProduct">
<el-icon><management /></el-icon>
<span>商家商品</span>
</el-menu-item>
<el-menu-item index="productCategory">
<el-icon><management /></el-icon>
<span>商品分类</span>
</el-menu-item>
<el-menu-item index="product">
<el-icon><management /></el-icon>
<span>商品列表</span>
</el-menu-item>
<div v-if="ax">
<el-menu
active-text-color="#ffd04b"
background-color="#2d3a4b"
class="el-menu-vertical-demo"
default-active="home"
text-color="#fff"
router
>
</el-sub-menu>
<el-sub-menu index="8">
<template #title >
<el-icon><tickets /></el-icon>
<span>美甲师管理</span>
</template>
<el-menu-item index="employeeVerify">
<el-icon><management /></el-icon>
<span>审核美甲师认证</span>
</el-menu-item>
<el-menu-item index="employee">
<el-icon><tickets /></el-icon>
<span>美甲师列表</span>
</el-menu-item>
</el-sub-menu>
<el-menu-item index="home">
<el-icon><home-filled /></el-icon>
<span>首页</span>
</el-menu-item>
<!-- <el-menu-item index="display">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>数据展示</span>-->
<!-- </el-menu-item>-->
<el-menu-item index="user">
<el-icon><user /></el-icon>
<span >用户管理</span>
</el-menu-item>
<el-sub-menu index="3">
<template #title >
<el-icon><management /></el-icon>
<span>商家管理</span>
</template>
<el-menu-item index="business">
<el-icon><management /></el-icon>
<span>商家列表</span>
</el-menu-item>
<el-menu-item index="businesVerify" >
<el-icon><management /></el-icon>
<span>审核商家入驻</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="6">
<template #title >
<el-icon><management /></el-icon>
<span>商品管理</span>
</template>
<el-menu-item index="businessProduct">
<el-icon><management /></el-icon>
<span>商家商品</span>
</el-menu-item>
<el-menu-item index="productCategory">
<el-icon><management /></el-icon>
<span>商品分类</span>
</el-menu-item>
<el-menu-item index="product">
<el-icon><management /></el-icon>
<span>商品列表</span>
</el-menu-item>
<el-sub-menu index="9">
<template #title >
<el-icon><management /></el-icon>
<span>订单管理</span>
</template>
<el-menu-item index="orderReservation">
<el-icon><tickets /></el-icon>
<span>上门预约</span>
</el-menu-item>
<el-menu-item index="order">
<el-icon><tickets /></el-icon>
<span>到店服务</span>
</el-menu-item>
<!-- <el-menu-item index="order">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>订单列表</span>-->
<!-- </el-menu-item>-->
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="8">
<template #title >
<el-icon><tickets /></el-icon>
<span>美甲师管理</span>
</template>
<el-menu-item index="employeeVerify">
<el-icon><management /></el-icon>
<span>审核美甲师认证</span>
</el-menu-item>
<el-menu-item index="employee">
<el-icon><tickets /></el-icon>
<span>美甲师列表</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="9">
<template #title >
<el-icon><management /></el-icon>
<span>订单管理</span>
</template>
<el-menu-item index="orderReservation">
<el-icon><tickets /></el-icon>
<span>上门预约</span>
</el-menu-item>
<el-menu-item index="order">
<el-icon><tickets /></el-icon>
<span>到店服务</span>
</el-menu-item>
<!-- <el-menu-item index="order">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>订单列表</span>-->
<!-- </el-menu-item>-->
</el-sub-menu>
<el-sub-menu index="10">
<template #title >
<el-icon><management /></el-icon>
<span>评价管理</span>
</template>
<el-menu-item index="permission">
<el-icon><tickets /></el-icon>
<span>权限操作</span>
</el-menu-item>
<el-menu-item >
<el-icon><tickets /></el-icon>
<span>星级评优</span>
</el-menu-item>
<el-menu-item index="rating">
<el-icon><tickets /></el-icon>
<span>评价列表</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="10">
<template #title >
<el-icon><management /></el-icon>
<span>评价管理</span>
</template>
<!-- <el-menu-item index="permission">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>权限操作</span>-->
<!-- </el-menu-item>-->
<el-menu-item index="permission">
<el-icon><tickets /></el-icon>
<span>星级评优</span>
</el-menu-item>
<el-menu-item index="rating">
<el-icon><tickets /></el-icon>
<span>评价操作</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="11">
<template #title >
<el-icon><management /></el-icon>
<span>系统管理</span>
</template>
<el-menu-item index="personal">
<el-icon><House /></el-icon>
<span>个人中心</span>
<el-sub-menu index="11">
<template #title >
<el-icon><management /></el-icon>
<span>系统管理</span>
</template>
<el-menu-item index="personal">
<el-icon><House /></el-icon>
<span>个人中心</span>
</el-menu-item>
<el-menu-item index="modifyPassword">
<el-icon><edit /></el-icon>
<span>修改密码</span>
</el-menu-item>
<el-menu-item >
<el-icon @click="logout"><switch-button /></el-icon>
<span @click="logout">安全退出</span>
</el-menu-item>
</el-sub-menu>
</el-menu>
</div>
<div v-else>
<el-menu
active-text-color="#ffd04b"
background-color="#2d3a4b"
class="el-menu-vertical-demo"
default-active="home"
text-color="#fff"
router
>
<el-menu-item index="home">
<el-icon><home-filled /></el-icon>
<span>首页</span>
</el-menu-item>
<el-menu-item index="modifyPassword">
<el-icon><edit /></el-icon>
<span>修改密码</span>
</el-menu-item>
<el-menu-item >
<el-icon @click="logout"><switch-button /></el-icon>
<span @click="logout">安全退出</span>
</el-menu-item>
</el-sub-menu>
</el-menu>
<el-sub-menu index="2">
<template #title >
<el-icon><management /></el-icon>
<span>订单管理</span>
</template>
<el-menu-item index="orderReservation">
<el-icon><tickets /></el-icon>
<span>上门预约</span>
</el-menu-item>
<el-menu-item index="order">
<el-icon><tickets /></el-icon>
<span>到店服务</span>
</el-menu-item>
<el-menu-item >
<el-icon><tickets /></el-icon>
<span>抢单</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="6">
<template #title >
<el-icon><management /></el-icon>
<span>商品管理</span>
</template>
<el-menu-item index="product">
<el-icon><management /></el-icon>
<span>商品列表</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="8">
<template #title >
<el-icon><tickets /></el-icon>
<span>美甲师管理</span>
</template>
<el-menu-item index="employee">
<el-icon><management /></el-icon>
<span>美甲师列表</span>
</el-menu-item>
<el-menu-item >
<el-icon><tickets /></el-icon>
<span>签约美甲师</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="10">
<template #title >
<el-icon><management /></el-icon>
<span>评价管理</span>
</template>
<!-- <el-menu-item index="permission">-->
<!-- <el-icon><tickets /></el-icon>-->
<!-- <span>权限操作</span>-->
<!-- </el-menu-item>-->
<el-menu-item index="permission">
<el-icon><tickets /></el-icon>
<span>星级评优</span>
</el-menu-item>
<el-menu-item index="rating">
<el-icon><tickets /></el-icon>
<span>评价操作</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="11">
<template #title >
<el-icon><management /></el-icon>
<span>系统管理</span>
</template>
<el-menu-item index="personal">
<el-icon><House /></el-icon>
<span>个人中心</span>
</el-menu-item>
<el-menu-item index="modifyPassword">
<el-icon><edit /></el-icon>
<span>修改密码</span>
</el-menu-item>
<el-menu-item >
<el-icon @click="logout"><switch-button /></el-icon>
<span @click="logout">安全退出</span>
</el-menu-item>
</el-sub-menu>
</el-menu>
</div>
</template>
<script setup>
import
@ -138,7 +240,21 @@ import
import { useStore } from 'vuex'
import axios from "@/util/axios";
import {ElMessage} from "element-plus";
import {ref} from "vue";
const store=useStore();
const ax=ref(true)
const initax=()=>{
let userInfoJson = window.sessionStorage.getItem("USER_LOGIN_STATE");
console.log(userInfoJson)
if(JSON.parse(userInfoJson).userRole==1)
{
ax.value=true
}else{
ax.value=false
}
console.log(ax.value)
}
initax();
const logout=async ()=>{
store.dispatch('logout')
let res= await axios.post("/user/logout")

View File

@ -36,7 +36,7 @@ import {ElMessage} from "element-plus";
import router from "@/router";
const form = ref({
userAccount: 'root2',
userAccount: 'root',
userPassword: '12345678'
});
@ -64,7 +64,7 @@ const handleLogin = () => {
try {
let result = await axiosUtil.post("user/login", form.value);
let data = result.data;
console.log(result)
// console.log(result)
// const value = response.data;
// // Vue使
// this.sessionValue = value;

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
model-value="dialogaddVisible"
model-value="edialogaddVisible"
:title="dialogTitle"
width="30%"
@close="handleClose"
@ -8,36 +8,52 @@
<el-form
ref="formRef"
:model="form"
label-width="100px"
>
<el-form-item label="门店头像" prop="avatarUrl">
<el-upload list-type="picture-card" limit="1" :auto-upload="false" drag action="#">
<el-icon><Plus /></el-icon>
<template #tip>
<div class="el-upload__tip">
最多传一张
</div>
</template>
</el-upload>
</el-form-item>
<el-form-item label="用户昵称" prop="username">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="用户账号" prop="userAccount">
<el-input v-model="form.userAccount" />
</el-form-item>
<el-form-item label="用户密码" prop="userPassword">
<el-input v-model="form.userPassword" show-password />
<el-input v-model="form.userPassword" />
</el-form-item>
<el-form-item label="用户昵称" prop="manicuristName">
<el-input v-model="form.manicuristName"/>
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-input v-model="form.gender"/>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone"/>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email"/>
</el-form-item>
<el-form-item label="工作名称" prop="specialties">
<el-input v-model="form.specialties"/>
</el-form-item>
<el-form-item label="评分" prop="rating">
<el-input v-model="form.rating"/>
</el-form-item>
<el-form-item label="余额" prop="salary">
<el-input v-model="form.salary"/>
</el-form-item>
<el-form-item label="认证号" prop="certification_number">
<el-input v-model="form.certification_number"/>
</el-form-item>
<el-form-item label="认证路径" prop="certificate_path">
<el-input v-model="form.certificate_path"/>
</el-form-item>
<el-form-item label="组织认证" prop="issuing_authority">
<el-input v-model="form.issuing_authority"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
</template>
</el-dialog>
</template>
@ -45,9 +61,6 @@
import {defineEmits, defineProps, ref, watch} from "vue";
import axios from "@/util/axios";
import { ElMessage } from "element-plus";
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue'
const props=defineProps({
dialogTitle:{
type:String,
@ -56,30 +69,25 @@ const props=defineProps({
}
})
const form=ref({
avatarUrl:'',
userAccount:'',
userPassword:'',
username:null
userAccount:"",
userPassword:"",
certificate_path: "",
certification_number: "",
email: "",
gender: null,
issuing_authority: "",
manicuristName: "",
phone: "",
rating: null,
salary: null,
specialties: ""
})
// const rules=ref({
// name: [
// {
// required: true,
// message: ''
// }
// ],
// remark: [
// {
// required: true,
// message: ''
// }
// ]
// })
const formRef=ref(null);
//
const emits=defineEmits(['update:modelValue','initUserList'])
const emits=defineEmits(['update:modelValue','initEmployeeList'])
const handleClose=()=>{
console.log("用户添加关闭xxx")
//
@ -88,13 +96,13 @@ const handleClose=()=>{
const handleConfirm=()=>{
formRef.value.validate(async(valid)=>{
if(valid){
let result=await axios.post("user/add",form.value)
let result=await axios.post("manicurist/adminAdd",form.value)
console.log(result.data)
let data=result.data;
if(data.code==0){
ElMessage.success("执行添加成功!");
formRef.value.resetFields();
emits("initUserList");
emits("initEmployeeList");
handleClose();
}else{
ElMessage.error(data.description);

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
model-value="dialogVisible"
model-value="edialogVisible"
:title="dialogTitle"
width="30%"
@close="handleClose"
@ -8,46 +8,44 @@
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
>
<el-form-item label="用户头像" prop="avatarUrl">
<img :src="form.avatarUrl" alt="空" width="50" height="50"/>
<el-form-item label="头像" prop="manicuristAvatar">
<img :src="form.manicuristAvatar" width="80px" height="80px"/>
</el-form-item>
<el-form-item label="用户昵称" prop="username">
{{form.username}}
</el-form-item>
<el-form-item label="用户账号" prop="userAccount">
{{form.userAccount}}
<el-form-item label="用户昵称" prop="manicuristName">
{{form.manicuristName}}
</el-form-item>
<el-form-item label="性别" prop="gender">
<template v-if="form.gender==0"></template>
<template v-else></template>
</el-form-item>
<el-form-item label="电话" prop="phone">
{{form.phone}}
{{form.phone}}
</el-form-item>
<el-form-item label="邮箱" prop="email">
{{form.email}}
</el-form-item>
<el-form-item label="用户状态" prop="userStatus">
<template v-if="form.userStatus==0">禁用</template>
<template v-else>启用</template>
<el-form-item label="工作名称" prop="specialties">
{{form.specialties}}
</el-form-item>
<el-form-item label="用户角色" prop="userRole">
<template v-if="form.userRole===0">普通用户</template>
<template v-else-if="form.userRole===1">管理员</template>
<template v-else-if="form.userRole===2">商家</template>
<template v-else>美甲师</template>
<el-form-item label="工作时长" prop="employment_date">
{{form.employment_date}}
</el-form-item>
<el-form-item label="评分" prop="rating">
{{form.rating}}
</el-form-item>
<el-form-item label="余额" prop="salary">
{{form.salary}}
</el-form-item>
</el-form>
<!-- <template #footer>-->
<!--<span class="dialog-footer">-->
<!--<el-button @click="handleClose">取消</el-button>-->
<!--<el-button type="primary" @click="handleConfirm">确认</el-button>-->
<!--</span>-->
<!-- </template>-->
<template #footer v-if="title">
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm">审核成功</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
@ -57,7 +55,7 @@ import { ElMessage } from "element-plus";
const props=defineProps({
id:{
type:String,
default:-1,
default:'',
required:true
},
dialogTitle:{
@ -67,86 +65,72 @@ const props=defineProps({
}
})
const form=ref({
avatarUrl: "",
createTime:"",
email:"",
gender:null,
isDelete:null,
openId:null,
phone:null,
unionId:null,
updateTime:"",
userAccount:"",
userPassword:"",
userRole:null,
userStatus:null,
username:""
id:null,
email: "",
gender: null,
phone: "",
businessId: "",
manicuristName: "",
employment_date: "",
specialties: "",
rating: null,
salary: null,
auditStatus:null,
manicuristAvatar: ""
})
// const rules=ref({
// name: [
// {
// required: true,
// message: ''
// }
// ],
// remark: [
// {
// required: true,
// message: ''
// }
// ]
// })
const formRef=ref(null);
const initFormData=async(ids)=>{
// console.log(ids)
const res=await axios.get("user/getById",{id: ids})
// console.log(res.data.data)
form.value=res.data.data;
const title=ref(false);
const formRef=ref(null);
const initFormData=async(id)=>{
const res = await axios.get("manicurist/queryById", {manicuristId: id})
form.value=res.data.data;
//console.log(res.data.data)
}
watch(
()=>props.id,
()=>{
//console.log("id="+props.id);
let ids=props.id;
initFormData(ids)
if (props.dialogTitle=='审核美甲师'){
title.value=true;
}
let id=props.id;
initFormData(id)
// }else{
// formRef.value.resetFields();
// form.value={
// id:-1,
// name:"",
// remark:""
// }
// }
}
)
//
const emits=defineEmits(['update:modelValue','initUserList'])
const emits=defineEmits(['update:modelValue','handleCollapse'])
const handleClose=()=>{
console.log("xxx")
//
emits('update:modelValue',false)
}
// const handleConfirm=()=>{
// formRef.value.validate(async(valid)=>{
// if(valid){
// let result=await axios.post("admin/bigType/save",form.value)
// let data=result.data;
// if(data.code==0){
// ElMessage.success("");
// formRef.value.resetFields();
// emits("initUserList");
// handleClose();
// }else{
// ElMessage.error(data.msg);
// }
// }else{
// console.log("fail")
// return false
// }
// })
// }
const handleConfirm = () => {
form.value.auditStatus=1
formRef.value.validate(async (valid) => {
if (valid) {
let result = await axios.post("manicurist/update", form.value)
console.log(result.data.data)
let data = result.data;
if (data.code == 0) {
ElMessage.success("执行成功!");
formRef.value.resetFields();
emits("handleCollapse");
handleClose();
} else {
ElMessage.error(data.description);
}
} else {
console.log("fail")
return false
}
})
}
</script>
<style scoped>
</style>

View File

@ -1,58 +1,64 @@
<template>
<!-- <g-gantt-chart-->
<!-- chart-start="00:00"-->
<!-- chart-end="23:59"-->
<!-- precision="hour"-->
<!-- date-format="HH:mm"-->
<!-- bar-start="beginDate"-->
<!-- bar-end="endDate"-->
<!-- grid-->
<!-- >-->
<!-- <template #upper-timeunit>-->
<!-- <h1>-->
<!-- {{-->
<!-- `${weekRangeInChina.currentWeekStart} / ${weekRangeInChina.currentWeekEnd}`-->
<!-- }}-->
<!-- </h1>-->
<!-- </template>-->
<!-- <g-gantt-row-->
<!-- v-for="(item, index) in context"-->
<!-- :key="index"-->
<!-- :bars="item"-->
<!-- :label="item[0].week"-->
<!-- highlight-on-hover-->
<!-- />-->
<!-- </g-gantt-chart>-->
<!--=================================================================-->
<el-card>
<el-row :gutter="20" class="header">
<el-col :span="7">
<el-input placeholder="请输入用户昵称..." clearable v-model="queryForm.username"></el-input>
<el-input placeholder="请输入美甲师ID..." clearable v-model="query" ></el-input>
</el-col>
<el-button type="button" :icon="Search" @click="initUserList" >搜索</el-button>
<el-button type="button" :icon="Search" @click="initEmployeeList">搜索</el-button>
<el-button type="primary" :icon="DocumentAdd" @click="open">评优结算</el-button>
</el-row>
<el-table :data="tableData" stripe style="width: 100%;" showOverflowTooltip>
<el-table-column fixed prop="id" label="#ID" width="80" />
<el-table-column prop="username" label="用户昵称" width="150" />
<el-table-column prop="avatarUrl" label="头像" width="200">
<el-table-column prop="id" label="#ID" width="80" />
<el-table-column prop="manicuristName" label="用户昵称" width="200" />
<el-table-column prop="manicuristAvatar" label="头像" width="200">
<template v-slot="scope">
<el-popover
placement="right-start"
:width="200"
trigger="hover"
:content="scope.row.avatarUrl"
>
<template #reference>
<img :src="scope.row.avatarUrl" width="50" height="50"/>
</template>
</el-popover>
<img :src="scope.row.manicuristAvatar" width="50" height="50"/>
</template>
</el-table-column>
<el-table-column prop="userStatus" label="用户状态" width="100">
<template v-slot="scope">
<div v-if="scope.row.userStatus===0" style="color: red">
禁用
</div>
<div style="color: lawngreen" v-else>
启用
<el-table-column prop="rating" label="评分" width="200px">
<template v-slot="scope" style="height: 100px">
<div class="demo-rate-block">
<el-rate v-model="scope.row.rating" :colors="colors"/>
{{scope.row.rating}}
</div>
</template>
</el-table-column>
<el-table-column prop="userRole" label="用户角色" width="100">
<template v-slot="scope">
<div v-if="scope.row.userRole===0">普通用户</div>
<div v-else-if="scope.row.userRole===1">管理员</div>
<div v-else-if="scope.row.userRole===2">商家</div>
<div v-else>美甲师</div>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="最后登录日期" />
<el-table-column prop="action" fixed="right" label="操作" min-width="170">
<el-table-column prop="createTime" label="注册日期" width="200"/>
<el-table-column prop="updateTime" label="最后登录日期" width="200"/>
<el-table-column prop="action" fixed="right" label="操作" min-width="220">
<template v-slot="scope" >
<!-- <el-button @click="handleRouter(scope.row.id)" type="primary" :icon="DocumentAdd" >审核美甲师</el-button>-->
<el-button type="success" size="small" @click="handleDialogValue(scope.row.id)">
详情
</el-button>
<el-button type="primary" size="small" :icon="Edit" @click="handleUpdateDialogValue(scope.row.id)"></el-button>
<el-button type="danger" size="small" :icon="Delete" @click="handleDelete(scope.row.id)"></el-button>
<el-button type="primary" size="small" :icon="Edit" @click="handleUpdateDialogValue(scope.row.id)">评优详情</el-button>
</template>
</el-table-column>
</el-table>
@ -65,78 +71,89 @@
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
<!-- {{total}}-->
</el-card>
<Dialog v-model="UdialogVisible" :id="id" :dialogTitle="dialogTitle"
@initUserList="initUserList"></Dialog>
<AddDialog v-model="UdialogaddVisible" :dialogTitle="dialogTitle"
@initUserList="initUserList"></AddDialog>
<UpdateDialog v-model="UdialogUpdateVisible" :id="id" :dialogTitle="dialogTitle"
@initUserList="initUserList"></UpdateDialog>
<Dialog v-model="edialogVisible" :id="id" :dialogTitle="dialogTitle"
@initEmployeeList="initEmployeeList"></Dialog>
<AddDialog v-model="edialogaddVisible" :dialogTitle="dialogTitle"
@initEmployeeList="initEmployeeList"></AddDialog>
<UpdateDialog v-model="edialogUpdateVisible" :id="id" :dialogTitle="dialogTitle"
@initEmployeeList="initEmployeeList"></UpdateDialog>
</template>
<script setup>
import {Search,Delete,Edit,DocumentAdd,Close,Check} from '@element-plus/icons-vue'
import {Search,DocumentAdd,Delete,Edit} from '@element-plus/icons-vue'
import {ref, watch} from 'vue'
import axios from "@/util/axios";
import Dialog from '@/views/user/dialog/index.vue'
import AddDialog from '@/views/user/addDialog/index.vue'
import UpdateDialog from '@/views/user/updateDialog/index.vue'
import Dialog from '@/views/permission/dialog/index.vue'
import AddDialog from '@/views/permission/addDialog/index.vue'
import UpdateDialog from '@/views/permission/updateDialog/index.vue'
import { ElMessage,ElMessageBox } from "element-plus";
import {parseTime} from "element-plus/es/components/time-select/src/utils";
const queryForm=ref({
username: '',
current:1,
pageSize:10
})
const query=ref();
const total=ref(0)
const tableData =ref([])
const id=ref('')
const dialogTitle=ref('');
const UdialogaddVisible=ref(false)
const UdialogVisible=ref(false)
const UdialogUpdateVisible=ref(false)
const edialogaddVisible=ref(false)
const edialogVisible=ref(false)
const edialogUpdateVisible=ref(false)
import { Action } from 'element-plus'
const open = () => {
ElMessageBox.alert('此接口暂无', 'Title', {
confirmButtonText: 'OK',
// callback: ( Action) => {
// ElMessage({
// type: 'info',
// message: `action: ${Action}`,
// })
// }
})
}
// watch(queryForm.value.username,()=>{
// // console.log(query.value)
// initUserList();
// },10000)
const handleDialogValue=(ids)=>{
//console.log("bigTypeId="+userAccount)
// if(userAccount){
id.value=ids;
dialogTitle.value="用户详情"
// console.log("asdfasdfasd"+useraccount.value)
// }else{
// useraccount.value=-1;
// dialogTitle.value=""
// // console.log(dialogTitle.value)
// }
UdialogVisible.value=true
dialogTitle.value="美甲师详情"
edialogVisible.value=true
}
const handleUpdateDialogValue=(ids)=>{
// console.log(userAccount)
id.value=ids;
// console.log(userAccount.value)
dialogTitle.value="用户修改"
UdialogUpdateVisible.value=true
}
const handleUpdateDialogValue=(ids)=>{
// console.log(id)
id.value=ids;
// console.log(id.value)
dialogTitle.value="美甲师修改"
edialogUpdateVisible.value=true
}
const handleAddDialogValue=()=>{
dialogTitle.value="美甲师添加"
edialogaddVisible.value=true
}
//
const handleDelete=(id)=>{
// console.log(id)
const handleDelete=(ids)=>{
// console.log(ids)
ElMessageBox.confirm(
'您确定要删除这条记录吗?',
'系统提示',
@ -147,13 +164,13 @@ const handleDelete=(id)=>{
}
)
.then(async() => {
let res=await axios.post('user/delete',{id:id})
let res=await axios.post('manicurist/deleteMan?id='+Number(ids))
if(res.data.code==0){
ElMessage({
type: 'success',
message: '删除成功',
})
initSmallTypeList();
initEmployeeList();
}else{
ElMessage({
type: 'error',
@ -168,47 +185,200 @@ const handleDelete=(id)=>{
const total=ref(0)
const tableData =ref([])
watch(query,()=>{
// console.log(query.value)
initEmployeeList();
},10000)
const initUserList=async()=>{
// // console.log(query)
// if (!query.value) {
// const res = await axios.post("user/list/page", queryForm.value);
// // console.log(res)
// tableData.value = res.data.data.records;
// //console.log(res.data.data)
// total.value = Number(res.data.data.total);
// }
// else{
// const res=await axios.get("user/getById", {id:query.value});
// // console.log(res.data.data)
// const temp=[];
// temp.push(res.data.data)
// tableData.value=temp;
// total.value=1;
// }
const res = await axios.post("user/list/page", queryForm.value);
// console.log(res.data.data.records)
if (res.data.data) {
tableData.value = res.data.data.records;
//console.log(res.data.data)
total.value = Number(res.data.data.total);
}
else{
ElMessage.error(res.data.description);
const tempstore=()=>{
const temp=[]
tableData.value.map(item=>{
if(item.manStatus==0)
{
item.manStatus=true
}
else{
item.manStatus=false
}
if (item.auditStatus==1)
{
temp.push(item)
}
})
tableData.value=temp
//console.log(res.data.data)
}
const initEmployeeList=async()=>{
if (!query.value){
const res=await axios.post("manicurist/queryAll");
// console.log(res.data)
tableData.value=res.data.data;
let num=tableData.value.filter(item=>item.auditStatus==1)
total.value=num.length;
tempstore();
}else{
const res = await axios.get("manicurist/queryById", {manicuristId: query.value});
// console.log(res.data)
const temp = []
temp.push(res.data.data)
tableData.value = temp;
total.value = 1;
tempstore();
}
}
initUserList();
initEmployeeList();
const handleSizeChange = (pageSize) => {
queryForm.value.current=1;
queryForm.value.pageSize=pageSize;
initUserList();
initEmployeeList();
}
const handleCurrentChange = (current1) => {
queryForm.value.current=current1;
initUserList();
const handleCurrentChange = (current) => {
queryForm.value.current=current;
initEmployeeList();
}
// =============================================
const colors = ref(['#99A9BF', '#F7BA2A', '#FF9900'])
// =========================================================================================================
const context = ref([
[
{
week: "星期一",
beginDate: "06:00",
endDate: "22:00",
ganttBarConfig: {
id: "0",
hasHandles: true,
label: "需求收集和分析 负责人:小张",
style: {
background: "#e96560"
}
}
}
],
[
{
week: "星期二",
beginDate: "09:00",
endDate: "18:00",
ganttBarConfig: {
id: "1",
hasHandles: true,
label: "系统设计 负责人:小强",
style: {
background: "#5ccfa3"
}
}
}
],
[
{
week: "星期三",
beginDate: "07:00",
endDate: "20:00",
ganttBarConfig: {
id: "2",
hasHandles: true,
label: "编码实现 负责人:老李",
style: {
background: "#77d6fa"
}
}
}
],
[
{
week: "星期四",
beginDate: "06:00",
endDate: "21:00",
ganttBarConfig: {
id: "3",
hasHandles: true,
label: "编码实现 负责人:小明",
style: {
color: "#fff",
background: "#1b2a47"
}
}
}
],
[
{
week: "星期五",
beginDate: "05:00",
endDate: "19:00",
ganttBarConfig: {
id: "4",
hasHandles: true,
label: "内部测试 负责人:小雪",
style: {
background: "#5ccfa3"
}
}
}
],
[
{
week: "星期六",
beginDate: "10:00",
endDate: "22:00",
ganttBarConfig: {
id: "5",
hasHandles: true,
label: "系统优化和文档整理 负责人:小欣",
style: {
background: "#f8bc45"
}
}
}
],
[
{
week: "星期天",
beginDate: "04:00",
endDate: "23:59",
ganttBarConfig: {
id: "6",
immobile: false,
hasHandles: false,
label: "部署和上线 负责人:老王",
style: {
background: "#f3953d"
}
}
}
]
]);
const getWeekRange=()=> {
const today = new Date();
const dayOfWeek = today.getDay();
const startDate = new Date(today);
startDate.setDate(today.getDate() - dayOfWeek + 1);
const endDate = new Date(startDate);
endDate.setDate(startDate.getDate() + 6);
const formatDate = date => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
const currentWeekStart = formatDate(startDate);
const currentWeekEnd = formatDate(endDate);
return {
currentWeekStart,
currentWeekEnd
};
}
const weekRangeInChina = getWeekRange();
</script>
<style lang="scss" scoped>
.header{
@ -220,4 +390,29 @@ const handleCurrentChange = (current1) => {
padding-top: 15px;
box-sizing: border-box;
}
</style>
.demo-rate-block {
padding: 15px 0;
text-align: center;
border-right: solid 1px var(--el-border-color);
display: inline-block;
width: 49%;
box-sizing: border-box;
}
.demo-rate-block:last-child {
border-right: none;
}
.demo-rate-block .demonstration {
display: block;
color: var(--el-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
model-value="dialogUpdateVisible"
model-value="edialogUpdateVisible"
:title="dialogTitle"
width="30%"
@close="handleClose"
@ -10,25 +10,14 @@
:model="form"
label-width="100px"
>
<el-form-item label="用户头像" prop="avatarUrl">
<!-- {{ form.avatarUrl }}-->
<el-input v-model="form.avatarUrl"/>
<el-form-item label="头像" prop="manicuristAvatar">
<el-input v-model="form.manicuristAvatar"/>
</el-form-item>
<el-form-item label="用户昵称" prop="username">
<el-input v-model="form.username"/>
</el-form-item>
<el-form-item label="用户ID" prop="id">
<el-input v-model="form.id"/>
<el-form-item label="用户昵称" prop="manicuristName">
<el-input v-model="form.manicuristName"/>
</el-form-item>
<el-form-item label="性别" prop="gender">
<template v-if="form.gender==0"></template>
<template v-else></template>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<el-radio-group v-model="form.gender">
<el-radio :value="0" size="default"></el-radio>
<el-radio :value="1" size="default"></el-radio>
</el-radio-group>
<el-input v-model="form.gender"/>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone"/>
@ -36,27 +25,20 @@
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email"/>
</el-form-item>
<el-form-item label="用户状态" prop="userStatus">
<el-input v-model="form.userStatus"/>
<el-form-item label="工作名称" prop="specialties">
<el-input v-model="form.specialties"/>
</el-form-item>
<el-form-item label="用户角色" prop="userRole">
<!-- {{form.userRole}}-->
<!-- {{labelt}}-->
<!-- 展示由于v-model绑定出现v-model的form.userRole的值-->
<el-select
v-model="form.userRole"
size="default"
placeholder="用户角色"
style="width: 100%"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-form-item label="关联商家ID" prop="businessId">
<el-input v-model="form.businessId"/>
</el-form-item>
<el-form-item label="工作时长" prop="employment_date">
<el-input v-model="form.employment_date"/>
</el-form-item>
<el-form-item label="评分" prop="rating">
<el-input v-model="form.rating"/>
</el-form-item>
<el-form-item label="余额" prop="salary">
<el-input v-model="form.salary"/>
</el-form-item>
</el-form>
<template #footer>
@ -75,7 +57,7 @@ import {ElMessage} from "element-plus";
const props = defineProps({
id: {
type: String,
default: -1,
default: '',
required: true
},
dialogTitle: {
@ -84,77 +66,52 @@ const props = defineProps({
required: true
}
})
const labelt=ref('')
const form = ref({
id:null,
avatarUrl: "",
email: "",
gender: null,
phone: null,
userRole: null,
userStatus: null,
username: ""
phone: "",
businessId: "",
manicuristName: "",
employment_date: "",
specialties: "",
rating: null,
salary: null,
manicuristAvatar: ""
})
const options = [
{
value: '',
label: '用户身份',
},
{
value: '0',
label: '普通用户',
},
{
value: '1',
label: '管理员',
},
{
value: '2',
label: '商家',
},
{
value: '3',
label: '美甲师',
},
]
const formRef = ref(null);
const initFormData = async (ids) => {
const res = await axios.get("user/getById", {id: ids})
const initFormData = async (id) => {
const res = await axios.get("manicurist/queryById", {manicuristId: id})
form.value = res.data.data;
labelt.value=options[form.value.userRole].label
// console.log(options[form.value.userRole].label)
// console.log(res.data.data)
}
watch(
() => props.id,
() => {
// console.log("id=" + props.useraccount);
let ids = props.id;
initFormData(ids)
// console.log("id=" + props.id);
let id = props.id;
initFormData(id)
}
)
//
const emits = defineEmits(['update:modelValue', 'initUserList'])
const emits = defineEmits(['update:modelValue', 'initEmployeeList'])
const handleClose = () => {
console.log("xxx")
//
//
emits('update:modelValue', false)
}
const handleConfirm = () => {
formRef.value.validate(async (valid) => {
if (valid) {
let result = await axios.post("user/update", form.value)
let result = await axios.post("manicurist/update", form.value)
console.log(result.data.data)
let data = result.data;
if (data.code == 0) {
ElMessage.success("执行成功!");
formRef.value.resetFields();
emits("initUserList");
emits("initEmployeeList");
handleClose();
} else {
ElMessage.error(data.description);
@ -167,5 +124,4 @@ const handleConfirm = () => {
}
</script>
<style scoped>
</style>
</style>

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
model-value="dialogaddVisible"
model-value="RdialogaddVisible"
:title="dialogTitle"
width="30%"
@close="handleClose"
@ -10,26 +10,27 @@
:model="form"
label-width="100px"
>
<el-form-item label="门店头像" prop="avatarUrl">
<el-upload list-type="picture-card" limit="1" :auto-upload="false" drag action="#">
<el-icon><Plus /></el-icon>
<template #tip>
<div class="el-upload__tip">
最多传一张
</div>
</template>
</el-upload>
<el-form-item label="商家ID" prop="businessId">
<el-input v-model="form.businessId" />
</el-form-item>
<el-form-item label="用户昵称" prop="username">
<el-input v-model="form.username" />
<el-form-item label="美甲师ID" prop="manicuristId">
<el-input v-model="form.manicuristId" />
</el-form-item>
<el-form-item label="用户账号" prop="userAccount">
<el-input v-model="form.userAccount" />
<el-form-item label="美甲师评分0-5" prop="manicuristRating">
<el-input v-model="form.manicuristRating" show-password />
</el-form-item>
<el-form-item label="用户密码" prop="userPassword">
<el-input v-model="form.userPassword" show-password />
<el-form-item label="订单ID" prop="orderId">
<el-input v-model="form.orderId" show-password />
</el-form-item>
<el-form-item label="评分0-5" prop="rating">
<el-input v-model="form.rating" show-password />
</el-form-item>
<el-form-item label="用户ID" prop="userId">
<el-input v-model="form.userId" show-password />
</el-form-item>
<el-form-item label="回复" prop="review">
<el-input v-model="form.review" show-password />
</el-form-item>
</el-form>
@ -56,30 +57,20 @@ const props=defineProps({
}
})
const form=ref({
avatarUrl:'',
userAccount:'',
userPassword:'',
username:null
businessId: null,
manicuristId: null,
manicuristRating: null,
orderId: null,
rating: null,
review: "",
userId: null
})
// const rules=ref({
// name: [
// {
// required: true,
// message: ''
// }
// ],
// remark: [
// {
// required: true,
// message: ''
// }
// ]
// })
const formRef=ref(null);
//
const emits=defineEmits(['update:modelValue','initUserList'])
const emits=defineEmits(['update:modelValue','initRatingList'])
const handleClose=()=>{
console.log("用户添加关闭xxx")
//
@ -88,13 +79,13 @@ const handleClose=()=>{
const handleConfirm=()=>{
formRef.value.validate(async(valid)=>{
if(valid){
let result=await axios.post("user/add",form.value)
let result=await axios.post("level/add",form.value)
console.log(result.data)
let data=result.data;
if(data.code==0){
ElMessage.success("执行添加成功!");
formRef.value.resetFields();
emits("initUserList");
emits("initRatingList");
handleClose();
}else{
ElMessage.error(data.description);

View File

@ -2,10 +2,10 @@
<el-card>
<el-row :gutter="20" class="header">
<el-col :span="7">
<el-input placeholder="请输入用户昵称..." clearable v-model="queryForm.username"></el-input>
<el-input placeholder="请输入商家ID..." clearable v-model="businessId"></el-input>
</el-col>
<el-button type="button" :icon="Search" @click="initRatingList" >搜索</el-button>
<el-button type="primary" :icon="DocumentAdd" @click="handleAddDialogValue()" >添加评论</el-button>
<el-button type="primary" :icon="DocumentAdd" @click="handleAddDialogValue()" >添加用户评论</el-button>
</el-row>
<el-table :data="tableData" stripe style="width: 100%;" showOverflowTooltip>
<el-table-column fixed prop="id" label="#ID" width="80" />
@ -18,14 +18,11 @@
<el-table-column prop="businessReview" label="商家评论" width="200" />
<el-table-column prop="createTime" label="注册日期" width="200"/>
<el-table-column prop="action" fixed="right" label="操作" min-width="170">
<!-- <template v-slot="scope" >-->
<!-- <el-button type="success" size="small" @click="handleDialogValue(scope.row.id)">-->
<!-- 详情-->
<!-- </el-button>-->
<!-- <el-button type="primary" size="small" :icon="Edit" @click="handleUpdateDialogValue(scope.row.id)"></el-button>-->
<!-- <el-button type="danger" size="small" :icon="Delete" @click="handleDelete(scope.row.id)"></el-button>-->
<!-- </template>-->
<el-table-column prop="action" fixed="right" label="操作" min-width="200">
<template v-slot="scope" >
<el-button type="primary" size="small" :icon="Edit" @click="handleUpdateDialogValue(scope.row.id)">添加商家回复</el-button>
<el-button type="danger" size="small" :icon="Delete" @click="handleDelete(scope.row.id)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@ -37,62 +34,51 @@
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
<!-- {{total}}-->
</el-card>
<Dialog v-model="UdialogVisible" :id="id" :dialogTitle="dialogTitle"
@initUserList="initUserList"></Dialog>
<AddDialog v-model="UdialogaddVisible" :dialogTitle="dialogTitle"
@initUserList="initUserList"></AddDialog>
<UpdateDialog v-model="UdialogUpdateVisible" :id="id" :dialogTitle="dialogTitle"
@initUserList="initUserList"></UpdateDialog>
<AddDialog v-model="RdialogaddVisible" :dialogTitle="dialogTitle"
@initRatingList="initRatingList"></AddDialog>
<UpdateDialog v-model="RdialogUpdateVisible" :id="id" :dialogTitle="dialogTitle"
@initRatingList="initRatingList"></UpdateDialog>
</template>
<script setup>
import {Search,Delete,Edit,DocumentAdd,Close,Check} from '@element-plus/icons-vue'
import {ref, watch} from 'vue'
import axios from "@/util/axios";
import Dialog from '@/views/user/dialog/index.vue'
import AddDialog from '@/views/user/addDialog/index.vue'
import UpdateDialog from '@/views/user/updateDialog/index.vue'
import UpdateDialog from '@/views/rating/updateDialog/index.vue'
import AddDialog from '@/views/rating/addDialog/index.vue'
import { ElMessage,ElMessageBox } from "element-plus";
import {parseTime} from "element-plus/es/components/time-select/src/utils";
const dialogTitle=ref('')
const id=ref()
const RdialogaddVisible=ref(false)
const RdialogUpdateVisible=ref(false)
const handleAddDialogValue=()=>{
dialogTitle.value="添加用户评论"
RdialogaddVisible.value=true
}
const handleUpdateDialogValue=(ids)=>{
id.value=ids;
dialogTitle.value="添加商家回复"
RdialogUpdateVisible.value=true
}
const businessId=ref()
const queryForm=ref({
username: '',
current:1,
pageSize:10
})
// const id=ref('')
// const dialogTitle=ref('');
// const UdialogaddVisible=ref(false)
// const UdialogVisible=ref(false)
// const UdialogUpdateVisible=ref(false)
// const handleDialogValue=(ids)=>{
// id.value=ids;
// dialogTitle.value=""
// UdialogVisible.value=true
// }
//
// const handleUpdateDialogValue=(ids)=>{
// id.value=ids;
// dialogTitle.value=""
// UdialogUpdateVisible.value=true
// }
//
// const handleAddDialogValue=()=>{
// dialogTitle.value=""
// UdialogaddVisible.value=true
// }
//
@ -134,19 +120,34 @@ const total=ref(0)
const tableData =ref([])
const initRatingList=async()=>{
// console.log(businessId.value)
if (!businessId.value){
const res = await axios.post("level/list");
// console.log(res.data.data)
if (res.data.data) {
tableData.value = res.data.data;
//console.log(res.data.data)
total.value = Number(res.data.data.length);
} else {
ElMessage.error(res.data.description);
}
}else {
const res = await axios.get("level/listBusinessRating",{businessId: businessId.value});
console.log(res.data.data)
if (res.data.data) {
tableData.value = res.data.data;
//console.log(res.data.data)
total.value = Number(res.data.data.length);
} else {
ElMessage.error(res.data.description);
}
const res = await axios.post("level/list");
console.log(res.data.data)
if (res.data.data) {
tableData.value = res.data.data;
//console.log(res.data.data)
total.value = Number(res.data.data.length);
}
else{
ElMessage.error(res.data.description);
}
}
initRatingList();
const handleSizeChange = (pageSize) => {
queryForm.value.current=1;
queryForm.value.pageSize=pageSize;

View File

@ -1,63 +1,24 @@
<template>
<el-dialog
model-value="dialogUpdateVisible"
model-value="RdialogUpdateVisible"
:title="dialogTitle"
width="30%"
@close="handleClose"
>
<el-form
ref="formRef"
:model="form"
label-width="100px"
>
<el-form-item label="用户头像" prop="avatarUrl">
<!-- {{ form.avatarUrl }}-->
<el-input v-model="form.avatarUrl"/>
</el-form-item>
<el-form-item label="用户昵称" prop="username">
<el-input v-model="form.username"/>
</el-form-item>
<el-form-item label="用户ID" prop="id">
<el-form-item label="评论ID" >
<el-input v-model="form.id"/>
</el-form-item>
<el-form-item label="性别" prop="gender">
<template v-if="form.gender==0"></template>
<template v-else></template>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<el-radio-group v-model="form.gender">
<el-radio :value="0" size="default"></el-radio>
<el-radio :value="1" size="default"></el-radio>
</el-radio-group>
<el-form-item label="商家回复" >
<el-input v-model="form.businessReview"/>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone"/>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email"/>
</el-form-item>
<el-form-item label="用户状态" prop="userStatus">
<el-input v-model="form.userStatus"/>
</el-form-item>
<el-form-item label="用户角色" prop="userRole">
<!-- {{form.userRole}}-->
<!-- {{labelt}}-->
<!-- 展示由于v-model绑定出现v-model的form.userRole的值-->
<el-select
v-model="form.userRole"
size="default"
placeholder="用户角色"
style="width: 100%"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
@ -84,63 +45,24 @@ const props = defineProps({
required: true
}
})
const labelt=ref('')
const form = ref({
id:null,
avatarUrl: "",
email: "",
gender: null,
phone: null,
userRole: null,
userStatus: null,
username: ""
businessReview: "",
})
const options = [
{
value: '',
label: '用户身份',
},
{
value: '0',
label: '普通用户',
},
{
value: '1',
label: '管理员',
},
{
value: '2',
label: '商家',
},
{
value: '3',
label: '美甲师',
},
]
const formRef = ref(null);
const initFormData = async (ids) => {
const res = await axios.get("user/getById", {id: ids})
form.value = res.data.data;
labelt.value=options[form.value.userRole].label
// console.log(options[form.value.userRole].label)
}
watch(
() => props.id,
() => {
// console.log("id=" + props.useraccount);
let ids = props.id;
initFormData(ids)
form.value.id = props.id;
}
)
//
const emits = defineEmits(['update:modelValue', 'initUserList'])
const emits = defineEmits(['update:modelValue', 'initRatingList'])
const handleClose = () => {
console.log("xxx")
//
@ -149,12 +71,12 @@ const handleClose = () => {
const handleConfirm = () => {
formRef.value.validate(async (valid) => {
if (valid) {
let result = await axios.post("user/update", form.value)
let result = await axios.post("level/business/reply", form.value)
let data = result.data;
if (data.code == 0) {
ElMessage.success("执行成功!");
formRef.value.resetFields();
emits("initUserList");
emits("initRatingList");
handleClose();
} else {
ElMessage.error(data.description);

View File

@ -1,474 +0,0 @@
<template>
<el-row :gutter="16">
<el-col :span="6">
<div class="statistic-card">
<el-statistic :value="98500">
<template #title>
<div style="display: inline-flex; justify-self: right;align-items: center;width: 100%">
用户人数
<el-tooltip
effect="dark"
content="Number of users who logged into the product in one day"
placement="top"
>
<el-icon style="margin-left: 4px" :size="12">
<Warning />
</el-icon>
</el-tooltip>
<el-icon style="float: right" size="24"><Odometer /></el-icon>
</div>
</template>
</el-statistic>
<div class="statistic-footer">
<div class="footer-item">
<span class="green">
+24%
<el-icon>
<CaretTop />
</el-icon>
</span>
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="statistic-card">
<el-statistic :value="693700">
<template #title>
<div style="display: inline-flex; align-items: center">
商家人数
<el-tooltip
effect="dark"
content="Number of users who logged into the product in one month"
placement="top"
>
<el-icon style="margin-left: 4px" :size="12">
<Warning />
</el-icon>
</el-tooltip>
</div>
</template>
</el-statistic>
<div class="statistic-footer">
<div class="footer-item">
<span class="red">
+12%
<el-icon>
<CaretBottom />
</el-icon>
</span>
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="statistic-card">
<el-statistic :value="72000" title="New transactions today">
<template #title>
<div style="display: inline-flex; align-items: center">
订单数量
</div>
</template>
</el-statistic>
<div class="statistic-footer">
<div class="footer-item">
<span class="green">
+16%
<el-icon>
<CaretTop />
</el-icon>
</span>
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="statistic-card">
<el-statistic :value="72000" title="New transactions today">
<template #title>
<div style="display: inline-flex; align-items: center">
用户满意度
</div>
</template>
</el-statistic>
<div class="statistic-footer">
<div class="footer-item">
<span class="green">
+16%
<el-icon>
<CaretTop />
</el-icon>
</span>
</div>
</div>
</div>
</el-col>
</el-row>
<!-- ============================================================================ -->
<el-row :gutter="16">
<el-col :span="18">
<div class="statistic-card">
<div style="display: inline-flex; justify-self: right;align-items: center;width: 100%">
分析概览
</div>
<div class="statistic-footer">
<div class="footer-item">
<div id="main1" style="height: 320px;width: 780px;border: 1px solid #ebebeb;border-radius: 2px;"></div>
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="statistic-card">
<div style="display: inline-flex; justify-self: right;align-items: center;width: 100%">
每周展示
</div>
<div class="statistic-footer">
<div class="footer-item">
<div style="height: 320px;width: 220px;border: 1px solid #ebebeb;border-radius: 2px;">
<div class="common" >
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周日</div>
</div>
<!-- ---------->
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周六</div>
</div>
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周五</div>
</div>
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周四</div>
</div>
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周三</div>
</div>
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周二</div>
</div>
<div class="common">
<div style="flex: 8"><el-progress
:text-inside="true"
:stroke-width="15"
:percentage="100"
duration="30"
color="#26ce83"
striped
striped-flow
/></div>
<div style="flex: 1">周一</div>
</div>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
</template>
<script setup>
import {
ArrowRight,
Odometer,
CaretBottom,
CaretTop,
Warning,
} from '@element-plus/icons-vue'
import {onMounted} from "vue";
import * as echarts from 'echarts';
onMounted(async () => {
setTimeout(() => {hei();}, 500)
})
const hei=()=>{
var app = {};
var chartDom = document.getElementById('main1');
var myChart = echarts.init(chartDom);
var option;
const posList = [
'left',
'right',
'top',
'bottom',
'inside',
'insideTop',
'insideLeft',
'insideRight',
'insideBottom',
'insideTopLeft',
'insideTopRight',
'insideBottomLeft',
'insideBottomRight'
];
app.configParameters = {
rotate: {
min: -90,
max: 90
},
align: {
options: {
left: 'left',
center: 'center',
right: 'right'
}
},
verticalAlign: {
options: {
top: 'top',
middle: 'middle',
bottom: 'bottom'
}
},
position: {
options: posList.reduce(function (map, pos) {
map[pos] = pos;
return map;
}, {})
},
distance: {
min: 0,
max: 100
}
};
app.config = {
rotate: 90,
align: 'left',
verticalAlign: 'middle',
position: 'insideBottom',
distance: 15,
onChange: function () {
const labelOption = {
rotate: app.config.rotate,
align: app.config.align,
verticalAlign: app.config.verticalAlign,
position: app.config.position,
distance: app.config.distance
};
myChart.setOption({
series: [
{
label: labelOption
},
{
label: labelOption
},
{
label: labelOption
},
{
label: labelOption
}
]
});
}
};
const labelOption = {
show: true,
position: app.config.position,
distance: app.config.distance,
align: app.config.align,
verticalAlign: app.config.verticalAlign,
rotate: app.config.rotate,
formatter: '{c} {name|{a}}',
fontSize: 16,
rich: {
name: {}
}
};
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Forest', 'Steppe', 'Desert', 'Wetland']
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
mark: { show: true },
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ['line', 'bar', 'stack'] },
restore: { show: true },
saveAsImage: { show: true }
}
},
xAxis: [
{
type: 'category',
axisTick: { show: false },
data: ['2012', '2013', '2014', '2015', '2016']
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: 'Forest',
type: 'bar',
barGap: 0,
label: labelOption,
emphasis: {
focus: 'series'
},
data: [320, 332, 301, 334, 390]
},
{
name: 'Steppe',
type: 'bar',
label: labelOption,
emphasis: {
focus: 'series'
},
data: [220, 182, 191, 234, 290]
},
{
name: 'Desert',
type: 'bar',
label: labelOption,
emphasis: {
focus: 'series'
},
data: [150, 232, 201, 154, 190]
},
{
name: 'Wetland',
type: 'bar',
label: labelOption,
emphasis: {
focus: 'series'
},
data: [98, 77, 101, 99, 40]
}
]
};
option && myChart.setOption(option);
}
</script>
<style scoped>
:global(h2#card-usage ~ .example .example-showcase) {
background-color: var(--el-fill-color) !important;
}
.common{
display: flex;
padding: 15px 0 15px;
}
.common_left{
flex: 8;
}
.common_right{
flex: 1;
}
.statistic-card {
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
background-color: #f0f2f5;
}
.statistic-footer {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
font-size: 12px;
color: var(--el-text-color-regular);
margin-top: 16px;
}
.statistic-footer .footer-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.statistic-footer .footer-item span:last-child {
display: inline-flex;
align-items: center;
margin-left: 4px;
}
.green {
color: var(--el-color-success);
}
.red {
color: var(--el-color-error);
}
</style>