Compare commits

..

2 Commits

Author SHA1 Message Date
Leo_Ding
7beb9fd909 开发 2025-07-10 17:33:05 +08:00
Leo_Ding
69a80a2e2f 邻里互助 2025-07-07 16:26:31 +08:00
83 changed files with 7242 additions and 746 deletions

View File

@ -2,7 +2,7 @@
NODE_ENV=development NODE_ENV=development
# app # app
VITE_TITLE=GuXuan-Admin VITE_TITLE=JinShan-Admin
VITE_PUBLIC_PATH=/ VITE_PUBLIC_PATH=/
VITE_OUT_DIR=dist VITE_OUT_DIR=dist
VITE_PERMISSION=false VITE_PERMISSION=false
@ -12,7 +12,7 @@ VITE_ROUTER_BASE=/
VITE_ROUTER_HISTORY=hash VITE_ROUTER_HISTORY=hash
# api # api
VITE_API_BASIC=/ VITE_API_BASIC=http://10.10.1.6:8071
VITE_API_HTTP=/api/v1/ VITE_API_HTTP=/api/v1/
# storage # storage
VITE_STORAGE_NAMESPACE = gin-admin_local_ VITE_STORAGE_NAMESPACE = gin-admin_local_

View File

@ -2,7 +2,7 @@
NODE_ENV=production NODE_ENV=production
# app # app
VITE_TITLE=GuXuan-Admin VITE_TITLE=JinShan-Admin
VITE_PUBLIC_PATH=/ VITE_PUBLIC_PATH=/
VITE_OUT_DIR=dist VITE_OUT_DIR=dist
VITE_PERMISSION=true VITE_PERMISSION=true

View File

