视频监控模块开发,地图模块管理开发
This commit is contained in:
parent
c960b57e0b
commit
e7658caa11
@ -12,8 +12,8 @@ VITE_APP_BASE_API = '/dev-api'
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||
# 汤伟
|
||||
# VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
||||
VITE_APP_BASE_URL = 'http://192.168.1.162:8093'
|
||||
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
||||
# VITE_APP_BASE_URL = 'http://192.168.1.162:8093'
|
||||
|
||||
# 测试环境线上
|
||||
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
"pinia": "^2.0.12",
|
||||
"screenfull": "^6.0.0",
|
||||
"sortablejs": "^1.14.0",
|
||||
"video.js": "^8.23.7",
|
||||
"videojs-contrib-hls": "^5.15.0",
|
||||
"vue": "^3.2.40",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-router": "^4.1.6",
|
||||
|
||||
@ -98,6 +98,12 @@ importers:
|
||||
sortablejs:
|
||||
specifier: ^1.14.0
|
||||
version: 1.15.7
|
||||
video.js:
|
||||
specifier: ^8.23.7
|
||||
version: 8.23.7
|
||||
videojs-contrib-hls:
|
||||
specifier: ^5.15.0
|
||||
version: 5.15.0
|
||||
vue:
|
||||
specifier: ^3.2.40
|
||||
version: 3.5.33(typescript@6.0.3)
|
||||
@ -865,6 +871,19 @@ packages:
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.3.3
|
||||
|
||||
'@videojs/http-streaming@3.17.4':
|
||||
resolution: {integrity: sha512-XAvdG2dolBuV2Fx8bu1kjmQ2D4TonGzZH68Pgv/O9xMSFWdZtITSMFismeQLEAtMmGwze8qNJp3RgV+jStrJqg==}
|
||||
engines: {node: '>=8', npm: '>=5'}
|
||||
peerDependencies:
|
||||
video.js: ^8.19.0
|
||||
|
||||
'@videojs/vhs-utils@4.1.1':
|
||||
resolution: {integrity: sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==}
|
||||
engines: {node: '>=8', npm: '>=5'}
|
||||
|
||||
'@videojs/xhr@2.7.0':
|
||||
resolution: {integrity: sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==}
|
||||
|
||||
'@vitejs/plugin-vue@4.6.2':
|
||||
resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
@ -1021,6 +1040,10 @@ packages:
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@xmldom/xmldom@0.8.13':
|
||||
resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
'@zarrita/storage@0.2.0':
|
||||
resolution: {integrity: sha512-855ZXqtnds7spnT8vNvD+MXa3QExP1m2GqShe8yt7uZXHnQLgJHgkpVwFjE1B0KDDRO0ki09hmk6OboTaIfPsQ==}
|
||||
|
||||
@ -1050,6 +1073,12 @@ packages:
|
||||
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
aes-decrypter@1.0.3:
|
||||
resolution: {integrity: sha512-rsx8pfx7wJsn+ziYbpJ8XA5c93hKAtBCrfydxJqJCMT+qfjipd/B5wC2xHtBcoxyvlqJcpeAo3K55t0lXOn9yQ==}
|
||||
|
||||
aes-decrypter@4.0.2:
|
||||
resolution: {integrity: sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==}
|
||||
|
||||
ajv@6.14.0:
|
||||
resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
|
||||
|
||||
@ -1173,6 +1202,9 @@ packages:
|
||||
axios@1.15.2:
|
||||
resolution: {integrity: sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==}
|
||||
|
||||
babel-runtime@6.26.0:
|
||||
resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==}
|
||||
|
||||
balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
@ -1350,6 +1382,10 @@ packages:
|
||||
resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
core-js@2.6.12:
|
||||
resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
|
||||
deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
|
||||
|
||||
core-js@3.49.0:
|
||||
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
|
||||
|
||||
@ -1534,6 +1570,9 @@ packages:
|
||||
dom-to-image@2.6.0:
|
||||
resolution: {integrity: sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==}
|
||||
|
||||
dom-walk@0.1.2:
|
||||
resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==}
|
||||
|
||||
dom7@3.0.0:
|
||||
resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==}
|
||||
|
||||
@ -1639,6 +1678,10 @@ packages:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
es5-shim@4.6.7:
|
||||
resolution: {integrity: sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
|
||||
|
||||
@ -1956,6 +1999,12 @@ packages:
|
||||
resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
global@4.3.2:
|
||||
resolution: {integrity: sha512-/4AybdwIDU4HkCUbJkZdWpe4P6vuw/CUtu+0I1YlLIPe7OlUO7KNJ+q/rO70CW2/NW6Jc6I62++Hzsf5Alu6rQ==}
|
||||
|
||||
global@4.4.0:
|
||||
resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==}
|
||||
|
||||
globals@13.24.0:
|
||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2099,6 +2148,9 @@ packages:
|
||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
individual@2.0.0:
|
||||
resolution: {integrity: sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==}
|
||||
|
||||
inflight@1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||
@ -2191,6 +2243,9 @@ packages:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-function@1.0.2:
|
||||
resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==}
|
||||
|
||||
is-generator-function@1.1.2:
|
||||
resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2480,6 +2535,12 @@ packages:
|
||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
m3u8-parser@2.1.0:
|
||||
resolution: {integrity: sha512-WbEpQ2FUaNGbJ0YanSeyj9D9ruu4FUvz+ZvebIzI2bSME+PUwcPXO1kKXZkjcPUAFruDikoOI5fWQNIA6JCCOQ==}
|
||||
|
||||
m3u8-parser@7.2.0:
|
||||
resolution: {integrity: sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==}
|
||||
|
||||
magic-string@0.25.9:
|
||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||
|
||||
@ -2564,6 +2625,9 @@ packages:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
min-document@2.19.2:
|
||||
resolution: {integrity: sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==}
|
||||
|
||||
min-indent@1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
@ -2585,6 +2649,10 @@ packages:
|
||||
moment@2.30.1:
|
||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||
|
||||
mpd-parser@1.3.1:
|
||||
resolution: {integrity: sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==}
|
||||
hasBin: true
|
||||
|
||||
ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
@ -2594,6 +2662,14 @@ packages:
|
||||
muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
|
||||
|
||||
mux.js@4.3.2:
|
||||
resolution: {integrity: sha512-g0q6DPdvb3yYcoK7ElBGobdSSrhY/RjPt19U7uUc733aqvc5bCS/aCvL9z+448y+IoCZnYDwyZfQBBXMSmGOaQ==}
|
||||
|
||||
mux.js@7.1.0:
|
||||
resolution: {integrity: sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==}
|
||||
engines: {node: '>=8', npm: '>=5'}
|
||||
hasBin: true
|
||||
|
||||
mz@2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
|
||||
@ -2816,6 +2892,15 @@ packages:
|
||||
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
pkcs7@0.2.3:
|
||||
resolution: {integrity: sha512-kJRwmADEQUg+qJyRgWLtpEL9q9cFjZschejTEK3GRjKvnsU9G5WWoe/wKqRgbBoqWdVSeTUKP6vIA3Y72M3rWA==}
|
||||
engines: {node: ^0.10, npm: ^1.4.6}
|
||||
hasBin: true
|
||||
|
||||
pkcs7@1.0.4:
|
||||
resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==}
|
||||
hasBin: true
|
||||
|
||||
posix-character-classes@0.1.1:
|
||||
resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -2920,6 +3005,14 @@ packages:
|
||||
process-nextick-args@2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
|
||||
process@0.11.10:
|
||||
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
process@0.5.2:
|
||||
resolution: {integrity: sha512-oNpcutj+nYX2FjdEW7PGltWhXulAnFlM0My/k48L90hARCOJtvBbQXc/6itV2jDvU5xAAtonP+r6wmQgCcbAUA==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
protobufjs@8.3.0:
|
||||
resolution: {integrity: sha512-JpJpFaR7yKNb6WqKvJJ1MLbiuIQWQnbUUb06nDtf2/i8YWYYLEfP6xf9BwSJoJQg1wAy61EQB8dssQg64oX4aA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@ -3005,6 +3098,9 @@ packages:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
regenerator-runtime@0.11.1:
|
||||
resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==}
|
||||
|
||||
regex-not@1.0.2:
|
||||
resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -3078,6 +3174,9 @@ packages:
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
rust-result@1.0.0:
|
||||
resolution: {integrity: sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==}
|
||||
|
||||
safe-array-concat@1.1.4:
|
||||
resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
|
||||
engines: {node: '>=0.4'}
|
||||
@ -3088,6 +3187,9 @@ packages:
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
safe-json-parse@4.0.0:
|
||||
resolution: {integrity: sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==}
|
||||
|
||||
safe-push-apply@1.0.0:
|
||||
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3464,6 +3566,10 @@ packages:
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
tsml@1.0.1:
|
||||
resolution: {integrity: sha512-3KmepnH9SUsoOVtg013CRrL7c+AK7ECaquAsJdvu4288EDJuraqBlP4PDXT/rLEJ9YDn4jqLAzRJsnFPx+V6lg==}
|
||||
deprecated: no longer maintained
|
||||
|
||||
tsutils@3.21.0:
|
||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -3559,6 +3665,9 @@ packages:
|
||||
resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
|
||||
deprecated: Please see https://github.com/lydell/urix#deprecated
|
||||
|
||||
url-toolkit@2.2.5:
|
||||
resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==}
|
||||
|
||||
use@3.1.1:
|
||||
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -3576,6 +3685,40 @@ packages:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
video.js@6.13.0:
|
||||
resolution: {integrity: sha512-36/JR/GhPQSZj0o+GNbhcEYv/b0SkV9SQsjlodAnzMQYN0TA7VhmqrKPYMCi1NGRYu7S9W3OaFCFoUxkYfSVlg==}
|
||||
|
||||
video.js@8.23.7:
|
||||
resolution: {integrity: sha512-cG4HOygYt+Z8j6Sf5DuK6OgEOoM+g9oGP6vpqoZRaD13aHE4PMITbyjJUXZcIQbgB0wJEadBRaVm5lJIzo2jAA==}
|
||||
|
||||
videojs-contrib-hls@5.15.0:
|
||||
resolution: {integrity: sha512-18zbMYZ0XRBKTPEayA9bFTWWrqhT9b4G8+zf0czJLD7Epe5PcK1I/3dflTHQeQ5rwlWir+/XnFU3sMg/B2MMcw==}
|
||||
engines: {node: '>= 0.10.12'}
|
||||
|
||||
videojs-contrib-media-sources@4.7.2:
|
||||
resolution: {integrity: sha512-e6iCHWBFuV05EGo7v+pS9iepObXnJ9joms467gzi8ZjpKVb3ifha9M0Ja24Rd8JfvYpzjltsgDVtGFDvIg4hQQ==}
|
||||
|
||||
videojs-contrib-quality-levels@4.1.0:
|
||||
resolution: {integrity: sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==}
|
||||
engines: {node: '>=16', npm: '>=8'}
|
||||
peerDependencies:
|
||||
video.js: ^8
|
||||
|
||||
videojs-font@2.1.0:
|
||||
resolution: {integrity: sha512-zFqWpLrXf1q8NtYx5qtZhMC6SLUFScDmR6j+UGPogobxR21lvXShhnzcNNMdOxJUuFLiToJ/BPpFUQwX4xhpvA==}
|
||||
|
||||
videojs-font@4.2.0:
|
||||
resolution: {integrity: sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==}
|
||||
|
||||
videojs-ie8@1.1.2:
|
||||
resolution: {integrity: sha512-0Zb2T4MLkpfZbeGMK/Z93b8Lrepr+rLFoHgQV1CoDeFqXvH7b+Vsd/VHoILGxQrgCSHFQ7mAODR6oyMjuiD4/g==}
|
||||
|
||||
videojs-vtt.js@0.12.6:
|
||||
resolution: {integrity: sha512-XFXeGBQiljnElMhwCcZst0RDbZn2n8LU7ZScXryd3a00OaZsHAjdZu/7/RdSr7Z1jHphd45FnOvOQkGK4YrWCQ==}
|
||||
|
||||
videojs-vtt.js@0.15.5:
|
||||
resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==}
|
||||
|
||||
vite-plugin-cesium@1.2.22:
|
||||
resolution: {integrity: sha512-OnS+VKNGck4kUu4/67Fdfhz0/zF9mDVNUp9hUWtX19C38O0mJsJy2MH1ev2QcrVLf6VieJ7vCGxkLchdB1n1HQ==}
|
||||
peerDependencies:
|
||||
@ -3679,6 +3822,9 @@ packages:
|
||||
web-worker@1.5.0:
|
||||
resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==}
|
||||
|
||||
webwackify@0.1.6:
|
||||
resolution: {integrity: sha512-pGcw1T3HpNnM/UTRQqqRkkkzythSLts05mB+7Gr00B+0VbL0m39dFL5g20rSIEUt9Wrpw+/8k+snxRlUFHhcqA==}
|
||||
|
||||
which-boxed-primitive@1.1.1:
|
||||
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3730,6 +3876,9 @@ packages:
|
||||
wujie@1.0.29:
|
||||
resolution: {integrity: sha512-u7PmBT4l5ov7ciwmZNG8DLIRKrYrnXDa0LnAFgRQikJ/ZrVZYzzSNz6duzEJoj8/o46dnMy/g9Hh/PBYGbgFUw==}
|
||||
|
||||
xhr@2.4.0:
|
||||
resolution: {integrity: sha512-TUbBsdAuJbX8olk9hsDwGK8P1ri1XlV+PdEWkYw+HQQbpkiBR8PLgD1F3kQDPBs9l4Px34hP9rCYAZOCCAENbw==}
|
||||
|
||||
xlsx@0.18.5:
|
||||
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
|
||||
engines: {node: '>=0.8'}
|
||||
@ -3738,6 +3887,10 @@ packages:
|
||||
xml-utils@1.10.2:
|
||||
resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==}
|
||||
|
||||
xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -4435,6 +4588,28 @@ snapshots:
|
||||
'@uppy/utils': 4.1.3
|
||||
nanoid: 3.3.11
|
||||
|
||||
'@videojs/http-streaming@3.17.4(video.js@8.23.7)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@videojs/vhs-utils': 4.1.1
|
||||
aes-decrypter: 4.0.2
|
||||
global: 4.4.0
|
||||
m3u8-parser: 7.2.0
|
||||
mpd-parser: 1.3.1
|
||||
mux.js: 7.1.0
|
||||
video.js: 8.23.7
|
||||
|
||||
'@videojs/vhs-utils@4.1.1':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
global: 4.4.0
|
||||
|
||||
'@videojs/xhr@2.7.0':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
global: 4.4.0
|
||||
is-function: 1.0.2
|
||||
|
||||
'@vitejs/plugin-vue@4.6.2(vite@4.5.14(@types/node@16.18.126)(sass@1.99.0))(vue@3.5.33(typescript@6.0.3))':
|
||||
dependencies:
|
||||
vite: 4.5.14(@types/node@16.18.126)(sass@1.99.0)
|
||||
@ -4662,6 +4837,8 @@ snapshots:
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@xmldom/xmldom@0.8.13': {}
|
||||
|
||||
'@zarrita/storage@0.2.0':
|
||||
dependencies:
|
||||
reference-spec-reader: 0.2.0
|
||||
@ -4686,6 +4863,17 @@ snapshots:
|
||||
|
||||
adler-32@1.3.1: {}
|
||||
|
||||
aes-decrypter@1.0.3:
|
||||
dependencies:
|
||||
pkcs7: 0.2.3
|
||||
|
||||
aes-decrypter@4.0.2:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@videojs/vhs-utils': 4.1.1
|
||||
global: 4.4.0
|
||||
pkcs7: 1.0.4
|
||||
|
||||
ajv@6.14.0:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
@ -4812,6 +5000,11 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
babel-runtime@6.26.0:
|
||||
dependencies:
|
||||
core-js: 2.6.12
|
||||
regenerator-runtime: 0.11.1
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
base@0.11.2:
|
||||
@ -5038,6 +5231,8 @@ snapshots:
|
||||
|
||||
copy-descriptor@0.1.1: {}
|
||||
|
||||
core-js@2.6.12: {}
|
||||
|
||||
core-js@3.49.0: {}
|
||||
|
||||
core-util-is@1.0.3: {}
|
||||
@ -5211,6 +5406,8 @@ snapshots:
|
||||
|
||||
dom-to-image@2.6.0: {}
|
||||
|
||||
dom-walk@0.1.2: {}
|
||||
|
||||
dom7@3.0.0:
|
||||
dependencies:
|
||||
ssr-window: 3.0.0
|
||||
@ -5387,6 +5584,8 @@ snapshots:
|
||||
esniff: 2.0.1
|
||||
next-tick: 1.1.0
|
||||
|
||||
es5-shim@4.6.7: {}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
@ -5797,6 +5996,16 @@ snapshots:
|
||||
dependencies:
|
||||
ini: 1.3.8
|
||||
|
||||
global@4.3.2:
|
||||
dependencies:
|
||||
min-document: 2.19.2
|
||||
process: 0.5.2
|
||||
|
||||
global@4.4.0:
|
||||
dependencies:
|
||||
min-document: 2.19.2
|
||||
process: 0.11.10
|
||||
|
||||
globals@13.24.0:
|
||||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
@ -5926,6 +6135,8 @@ snapshots:
|
||||
|
||||
indent-string@4.0.0: {}
|
||||
|
||||
individual@2.0.0: {}
|
||||
|
||||
inflight@1.0.6:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
@ -6021,6 +6232,8 @@ snapshots:
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-function@1.0.2: {}
|
||||
|
||||
is-generator-function@1.1.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@ -6263,6 +6476,14 @@ snapshots:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
m3u8-parser@2.1.0: {}
|
||||
|
||||
m3u8-parser@7.2.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@videojs/vhs-utils': 4.1.1
|
||||
global: 4.4.0
|
||||
|
||||
magic-string@0.25.9:
|
||||
dependencies:
|
||||
sourcemap-codec: 1.4.8
|
||||
@ -6352,6 +6573,10 @@ snapshots:
|
||||
|
||||
mimic-fn@2.1.0: {}
|
||||
|
||||
min-document@2.19.2:
|
||||
dependencies:
|
||||
dom-walk: 0.1.2
|
||||
|
||||
min-indent@1.0.1: {}
|
||||
|
||||
minimatch@3.1.5:
|
||||
@ -6373,12 +6598,26 @@ snapshots:
|
||||
|
||||
moment@2.30.1: {}
|
||||
|
||||
mpd-parser@1.3.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@videojs/vhs-utils': 4.1.1
|
||||
'@xmldom/xmldom': 0.8.13
|
||||
global: 4.4.0
|
||||
|
||||
ms@2.0.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
muggle-string@0.4.1: {}
|
||||
|
||||
mux.js@4.3.2: {}
|
||||
|
||||
mux.js@7.1.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
global: 4.4.0
|
||||
|
||||
mz@2.7.0:
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
@ -6598,6 +6837,12 @@ snapshots:
|
||||
|
||||
pirates@4.0.7: {}
|
||||
|
||||
pkcs7@0.2.3: {}
|
||||
|
||||
pkcs7@1.0.4:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
|
||||
posix-character-classes@0.1.1: {}
|
||||
|
||||
possible-typed-array-names@1.1.0: {}
|
||||
@ -6687,6 +6932,10 @@ snapshots:
|
||||
|
||||
process-nextick-args@2.0.1: {}
|
||||
|
||||
process@0.11.10: {}
|
||||
|
||||
process@0.5.2: {}
|
||||
|
||||
protobufjs@8.3.0:
|
||||
dependencies:
|
||||
long: 5.3.2
|
||||
@ -6775,6 +7024,8 @@ snapshots:
|
||||
get-proto: 1.0.1
|
||||
which-builtin-type: 1.2.1
|
||||
|
||||
regenerator-runtime@0.11.1: {}
|
||||
|
||||
regex-not@1.0.2:
|
||||
dependencies:
|
||||
extend-shallow: 3.0.2
|
||||
@ -6842,6 +7093,10 @@ snapshots:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
rust-result@1.0.0:
|
||||
dependencies:
|
||||
individual: 2.0.0
|
||||
|
||||
safe-array-concat@1.1.4:
|
||||
dependencies:
|
||||
call-bind: 1.0.9
|
||||
@ -6854,6 +7109,10 @@ snapshots:
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
safe-json-parse@4.0.0:
|
||||
dependencies:
|
||||
rust-result: 1.0.0
|
||||
|
||||
safe-push-apply@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@ -7317,6 +7576,8 @@ snapshots:
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
tsml@1.0.1: {}
|
||||
|
||||
tsutils@3.21.0(typescript@6.0.3):
|
||||
dependencies:
|
||||
tslib: 1.14.1
|
||||
@ -7421,6 +7682,8 @@ snapshots:
|
||||
|
||||
urix@0.1.0: {}
|
||||
|
||||
url-toolkit@2.2.5: {}
|
||||
|
||||
use@3.1.1: {}
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
@ -7434,6 +7697,71 @@ snapshots:
|
||||
|
||||
vary@1.1.2: {}
|
||||
|
||||
video.js@6.13.0:
|
||||
dependencies:
|
||||
babel-runtime: 6.26.0
|
||||
global: 4.3.2
|
||||
safe-json-parse: 4.0.0
|
||||
tsml: 1.0.1
|
||||
videojs-font: 2.1.0
|
||||
videojs-ie8: 1.1.2
|
||||
videojs-vtt.js: 0.12.6
|
||||
xhr: 2.4.0
|
||||
|
||||
video.js@8.23.7:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@videojs/http-streaming': 3.17.4(video.js@8.23.7)
|
||||
'@videojs/vhs-utils': 4.1.1
|
||||
'@videojs/xhr': 2.7.0
|
||||
aes-decrypter: 4.0.2
|
||||
global: 4.4.0
|
||||
m3u8-parser: 7.2.0
|
||||
mpd-parser: 1.3.1
|
||||
mux.js: 7.1.0
|
||||
videojs-contrib-quality-levels: 4.1.0(video.js@8.23.7)
|
||||
videojs-font: 4.2.0
|
||||
videojs-vtt.js: 0.15.5
|
||||
|
||||
videojs-contrib-hls@5.15.0:
|
||||
dependencies:
|
||||
aes-decrypter: 1.0.3
|
||||
global: 4.4.0
|
||||
m3u8-parser: 2.1.0
|
||||
mux.js: 4.3.2
|
||||
url-toolkit: 2.2.5
|
||||
video.js: 6.13.0
|
||||
videojs-contrib-media-sources: 4.7.2
|
||||
webwackify: 0.1.6
|
||||
|
||||
videojs-contrib-media-sources@4.7.2:
|
||||
dependencies:
|
||||
global: 4.4.0
|
||||
mux.js: 4.3.2
|
||||
video.js: 6.13.0
|
||||
webwackify: 0.1.6
|
||||
|
||||
videojs-contrib-quality-levels@4.1.0(video.js@8.23.7):
|
||||
dependencies:
|
||||
global: 4.4.0
|
||||
video.js: 8.23.7
|
||||
|
||||
videojs-font@2.1.0: {}
|
||||
|
||||
videojs-font@4.2.0: {}
|
||||
|
||||
videojs-ie8@1.1.2:
|
||||
dependencies:
|
||||
es5-shim: 4.6.7
|
||||
|
||||
videojs-vtt.js@0.12.6:
|
||||
dependencies:
|
||||
global: 4.4.0
|
||||
|
||||
videojs-vtt.js@0.15.5:
|
||||
dependencies:
|
||||
global: 4.4.0
|
||||
|
||||
vite-plugin-cesium@1.2.22(cesium@1.141.0)(rollup@3.30.0)(vite@4.5.14(@types/node@16.18.126)(sass@1.99.0)):
|
||||
dependencies:
|
||||
cesium: 1.141.0
|
||||
@ -7533,6 +7861,8 @@ snapshots:
|
||||
|
||||
web-worker@1.5.0: {}
|
||||
|
||||
webwackify@0.1.6: {}
|
||||
|
||||
which-boxed-primitive@1.1.1:
|
||||
dependencies:
|
||||
is-bigint: 1.1.0
|
||||
@ -7603,6 +7933,13 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
|
||||
xhr@2.4.0:
|
||||
dependencies:
|
||||
global: 4.3.2
|
||||
is-function: 1.0.2
|
||||
parse-headers: 2.0.6
|
||||
xtend: 4.0.2
|
||||
|
||||
xlsx@0.18.5:
|
||||
dependencies:
|
||||
adler-32: 1.3.1
|
||||
@ -7615,6 +7952,8 @@ snapshots:
|
||||
|
||||
xml-utils@1.10.2: {}
|
||||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yallist@4.0.0: {}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import request from '@/utils/request';
|
||||
import { SERVICE_URLS } from '../config'; // 引入配置
|
||||
// 基本情况介绍
|
||||
export function getBaseWbsb(data: any) {
|
||||
return request({
|
||||
url: SERVICE_URLS.lygk + '/base/wbsb/GetKendoList',
|
||||
url: '/dec-lygk-base-server/base/wbsb/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
|
||||
25
frontend/src/api/shiPinJianKong/index.ts
Normal file
25
frontend/src/api/shiPinJianKong/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import request from '@/utils/request';
|
||||
// 顶部tabs
|
||||
export function baseMsstbprpt(data: any) {
|
||||
return request({
|
||||
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 实时视频
|
||||
export function envVdTreeGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/api/wmp-env-server/env/vd/tree/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 录像
|
||||
export function envVdRunDataGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/api/wmp-env-server/env/vd/runData/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
1
frontend/src/assets/icons/fishxz.7410ec88.svg
Normal file
1
frontend/src/assets/icons/fishxz.7410ec88.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="14" height="12" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M14 0v10.998C14 11.55 13.55 12 12.993 12H0L14 0Z" fill="#2F6B98"/><path d="M7 5h6v6H7z"/><path d="M12.878 7.095a.335.335 0 0 1-.001.5l-3.414 3.027a.42.42 0 0 1-.368.096.38.38 0 0 1-.232-.123L7.096 8.633a.375.375 0 0 1 .558-.501l1.551 1.722 3.114-2.761a.42.42 0 0 1 .56.002Z" fill="#FFF"/></g></svg>
|
||||
|
After Width: | Height: | Size: 405 B |
@ -20,8 +20,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch, nextTick } from "vue";
|
||||
import { calcTableScrollY } from "@/utils/index";
|
||||
import { ref, computed, onMounted, watch, nextTick } from 'vue';
|
||||
import { calcTableScrollY } from '@/utils/index';
|
||||
|
||||
// --- Types ---
|
||||
interface Props {
|
||||
@ -39,18 +39,18 @@ interface Props {
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
enableRowSelection: false,
|
||||
rowKey: "id",
|
||||
rowKey: 'id',
|
||||
data: () => [],
|
||||
searchParams: () => ({}),
|
||||
defaultPageSize: 20,
|
||||
getCheckboxProps: undefined,
|
||||
transformData: undefined,
|
||||
scrollY: undefined,
|
||||
scrollY: undefined
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "data-loaded", params: any, data: any): void;
|
||||
(e: "selection-change", selectedRowKeys: string[], selectedRows: any[]): void;
|
||||
(e: 'data-loaded', params: any, data: any): void;
|
||||
(e: 'selection-change', selectedRowKeys: string[], selectedRows: any[]): void;
|
||||
}>();
|
||||
|
||||
// --- State ---
|
||||
@ -68,10 +68,11 @@ const tableScrollY = ref<number>(0); // ✅ 新增:存储容器高度
|
||||
// --- Computed Scroll Config ---
|
||||
const scrollConfig = computed(() => {
|
||||
const config: any = {
|
||||
x: "100%",
|
||||
x: '100%',
|
||||
y: 0
|
||||
};
|
||||
|
||||
// 1. 如果父组件传入了固定的 scrollY,优先使用
|
||||
// // 1. 如果父组件传入了固定的 scrollY,优先使用
|
||||
if (props.scrollY !== undefined && props.scrollY !== null) {
|
||||
config.y = props.scrollY;
|
||||
}
|
||||
@ -79,6 +80,7 @@ const scrollConfig = computed(() => {
|
||||
else if (tableScrollY.value > 0) {
|
||||
config.y = tableScrollY.value;
|
||||
}
|
||||
console.log(tableScrollY.value);
|
||||
|
||||
return config;
|
||||
});
|
||||
@ -89,11 +91,11 @@ const rowSelection = computed(() => ({
|
||||
onChange: (keys: string[], rows: any[]) => {
|
||||
selectedRowKeys.value = keys;
|
||||
selectedRows.value = rows;
|
||||
emit("selection-change", keys, rows);
|
||||
emit('selection-change', keys, rows);
|
||||
},
|
||||
getCheckboxProps: props.getCheckboxProps
|
||||
? props.getCheckboxProps
|
||||
: (record: any) => ({}),
|
||||
: (record: any) => ({})
|
||||
}));
|
||||
|
||||
// --- Pagination Config ---
|
||||
@ -104,7 +106,7 @@ const paginationConfig = computed(() => ({
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
pageSizeOptions: ["20", "50", "100"],
|
||||
pageSizeOptions: ['20', '50', '100']
|
||||
}));
|
||||
|
||||
// --- Methods ---
|
||||
@ -121,7 +123,7 @@ const getList = async (filter?: Record<string, any>) => {
|
||||
...props.searchParams,
|
||||
skip: page.value,
|
||||
take: size.value,
|
||||
filter: lastFilter.value,
|
||||
filter: lastFilter.value
|
||||
};
|
||||
|
||||
const res = await props.listUrl(params);
|
||||
@ -140,9 +142,9 @@ const getList = async (filter?: Record<string, any>) => {
|
||||
|
||||
tableData.value = finalRecords;
|
||||
total.value = finalTotal;
|
||||
emit("data-loaded", params, { records: finalRecords, total: finalTotal });
|
||||
emit('data-loaded', params, { records: finalRecords, total: finalTotal });
|
||||
} catch (error) {
|
||||
console.error("Fetch table data error:", error);
|
||||
console.error('Fetch table data error:', error);
|
||||
tableData.value = [];
|
||||
total.value = 0;
|
||||
} finally {
|
||||
@ -181,8 +183,8 @@ defineExpose({
|
||||
clearSelection,
|
||||
getSelected: () => ({
|
||||
keys: selectedRowKeys.value,
|
||||
rows: selectedRows.value,
|
||||
}),
|
||||
rows: selectedRows.value
|
||||
})
|
||||
});
|
||||
|
||||
watch(
|
||||
|
||||
@ -108,3 +108,8 @@ svg {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
// 暂无数据文字颜色
|
||||
|
||||
.ant-empty-description {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
@ -19,14 +19,17 @@ service.interceptors.request.use(
|
||||
`Expected 'config' and 'config.headers' not to be undefined`
|
||||
);
|
||||
}
|
||||
if (config.url.includes('/dec-lygk-base-server')) {
|
||||
if (
|
||||
config.url.includes('/dec-lygk-base-server') ||
|
||||
config.url.includes('/wmp-env-server')
|
||||
) {
|
||||
config.headers._appid = '974975A6-47FD-4C04-9ACD-68938D2992BD';
|
||||
config.headers._isolateid = '5b34aecb-adfb-4dfc-ad95-21505a9eb388';
|
||||
config.headers._platformid = '31e6d13f-c359-4a19-8e67-b6f868f2401b';
|
||||
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
|
||||
|
||||
config.headers.authorization =
|
||||
'bearer f96d0008-f77f-497a-b05d-82cded9ccd89';
|
||||
'bearer ff5f2ec1-27ba-4ff4-8987-606cbfac6f2f';
|
||||
config.baseURL = '/';
|
||||
} else {
|
||||
const user = useUserStoreHook();
|
||||
|
||||
348
frontend/src/views/shiPinJianKong/components/LiveVideoBox.vue
Normal file
348
frontend/src/views/shiPinJianKong/components/LiveVideoBox.vue
Normal file
@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<div class="live-video-box" :style="{ height }">
|
||||
<!-- 有视频时显示播放器 -->
|
||||
<div v-if="videoUrl" class="video-container">
|
||||
<!-- 视频标题和关闭按钮 -->
|
||||
<div class="live-video-title">
|
||||
{{ videoData?.flnm }}
|
||||
<div class="title-actions">
|
||||
<CloseOutlined @click="handleClose" />
|
||||
</div>
|
||||
</div>
|
||||
<div :id="playerId" class="video-player"></div>
|
||||
</div>
|
||||
|
||||
<!-- 无视频时显示占位 -->
|
||||
<div v-else class="video-empty">
|
||||
<i class="iconfont icon-jiankong"></i>
|
||||
<div>请选择视频</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, watch, computed } from "vue";
|
||||
import { CloseOutlined } from "@ant-design/icons-vue";
|
||||
import videojs from "video.js";
|
||||
import "video.js/dist/video-js.css";
|
||||
const baseUrl = import.meta.env.VITE_APP_PREVIEW_URL;
|
||||
|
||||
// 注册 HLS 支持(video.js 8.x 内置了 HLS 支持)
|
||||
|
||||
interface VideoData {
|
||||
flnm?: string;
|
||||
stnm?: string;
|
||||
url?: string;
|
||||
urls?: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
videoData?: VideoData | null;
|
||||
height?: string;
|
||||
monitorType?: "live" | "record"; // 监控类型:live-实时视频, record-录像
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: [nodeKey?: string];
|
||||
}>();
|
||||
|
||||
// 生成唯一ID
|
||||
const playerId = `video-player-${Math.random().toString(36).substr(2, 9)}`;
|
||||
let player: any = null;
|
||||
|
||||
// 获取第一个有效的URL
|
||||
const videoUrl = computed(() => {
|
||||
if (!props.videoData) return "";
|
||||
|
||||
// 优先使用url字段
|
||||
if (props.videoData.url) return props.videoData.url;
|
||||
|
||||
// 其次使用urls数组的第一个
|
||||
if (
|
||||
props.videoData.urls &&
|
||||
Array.isArray(props.videoData.urls) &&
|
||||
props.videoData.urls.length > 0
|
||||
) {
|
||||
return props.videoData.urls[0];
|
||||
}
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
// 初始化 video.js 播放器
|
||||
const initPlayer = () => {
|
||||
if (!videoUrl.value) return;
|
||||
|
||||
// 销毁旧播放器
|
||||
if (player) {
|
||||
player.dispose();
|
||||
player = null;
|
||||
}
|
||||
try {
|
||||
// 创建 video 元素
|
||||
const videoElement = document.createElement("video");
|
||||
videoElement.className = "video-js vjs-default-skin vjs-big-play-centered";
|
||||
videoElement.setAttribute("id", playerId);
|
||||
videoElement.setAttribute("playsinline", "playsinline");
|
||||
videoElement.setAttribute("webkit-playsinline", "webkit-playsinline");
|
||||
|
||||
// 将 video 元素添加到容器
|
||||
const container = document.getElementById(playerId);
|
||||
if (container) {
|
||||
container.innerHTML = "";
|
||||
container.appendChild(videoElement);
|
||||
}
|
||||
|
||||
// 根据 monitorType 判断是否为直播流
|
||||
// live: 实时视频流(m3u8),显示直播UI
|
||||
// record: 录像文件,显示进度条
|
||||
const isLiveStream = props.monitorType === "live";
|
||||
|
||||
// 根据 URL 后缀或监控类型确定视频 MIME Type
|
||||
const getVideoType = (url: string): string => {
|
||||
const lowerUrl = url.toLowerCase();
|
||||
|
||||
// 优先根据 URL 后缀判断
|
||||
if (lowerUrl.includes(".m3u8")) {
|
||||
return "application/x-mpegURL"; // HLS 流
|
||||
} else if (lowerUrl.includes(".mp4")) {
|
||||
return "video/mp4";
|
||||
} else if (lowerUrl.includes(".webm")) {
|
||||
return "video/webm";
|
||||
} else if (lowerUrl.includes(".ogg") || lowerUrl.includes(".ogv")) {
|
||||
return "video/ogg";
|
||||
} else if (lowerUrl.includes(".avi")) {
|
||||
return "video/x-msvideo";
|
||||
} else if (lowerUrl.includes(".mov")) {
|
||||
return "video/quicktime";
|
||||
} else if (lowerUrl.includes(".wmv")) {
|
||||
return "video/x-ms-wmv";
|
||||
} else if (lowerUrl.includes(".flv")) {
|
||||
return "video/x-flv";
|
||||
}
|
||||
|
||||
// 如果 URL 中没有明确后缀,根据监控类型判断
|
||||
return isLiveStream ? "application/x-mpegURL" : "video/mp4";
|
||||
};
|
||||
|
||||
const videoType = getVideoType(videoUrl.value);
|
||||
|
||||
// 初始化 video.js
|
||||
player = videojs(videoElement, {
|
||||
autoplay: true,
|
||||
muted: true,
|
||||
controls: true,
|
||||
fluid: false,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
preload: "auto",
|
||||
playbackRates: [0.5, 1, 1.5, 2],
|
||||
liveui: isLiveStream, // 直播流显示直播UI
|
||||
// 录像模式下禁用直播相关功能
|
||||
inactivityTimeout: 0, // 禁用不活动超时
|
||||
controlBar: {
|
||||
children: [
|
||||
"playToggle",
|
||||
"volumePanel",
|
||||
"currentTimeDisplay",
|
||||
"timeDivider",
|
||||
"durationDisplay",
|
||||
"progressControl",
|
||||
"liveDisplay",
|
||||
"remainingTimeDisplay",
|
||||
"customControlSpacer",
|
||||
"playbackRateMenuButton",
|
||||
"fullscreenToggle",
|
||||
],
|
||||
},
|
||||
html5: {
|
||||
hls: {
|
||||
enableLowInitialPlaylist: true,
|
||||
smoothQualityChange: true,
|
||||
},
|
||||
},
|
||||
sources: [
|
||||
{
|
||||
src: videoUrl.value,
|
||||
type: videoType, // 指定视频类型
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 如果是录像模式,隐藏直播指示器
|
||||
if (!isLiveStream) {
|
||||
player.ready(() => {
|
||||
const liveDisplay = player.controlBar.getChild("liveDisplay");
|
||||
if (liveDisplay) {
|
||||
liveDisplay.el().style.display = "none";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 监听错误事件
|
||||
player.on("error", () => {
|
||||
const error = player.error();
|
||||
console.error("播放器错误:", error);
|
||||
|
||||
// 保持最后一帧画面,不显示错误提示
|
||||
// 在后台静默重试
|
||||
let retryCount = 0;
|
||||
const maxRetries = 10;
|
||||
|
||||
const attemptReload = () => {
|
||||
if (retryCount < maxRetries && player && videoUrl.value) {
|
||||
retryCount++;
|
||||
setTimeout(() => {
|
||||
try {
|
||||
player.src({
|
||||
src: videoUrl.value,
|
||||
type: videoType, // 指定视频类型
|
||||
});
|
||||
player.load();
|
||||
player.play();
|
||||
} catch (e) {
|
||||
if (retryCount < maxRetries) {
|
||||
attemptReload();
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
attemptReload();
|
||||
});
|
||||
|
||||
// 监听加载完成
|
||||
player.on("loadeddata", () => {});
|
||||
|
||||
// 监听播放状态
|
||||
player.on("play", () => {});
|
||||
|
||||
// 监听暂停
|
||||
player.on("pause", () => {});
|
||||
|
||||
// 监听等待(缓冲)
|
||||
player.on("waiting", () => {});
|
||||
} catch (error) {
|
||||
// 静默处理错误
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭视频
|
||||
const handleClose = () => {
|
||||
// 传递节点的 key 给父组件
|
||||
emit("close", props.videoData?.key);
|
||||
};
|
||||
|
||||
// 监听视频URL变化
|
||||
watch(
|
||||
videoUrl,
|
||||
(newUrl, oldUrl) => {
|
||||
if (newUrl && newUrl !== oldUrl) {
|
||||
// URL 变化时延迟初始化,确保 DOM 已更新
|
||||
setTimeout(() => initPlayer(), 200);
|
||||
} else if (newUrl && !oldUrl) {
|
||||
// 首次加载
|
||||
setTimeout(() => initPlayer(), 100);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
if (videoUrl.value) {
|
||||
initPlayer();
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 清理播放器
|
||||
if (player) {
|
||||
player.dispose();
|
||||
player = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.live-video-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
.live-video-title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: #2f6b98;
|
||||
display: flex;
|
||||
padding: 8px 16px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.title-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video-container {
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
position: relative;
|
||||
|
||||
.video-player {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// video.js 样式优化
|
||||
:deep(.video-js) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000;
|
||||
|
||||
video {
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #666;
|
||||
background-color: #1a1a1a;
|
||||
|
||||
i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 12px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑配置' : '新增配置'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="配置项名称" name="configName">
|
||||
<a-input
|
||||
v-model:value="formData.configName"
|
||||
style="width: 100%"
|
||||
placeholder="请输入配置项名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="配置类型" name="configType">
|
||||
<a-input
|
||||
v-model:value="formData.configType"
|
||||
style="width: 100%"
|
||||
placeholder="请输入配置类型"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="配置值" name="configValue">
|
||||
<a-input
|
||||
v-model:value="formData.configValue"
|
||||
style="width: 100%"
|
||||
placeholder="请输入配置值"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="描述" name="description">
|
||||
<a-textarea
|
||||
v-model:value="formData.description"
|
||||
style="width: 100%"
|
||||
placeholder="请输入描述"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false
|
||||
});
|
||||
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: val => emit('update:visible', val)
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'ok', values: any): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
configName: undefined,
|
||||
configType: undefined,
|
||||
configValue: undefined,
|
||||
description: undefined
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
configName: [
|
||||
{ required: true, message: '请输入配置项名称', trigger: 'blur' }
|
||||
],
|
||||
configType: [{ required: true, message: '请输入配置类型', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData
|
||||
};
|
||||
emit('ok', submitValues);
|
||||
} catch (error) {
|
||||
console.error('Validate Failed:', error);
|
||||
message.error('请检查表单填写是否正确');
|
||||
}
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach(key => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
newVisible => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
localLoading
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="config-management-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增配置">
|
||||
<a-button @click="props.handleAdd" type="primary">
|
||||
新增配置
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'reset', values: any): void;
|
||||
(e: 'searchFinish', values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
configName: ''
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: 'Input',
|
||||
name: 'configName',
|
||||
label: '配置项名称',
|
||||
fieldProps: {
|
||||
allowClear: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit('searchFinish', values);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit('reset', initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit('searchFinish', initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@ -0,0 +1,200 @@
|
||||
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
||||
<template>
|
||||
<div class="config-management">
|
||||
<ConfigManagementSearch
|
||||
ref="configManagementSearch"
|
||||
:handle-add="handleAdd"
|
||||
@reset="handleReset"
|
||||
@search-finish="onSearchFinish"
|
||||
/>
|
||||
<BasicTable
|
||||
:columns="columns"
|
||||
:data="dataSource"
|
||||
:list-url="fetchConfigData"
|
||||
:search-params="searchParams"
|
||||
:enable-row-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)"
|
||||
>编辑</a-button
|
||||
>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click="handleDelete(record)"
|
||||
>删除</a-button
|
||||
>
|
||||
</a-space>
|
||||
</template>
|
||||
<template v-if="column.key === 'configType'">
|
||||
<a-tag :color="getConfigTypeColor(record.configType)">
|
||||
{{ record.configType }}
|
||||
</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<ConfigManagementForm
|
||||
ref="configManagementForm"
|
||||
v-model:visible="editModalVisible"
|
||||
:initial-values="currentRecord"
|
||||
@cancel="editModalCancel"
|
||||
@ok="handleEditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '@/components/BasicTable/index.vue';
|
||||
import ConfigManagementSearch from './ConfigManagementSearch.vue';
|
||||
import ConfigManagementForm from './ConfigManagementForm.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '配置项名称',
|
||||
dataIndex: 'configName',
|
||||
key: 'configName',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '配置类型',
|
||||
key: 'configType',
|
||||
dataIndex: 'configType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '配置值',
|
||||
dataIndex: 'configValue',
|
||||
key: 'configValue',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
fixed: 'right'
|
||||
}
|
||||
];
|
||||
|
||||
// 搜索参数
|
||||
const searchParams = ref({});
|
||||
// 编辑弹窗数据
|
||||
const currentRecord = ref<any | null>(null);
|
||||
const editModalVisible = ref(false);
|
||||
|
||||
// 数据源
|
||||
const dataSource = ref([]);
|
||||
|
||||
// 获取配置类型标签颜色
|
||||
const getConfigTypeColor = (type: string) => {
|
||||
const colorMap: Record<string, string> = {
|
||||
系统配置: 'blue',
|
||||
显示配置: 'green',
|
||||
业务配置: 'orange'
|
||||
};
|
||||
return colorMap[type] || 'default';
|
||||
};
|
||||
|
||||
// 模拟数据获取函数
|
||||
const fetchConfigData = (params: any) => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
configName: '默认缩放级别',
|
||||
configType: '显示配置',
|
||||
configValue: '10',
|
||||
description: '地图默认显示的缩放级别',
|
||||
updateTime: '2023-05-15 10:30:00'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
configName: '数据刷新间隔',
|
||||
configType: '系统配置',
|
||||
configValue: '300',
|
||||
description: '数据自动刷新的时间间隔(秒)',
|
||||
updateTime: '2023-06-20 14:45:00'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
configName: '预警阈值',
|
||||
configType: '业务配置',
|
||||
configValue: '85%',
|
||||
description: '触发预警的阈值百分比',
|
||||
updateTime: '2023-07-10 09:15:00'
|
||||
}
|
||||
],
|
||||
total: 3
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
currentRecord.value = null;
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 编辑处理
|
||||
const handleEdit = (record: any) => {
|
||||
currentRecord.value = { ...record };
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 删除处理
|
||||
const handleDelete = (record: any) => {
|
||||
message.warning(`删除配置: ${record.configName}`);
|
||||
};
|
||||
|
||||
// 搜索完成处理
|
||||
const onSearchFinish = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
|
||||
// 重置
|
||||
const handleReset = (params: any) => {};
|
||||
|
||||
// 选择变化处理
|
||||
const handleSelectionChange = (selectedRows: any[]) => {
|
||||
console.log('选中的行:', selectedRows);
|
||||
};
|
||||
|
||||
// 表单取消
|
||||
const editModalCancel = () => {
|
||||
editModalVisible.value = false;
|
||||
};
|
||||
|
||||
// 表单提交
|
||||
const handleEditSubmit = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.config-management {
|
||||
height: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑图层' : '新增图层'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="图层名称" name="title">
|
||||
<a-input
|
||||
v-model:value="formData.title"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图层名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图层编码" name="code">
|
||||
<a-input
|
||||
v-model:value="formData.code"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图层编码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="标签显示级别" name="treeLevel">
|
||||
<a-input-number
|
||||
v-model:value="formData.treeLevel"
|
||||
style="width: 100%"
|
||||
placeholder="请输入标签显示级别"
|
||||
:min="0"
|
||||
:step="1"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="description">
|
||||
<a-textarea
|
||||
rows="4"
|
||||
v-model:value="formData.description"
|
||||
style="width: 100%"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
||||
// 定义 Props
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
// 加载状态
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false
|
||||
});
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: val => emit('update:visible', val)
|
||||
});
|
||||
// 定义 Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'ok', values: any): void;
|
||||
(
|
||||
e: 'preview-click',
|
||||
record: any,
|
||||
type: string,
|
||||
index: number,
|
||||
action: string
|
||||
): void;
|
||||
}>();
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref();
|
||||
// 1. 新增用于存储手动验证错误信息的响应式变量
|
||||
const bodyLengthError = ref<string>('');
|
||||
const weightError = ref<string>('');
|
||||
|
||||
// 表单数据模型
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
title: undefined,
|
||||
code: undefined,
|
||||
treeLevel: undefined,
|
||||
description: undefined
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
// 验证规则
|
||||
const rules: Record<string, Rule[]> = {
|
||||
title: [{ required: true, message: '请输入图层名称', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '请输入图层编码', trigger: 'blur' }],
|
||||
treeLevel: [
|
||||
{ required: true, message: '请输入标签显示级别', trigger: 'blur' }
|
||||
]
|
||||
};
|
||||
|
||||
// 计算是否为编辑模式
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
// 确认操作
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
// 验证表单
|
||||
await formRef.value.validate();
|
||||
// 准备提交数据
|
||||
const submitValues = {
|
||||
...formData
|
||||
};
|
||||
emit('ok', submitValues);
|
||||
} catch (error) {
|
||||
console.error('Validate Failed:', error);
|
||||
message.error('请检查表单填写是否正确');
|
||||
}
|
||||
};
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
// --- 编辑模式:回填数据 ---
|
||||
const values = props.initialValues;
|
||||
// 回填其他普通字段
|
||||
Object.keys(formData).forEach(key => {
|
||||
// 确保字段存在于 initialValues 中再赋值,避免覆盖默认值
|
||||
if (values.hasOwnProperty(key)) {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
// 清空手动验证的错误信息
|
||||
bodyLengthError.value = '';
|
||||
weightError.value = '';
|
||||
};
|
||||
|
||||
// 取消操作
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
newVisible => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false } // 不需要 immediate,因为初始状态通常是 false
|
||||
);
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
localLoading
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="guoYuSheShiShuJuTianBao-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增图层">
|
||||
<a-button @click="props.handleAdd" type="primary">
|
||||
新增图层
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import BasicSearch from '@/components/BasicSearch/index.vue'; // 确保路径正确
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'reset', values: any): void;
|
||||
(e: 'searchFinish', values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
title: ''
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: 'Input',
|
||||
name: 'title',
|
||||
label: '图层名称',
|
||||
fieldProps: {
|
||||
allowClear: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
// --- Methods ---
|
||||
|
||||
// 2. 搜索表单逻辑
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit('searchFinish', values);
|
||||
};
|
||||
// 值改变
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
emit('reset', initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit('searchFinish', initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
5293
frontend/src/views/system/map/components/LayerManagement/index.vue
Normal file
5293
frontend/src/views/system/map/components/LayerManagement/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑图例数据' : '新增图例数据'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="图例名称" name="name">
|
||||
<a-input
|
||||
v-model:value="formData.name"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图例名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图例类型" name="code">
|
||||
<a-select
|
||||
v-model:value="formData.code"
|
||||
style="width: 100%"
|
||||
placeholder="请选择图例类型"
|
||||
:options="options"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="图例编码" name="nameEn">
|
||||
<a-input
|
||||
v-model:value="formData.nameEn"
|
||||
style="width: 100%"
|
||||
placeholder="请选择图例类型"
|
||||
:options="options"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="icon编码" name="icon">
|
||||
<a-input
|
||||
v-model:value="formData.icon"
|
||||
style="width: 100%"
|
||||
placeholder="请输入icon编码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="父级图例名称" name="parentName">
|
||||
<a-input
|
||||
v-model:value="formData.parentName"
|
||||
style="width: 100%"
|
||||
placeholder="请输入父级图例名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图层名称" name="layerCodeName">
|
||||
<a-input
|
||||
v-model:value="formData.layerCodeName"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图层名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="二维最小缩放" name="minZoom">
|
||||
<a-input
|
||||
v-model:value="formData.minZoom"
|
||||
style="width: 100%"
|
||||
placeholder="请输入二维最小缩放"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="二维最大缩放" name="maxZoom">
|
||||
<a-input
|
||||
v-model:value="formData.maxZoom"
|
||||
style="width: 100%"
|
||||
placeholder="请输入二维最大缩放"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="三维最小高程" name="minElevation">
|
||||
<a-input
|
||||
v-model:value="formData.minElevation"
|
||||
style="width: 100%"
|
||||
placeholder="请输入三维最小高程"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="三维最大高程" name="maxElevation">
|
||||
<a-input
|
||||
v-model:value="formData.maxElevation"
|
||||
style="width: 100%"
|
||||
placeholder="请输入三维最大高程"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="区间表达式" name="expression">
|
||||
<a-input
|
||||
v-model:value="formData.expression"
|
||||
style="width: 100%"
|
||||
placeholder="请输入区间表达式"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="description">
|
||||
<a-input
|
||||
v-model:value="formData.description"
|
||||
style="width: 100%"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import type { Rule } from "ant-design-vue/es/form";
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false,
|
||||
});
|
||||
const options = ref([
|
||||
{ label: "色块图例", value: "colorLayer" },
|
||||
{ label: "地图GIS", value: "baseLayer" },
|
||||
{ label: "锚点", value: "pointLayer" },
|
||||
]);
|
||||
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit("update:visible", val),
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:visible", value: boolean): void;
|
||||
(e: "cancel"): void;
|
||||
(e: "ok", values: any): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
dataName: undefined,
|
||||
dataType: undefined,
|
||||
relatedLegend: undefined,
|
||||
dataSource: undefined,
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
name: [{ required: true, message: "请输入图例名称", trigger: "blur" }],
|
||||
nameEn: [{ required: true, message: "请输入图例编码", trigger: "blur" }],
|
||||
code: [{ required: true, message: "请选择图例类型", trigger: "blur" }],
|
||||
icon: [{ required: true, message: "请输入icon编码", trigger: "blur" }],
|
||||
parentName: [{ required: true, message: "请输入父级图例名称", trigger: "blur" }],
|
||||
layerCodeName: [{ required: true, message: "请输入图层名称", trigger: "blur" }],
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData,
|
||||
};
|
||||
emit("ok", submitValues);
|
||||
} catch (error) {
|
||||
console.error("Validate Failed:", error);
|
||||
message.error("请检查表单填写是否正确");
|
||||
}
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach((key) => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit("update:visible", false);
|
||||
emit("cancel");
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVisible) => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
localLoading,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="legend-data-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增图例数据">
|
||||
<a-button @click="props.handleAdd" type="primary"> 新增图例数据 </a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "reset", values: any): void;
|
||||
(e: "searchFinish", values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
name: "",
|
||||
parentName: "",
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: "Input",
|
||||
name: "name",
|
||||
label: "图例名称",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Select",
|
||||
name: "code",
|
||||
label: "父级图例",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit("searchFinish", values);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit("reset", initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit("searchFinish", initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
1242
frontend/src/views/system/map/components/LegendData/index.vue
Normal file
1242
frontend/src/views/system/map/components/LegendData/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑图例' : '新增图例'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="图例名称" name="name">
|
||||
<a-input
|
||||
v-model:value="formData.name"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图例名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图例编码" name="nameEn">
|
||||
<a-input
|
||||
v-model:value="formData.nameEn"
|
||||
style="width: 100%"
|
||||
placeholder="请输入图例编码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图例类型" name="code">
|
||||
<a-select
|
||||
v-model:value="formData.code"
|
||||
style="width: 100%"
|
||||
placeholder="请选择图例类型"
|
||||
:options="options"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="description">
|
||||
<a-textarea
|
||||
rows="4"
|
||||
v-model:value="formData.description"
|
||||
style="width: 100%"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import type { Rule } from "ant-design-vue/es/form";
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false,
|
||||
});
|
||||
const options = ref([
|
||||
{ label: "色块图例", value: "colorLayer" },
|
||||
{ label: "地图GIS", value: "baseLayer" },
|
||||
{ label: "锚点", value: "pointLayer" },
|
||||
]);
|
||||
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit("update:visible", val),
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:visible", value: boolean): void;
|
||||
(e: "cancel"): void;
|
||||
(e: "ok", values: any): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
nameEn: undefined,
|
||||
code: undefined,
|
||||
description: undefined,
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
name: [{ required: true, message: "请输入图例名称", trigger: "blur" }],
|
||||
nameEn: [{ required: true, message: "请输入图例编码", trigger: "blur" }],
|
||||
code: [{ required: true, message: "请选择图例类型", trigger: "change" }],
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData,
|
||||
};
|
||||
emit("ok", submitValues);
|
||||
} catch (error) {
|
||||
console.error("Validate Failed:", error);
|
||||
message.error("请检查表单填写是否正确");
|
||||
}
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach((key) => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit("update:visible", false);
|
||||
emit("cancel");
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVisible) => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
localLoading,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="legend-structure-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增图例">
|
||||
<a-button @click="props.handleAdd" type="primary"> 新增图例 </a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "reset", values: any): void;
|
||||
(e: "searchFinish", values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: "Input",
|
||||
name: "name",
|
||||
label: "图例名称",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit("searchFinish", values);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit("reset", initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit("searchFinish", initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
1844
frontend/src/views/system/map/components/LegendStructure/index.vue
Normal file
1844
frontend/src/views/system/map/components/LegendStructure/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑电站' : '新增电站'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="电站名称" name="stationName">
|
||||
<a-input
|
||||
v-model:value="formData.stationName"
|
||||
style="width: 100%"
|
||||
placeholder="请输入电站名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属流域" name="basin">
|
||||
<a-input
|
||||
v-model:value="formData.basin"
|
||||
style="width: 100%"
|
||||
placeholder="请输入所属流域"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="装机容量(MW)" name="capacity">
|
||||
<a-input-number
|
||||
v-model:value="formData.capacity"
|
||||
style="width: 100%"
|
||||
placeholder="请输入装机容量"
|
||||
:min="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-select v-model:value="formData.status" style="width: 100%">
|
||||
<a-select-option value="running">运行中</a-select-option>
|
||||
<a-select-option value="stopped">停运</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="位置坐标" name="coordinates">
|
||||
<a-input
|
||||
v-model:value="formData.coordinates"
|
||||
style="width: 100%"
|
||||
placeholder="请输入位置坐标"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false
|
||||
});
|
||||
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: val => emit('update:visible', val)
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'ok', values: any): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
stationName: undefined,
|
||||
basin: undefined,
|
||||
capacity: undefined,
|
||||
status: undefined,
|
||||
coordinates: undefined
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
stationName: [{ required: true, message: '请输入电站名称', trigger: 'blur' }],
|
||||
basin: [{ required: true, message: '请输入所属流域', trigger: 'blur' }],
|
||||
capacity: [{ required: true, message: '请输入装机容量', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData
|
||||
};
|
||||
emit('ok', submitValues);
|
||||
} catch (error) {
|
||||
console.error('Validate Failed:', error);
|
||||
message.error('请检查表单填写是否正确');
|
||||
}
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach(key => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
newVisible => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
localLoading
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="station-management-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增电站">
|
||||
<a-button @click="props.handleAdd" type="primary">
|
||||
新增电站
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'reset', values: any): void;
|
||||
(e: 'searchFinish', values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
stationName: ''
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: 'Input',
|
||||
name: 'stationName',
|
||||
label: '电站名称',
|
||||
fieldProps: {
|
||||
allowClear: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit('searchFinish', values);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit('reset', initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit('searchFinish', initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@ -0,0 +1,190 @@
|
||||
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\StationManagement\index.vue -->
|
||||
<template>
|
||||
<div class="station-management">
|
||||
<StationManagementSearch
|
||||
ref="stationManagementSearch"
|
||||
:handle-add="handleAdd"
|
||||
@reset="handleReset"
|
||||
@search-finish="onSearchFinish"
|
||||
/>
|
||||
<BasicTable
|
||||
:columns="columns"
|
||||
:data="dataSource"
|
||||
:list-url="fetchStationData"
|
||||
:search-params="searchParams"
|
||||
:enable-row-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)"
|
||||
>编辑</a-button
|
||||
>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click="handleDelete(record)"
|
||||
>删除</a-button
|
||||
>
|
||||
</a-space>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag :color="record.status === 'running' ? 'green' : 'red'">
|
||||
{{ record.status === 'running' ? '运行中' : '停运' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<StationManagementForm
|
||||
ref="stationManagementForm"
|
||||
v-model:visible="editModalVisible"
|
||||
:initial-values="currentRecord"
|
||||
@cancel="editModalCancel"
|
||||
@ok="handleEditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '@/components/BasicTable/index.vue';
|
||||
import StationManagementSearch from './StationManagementSearch.vue';
|
||||
import StationManagementForm from './StationManagementForm.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '电站名称',
|
||||
dataIndex: 'stationName',
|
||||
key: 'stationName',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '所属流域',
|
||||
dataIndex: 'basin',
|
||||
key: 'basin',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '装机容量(MW)',
|
||||
dataIndex: 'capacity',
|
||||
key: 'capacity',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
dataIndex: 'status',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '位置坐标',
|
||||
dataIndex: 'coordinates',
|
||||
key: 'coordinates',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
fixed: 'right'
|
||||
}
|
||||
];
|
||||
|
||||
// 搜索参数
|
||||
const searchParams = ref({});
|
||||
// 编辑弹窗数据
|
||||
const currentRecord = ref<any | null>(null);
|
||||
const editModalVisible = ref(false);
|
||||
|
||||
// 数据源
|
||||
const dataSource = ref([]);
|
||||
|
||||
// 模拟数据获取函数
|
||||
const fetchStationData = (params: any) => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
stationName: '三峡电站',
|
||||
basin: '长江流域',
|
||||
capacity: 22500,
|
||||
status: 'running',
|
||||
coordinates: '111.29,30.83'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
stationName: '葛洲坝电站',
|
||||
basin: '长江流域',
|
||||
capacity: 2715,
|
||||
status: 'running',
|
||||
coordinates: '111.28,30.75'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
stationName: '溪洛渡电站',
|
||||
basin: '金沙江流域',
|
||||
capacity: 13860,
|
||||
status: 'stopped',
|
||||
coordinates: '103.65,28.25'
|
||||
}
|
||||
],
|
||||
total: 3
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
currentRecord.value = null;
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 编辑处理
|
||||
const handleEdit = (record: any) => {
|
||||
currentRecord.value = { ...record };
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 删除处理
|
||||
const handleDelete = (record: any) => {
|
||||
message.warning(`删除电站: ${record.stationName}`);
|
||||
};
|
||||
|
||||
// 搜索完成处理
|
||||
const onSearchFinish = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
|
||||
// 重置
|
||||
const handleReset = (params: any) => {};
|
||||
|
||||
// 选择变化处理
|
||||
const handleSelectionChange = (selectedRows: any[]) => {
|
||||
console.log('选中的行:', selectedRows);
|
||||
};
|
||||
|
||||
// 表单取消
|
||||
const editModalCancel = () => {
|
||||
editModalVisible.value = false;
|
||||
};
|
||||
|
||||
// 表单提交
|
||||
const handleEditSubmit = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.station-management {
|
||||
height: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑倾斜摄影' : '新增倾斜摄影'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
>
|
||||
<a-form-item label="项目名称" name="projectName">
|
||||
<a-input
|
||||
v-model:value="formData.projectName"
|
||||
style="width: 100%"
|
||||
placeholder="请输入项目名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="拍摄日期" name="captureDate">
|
||||
<a-date-picker
|
||||
v-model:value="formData.captureDate"
|
||||
style="width: 100%"
|
||||
placeholder="请选择拍摄日期"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件大小" name="fileSize">
|
||||
<a-input
|
||||
v-model:value="formData.fileSize"
|
||||
style="width: 100%"
|
||||
placeholder="请输入文件大小"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-select v-model:value="formData.status" style="width: 100%">
|
||||
<a-select-option value="processed">已处理</a-select-option>
|
||||
<a-select-option value="pending">待处理</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="覆盖区域" name="coverageArea">
|
||||
<a-textarea
|
||||
v-model:value="formData.coverageArea"
|
||||
style="width: 100%"
|
||||
placeholder="请输入覆盖区域"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
initialValues: null,
|
||||
loading: false
|
||||
});
|
||||
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: val => emit('update:visible', val)
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'ok', values: any): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
projectName: undefined,
|
||||
captureDate: undefined,
|
||||
fileSize: undefined,
|
||||
status: undefined,
|
||||
coverageArea: undefined
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
|
||||
captureDate: [
|
||||
{ required: true, message: '请选择拍摄日期', trigger: 'change' }
|
||||
]
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData,
|
||||
captureDate: formData.captureDate
|
||||
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||
: undefined
|
||||
};
|
||||
emit('ok', submitValues);
|
||||
} catch (error) {
|
||||
console.error('Validate Failed:', error);
|
||||
message.error('请检查表单填写是否正确');
|
||||
}
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach(key => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
if (key === 'captureDate' && values[key]) {
|
||||
formData[key] = dayjs(values[key]);
|
||||
} else {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
resetForm();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
newVisible => {
|
||||
if (newVisible) {
|
||||
initForm();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
localLoading
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="tilt-photo-management-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="新增倾斜摄影">
|
||||
<a-button @click="props.handleAdd" type="primary">
|
||||
新增倾斜摄影
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||
|
||||
interface Props {
|
||||
handleAdd: () => void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'reset', values: any): void;
|
||||
(e: 'searchFinish', values: any): void;
|
||||
}>();
|
||||
|
||||
const initSearchData = {
|
||||
projectName: ''
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: 'Input',
|
||||
name: 'projectName',
|
||||
label: '项目名称',
|
||||
fieldProps: {
|
||||
allowClear: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
const onSearchFinish = (values: any) => {
|
||||
emit('searchFinish', values);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit('reset', initSearchData);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emit('searchFinish', initSearchData);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@ -0,0 +1,198 @@
|
||||
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\TiltPhotoManagement\index.vue -->
|
||||
<template>
|
||||
<div class="tilt-photo-management">
|
||||
<TiltPhotoManagementSearch
|
||||
ref="tiltPhotoManagementSearch"
|
||||
:handle-add="handleAdd"
|
||||
@reset="handleReset"
|
||||
@search-finish="onSearchFinish"
|
||||
/>
|
||||
<BasicTable
|
||||
:columns="columns"
|
||||
:data="dataSource"
|
||||
:list-url="fetchTiltPhotoData"
|
||||
:search-params="searchParams"
|
||||
:enable-row-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handlePreview(record)"
|
||||
>预览</a-button
|
||||
>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)"
|
||||
>编辑</a-button
|
||||
>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click="handleDelete(record)"
|
||||
>删除</a-button
|
||||
>
|
||||
</a-space>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag :color="record.status === 'processed' ? 'green' : 'orange'">
|
||||
{{ record.status === 'processed' ? '已处理' : '待处理' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<TiltPhotoManagementForm
|
||||
ref="tiltPhotoManagementForm"
|
||||
v-model:visible="editModalVisible"
|
||||
:initial-values="currentRecord"
|
||||
@cancel="editModalCancel"
|
||||
@ok="handleEditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '@/components/BasicTable/index.vue';
|
||||
import TiltPhotoManagementSearch from './TiltPhotoManagementSearch.vue';
|
||||
import TiltPhotoManagementForm from './TiltPhotoManagementForm.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'projectName',
|
||||
key: 'projectName',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '拍摄日期',
|
||||
dataIndex: 'captureDate',
|
||||
key: 'captureDate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '文件大小',
|
||||
dataIndex: 'fileSize',
|
||||
key: 'fileSize',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
dataIndex: 'status',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '覆盖区域',
|
||||
dataIndex: 'coverageArea',
|
||||
key: 'coverageArea',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 200,
|
||||
fixed: 'right'
|
||||
}
|
||||
];
|
||||
|
||||
// 搜索参数
|
||||
const searchParams = ref({});
|
||||
// 编辑弹窗数据
|
||||
const currentRecord = ref<any | null>(null);
|
||||
const editModalVisible = ref(false);
|
||||
|
||||
// 数据源
|
||||
const dataSource = ref([]);
|
||||
|
||||
// 模拟数据获取函数
|
||||
const fetchTiltPhotoData = (params: any) => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
projectName: '三峡库区倾斜摄影',
|
||||
captureDate: '2023-03-15',
|
||||
fileSize: '2.5GB',
|
||||
status: 'processed',
|
||||
coverageArea: '三峡大坝周边5公里范围'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
projectName: '葛洲坝区域航拍',
|
||||
captureDate: '2023-04-20',
|
||||
fileSize: '1.8GB',
|
||||
status: 'processed',
|
||||
coverageArea: '葛洲坝枢纽工程区域'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
projectName: '金沙江下游航测',
|
||||
captureDate: '2023-05-10',
|
||||
fileSize: '3.2GB',
|
||||
status: 'pending',
|
||||
coverageArea: '金沙江下游河段'
|
||||
}
|
||||
],
|
||||
total: 3
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
currentRecord.value = null;
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 预览处理
|
||||
const handlePreview = (record: any) => {
|
||||
message.info(`预览倾斜摄影: ${record.projectName}`);
|
||||
};
|
||||
|
||||
// 编辑处理
|
||||
const handleEdit = (record: any) => {
|
||||
currentRecord.value = { ...record };
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 删除处理
|
||||
const handleDelete = (record: any) => {
|
||||
message.warning(`删除倾斜摄影: ${record.projectName}`);
|
||||
};
|
||||
|
||||
// 搜索完成处理
|
||||
const onSearchFinish = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
|
||||
// 重置
|
||||
const handleReset = (params: any) => {};
|
||||
|
||||
// 选择变化处理
|
||||
const handleSelectionChange = (selectedRows: any[]) => {
|
||||
console.log('选中的行:', selectedRows);
|
||||
};
|
||||
|
||||
// 表单取消
|
||||
const editModalCancel = () => {
|
||||
editModalVisible.value = false;
|
||||
};
|
||||
|
||||
// 表单提交
|
||||
const handleEditSubmit = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tilt-photo-management {
|
||||
height: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
</style>
|
||||
114
frontend/src/views/system/map/index.vue
Normal file
114
frontend/src/views/system/map/index.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div class="map-page">
|
||||
<!-- Ant Design Tabs -->
|
||||
<a-tabs v-model:activeKey="activeTab" class="map-tabs">
|
||||
<a-tab-pane v-for="tab in tabs" :key="tab.value" :tab="tab.name">
|
||||
<!-- 动态加载对应的组件 -->
|
||||
<component :is="getComponent(tab.value)" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineAsyncComponent } from 'vue';
|
||||
|
||||
// Tab 配置
|
||||
const tabs = [
|
||||
{
|
||||
name: '图层管理',
|
||||
value: 'layer'
|
||||
},
|
||||
{
|
||||
name: '图例结构管理',
|
||||
value: 'legend'
|
||||
},
|
||||
{
|
||||
name: '图例数据管理',
|
||||
value: 'legendData'
|
||||
},
|
||||
{
|
||||
name: '电站专题管理',
|
||||
value: 'station'
|
||||
},
|
||||
{
|
||||
name: '沿程配置管理',
|
||||
value: 'config'
|
||||
},
|
||||
{
|
||||
name: '倾斜摄影管理',
|
||||
value: 'tilt'
|
||||
}
|
||||
];
|
||||
|
||||
// 当前激活的 tab
|
||||
const activeTab = ref('layer');
|
||||
|
||||
// 获取对应组件的方法
|
||||
const getComponent = (value: string) => {
|
||||
const componentMap: Record<string, any> = {
|
||||
layer: defineAsyncComponent(
|
||||
() => import('./components/LayerManagement/index.vue')
|
||||
),
|
||||
legend: defineAsyncComponent(
|
||||
() => import('./components/LegendStructure/index.vue')
|
||||
),
|
||||
legendData: defineAsyncComponent(
|
||||
() => import('./components/LegendData/index.vue')
|
||||
),
|
||||
station: defineAsyncComponent(
|
||||
() => import('./components/StationManagement/index.vue')
|
||||
),
|
||||
config: defineAsyncComponent(
|
||||
() => import('./components/ConfigManagement/index.vue')
|
||||
),
|
||||
tilt: defineAsyncComponent(
|
||||
() => import('./components/TiltPhotoManagement/index.vue')
|
||||
)
|
||||
};
|
||||
|
||||
return componentMap[value] || null;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.map-page {
|
||||
position: relative;
|
||||
z-index: 900;
|
||||
pointer-events: all;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: 2px;
|
||||
background-color: #ffffff;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
.content {
|
||||
position: relative;
|
||||
z-index: 900;
|
||||
pointer-events: all;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-tabs) {
|
||||
height: 100%; // 减去 tabs header 的高度
|
||||
padding: 0 13px;
|
||||
}
|
||||
.map-tabs {
|
||||
:deep(.ant-tabs-content) {
|
||||
height: 100%; // 减去 tabs header 的高度
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-tabpane) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -54,6 +54,16 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
||||
new RegExp('^/api/dec-lygk-base-server'),
|
||||
'/api/dec-lygk-base-server'
|
||||
)
|
||||
},
|
||||
'/api/wmp-env-server': {
|
||||
target: 'https://211.99.26.225:12122',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: path =>
|
||||
path.replace(
|
||||
new RegExp('^/api/wmp-env-server'),
|
||||
'/api/wmp-env-server'
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user