| package.json | ●●●●● patch | view | raw | blame | history | |
| pnpm-lock.yaml | ●●●●● patch | view | raw | blame | history | |
| src/components/map-container/mapContainer.vue | ●●●●● patch | view | raw | blame | history | |
| src/main.js | ●●●●● patch | view | raw | blame | history | |
| src/views/tickets/ticket.vue | ●●●●● patch | view | raw | blame | history | |
| vite.config.mjs | ●●●●● patch | view | raw | blame | history | |
| vite/plugins/index.js | ●●●●● patch | view | raw | blame | history |
package.json
@@ -9,6 +9,8 @@ "serve": "vite preview --host" }, "dependencies": { "@dvgis/dc-sdk": "3.4.0", "@dvgis/vite-plugin-dc": "2.2.0", "@element-plus/icons-vue": "^2.3.1", "@saber/nf-design-base-elp": "^1.2.0", "@smallwei/avue": "^3.4.4", @@ -22,6 +24,7 @@ "js-cookie": "^3.0.0", "js-md5": "^0.7.3", "jszip": "^3.10.1", "lodash": "^4.17.21", "mitt": "^3.0.1", "nprogress": "^0.2.0", "reconnecting-websocket": "^4.4.0", pnpm-lock.yaml
@@ -5,6 +5,12 @@ excludeLinksFromLockfile: false dependencies: '@dvgis/dc-sdk': specifier: 3.4.0 version: 3.4.0 '@dvgis/vite-plugin-dc': specifier: 2.2.0 version: 2.2.0(@dvgis/dc-sdk@3.4.0) '@element-plus/icons-vue': specifier: ^2.3.1 version: 2.3.1(vue@3.4.30) @@ -13,7 +19,7 @@ version: 1.2.0 '@smallwei/avue': specifier: ^3.4.4 version: 3.4.6(element-plus@2.7.6)(vue@3.4.30) version: 3.4.6(element-plus@2.9.7)(vue@3.4.30) animate.css: specifier: ^4.1.1 version: 4.1.1 @@ -27,11 +33,11 @@ specifier: ^4.1.1 version: 4.2.0 dayjs: specifier: ^1.10.6 version: 1.11.11 specifier: ^1.11.13 version: 1.11.13 element-plus: specifier: ^2.7.3 version: 2.7.6(vue@3.4.30) specifier: ^2.9.7 version: 2.9.7(vue@3.4.30) js-base64: specifier: ^3.7.4 version: 3.7.7 @@ -41,9 +47,21 @@ js-md5: specifier: ^0.7.3 version: 0.7.3 jszip: specifier: ^3.10.1 version: 3.10.1 lodash: specifier: ^4.17.21 version: 4.17.21 mitt: specifier: ^3.0.1 version: 3.0.1 nprogress: specifier: ^0.2.0 version: 0.2.0 reconnecting-websocket: specifier: ^4.4.0 version: 4.4.0 sm-crypto: specifier: ^0.3.13 version: 0.3.13 @@ -59,6 +77,9 @@ vuex: specifier: ^4.1.0 version: 4.1.0(vue@3.4.30) xlsx: specifier: ^0.18.5 version: 0.18.5 devDependencies: '@vitejs/plugin-vue': @@ -135,6 +156,28 @@ /@ctrl/tinycolor@3.6.1: resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} dev: false /@dvgis/dc-common@1.0.0: resolution: {integrity: sha512-sjRD9kQbQ3tAhbmJt00eleU3XM7laMHWl5qMU63Mk0tj2c/M8NTTIbXEdB8gdgDDHuZGN5eRm9nJ3rSO4nsSFw==} dev: false /@dvgis/dc-sdk@3.4.0: resolution: {integrity: sha512-WgoNmfwPiPuAf4mxEOYhoyi3FovkSxf1gMat2ds5vEigz6aE/r86gCoWRgmVjNxlkTuRYi6ROV8vGXxcZTVQYA==} dependencies: '@dvgis/dc-common': 1.0.0 dev: false /@dvgis/vite-plugin-dc@2.2.0(@dvgis/dc-sdk@3.4.0): resolution: {integrity: sha512-bREX+ycd6vzvpl1l7Gxxfm+91e6QicmEvqPIu8MYYOtdEd3hLjhFooF0vTi/Kp2gu2RIbwVi4pLo+HegpvsuPw==} peerDependencies: '@dvgis/dc-sdk': ^3.4.0 dependencies: '@dvgis/dc-sdk': 3.4.0 fs-extra: 9.1.0 serve-static: 1.16.2 transitivePeerDependencies: - supports-color dev: false /@element-plus/icons-vue@2.3.1(vue@3.4.30): @@ -606,7 +649,7 @@ randomcolor: 0.6.2 dev: false /@smallwei/avue@3.4.6(element-plus@2.7.6)(vue@3.4.30): /@smallwei/avue@3.4.6(element-plus@2.9.7)(vue@3.4.30): resolution: {integrity: sha512-JRka3h/NAoHwiCwkZuNfbHS1wevi3/3MxRXTU7IjX5TDveBx2jmLu1SWYU68f+1appm99RuBQYDJBlSJ21JU5w==} peerDependencies: element-plus: '>=2.2.0' @@ -614,8 +657,8 @@ dependencies: '@element-plus/icons-vue': 2.3.1(vue@3.4.30) countup.js: 1.9.3 dayjs: 1.11.11 element-plus: 2.7.6(vue@3.4.30) dayjs: 1.11.13 element-plus: 2.9.7(vue@3.4.30) vue: 3.4.30 dev: false @@ -987,6 +1030,11 @@ hasBin: true dev: true /adler-32@1.3.1: resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} engines: {node: '>=0.8'} dev: false /animate.css@4.1.1: resolution: {integrity: sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==} dev: false @@ -1008,6 +1056,11 @@ /async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} dev: false /at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} dev: false /avue-plugin-ueditor@1.0.4(axios@0.21.4)(vue@3.4.30): @@ -1068,6 +1121,14 @@ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true /cfb@1.2.2: resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} engines: {node: '>=0.8'} dependencies: adler-32: 1.3.1 crc-32: 1.2.2 dev: false /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1094,6 +1155,11 @@ /clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} dev: false /codepage@1.15.0: resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} engines: {node: '>=0.8'} dev: false /color-convert@2.0.1: @@ -1123,8 +1189,18 @@ resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} dev: true /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: false /countup.js@1.9.3: resolution: {integrity: sha512-UHf2P/mFKaESqdPq+UdBJm/1y8lYdlcDd0nTZHNC8cxWoJwZr1Eldm1PpWui446vDl5Pd8PtRYkr3q6K4+Qa5A==} dev: false /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} hasBin: true dev: false /crypto-js@4.2.0: @@ -1142,8 +1218,19 @@ type: 2.7.3 dev: false /dayjs@1.11.11: resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} /dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} dev: false /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true dependencies: ms: 2.0.0 dev: false /debug@4.3.5: @@ -1157,6 +1244,16 @@ dependencies: ms: 2.1.2 dev: true /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} dev: false /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} dev: false /diagram-js-direct-editing@2.1.2(diagram-js@11.13.1): resolution: {integrity: sha512-VpccLAnLqLF1cp3fk363QUbRVTd/qTcj2oOb+IqgcmOiWszJp7J9Ta6y5GjUvw48hDZpzCatlmWwA4CJ3MaYGQ==} @@ -1197,8 +1294,12 @@ resolution: {integrity: sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==} dev: false /element-plus@2.7.6(vue@3.4.30): resolution: {integrity: sha512-36sw1K23hYjgeooR10U6CiCaCp2wvOqwoFurADZVlekeQ9v5U1FhJCFGEXO6i/kZBBMwsE1c9fxjLs9LENw2Rg==} /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false /element-plus@2.9.7(vue@3.4.30): resolution: {integrity: sha512-6vjZh5SXBncLhUwJGTVKS5oDljfgGMh6J4zVTeAZK3YdMUN76FgpvHkwwFXocpJpMbii6rDYU3sgie64FyPerQ==} peerDependencies: vue: ^3.2.0 dependencies: @@ -1210,7 +1311,7 @@ '@types/lodash-es': 4.17.12 '@vueuse/core': 9.13.0(vue@3.4.30) async-validator: 4.2.5 dayjs: 1.11.11 dayjs: 1.11.13 escape-html: 1.0.3 lodash: 4.17.21 lodash-es: 4.17.21 @@ -1220,6 +1321,16 @@ vue: 3.4.30 transitivePeerDependencies: - '@vue/composition-api' dev: false /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} dev: false /encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} dev: false /entities@4.5.0: @@ -1306,6 +1417,11 @@ /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} /etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} dev: false /event-emitter@0.3.5: resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} dependencies: @@ -1353,6 +1469,16 @@ optional: true dev: false /frac@1.1.2: resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} engines: {node: '>=0.8'} dev: false /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} dev: false /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1361,6 +1487,16 @@ jsonfile: 6.1.0 universalify: 2.0.1 dev: true /fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} dependencies: at-least-node: 1.0.0 graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 dev: false /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} @@ -1379,7 +1515,6 @@ /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: true /hammerjs@2.0.8: resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} @@ -1399,6 +1534,17 @@ resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} dev: false /http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} dependencies: depd: 2.0.0 inherits: 2.0.4 setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 dev: false /i18next@20.6.1: resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} dependencies: @@ -1407,6 +1553,10 @@ /ids@1.0.5: resolution: {integrity: sha512-XQ0yom/4KWTL29sLG+tyuycy7UmeaM/79GRtSJq6IG9cJGIPeBz5kwDCguie3TwxaMNIc3WtPi0cTa1XYHicpw==} dev: false /immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} dev: false /immer@9.0.21: @@ -1419,6 +1569,10 @@ /inherits-browser@0.1.0: resolution: {integrity: sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==} dev: false /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false /is-binary-path@2.1.0: @@ -1458,6 +1612,10 @@ resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} dev: false /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: false /js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} dev: false @@ -1481,7 +1639,21 @@ universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 dev: true /jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} dependencies: lie: 3.3.0 pako: 1.0.11 readable-stream: 2.3.8 setimmediate: 1.0.5 dev: false /lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} dependencies: immediate: 3.0.6 dev: false /local-pkg@0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} @@ -1584,6 +1756,12 @@ wildcard: 1.1.2 dev: false /mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true dev: false /min-dash@4.2.1: resolution: {integrity: sha512-to+unsToePnm7cUeR9TrMzFlETHd/UXmU+ELTRfWZj5XGT41KF6X3L233o3E/GdEs3sk2Tbw/lOLD1avmWkg8A==} dev: false @@ -1594,6 +1772,10 @@ component-event: 0.2.1 domify: 1.4.2 min-dash: 4.2.1 dev: false /mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} dev: false /mlly@1.7.1: @@ -1623,9 +1805,17 @@ resolution: {integrity: sha512-/CaclMHKQ3A6rnzBzOADfwdSJ25BFoFT0Emxsc4zYVyav5SkK9iA6lEtIeuN/oRYbwPgviJT+t3l+sjFa28jYg==} dev: false /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false /namespace-emitter@2.0.1: resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==} @@ -1655,6 +1845,22 @@ /object-refs@0.3.0: resolution: {integrity: sha512-eP0ywuoWOaDoiake/6kTJlPJhs+k0qNm4nYRzXLNHj6vh+5M3i9R1epJTdxIPGlhWc4fNRQ7a6XJNCX+/L4FOQ==} dev: false /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 dev: false /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} dev: false /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} dev: false /path-intersection@2.2.1: @@ -1704,6 +1910,10 @@ engines: {node: '>=6'} dev: false /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: false /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true @@ -1712,12 +1922,33 @@ resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==} dev: false /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} dev: false /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: core-util-is: 1.0.3 inherits: 2.0.4 isarray: 1.0.0 process-nextick-args: 2.0.1 safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 dev: false /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 dev: true /reconnecting-websocket@4.4.0: resolution: {integrity: sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==} dev: false /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -1760,6 +1991,10 @@ queue-microtask: 1.2.3 dev: true /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: false /sass@1.77.6: resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} engines: {node: '>=14.0.0'} @@ -1783,6 +2018,47 @@ /scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} dev: true /send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} dependencies: debug: 2.6.9 depd: 2.0.0 destroy: 1.2.0 encodeurl: 1.0.2 escape-html: 1.0.3 etag: 1.8.1 fresh: 0.5.2 http-errors: 2.0.0 mime: 1.6.0 ms: 2.1.3 on-finished: 2.4.1 range-parser: 1.2.1 statuses: 2.0.1 transitivePeerDependencies: - supports-color dev: false /serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 send: 0.19.0 transitivePeerDependencies: - supports-color dev: false /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} dev: false /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: false /slate-history@0.66.0(slate@0.72.8): resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==} @@ -1833,8 +2109,26 @@ deprecated: Please use @jridgewell/sourcemap-codec instead dev: true /ssf@0.11.2: resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} engines: {node: '>=0.8'} dependencies: frac: 1.1.2 dev: false /ssr-window@3.0.0: resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==} dev: false /statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} dev: false /string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: safe-buffer: 5.1.2 dev: false /strip-literal@1.3.0: @@ -1880,6 +2174,11 @@ is-number: 7.0.0 dev: true /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} dev: false /type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} dev: false @@ -1909,7 +2208,6 @@ /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} dev: true /unplugin-auto-import@0.11.5: resolution: {integrity: sha512-nvbL2AQwLRR8wbHpJ6L1EBVNmjN045RSedTa4NtsGRkSQFXkI1iKHs4dTqJwcKZsnFrZOAKtLPiN1/oQTObLZw==} @@ -1939,6 +2237,10 @@ webpack-sources: 3.2.3 webpack-virtual-modules: 0.6.2 dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false /vite-plugin-compression@0.5.1(vite@5.3.1): resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} @@ -2071,3 +2373,27 @@ /wildcard@1.1.2: resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==} dev: false /wmf@1.0.2: resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} engines: {node: '>=0.8'} dev: false /word@0.3.0: resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} engines: {node: '>=0.8'} dev: false /xlsx@0.18.5: resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} engines: {node: '>=0.8'} hasBin: true dependencies: adler-32: 1.3.1 cfb: 1.2.2 codepage: 1.15.0 crc-32: 1.2.2 ssf: 0.11.2 wmf: 1.0.2 word: 0.3.0 dev: false src/components/map-container/mapContainer.vue
New file @@ -0,0 +1,154 @@ <!-- * @Author: shuishen 1109946754@qq.com * @Date: 2024-10-25 15:07:51 * @LastEditors: shuishen 1109946754@qq.com * @LastEditTime: 2025-04-10 13:04:30 * @FilePath: \drone-web-manage\src\components\map-container\MapContainer.vue * @Description: * * Copyright (c) 2024 by shuishen, All Rights Reserved. --> <template> <div class="map-container"> <div class="viewer-container" id="viewer-container"> <div class="content"> <slot name="content"></slot> </div> </div> </div> </template> <script setup> import { nextTick, onMounted, onUnmounted } from 'vue' window.$viewer = null window.$Cesium = null let pointLayer = null const { VITE_APP_BASE } = import.meta.env // import * as Cesium from 'cesium' // import 'cesium/Build/Cesium/Widgets/widgets.css' const isViewerReady = ref(false) const { rowDetails } = defineProps({ rowDetails: { type: Object, default: () => ({}), } }) watch( [() => isViewerReady.value, () => rowDetails], ([ready, detail]) => { if (ready && detail?.location) { const [lng, lat] = detail.location if (!lng || !lat) return window.$viewer?.zoomToPosition(new DC.Position( lng, lat, 1000, 0, -90, 0 ), () => { }) let point = new DC.Point(new DC.Position(lng, lat)) pointLayer.addOverlay(point) } }, { deep: true, immediate: true } // 初始化时立即执行 ) function initMap () { if (window.$viewer) return nextTick(() => { DC.ready({ // Cesium: Cesium, baseUrl: `${VITE_APP_BASE}/libs/dc-sdk/resources/`, }).then(() => { window.$Cesium = DC.getLib('Cesium') // 天地图地图 const imageryProvider_standZh = new window.$Cesium.UrlTemplateImageryProvider({ url: 'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], maximumLevel: 18, credit: 'stand_zj', }) const imageryProvider_stand = new window.$Cesium.UrlTemplateImageryProvider({ url: 'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], // format: 'image/jpeg', // show: true, maximumLevel: 18, credit: 'stand_tc', }) window.$viewer = new DC.Viewer('viewer-container') window.$viewer.locationBar.enable = false window.$viewer?.imageryLayers.addImageryProvider(imageryProvider_stand) window.$viewer?.imageryLayers.addImageryProvider(imageryProvider_standZh) pointLayer = new DC.VectorLayer('pointLayer') window.$viewer?.addLayer(pointLayer) isViewerReady.value = true }) }) } onMounted(() => { initMap() }) onUnmounted(() => { if (pointLayer) { window.$viewer?.removeLayer(pointLayer) pointLayer = null } window.$viewer?.entities.removeAll() window.$viewer?.imageryLayers.removeAll() window.$viewer?.dataSources.removeAll() let gl = window.$viewer.scene.context._originalGLContext gl.canvas.width = 1 gl.canvas.height = 1 window.$viewer && window.$viewer.setTerrain() window.$viewer && window.$viewer.destroy() window.$viewer = null delete window.$viewer window.$Cesium = null delete window.$Cesium var cesiumContainer = document.getElementById('viewer-container') if (cesiumContainer) { cesiumContainer.remove() // 移除与地图相关的DOM元素 } }) </script> <script> export default { name: 'MapContainer' } </script> <style lang="scss" scoped> .map-container { position: relative; width: 100% !important; height: 100% !important; overflow: hidden; } .viewer-container { position: absolute; top: 50%; left: 50%; width: 120%; height: 120%; transform: translate(-50%, -50%); } </style> src/main.js
@@ -1,34 +1,51 @@ import { createApp } from 'vue'; import website from './config/website'; import axios from './axios'; import router from './router/'; import store from './store'; import i18n from './lang/'; import { language, messages } from './lang/'; import * as ElementPlusIconsVue from '@element-plus/icons-vue'; import ElementPlus from 'element-plus'; import 'element-plus/dist/index.css'; import Avue from '@smallwei/avue'; import '@smallwei/avue/lib/index.css'; import crudCommon from '@/mixins/crud.js'; import { getScreen } from './utils/util'; /* * @Author: shuishen 1109946754@qq.com * @Date: 2025-04-10 11:19:47 * @LastEditors: shuishen 1109946754@qq.com * @LastEditTime: 2025-04-10 12:19:47 * @FilePath: \drone-web-manage\src\main.js * @Description: * * Copyright (c) 2025 by shuishen, All Rights Reserved. */ import { createApp } from 'vue' import website from './config/website' import axios from './axios' import router from './router/' import store from './store' import i18n from './lang/' import { language, messages } from './lang/' import * as ElementPlusIconsVue from '@element-plus/icons-vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import Avue from '@smallwei/avue' import '@smallwei/avue/lib/index.css' import crudCommon from '@/mixins/crud.js' import { getScreen } from './utils/util' import { getUrlParams, validatenull } from './utils/validate' import { setToken, setRefreshToken } from './utils/auth'; import { setStore } from './utils/store'; import './permission'; import error from './error'; import avueUeditor from 'avue-plugin-ueditor'; import basicBlock from 'components/basic-block/main.vue'; import basicContainer from 'components/basic-container/main.vue'; import thirdRegister from './components/third-register/main.vue'; import NfDesignBase from '@saber/nf-design-base-elp'; import flowDesign from './components/flow-design/main.vue'; import App from './App.vue'; import 'animate.css'; import dayjs from 'dayjs'; import 'styles/common.scss'; import { setToken, setRefreshToken } from './utils/auth' import { setStore } from './utils/store' import './permission' import error from './error' import avueUeditor from 'avue-plugin-ueditor' import basicBlock from 'components/basic-block/main.vue' import basicContainer from 'components/basic-container/main.vue' import thirdRegister from './components/third-register/main.vue' import NfDesignBase from '@saber/nf-design-base-elp' import flowDesign from './components/flow-design/main.vue' import App from './App.vue' import 'animate.css' import dayjs from 'dayjs' import 'styles/common.scss' // 业务组件 import tenantPackage from './views/system/tenantpackage.vue'; import tenantPackage from './views/system/tenantpackage.vue' // 地图依赖 import mapContainer from './components/map-container/mapContainer.vue' import * as DC from '@dvgis/dc-sdk' import '@dvgis/dc-sdk/dist/dc.min.css' window.DC = Object.create(DC) // 获取url中是否存在token const urlParams = getUrlParams(window.location.href) @@ -39,14 +56,14 @@ setToken(urlParams.token) setRefreshToken(urlParams.token) // 设置用户信息,把大屏用户信息保存到localStorage let obj = {}; obj = localStorage.getItem("bs_userInfo"); let obj = {} obj = localStorage.getItem("bs_userInfo") if (obj instanceof Object) { obj = obj.content } else { obj = JSON.parse(obj).content } setStore({ name: 'userInfo', content: obj }); setStore({ name: 'userInfo', content: obj }) location.reload() } else { if (localStorage.getItem("isReload")) { @@ -55,32 +72,34 @@ } window.$crudCommon = crudCommon; window.axios = axios; const app = createApp(App); window.$crudCommon = crudCommon window.axios = axios const app = createApp(App) for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component); app.component(key, component) } app.component('basicContainer', basicContainer); app.component('basicBlock', basicBlock); app.component('thirdRegister', thirdRegister); app.component('flowDesign', flowDesign); app.component('tenantPackage', tenantPackage); app.config.globalProperties.$dayjs = dayjs; app.config.globalProperties.website = website; app.config.globalProperties.getScreen = getScreen; app.use(error); app.use(i18n); app.use(store); app.use(router); app.component('basicContainer', basicContainer) app.component('basicBlock', basicBlock) app.component('thirdRegister', thirdRegister) app.component('flowDesign', flowDesign) app.component('tenantPackage', tenantPackage) app.component('mapContainer', mapContainer) app.config.globalProperties.$dayjs = dayjs app.config.globalProperties.website = website app.config.globalProperties.getScreen = getScreen app.use(error) app.use(i18n) app.use(store) app.use(router) app.use(ElementPlus, { locale: messages[language], }); }) app.use(Avue, { axios, calcHeight: 10, locale: messages[language], }); }) app.use(avueUeditor, { axios }) app.use(NfDesignBase); app.mount('#app'); app.use(NfDesignBase) app.mount('#app') src/views/tickets/ticket.vue
@@ -8,15 +8,19 @@ <el-input v-model="filters.keyword" placeholder="请输入关键字" class="filter-item" clearable @keyup.enter="handleSearch" /> <el-select v-model="filters.department" placeholder="请选择所属单位" class="filter-item" clearable> <el-option v-for="item in departments" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in departments" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-select v-model="filters.type" placeholder="请选择工单类型" class="filter-item" clearable> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" class="date-picker" value-format="yyyy-MM-dd" /> <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" class="date-picker" value-format="yyyy-MM-dd" /> <el-select v-model="filters.status" placeholder="请选择状态" class="filter-item" clearable> <el-option v-for="item in statuses" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in statuses" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button> <el-button icon="el-icon-refresh" @click="handleReset">重置</el-button> @@ -63,7 +67,8 @@ <el-col :span="12"> <el-form-item label="工单类型" prop="type"> <el-select v-model="form.type" placeholder="请选择工单类型" class="full-width"> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> @@ -71,16 +76,19 @@ <el-row :gutter="12"> <el-col :span="12"> <el-form-item label="所属部门" prop="department"> <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange" class="full-width"> <el-option v-for="dept in departments" :key="dept.value" :label="dept.label" :value="dept.value" /> <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange" class="full-width"> <el-option v-for="dept in departments" :key="dept.value" :label="dept.label" :value="dept.value" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="处理人员" prop="handler"> <el-select v-model="form.handler" placeholder="请选择处理人员" :disabled="!form.department" class="full-width"> <el-option v-for="user in availableHandlers" :key="user.id" :label="user.name" :value="user.id" /> <el-select v-model="form.handler" placeholder="请选择处理人员" :disabled="!form.department" class="full-width"> <el-option v-for="user in availableHandlers" :key="user.id" :label="user.name" :value="user.id" /> </el-select> </el-form-item> </el-col> @@ -89,7 +97,8 @@ <el-col :span="12"> <el-form-item label="关联算法" prop="algorithm"> <el-select v-model="form.algorithm" placeholder="请选择关联算法" class="full-width"> <el-option v-for="item in algorithms" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in algorithms" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> @@ -104,12 +113,8 @@ <el-form-item label="地图选址" prop="location"> <div class="map-select"> <!-- 替换地图为按钮 --> <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange" type="button" > <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange" type="button"> <el-button type="primary" plain> <i class="el-icon-map-location"></i> 选择位置 </el-button> @@ -130,21 +135,13 @@ <div class="form-section"> <div class="section-title">工单内容</div> <el-form-item label="工单描述" prop="content"> <el-input type="textarea" v-model="form.content" rows="3" placeholder="请输入工单内容描述" resize="none"></el-input> <el-input type="textarea" v-model="form.content" rows="3" placeholder="请输入工单内容描述" resize="none"></el-input> </el-form-item> <el-form-item label="附件图片" class="upload-item"> <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card" :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload" :file-list="form.photos" :limit="1" accept="image/*" > <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card" :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload" :file-list="form.photos" :limit="1" accept="image/*"> <i class="el-icon-plus"></i> </el-upload> <div class="el-upload__tip">支持jpg/png格式图片,最多1张,单张不超过5MB</div> @@ -165,18 +162,12 @@ <!-- 工单状态流程 --> <div class="status-flow"> <el-steps :active="currentDetail.status" align-center finish-status="success"> <el-step title="发起任务" :description="currentDetail.creator || '未知创建人'" /> <el-step title="发起任务" :description="currentDetail.creator || '未知创建人'" /> <el-step title="待审核" /> <el-step title="待处理" /> <el-step title="处理中" /> <el-step title="已完成" /> <el-step title="已完结" :description="currentDetail.handler || '未分配'" /> <el-step title="已完结" :description="currentDetail.handler || '未分配'" /> </el-steps> </div> @@ -199,7 +190,8 @@ </template> <template v-else-if="currentDetail.status === 2 && row.label2 === '工单类型'"> <el-select v-model="currentDetail.type" placeholder="请选择工单类型"> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </template> <template v-else>{{ row.value2 }}</template> @@ -210,30 +202,17 @@ <!-- 事件处理详情 --> <div v-if="[3, 4, 5].includes(currentDetail.status)" class="form-section"> <div class="section-title">事件处理详情</div> <el-input type="textarea" v-model="currentDetail.processingDetail" :disabled="currentDetail.status !== 3" placeholder="请输入事件处理详情" rows="4" style="width: 100%; margin-bottom: 10px;" /> <el-input type="textarea" v-model="currentDetail.processingDetail" :disabled="currentDetail.status !== 3" placeholder="请输入事件处理详情" rows="4" style="width: 100%; margin-bottom: 10px;" /> </div> <!-- 上传图片 --> <div v-if="[3, 4].includes(currentDetail.status)" class="form-section"> <div class="section-title">上传图片</div> <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card" :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload" :file-list="[]" accept="image/*" > <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card" :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload" :file-list="[]" accept="image/*"> <i class="el-icon-plus"></i> </el-upload> <div class="el-upload__tip">支持 jpg/png 格式图片,最多 5 张,单张不超过 5MB</div> @@ -246,13 +225,9 @@ <div class="media-box"> <div class="media-title">事件图片/事件视频</div> <div class="media-content"> <el-image v-if="currentDetail.mediaUrl" :src="currentDetail.mediaUrl" :preview-src-list="[currentDetail.mediaUrl]" fit="cover" style="width: 100%; height: 300px;" > <el-image v-if="currentDetail.mediaUrl" :src="currentDetail.mediaUrl" :preview-src-list="[currentDetail.mediaUrl]" fit="cover" style="width: 100%; height: 300px;"> <template #placeholder> <div class="image-placeholder"> <i class="el-icon-picture-outline"></i> @@ -276,7 +251,7 @@ <div class="media-content"> <div id="map-container" style="width: 100%; height: 300px; background: #f5f5f5;"> <!-- 地图容器 --> <span>地图功能待实现</span> <map-container v-if='detailVisible' :rowDetails="currentDetail"></map-container> </div> </div> </div> @@ -319,8 +294,8 @@ </template> <script> import { getList, createTicket, getTicketInfo } from '@/api/tickets/ticket'; import { export_json_to_excel } from '@/utils/exportExcel'; import { getList, createTicket, getTicketInfo } from '@/api/tickets/ticket' import { export_json_to_excel } from '@/utils/exportExcel' export default { name: "TicketPage", @@ -426,18 +401,18 @@ zoom: 15, center: [115.861365, 28.621311], // 默认中心点 }, }; } }, created() { this.loadAMapScripts(); this.fetchDropdownData(); this.loadAMapScripts() this.fetchDropdownData() }, mounted() { this.fetchTableData(); this.fetchTableData() }, computed: { availableHandlers() { return this.form.department ? (this.departmentUsers[this.form.department] || []) : []; return this.form.department ? (this.departmentUsers[this.form.department] || []) : [] }, detailTableData() { return [ @@ -495,7 +470,7 @@ editable: this.currentDetail.status === 2, type: "textarea", }, ]; ] }, detailFields() { return [ @@ -509,7 +484,7 @@ { label: "任务接收单位", value: this.currentDetail.department, editable: false }, { label: "发起任务时间", value: this.currentDetail.startTime, editable: false }, { label: "工单内容", value: this.currentDetail.remark, editable: this.currentDetail.status === 2, type: "textarea" }, ]; ] }, formattedDetailFields() { const fields = [ @@ -523,67 +498,67 @@ { label: "任务接收单位", value: this.currentDetail.department }, { label: "发起任务时间", value: this.currentDetail.startTime }, { label: "工单内容", value: this.currentDetail.remark }, ]; ] // 将字段分成两列 const formattedFields = []; const formattedFields = [] for (let i = 0; i < fields.length; i += 2) { formattedFields.push({ label1: fields[i]?.label || "", value1: fields[i]?.value || "暂无数据", label2: fields[i + 1]?.label || "", value2: fields[i + 1]?.value || "暂无数据", }); }) } return formattedFields; return formattedFields }, }, methods: { async loadAMapScripts() { try { this.mapLoaded = true; this.mapLoaded = true } catch (error) { console.error('Failed to load AMap scripts:', error); this.$message.error('地图加载失败,请检查网络或API Key配置'); console.error('Failed to load AMap scripts:', error) this.$message.error('地图加载失败,请检查网络或API Key配置') } }, async fetchDropdownData() { try { const response = await getTicketInfo(); const { dept_data, event_type, ai_type } = response.data.data; const response = await getTicketInfo() const { dept_data, event_type, ai_type } = response.data.data this.departments = dept_data.map(item => ({ label: item.dept_name, value: item.id, })); })) this.departmentUsers = dept_data.reduce((acc, dept) => { acc[dept.id] = dept.user_data || []; return acc; }, {}); acc[dept.id] = dept.user_data || [] return acc }, {}) this.types = Object.entries(event_type).map(([key, value]) => ({ label: value, value: key, })); })) this.algorithms = ai_type.map(item => ({ label: item.dict_value, value: item.dict_key, })); })) } catch (error) { console.error('获取下拉框数据失败:', error); this.$message.error('加载下拉框数据失败'); console.error('获取下拉框数据失败:', error) this.$message.error('加载下拉框数据失败') } }, async fetchTableData() { if (this.isFetching) return; this.isFetching = true; this.loading = true; if (this.isFetching) return this.isFetching = true this.loading = true try { const currentTab = this.tabs.find(tab => tab.name === this.activeTab); const currentTab = this.tabs.find(tab => tab.name === this.activeTab) const params = { word_order_type: this.filters.type || undefined, status: currentTab?.name === 'myTickets' ? undefined : @@ -595,32 +570,32 @@ end_date: this.filters.dateRange?.[1] ? this.formatDate(this.filters.dateRange[1]).replace("00:00:00", "23:59:59") : undefined, current: parseInt(this.page.currentPage), // 确保是数字 size: parseInt(this.page.pageSize) // 确保是数字 }; } const param = ref({ zoom: 10, // zoomEnable: false, // dragEnable: false, }); }) const form = ref([113.10235504165291, 41.03624227495205, "内蒙古自治区乌兰察布市集宁区新体路街道顺达源广告传媒"]); const response = await getList(params); const form = ref([113.10235504165291, 41.03624227495205, "内蒙古自治区乌兰察布市集宁区新体路街道顺达源广告传媒"]) const response = await getList(params) if (!response?.data?.data?.records) { throw new Error('接口返回数据格式不正确'); throw new Error('接口返回数据格式不正确') } const { total, records } = response.data.data; let filteredRecords = records; const { total, records } = response.data.data let filteredRecords = records // 如果是"我发起的"tab,过滤数据 if (currentTab?.name === 'myTickets') { filteredRecords = records.filter(item => String(item.create_user_id) === String(item.user_id) ); ) } this.tableData = filteredRecords.map(item => { const longitude = Number(item.longitude) || 0; const latitude = Number(item.latitude) || 0; const longitude = Number(item.longitude) || 0 const latitude = Number(item.latitude) || 0 return { id: item.id, orderNumber: item.event_num , // 修改这里:优先使用 event_num @@ -640,34 +615,34 @@ photo_url: item.photo_url || '', // 保存原始 photo_url video_url: item.video_url || '', // 保存原始 video_url location: (!isNaN(longitude) && !isNaN(latitude)) ? [longitude, latitude] : null, }; }); } }) // 更新总数显示 if (currentTab?.name === 'myTickets') { this.page.total = filteredRecords.length; this.page.total = filteredRecords.length } else { this.page.total = total || 0; this.page.total = total || 0 } if (this.activeTab === 'all') { // 计算"我发起的"工单数量 const myTicketsCount = records.filter(item => String(item.create_user_id) === String(item.user_id) ).length; ).length // 更新全局计数,包括"我发起的"数量 this.updateGlobalCounts(records, total, myTicketsCount); this.updateGlobalCounts(records, total, myTicketsCount) } this.updateTabCounts(); this.updateTabCounts() } catch (error) { console.error("获取数据失败:", error); this.$message.error(error.message || "获取数据失败"); this.tableData = []; this.page.total = 0; console.error("获取数据失败:", error) this.$message.error(error.message || "获取数据失败") this.tableData = [] this.page.total = 0 } finally { this.loading = false; this.isFetching = false; this.loading = false this.isFetching = false } }, @@ -675,8 +650,8 @@ this.$refs.form.validate(async (valid) => { if (valid) { if (!this.form.location || this.form.location.length < 2) { this.$message.warning('请在地图上选择位置'); return; this.$message.warning('请在地图上选择位置') return } try { @@ -693,56 +668,56 @@ updateUser: this.form.handler, createDept: this.form.department, // 添加所属部门ID isDraft: 0 }; } // 获取文件对象 let file = null; let file = null if (this.form.photos && this.form.photos.length > 0) { file = this.form.photos[0].raw; file = this.form.photos[0].raw } const response = await createTicket(submitData, file); const response = await createTicket(submitData, file) if (response.data.code === 0) { this.$message.success('工单创建成功'); this.dialogVisible = false; this.fetchTableData(); this.$message.success('工单创建成功') this.dialogVisible = false this.fetchTableData() } else { throw new Error(response.data.msg || '创建失败'); throw new Error(response.data.msg || '创建失败') } } catch (error) { console.error('提交失败:', error); this.$message.error(error.message || '工单创建失败,请稍后重试'); console.error('提交失败:', error) this.$message.error(error.message || '工单创建失败,请稍后重试') } } }); }) }, async handleLocationChange(val) { console.log('地图选址返回值:', val); console.log('地图选址返回值:', val) // 处理 Proxy 对象的值 let locationValue = val.value; let locationValue = val.value if (locationValue && locationValue.length >= 3) { // 确保我们获取到实际的数组值 this.form.location = [locationValue[0], locationValue[1]]; this.form.address = locationValue[2] || ''; this.form.location = [locationValue[0], locationValue[1]] this.form.address = locationValue[2] || '' console.log('解析后的位置信息:', { 经度: this.form.location[0], 纬度: this.form.location[1], 地址: this.form.address }); }) } else { console.warn('无效的位置数据'); this.form.location = []; this.form.address = ''; console.warn('无效的位置数据') this.form.location = [] this.form.address = '' } }, formatDate(date) { if (!date) return undefined; const d = new Date(date); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} 00:00:00`; if (!date) return undefined const d = new Date(date) return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} 00:00:00` }, mapStatus(status) { @@ -752,8 +727,8 @@ 3: "处理中", 4: "已完成", 5: "已完结" }; return statusTextMap[status] || "未知状态"; } return statusTextMap[status] || "未知状态" }, getStatusTagType(status) { @@ -763,20 +738,20 @@ 3: "primary", 4: "success", 5: "danger", }; return statusMap[status] || "info"; } return statusMap[status] || "info" }, handleTabChange(tab) { this.activeTab = tab.props?.name || tab.name; this.filters.status = ""; this.page.currentPage = 1; this.fetchTableData(); this.activeTab = tab.props?.name || tab.name this.filters.status = "" this.page.currentPage = 1 this.fetchTableData() }, handleSearch() { this.page.currentPage = 1; this.fetchTableData(); this.page.currentPage = 1 this.fetchTableData() }, handleReset() { @@ -786,27 +761,27 @@ type: "", dateRange: [], status: "", }; this.page.currentPage = 1; this.fetchTableData(); } this.page.currentPage = 1 this.fetchTableData() }, currentChange(currentPage) { console.log('currentChange triggered, new page:', currentPage); console.log('currentChange triggered, new page:', currentPage) // 先更新页码,再请求数据 this.page.currentPage = currentPage; this.page.currentPage = currentPage this.$nextTick(() => { this.fetchTableData(); }); this.fetchTableData() }) }, sizeChange(pageSize) { console.log('sizeChange triggered, new size:', pageSize); this.page.pageSize = pageSize; this.page.currentPage = 1; console.log('sizeChange triggered, new size:', pageSize) this.page.pageSize = pageSize this.page.currentPage = 1 this.$nextTick(() => { this.fetchTableData(); }); this.fetchTableData() }) }, updateGlobalCounts(records, total, myTicketsCount) { @@ -818,36 +793,36 @@ completed: 0, closed: 0, myTickets: myTicketsCount || 0 // 添加"我发起的"计数 }; } records.forEach(item => { const tab = this.tabs.find(t => t.value === Number(item.status)); const tab = this.tabs.find(t => t.value === Number(item.status)) if (tab) { counts[tab.name] = (counts[tab.name] || 0) + 1; counts[tab.name] = (counts[tab.name] || 0) + 1 } }); }) this.globalCounts = counts; this.globalCounts = counts }, updateTabCounts() { if (this.activeTab === 'all') { this.tabs.forEach(tab => { tab.count = this.globalCounts[tab.name] || 0; }); tab.count = this.globalCounts[tab.name] || 0 }) } else { this.tabs.forEach(tab => { if (tab.name === this.activeTab) { tab.count = this.tableData.length; tab.count = this.tableData.length } else { tab.count = this.globalCounts[tab.name] || 0; tab.count = this.globalCounts[tab.name] || 0 } }); }) } }, handleAdd() { this.dialogVisible = true; this.dialogVisible = true }, resetForm() { @@ -861,34 +836,34 @@ address: '', content: '', photos: [], }; } if (this.$refs.form) { this.$refs.form.resetFields(); this.$refs.form.resetFields() } }, formatLocation(location) { if (!Array.isArray(location)) { return '未知位置'; return '未知位置' } return `${location[0].toFixed(6)}, ${location[1].toFixed(6)}`; return `${location[0].toFixed(6)}, ${location[1].toFixed(6)}` }, handleViewDetail(row) { // 添加调试日志 console.log('原始行数据:', row); console.log('原始行数据:', row) const mediaUrl = row.photo_url || row.video_url; const mediaUrl = row.photo_url || row.video_url console.log('媒体信息:', { photo_url: row.photo_url, video_url: row.video_url, mediaUrl: mediaUrl, rowData: JSON.stringify(row) // 添加完整行数据打印 }); }) const longitude = row.location?.[0] || '未知经度'; const latitude = row.location?.[1] || '未知纬度'; const addressWithCoordinates = `${row.address || '暂无地址信息'} (${longitude}, ${latitude})`; const longitude = row.location?.[0] || '未知经度' const latitude = row.location?.[1] || '未知纬度' const addressWithCoordinates = `${row.address || '暂无地址信息'} (${longitude}, ${latitude})` this.currentDetail = { ...row, @@ -896,36 +871,36 @@ photos: mediaUrl ? [{ url: mediaUrl }] : [], address: addressWithCoordinates, handler: row.handler || '未分配', // 设置处理人 }; this.detailVisible = true; } this.detailVisible = true }, openMap() { this.$message.info("地图选址功能暂未实现"); this.$message.info("地图选址功能暂未实现") }, handlePreview(file) { this.$message.info(`预览图片:${file.name}`); this.$message.info(`预览图片:${file.name}`) }, handleRemove(file) { this.$message.info(`移除图片:${file.name}`); this.$message.info(`移除图片:${file.name}`) }, refreshChange() { if (this.isFetching) return; this.fetchTableData(); if (this.isFetching) return this.fetchTableData() }, onLoad() { if (this.isFetching) return; this.fetchTableData(); if (this.isFetching) return this.fetchTableData() }, async exportData() { try { this.loading = true; const currentTab = this.tabs.find(tab => tab.name === this.activeTab); this.loading = true const currentTab = this.tabs.find(tab => tab.name === this.activeTab) // 使用与查询列表相同的参数构造逻辑 const params = { @@ -939,26 +914,26 @@ end_date: this.filters.dateRange?.[1] ? this.formatDate(this.filters.dateRange[1]) : undefined, current: 1, size: 10000 }; const response = await getList(params); if (!response?.data?.data?.records) { throw new Error('接口返回数据格式不正确'); } const { records } = response.data.data; const response = await getList(params) if (!response?.data?.data?.records) { throw new Error('接口返回数据格式不正确') } const { records } = response.data.data // 使用与查询列表相同的过滤逻辑 let filteredRecords = records; let filteredRecords = records if (currentTab?.name === 'myTickets') { filteredRecords = records.filter(item => String(item.create_user_id) === String(item.user_id) ); ) } const exportData = filteredRecords.map(item => { const longitude = Number(item.longitude) || 0; const latitude = Number(item.latitude) || 0; const longitude = Number(item.longitude) || 0 const latitude = Number(item.latitude) || 0 return { 工单编号: item.event_num || '', 工单名称: item.event_name || '', @@ -971,12 +946,12 @@ 创建人: item.create_user || '', 处理人: item.update_user || '', 工单状态: this.mapStatus(Number(item.status || 0)) }; }); } }) if (exportData.length === 0) { this.$message.warning('没有数据可供导出'); return; this.$message.warning('没有数据可供导出') return } const headers = [ @@ -991,75 +966,75 @@ '创建人', '处理人', '工单状态' ]; ] export_json_to_excel(headers, exportData, '工单数据'); this.$message.success('数据导出成功'); export_json_to_excel(headers, exportData, '工单数据') this.$message.success('数据导出成功') } catch (error) { console.error('导出失败:', error); this.$message.error(error.message || '导出失败,请稍后重试'); console.error('导出失败:', error) this.$message.error(error.message || '导出失败,请稍后重试') } finally { this.loading = false; this.loading = false } }, handleDepartmentChange(deptId) { this.form.handler = ''; this.form.handler = '' }, // 文件改变时的钩子 handleFileChange(file, fileList) { this.form.photos = fileList; this.currentDetail.photos = fileList; this.form.photos = fileList this.currentDetail.photos = fileList }, // 文件移除时的钩子 handleUploadRemove(file, fileList) { this.form.photos = fileList; this.currentDetail.photos = fileList; this.form.photos = fileList this.currentDetail.photos = fileList }, // 上传前的验证 beforeUpload(file) { const isImage = file.type.includes('image'); const isLt5M = file.size / 1024 / 1024 < 5; const isImage = file.type.includes('image') const isLt5M = file.size / 1024 / 1024 < 5 if (!isImage) { this.$message.error('只能上传图片文件!'); return false; this.$message.error('只能上传图片文件!') return false } if (!isLt5M) { this.$message.error('图片大小不能超过5MB!'); return false; this.$message.error('图片大小不能超过5MB!') return false } return true; return true }, approveTicket() { this.$message.success("工单已通过并派发"); this.$message.success("工单已通过并派发") }, rejectTicket() { this.$message.error("工单未通过"); this.$message.error("工单未通过") }, submitProcessing() { this.$message.success("处理详情已提交"); this.$message.success("处理详情已提交") }, markAsCompleted() { this.$message.success("工单已标记为完成"); this.$message.success("工单已标记为完成") }, completeTicket() { this.$message.success("工单已完成"); this.$message.success("工单已完成") }, }, watch: { tableData: { handler() { this.updateTabCounts(); this.updateTabCounts() }, deep: true }, } }; } </script> <style lang="scss" scoped> vite.config.mjs
@@ -1,19 +1,30 @@ import { defineConfig, loadEnv } from 'vite'; import { resolve } from 'path'; import createVitePlugins from './vite/plugins'; /* * @Author: shuishen 1109946754@qq.com * @Date: 2025-04-10 11:19:47 * @LastEditors: shuishen 1109946754@qq.com * @LastEditTime: 2025-04-10 12:23:50 * @FilePath: \drone-web-manage\vite.config.mjs * @Description: * * Copyright (c) 2025 by shuishen, All Rights Reserved. */ import { defineConfig, loadEnv } from 'vite' import { resolve } from 'path' import createVitePlugins from './vite/plugins' // https://vitejs.dev/config/ export default ({ mode, command }) => { const env = loadEnv(mode, process.cwd()); const { VITE_APP_ENV, VITE_APP_BASE, VITE_APP_URL } = env; const env = loadEnv(mode, process.cwd()) const { VITE_APP_ENV, VITE_APP_BASE, VITE_APP_URL } = env // 判断是打生产环境包 const isProd = VITE_APP_ENV === 'production'; const isProd = VITE_APP_ENV === 'production' // 根据是否生产环境,动态设置压缩配置 const buildConfig = { outDir: 'manage', target: 'esnext', minify: isProd ? 'terser' : 'esbuild', // 根据环境选择压缩工具 }; } // 如果是生产环境,添加Terser的配置 if (isProd) { @@ -25,7 +36,7 @@ format: { comments: false, // 删除所有注释 }, }; } } return defineConfig({ base: VITE_APP_BASE, @@ -62,5 +73,5 @@ target: 'esnext', }, }, }); }; }) } vite/plugins/index.js
@@ -1,13 +1,14 @@ import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue' import createAutoImport from './auto-import'; import createCompression from './compression'; import createSetupExtend from './setup-extend'; import createAutoImport from './auto-import' import createCompression from './compression' import createSetupExtend from './setup-extend' import DC from "@dvgis/vite-plugin-dc" export default function createVitePlugins(viteEnv, isBuild = false) { const vitePlugins = [vue()]; vitePlugins.push(createAutoImport()); vitePlugins.push(createSetupExtend()); isBuild && vitePlugins.push(...createCompression(viteEnv)); return vitePlugins; const vitePlugins = [vue(), DC()] vitePlugins.push(createAutoImport()) vitePlugins.push(createSetupExtend()) isBuild && vitePlugins.push(...createCompression(viteEnv)) return vitePlugins }