@ -1,8 +1,8 @@
# GuXuan-Admin-Template # JinShan-Admin-Template
> GIN-Admin-vue is a frontend project for [gin-admin](https://github.com/LyricTian/gin-admin) base on Ant Design React. > GIN-Admin-vue is a frontend project for [gin-admin](https://github.com/LyricTian/gin-admin) base on Ant Design React.
![guxuan-admin-template](./demo.png) ![JinShan-Admin-template](./demo.png)
- [Preview](http://101.42.232.163:8040) - [Preview](http://101.42.232.163:8040)
- Username: admin - Username: admin

View File

@ -1,9 +1,10 @@
export default () => ({ export default () => ({
host: true, host: true,
port: 8080, port: 8080,
open:true,
proxy: { proxy: {
'/api': { '/api': {
target: 'http://101.42.232.163:8080/api', target: 'http://10.10.1.6:8071',
// target: 'http://127.0.0.1:8045/api', // target: 'http://127.0.0.1:8045/api',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace('/api', ''), rewrite: (path) => path.replace('/api', ''),

593
package-lock.json generated
View File

@ -1,13 +1,14 @@
{ {
"name": "gin-admin", "name": "JinShan-Admin",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "gin-admin", "name": "JinShan-Admin",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@ant-design/colors": "^7.0.0", "@ant-design/colors": "^7.0.0",
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^6.1.0",
"@icon-park/vue-next": "^1.4.2", "@icon-park/vue-next": "^1.4.2",
@ -49,10 +50,12 @@
"husky": "^8.0.3", "husky": "^8.0.3",
"less": "^4.2.0", "less": "^4.2.0",
"lint-staged": "^14.0.0", "lint-staged": "^14.0.0",
"mockjs": "^1.1.0",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.9.2",
"vite": "^4.4.9", "vite": "^4.4.9",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-plugin-mock": "^3.0.2",
"vite-plugin-progress": "^0.0.7", "vite-plugin-progress": "^0.0.7",
"vitepress": "^1.0.0-beta.7" "vitepress": "^1.0.0-beta.7"
} }
@ -240,6 +243,12 @@
"@algolia/requester-common": "4.19.1" "@algolia/requester-common": "4.19.1"
} }
}, },
"node_modules/@amap/amap-jsapi-loader": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
"integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==",
"license": "MIT"
},
"node_modules/@ant-design/colors": { "node_modules/@ant-design/colors": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz", "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz",
@ -1479,6 +1488,20 @@
"@ctrl/tinycolor": "^3.4.0" "@ctrl/tinycolor": "^3.4.0"
} }
}, },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/argparse": { "node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
@ -1533,6 +1556,19 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/body-scroll-lock": { "node_modules/body-scroll-lock": {
"version": "4.0.0-beta.0", "version": "4.0.0-beta.0",
"resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz", "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz",
@ -1591,6 +1627,22 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/bundle-require": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/bundle-require/-/bundle-require-4.2.1.tgz",
"integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==",
"dev": true,
"license": "MIT",
"dependencies": {
"load-tsconfig": "^0.2.3"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"peerDependencies": {
"esbuild": ">=0.17"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
@ -1624,6 +1676,44 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/cli-cursor": { "node_modules/cli-cursor": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz",
@ -1764,6 +1854,39 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true "dev": true
}, },
"node_modules/connect": {
"version": "3.7.0",
"resolved": "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz",
"integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"finalhandler": "1.1.2",
"parseurl": "~1.3.3",
"utils-merge": "1.0.1"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/connect/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/connect/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
"license": "MIT"
},
"node_modules/copy-anything": { "node_modules/copy-anything": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
@ -1949,6 +2072,13 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
}, },
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"dev": true,
"license": "MIT"
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -1959,6 +2089,16 @@
"resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
}, },
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/errno": { "node_modules/errno": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
@ -2018,6 +2158,13 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true,
"license": "MIT"
},
"node_modules/escape-string-regexp": { "node_modules/escape-string-regexp": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -2446,6 +2593,42 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/finalhandler/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
"license": "MIT"
},
"node_modules/find-up": { "node_modules/find-up": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@ -2737,6 +2920,19 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true "dev": true
}, },
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-docker": { "node_modules/is-docker": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
@ -3137,6 +3333,16 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/load-tsconfig": {
"version": "0.2.5",
"resolved": "https://registry.npmmirror.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz",
"integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/locate-path": { "node_modules/locate-path": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -3385,12 +3591,23 @@
"integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==", "integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==",
"dev": true "dev": true
}, },
"node_modules/mockjs": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz",
"integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==",
"dev": true,
"dependencies": {
"commander": "*"
},
"bin": {
"random": "bin/random"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true, "dev": true
"optional": true
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "4.0.2", "version": "4.0.2",
@ -3438,6 +3655,16 @@
"node": ">= 4.4.x" "node": ">= 4.4.x"
} }
}, },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz",
@ -3476,6 +3703,19 @@
"url": "https://github.com/fb55/nth-check?sponsor=1" "url": "https://github.com/fb55/nth-check?sponsor=1"
} }
}, },
"node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"dev": true,
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": { "node_modules/once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -3599,6 +3839,16 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-exists": { "node_modules/path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -3625,6 +3875,13 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/path-to-regexp": {
"version": "6.3.0",
"resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
"dev": true,
"license": "MIT"
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -3886,6 +4143,19 @@
"integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
"dev": true "dev": true
}, },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/regenerator-runtime": { "node_modules/regenerator-runtime": {
"version": "0.13.9", "version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
@ -4363,6 +4633,16 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/string-argv": { "node_modules/string-argv": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz",
@ -4538,6 +4818,16 @@
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
}, },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/untildify": { "node_modules/untildify": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz",
@ -4562,6 +4852,16 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true "dev": true
}, },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "4.4.9", "version": "4.4.9",
"resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz", "resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz",
@ -4666,6 +4966,48 @@
"vite": ">=2" "vite": ">=2"
} }
}, },
"node_modules/vite-plugin-mock": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-3.0.2.tgz",
"integrity": "sha512-bD//HvkTygGmk+LsIAdf0jGNlCv4iWv0kZlH9UEgWT6QYoUwfjQAE4SKxHRw2tfLgVhbPQVv/+X3YlNWvueGUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"bundle-require": "^4.0.1",
"chokidar": "^3.5.3",
"connect": "^3.7.0",
"debug": "^4.3.4",
"fast-glob": "^3.2.12",
"path-to-regexp": "^6.2.1",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"esbuild": ">=0.17",
"mockjs": ">=1.1.0",
"vite": ">=4.0.0"
}
},
"node_modules/vite-plugin-mock/node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/vite-plugin-progress": { "node_modules/vite-plugin-progress": {
"version": "0.0.7", "version": "0.0.7",
"resolved": "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz",
@ -5179,6 +5521,11 @@
"@algolia/requester-common": "4.19.1" "@algolia/requester-common": "4.19.1"
} }
}, },
"@amap/amap-jsapi-loader": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
"integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
},
"@ant-design/colors": { "@ant-design/colors": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz", "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz",
@ -5977,6 +6324,16 @@
} }
} }
}, },
"anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"argparse": { "argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
@ -6025,6 +6382,12 @@
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz",
"integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw=="
}, },
"binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true
},
"body-scroll-lock": { "body-scroll-lock": {
"version": "4.0.0-beta.0", "version": "4.0.0-beta.0",
"resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz", "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz",
@ -6074,6 +6437,15 @@
"run-applescript": "^5.0.0" "run-applescript": "^5.0.0"
} }
}, },
"bundle-require": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/bundle-require/-/bundle-require-4.2.1.tgz",
"integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==",
"dev": true,
"requires": {
"load-tsconfig": "^0.2.3"
}
},
"callsites": { "callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
@ -6095,6 +6467,33 @@
"supports-color": "^7.1.0" "supports-color": "^7.1.0"
} }
}, },
"chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"dependencies": {
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
}
}
},
"cli-cursor": { "cli-cursor": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz",
@ -6212,6 +6611,35 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true "dev": true
}, },
"connect": {
"version": "3.7.0",
"resolved": "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz",
"integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
"dev": true,
"requires": {
"debug": "2.6.9",
"finalhandler": "1.1.2",
"parseurl": "~1.3.3",
"utils-merge": "1.0.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
}
}
},
"copy-anything": { "copy-anything": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
@ -6363,6 +6791,12 @@
} }
} }
}, },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"dev": true
},
"emoji-regex": { "emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -6373,6 +6807,12 @@
"resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
}, },
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true
},
"errno": { "errno": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
@ -6419,6 +6859,12 @@
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true "dev": true
}, },
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true
},
"escape-string-regexp": { "escape-string-regexp": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -6737,6 +7183,38 @@
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
} }
}, },
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"dev": true,
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
}
}
},
"find-up": { "find-up": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@ -6946,6 +7424,15 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true "dev": true
}, },
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-docker": { "is-docker": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
@ -7238,6 +7725,12 @@
} }
} }
}, },
"load-tsconfig": {
"version": "0.2.5",
"resolved": "https://registry.npmmirror.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz",
"integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==",
"dev": true
},
"locate-path": { "locate-path": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -7431,12 +7924,20 @@
"integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==", "integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==",
"dev": true "dev": true
}, },
"mockjs": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz",
"integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==",
"dev": true,
"requires": {
"commander": "*"
}
},
"ms": { "ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true, "dev": true
"optional": true
}, },
"nanoid": { "nanoid": {
"version": "4.0.2", "version": "4.0.2",
@ -7466,6 +7967,12 @@
"sax": "^1.2.4" "sax": "^1.2.4"
} }
}, },
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"npm-run-path": { "npm-run-path": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz",
@ -7497,6 +8004,15 @@
"boolbase": "^1.0.0" "boolbase": "^1.0.0"
} }
}, },
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"dev": true,
"requires": {
"ee-first": "1.1.1"
}
},
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -7587,6 +8103,12 @@
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
"dev": true "dev": true
}, },
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"dev": true
},
"path-exists": { "path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -7604,6 +8126,12 @@
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true "dev": true
}, },
"path-to-regexp": {
"version": "6.3.0",
"resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
"dev": true
},
"picocolors": { "picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -7761,6 +8289,15 @@
} }
} }
}, },
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.9", "version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
@ -8117,6 +8654,12 @@
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
}, },
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"dev": true
},
"string-argv": { "string-argv": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz",
@ -8254,6 +8797,12 @@
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true "dev": true
}, },
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"dev": true
},
"untildify": { "untildify": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz",
@ -8275,6 +8824,12 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true "dev": true
}, },
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true
},
"vite": { "vite": {
"version": "4.4.9", "version": "4.4.9",
"resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz", "resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz",
@ -8337,6 +8892,32 @@
"rollup": "^2.77.2" "rollup": "^2.77.2"
} }
}, },
"vite-plugin-mock": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-3.0.2.tgz",
"integrity": "sha512-bD//HvkTygGmk+LsIAdf0jGNlCv4iWv0kZlH9UEgWT6QYoUwfjQAE4SKxHRw2tfLgVhbPQVv/+X3YlNWvueGUA==",
"dev": true,
"requires": {
"bundle-require": "^4.0.1",
"chokidar": "^3.5.3",
"connect": "^3.7.0",
"debug": "^4.3.4",
"fast-glob": "^3.2.12",
"path-to-regexp": "^6.2.1",
"picocolors": "^1.0.0"
},
"dependencies": {
"debug": {
"version": "4.4.1",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"requires": {
"ms": "^2.1.3"
}
}
}
},
"vite-plugin-progress": { "vite-plugin-progress": {
"version": "0.0.7", "version": "0.0.7",
"resolved": "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz",

View File

@ -1,5 +1,5 @@
{ {
"name": "guxuan-admin", "name": "JinShan-Admin",
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
@ -17,6 +17,7 @@
"src/**/*.{js,vue}": "eslint --ext .js,.vue .eslintignore --no-cache --fix" "src/**/*.{js,vue}": "eslint --ext .js,.vue .eslintignore --no-cache --fix"
}, },
"dependencies": { "dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@ant-design/colors": "^7.0.0", "@ant-design/colors": "^7.0.0",
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^6.1.0",
"@icon-park/vue-next": "^1.4.2", "@icon-park/vue-next": "^1.4.2",
@ -58,10 +59,12 @@
"husky": "^8.0.3", "husky": "^8.0.3",
"less": "^4.2.0", "less": "^4.2.0",
"lint-staged": "^14.0.0", "lint-staged": "^14.0.0",
"mockjs": "^1.1.0",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.9.2",
"vite": "^4.4.9", "vite": "^4.4.9",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-plugin-mock": "^3.0.2",
"vite-plugin-progress": "^0.0.7", "vite-plugin-progress": "^0.0.7",
"vitepress": "^1.0.0-beta.7" "vitepress": "^1.0.0-beta.7"
} }

View File

@ -0,0 +1,16 @@
/**
* 区域模块接口
*/
import request from '@/utils/request'
// 获取项目列表
export const getProjectList = (params) => request.basic.get('/api/v1/activities', params)
// 获取单挑数据
export const getItem = (id) => request.basic.get(`/api/v1/activities/${id}`)
// 添加条目
export const createProject = (params) => request.basic.post('/api/v1/activities', params)
// 更新role
export const updateItem = (id, params) => request.basic.put(`/api/v1/activities/${id}`, params)
// 删除数据
export const delItem = (id) => request.basic.delete(`/api/v1/activities/${id}`)
//获取活动报名列表
export const getActivityList=(params)=>request.basic.get('/api/v1/activity-details',params)

View File

@ -0,0 +1,15 @@
/**
* 消息公告
*/
import request from '@/utils/request'
// 获取公告列表
export const getNoticesList = (params) => request.basic.get('/api/v1/notices', params)
// 获取条目
export const getNotices = (id) => request.basic.get(`/api/v1/notices/${id}`)
// 添加公告
export const createNotices = (params) => request.basic.post('/api/v1/notices', params)
// 更新公告
export const updateNotices = (id, params) => request.basic.put(`/api/v1/notices/${id}`, params)
// 删除公告
export const delNotices = (id) => request.basic.delete(`/api/v1/notices/${id}`)

View File

@ -5,3 +5,10 @@ export const getRegion = (params) => request.basic.get('/region', params)
// 获取 验证码ID // 获取 验证码ID
export const getCaptcha = (params) => request.basic.get('/api/v1/captcha/id', params) export const getCaptcha = (params) => request.basic.get('/api/v1/captcha/id', params)
//上传图片
export const uploadFile=(params)=>request.basic.post('/api/v1/upload',params,{
headers: {
'Content-Type': 'multipart/form-data'
},
})

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/customers', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/customers/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/customers', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/customers/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/customers/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/banners', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/banners/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/banners', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/banners/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/banners/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/metting-rooms', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/metting-rooms/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/metting-rooms', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/metting-rooms/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/metting-rooms/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/metting-room-orders', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/metting-room-orders/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/metting-room-orders', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/metting-room-orders/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/metting-room-orders/${id}`)

14
src/apis/modules/mock.js Normal file
View File

@ -0,0 +1,14 @@
/**
* 权限接口
*/
import request from '@/utils/request'
// 获取role列表
export const getUserRoleList = (params) => request.basic.get('/system/getUserRoleList', params)
// 获取role条数据
export const getRole = (id) => request.basic.get(`/api/v1/roles/${id}`)
// 添加role
export const createRole = (params) => request.basic.post('/api/v1/roles', params)
// 更新role
export const updateRole = (id, params) => request.basic.put(`/api/v1/roles/${id}`, params)
// 删除role
export const delRole = (id) => request.basic.delete(`/api/v1/roles/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('api/v1/mutualComment', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`api/v1/mutualComment/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('api/v1/mutualComment', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`api/v1/mutualComment/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`api/v1/mutualComment/${id}`)

View File

@ -0,0 +1,16 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/reciprocities', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/reciprocities/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/reciprocities', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/reciprocities/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/reciprocities/${id}`)
// 获取评论历史
export const getList = (id) => request.basic.get(`/api/v1/reciprocity-histories/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/work-orders', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/work-orders/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/work-orders', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/work-orders/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/work-orders/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/work-order-types', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/work-order-types/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/work-order-types', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/work-order-types/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/work-order-types/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/surrounding-services', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/surrounding-services/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/surrounding-services', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/surrounding-services/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/surrounding-services/${id}`)

View File

@ -0,0 +1,14 @@
/**
* 图片管理接口
*/
import request from '@/utils/request'
// 获取菜单列表
export const getDataList = (params) => request.basic.get('/api/v1/surrounding-service-types', params)
// 获取菜单条数据
export const getMenu = (id) => request.basic.get(`/api/v1/surrounding-service-types/${id}`)
// 添加菜单
export const createMenu = (params) => request.basic.post('/api/v1/surrounding-service-types', params)
// 更新菜单
export const updateMenu = (id, params) => request.basic.put(`/api/v1/surrounding-service-types/${id}`, params)
// 删除菜单
export const delMenu = (id) => request.basic.delete(`/api/v1/surrounding-service-types/${id}`)

View File

@ -2,6 +2,7 @@ import request from '@/utils/request'
// 登录 // 登录
export const login = (params) => request.basic.post('/api/v1/login', params) export const login = (params) => request.basic.post('/api/v1/login', params)
export const mocklogin = (params) => request.basic.post('/api/login', params)
// 获取用户详情 // 获取用户详情
export const getUserDetail = () => request.basic.get('/api/v1/current/user') export const getUserDetail = () => request.basic.get('/api/v1/current/user')
// 更新用户信息 // 更新用户信息

BIN
src/assets/blankSpace.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/errImg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,55 @@
@font-face {
font-family: "iconfont"; /* Project id 4966438 */
src: url('iconfont.woff2?t=1752057370159') format('woff2'),
url('iconfont.woff?t=1752057370159') format('woff'),
url('iconfont.ttf?t=1752057370159') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-cooperation:before {
content: "\e611";
}
.icon-huiyishi:before {
content: "\e614";
}
.icon-gongdan:before {
content: "\ec37";
}
.icon-zhoubian:before {
content: "\e739";
}
.icon-lishi:before {
content: "\e60e";
}
.icon-xiangqing:before {
content: "\e63c";
}
.icon-kaishi-yuan:before {
content: "\e64b";
}
.icon-shenhe:before {
content: "\f195";
}
.icon-huodongliebiao-copy:before {
content: "\e600";
}
.icon-gonggao:before {
content: "\e62a";
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,79 @@
{
"id": "4966438",
"name": "近山",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "551475",
"name": "同行互助",
"font_class": "cooperation",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "4942645",
"name": "会议室",
"font_class": "huiyishi",
"unicode": "e614",
"unicode_decimal": 58900
},
{
"icon_id": "5769243",
"name": "工单",
"font_class": "gongdan",
"unicode": "ec37",
"unicode_decimal": 60471
},
{
"icon_id": "14145077",
"name": "周边",
"font_class": "zhoubian",
"unicode": "e739",
"unicode_decimal": 59193
},
{
"icon_id": "10933913",
"name": "历史",
"font_class": "lishi",
"unicode": "e60e",
"unicode_decimal": 58894
},
{
"icon_id": "24848552",
"name": "详情",
"font_class": "xiangqing",
"unicode": "e63c",
"unicode_decimal": 58940
},
{
"icon_id": "34273005",
"name": "开始-圆",
"font_class": "kaishi-yuan",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "19738994",
"name": "审核",
"font_class": "shenhe",
"unicode": "f195",
"unicode_decimal": 61845
},
{
"icon_id": "29742036",
"name": "活动列表",
"font_class": "huodongliebiao-copy",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "8765148",
"name": "公告",
"font_class": "gonggao",
"unicode": "e62a",
"unicode_decimal": 58922
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -65,7 +65,7 @@ const content = ref('')
const opts = deepMerge( const opts = deepMerge(
{ {
language: 'zh-Hans', language: 'zh-Hans',
height: 480, height: props.height,
branding: false, branding: false,
resize: false, resize: false,
promotion: false, promotion: false,

View File

@ -0,0 +1,262 @@
<template>
<div class="map-container">
<!-- 地图容器 -->
<a-form-item :label="'输入地址'">
<a-input-search v-model:value="searchValue" placeholder="输入需要查找的地址" enter-button @search="searchLocation" />
</a-form-item>
<a-form-item :label="'搜索结果'">
<a-select ref="select" v-model:value="selectValue" style="width: 100%" @focus="focus" @change="handleChange" >
<a-select-option v-for="item in searchList" :value="item.id">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<div id="map" ref="mapContainer" style="height: calc(100% - 100px);"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted,defineEmits } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
defineOptions({
name: 'GxMap',
})
//
const map = ref(null)
const mapContainer = ref(null)
const searchValue = ref('')
const searchResult = ref(null);
const markers = ref([]);
const locationMode = ref()
const locationData = ref({});
const infoWindow = ref(null);
const geocoder = ref(null);
const selectValue = ref('')
const searchList = ref([])
const emit = defineEmits(['handleGetLng']) //
onMounted(() => {
initMap()
})
onUnmounted(() => {
if (map.value) {
map.value.destroy()
}
})
const initMap = async () => {
try {
//
window._AMapSecurityConfig = {
securityJsCode: 'df197447a4adc77f0cb376a44462272c' // jscode
};
// SDK
const AMap = await AMapLoader.load({
key: "38b334d84b1f89aa39d4efae76f0b341", // Key
version: "2.0", // SDK
plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.Geocoder'] //
})
//
map.value = new AMap.Map(mapContainer.value, {
zoom: 13, //
center: [120.894522,31.981269], //
viewMode: "3D" // 使3D
})
//
map.value.addControl(new AMap.ToolBar())
map.value.addControl(new AMap.Scale())
//
geocoder.value = new AMap.Geocoder({
city: "全国"
});
//
const marker = new AMap.Marker({
position: [120.894522,31.981269],
title: "南通市人民政府"
})
map.value.add(marker)
//
map.value.on('click', handleMapClick);
} catch (error) {
console.error("地图加载失败:", error)
}
}
//
const handleMapClick = (e) => {
//
clearMarkers();
//
const lng = e.lnglat.getLng();
const lat = e.lnglat.getLat();
//
locationMode.value = "点击定位";
//
locationData.value = {
lng: lng,
lat: lat,
name: "点击位置",
address: "正在获取地址..."
};
//
const marker = new AMap.Marker({
position: [lng, lat],
title: "点击位置"
});
map.value.add(marker);
markers.value.push(marker);
//
map.value.setCenter([lng, lat]);
// 使
geocoder.value.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.regeocode) {
const address = result.regeocode.formattedAddress;
locationData.value.address = address;
//
infoWindow.value = new AMap.InfoWindow({
content: `<div style="padding:10px;min-width:200px;">
<div style="font-weight:bold;margin-bottom:5px;">点击位置</div>
<div>${address}</div>
<div style="margin-top:8px;color:#666;">
<div>经度: ${lng.toFixed(6)}</div>
<div>纬度: ${lat.toFixed(6)}</div>
</div>
</div>`,
offset: new AMap.Pixel(0, -35)
});
const obj={address:address,lng:lng,lat:lat}
infoWindow.value.open(map.value, [lng, lat]);
emit('handleGetLng', obj)
} else {
locationData.value.address = "无法获取地址信息";
}
});
};
//
const searchLocation = () => {
if (!searchValue.value.trim()) {
alert('请输入搜索关键词');
return;
}
//
clearMarkers();
// 使
AMap.plugin('AMap.PlaceSearch', () => {
const placeSearch = new AMap.PlaceSearch({
pageSize: 10,
pageIndex: 1,
city: '全国'
});
placeSearch.search(searchValue.value, (status, result) => {
if (status === 'complete' && result.poiList.pois.length) {
searchList.value = result.poiList.pois.map(item => {
return {
id: item.id,
name: item.name,
address: item.address,
location: {
lng: item.location.lng,
lat: item.location.lat
}
}
})
console.log(searchList.value)
const poi = result.poiList.pois[0];
//
searchResult.value = {
id: poi.id,
name: poi.name,
address: poi.address,
location: {
lng: poi.location.lng,
lat: poi.location.lat
}
};
//
const marker = new AMap.Marker({
position: [poi.location.lng, poi.location.lat],
title: poi.name
});
map.value.add(marker);
markers.value.push(marker);
//
map.value.setCenter([poi.location.lng, poi.location.lat]);
//
const infoWindow = new AMap.InfoWindow({
content: `<div style="padding:5px;min-width:150px;">
<div style="font-weight:bold;">${poi.name}</div>
<div>${poi.address}</div>
<div>经度: ${poi.location.lng.toFixed(6)}</div>
<div>纬度: ${poi.location.lat.toFixed(6)}</div>
</div>`,
offset: new AMap.Pixel(0, -30)
});
infoWindow.open(map.value, marker.getPosition());
//
marker.on('click', () => {
infoWindow.open(map.value, marker.getPosition());
});
} else {
alert('未找到相关地点,请尝试其他关键词');
searchResult.value = null;
}
});
});
};
//
const clearMarkers = () => {
markers.value.forEach(marker => {
map.value.remove(marker);
});
markers.value = [];
searchResult.value = null;
};
const handleChange=(e)=>{
const item = searchList.value.find(item=>item.id===e)
const obj={
lng:item.location.lng,
lat:item.location.lat,
addres:item.address
}
emit('handleGetLng', obj)
}
</script>
<style scoped>
.map-container {
width: 100%;
height: 500px;
background-color: #eee;
padding: 20px;
border-radius: 10px;
}
#map {
width: 100%;
height: 100%;
border: 1px solid #eee;
}
</style>

View File

@ -106,9 +106,6 @@ const handlePreview = async (file) => {
// handleChange // handleChange
const handleChange = ({ file, fileList: updatedList }) => { const handleChange = ({ file, fileList: updatedList }) => {
console.log(111)
console.log(file.status)
console.log(updatedList)
// //
if (file.status === 'done') { if (file.status === 'done') {
const response = file.response; const response = file.response;
@ -145,7 +142,7 @@ const handleCustomRequest = async (options) => {
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('file', file);
const { data } = await apis.common.uploadImg(formData); const { data } = await apis.common.uploadFile(formData);
const fullUrl = config('http.apiBasic') + data; const fullUrl = config('http.apiBasic') + data;
// //

View File

View File

@ -19,6 +19,8 @@ import UploadImage from './Upload/UploadImage.vue'
import UploadInput from './Upload/UploadInput.vue' import UploadInput from './Upload/UploadInput.vue'
import Scrollbar from './Scrollbar/Scrollbar.vue' import Scrollbar from './Scrollbar/Scrollbar.vue'
import Cascader from './Cascader/Cascader.vue' import Cascader from './Cascader/Cascader.vue'
import GxUpload from './GxUpload/index.vue'
import GxMap from './GxMap/index.vue'
import { setupLoadingDirective } from './Loading/directive' import { setupLoadingDirective } from './Loading/directive'
const componentList = [ const componentList = [
@ -41,6 +43,8 @@ const componentList = [
UploadInput, UploadInput,
Scrollbar, Scrollbar,
Cascader, Cascader,
GxUpload,
GxMap
] ]
export const loading = Loading export const loading = Loading

38
src/enums/enums.js Normal file
View File

@ -0,0 +1,38 @@
export class EnumManager {
constructor(data) {
this.data = data;
this.valueMap = new Map(data.map(item => [item.value, item.name]));
this.nameMap = new Map(data.map(item => [item.name, item.value]));
this.colorMap=new Map(data.map(item=>[item.value,item.color]))
}
// 获取整个数组
getAll() {
return this.data.map(item=>({label:item.name,value:item.value}))
}
// 根据value获取name
getName(value) {
return this.valueMap.get(value) || '';
}
//根据value获取color
getColor(value){
return this.colorMap.get(value)||''
}
// 根据name获取value可选
getValue(name) {
return this.nameMap.get(name) || '';
}
// 获取所有value的数组
getValues() {
return Array.from(this.valueMap.keys());
}
// 获取所有name的数组
getNames() {
return Array.from(this.valueMap.values());
}
}

57
src/enums/index.js Normal file
View File

@ -0,0 +1,57 @@
import {EnumManager} from './enums'
const activatyStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '待开始', color: '#faad14' }, // 黄色(警告色)
{ value: 3, name: '进行中', color: '#52c41a' }, // 绿色(进行中)
{ value: 4, name: '已结束', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
//工单
const orderStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '进行中', color: '#52c41a' }, // 绿色(进行中)
{ value: 3, name: '已完成', color: '#1890ff' }, // 蓝色(完成色)
{ value: 97, name: '已过期', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 98, name: '已撤销', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
//公告状态
const announcementStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '进行中', color: '#52c41a' }, // 绿色(进行中)
{ value:98, name: '停用', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
const enumsStatus = new EnumManager([
{ value: 1, name: '启用', color: '#52c41a' }, // 绿色(启用)
{ value: 2, name: '停用', color: '#ff4d4f' } // 红色(停用)
])
//互助状态
const nbdMutualStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '进行中', color: '#52c41a' }, // 绿色(进行中)
{ value: 3, name: '已完成', color: '#1890ff' }, // 蓝色(完成色)
{ value: 98, name: '已撤销', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
//工单类型状态
const workTypeStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '启用中', color: '#52c41a' }, // 绿色(进行中)
{ value: 98, name: '禁用', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
//会议室类型状态
const mettingStatus = new EnumManager([
{ value: 1, name: '待审核', color: '#faad14' }, // 黄色(警告色)
{ value: 2, name: '启用中', color: '#52c41a' }, // 绿色(进行中)
{ value: 98, name: '禁用', color: '#bfbfbf' }, // 灰色(失效色)
{ value: 99, name: '审核不通过', color: '#ff4d4f' } // 红色(错误色)
])
//用户类型状态
const userStatus = new EnumManager([
{ value: 1, name: '启用', color: '#52c41a' }, // 黄色(警告色)
{ value: 2, name: '禁用', color: '#ff4d4f' } // 红色(错误色)
])
export {activatyStatus,enumsStatus,orderStatus,announcementStatus,nbdMutualStatus,workTypeStatus,mettingStatus,userStatus}

View File

@ -4,3 +4,4 @@ export { default as useMenu } from './useMenu'
export { default as useModal } from './useModal' export { default as useModal } from './useModal'
export { default as useMultiTab } from './useMultiTab' export { default as useMultiTab } from './useMultiTab'
export { default as usePagination } from './usePagination' export { default as usePagination } from './usePagination'
export { default as useSpining } from './useSpining'

15
src/hooks/useSpining.js Normal file
View File

@ -0,0 +1,15 @@
import { ref } from 'vue'
export default () => {
const spining = ref(false) // 直接使用基本类型ref
const showSpining = () => {
spining.value = true
}
const hideSpining = () => {
spining.value = false
}
return {
spining, // 直接暴露ref
showSpining,
hideSpining,
}
}

View File

@ -5,10 +5,8 @@
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
</div> </div>
<div class="aside-body"> <div class="aside-body">
<img <img alt="" :src="assets('logos.png')" />
alt="" <!-- <h3>{{ $t('pages.layouts.userLayout.title') }}</h3> -->
:src="assets('logos.png')" />
<h3>{{ $t('pages.layouts.userLayout.title') }}</h3>
<!-- <p>Vue3 + Ant Design Vue + vite</p>--> <!-- <p>Vue3 + Ant Design Vue + vite</p>-->
</div> </div>
<div class="aside-footer"> <div class="aside-footer">
@ -27,9 +25,7 @@
</div> </div>
</div> </div>
<div <div class="basic-header__right" style="padding: 30px">
class="basic-header__right"
style="padding: 30px">
<a-space :size="16"> <a-space :size="16">
<a-dropdown :trigger="['hover']"> <a-dropdown :trigger="['hover']">
<action-button :style="{ height: '44px' }"> <action-button :style="{ height: '44px' }">
@ -38,10 +34,7 @@
<a-spin /> <a-spin />
<template #overlay> <template #overlay>
<a-menu v-model:selectedKeys="current"> <a-menu v-model:selectedKeys="current">
<a-menu-item <a-menu-item v-for="(item, key) in langData" :key="key" @click="handleLang(key)">
v-for="(item, key) in langData"
:key="key"
@click="handleLang(key)">
{{ item.icon }} {{ item.label }} {{ item.icon }} {{ item.label }}
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>

View File

@ -1,18 +1,11 @@
<template> <template>
<a-layout-header <a-layout-header class="basic-header" :class="cpClassNames" :style="cpStyles">
class="basic-header"
:class="cpClassNames"
:style="cpStyles">
<!-- 左侧 --> <!-- 左侧 -->
<div <div v-if="cpShowLeftSlot" class="basic-header__left">
v-if="cpShowLeftSlot"
class="basic-header__left">
<slot name="left"></slot> <slot name="left"></slot>
</div> </div>
<!-- 中间 --> <!-- 中间 -->
<div <div v-if="cpShowDefaultSlot" class="basic-header__center">
v-if="cpShowDefaultSlot"
class="basic-header__center">
<slot></slot> <slot></slot>
</div> </div>
<!-- 右侧 --> <!-- 右侧 -->
@ -28,10 +21,7 @@
<a-spin /> <a-spin />
<template #overlay> <template #overlay>
<a-menu v-model:selectedKeys="current"> <a-menu v-model:selectedKeys="current">
<a-menu-item <a-menu-item v-for="(item, key) in langData" :key="key" @click="handleLang(key)">
v-for="(item, key) in langData"
:key="key"
@click="handleLang(key)">
{{ item.icon }} {{ item.label }} {{ item.icon }} {{ item.label }}
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
@ -40,9 +30,7 @@
<a-dropdown :trigger="['click']"> <a-dropdown :trigger="['click']">
<action-button :style="{ height: '44px' }"> <action-button :style="{ height: '44px' }">
<a-avatar <a-avatar class="mr-8-1 display-inline-flex justify-content-center" :size="24"
class="mr-8-1 display-inline-flex justify-content-center"
:size="24"
:src="userInfo?.avatar"> :src="userInfo?.avatar">
</a-avatar> </a-avatar>
<span>{{ userInfo?.name }}</span> <span>{{ userInfo?.name }}</span>
@ -50,15 +38,13 @@
<a-spin /> <a-spin />
<template #overlay> <template #overlay>
<a-menu> <a-menu>
<a-menu-item <!-- <a-menu-item
key="edit" key="edit"
@click="handleOpen"> @click="handleOpen">
<edit-outlined /> <edit-outlined />
{{ $t('component.RightContent.profile') }} {{ $t('component.RightContent.profile') }}
</a-menu-item> </a-menu-item> -->
<a-menu-item <a-menu-item key="logout" @click="handleLogout">
key="logout"
@click="handleLogout">
<login-outlined></login-outlined> <login-outlined></login-outlined>
{{ $t('component.RightContent.logout') }} {{ $t('component.RightContent.logout') }}
</a-menu-item> </a-menu-item>
@ -164,9 +150,7 @@ function handleLogout() {
*/ */
function handleOpen() { function handleOpen() {
router.push({ router.push()
name: 'setting',
})
} }
/** /**

View File

@ -1,17 +1,8 @@
<template> <template>
<div <div class="basic-menu" ref="basicMenuRef">
class="basic-menu" <a-menu v-model:selected-keys="selectedKeys" :get-pop-container="() => basicMenuRef"
ref="basicMenuRef"> :inline-collapsed="collapsed" :mode="mode" :open-keys="cpOpenKeys" :theme="theme" :items="items"
<a-menu @openChange="onOpenChange" @click="handleClick"></a-menu>
v-model:selected-keys="selectedKeys"
:get-pop-container="() => basicMenuRef"
:inline-collapsed="collapsed"
:mode="mode"
:open-keys="cpOpenKeys"
:theme="theme"
:items="items"
@openChange="onOpenChange"
@click="handleClick"></a-menu>
</div> </div>
</template> </template>
@ -79,17 +70,30 @@ watch(
h(Badge, { count: item?.meta?.badge || 0 }), h(Badge, { count: item?.meta?.badge || 0 }),
]), ]),
icon: (item) => { icon: (item) => {
const iconName = item?.meta?.icon;
if(!iconName) return
// Iconfont ('icon-')
if (typeof (iconName)==='string') {
const iconfontName = iconName;
return h('span', {
class: 'ceshi',
'aria-hidden': true,
innerHTML: `<i class='iconfont ${iconfontName}' style='font-size:14px'></i>`
});
} else {
const icon = item?.meta?.icon const icon = item?.meta?.icon
if (icon) { if (icon) {
return h(icon) return h(icon)
} }
return '' return ''
}
}, },
children: 'children', children: 'children',
}, },
treeFieldName: 'children', treeFieldName: 'children',
keepOtherFields: true, keepOtherFields: true,
}) })
console.log(items)
}, },
{ immediate: true, deep: true } { immediate: true, deep: true }
) )
@ -173,6 +177,7 @@ function onOpenChange(value) {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
&__name { &__name {
flex: 1; flex: 1;
min-width: 0; min-width: 0;

View File

@ -1,13 +1,6 @@
<template> <template>
<a-layout-sider <a-layout-sider breakpoint="lg" class="basic-side" v-model:collapsed="collapsed" :style="cpStyles"
breakpoint="lg" :collapsible="true" :collapsed-width="config.sideCollapsedWidth" :theme="theme" :width="config.sideWidth">
class="basic-side"
v-model:collapsed="collapsed"
:style="cpStyles"
:collapsible="true"
:collapsed-width="config.sideCollapsedWidth"
:theme="theme"
:width="config.sideWidth">
<template #trigger> <template #trigger>
<div class="basic-side__trigger"> <div class="basic-side__trigger">
<component :is="collapsed ? MenuUnfoldOutlined : MenuFoldOutlined"></component> <component :is="collapsed ? MenuUnfoldOutlined : MenuFoldOutlined"></component>
@ -16,14 +9,10 @@
<div class="basic-side__header"> <div class="basic-side__header">
<slot name="header"></slot> <slot name="header"></slot>
</div> </div>
<x-scrollbar <x-scrollbar v-if="cpShowDefaultSlot" class="basic-side__body">
v-if="cpShowDefaultSlot"
class="basic-side__body">
<slot></slot> <slot></slot>
</x-scrollbar> </x-scrollbar>
<div <div v-if="cpShowFooterSlot" class="basic-side__footer">
v-if="cpShowFooterSlot"
class="basic-side__footer">
<slot name="footer"></slot> <slot name="footer"></slot>
</div> </div>
</a-layout-sider> </a-layout-sider>

View File

@ -32,4 +32,21 @@ export default {
account: '个人页', account: '个人页',
'account.trigger': '触发报错', 'account.trigger': '触发报错',
'account.logout': '退出登录', 'account.logout': '退出登录',
homebanner: '首页轮播图',
neighborhood: '邻里圈轮播图',
announcementList: '社区公告',
activity: '活动列表',
nbdMutualAid: '邻里互助',
nbdMutual: '邻里互助',
mutualComment: '评论列表',
workOrder: '工单管理',
orderList: '工单列表',
orderType: '工单类型',
server:'周边服务',
serverList: '门店列表',
serverType: '门店分类',
mettingMgt:'会议室管理',
mettingRoom:'会议室列表',
mettingYuYue:'预约记录',
customer:'用户管理'
} }

View File

@ -57,7 +57,7 @@ export default {
// role // role
'pages.system.role.add': '添加角色', 'pages.system.role.add': '添加角色',
'pages.system.role.edit': '编辑角色', 'pages.system.role.edit': '编辑角色',
'pages.system.role.delTip': '确定删除该角色吗?', 'pages.system.role.delTip': '确定删除该吗?',
'pages.system.role.form.code': '编码', 'pages.system.role.form.code': '编码',
'pages.system.role.form.code.placeholder': '请输入编码', 'pages.system.role.form.code.placeholder': '请输入编码',
'pages.system.role.form.code.required': '编码是必填项!', 'pages.system.role.form.code.required': '编码是必填项!',
@ -78,7 +78,7 @@ export default {
// user // user
'pages.system.user.add': '添加用户', 'pages.system.user.add': '添加用户',
'pages.system.user.edit': '编辑用户', 'pages.system.user.edit': '编辑用户',
'pages.system.user.delTip': '确定删除该用户吗?', 'pages.system.user.delTip': '确定删除该吗?',
'pages.system.user.form.username': '用户名', 'pages.system.user.form.username': '用户名',
'pages.system.user.form.username.placeholder': '请输入用户名', 'pages.system.user.form.username.placeholder': '请输入用户名',
'pages.system.user.form.username.required': '用户名是必填项!', 'pages.system.user.form.username.required': '用户名是必填项!',

View File

@ -1,8 +1,10 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import App from '@/App.vue' import App from '@/App.vue'
import { useCore } from '@/core'
import { useCore } from '@/core'
import './assets/iconfont/iconfont.css';
const app = createApp(App) const app = createApp(App)
useCore(app) useCore(app)
app.mount('#app') app.mount('#app')

View File

@ -1,11 +1,10 @@
import Mock from 'mockjs' // src/mock/index.js
import userMocks from './modules/user';
import './modules/common.js' export default [
import './modules/system.js' ...userMocks
import './modules/user.js' ];
// export const setupMock = () => {
export const setupMock = () => { // Mock.setup({
Mock.setup({ // timeout: 200,
timeout: 200, // })
}) // }
}

View File

@ -1,124 +0,0 @@
import Mock from 'mockjs'
import { builder, getQueryParams } from '../util'
// 获取欢迎页数据
Mock.mock(new RegExp('/home/getData'), 'get', () => {
return builder(
Mock.mock({
'dynamicRows|5': [
{
id: '@increment',
avatar: '@image(32, @color, @cfirst)',
title: '@cparagraph(1, 2)',
time: '@datetime',
},
],
})
)
})
// 获取分页列表
Mock.mock(new RegExp('/common/getPageList'), 'get', () => {
return builder(
Mock.mock({
'rows|10': [
{
id: '@increment',
avatar: '@image(60, @color)',
userName: '@cname',
'userList|2-4': [
{
id: '@increment',
avatar: '@image(60, @color)',
},
],
title: '@ctitle',
name: '@ctitle',
desc: '@cparagraph(3)',
desc1: '@cparagraph(1)',
'valid|1': true,
keyValue: '@word',
content: '@cparagraph(3)',
'tags|2-3': ['@cword(3,5)'],
url: '@url("https")',
time: '@date(yyyy-MM-dd HH:mm)',
time1: '@date(MM-dd)',
star: '@integer(20, 200)',
like: '@integer(20, 200)',
comment: '@integer(20, 200)',
cover: '@image(532x320)',
activeUsers: '@integer(10, 99)',
newUsers: '@integer(1000, 5000)',
count: '@integer(1, 100)',
'status|1': ['成功', '失败'],
},
],
total: 32,
})
)
})
// 保存/删除
Mock.mock(new RegExp(/(save|delete)/), 'post', () => {
return builder(
Mock.mock({
result: true,
})
)
})
// 文件上传
Mock.mock(new RegExp('/comment/upload'), 'post', () => {
return builder(
Mock.mock({
src: '@image(80, @color)',
})
)
})
// 获取地区列表
Mock.mock(new RegExp('/common/getRegionList'), 'get', (options) => {
const { parentId = 0 } = getQueryParams(options)
const list = {
0: [
{ id: 1, name: '北京' },
{ id: 2, name: '山东省' },
],
1: [{ id: 11, name: '北京市' }],
2: [
{ id: 21, name: '济南市' },
{ id: 22, name: '菏泽市' },
{ id: 23, name: '青岛市' },
],
11: [
{ id: 111, name: '东城区' },
{ id: 112, name: '西城区' },
{ id: 113, name: '海淀区' },
{ id: 114, name: '昌平区' },
{ id: 114, name: '朝阳区' },
],
21: [
{ id: 211, name: '历下区' },
{ id: 212, name: '市中区' },
{ id: 213, name: '槐荫区' },
],
22: [
{ id: 221, name: '牡丹区' },
{ id: 222, name: '定陶区' },
{ id: 223, name: '郓城县' },
],
23: [
{ id: 231, name: '市南区' },
{ id: 232, name: '市北区' },
{ id: 233, name: '黄岛区' },
],
}
return builder(
Mock.mock({
rows: list[parentId],
})
)
})

View File

@ -1,391 +0,0 @@
import Mock from 'mockjs'
import { builder } from '../util'
// 获取角色列表
Mock.mock(new RegExp('/system/getUserRoleList'), 'get', () => {
return builder(
Mock.mock({
rows: [
{
name: '超级管理员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '管理员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
children: [
{
name: '系统管理员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '业务管理员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '数据管理员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
],
},
{
name: '操作员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
children: [
{
name: '公告维护员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '审核员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '复审员',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
],
},
],
})
)
})
// 获取用户分页列表
Mock.mock(new RegExp('/system/getUserPageList'), 'get', () => {
return builder(
Mock.mock({
'rows|10': [
{
id: '@id',
avatar: '@image(60x60, @color, @cfirst)',
userName: '@email',
name: '@cname',
'roleName|+1': ['超级管理员', '业务管理员', '数据管理员'],
date: '@date',
},
],
total: 40,
})
)
})
// 获取菜单列表
Mock.mock(new RegExp('/system/getMenuList'), 'get', () => {
return builder(
Mock.mock({
rows: [
{
name: '欢迎页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
},
{
name: '表单页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '基础表单',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '新增',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '编辑',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '删除',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
],
},
{
name: '分步表单',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '新增',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '编辑',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '删除',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
],
},
],
},
{
name: '列表页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '基础列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '新增',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '编辑',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '删除',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
],
},
{
name: '卡片列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '新增',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '编辑',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '删除',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
],
},
{
name: '搜索列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'menu',
children: [
{
name: '新增',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '编辑',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
{
name: '删除',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
type: 'button',
},
],
},
],
},
],
})
)
})
// 获取菜单列表
Mock.mock(new RegExp('/system/getNewMenuList'), 'get', () => {
return builder(
Mock.mock({
rows: [
{
name: '欢迎页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '表单页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
children: [
{
name: '基础表单',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '分步表单',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
],
},
{
name: '列表页',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
children: [
{
name: '基础列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '卡片列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
{
name: '搜索列表',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
},
],
},
],
})
)
})
// 获取字典分类列表
Mock.mock(new RegExp('/system/getDictTypeList'), 'get', () => {
return builder(
Mock.mock({
rows: [
{
name: '通知类型',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
},
{
name: '性别',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
},
{
name: '菜单类型',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
},
{
name: '用户类型',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
children: [
{
name: '移动端',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
},
{
name: '桌面端',
alias: '@word(2,4)',
sort: '@increment',
key: '@id',
code: '@word',
},
],
},
],
})
)
})

View File

@ -1,22 +1,37 @@
import Mock from 'mockjs' // src/mock/user.js
export default [
import { builder, getBody } from '../util' // GET 示例
{
// 登录 url: '/api/user',
Mock.mock(new RegExp('/user/login'), 'post', (options) => { method: 'get',
const { username, password } = getBody(options) response: () => ({
code: 0,
if ('admin' === username && '123456' === password) { data: {
return builder( 'list|5-10': [{
Mock.mock({ 'id|+1': 1,
id: '@increment', name: '@cname',
username: username, avatar: '@image("100x100")'
avatar: '@dataImage', }]
token: '@guid',
email: '@email',
})
)
} else {
return builder({}, '301', '用户名或密码错误')
} }
}) })
},
// POST 示例
{
url: '/api/login',
method: 'post',
timeout: 1000, // 模拟延迟
response: ({ body }) => {
if (body.username === 'admin' && body.password === '123456') {
return {
code: 0,
token: 'mock_token_123456'
}
}
return {
code: 401,
message: '认证失败'
}
}
}
]

View File

@ -1,57 +0,0 @@
/**
* 基础数据结构
* @type {{msg: string, code: string, data: null, timestamp: number}}
*/
const responseBody = {
code: 200,
msg: 'success',
timestamp: 0,
data: null,
}
/**
* 构建返回的数据结构
* @param data
* @param code
* @param message
* @returns {{msg: string, code: string, data: null, timestamp: number}}
*/
export const builder = (data = {}, code = 200, message = 'success') => {
responseBody.data = data
if (code !== undefined && code !== 0) {
responseBody.code = code
}
if (message !== undefined && message !== null) {
responseBody.msg = message
}
responseBody.timestamp = new Date().getTime()
return responseBody
}
/**
* 获取地址栏参数
* @param options
* @returns {{}|any}
*/
export const getQueryParams = (options) => {
const url = options.url
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' + decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}'
)
}
/**
* 获取body参数
* @param options
* @returns {*}
*/
export const getBody = (options) => {
return options.body && JSON.parse(options.body)
}

View File

@ -9,7 +9,7 @@ import system from './system'
import link from './link' import link from './link'
import iframe from './iframe' import iframe from './iframe'
import other from './other' import other from './other'
import pages from './pages'
export default [ export default [
...home, ...home,
...form, ...form,
@ -22,4 +22,5 @@ export default [
...link, ...link,
...iframe, ...iframe,
...other, ...other,
...pages
] ]

216
src/router/routes/pages.js Normal file
View File

@ -0,0 +1,216 @@
import { TableOutlined, HomeOutlined } from '@ant-design/icons-vue'
export default [
{
path: 'homebanner/index',
name: 'homebanner',
component: 'pages/homeBanner/index.vue',
meta: {
icon: HomeOutlined,
title: '首页轮播图',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'neighborhood/index',
name: 'neighborhood',
component: 'pages/neighborhood/index.vue',
meta: {
icon: TableOutlined,
title: '邻里圈轮播图',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'announcementList/index',
name: 'announcementList',
component: 'pages/announcementList/index.vue',
meta: {
icon: 'icon-gonggao',
title: '社区公告',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'activity/index',
name: 'activity',
component: 'pages/activity/index.vue',
meta: {
icon: 'icon-huodongliebiao-copy',
title: '热门活动',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'nbdMutual',
name: 'nbdMutual',
component: 'RouteViewLayout',
meta: {
icon: 'icon-cooperation',
title: '邻里互助',
isMenu: true,
keepAlive: true,
permission: '*',
},
children: [
{
path: 'nbdMutual/nbdMutualAid',
name: 'nbdMutualAid',
component: 'pages/nbdMutual/nbdMutualAid/index.vue',
meta: {
icon: '',
title: '邻里互助',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
// {
// path: 'nbdMutual/mutualComment',
// name: 'mutualComment',
// component: 'pages/nbdMutual/mutualComment/index.vue',
// meta: {
// icon: 'icon-huodongliebiao-copy',
// title: '求助评论',
// isMenu: true,
// keepAlive: true,
// permission: '*',
// },
// },
],
},
{
path: 'workOrder',
name: 'workOrder',
component: 'RouteViewLayout',
meta: {
icon: 'icon-gongdan',
title: '工单列表',
isMenu: true,
keepAlive: true,
permission: '*',
},
children: [
{
path: 'workOrder/orderType',
name: 'orderType',
component: 'pages/workOrder/orderType/index.vue',
meta: {
icon: '',
title: '功能类型',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'workOrder/orderList',
name: 'orderList',
component: 'pages/workOrder/orderList/index.vue',
meta: {
icon: '',
title: '工单列表',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
],
},
{
path: 'server',
name: 'server',
component: 'RouteViewLayout',
meta: {
icon: 'icon-zhoubian',
title: '周边服务',
isMenu: true,
keepAlive: true,
permission: '*',
},
children: [
{
path: 'server/serverType',
name: 'serverType',
component: 'pages/server/serverType/index.vue',
meta: {
icon: '',
title: '门店类型',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'server/serverList',
name: 'serverList',
component: 'pages/server/serverList/index.vue',
meta: {
icon: '',
title: '门店列表',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
],
},
{
path: 'mettingMgt',
name: 'mettingMgt',
component: 'RouteViewLayout',
meta: {
icon: 'icon-zhoubian',
title: '会议室管理',
isMenu: true,
keepAlive: true,
permission: '*',
},
children: [
{
path: 'mettingMgt/mettingRoom',
name: 'mettingRoom',
component: 'pages/mettingMgt/mettingList/index.vue',
meta: {
icon: '',
title: '会议室',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
{
path: 'mettingMgt/mettingYuYue',
name: 'mettingYuYue',
component: 'pages/mettingMgt/mettingYuYue/index.vue',
meta: {
icon: '',
title: '会议室预约',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
],
},
{
path: 'customer/index',
name: 'customer',
component: 'pages/user/index.vue',
meta: {
icon: HomeOutlined,
title: '用户管理',
isMenu: true,
keepAlive: true,
permission: '*',
},
},
]

View File

@ -2,17 +2,10 @@
<div> <div>
<a-tabs> <a-tabs>
<!-- 账号登录 --> <!-- 账号登录 -->
<a-tab-pane <a-tab-pane key="account" :tab="$t('pages.login.accountLogin.tab')">
key="account" <a-form :model="formData" :rules="formRules" ref="formRef">
:tab="$t('pages.login.accountLogin.tab')">
<a-form
:model="formData"
:rules="formRules"
ref="formRef">
<a-form-item name="username"> <a-form-item name="username">
<a-input <a-input :placeholder="$t('pages.login.username.placeholder')" v-model:value="formData.username"
:placeholder="$t('pages.login.username.placeholder')"
v-model:value="formData.username"
size="large"> size="large">
<template #prefix> <template #prefix>
<user-outlined></user-outlined> <user-outlined></user-outlined>
@ -20,45 +13,28 @@
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item name="password"> <a-form-item name="password">
<a-input <a-input v-model:value="formData.password" size="large" type="password"
v-model:value="formData.password" :placeholder="$t('pages.login.password.placeholder')" @pressEnter="handleLogin">
size="large"
type="password"
:placeholder="$t('pages.login.password.placeholder')"
@pressEnter="handleLogin">
<template #prefix> <template #prefix>
<lock-outlined></lock-outlined> <lock-outlined></lock-outlined>
</template> </template>
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item name="captcha_code"> <!-- <a-form-item name="captcha_code">
<a-space> <a-space>
<a-input <a-input v-model:value="formData.captcha_code" size="large" type="text"
v-model:value="formData.captcha_code" :placeholder="$t('pages.login.captcha.placeholder')" @pressEnter="handleLogin">
size="large"
type="text"
:placeholder="$t('pages.login.captcha.placeholder')"
@pressEnter="handleLogin">
<template #prefix> <template #prefix>
<safety-outlined /> <safety-outlined />
</template> </template>
</a-input> </a-input>
<a-image <a-image @click="getCaptcha" :preview="false" :width="140" :height="42"
@click="getCaptcha"
:preview="false"
:width="140"
:height="42"
:src="captcha_img" /> :src="captcha_img" />
</a-space> </a-space>
</a-form-item> </a-form-item> -->
<a-form-item> <a-form-item>
<a-button <a-button type="primary" size="large" block :loading="loading" @click="handleLogin">{{
type="primary" $t('pages.login.submit') }}
size="large"
block
:loading="loading"
@click="handleLogin"
>{{ $t('pages.login.submit') }}
</a-button> </a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
@ -125,7 +101,6 @@ async function handleLogin() {
formRef.value.validate().then(async (values) => { formRef.value.validate().then(async (values) => {
values.captcha_id = captcha_id.value values.captcha_id = captcha_id.value
if (values.password === 'abc-123') values.password = md5(values.password) if (values.password === 'abc-123') values.password = md5(values.password)
loading.value = true loading.value = true
const { success } = await userStore const { success } = await userStore
.login({ .login({

View File

@ -0,0 +1,198 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel" :ok-button-props="{ disabled: formData.status!==2 }">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'活动标题'" name="title">
<a-input :placeholder="'请输入活动标题'" v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'活动内容'" name="content">
<x-editor v-model="formData.content"></x-editor>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'活动时间'" name="openAt">
<a-input v-model:value="formData.openAt" placeholder="请输入活动时间" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status" :options="activatyStatus.getAll()" disabled></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :label="'活动图片'" name="cover">
<gx-upload v-model="formData.cover" accept-types=".jpg,.png,.webp"
:fileNumber="1" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :label="'背景图片'" name="images">
<gx-upload v-model="formData.images" accept-types=".jpg,.png,.webp"
:fileNumber="1" />
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import GxUpload from '@/components/GxUpload/index.vue'
import { spliceUrl } from "@/utils/util"
import { activatyStatus } from '@/enums/index'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const fileList = ref([])
formRules.value = {
title: [{ required: true, message: '请输入活动名称' }],
openAt: [{ required: true, message: '请输入活动时间' }],
cover: [{required: false, message: '请上传图片', trigger: 'change'}],
images: [{ required: false, message: '请上传图片', trigger: 'change' }],
activityContent:[{ required: true, message: '请输入活动内容' }]
}
onBeforeMount(() => {
})
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '新增活动',
})
// initData()
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑活动',
})
try {
showSpining()
const { data, success } = await apis.activity.getItem(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
if (data.images && data.images.length > 0) {
formData.value.images = data.images.map(item => config('http.apiBasic') + item)
}else{
formData.value.images=[]
}
if(data.cover){
formData.value.cover=[config('http.apiBasic')+data.cover]
}else{
formData.value.cover=[]
}
} catch (error) {
message.error({ content: error.message })
hideSpining()
}
}
const uploadSuccess = (data) => {
fileList.value.push(data)
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
cover: formData.value.cover?spliceUrl(formData.value.cover[0]):'',
images: formData.value.images ? formData.value.images.map(item => spliceUrl(item)) : []
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.activity.createProject(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.activity.updateItem(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
formData.value.areaId = 1
hideModal()
}
const onRangeChange = (value, dateString) => {
console.log('value', value)
console.log('Formatted Selected Time: ', dateString);
formData.value.startAt = dayjs(dateString[0])
formData.value.endAt = dayjs(dateString[1])
console.log(formData.value)
};
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,290 @@
<template>
<!-- <x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="姓名" name="name">
<a-input placeholder="请输入姓名" v-model:value="searchFormData.name"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="状态" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option value="">全部</a-select-option>
<a-select-option value="enabled">启用</a-select-option>
<a-select-option value="disabled">停用</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar> -->
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增活动
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'cover'">
<a-image :width="60"
:src="record.cover ? config('http.apiBasic') + record.cover : errImg" />
</template>
<template v-if="column.dataIndex === 'content'">
<span style="cursor: pointer;color:#1677ff;"
@click="content = record.content || ''; type = 2; open = true" type="link">点击查看</span>
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="activatyStatus.getColor(record.status)">{{
activatyStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record)" v-if="record.status === 1">
<a-tooltip>
<template #title> {{ '审核' }}</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="startHandleEdit(record)" v-if="record.status === 2">
<a-tooltip>
<template #title> {{ '开始活动' }}</template>
<i class='iconfont icon-kaishi-yuan' style='font-size:14px;color:#52c41a'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title> {{ $t('pages.system.user.edit') }}</template>
<edit-outlined />
</a-tooltip>
</x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>{{ $t('pages.system.delete') }}</template>
<delete-outlined style="color: #ff4d4f" />
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal v-model:open="open" :title="type === 1 ? '活动图片' : '活动详情'" @ok="open = false">
<a-card class="mb-8-2">
<template v-if="type === 1">
<a-image v-if="imgList.length > 0" :width="200" v-for="item of imgList"
:src="config('http.apiBasic') + item" />
<span v-else>
暂无图片
</span>
</template>
<template v-else>
<p v-html="content"></p>
</template>
</a-card>
</a-modal>
<a-modal :open="modal.open" :title="'审核'" :width="640" :confirm-loading="modal.confirmLoading" title="审核"
ok-text="确认" cancel-text="取消" @ok="handleAuditEdit" @cancel="hideModal()">
<a-card class="mb-8-2">
<a-form-item :label="'审核'" name="">
<a-radio-group v-model:value="auditStatus"
:options="[{ value: 2, label: '通过' }, { value: 99, label: '不通过' }]"></a-radio-group>
</a-form-item>
<a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { formatUtcDateTime } from '@/utils/util'
import { config } from '@/config'
import dayjs from 'dayjs'
import { usePagination,useModal } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined, QrcodeOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { activatyStatus } from '@/enums/index.js'
import errImg from '@/assets/blankSpace.png'
defineOptions({
name: 'activity',
})
const { t } = useI18n() // t
const open = ref(false)
const imgList = ref([])
const type = ref(1)
const columns = [
{ title: '活动封面', dataIndex: 'cover', align: 'center', width: 100 },
{ title: '活动标题', dataIndex: 'title' },
{ title: '活动时间', dataIndex: 'openAt', align: 'center' },
{ title: '活动内容', dataIndex: 'content', align: 'center', width: 100 },
{ title: '状态', dataIndex: 'status', align: 'center', width: 100 },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 140, align: 'center' },
]
const { modal, showModal, hideModal, showLoading:auditShowLoading, hideLoading:auditHideLoading } = useModal()
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } =usePagination()
const editDialogRef = ref()
const currentForm=ref({})
const auditStatus=ref(2)
const remark=ref('')
getPageList()
/**
* 获取表格数据
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.activity
.getProjectList({
pageSize,
current: current,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (params) => {
currentForm.value = params
showModal()
}
const startHandleEdit=async (obj)=>{
try {
const params = {
...obj,
status: 3,
}
const result = await apis.activity.updateItem(obj.id, params).catch(() => {
throw new Error()
})
if (config('http.code.success') === result?.success) {
hideModal()
getPageList()
message.success('活动已成功')
}
} catch (error) {
message.error(error.message)
}
}
const handleAuditEdit = async () => {
try {
auditShowLoading()
const params = {
...currentForm.value,
status: auditStatus.value,
remark: remark.value
}
console.log(params);
const result = await apis.activity.updateItem(currentForm.value.id, params).catch(() => {
throw new Error()
})
auditHideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
getPageList()
message.success('审核成功')
}
} catch (error) {
message.error(error.message)
auditHideLoading()
}
}
/**
* 删除
*/
function handleDelete({ id }) {
Modal.confirm({
title: t('pages.system.user.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.activity.delItem(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,211 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel" :ok-button-props="{ disabled: formData.status!==1 }">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules" :label-col="{ style: { width: '90px' } }">
<a-card class="mb-8-2">
<a-row :gutter="24">
<a-col :span="24">
<a-form-item label="公告标题" name="title">
<a-input placeholder="请输入标题" v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="创建时间" name="createdAt">
<a-date-picker v-model:value="formData.createdAt" placeholder="请选择发布时间"
style="width: 100%;" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="排序" name="sequence">
<a-input-number v-model:value="formData.sequence" style="width: 100%;" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status" :options="announcementStatus.getAll()" disabled></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'公告简介'" name="desc">
<a-textarea v-model:value="formData.desc" ></a-textarea>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'公告内容'" name="content">
<x-editor v-model="formData.content" :uploadHandler="uploadHandler" :height="350"></x-editor>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'公告封面'" name="cover">
<gx-upload v-model="formData.cover" :fileNumber="1"></gx-upload>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import { announcementStatus } from '@/enums/index'
import {spliceUrl} from '@/utils/util'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const rolesValue = ref([])
const roles = ref([])
const { spining, showSpining, hideSpining } = useSpining()
formRules.value = {
title: { required: true, message: '请输入标题' },
desc: { required: true, message: '请输入简介' },
content: { required: true, message: '请输入内容' },
sequence: { required: true, message: '请选择排序' },
status: { required: true, message: '请选择是否启用' },
createdAt: { required: true, message: '请选择创建时间' },
cover:{required: false, message: '请上传封面'}
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '新增',
})
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
try {
showModal({ type: 'edit', title: '修改公告信息' })
showSpining()
const { data, success } = await apis.announcement.getNotices(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
formData.value.createdAt = dayjs(data.createdAt)
formData.value.cover=formData.value.cover?[config('http.apiBasic')+formData.value.cover]:[]
} catch (error) {
message.error(error.message)
}
}
/**
* 确定
*/
function handleOk() {
formRef.value
.validateFields()
.then(async (values) => {
console.log(2222)
try {
showLoading()
const params = {
...values,
cover:formData.value.cover?spliceUrl(formData.value.cover[0]):''
}
console.log(params);
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.announcement.createNotices(params).catch(() => {
throw new Error()
})
break
case 'edit':
result = await apis.announcement.updateNotices(formData.value.id, params).catch(() => {
throw new Error()
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
message.success(modal.value.type === 'create' ? '创建成功' : '更新成功')
}
} catch (error) {
hideLoading()
}
})
.catch(() => {
hideLoading()
})
}
/**
* 对权限组 过数据格式
*/
function formatArr(data, type = '') {
const rolesArr = []
data.forEach((item) => {
roles.value.forEach((r) => {
if (type === 'edit') {
if (item.role_id === r.value) {
rolesArr.push({
value: item.role_id,
label: r.label,
})
return
}
} else if (r.value === item) {
rolesArr.push({
role_id: item,
role_name: r.label,
})
return
}
})
})
return rolesArr
}
const uploadHandler = async (file) => {
const formData = new FormData();
formData.append('file', file);
const { data } = await apis.common.uploadImg(formData);
return config('http.apiBasic') + data
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,251 @@
<template>
<x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="标题" name="title">
<a-input placeholder="请输入标题" v-model:value="searchFormData.title"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item :label="'状态'" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option v-for="item of announcementStatus.getAll()" :value="item.value">{{
item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button v-action="'add'" type="primary" @click="$refs.addDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" :loading="loading" bordered="true"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'cover'">
<a-image :width="60"
:src="record.cover ? config('http.apiBasic') + record.cover : errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="announcementStatus.getColor(record.status)">{{
announcementStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'createdAt' === column.dataIndex">
{{ dayjs(record.createdAt).format('YYYY-MM-DD') }}
</template>
<template v-if="'desc' === column.dataIndex">
<p v-html="record.desc"></p>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record)" v-if="record.status === 1">
<a-tooltip>
<template #title> {{ '审核' }}</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="$refs.addDialogRef.handleEdit(record)">
<a-tooltip>
<template #title> {{ '编辑公告' }}</template>
<edit-outlined />
</a-tooltip>
</x-action-button>
<x-action-button @click="handleRemove(record)">
<a-tooltip>
<template #title> {{ '删除公告' }}</template>
<delete-outlined style="color: #ff4d4f" />
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal :open="modal.open" :title="'审核'" :width="640" :confirm-loading="modal.confirmLoading" title="审核"
ok-text="确认" cancel-text="取消" @ok="handleAuditEdit" @cancel="hideModal()">
<a-card class="mb-8-2">
<a-form-item :label="'审核'" name="">
<a-radio-group v-model:value="auditStatus"
:options="[{ value: 2, label: '通过' }, { value: 99, label: '不通过' }]"></a-radio-group>
</a-form-item>
<a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<add-dialog ref="addDialogRef" @ok="onOk"></add-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { announcementStatus } from '@/enums/index.js'
import { usePagination,useModal } from '@/hooks'
import AddDialog from './components/AddDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import errImg from '@/assets/blankSpace.png'
defineOptions({
name: 'systemRole',
})
const { t } = useI18n() // t
const columns = [
{ title: '封面', dataIndex: 'cover', key: 'cover', with: 60, align: 'center' },
{ title: '标题', dataIndex: 'title', key: 'title', ellipsis: true },
{ title: '简介', dataIndex: 'desc', ellipsis: true },
{ title: '排序', dataIndex: 'sequence', width: 80, align: 'center' },
{ title: '状态', key: 'status', dataIndex: 'status', width: 120, align: 'center' },
{ title: '创建时间', dataIndex: 'createdAt', width: 200, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 140, align: 'center' },
]
const { modal, showModal, hideModal, showLoading:auditShowLoading, hideLoading:auditHideLoading } = useModal()
const { listData, loading, showLoading, hideLoading, paginationState, searchFormData, resetPagination } = usePagination()
// const { resetForm } = useForm()
const addDialogRef = ref()
const currentForm=ref({})
const auditStatus=ref(2)
const remark=ref('')
getPageList()
/**
* 获取公公告列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.announcement
.getNoticesList({
pageSize,
current: current,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 移除
*/
function handleRemove({ id }) {
Modal.confirm({
title: t('pages.system.role.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.announcement.delNotices(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
const auditHandleEdit = (params) => {
currentForm.value = params
showModal()
}
const handleAuditEdit = async () => {
try {
auditShowLoading()
const params = {
...currentForm.value,
status: auditStatus.value,
remark: remark.value
}
console.log(params);
const result = await apis.announcement.updateNotices(currentForm.value.id, params).catch(() => {
throw new Error()
})
auditHideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
getPageList()
message.success('审核成功')
}
} catch (error) {
message.error(error.message)
auditHideLoading()
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,191 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'名称'" name="title">
<a-input :placeholder="'请输入名称'" v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'顺序'" name="sequence">
<a-input-number :placeholder="'请输入顺序'" v-model:value="formData.sequence" style="width: 100%;"></a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status" :options="enumsStatus.getAll()"></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'图片'" name="img">
<gx-upload v-model="formData.img" :fileNumber="1" />
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import { createMenu, getMenu, updateMenu } from '@/apis/modules/imgmgt'
import {spliceUrl} from '@/utils/util'
import { enumsStatus } from '@/enums/index.js'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const rolesValue = ref([])
const roles = ref([])
const img = ref('')
formRules.value = {
title: { required: true, message: '请输入名称' },
status: [{ required: true, message: '请选择状态', trigger: 'change' }],
sequence: [{ required: true, message: '请选择顺序', trigger: 'change' }],
img: [{ required: true, message: '请上传图片', trigger: 'change' }],
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
// 80about
title: '添加',
})
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: t('pages.system.user.edit'),
})
showSpining()
const { data, success } = await apis.imgmgt.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
formData.value.img=[config('http.apiBasic')+data.img]
}
/**
* 确定
*/
function handleOk() {
if (!formData.value.img) return message.error('请上传图片');
formRef.value.validateFields().then(async (values) => {
console.log(values)
try {
showLoading()
const params = {
...values,
img: spliceUrl(formData.value?.img[0]),
scene: 1 ,
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.imgmgt.createMenu(params).catch(() => {
throw new Error()
})
break
case 'edit':
// result = await apis.imgmgt.updateMenu(formData.value.id, params).catch(() => {
result = await apis.imgmgt.updateMenu(formData.value.id, params).catch(() => {
throw new Error()
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
console.log(error)
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 对权限组 过数据格式
*/
function formatArr(data, type = '') {
const rolesArr = []
data.forEach((item) => {
roles.value.forEach((r) => {
if (type === 'edit') {
if (item.role_id === r.value) {
rolesArr.push({
value: item.role_id,
label: r.label,
})
return
}
} else if (r.value === item) {
rolesArr.push({
role_id: item,
role_name: r.label,
})
return
}
})
})
return rolesArr
}
/**
* 取消
*/
function handleCancel() {
img.value = ''
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,193 @@
<template>
<!-- <x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :label-col="{ style: { width: '40px' } }" :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="名称" name="name">
<a-input placeholder="请输入图片名称" v-model:value="searchFormData.name"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="状态" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option v-for="item of enumsStatus.getAll()" :value="item.value">{{ item.label
}}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar> -->
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'img' === column.dataIndex">
<a-image :width="60" :src="record.img ? config('http.apiBasic') + record.img : errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="enumsStatus.getColor(record.status)">{{ enumsStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title> {{ $t('pages.system.user.edit') }}</template>
<edit-outlined /> </a-tooltip></x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>{{ $t('pages.system.delete') }}</template>
<delete-outlined style="color: #ff4d4f" /> </a-tooltip></x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { formatUtcDateTime } from '@/utils/util'
import { config } from '@/config'
import { statusUserTypeEnum } from '@/enums/system'
import { usePagination } from '@/hooks'
import errImg from '@/assets/blankSpace.png'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { delMenu, getDataList } from '@/apis/modules/imgmgt'
import { enumsStatus } from '@/enums/index.js'
defineOptions({
name: 'homeBanner',
})
const { t } = useI18n() // t
const columns = [
{ title: '图片', dataIndex: 'img', width: 100, align: 'center' },
{ title: '名称', dataIndex: 'title', key: 'name' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: '顺序', dataIndex: 'sequence', width: 100, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.imgmgt
.getDataList({
pageSize,
current: current,
scene: 1,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
//type80about
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 删除
*/
function handleDelete({ id }) {
Modal.confirm({
title: t('pages.system.user.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.imgmgt.delMenu(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,174 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'会议室名称'" name="title">
<a-input :placeholder="'请输入会议室名称'" v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'会议室人数'" name="maxNum">
<a-input-number :placeholder="'请输入排序'" v-model:value="formData.maxNum"
style="width: 100%;">
<template #addonAfter>
人间
</template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'会议室描述'" name="content">
<x-editor v-model="formData.content"></x-editor>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'会议室图片'" name="imgs">
<gx-upload v-model="formData.imgs" accept-types=".jpg,.png,.webp" :fileNumber="10" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status" :options="mettingStatus.getAll()"
disabled></a-radio-group>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { mettingStatus } from '@/enums/index.js'
import { spliceUrl } from '@/utils/util'
import { status } from 'nprogress'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const treeData = ref([])
formRules.value = {
title: { required: true, message: '请输入会议室名称' },
maxNum: { required: true, message: '请输入人数' },
content: { required: true, message: '请输入会议室描述' },
status: { required: true, message: '请选择状态', trigger: 'change' },
imgs: { required: true, message: '请选择状态', trigger: 'change' }
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '新增',
})
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑',
})
try {
showSpining()
const { data, success } = await apis.mettingRoom.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
formData.value.imgs=data.imgs.length>0?data.imgs.map(item=>config('http.apiBasic')+item):[]
} catch (error) {
message.error({ content: error.message })
hideSpining()
}
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
status:1,
imgs:formData.value.imgs.length>0?formData.value.imgs.map(item=>spliceUrl(item)):[]
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.mettingRoom.createMenu(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.mettingRoom.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,182 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增会议室
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'status' === column.dataIndex">
<a-tag :color="workTypeStatus.getColor(record.status)">{{
workTypeStatus.getName(record.status) }}</a-tag>
</template>
<template v-if="'content'===column.dataIndex">
<a-button type="link" @click="content=record.content;contentView=true">点击查看</a-button>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)" >
<a-tooltip>
<template #title>编辑</template>
<edit-outlined />
</a-tooltip>
</x-action-button>
<x-action-button @click="auditHandleEdit(record)" v-if="record.status === 1">
<a-tooltip>
<template #title>审核</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal :open="open" :title="'审核'" :width="640" title="审核" ok-text="确认" cancel-text="取消" @ok="handleAuditEdit"
@cancel="open = false">
<a-card class="mb-8-2">
<a-form-item :label="'审核'" name="">
<a-radio-group v-model:value="auditStatus"
:options="[{ value: 2, label: '通过' }, { value: 99, label: '不通过' }]"></a-radio-group>
</a-form-item>
<a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<a-modal :open="contentView" :title="'描述'" :width="640" ok-text="确认" cancel-text="取消" @ok="contentView=false"
@cancel="contentView = false">
<a-card class="mb-8-2">
<p v-html="content"></p>
</a-card>
</a-modal>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { workTypeStatus } from '@/enums/index.js'
defineOptions({
name: 'mettingRoom',
})
const currentForm = ref({})
const open = ref(false)
const auditStatus = ref(2)
const remark = ref('')
const { t } = useI18n() // t
const content=ref('')
const contentView=ref(false)
const columns = [
{ title: '会议室名称', dataIndex: 'title' },
{ title: '会议室描述', dataIndex: 'content',align:'center' },
{ title: '会议室人数', dataIndex: 'maxNum' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } =
usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.mettingRoom
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (params) => {
currentForm.value = params
open.value = true
}
/**
* 删除
*/
const handleAuditEdit = async () => {
try {
const params = {
...currentForm.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.mettingRoom.updateMenu(currentForm.value.id, params).catch(() => {
throw new Error()
})
if (config('http.code.success') === result?.success) {
getPageList()
open.value = false
message.success('审核成功')
}
} catch (error) {
message.error(error.message)
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,163 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'用户名'" name="customerName">
<a-input :placeholder="'请输入用户名'" v-model:value="formData.customerName"
></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工单分类'" name="label">
<a-input :placeholder="'请输入工单分类'" v-model:value="formData.label" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工单内容'" name="content">
<a-textarea :placeholder="'请输入工单内容'" v-model:value="formData.content"
:auto-size="{ minRows: 2, maxRows: 5 }" ></a-textarea>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工作地点'" name="address">
<a-input :placeholder="'请输入工作地点'" v-model:value="formData.address" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'创建时间'" name="createAt">
<a-input :placeholder="'请输入创建时间'" v-model:value="formData.createAt" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'上门时间'" name="startAt">
<a-input :placeholder="'请输入上门时间'" v-model:value="formData.startAt" ></a-input>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { spliceUrl } from '@/utils/util'
import { readonly } from 'vue'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const treeData = ref([])
const status=ref(2)
const remark=ref('')
formRules.value = {
label: { required: true, message: '请输入产品类别名称' },
sequence: { required: true, message: '请输入排序' }
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '产品分类',
})
//
initData()
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑分类',
})
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
status:status.value,
remark:status.remark
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.orderList.createProductsItem(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.orderList.updateItem(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,182 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'startAt' === column.dataIndex">
<span>{{ dayjs(record.startAt).format('YYYY-MM-DD HH:mm:ss') + ' - ' +
dayjs(record.endAt).format('YYYY-MM-DD HH:mm:ss')}}</span>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record)" v-if="record.status === 1">
<a-tooltip>
<template #title>审核</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal :open="open" :title="'审核'" :width="640" title="审核" ok-text="确认" cancel-text="取消" @ok="handleAuditEdit"
@cancel="open = false">
<a-card class="mb-8-2">
<a-form-item :label="'审核'" name="">
<a-radio-group v-model:value="auditStatus"
:options="[{ value: 2, label: '通过' }, { value: 99, label: '驳回' }]"></a-radio-group>
</a-form-item>
<a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { orderStatus } from '@/enums/index.js'
import { status } from 'nprogress'
import dayjs from 'dayjs'
defineOptions({
name: 'mettingYuYue',
})
const { t } = useI18n() // t
const columns = [
{ title: '用户', dataIndex: 'concatName' },
{ title: '手机号', dataIndex: 'concatPhone' },
{ title: '会议室', dataIndex: 'roomName' },
{ title: '时间段', dataIndex: 'startAt', width: 300, align: 'center' },
{ title: '备注', dataIndex: 'remark' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const remark = ref('')
const currentInfo = ref({})
const auditStatus = ref(2)
const editDialogRef = ref()
const open = ref(false)
const imgOpen = ref(false)
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.mettingYuYue
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (obj = {}, type) => {
currentInfo.value = obj
if (type === 'audit') {
open.value = true
} else {
imgOpen.value = true
}
}
const handleClick = async () => {
try {
const params = {
...currentInfo.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.mettingYuYue.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
if (config('http.code.success') === result?.success) {
message.success('已审核')
open.value = false
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
}
/**
* 删除
*/
const handleAuditEdit = async () => {
try {
const params = {
...currentForm.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.mettingRoom.updateMenu(currentForm.value.id, params).catch(() => {
throw new Error()
})
if (config('http.code.success') === result?.success) {
getPageList()
open.value = false
message.success('审核成功')
}
} catch (error) {
message.error(error.message)
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,115 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'审核结果'" name="status">
<a-radio-group v-model:value="formData.status"
:options="[{ label: '通过', value: 2 }, { label: '拒绝', value: 5 }]"></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'备注'" name="remark">
<a-input v-model:value="formData.remark"></a-input>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
formRules.value = {
status: { required: true, message: '请选择审核状态', trigger: 'change' },
remark: [{ required: true, message: '请输入备注', trigger: 'remark' }],
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({type: 'edit',title: '审核'})
formData.value.id=record.id
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
id: formData.value.id,
status: formData.value.status,
remark: formData.value.remark
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.nbdMutualAid.createMenu(params).catch(() => {
throw new Error()
})
break
case 'edit':
result = await apis.nbdMutualAid.updateMenu(formData.value.id, params).catch(() => {
throw new Error()
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
console.log(error)
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,175 @@
<template>
<x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="用户名称:" name="userName">
<a-input placeholder="请输入用户名称" v-model:value="searchFormData.userName"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="评论人名称:" name="commentUser">
<a-input placeholder="请输入评论人名称" v-model:value="searchFormData.commentUser"></a-input>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'status' === column.dataIndex">
<a-tag :color="activatyStatus.getColor(record.status)">{{activatyStatus.getName(record.status)}}</a-tag>
</template>
<template v-if="'pushAt' === column.dataIndex">
<span>{{ dayjs(record.pushAt).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>{{ $t('pages.system.delete') }}</template>
<delete-outlined style="color: #ff4d4f" />
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import errImg from '@/assets/blankSpace.png'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { activatyStatus } from '@/enums/index.js'
defineOptions({
name: 'mutualComment',
})
const { t } = useI18n() // t
const columns = [
{ title: '评论人名称', dataIndex: 'commentUser', key: 'commentUser' },
{ title: '评论内容', dataIndex: 'commentContent' },
{ title: '发布时间', dataIndex: 'pushAt', width: 120, align: 'center' },
{ title: '被评论人', dataIndex: 'userName', align: 'center' },
{ title: '被评论帖子', dataIndex: 'title', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.mutualComment
.getDataList({
pageSize,
current: current,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
//type80about
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 删除
*/
function handleDelete({ id }) {
Modal.confirm({
title: t('pages.system.user.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.mutualComment.delMenu(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,59 @@
// CommentItem.js
import { h } from 'vue'
export const CommentItem = {
name: 'CommentItem',
props: {
comment: {
type: Object,
required: true,
},
// 可选:添加深度限制防止无限递归
depth: {
type: Number,
default: 0,
},
},
setup(props) {
// 日期格式化函数
const formatDate = (dateString) => {
return new Date(dateString).toLocaleString()
}
// 返回渲染函数
return () => {
const { comment, depth } = props
// 创建子评论元素(递归部分)
let childComments = null
if (comment.children?.length && depth < 10) {
// 限制最大深度为10层
childComments = h(
'div',
{ class: 'replies' },
comment.children.map((child) =>
h(CommentItem, {
comment: child,
key: child.id,
depth: depth + 1, // 传递增加后的深度
})
)
)
}
// 构建主组件结构
return h('div', { class: 'comment' }, [
// 评论头部
h('div', { class: 'comment-header' }, [
h('span', { class: 'username' }, comment.pusherName),
h('span', { class: 'time' }, formatDate(comment.createdAt)),
]),
// 评论内容
h('div', { class: 'comment-content' }, comment.content),
// 子评论容器
childComments,
])
}
},
}

View File

@ -0,0 +1,160 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleCancel" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'用户名称'" name="customerName">
<a-input v-model:value="formData.customerName"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'求助标题'" name="title">
<a-input v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'创建时间'" name="createdAt">
<a-date-picker v-model:value="formData.createdAt" style="width: 100%;"></a-date-picker>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status"
:options="nbdMutualStatus.getAll()" disabled></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'内容'" name="content">
<a-textarea v-model:value="formData.content"></a-textarea>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'备注'" name="remark">
<a-input v-model:value="formData.remark"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'图片'" name="images">
<a-image :width="200" v-for="item in formData.images" :src="config('http.apiBasic')+item" />
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { nbdMutualStatus } from '@/enums/index.js'
import dayjs from 'dayjs'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
formRules.value = {
// customerName: { required: true, message: '', trigger: 'change' },
// status: { required: true, message: '', trigger: 'change' },
// remark: [{ required: true, message: '', trigger: 'remark' }],
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑',
})
try {
showSpining()
const { data, success } = await apis.nbdMutuaAid.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
formData.value.createdAt=dayjs(data.createdAt)
} catch (error) {
message.error({ content: error.message })
hideSpining()
}
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
id: formData.value.id,
status: formData.value.status,
remark: formData.value.remark
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.nbdMutualAid.createMenu(params).catch(() => {
throw new Error()
})
break
case 'edit':
result = await apis.nbdMutualAid.updateMenu(formData.value.id, params).catch(() => {
throw new Error()
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
console.log(error)
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,307 @@
<template>
<x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="用户名称:" name="userName">
<a-input placeholder="请输入用户名称" v-model:value="searchFormData.userName"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="状态" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option v-for="item of nbdMutualStatus.getAll()" :value="item.value">{{
item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'avator' === column.dataIndex">
<a-image :width="60"
:src="record.avator ? config('http.apiBasic') + record.avator : errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="nbdMutualStatus.getColor(record.status)">{{
nbdMutualStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'createdAt' === column.dataIndex">
<span>{{ dayjs(record.createdAt).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template v-if="'title' === column.dataIndex">
<a-tooltip :title="record.title">
<span>{{ record.title }}</span>
</a-tooltip>
</template>
<template v-if="'content' === column.dataIndex">
<a-tooltip :title="record.content">
<span>{{ record.content }}</span>
</a-tooltip>
</template>
<template v-if="'remark' === column.dataIndex">
<a-tooltip :title="record.remark">
<span>{{ record.remark }}</span>
</a-tooltip>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record, 'audit')" v-if="record.status === 1">
<a-tooltip :title="'审核'">
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip :title="'详情'">
<i class="iconfont icon-xiangqing" style='font-size:16px;'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip :title="'评论列表'">
<i class="iconfont icon-lishi" style='font-size:16px;color:#666666'></i>
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal v-model:open="open" :title="'审核'" @ok="handleClick">
<a-card class="mb-8-2">
<a-form-item label="审核" name="">
<a-radio-group v-model:value="auditStatus">
<a-radio :value="2">通过</a-radio>
<a-radio :value="99">不通过</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="备注" name="">
<a-textarea :placeholder="'请输入审核备注'" v-model:value="remark"
:auto-size="{ minRows: 2, maxRows: 5 }"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<a-modal v-model:open="historyOpen" :title="'历史记录'" @ok="historyOpen = false">
<a-spin :spinning="spining">
<a-card class="mb-8-2">
<p>{{ nbdMutualAidInfo.content }}</p>
<div v-if="nbdMutualAidInfo.histories.length > 0">
<comment-item v-for="comment in nbdMutualAidInfo.histories" :key="comment.id" :comment="comment" />
</div>
<span v-else>暂无记录...</span>
</a-card>
</a-spin>
</a-modal>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination, useSpining } from '@/hooks'
import { CommentItem } from './components/CommentItem.js';
import errImg from '@/assets/blankSpace.png'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { nbdMutualStatus } from '@/enums/index.js'
import dayjs from 'dayjs'
defineOptions({
name: 'nbdMutuaAid',
})
const { t } = useI18n() // t
const columns = [
{ title: '用户名称', dataIndex: 'customerName', key: 'customerName', width: 120 },
{ title: '求助标题', dataIndex: 'title', width: 120, align: 'center', ellipsis: true },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: '创建时间', dataIndex: 'createdAt', width: 160, align: 'center' },
{ title: '内容', dataIndex: 'content', align: 'center', ellipsis: true },
{ title: '备注', dataIndex: 'remark', align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 140, align: 'center' },
]
const historyList = ref([])
const historyOpen = ref(false)
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const { spining, showSpining, hideSpining } = useSpining()
const open = ref(false)
const auditStatus = ref(2)
const remark = ref('')
const editDialogRef = ref()
const currentInfo = ref({})
const nbdMutualAidInfo = ref({})
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.nbdMutuaAid
.getDataList({
pageSize,
current: current,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
//type80about
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (obj = {}, type) => {
currentInfo.value = obj
if (type === 'audit') {
open.value = true
} else {
// imgOpen.value = true
}
}
const handleClick = async () => {
try {
const params = {
...currentInfo.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.nbdMutuaAid.updateMenu(currentInfo.value.id, params).catch(() => {
throw new Error(error)
})
if (config('http.code.success') === result?.success) {
message.success('已审核')
open.value = false
getPageList()
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
}
/**
* 评论列表
*/
const handleDelete = async ({ id }) => {
try {
historyOpen.value = true
showSpining()
const { success, data } = await apis.nbdMutuaAid.getList(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
nbdMutualAidInfo.value = { ...data }
hideSpining()
}
} catch (error) {
hideSpining()
message.error(error.message)
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped>
/* 全局评论样式 */
.comment {
margin-bottom: 15px;
padding: 15px;
border-radius: 8px;
background-color: #f9f9f9;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.comment-header {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
object-fit: cover;
}
.username {
font-weight: bold;
margin-right: 10px;
}
.time {
color: #888;
font-size: 0.85em;
}
.comment-content {
line-height: 1.5;
color: #333;
}
.replies {
margin-top: 15px;
margin-left: 30px;
padding-left: 15px;
border-left: 2px solid #e0e0e0;
}
</style>

View File

@ -0,0 +1,163 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'名称'" name="title">
<a-input :placeholder="'请输入名称'" v-model:value="formData.title"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'顺序'" name="sequence">
<a-input-number :placeholder="'请输入顺序'" v-model:value="formData.sequence"
style="width: 100%;"></a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status"
:options="enumsStatus.getAll()"></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'图片'" name="img">
<gx-upload v-model="formData.img" :fileNumber="1" />
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import { enumsStatus } from '@/enums/index.js'
import { spliceUrl } from '@/utils/util'
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const rolesValue = ref([])
const roles = ref([])
const img = ref('')
formRules.value = {
title: { required: true, message: '请输入名称' },
status: [{ required: true, message: '请选择状态', trigger: 'change' }],
sequence: [{ required: true, message: '请选择顺序', trigger: 'change' }],
img: [{ required: true, message: '请上传图片', trigger: 'change' }],
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
// 80about
title: '添加',
})
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: t('pages.system.user.edit'),
})
showSpining()
const { data, success } = await apis.imgmgt.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
formData.value.img = [config('http.apiBasic') + data.img]
}
/**
* 确定
*/
function handleOk() {
if (!formData.value.img) return message.error('请上传图片');
formRef.value.validateFields().then(async (values) => {
console.log(values)
try {
showLoading()
const params = {
...values,
img: spliceUrl(formData.value?.img[0]),
scene: 2,
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.imgmgt.createMenu(params).catch(() => {
throw new Error()
})
break
case 'edit':
// result = await apis.imgmgt.updateMenu(formData.value.id, params).catch(() => {
result = await apis.imgmgt.updateMenu(formData.value.id, params).catch(() => {
throw new Error()
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
console.log(error)
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
formData.value.img = ['']
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,191 @@
<template>
<!-- <x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :label-col="{ style: { width: '40px' } }" :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="名称" name="title">
<a-input placeholder="请输入图片名称" v-model:value="searchFormData.title"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="状态" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option v-for="item of enumsStatus.getAll()" :value="item.value">{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar> -->
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'img' === column.dataIndex">
<a-image :width="60" :src="record.img?config('http.apiBasic')+record.img:errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="enumsStatus.getColor(record.status)">{{ enumsStatus.getName(record.status) }}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title> {{ $t('pages.system.user.edit') }}</template>
<edit-outlined /> </a-tooltip></x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>{{ $t('pages.system.delete') }}</template>
<delete-outlined style="color: #ff4d4f" /> </a-tooltip></x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { formatUtcDateTime } from '@/utils/util'
import { config } from '@/config'
import { statusUserTypeEnum } from '@/enums/system'
import { usePagination } from '@/hooks'
import errImg from '@/assets/blankSpace.png'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { delMenu, getDataList } from '@/apis/modules/imgmgt'
import { enumsStatus } from '@/enums/index.js'
defineOptions({
name: 'homeBanner',
})
const { t } = useI18n() // t
const columns = [
{ title: '图片', dataIndex: 'img', width: 100, align: 'center' },
{ title: '名称', dataIndex: 'title', key: 'name' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: '顺序', dataIndex: 'sequence', width: 100, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.imgmgt
.getDataList({
pageSize,
current:current,
scene: 2,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
//type80about
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 删除
*/
function handleDelete({ id }) {
Modal.confirm({
title: t('pages.system.user.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.imgmgt.delMenu(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,245 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="基本信息">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'产品分类'" name="typeId">
<a-select ref="select" v-model:value="formData.typeId" style="width: 100%">
<a-select-option v-for="item in typeList" :value="item.value">{{
item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'产品排序'" name="sequence">
<a-input-number :placeholder="'请输入排序'" v-model:value="formData.sequence"
style="width: 100%;"></a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'门店名称'" name="storeName">
<a-input :placeholder="'请输入门店名称'" v-model:value="formData.storeName"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'营业时间'" name="openAt">
<a-input :placeholder="'请输入营业时间'" v-model:value="formData.openAt"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'标签'" name="labels">
<a-select v-model:value="formData.labels" mode="tags" style="width: 100%"
placeholder="输入标签然后回车"></a-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status"
:options="enumsStatus.getAll()"></a-radio-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'店铺描述'" name="content">
<a-textarea :placeholder="'请输入店铺描述'" v-model:value="content"
:auto-size="{ minRows: 2, maxRows: 5 }"></a-textarea>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :label="'店铺封面'" name="storeCover">
<gx-upload v-model="formData.storeCover" accept-types=".jpg,.png,.webp"
:fileNumber="1" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :label="'详情图片'" name="img">
<gx-upload v-model="formData.img" accept-types=".jpg,.png,.webp"
:fileNumber="1" />
</a-form-item>
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane key="2" tab="位置信息">
<a-row :gutter="12">
<a-col :span="12">
<a-form-item :label="'经度'" name="longitude">
<a-input :placeholder="'请输入经度'" v-model:value="formData.longitude"></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :label="'纬度'" name="latitude">
<a-input :placeholder="'请输入纬度'" v-model:value="formData.latitude"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'详细地址'" name="storeAddress">
<a-input :placeholder="'请输入详细地址'"
v-model:value="formData.storeAddress"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<gx-map @handleGetLng="handleGetLng" />
</a-col>
</a-row>
</a-tab-pane>
</a-tabs>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { enumsStatus } from '@/enums/index.js'
import { spliceUrl } from '@/utils/util'
import { init } from 'echarts'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const typeList = ref([])
const searchValue = ref('')
const activeKey = ref('1')
formRules.value = {
typeId: [{ required: true, message: '请选择产品类别名称', trigger: 'change' }],
sequence: { required: true, message: '请输入排序' },
storeName: { required: true, message: '请输入门店名称' },
openAt: { required: true, message: '请输入营业时间' },
longitude: { required: true, message: '请输入经度' },
latitude: { required: true, message: '请输入纬度' },
storeAddress: { required: true, message: '请输入门店地址' },
status:{required: true, message: '请选择状态', trigger: 'change'}
}
const initData = async () => {
try {
showSpining()
const { data, success } = await apis.serverType.getDataList({ pageSize: 99, current: 1 })
if (success) {
typeList.value = data.map(item => ({ value: item.id, label: item.label }))
hideSpining()
}
} catch (error) {
hideSpining()
}
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '新增',
})
initData()
formData.value.status = 1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑',
})
const { data, success } = await apis.serverList.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
formData.value = { ...data }
formData.value.storeCover=data.storeCover?[config('http.apiBasic')+data.storeCover]:''
formData.value.img=data.img?[config('http.apiBasic')+data.img]:''
initData()
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
console.log(formData.value)
const params = {
...values,
storeCover: formData.value.storeCover ? spliceUrl(formData.value.storeCover[0]) : '',
img: formData.value.img ? spliceUrl(formData.value.img[0]) : '',
latitude: parseFloat(formData.value.latitude),
longitude: parseFloat(formData.value.longitude)
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.serverList.createMenu(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.serverList.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
const handleGetLng = (obj = {}) => {
formData.value.longitude = obj.lng
formData.value.latitude = obj.lat
formData.value.storeAddress = obj.address
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,159 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增门店
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'status' === column.dataIndex">
<a-tag :color="enumsStatus.getColor(record.status)">{{ enumsStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title>编辑</template>
<edit-outlined /> </a-tooltip></x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>撤销</template>
<delete-outlined style="color: #ff4d4f" /> </a-tooltip></x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { enumsStatus } from '@/enums/index.js'
defineOptions({
name: 'serverList',
})
const { t } = useI18n() // t
const columns = [
{ title: '所属分类', dataIndex: 'label' },
{ title: '门店名称', dataIndex: 'storeName', ellipsis: true },
// { title: '', dataIndex: 'storeCover' },
{ title: '经度', dataIndex: 'longitude' },
{ title: '纬度', dataIndex: 'latitude' },
{ title: '详细地址', dataIndex: 'storeAddress', ellipsis: true },
{ title: '营业时间', dataIndex: 'openAt' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } =
usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.serverList
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 删除
*/
function handleDelete(value) {
Modal.confirm({
title: '确定撤销该工单吗',
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.serverList.delMenu(value).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,143 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'产品分类'" name="label">
<a-input :placeholder="'请输入产品分类名称'" v-model:value="formData.label"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'产品排序'" name="sequence">
<a-input-number :placeholder="'请输入排序'"
v-model:value="formData.sequence" style="width: 100%;"></a-input-number>
</a-form-item>
</a-col>
<!-- <a-col :span="24">
<a-form-item :label="'图标'" name="iconUrl">
<gx-upload v-model="formData.iconUrl" accept-types=".jpg,.png,.webp" :fileNumber="1" />
</a-form-item>
</a-col> -->
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { spliceUrl } from '@/utils/util'
import Http from 'xy-http'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const treeData = ref([])
formRules.value = {
label: { required: true, message: '请输入产品类别名称' },
sequence: { required: true, message: '请输入排序' },
iconUrl:{required: true, message: '请上传图标', trigger: 'change'}
}
/**
* 新建
*/
function handleCreate() {
showModal({type: 'create',title: '产品分类'})
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({type: 'edit',title: '编辑分类'})
const { data, success } = await apis.serverType.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
formData.value = { ...data }
formData.value.iconUrl=[config('http.apiBasic')+data.iconUrl]
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
iconUrl:formData.value.iconUrl?spliceUrl(formData.value.iconUrl[0]):''
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.serverType.createMenu(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.serverType.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,160 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增分类
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'iconUrl'===column.dataIndex">
<a-image :width="60" :src="record.iconUrl?config('http.apiBasic')+record.iconUrl:errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="orderStatus.getColor(record.status)">{{ orderStatus.getName(record.status)}}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title>编辑分类</template>
<edit-outlined /> </a-tooltip></x-action-button>
<x-action-button @click="handleDelete(record)">
<a-tooltip>
<template #title>{{ $t('pages.system.delete') }}</template>
<delete-outlined style="color: #ff4d4f" />
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { orderStatus } from '@/enums/index.js'
import errImg from '@/assets/blankSpace.png'
defineOptions({
name: 'serverType',
})
const { t } = useI18n() // t
const columns = [
{ title: '分类名称', dataIndex: 'label' },
// { title: '', dataIndex: 'iconUrl' },
{ title: '分类排序', dataIndex: 'sequence' },
// { title: '', dataIndex: 'status', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } =
usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.serverType
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 删除
*/
function handleDelete(value) {
Modal.confirm({
title: '确定删除该分类吗',
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.serverType.delMenu(value).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,232 @@
<template>
<!-- <x-search-bar class="mb-8-2">
<template #default="{ gutter, colSpan }">
<a-form :model="searchFormData" layout="inline">
<a-row :gutter="gutter">
<a-col v-bind="colSpan">
<a-form-item label="登录账号" name="username">
<a-input placeholder="请输入登录账号" v-model:value="searchFormData.username"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="用户名称" name="name">
<a-input placeholder="请输入用户名称" v-model:value="searchFormData.name"></a-input>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item :label="'状态'" name="status">
<a-select v-model:value="searchFormData.status" allowClear>
<a-select-option v-for="item of userStatus.getAll()" :value="item.value">{{
item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col class="align-right" v-bind="colSpan">
<a-space>
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
<a-button ghost type="primary" @click="handleSearch">
{{ $t('button.search') }}
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
</x-search-bar> -->
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<a-table :columns="columns" :data-source="listData" :loading="loading" bordered="true"
:pagination="paginationState" :scroll="{ x: 1000 }" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'avatar'">
<a-image :width="45" :src="record.avatar ? config('http.apiBasic') + record.avatar : errImg" />
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="userStatus.getColor(record.status)">{{
userStatus.getName(record.status)
}}</a-tag>
</template>
<template v-if="'createdAt' === column.dataIndex">
{{ dayjs(record.createdAt).format('YYYY-MM-DD') }}
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record)">
<a-tooltip>
<template #title> {{ '编辑' }}</template>
<edit-outlined />
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal :open="modal.open" :title="'编辑'" :width="640" :confirm-loading="modal.confirmLoading"
ok-text="确认" cancel-text="取消" @ok="handleAuditEdit" @cancel="hideModal()">
<a-card class="mb-8-2">
<a-form-item :label="'编辑'" name="">
<a-radio-group v-model:value="auditStatus"
:options="userStatus.getAll()"></a-radio-group>
</a-form-item>
<!-- <a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item> -->
</a-card>
</a-modal>
<add-dialog ref="addDialogRef" @ok="onOk"></add-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { userStatus } from '@/enums/index.js'
import { usePagination,useModal } from '@/hooks'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import dayjs from 'dayjs'
import errImg from '@/assets/blankSpace.png'
defineOptions({
name: 'systemRole',
})
const { t } = useI18n() // t
const columns = [
{ title: '头像', dataIndex: 'avatar', key: 'avatar', with: 50, align: 'center' },
{ title: '用户名', dataIndex: 'name', key: 'name'},
{ title: '手机号', dataIndex: 'phone'},
{ title: '简介', dataIndex: 'introduce',align: 'center' },
{ title: '状态', key: 'status', dataIndex: 'status', width: 120, align: 'center' },
{ title: '创建时间', dataIndex: 'createdAt', width: 200, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 140, align: 'center' },
]
const { modal, showModal, hideModal, showLoading:auditShowLoading, hideLoading:auditHideLoading } = useModal()
const { listData, loading, showLoading, hideLoading, paginationState, searchFormData, resetPagination } = usePagination()
// const { resetForm } = useForm()
const addDialogRef = ref()
const currentForm=ref({})
const auditStatus=ref(2)
const remark=ref('')
getPageList()
/**
* 获取公公告列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.customer
.getDataList({
pageSize,
current: current,
...searchFormData.value,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
/**
* 移除
*/
function handleRemove({ id }) {
Modal.confirm({
title: t('pages.system.role.delTip'),
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const { success } = await apis.customer.delNotices(id).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success(t('component.message.success.delete'))
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
const auditHandleEdit = (params) => {
currentForm.value = params
auditStatus.value=params.status
showModal()
}
const handleAuditEdit = async () => {
try {
auditShowLoading()
const params = {
...currentForm.value,
status: auditStatus.value,
}
console.log(params);
const result = await apis.customer.updateMenu(currentForm.value.id, params).catch(() => {
throw new Error()
})
auditHideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
getPageList()
message.success('编辑成功')
}
} catch (error) {
message.error(error.message)
auditHideLoading()
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,163 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'用户名'" name="customerName">
<a-input :placeholder="'请输入用户名'" v-model:value="formData.customerName"
></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工单分类'" name="label">
<a-input :placeholder="'请输入工单分类'" v-model:value="formData.label" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工单内容'" name="content">
<a-textarea :placeholder="'请输入工单内容'" v-model:value="formData.content"
:auto-size="{ minRows: 2, maxRows: 5 }" ></a-textarea>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'工作地点'" name="address">
<a-input :placeholder="'请输入工作地点'" v-model:value="formData.address" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'创建时间'" name="createAt">
<a-input :placeholder="'请输入创建时间'" v-model:value="formData.createAt" ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'上门时间'" name="startAt">
<a-input :placeholder="'请输入上门时间'" v-model:value="formData.startAt" ></a-input>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { spliceUrl } from '@/utils/util'
import { readonly } from 'vue'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const treeData = ref([])
const status=ref(2)
const remark=ref('')
formRules.value = {
label: { required: true, message: '请输入产品类别名称' },
sequence: { required: true, message: '请输入排序' }
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '产品分类',
})
//
initData()
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑分类',
})
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
status:status.value,
remark:status.remark
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.orderList.createProductsItem(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.orderList.updateItem(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
console.log(e)
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,230 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'url' === column.dataIndex">
<a-button type="link" @click="auditHandleEdit(record, 'img')">点击查看</a-button>
</template>
<template v-if="'status' === column.dataIndex">
<a-tag :color="orderStatus.getColor(record.status)">{{
orderStatus.getName(record.status) }}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="auditHandleEdit(record, 'audit')" v-if="record.status === 1">
<a-tooltip>
<template #title> {{ '审核' }}</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
<x-action-button @click="handleDelete(record)" v-if="record.status!==98">
<a-tooltip>
<template #title>撤销</template>
<delete-outlined style="color: #ff4d4f" /> </a-tooltip></x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal v-model:open="open" :title="'审核'" @ok="handleClick">
<a-card class="mb-8-2">
<a-form-item label="审核" name="">
<a-radio-group v-model:value="auditStatus">
<a-radio :value="2">通过</a-radio>
<a-radio :value="99">不通过</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="备注" name="">
<a-textarea :placeholder="'请输入审核备注'" v-model:value="remark"
:auto-size="{ minRows: 2, maxRows: 5 }"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<a-modal v-model:open="imgOpen" :title="'图片/视频'" @ok="imgOpen = false">
<a-card class="mb-8-2">
<a-form-item :label="'图片'" name="images">
<template v-if="currentInfo.images && currentInfo.images.length > 0">
<a-image-preview-group>
<a-image v-for="item in currentInfo.images" :width="200"
:src="config('http.apiBasic') + item" />
</a-image-preview-group>
</template>
<template v-else>暂无</template>
</a-form-item>
<a-form-item label="视频" name="video">
<template v-if="currentInfo.videos && currentInfo.videos.length > 0">
<video width="320" height="240" controls>
<source v-for="item in currentInfo.videos" :src="config('http.apiBasic') + item">
</video>
</template>
<template>暂无</template>
</a-form-item>
</a-card>
</a-modal>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { orderStatus } from '@/enums/index.js'
import { status } from 'nprogress'
defineOptions({
name: 'orderList',
})
const { t } = useI18n() // t
const columns = [
{ title: '用户名称', dataIndex: 'customerName' },
{ title: '工单分类', dataIndex: 'label' },
{ title: '工单标题', dataIndex: 'title', ellipsis: true },
{ title: '工单内容', dataIndex: 'content', ellipsis: true },
{ title: '图片/视频', dataIndex: 'url', width: 120,align:'center' },
{ title: '工作地点', dataIndex: 'address', ellipsis: true },
{ title: '创建时间', dataIndex: 'createAt' },
{ title: '上门时间', dataIndex: 'startAt' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
const remark = ref('')
const currentInfo = ref({})
const auditStatus = ref(2)
const editDialogRef = ref()
const open = ref(false)
const imgOpen=ref(false)
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.orderList
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (obj = {}, type) => {
currentInfo.value = obj
if (type === 'audit') {
open.value = true
} else {
imgOpen.value = true
}
}
const handleClick = async () => {
try {
const params = {
...currentInfo.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.orderList.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
if (config('http.code.success') === result?.success) {
message.success('已审核')
open.value=false
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
}
/**
* 删除
*/
function handleDelete(value) {
Modal.confirm({
title: '确定撤销该工单吗',
content: t('button.confirm'),
okText: t('button.confirm'),
onOk: () => {
return new Promise((resolve, reject) => {
; (async () => {
try {
const params={
...value,
status:98
}
console.log(params)
const { success } = await apis.orderList.updateMenu(value.id, params).catch(() => {
throw new Error()
})
if (config('http.code.success') === success) {
resolve()
message.success('撤销成功')
await getPageList()
}
} catch (error) {
reject()
}
})()
})
},
})
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,153 @@
<template>
<a-modal :open="modal.open" :title="modal.title" :width="640" :confirm-loading="modal.confirmLoading"
:after-close="onAfterClose" :cancel-text="cancelText" :ok-text="okText" @ok="handleOk" @cancel="handleCancel">
<a-spin :spinning="spining">
<a-form ref="formRef" :model="formData" :rules="formRules">
<a-card class="mb-8-2">
<a-row :gutter="12">
<a-col :span="24">
<a-form-item :label="'产品分类'" name="label">
<a-input :placeholder="'请输入产品分类名称'" v-model:value="formData.label"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'产品排序'" name="sequence">
<a-input-number :placeholder="'请输入排序'" v-model:value="formData.sequence"
style="width: 100%;"></a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="'状态'" name="status">
<a-radio-group v-model:value="formData.status" :options="workTypeStatus.getAll()" disabled></a-radio-group>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</a-spin>
</a-modal>
</template>
<script setup>
import { cloneDeep } from 'lodash-es'
import { ref, onBeforeMount } from 'vue'
import { config } from '@/config'
import apis from '@/apis'
import { useForm, useModal, useSpining } from '@/hooks'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { workTypeStatus } from '@/enums/index.js'
import { spliceUrl } from '@/utils/util'
const areaFormRef = ref()
const emit = defineEmits(['ok'])
const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
const { spining, showSpining, hideSpining } = useSpining()
const cancelText = ref(t('button.cancel'))
const okText = ref(t('button.confirm'))
const treeData = ref([])
formRules.value = {
label: { required: true, message: '请输入产品类别名称' },
sequence: { required: true, message: '请输入排序' },
status: { required: true, message: '请选择状态', trigger: 'change' }
}
/**
* 新建
*/
function handleCreate() {
showModal({
type: 'create',
title: '新增分类',
})
formData.value.status=1
}
/**
* 编辑
*/
async function handleEdit(record = {}) {
showModal({
type: 'edit',
title: '编辑分类',
})
try {
showSpining()
const { data, success } = await apis.orderType.getMenu(record.id).catch()
if (!success) {
hideModal()
return
}
hideSpining()
formData.value = { ...data }
} catch (error) {
message.error({ content: error.message })
hideSpining()
}
}
/**
* 确定
*/
function handleOk() {
formRef.value.validateFields().then(async (values) => {
try {
showLoading()
const params = {
...values,
}
let result = null
switch (modal.value.type) {
case 'create':
result = await apis.orderType.createMenu(params).catch((error) => {
throw new Error(error)
})
break
case 'edit':
result = await apis.orderType.updateMenu(formData.value.id, params).catch(() => {
throw new Error(error)
})
break
}
hideLoading()
if (config('http.code.success') === result?.success) {
hideModal()
emit('ok')
}
} catch (error) {
message.error({ content: error.message })
hideLoading()
}
})
.catch((e) => {
hideLoading()
})
}
/**
* 取消
*/
function handleCancel() {
hideModal()
}
/**
* 关闭后
*/
function onAfterClose() {
resetForm()
hideLoading()
}
defineExpose({
handleCreate,
handleEdit,
})
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,170 @@
<template>
<a-row :gutter="8" :wrap="false">
<a-col flex="auto">
<a-card type="flex">
<x-action-bar class="mb-8-2">
<a-button type="primary" @click="$refs.editDialogRef.handleCreate()">
<template #icon>
<plus-outlined></plus-outlined>
</template>
新增分类
</a-button>
</x-action-bar>
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
:pagination="paginationState" @change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="'status' === column.dataIndex">
<a-tag :color="workTypeStatus.getColor(record.status)">{{
workTypeStatus.getName(record.status) }}</a-tag>
</template>
<template v-if="'action' === column.key">
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
<a-tooltip>
<template #title>编辑分类</template>
<edit-outlined />
</a-tooltip>
</x-action-button>
<x-action-button @click="auditHandleEdit(record)" v-if="record.status === 1">
<a-tooltip>
<template #title>审核</template>
<i class='iconfont icon-shenhe' style='font-size:14px;color:#faad14'></i>
</a-tooltip>
</x-action-button>
</template>
</template>
</a-table>
</a-card>
</a-col>
</a-row>
<a-modal :open="open" :title="'审核'" :width="640" title="审核" ok-text="确认" cancel-text="取消" @ok="handleAuditEdit"
@cancel="open = false">
<a-card class="mb-8-2">
<a-form-item :label="'审核'" name="">
<a-radio-group v-model:value="auditStatus"
:options="[{ value: 2, label: '通过' }, { value: 99, label: '不通过' }]"></a-radio-group>
</a-form-item>
<a-form-item :label="'备注'" name="">
<a-textarea v-model:value="remark"></a-textarea>
</a-form-item>
</a-card>
</a-modal>
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue'
import { ref } from 'vue'
import apis from '@/apis'
import { config } from '@/config'
import { usePagination } from '@/hooks'
import EditDialog from './components/EditDialog.vue'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { workTypeStatus } from '@/enums/index.js'
defineOptions({
name: 'orderType',
})
const currentForm = ref({})
const open = ref(false)
const auditStatus = ref(2)
const remark = ref('')
const { t } = useI18n() // t
const columns = [
{ title: '分类名称', dataIndex: 'label' },
{ title: '分类排序', dataIndex: 'sequence' },
{ title: '状态', dataIndex: 'status', width: 120, align: 'center' },
{ title: t('button.action'), key: 'action', fixed: 'right', width: 100, align: 'center' },
]
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } =
usePagination()
const editDialogRef = ref()
getPageList()
/**
* 获取用户列表
* @returns {Promise<void>}
*/
async function getPageList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.orderType
.getDataList({
pageSize,
current: current,
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
listData.value = data.map(item => ({
...item,
key: item.value
}))
paginationState.total = total
}
} catch (error) {
hideLoading()
}
}
const auditHandleEdit = (params) => {
currentForm.value = params
open.value = true
}
/**
* 删除
*/
const handleAuditEdit = async () => {
try {
const params = {
...currentForm.value,
status: auditStatus.value,
remark: remark.value
}
const result = await apis.orderType.updateMenu(currentForm.value.id, params).catch(() => {
throw new Error()
})
if (config('http.code.success') === result?.success) {
getPageList()
open.value = false
message.success('审核成功')
}
} catch (error) {
message.error(error.message)
}
}
/**
* 分页
*/
function onTableChange({ current, pageSize }) {
paginationState.current = current
paginationState.pageSize = pageSize
getPageList()
}
/**
* 搜索
*/
function handleSearch() {
resetPagination()
getPageList()
}
/**
* 重置
*/
function handleResetSearch() {
searchFormData.value = {}
resetPagination()
getPageList()
}
/**
* 编辑完成
*/
async function onOk() {
await getPageList()
}
</script>
<style lang="less" scoped></style>

View File

@ -239,7 +239,6 @@ function handleDelete({ id }) {
* 编辑完成 * 编辑完成
*/ */
async function onOk() { async function onOk() {
message.success(t('component.message.success.delete'))
await getMenuList() await getMenuList()
} }
</script> </script>

View File

@ -8,7 +8,7 @@ import useVuePlugin from './config/useVuePlugin'
import useVisualizerPlugin from './config/useVisualizerPlugin' import useVisualizerPlugin from './config/useVisualizerPlugin'
import useServer from './config/useServer' import useServer from './config/useServer'
// import useEslintPlugin from './config/useEslintPlugin' // import useEslintPlugin from './config/useEslintPlugin'
import { viteMockServe } from 'vite-plugin-mock'
export default ({ mode }) => { export default ({ mode }) => {
const env = loadEnv(mode, process.cwd(), '') const env = loadEnv(mode, process.cwd(), '')
return defineConfig({ return defineConfig({
@ -53,7 +53,19 @@ export default ({ mode }) => {
version: pkg.version, version: pkg.version,
}), }),
}, },
plugins: [useVuePlugin(), useProgressPlugin(), useCompressPlugin(), useVisualizerPlugin()], plugins: [
useVuePlugin(),
useProgressPlugin(),
useCompressPlugin(),
useVisualizerPlugin(),
viteMockServe({
mockPath: 'src/mock', // mock 文件目录
configPath:'src/mock/index.js',
localEnabled: true, // 开发环境启用
prodEnabled: false, // 生产环境禁用
logger: true, // 控制台日志
}),
],
server: useServer(), server: useServer(),
resolve: { resolve: {
alias: { alias: {

197
yarn.lock
View File

@ -138,6 +138,11 @@
"@algolia/logger-common" "4.19.1" "@algolia/logger-common" "4.19.1"
"@algolia/requester-common" "4.19.1" "@algolia/requester-common" "4.19.1"
"@amap/amap-jsapi-loader@^1.0.1":
version "1.0.1"
resolved "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz"
integrity sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==
"@ant-design/colors@^6.0.0": "@ant-design/colors@^6.0.0":
version "6.0.0" version "6.0.0"
resolved "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz" resolved "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz"
@ -629,6 +634,14 @@ ant-design-vue@^4.0.1:
vue-types "^3.0.0" vue-types "^3.0.0"
warning "^4.0.0" warning "^4.0.0"
anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz"
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
argparse@^2.0.1: argparse@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz" resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz"
@ -673,6 +686,11 @@ bignumber.js@^9.0.0:
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz" resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz"
integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
binary-extensions@^2.0.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
body-scroll-lock@4.0.0-beta.0: body-scroll-lock@4.0.0-beta.0:
version "4.0.0-beta.0" version "4.0.0-beta.0"
resolved "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz" resolved "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz"
@ -698,7 +716,7 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0" balanced-match "^1.0.0"
concat-map "0.0.1" concat-map "0.0.1"
braces@^3.0.2: braces@^3.0.2, braces@~3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@ -712,6 +730,13 @@ bundle-name@^3.0.0:
dependencies: dependencies:
run-applescript "^5.0.0" run-applescript "^5.0.0"
bundle-require@^4.0.1:
version "4.2.1"
resolved "https://registry.npmmirror.com/bundle-require/-/bundle-require-4.2.1.tgz"
integrity sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==
dependencies:
load-tsconfig "^0.2.3"
callsites@^3.0.0: callsites@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz" resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz"
@ -735,6 +760,21 @@ chalk@5.3.0:
resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz" resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz"
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
chokidar@^3.5.3:
version "3.6.0"
resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
cli-cursor@^4.0.0: cli-cursor@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz" resolved "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz"
@ -801,7 +841,7 @@ combined-stream@^1.0.8:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
commander@11.0.0: commander@*, commander@11.0.0:
version "11.0.0" version "11.0.0"
resolved "https://registry.npmmirror.com/commander/-/commander-11.0.0.tgz" resolved "https://registry.npmmirror.com/commander/-/commander-11.0.0.tgz"
integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==
@ -816,6 +856,16 @@ concat-map@0.0.1:
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
connect@^3.7.0:
version "3.7.0"
resolved "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz"
integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
dependencies:
debug "2.6.9"
finalhandler "1.1.2"
parseurl "~1.3.3"
utils-merge "1.0.1"
copy-anything@^2.0.1: copy-anything@^2.0.1:
version "2.0.6" version "2.0.6"
resolved "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz" resolved "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz"
@ -886,11 +936,18 @@ debug@^4.3.3:
ms "2.1.2" ms "2.1.2"
debug@^4.3.4: debug@^4.3.4:
version "4.3.4" version "4.4.1"
resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz" resolved "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
dependencies: dependencies:
ms "2.1.2" ms "^2.1.3"
debug@2.6.9:
version "2.6.9"
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
debug@4.3.4: debug@4.3.4:
version "4.3.4" version "4.3.4"
@ -982,6 +1039,11 @@ echarts@^5.4.3:
tslib "2.3.0" tslib "2.3.0"
zrender "5.4.4" zrender "5.4.4"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
emoji-regex@^8.0.0: emoji-regex@^8.0.0:
version "8.0.0" version "8.0.0"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
@ -997,6 +1059,11 @@ encode-utf8@^1.0.3:
resolved "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz" resolved "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz"
integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
errno@^0.1.1: errno@^0.1.1:
version "0.1.8" version "0.1.8"
resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz"
@ -1004,7 +1071,7 @@ errno@^0.1.1:
dependencies: dependencies:
prr "~1.0.1" prr "~1.0.1"
esbuild@^0.18.10: esbuild@^0.18.10, esbuild@>=0.17:
version "0.18.20" version "0.18.20"
resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz" resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz"
integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==
@ -1037,6 +1104,11 @@ escalade@^3.1.1:
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
escape-string-regexp@^4.0.0: escape-string-regexp@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
@ -1207,7 +1279,7 @@ fast-diff@^1.1.2:
resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-glob@^3.3.0: fast-glob@^3.2.12, fast-glob@^3.3.0:
version "3.3.1" version "3.3.1"
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz" resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz"
integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
@ -1259,6 +1331,19 @@ fill-range@^7.0.1:
dependencies: dependencies:
to-regex-range "^5.0.1" to-regex-range "^5.0.1"
finalhandler@1.1.2:
version "1.1.2"
resolved "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz"
integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
dependencies:
debug "2.6.9"
encodeurl "~1.0.2"
escape-html "~1.0.3"
on-finished "~2.3.0"
parseurl "~1.3.3"
statuses "~1.5.0"
unpipe "~1.0.0"
find-up@^4.1.0: find-up@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz"
@ -1347,6 +1432,13 @@ glob-parent@^6.0.2:
dependencies: dependencies:
is-glob "^4.0.3" is-glob "^4.0.3"
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob@^7.1.3: glob@^7.1.3:
version "7.2.3" version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
@ -1446,6 +1538,13 @@ inherits@2:
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-docker@^2.0.0, is-docker@^2.1.1: is-docker@^2.0.0, is-docker@^2.1.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz"
@ -1471,7 +1570,7 @@ is-fullwidth-code-point@^4.0.0:
resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz" resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz"
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3" version "4.0.3"
resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
@ -1643,6 +1742,11 @@ listr2@6.6.1:
rfdc "^1.3.0" rfdc "^1.3.0"
wrap-ansi "^8.1.0" wrap-ansi "^8.1.0"
load-tsconfig@^0.2.3:
version "0.2.5"
resolved "https://registry.npmmirror.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz"
integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==
locate-path@^5.0.0: locate-path@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz"
@ -1774,11 +1878,23 @@ minisearch@^6.1.0:
resolved "https://registry.npmjs.org/minisearch/-/minisearch-6.1.0.tgz" resolved "https://registry.npmjs.org/minisearch/-/minisearch-6.1.0.tgz"
integrity sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg== integrity sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==
ms@^2.1.1: mockjs@^1.1.0, mockjs@>=1.1.0:
version "1.1.0"
resolved "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz"
integrity sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==
dependencies:
commander "*"
ms@^2.1.1, ms@^2.1.3:
version "2.1.3" version "2.1.3"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
ms@2.1.2: ms@2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz" resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz"
@ -1813,6 +1929,11 @@ needle@^3.1.0:
iconv-lite "^0.6.3" iconv-lite "^0.6.3"
sax "^1.2.4" sax "^1.2.4"
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
npm-run-path@^4.0.1: npm-run-path@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz" resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz"
@ -1839,6 +1960,13 @@ nth-check@^2.1.1:
dependencies: dependencies:
boolbase "^1.0.0" boolbase "^1.0.0"
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz"
integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==
dependencies:
ee-first "1.1.1"
once@^1.3.0: once@^1.3.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
@ -1953,6 +2081,11 @@ parse-node-version@^1.0.1:
resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz" resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz"
integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
path-exists@^4.0.0: path-exists@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
@ -1973,12 +2106,17 @@ path-key@^4.0.0:
resolved "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz" resolved "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz"
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
path-to-regexp@^6.2.1:
version "6.3.0"
resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz"
integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==
picocolors@^1.0.0: picocolors@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.2.2, picomatch@^2.3.1: picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1:
version "2.3.1" version "2.3.1"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@ -2087,6 +2225,13 @@ rd@^2.0.1:
dependencies: dependencies:
"@types/node" "^10.3.6" "@types/node" "^10.3.6"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
regenerator-runtime@^0.13.4: regenerator-runtime@^0.13.4:
version "0.13.9" version "0.13.9"
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz"
@ -2286,6 +2431,11 @@ source-map@~0.6.0:
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
statuses@~1.5.0:
version "1.5.0"
resolved "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
string-argv@0.3.2: string-argv@0.3.2:
version "0.3.2" version "0.3.2"
resolved "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz" resolved "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz"
@ -2446,6 +2596,11 @@ universalify@^2.0.0:
resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
untildify@^4.0.0: untildify@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz" resolved "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz"
@ -2463,6 +2618,11 @@ util-deprecate@^1.0.2:
resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz" resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz"
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
vite-plugin-compression@^0.5.1: vite-plugin-compression@^0.5.1:
version "0.5.1" version "0.5.1"
resolved "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz" resolved "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz"
@ -2481,6 +2641,19 @@ vite-plugin-eslint@^1.8.1:
"@types/eslint" "^8.4.5" "@types/eslint" "^8.4.5"
rollup "^2.77.2" rollup "^2.77.2"
vite-plugin-mock@^3.0.2:
version "3.0.2"
resolved "https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-3.0.2.tgz"
integrity sha512-bD//HvkTygGmk+LsIAdf0jGNlCv4iWv0kZlH9UEgWT6QYoUwfjQAE4SKxHRw2tfLgVhbPQVv/+X3YlNWvueGUA==
dependencies:
bundle-require "^4.0.1"
chokidar "^3.5.3"
connect "^3.7.0"
debug "^4.3.4"
fast-glob "^3.2.12"
path-to-regexp "^6.2.1"
picocolors "^1.0.0"
vite-plugin-progress@^0.0.7: vite-plugin-progress@^0.0.7:
version "0.0.7" version "0.0.7"
resolved "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz" resolved "https://registry.npmjs.org/vite-plugin-progress/-/vite-plugin-progress-0.0.7.tgz"
@ -2490,7 +2663,7 @@ vite-plugin-progress@^0.0.7:
progress "^2.0.3" progress "^2.0.3"
rd "^2.0.1" rd "^2.0.1"
vite@^4.0.0, vite@^4.4.7, vite@^4.4.9, vite@>=2, vite@>=2.0.0, vite@>2.0.0-0: vite@^4.0.0, vite@^4.4.7, vite@^4.4.9, vite@>=2, vite@>=2.0.0, vite@>=4.0.0, vite@>2.0.0-0:
version "4.4.9" version "4.4.9"
resolved "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz" resolved "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz"
integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA== integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==