This commit is contained in:
zh
2025-11-05 18:24:48 +08:00
35 changed files with 2236 additions and 374 deletions

1303
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
"compressing": "^1.5.1", "compressing": "^1.5.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"decimal.js": "^10.6.0",
"echarts": "^6.0.0", "echarts": "^6.0.0",
"electron-store": "8.1.0", "electron-store": "8.1.0",
"electron-updater": "^6.3.9", "electron-updater": "^6.3.9",

Binary file not shown.

View File

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>后台管理</title><script src=./reconnecting-websocket.js></script><link href=static/css/app.58b4d6f6.css rel=preload as=style><link href=static/css/chunk-elementUI.68c70ad5.css rel=preload as=style><link href=static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=static/js/app.d12d50a9.js rel=preload as=script><link href=static/js/chunk-elementUI.a9f82b5b.js rel=preload as=script><link href=static/js/chunk-libs.e232667f.js rel=preload as=script><link href=static/css/chunk-elementUI.68c70ad5.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.58b4d6f6.css rel=stylesheet></head><body><noscript><strong>We're sorry but doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,o,a=t[0],i=t[1],f=t[2],l=0,d=[];l<a.length;l++)o=a[l],Object.prototype.hasOwnProperty.call(c,o)&&c[o]&&d.push(c[o][0]),c[o]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(d.length)d.shift()();return u.push.apply(u,f||[]),n()}function n(){for(var e,t=0;t<u.length;t++){for(var n=u[t],r=!0,o=1;o<n.length;o++){var a=n[o];0!==c[a]&&(r=!1)}r&&(u.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={runtime:0},c={runtime:0},u=[];function a(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-6337fcfc":"ce706d4d","chunk-375947db":"7683b89a","chunk-4274d9fc":"4a15316e","chunk-7523e759":"fdb7fb12","chunk-63b9e6fe":"7de6c7ad","chunk-94d3c3c4":"d08f8612"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-375947db":1,"chunk-4274d9fc":1,"chunk-7523e759":1,"chunk-63b9e6fe":1,"chunk-94d3c3c4":1};o[e]?t.push(o[e]):0!==o[e]&&n[e]&&t.push(o[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-6337fcfc":"31d6cfe0","chunk-375947db":"cd13572c","chunk-4274d9fc":"c6dda9a9","chunk-7523e759":"f264e692","chunk-63b9e6fe":"cf107c33","chunk-94d3c3c4":"3c7f5ad9"}[e]+".css",c=i.p+r,u=document.getElementsByTagName("link"),a=0;a<u.length;a++){var f=u[a],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===c))return t()}var d=document.getElementsByTagName("style");for(a=0;a<d.length;a++){f=d[a],l=f.getAttribute("data-href");if(l===r||l===c)return t()}var s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.onload=t,s.onerror=function(t){var r=t&&t.target&&t.target.src||c,u=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");u.code="CSS_CHUNK_LOAD_FAILED",u.request=r,delete o[e],s.parentNode.removeChild(s),n(u)},s.href=c;var h=document.getElementsByTagName("head")[0];h.appendChild(s)})).then((function(){o[e]=0})));var r=c[e];if(0!==r)if(r)t.push(r[2]);else{var u=new Promise((function(t,n){r=c[e]=[t,n]}));t.push(r[2]=u);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=a(e);var d=new Error;f=function(t){l.onerror=l.onload=null,clearTimeout(s);var n=c[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;d.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",d.name="ChunkLoadError",d.type=r,d.request=o,n[1](d)}c[e]=void 0}};var s=setTimeout((function(){f({type:"timeout",target:l})}),12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var d=0;d<f.length;d++)t(f[d]);var s=l;n()})([]);</script><script src=static/js/chunk-elementUI.a9f82b5b.js></script><script src=static/js/chunk-libs.e232667f.js></script><script src=static/js/app.d12d50a9.js></script></body><script src=./echarts.min.js></script></html> <!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>后台管理</title><script src=./reconnecting-websocket.js></script><link href=static/css/app.46ef1c6b.css rel=preload as=style><link href=static/css/chunk-elementUI.68c70ad5.css rel=preload as=style><link href=static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=static/js/app.7782b1e9.js rel=preload as=script><link href=static/js/chunk-elementUI.a9f82b5b.js rel=preload as=script><link href=static/js/chunk-libs.8de98ba2.js rel=preload as=script><link href=static/css/chunk-elementUI.68c70ad5.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.46ef1c6b.css rel=stylesheet></head><body><noscript><strong>We're sorry but doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,o,a=t[0],i=t[1],d=t[2],l=0,f=[];l<a.length;l++)o=a[l],Object.prototype.hasOwnProperty.call(c,o)&&c[o]&&f.push(c[o][0]),c[o]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(f.length)f.shift()();return u.push.apply(u,d||[]),n()}function n(){for(var e,t=0;t<u.length;t++){for(var n=u[t],r=!0,o=1;o<n.length;o++){var a=n[o];0!==c[a]&&(r=!1)}r&&(u.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={runtime:0},c={runtime:0},u=[];function a(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-0e163d56":"264fd37b","chunk-6337fcfc":"ce706d4d","chunk-213dd466":"f0e897b9","chunk-626cc720":"42d599ab","chunk-69ab8e14":"e2ed086d","chunk-94d3c3c4":"d08f8612"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-0e163d56":1,"chunk-213dd466":1,"chunk-626cc720":1,"chunk-69ab8e14":1,"chunk-94d3c3c4":1};o[e]?t.push(o[e]):0!==o[e]&&n[e]&&t.push(o[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-0e163d56":"f278854e","chunk-6337fcfc":"31d6cfe0","chunk-213dd466":"ee4aa5be","chunk-626cc720":"61ca7dbd","chunk-69ab8e14":"e18a06cd","chunk-94d3c3c4":"3c7f5ad9"}[e]+".css",c=i.p+r,u=document.getElementsByTagName("link"),a=0;a<u.length;a++){var d=u[a],l=d.getAttribute("data-href")||d.getAttribute("href");if("stylesheet"===d.rel&&(l===r||l===c))return t()}var f=document.getElementsByTagName("style");for(a=0;a<f.length;a++){d=f[a],l=d.getAttribute("data-href");if(l===r||l===c)return t()}var s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.onload=t,s.onerror=function(t){var r=t&&t.target&&t.target.src||c,u=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");u.code="CSS_CHUNK_LOAD_FAILED",u.request=r,delete o[e],s.parentNode.removeChild(s),n(u)},s.href=c;var h=document.getElementsByTagName("head")[0];h.appendChild(s)})).then((function(){o[e]=0})));var r=c[e];if(0!==r)if(r)t.push(r[2]);else{var u=new Promise((function(t,n){r=c[e]=[t,n]}));t.push(r[2]=u);var d,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=a(e);var f=new Error;d=function(t){l.onerror=l.onload=null,clearTimeout(s);var n=c[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;f.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",f.name="ChunkLoadError",f.type=r,f.request=o,n[1](f)}c[e]=void 0}};var s=setTimeout((function(){d({type:"timeout",target:l})}),12e4);l.onerror=l.onload=d,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var d=window["webpackJsonp"]=window["webpackJsonp"]||[],l=d.push.bind(d);d.push=t,d=d.slice();for(var f=0;f<d.length;f++)t(d[f]);var s=l;n()})([]);</script><script src=static/js/chunk-elementUI.a9f82b5b.js></script><script src=static/js/chunk-libs.8de98ba2.js></script><script src=static/js/app.7782b1e9.js></script></body><script src=./echarts.min.js></script></html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.el-row[data-v-2649a100]{margin-bottom:20px}.el-row[data-v-2649a100]:last-child{margin-bottom:0}.el-col[data-v-2649a100]{border-radius:4px}.grid-content[data-v-2649a100]{background:#fff;border:1px solid #f3f4f6;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05),0 0 0 transparent,0 0 0 transparent;box-shadow:0 1px 2px rgba(0,0,0,.05),0 0 0 transparent,0 0 0 transparent;border-radius:8px}.userNum[data-v-2649a100]{height:10vh;line-height:10vh;min-height:60px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px}.userNum .img[data-v-2649a100]{width:48px;height:48px;margin-left:15px;line-height:100%}.userNum .img .svg-icon[data-v-2649a100]{width:100%;height:100%;vertical-align:baseline!important}.userNum .numCon[data-v-2649a100]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:1}.userNum .numCon div[data-v-2649a100]:first-child{width:100px;height:20px;line-height:20px;font-size:14px;font-weight:400;color:#6b7280;text-align:left;margin-top:2vh}.userNum .numCon div[data-v-2649a100]:last-child{width:100px;height:32px;font-size:24px;font-weight:400;color:#1d2129;margin-top:5px}.search[data-v-2649a100]{height:8vh;min-height:45px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px}.search .el-input[data-v-2649a100]{width:15vw;margin-left:20px;min-width:170px}.search .el-select[data-v-2649a100]{width:16vw;min-width:160px}.search .addUser[data-v-2649a100]{position:absolute;right:160px}.search .delUser[data-v-2649a100]{position:absolute;right:30px}.table[data-v-2649a100]{height:65vh}.table .title[data-v-2649a100]{width:100%;height:50px;padding:0 20px;line-height:50px;color:#1d2129;font-size:16px;font-weight:400;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;border-bottom:1px solid #f3f4f6}.table .title .totalNum[data-v-2649a100]{color:#6b7280;font-size:14px;font-weight:400}.table .tabCon[data-v-2649a100]{width:100%;padding:20px 20px 0 20px;height:100%}.table .tabCon .state[data-v-2649a100]{width:40px;height:24px;display:inline-block;opacity:1;border-radius:12px;background:rgba(0,180,42,.1);color:#00b42a;font-size:12px;font-weight:400}.table .tabCon .puase[data-v-2649a100]{background:rgba(245,63,63,.1);color:#f53f3f}.table .tabCon .el-table[data-v-2649a100]{height:calc(100% - 100px)!important}.el-table thead tr[data-v-2649a100],[data-v-2649a100] .el-table thead th{background-color:#f9fafb!important}[data-v-2649a100] .el-table--border td,[data-v-2649a100] .el-table--border th,[data-v-2649a100] .el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:unset!important}.el-table--border[data-v-2649a100],.el-table--group[data-v-2649a100]{border:unset!important}.el-table[data-v-2649a100]:before,[data-v-2649a100] .el-table--border:after,[data-v-2649a100] .el-table--group:after{background-color:unset!important}[data-v-2649a100] .el-table .el-table__body-wrapper td,[data-v-2649a100] .el-table .el-table__body-wrapper th.is-leaf{border-bottom:unset!important}.el-pagination[data-v-2649a100]{position:absolute;right:30px;margin-top:10px}[data-v-2649a100] .el-pager li{border:1px solid #d1d5db;border-radius:4px}[data-v-2649a100] .el-pager li.active{background:#165dff!important;color:#fff!important;border:unset!important}[data-v-2649a100] .el-dialog__title{padding:2px 10px;border-left:3px solid #165dff;font-size:16px;font-weight:400;color:#1d2129}[data-v-2649a100] .avatar-uploader .el-upload{border:1px dashed #dcdfe6;border-radius:6px;cursor:pointer;position:relative;overflow:hidden;width:100px;height:100px}[data-v-2649a100] .avatar-uploader .el-upload:hover{border-color:#409eff}[data-v-2649a100] .avatar-uploader-icon{font-size:28px;color:#8c939d;width:100px;height:100px;line-height:100px;text-align:center}[data-v-2649a100] .avatar{width:100px;height:100px;display:block}[data-v-2649a100] .el-dialog__body{padding:10px 20px 0 20px}[data-v-2649a100] .el-upload__tip{height:25px;line-height:25px}.show-pwd[data-v-2649a100]{position:absolute;right:10px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}[data-v-2649a100] .no-status-icon .el-input__icon:after,[data-v-2649a100] .no-status-icon .el-input__icon:before{display:none!important}[data-v-2649a100] .el-table__body-wrapper{max-height:calc(100% - 45px)!important;overflow-y:auto!important}[data-v-2649a100] .userImg{width:32px;height:32px;border-radius:16px}

View File

@ -0,0 +1 @@
.el-row[data-v-a64d02ba]{margin-bottom:20px}.el-row[data-v-a64d02ba]:last-child{margin-bottom:0}.el-col[data-v-a64d02ba]{border-radius:4px}.grid-content[data-v-a64d02ba]{background:#fff;border:1px solid #f3f4f6;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05),0 0 0 transparent,0 0 0 transparent;box-shadow:0 1px 2px rgba(0,0,0,.05),0 0 0 transparent,0 0 0 transparent;border-radius:8px}.userNum[data-v-a64d02ba]{height:10vh;line-height:10vh;min-height:60px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px}.userNum .img[data-v-a64d02ba]{width:48px;height:48px;margin-left:15px;line-height:100%}.userNum .img .svg-icon[data-v-a64d02ba]{width:100%;height:100%;vertical-align:baseline!important}.userNum .numCon[data-v-a64d02ba]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:1}.userNum .numCon div[data-v-a64d02ba]:first-child{width:100px;height:20px;line-height:20px;font-size:14px;font-weight:400;color:#6b7280;text-align:left;margin-top:2vh}.userNum .numCon div[data-v-a64d02ba]:last-child{width:100px;height:32px;font-size:24px;font-weight:400;color:#1d2129;margin-top:5px}.search[data-v-a64d02ba]{height:8vh;min-height:45px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px}.search .el-input[data-v-a64d02ba]{width:15vw;margin-left:20px;min-width:170px}.search .el-select[data-v-a64d02ba]{width:16vw;min-width:160px}.search .addUser[data-v-a64d02ba]{position:absolute;right:160px}.search .delUser[data-v-a64d02ba]{position:absolute;right:30px}.table[data-v-a64d02ba]{height:65vh}.table .title[data-v-a64d02ba]{width:100%;height:50px;padding:0 20px;line-height:50px;color:#1d2129;font-size:16px;font-weight:400;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;border-bottom:1px solid #f3f4f6}.table .title .totalNum[data-v-a64d02ba]{color:#6b7280;font-size:14px;font-weight:400}.table .tabCon[data-v-a64d02ba]{width:100%;padding:20px 20px 0 20px;height:100%}.table .tabCon .state[data-v-a64d02ba]{width:40px;height:24px;display:inline-block;opacity:1;border-radius:12px;background:rgba(0,180,42,.1);color:#00b42a;font-size:12px;font-weight:400}.table .tabCon .puase[data-v-a64d02ba]{background:rgba(245,63,63,.1);color:#f53f3f}.table .tabCon .el-table[data-v-a64d02ba]{height:calc(100% - 100px)!important}.el-table thead tr[data-v-a64d02ba],[data-v-a64d02ba] .el-table thead th{background-color:#f9fafb!important}[data-v-a64d02ba] .el-table--border td,[data-v-a64d02ba] .el-table--border th,[data-v-a64d02ba] .el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:unset!important}.el-table--border[data-v-a64d02ba],.el-table--group[data-v-a64d02ba]{border:unset!important}.el-table[data-v-a64d02ba]:before,[data-v-a64d02ba] .el-table--border:after,[data-v-a64d02ba] .el-table--group:after{background-color:unset!important}[data-v-a64d02ba] .el-table .el-table__body-wrapper td,[data-v-a64d02ba] .el-table .el-table__body-wrapper th.is-leaf{border-bottom:unset!important}.el-pagination[data-v-a64d02ba]{position:absolute;right:30px;margin-top:10px}[data-v-a64d02ba] .el-pager li{border:1px solid #d1d5db;border-radius:4px}[data-v-a64d02ba] .el-pager li.active{background:#165dff!important;color:#fff!important;border:unset!important}[data-v-a64d02ba] .el-dialog__title{padding:2px 10px;border-left:3px solid #165dff;font-size:16px;font-weight:400;color:#1d2129}[data-v-a64d02ba] .avatar-uploader .el-upload{border:1px dashed #dcdfe6;border-radius:6px;cursor:pointer;position:relative;overflow:hidden;width:100px;height:100px}[data-v-a64d02ba] .avatar-uploader .el-upload:hover{border-color:#409eff}[data-v-a64d02ba] .avatar-uploader-icon{font-size:28px;color:#8c939d;width:100px;height:100px;line-height:100px;text-align:center}[data-v-a64d02ba] .avatar{width:100px;height:100px;display:block}[data-v-a64d02ba] .el-dialog__body{padding:10px 20px 0 20px}[data-v-a64d02ba] .el-upload__tip{height:25px;line-height:25px}[data-v-a64d02ba] .el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{color:#606266!important}[data-v-a64d02ba] .el-transfer__buttons{width:180px!important}[data-v-a64d02ba] .el-transfer__button:first-child{padding-left:15px!important}[data-v-a64d02ba] .el-transfer__button:nth-child(2){margin-left:0!important}[data-v-a64d02ba] .el-table__body-wrapper{max-height:calc(100% - 45px)!important;overflow-y:auto!important}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-61b02ca0]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-61b02ca0]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-61b02ca0]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-61b02ca0]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-61b02ca0]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-61b02ca0]{position:relative}.login-container .title-container .title[data-v-61b02ca0]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-61b02ca0]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -34,7 +34,8 @@ export default {
addXlsx: '添加作战数据', addXlsx: '添加作战数据',
showAttr: '查看属性', showAttr: '查看属性',
importHeader: '导入表头', importHeader: '导入表头',
resetPerspective: '重置透视' resetPerspective: '重置透视',
addEvent: '添加态势事件',
}, },
iconTitle: { iconTitle: {
reset: '默认视角', reset: '默认视角',

View File

@ -34,6 +34,8 @@ export default {
showAttr: 'show Attribute', showAttr: 'show Attribute',
importHeader: 'import Header', importHeader: 'import Header',
resetPerspective: 'reset Perspective', resetPerspective: 'reset Perspective',
addEvent: 'add Event',
}, },
iconTitle: { iconTitle: {
reset: 'default view', reset: 'default view',

View File

@ -34,6 +34,7 @@ export default {
showAttr: '查看屬性', showAttr: '查看屬性',
importHeader: '導入表头', importHeader: '導入表头',
resetPerspective: '重置透視', resetPerspective: '重置透視',
addEvent: '添加態勢事件',
}, },
iconTitle: { iconTitle: {
reset: '默認視角', reset: '默認視角',

View File

@ -20,4 +20,30 @@ export const TsApi = {
data data
}) })
}, },
addTsSource: async (data: any) => {
return await request.post({
url: '/tsSource/add',
data
})
},
///tsSource/addModelSource
addTsModelSource: async (data: any) => {
return await request.post({
url: '/tsSource/addTsModelSource',
data
})
},
queryTsSource: async (data: any) => {
return await request.post({
url: '/tsSource/query',
data
})
},
// /tsEvent/query
queryTsEvent: async (data: any) => {
return await request.get({
url: "/tsEvent/query",
params: data
})
}
} }

View File

@ -27,21 +27,87 @@ import {$changeComponentShow} from "../../utils/communication";
const {getSelectedNodes, cusSelectNode, getSameLevel, cusNodeIcon, nodeType} = useTreeNode() const {getSelectedNodes, cusSelectNode, getSameLevel, cusNodeIcon, nodeType} = useTreeNode()
import {showRightMenuTs} from "./tree" import {showRightMenuTs} from "./tree"
import {TsApi} from "../../api/ts";
import {initMapData} from "./entity";
const rightMenuRef: any = ref() const rightMenuRef: any = ref()
const treeObj = ref() //树形的实例 const treeObj = ref() //树形的实例
const nodes: any = ref([]) let zNodes: any = ref([])//树形结构数据
let nodes: any = ref([])//选中的node节点
let input2 = ref('') let input2 = ref('')
let formData = new FormData()
formData.append('id', window["planId"])
onMounted(() => { onMounted(() => {
let data = [
{ // let data = []
name: "88",
sourceType: "directory"
}
]
treeObj.value = $.fn.zTree.init($(`#treeDemos`), setting, data)
window.treeObj = treeObj.value
}) })
const initTreeCallBack = () => {
TsApi.queryTsSource(formData).then(async res => {
console.log('queryTsSource', res)
if (res.code == 200) {
for (let i = res.data.length - 1; i >= 0; i--) {
res.data[i].icon = await cusNodeIcon(res.data[i]);
}
zNodes.value = res.data
console.log("data", zNodes.value)
treeObj.value = $.fn.zTree.init($(`#treeDemos`), setting, zNodes.value)
window.treeObj = treeObj.value
}
console.log("initTreeCallBack++++++++++++++++++++", zNodes.value)
let arr = zNodes.value
let layerTypes = [
"arcgisWximagery",
"arcgisBlueImagery",
"ArcgisLWImagery",
"gdlwImagery",
"gdwxImagery",
"gdslImagery",
"layer",
];
let layers: any = []
for (let i = 0; i < arr.length; i++) {
if (arr[i].sourceType === 'directory') {
continue
}
let detail = JSON.parse(arr[i].detail || '{}')
let params = JSON.parse(arr[i].params || '{}')
if (!detail.name) {
detail.name = arr[i].sourceName
}
if (!detail.id) {
detail.id = arr[i].id
}
if (layerTypes.includes(arr[i].sourceType)) {
layers.push(
{
sourceType: arr[i].sourceType,
detail: {...detail, ...params}
}
)
} else {
initMapData(arr[i].sourceType, {...detail, ...params})
}
}
layers.sort((obj1, obj2) => {
return obj1.detail.layerIndex - obj2.detail.layerIndex;
});
if (window.earth_ts) {
for (let i = 0; i < layers.length; i++) {
// initMapData(layers[i].sourceType, layers[i].detail, null)
}
}
})
}
const onDblClick = (event: MouseEvent, treeId: string, treeNode: any) => {
let entityObject
entityObject = (window as any)._entityMap.get(treeNode.id)
entityObject.flyTo()
}
const onClick = (event: MouseEvent, treeId: string, treeNode: any) => { const onClick = (event: MouseEvent, treeId: string, treeNode: any) => {
console.log('selectNode', treeNode) console.log('selectNode', treeNode)
@ -131,20 +197,21 @@ const setting = {
data: { data: {
key: { key: {
//zdatas数据中表示节点name的属性key //zdatas数据中表示节点name的属性key
name: "name", name: "sourceName",
checked: "is_show", checked: "isShow",
}, },
simpleData: { simpleData: {
enable: true, enable: true,
idKey: "id", idKey: "id",
pIdKey: "p_id", pIdKey: "parentId",
nameKey: "name", nameKey: "sourceName",
}, },
}, },
callback: { callback: {
onMouseDown: onMouseDown, onMouseDown: onMouseDown,
onRightClick: rightClick, onRightClick: rightClick,
onClick: onClick, onClick: onClick,
onDblClick: onDblClick
/* /*
onClick: this.onClick, onClick: this.onClick,
onDblClick: this.onDblClick, onDblClick: this.onDblClick,
@ -162,8 +229,11 @@ const setting = {
beforeClick: this.zTreeBeforeClick, beforeClick: this.zTreeBeforeClick,
onCheck: this.onCheck*/ onCheck: this.onCheck*/
}, },
}
}
defineExpose({
initTreeCallBack
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -189,6 +259,19 @@ const setting = {
height: 100%; height: 100%;
} }
} }
:deep("li a.curSelectedNode") {
background-color: #ffe6b0 !important;
}
.ztree {
li {
a.curSelectedNode {
}
}
}
} }
:deep(.el-input__wrapper), :deep(.el-input__inner ) { :deep(.el-input__wrapper), :deep(.el-input__inner ) {

View File

@ -21,12 +21,14 @@
//@ts-nocheck //@ts-nocheck
import {computed, onMounted, ref} from "vue" import {computed, onMounted, ref} from "vue"
const props = defineProps(['eventList',])
let columns = ref([{name: '事件名称', key: "name", style: "flex:auto"}, let columns = ref([{name: '事件名称', key: "name", style: "flex:auto"},
{name: '开始时间', key: "start_time", style: "width:120px"}, {name: '开始时间', key: "start_time", style: "width:120px"},
{name: '持续时间', key: "duration_time", style: "width:70px"}]) {name: '持续时间', key: "duration_time", style: "width:70px"}])
let eventList = ref([]) // let eventList = ref([])
let style = ref({}) let style = ref({})
eventList.value = window['tsObj']._Store._tasks // eventList.value = window['tsObj']._Store._tasks
// 格式化时间 // 格式化时间
let format = (key, val) => { let format = (key, val) => {
if ('start_time' == key) { if ('start_time' == key) {

View File

@ -7,7 +7,7 @@
<div <div
v-for="item in menus" v-for="item in menus"
class="itemBox" class="itemBox"
@click="itemClick(item, eventBus)" @click="itemClicks(item)"
> >
<div class="itemIcon"> <div class="itemIcon">
<svg-icon :name="item.key" :size="14"></svg-icon> <svg-icon :name="item.key" :size="14"></svg-icon>
@ -32,12 +32,19 @@ import {useI18n} from 'vue-i18n'
import {ref} from 'vue' import {ref} from 'vue'
import {useRightOperate} from "./rightOperate"; import {useRightOperate} from "./rightOperate";
import {useRightMenu} from "../../components/tree/components/hooks/rightMenu"; import {useRightMenu} from "../../components/tree/components/hooks/rightMenu";
import {$changeComponentShow} from "../../../utils/communication";
const {t} = useI18n() const {t} = useI18n()
const {rightMenus} = useRightOperate() const {rightMenus} = useRightOperate()
const menus: any = ref([]) //右侧菜单 const menus: any = ref([]) //右侧菜单
const rightClickTreeNode: any = ref() const rightClickTreeNode: any = ref()
const {itemClick} = useRightMenu() const {itemClick} = useRightMenu()
const eventBus: any = inject('bus')
const itemClicks = (item) => {
itemClick(item, eventBus)
$changeComponentShow('.rightMenuTs', false)
}
const initMenus = (arr: any, treeNode: any) => { const initMenus = (arr: any, treeNode: any) => {
let rightMenu: any = [] let rightMenu: any = []
console.log('rightMenu2222', rightMenu) console.log('rightMenu2222', rightMenu)
@ -67,8 +74,11 @@ defineExpose({
user-select: none; user-select: none;
width: 8.5vw; width: 8.5vw;
height: 23vh; height: 23vh;
border: 1px solid red; //border: 1px solid red;
visibility: hidden; visibility: hidden;
background-color: rgba(0, 0, 0, 0.5);
border: 1.5px solid;
border-image: linear-gradient(137.95deg, rgba(var(--color-base1), 1) 6.25%, var(--color-border1) 100%) 1.5;
.menuItem { .menuItem {
//padding: 1vh .5vw; //padding: 1vh .5vw;

View File

@ -1,13 +1,146 @@
import {$changeComponentPop} from "../../../utils/communication";
import {ipcRenderer} from "electron";
import {addMapSource, initMapData} from "../entity";
import {TsApi} from "../../../api/ts";
import {ElMessage} from "element-plus";
import {useTreeNode} from "../../components/tree/hooks/treeNode";
const {cusAddNodes} = useTreeNode()
function getLastPathComponent(path, extensionsToRemove = []) {
// 处理路径分隔符
const normalizedPath = path.replace(/\\/g, '/');
const lastComponent = normalizedPath.split('/').pop();
// 如果没有提供需要移除的后缀列表,直接返回原始名称
if (extensionsToRemove.length === 0) return lastComponent;
// 检查是否匹配任何需要移除的后缀
for (const ext of extensionsToRemove) {
//@ts-ignore
const extWithDot = ext.startsWith('.') ? ext : `.${ext}`;
if (lastComponent.endsWith(extWithDot)) {
return lastComponent.slice(0, -extWithDot.length);
}
}
return lastComponent;
}
export const useRightOperate = () => { export const useRightOperate = () => {
const addDirectory = () => { const addDirectory = () => {
// $changeComponentPop('.adddirectoryBox', true) $changeComponentPop('.adddirectoryBox', true)
console.log("addDirectory") console.log("addDirectory")
} }
const addResource = () => { const addResource = () => {
console.log("addResource") console.log("addResource")
const {ipcRenderer} = require('electron')
const options = {
properties: ['openFile'], // 允许选择多个文件
filters: [
{name: '模型、影像、地形', extensions: ['clt', 'mbtiles', 'pak', /*'json', 'jct'*/]},
// {name: '矢量数据', extensions: ['kmz', 'kml', 'shp', 'tab', 'mif', 'geojson']},
]
};
let selectedNodes = window.treeObj.getSelectedNodes()
let node = selectedNodes && selectedNodes[selectedNodes.length - 1]
let parentId
if (node) {
if (node.sourceType === 'directory') {
parentId = node.id
} else {
parentId = node.parentId
}
}
ipcRenderer.send('open-directory-dialog', options);
// @ts-ignore
ipcRenderer.once('selectedItem', async (event, filePaths) => {
console.log(filePaths)
if (filePaths.length) {
let id = new YJ.Tools().randomString()
// 检查文件名是否有效
if (typeof filePaths[0] !== 'string' || filePaths[0].trim() === '') {
return false;
}
let item = filePaths[0]
// @ts-ignore
let name = getLastPathComponent(item, ['clt', 'json', 'pak', 'kml', 'kmz', 'shp', 'geojson', 'geoJson', 'czml', 'jct', 'mif', 'tab', 'csv']);
let sourceType = "layer";
if (item.endsWith(".clt") || item.endsWith(".json")) {
sourceType = "tileset";
} else if (item.endsWith(".pak")) {
sourceType = "Terrain";
} else if (item.endsWith(".kml") || item.endsWith(".kmz")) {
sourceType = "kml";
} else if (item.endsWith(".shp")) {
sourceType = "shp";
} else if (item.endsWith(".geojson") || item.endsWith(".geoJson")) {
sourceType = "geojson";
} else if (item.endsWith(".czml")) {
sourceType = "czml";
} else if (item.endsWith(".jct")) {
sourceType = "bim";
} else if (item.endsWith(".mif")) {
sourceType = "shp";
} else if (item.endsWith(".tab")) {
sourceType = "shp";
} else if (item.endsWith(".csv")) {
sourceType = "csv";
}
// 获取最后一个点的位置
const lastDotIndex = filePaths[0].lastIndexOf('.');
// 如果没有点或者点是最后一个字符,则不是有效的文件后缀
if (lastDotIndex === -1 || lastDotIndex === filePaths[0].length - 1) {
return false;
}
let params2: any = {
id: id,
show: true,
}
if (item.endsWith(".mbtiles")) {
params2.alpha = 1
params2.brightness = 1
params2.layerIndex = 99999
}
let params: any = {
id: id,
sourcePath: filePaths[0],
parentId: parentId,
params: params2,
planId: window['planId']
}
// addMapSource(sourceType, parentId, params)
// 先调接口再渲染并上树
let res = await TsApi.addTsModelSource(params)
console.log('res', res)
if (res.code === 0 || res.code === 200) {
ElMessage({
message: '添加成功',
type: 'success'
})
res.data.params = JSON.parse(res.data.params)
if (!res.data.params.name) {
res.data.params.name = res.data.sourceName
}
if (!res.data.params.id) {
res.data.params.id = res.data.id
}
let detail = JSON.parse(res.data.detail)
let mapParams = {...detail, ...res.data.params}
initMapData(sourceType, mapParams, entity => {
entity.flyTo()
let selectedNode = window.treeObj.getNodeByParam('id', parentId)
//
cusAddNodes(window.treeObj, selectedNode, [res.data], true)
})
}
}
})
} }
const addEvent = () => { const addEvent = (eventBus) => {
$(".newEvent")[0].style.display = "block" eventBus.emit('openAddEvent', true)
} }
const rightMenus: any = reactive({ const rightMenus: any = reactive({
addDirectory: { addDirectory: {

View File

@ -0,0 +1,274 @@
<template>
<div class="tsdirectory">
<div class="box">
<div class="boxHeader nav">
<!-- <span></span> -->
<span class="label">{{ title }}</span>
<div class="close-box" @click="close">
<span class="close"></span>
<i>x</i>
</div>
</div>
<div class="boxBody">
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="80px"
@keyup.enter.native="submitForm(ruleForm)">
<el-form-item label="名称:" prop="sourceName">
<!-- @input="removeSpaces" -->
<el-input v-model.trim="form.sourceName" placeholder="图层文件夹"></el-input>
</el-form-item>
<el-form-item>
<div class="btnOption">
<el-button type="primary" @click="submitForm(ruleForm)">确定</el-button>
<el-button @click="cancel">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {$changeComponentPop} from '@/utils/communication'
import {throttle} from '@/utils/index'
import {ElMessage, FormInstance} from 'element-plus'
import {TreeApi} from '@/api/tree'
import {useTreeNode} from '@/views/components/tree/hooks/treeNode'
import {addMapSource} from "../entity";
const {getKeyOfSelectedNode, getSelectedNode, cusAddNodes, getSameLevel} = useTreeNode()
const title = ref('添加文件夹')
let form: any = reactive({
sourceName: '图层'
})
const ruleForm = ref()
const rules = reactive({
sourceName: [{required: true, message: '请输入名称', trigger: 'blur'}]
})
const removeSpaces = (value: string) => {
form.sourceName = value.replace(/\s/g, '')
}
const close = () => {
$changeComponentPop('.adddirectory', false)
}
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
add()
} else {
console.log('error submit!', fields)
}
})
}
const add = throttle(async () => {
let parentId = getKeyOfSelectedNode(window.treeObj, 'id')
let fnone = getSelectedNode(window.treeObj)
addMapSource('directory', parentId, {id: new YJ.Tools().randomString(), name: form.sourceName,}, res => {
if (res.code == 0 || res.code == 200) {
ElMessage({
message: '添加成功',
type: 'success'
})
cancel()
}
})
/* const res: any = await TreeApi.addDirectory({
id: new YJ.Tools().randomString(),
sourceName: form.sourceName,
parentId: parentId || undefined
})
console.log(res)
if (res.code == 0 || res.code == 200) {
const node = {
...res.data
}
let addNode = await cusAddNodes(window.treeObj, getSelectedNode(window.treeObj), [node], true) //添加节点
//获取该节点下的同级节点
const someNode: any = getSameLevel(window.treeObj, addNode[0])
console.log('someNode', someNode)
const newNode = someNode.map((item: any) => {
let index = item.getIndex()
item.treeIndex = index + 1
return {
...item,
treeIndex: item.getIndex()
}
})
ElMessage({
message: '添加成功',
type: 'success'
})
cancel()
} else {
ElMessage({
message: '添加失败',
type: 'error'
})
}*/
// console.log(res)
}, 3000)
////上传或修改树的层级
// const updateTree = async (newNode: any) => {
// const list = newNode.map((item: any) => {
// return {
// id: item.id,
// treeIndex: item.treeIndex,
// parentId: item.parentId
// }
// })
// console.log(list)
// const res = await TreeApi.updateTree({ list })
// if (res.code == 0) {
// ElMessage({
// message: '添加成功',
// type: 'success'
// })
// cancel()
// } else {
// ElMessage({
// message: '添加失败',
// type: 'error'
// })
// }
// }
const cancel = () => {
$changeComponentPop('.tsdirectory', false)
form.sourceName = '图层'
ruleForm.value?.resetFields()
}
</script>
<style lang="scss">
.tsdirectory {
user-select: none;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
.box {
width: 20vw;
height: 10vw;
display: flex;
flex-direction: column;
position: absolute;
left: 50%;
top: 45%;
transform: translate(-50%, -50%);
color: var(--color-sdk-auxiliary-public);
font-size: 14px;
// z-index: 999999;
background: linear-gradient(0deg, var(--color-sdk-bg-gradual)), rgba(0, 0, 0, 0.6);
border: 1.5px solid;
backdrop-filter: blur(2px);
border-image: linear-gradient(to bottom, var(--color-sdk-gradual)) 1;
text-align: left;
font-family: 'sy-boldface';
.boxHeader {
display: flex;
justify-content: space-between;
font-size: 18px;
line-height: 46px;
padding: 5px 16px 5px 16px;
height: 46px;
.label {
font-family: 'Ali-mother-counts-bold';
font-size: 18px;
font-weight: 400;
color: rgba(255, 255, 255, 1);
text-align: left;
text-shadow: 0px 0px 9px rgb(20 118 255);
}
.close-box {
position: absolute;
top: -1px;
right: 0;
height: 30px;
cursor: pointer;
width: 30px;
border-radius: 0 0 0 90%;
overflow: hidden;
.close {
display: block;
width: 100%;
height: 100%;
background: rgba(var(--color-base1), 1);
opacity: 0.5;
}
i {
font-style: normal;
font-size: 18px;
font-weight: 900;
position: absolute;
top: -13px;
left: 11px;
}
}
}
.boxBody {
flex: auto;
flex-direction: column;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 20px;
.el-form--label-top .el-form-item__label {
padding: 0;
}
.el-form-item {
margin-bottom: 10px;
}
.el-form-item__label {
color: #fff;
}
.el-input__wrapper {
background-color: rgba(0, 0, 0, 0.5);
border: 0.2px solid rgba(var(--color-base1), 0.5);
box-shadow: 0 0 0 0.2px rgba(var(--color-base1), 0.5) inset !important;
/* 新增此行 */
}
.el-input__inner {
background-color: transparent;
color: #fff;
// border-color: rgba(var(--color-base1), 0.5) !important;
}
.btnOption {
margin-top: 5px;
text-align: right;
}
.el-button {
background: rgba(var(--color-base1), 0.2);
border-color: rgba(var(--color-base1), 0.5) !important;
color: #ffffff;
padding: 8px 16px;
}
.el-button:hover {
border-color: rgba(var(--color-base1), 1) !important;
}
}
}
}
</style>

View File

@ -25,7 +25,7 @@
<div class="layoutBoxs"> <div class="layoutBoxs">
<div class="layout"> <div class="layout">
<!-- 左侧事件列表 --> <!-- 左侧事件列表 -->
<grid></grid> <grid :eventList="TSOBJ._Store._tasks"></grid>
<!--右侧时间轴容器--> <!--右侧时间轴容器-->
<div class="TLContainer"> <div class="TLContainer">
<div class="timelineCursorBox" :style="{ left: `${cursorLeft || 0}px` }"> <div class="timelineCursorBox" :style="{ left: `${cursorLeft || 0}px` }">

View File

@ -4,10 +4,11 @@
<use xlink:href="#icon-tuichu"></use> <use xlink:href="#icon-tuichu"></use>
</svg> </svg>
<div id="earthContainer" class="fullSize"></div> <div id="earthContainer" class="fullSize"></div>
<cabin></cabin> <cabin ref="cabin"></cabin>
<element></element> <element></element>
<deduction :TSOBJ="tsOBJ"></deduction> <deduction :TSOBJ="tsOBJ"></deduction>
<newEvent></newEvent> <newEvent></newEvent>
<addDirectory class="adddirectoryBox absolute zIndex999"></addDirectory>
</div> </div>
</template> </template>
@ -18,10 +19,13 @@ import Cabin from "./cabin.vue"
import Element from "./element.vue" import Element from "./element.vue"
import NewEvent from "./newEvent.vue" import NewEvent from "./newEvent.vue"
import Deduction from "./deduction.vue"; import Deduction from "./deduction.vue";
import AddDirectory from './components/tsdirectory.vue'
import {TS} from "./sdk"; import {TS} from "./sdk";
import * as domain from "domain"; import * as domain from "domain";
import {TsApi} from "../../api/ts";
let tsOBJ = reactive({}) let cabin = ref()
let tsOBJ = ref({})
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
let params:any = {} let params:any = {}
@ -33,6 +37,7 @@ for (const routeQueryKey in route.query) {
} }
} }
console.log("params", params) console.log("params", params)
window.planId = params.id
// 通过planID获取方案包含的所有事件 // 通过planID获取方案包含的所有事件
let getEventList = () => { let getEventList = () => {
@ -48,13 +53,19 @@ let getEventList = () => {
duration_time: (i * 5 + 10) duration_time: (i * 5 + 10)
}) })
} }
let formData = {planId: window['planId']}
TsApi.queryTsEvent(formData).then(res => {
if (res.code == 200) {
tsOBJ.value._Store._tasks = res.data
}
})
newTS(params, events) newTS(params, events)
} }
// 新建态势推演对象 // 新建态势推演对象
let newTS = (params, events) => { let newTS = (params, events) => {
window['tsObj'] = new TS({name: params.name, tasks: events, startTimestamp: params.start_time}) window['tsObj'] = new TS({name: params.name, tasks: events, startTimestamp: params.start_time})
tsOBJ = window['tsObj'] tsOBJ.value = window['tsObj']
window['tsAction'] = window['tsObj'].initAction() window['tsAction'] = window['tsObj'].initAction()
console.log("window['tsObj']", window['tsObj']) console.log("window['tsObj']", window['tsObj'])
@ -79,6 +90,8 @@ const createEarth = async () => {
setTimeout(() => { setTimeout(() => {
new YJ.Tools((window as any).earth_ts).flyHome() new YJ.Tools((window as any).earth_ts).flyHome()
}, 1000) }, 1000)
console.log("createEarth++++++++++++++++++++")
cabin.value.initTreeCallBack()
} }
const closeSituationEdit = () => { const closeSituationEdit = () => {
router.back() router.back()
@ -96,5 +109,9 @@ const closeSituationEdit = () => {
height: 2.2222222222vh !important; height: 2.2222222222vh !important;
cursor: pointer; cursor: pointer;
} }
.adddirectoryBox {
display: none;
}
} }
</style> </style>

View File

@ -34,7 +34,7 @@
</div> </div>
<div class="list" v-if="currentTypeId!=''"> <div class="list" v-if="currentTypeId!=''">
<div v-for="item in elementList" class="itemBox"> <div v-for="item in elementList" class="itemBox" @click="addMarker(item)">
<div class="imgbg"> <div class="imgbg">
<img :src="service + (item.posterDataUrl||item.militaryDataUrl)"/> <img :src="service + (item.posterDataUrl||item.militaryDataUrl)"/>
</div> </div>
@ -56,8 +56,11 @@ import {ref, onMounted} from "vue";
import {Search} from '@element-plus/icons-vue' import {Search} from '@element-plus/icons-vue'
import {ModelApi} from "../../api/model"; import {ModelApi} from "../../api/model";
import {GraphApi} from "../../api/graphLabel"; import {GraphApi} from "../../api/graphLabel";
import {addMapSource} from "./entity";
import {addMapSource} from "./entity";
import {useTreeNode} from "../components/tree/hooks/treeNode";
const {getSelectedNodes} = useTreeNode()
const service = ref(localStorage.getItem('ip')) const service = ref(localStorage.getItem('ip'))
interface Tree { interface Tree {
@ -72,17 +75,17 @@ const defaultProps = {
const activIndex = ref(0) const activIndex = ref(0)
const tabs = [ const tabs = [
{name: "人工模型", dataType: 'tree', key: "model"}, {name: "人工模型", dataType: 'tree', key: "model",},
{name: "军事标绘", dataType: 'tree', key: "graph"}, {name: "军事标绘", dataType: 'tree', key: "graph", funName: 'DrawPoint',},
{ {
name: "基础标绘", dataType: 'list', children: name: "基础标绘", dataType: 'list', children:
[ [
{name: "点", source_name: "点标注", funName: 'DrawPoint', type: "point"}, {name: "点", source_name: "点标注", funName: 'DrawPoint', type: "point"},
{name: "线", source_name: "", funName: 'DrawPolyline', type: ""}, {name: "线", source_name: "线标注", funName: 'DrawPolyline', type: "line"},
{name: "面", source_name: "", funName: 'DrawPolygon', type: ""}, {name: "面", source_name: "面标注", funName: 'DrawPolygon', type: "panel"},
{name: "圆", source_name: "", funName: 'DrawCircle', type: ""}, {name: "圆", source_name: "圆标注", funName: 'DrawCircle', type: "circle"},
{name: "攻击箭头", source_name: "", funName: 'DrawAttackArrow', type: ""}, {name: "攻击箭头", source_name: "攻击箭头", funName: 'DrawAttackArrow', type: "attackArrow"},
{name: "钳形箭头", source_name: "", funName: 'DrawPincerArrow', type: ""} {name: "钳形箭头", source_name: "钳形箭头", funName: 'DrawPincerArrow', type: "pincerArrow"}
] ]
}, },
{name: "特效", dataType: 'list', children: [{name: "火焰"}]}, {name: "特效", dataType: 'list', children: [{name: "火焰"}]},
@ -135,11 +138,18 @@ const getModelListByType = (id) => {
if (activIndex.value == 0) { if (activIndex.value == 0) {
formData.append('modelTypeId', id) formData.append('modelTypeId', id)
ModelApi.showModelByType(formData).then((res) => { ModelApi.showModelByType(formData).then((res) => {
res.data.forEach(item => {
item.funName = 'DrawPoint'
item.type = 'model'
})
elementList.value = res.data elementList.value = res.data
}) })
} else { } else {
formData.append('militaryTypeId', id) formData.append('militaryTypeId', id)
GraphApi.showModelByType(formData).then((res) => { GraphApi.showModelByType(formData).then((res) => {
res.data.forEach(item => {
item.funName = 'DrawPoint'
})
elementList.value = res.data elementList.value = res.data
}) })
} }
@ -159,11 +169,41 @@ let getGraphTypeList = async () => {
} }
// 添加标绘 // 添加标绘
let addMarker = (item) => { let addMarker = (item) => {
console.log("绘制" + item.name) let nodes = getSelectedNodes(window['treeObj'])
console.log("绘制", item)
console.log("获取选中的节点", nodes)
let id = new YJ.Tools().randomString()
let pId = -1
if (nodes.length) {
pId = nodes[0].sourceType == 'directory' ? nodes[0].id : nodes[0].parentId
}
// let pId = nodes.length >= 1 ? nodes[0].id : -1
window.draw = new YJ.Draw[item.funName](earth_ts) window.draw = new YJ.Draw[item.funName](earth_ts)
window.draw.start((a, position) => { window.draw.start((a, position) => {
console.log(position) console.log(position)
addMapSource({id: 777, type: item.type, name: item.source_name, position}) if (position != undefined) {
let obj = {id, name: item.source_name, position}
switch (item.type) {
case 'model':
obj.modelDataUrl = item.modelDataUrl
obj.name = item.modelName
break
case 'line':
case 'panel':
case 'attackArrow':
case 'pincerArrow':
delete obj.position
obj.positions = position
break
case 'circle':
obj.center = position.center
obj.radius = position.radius
break
}
addMapSource(item.type, pId, obj)
}
}) })
} }

View File

@ -1,18 +1,44 @@
export function addMapSource(option) { import {TsApi} from "../../api/ts";
console.log("添加到地球上", option) import {useTreeNode} from '@/views/components/tree/hooks/treeNode'
let id = option.id || new YJ.Tools().randomString()
let name = option.name
let entityObject
let options
let baseURL = localStorage.getItem('ip')
switch (option.type) {
case 'point':
console.log({id, name, position: option.position})
entityObject = new YJ.Obj.BillboardObject(window['earth_ts'], {id, name, position: option.position})
console.log("添加dian")
break;
}
const {cusAddNodes, getSelectedNode} = useTreeNode()
export function initMapData(type, data, cb: any = null) {
console.log("initMapData", type, data)
let baseURL = localStorage.getItem('ip')
let options
let entityObject
switch (type) {
case 'point':
entityObject = new YJ.Obj.BillboardObject(window['earth_ts'], data)
break
case 'model':
entityObject = new YJ.Obj.Model(window['earth_ts'], data)
break
case 'line':
entityObject = new YJ.Obj.PolylineObject(window['earth_ts'], data)
break
case 'panel':
entityObject = new YJ.Obj.PolygonObject(window['earth_ts'], data)
break
case 'circle':
entityObject = new YJ.Obj.CircleObject(window['earth_ts'], data)
break
case 'attackArrow':
entityObject = new YJ.Obj.AttackArrowObject(window['earth_ts'], data)
break
case 'pincerArrow':
entityObject = new YJ.Obj.PincerArrowObject(window['earth_ts'], data)
break
case 'tileset':
data.host = baseURL
entityObject = new YJ.Obj.Tileset(window['earth_ts'], data)
entityObject.load((res) => {
cb && cb(entityObject)
})
break
}
if (entityObject) { if (entityObject) {
function getOptions() { function getOptions() {
let opt = structuredClone(entityObject.options) let opt = structuredClone(entityObject.options)
@ -21,8 +47,73 @@ export function addMapSource(option) {
} }
options = getOptions() options = getOptions()
} if (entityObject.options.id) {
console.log('options', options) (window as any)._entityMap.set(entityObject.options.id, entityObject)
// 进数据库 }
// 上树 return options
} else return null
} }
export function addMapSource(type, pId, option, cb: any = null) {
console.log("添加到地球上", option)
let options
/*switch (type) {
case 'point':
data = {id, name, position: option.position}
break;
case 'line':
case 'panel':
data = {id, name, positions: option.positions}
break
case 'circle':
data = {id, name, positions: option.positions}
break
case 'attackArrow':
break
case 'pincerArrow':
break
case 'model':
data = {
id,
name,
position: option.position,
url: baseURL + option.modelDataUrl,
maximumScale: 1,
rotate: {
x: 0,
y: 0,
z: 0
}
}
break
}*/
options = initMapData(type, option)
// 进数据库
let dbOption = {
"id": option.id,
"sourceName": option.name,
"sourceType": type,
"sourcePath": "",
"parentId": pId,
"treeIndex": 0,
"isShow": 1,
"detail": JSON.stringify(options) || '{}',
"params": "",
"planId": window['planId']
}
console.log('dbOption', dbOption)
TsApi.addTsSource(dbOption).then(res => {
console.log("addTsSource", res)
cb && cb(res)
// 上树
let selectedNode = window.treeObj.getNodeByParam('id', pId)
cusAddNodes(window.treeObj, selectedNode, [dbOption], true)
})
}

View File

@ -151,7 +151,10 @@ const getList = (params:any = null) => {
formData.append(paramsKey, params[paramsKey]) formData.append(paramsKey, params[paramsKey])
} }
} }
} }
formData.append('username', params["createdBy"])
} }
TsApi.planList(formData).then(res => { TsApi.planList(formData).then(res => {
console.log(res) console.log(res)
@ -175,7 +178,7 @@ const toTSEdit = (row) => {
console.log("当前推演方案", row) console.log("当前推演方案", row)
router.push({ router.push({
name: 'tsEdit', // 必须用 name 匹配路由,不能用 path name: 'tsEdit', // 必须用 name 匹配路由,不能用 path
query: {id: 123, name: "战时推演", start_time: 946684800000} query: {id: row.id, name: row.name, start_time: new Date(row.simulationStartTime).getTime()}
}) })
} }
const delPlan = (id) => { const delPlan = (id) => {

View File

@ -34,7 +34,7 @@
<el-date-picker <el-date-picker
v-model="form.datetime" v-model="form.datetime"
type="datetime" type="datetime"
placeholder="Select date and time" placeholder="选择触发时间"
/> />
</el-form-item> </el-form-item>
<el-form-item label="持续时间"> <el-form-item label="持续时间">
@ -78,7 +78,7 @@
<el-form-item> <el-form-item>
<div class="optionbtn"> <div class="optionbtn">
<el-button>确定</el-button> <el-button @click="addEvent">确定</el-button>
<el-button>取消</el-button> <el-button>取消</el-button>
</div> </div>
</el-form-item> </el-form-item>
@ -99,7 +99,7 @@ import type {RenderContentContext, TreeInstance} from 'element-plus'
const treeRef = ref<TreeInstance>() const treeRef = ref<TreeInstance>()
// 存储当前需要高亮的节点 key初始为空 // 存储当前需要高亮的节点 key初始为空
const currentKey = ref<number | null>(1); const currentKey = ref<number | string | null>("flicker");
interface Tree { interface Tree {
label: string label: string
@ -108,6 +108,7 @@ interface Tree {
const form = reactive({ const form = reactive({
name: '', name: '',
datetime: '',
}) })
const hour = ref(0) const hour = ref(0)
const minute = ref(0) const minute = ref(0)
@ -115,9 +116,10 @@ const second = ref(0)
const times = ref(0)//闪烁间隔 const times = ref(0)//闪烁间隔
const numbers = ref(0)//闪烁次数 const numbers = ref(0)//闪烁次数
const isContainModelPosition = ref(true) const isContainModelPosition = ref(true)
const eventBus: any = inject('bus')
form['datetime'] = new Date(2000, 1, 1, 12, 0, 0) // form['datetime'] = new Date(2000, 1, 1, 12, 0, 0)
const isShowPup = ref(true) const isShowPup = ref(false)
const eventTree: { children: ({ label: string } | { label: string })[]; id: string; label: string }[] = [ const eventTree: { children: ({ label: string } | { label: string })[]; id: string; label: string }[] = [
{ {
id: "normal", id: "normal",
@ -143,9 +145,25 @@ const handleNodeClick = (data: Tree, node, TreeNode, event) => {
currentKey.value = data.id; // data.id 为节点的唯一 key需与 tree 的 node-key 对应) currentKey.value = data.id; // data.id 为节点的唯一 key需与 tree 的 node-key 对应)
form.name = data.label form.name = data.label
} }
const addEvent = () => {
console.log(form)
}
eventBus.on('openAddEvent', (data, cb, type) => {
// selectCallback = cb
// addType.value = type
isShowPup.value = data
// if (data) {
// getModelList()
// getSetting()
// }
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.newEvent>div) {
position: absolute;
}
.newEvent { .newEvent {
position: absolute; position: absolute;
z-index: 99; z-index: 99;
@ -153,7 +171,6 @@ const handleNodeClick = (data: Tree, node, TreeNode, event) => {
//left: 50%; //left: 50%;
//width: 40vw; //width: 40vw;
//height: 50vh; //height: 50vh;
display: none;
.set_detail { .set_detail {
display: flex; display: flex;
@ -226,13 +243,18 @@ const handleNodeClick = (data: Tree, node, TreeNode, event) => {
} }
} }
:deep(.el-overlay-dialog) {
/*position: absolute;
bottom: auto;
right: auto;*/
}
:deep(.el-dialog) { :deep(.el-dialog) {
background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%), background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%),
rgba(0, 0, 0, 0.6); rgba(0, 0, 0, 0.6);
border: 1px solid #00c9ff; border: 1px solid #00c9ff;
padding: 0 !important; padding: 0 !important;
width: 30vw; //position: absolute;
height: 30vh;
width: 570px; width: 570px;
height: 323px; height: 323px;

View File

@ -11,28 +11,31 @@
</template> </template>
<div class="set_detail"> <div class="set_detail">
<el-form <el-form
ref="ruleFormRef"
style="max-width: 600px" style="max-width: 600px"
:model="sizeForm" :model="sizeForm"
label-width="auto" label-width="auto"
:label-position="'top'" :label-position="'top'"
:rules="rules"
> >
<el-form-item label="推演名称"> <el-form-item label="推演名称" prop="name" required>
<el-input v-model="sizeForm.name" placeholder="请填写名称"/> <el-input v-model="sizeForm.name" placeholder="请填写名称"/>
</el-form-item> </el-form-item>
<el-form-item label="仿真开始时间"> <el-form-item label="仿真开始时间" prop="simulationStartTime" required>
<el-date-picker <el-date-picker
v-model="sizeForm.date1" v-model="sizeForm.simulationStartTime"
type="datetime" type="datetime"
timezone="Asia/Shanghai"
value-format="YYYY-MM-DDTHH:mm:ss"
placeholder="请选择日期时间" placeholder="请选择日期时间"
/> />
</el-form-item> </el-form-item>
<el-form-item label="推演描述" prop="desc"> <el-form-item label="推演描述" prop="desc" required>
<el-input v-model="sizeForm.desc" type="textarea" placeholder="请输入内容描述"/> <el-input v-model="sizeForm.desc" type="textarea" placeholder="请输入内容描述"/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div class="optionbtn"> <div class="optionbtn">
<el-button @click="addPlan">确定</el-button> <el-button @click="addPlan(ruleFormRef)">确定</el-button>
<el-button>取消</el-button> <el-button>取消</el-button>
</div> </div>
</el-form-item> </el-form-item>
@ -46,30 +49,69 @@
<script lang="ts" setup> <script lang="ts" setup>
//@ts-nocheck //@ts-nocheck
import {ref, reactive,} from "vue"; import {ref, reactive,} from "vue";
import {ElMessage} from 'element-plus' import {ElMessage, FormInstance, FormRules} from 'element-plus'
import {TsApi} from "../../api/ts"; import {TsApi} from "../../api/ts";
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
const emit = defineEmits(['addCallback']); const emit = defineEmits(['addCallback']);
const isShowPup = ref(false) const isShowPup = ref(false)
const sizeForm = reactive({
interface RuleForm {
name: string,
simulationStartTime: string,
desc: string,
}
const ruleFormRef = ref<FormInstance>()
const sizeForm = reactive<RuleForm>({
name: '', name: '',
// date1: '', simulationStartTime: '',
desc: '', desc: '',
}) })
const addPlan = () => {
TsApi.addPlan({name: sizeForm.name, desc: sizeForm.desc}).then(res => { const rules = reactive<FormRules<RuleForm>>({
console.log(res) name: [
if (res.code == 200) { {required: true, message: '推演名称不能为空', trigger: 'blur'},
ElMessage({ ],
message: '操作成功', desc: [
type: 'success' {required: true, message: '推演描述不能为空', trigger: 'blur'},
}) ],
emit('addCallback'); simulationStartTime: [
{required: true, message: '仿真开始时间不能为空', trigger: 'blur'},
],
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!', fields)
} }
$(".newPlan")[0].style.display = "none"
}) })
} }
const addPlan = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
TsApi.addPlan(sizeForm).then(res => {
console.log(res)
if (res.code == 200) {
ElMessage({
message: '操作成功',
type: 'success'
})
emit('addCallback');
}
$(".newPlan")[0].style.display = "none"
})
} else {
console.log('提交失败', fields)
}
})
}
eventBus.on('openAddPlan', (data, cb, type) => { eventBus.on('openAddPlan', (data, cb, type) => {
// selectCallback = cb // selectCallback = cb
// addType.value = type // addType.value = type

View File

@ -49,7 +49,7 @@ export const showRightMenuTs = (event: any, treeObj: any, selectedNodes, nodeTyp
} }
} }
for (let i = arr.length - 1; i >= 0; i--) { for (let i = arr.length - 1; i >= 0; i--) {
if (['pictureLocation', 'importPanorama'].includes(arr[i])) { if (['pictureLocation', 'importPanorama', 'setView', 'resetView',].includes(arr[i])) {
arr.splice(i, 1); // 从索引 i 开始删除 1 个元素 arr.splice(i, 1); // 从索引 i 开始删除 1 个元素
} }
} }

View File

@ -79,21 +79,28 @@
<div class="col"> <div class="col">
<span class="label">阴影柔和度</span> <span class="label">阴影柔和度</span>
<el-input <el-input
class="input height" class="input height custom-number-input with-arrows"
type="number" type="number"
step="0.1" step="0.1"
min="0" min="0"
max="1" max="1"
v-model="weatherData.darkness" v-model="weatherData.darkness"
@change="changDarkness" @change="changDarkness"
/> >
<template #suffix>
<div class="custom-arrows">
<div class="arrow-up" @click="incrementValue"></div>
<div class="arrow-down" @click="decrementValue"></div>
</div>
</template>
</el-input>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<span class="label">倍数</span> <span class="label">倍数</span>
<el-input <el-input
class="input height" class="input height custom-number-input with-arrows arrows2"
type="number" type="number"
min="-9999999" min="-9999999"
max="999999999" max="999999999"
@ -102,6 +109,10 @@
size="small" size="small"
> >
<template #suffix> <template #suffix>
<div class="custom-arrows">
<div class="arrow-up" @click="incrementValue2"></div>
<div class="arrow-down" @click="decrementValue2"></div>
</div>
<span>X</span> <span>X</span>
</template> </template>
</el-input> </el-input>
@ -152,7 +163,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, onBeforeUnmount } from 'vue' import { reactive, onMounted, onBeforeUnmount, watch } from 'vue'
import { Decimal } from 'decimal.js'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import TimeLine from './timeLIne' import TimeLine from './timeLIne'
import { before } from 'node:test' import { before } from 'node:test'
@ -251,6 +263,41 @@ var weatherChange = () => {
timeline.setSpeed(weatherData.speed) timeline.setSpeed(weatherData.speed)
} }
} }
watch(
() => weatherData.darkness,
(newValue) => {
if (sunshine) {
sunshine.darkness = newValue
}
}
)
var incrementValue = () => {
if (weatherData.darkness < 1) {
const newDarkness = new Decimal(weatherData.darkness).add(0.1)
weatherData.darkness = Math.min(newDarkness, 1)
}
}
var decrementValue = () => {
if (weatherData.darkness > 0) {
const newDarkness = new Decimal(weatherData.darkness).sub(0.1)
weatherData.darkness = Math.max(newDarkness, 0)
}
}
watch(
() => weatherData.speed,
(newValue) => {
weatherData.currWeather = false
sunshine && (sunshine.speed = newValue)
timeline.setSpeed(newValue)
}
)
var incrementValue2 = () => {
weatherData.speed = new Decimal(weatherData.speed).add(1).toNumber()
}
var decrementValue2 = () => {
weatherData.speed = new Decimal(weatherData.speed).sub(1).toNumber()
}
var getCurrentTime = () => { var getCurrentTime = () => {
const now = new Date() const now = new Date()
const hours = String(now.getHours()).padStart(2, '0') const hours = String(now.getHours()).padStart(2, '0')
@ -313,6 +360,7 @@ var clickIcon = (item: any) => {
} }
var changDarkness = () => { var changDarkness = () => {
console.log('changDarkness')
sunshine && (sunshine.darkness = weatherData.darkness) sunshine && (sunshine.darkness = weatherData.darkness)
} }
var changSpeed = () => { var changSpeed = () => {
@ -597,13 +645,66 @@ var shadowChange = () => {
} }
} }
} }
/* 隐藏Webkit内核浏览器中的上下箭头及白色背景 */
.input ::v-deep(input::-webkit-outer-spin-button), input[type='number']::-webkit-outer-spin-button,
.input ::v-deep(input::-webkit-inner-spin-button) { input[type='number']::-webkit-inner-spin-button {
-webkit-appearance: none !important; -webkit-appearance: none;
appearance: none !important; }
margin: 0;
background: none; /* 移除白色背景 */ /* Firefox */
display: none; /* 彻底隐藏元素 */ input[type='number'] {
-moz-appearance: textfield;
}
.custom-number-input .el-input__inner {
line-height: 1px !important;
}
.custom-number-input.with-arrows {
position: relative;
}
.custom-number-input.with-arrows .custom-arrows {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 2px;
z-index: 1;
}
.custom-number-input.with-arrows.arrows2 .custom-arrows {
right: 17px;
}
.custom-number-input.with-arrows .arrow-up,
.custom-number-input.with-arrows .arrow-down {
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
cursor: pointer;
transition: all 0.2s ease;
}
.custom-number-input.with-arrows .arrow-up {
border-bottom: 6px solid #909399;
}
.custom-number-input.with-arrows .arrow-down {
border-top: 6px solid #909399;
}
.custom-number-input.with-arrows .arrow-up:hover {
border-bottom-color: rgba(var(--color-base1), 1);
}
.custom-number-input.with-arrows .arrow-down:hover {
border-top-color: rgba(var(--color-base1), 1);
}
/* 确保输入框有足够空间显示自定义箭头 */
.custom-number-input.with-arrows .el-input__inner {
padding-right: 30px;
} }
</style> </style>

View File

@ -19,34 +19,34 @@
stroke-linejoin="round" /> stroke-linejoin="round" />
</svg> --> </svg> -->
<svg class="item_icon_bg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" <svg class="item_icon_bg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="162" height="44" viewBox="0 0 162 44" fill="none" preserveAspectRatio="none"> width="162" height="44" viewBox="0 0 162 44" fill="none" preserveAspectRatio="none">
<path fill="#000000" fill-opacity="0.5" d="M0 44L136.639 44L162 18L162 0L0 0L0 44Z" /> <path fill="#000000" fill-opacity="0.5" d="M0 44L136.639 44L162 18L162 0L0 0L0 44Z"/>
<path fill-rule="evenodd" fill="url(#linear_border_2218_109_0)" <path fill-rule="evenodd" fill="url(#linear_border_2218_109_0)"
d="M136.006 42.5L1.5 42.5L1.5 1.5L160.5 1.5L160.5 17.3896L136.006 42.5ZM136.639 44L0 44L0 0L162 0L162 18L136.639 44Z" /> d="M136.006 42.5L1.5 42.5L1.5 1.5L160.5 1.5L160.5 17.3896L136.006 42.5ZM136.639 44L0 44L0 0L162 0L162 18L136.639 44Z"/>
<path d="M0 0L15.0533 0L49.1742 41L98.4484 41.2681L102 44L0 44L0 0Z" <path d="M0 0L15.0533 0L49.1742 41L98.4484 41.2681L102 44L0 44L0 0Z"
fill="rgba(var(--color-base1), 0.2)" /> fill="rgba(var(--color-base1), 0.2)"/>
<path d="M3 34L3 41L10 41L3 34Z" stroke="rgba(var(--color-base2), 1)" stroke-width="0.5" <path d="M3 34L3 41L10 41L3 34Z" stroke="rgba(var(--color-base2), 1)" stroke-width="0.5"
stroke-linejoin="round" /> stroke-linejoin="round"/>
<path d="M159 10L159 3L152 3L159 10Z" stroke="rgba(var(--color-base2), 1)" stroke-width="0.5" <path d="M159 10L159 3L152 3L159 10Z" stroke="rgba(var(--color-base2), 1)" stroke-width="0.5"
stroke-linejoin="round" /> stroke-linejoin="round"/>
<defs> <defs>
<linearGradient id="linear_border_2218_109_0" x1="0" y1="-1.7520751953125" x2="140.2142333984375" <linearGradient id="linear_border_2218_109_0" x1="0" y1="-1.7520751953125" x2="140.2142333984375"
y2="40.473846435546875" gradientUnits="userSpaceOnUse"> y2="40.473846435546875" gradientUnits="userSpaceOnUse">
<stop offset="0.0625" stop-color="rgba(var(--color-base1), 1)" /> <stop offset="0.0625" stop-color="rgba(var(--color-base1), 1)"/>
<stop offset="1" stop-color="var(--color-border1)" /> <stop offset="1" stop-color="var(--color-border1)"/>
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
<svg class="item_icon_bg item_icon_bg_hover" style="opacity: 0;" xmlns="http://www.w3.org/2000/svg" <svg class="item_icon_bg item_icon_bg_hover" style="opacity: 0;" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="163" height="45" viewBox="0 0 163 45" fill="none" xmlns:xlink="http://www.w3.org/1999/xlink" width="163" height="45" viewBox="0 0 163 45" fill="none"
preserveAspectRatio="none"> preserveAspectRatio="none">
<path fill="url(#linear_fill_2218_82_1)" <path fill="url(#linear_fill_2218_82_1)"
d="M0.5 44.5L137.139 44.5L162.5 18.5L162.5 0.5L0.5 0.5L0.5 44.5Z" /> d="M0.5 44.5L137.139 44.5L162.5 18.5L162.5 0.5L0.5 0.5L0.5 44.5Z"/>
<defs> <defs>
<linearGradient id="linear_fill_2218_82_1" x1="84.9554443359375" y1="44.49997329711914" <linearGradient id="linear_fill_2218_82_1" x1="84.9554443359375" y1="44.49997329711914"
x2="84.95498657226562" y2="0.5" gradientUnits="userSpaceOnUse"> x2="84.95498657226562" y2="0.5" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.6" /> <stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.6"/>
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0" /> <stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0"/>
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
@ -62,41 +62,41 @@
</div> </div>
<div class="left_bottom" @click="fold"> <div class="left_bottom" @click="fold">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"
viewBox="0 0 32 32" fill="none"> viewBox="0 0 32 32" fill="none">
<path fill="#000000" fill-opacity="0.6" <path fill="#000000" fill-opacity="0.6"
d="M16 0C24.835 0 32 7.16496 32 16C32 24.835 24.835 32 16 32C7.16496 32 0 24.835 0 16C0 7.16496 7.16496 0 16 0Z" /> d="M16 0C24.835 0 32 7.16496 32 16C32 24.835 24.835 32 16 32C7.16496 32 0 24.835 0 16C0 7.16496 7.16496 0 16 0Z"/>
<path fill="url(#linear_fill_2442_491_1)" <path fill="url(#linear_fill_2442_491_1)"
d="M16 0C24.835 0 32 7.16496 32 16C32 24.835 24.835 32 16 32C7.16496 32 0 24.835 0 16C0 7.16496 7.16496 0 16 0Z" /> d="M16 0C24.835 0 32 7.16496 32 16C32 24.835 24.835 32 16 32C7.16496 32 0 24.835 0 16C0 7.16496 7.16496 0 16 0Z"/>
<path fill-rule="evenodd" fill="url(#linear_border_2442_491_0)" <path fill-rule="evenodd" fill="url(#linear_border_2442_491_0)"
d="M32 16C32 7.16496 24.835 0 16 0C7.16496 0 0 7.16496 0 16C0 24.835 7.16496 32 16 32C24.835 32 32 24.835 32 16ZM30.5 16C30.5 7.99187 24.0081 1.5 16 1.5C7.99187 1.5 1.5 7.99187 1.5 16C1.5 24.0081 7.99187 30.5 16 30.5C24.0081 30.5 30.5 24.0081 30.5 16Z" /> d="M32 16C32 7.16496 24.835 0 16 0C7.16496 0 0 7.16496 0 16C0 24.835 7.16496 32 16 32C24.835 32 32 24.835 32 16ZM30.5 16C30.5 7.99187 24.0081 1.5 16 1.5C7.99187 1.5 1.5 7.99187 1.5 16C1.5 24.0081 7.99187 30.5 16 30.5C24.0081 30.5 30.5 24.0081 30.5 16Z"/>
<g filter="url(#filter_2442_492)"> <g filter="url(#filter_2442_492)">
<path <path
d="M10.4025 16.1283L19.1887 9.77097C19.1941 9.76721 19.1995 9.76361 19.205 9.76018C19.2106 9.75678 19.2162 9.75356 19.222 9.75054C19.2278 9.74754 19.2337 9.74473 19.2396 9.74211C19.2456 9.73947 19.2517 9.73705 19.2578 9.73486C19.2639 9.73265 19.2701 9.73065 19.2764 9.72886C19.2827 9.72708 19.289 9.7255 19.2954 9.72415C19.3017 9.72279 19.3082 9.72166 19.3146 9.72075C19.3211 9.71985 19.3275 9.71916 19.334 9.71868C19.3405 9.71821 19.347 9.71794 19.3535 9.7179C19.3601 9.71787 19.3666 9.71808 19.3731 9.7185C19.3796 9.71891 19.3861 9.71954 19.3925 9.7204C19.399 9.72125 19.4054 9.72234 19.4118 9.72365C19.4182 9.72493 19.4245 9.72645 19.4308 9.72818C19.4371 9.7299 19.4433 9.73184 19.4495 9.734C19.4556 9.73615 19.4617 9.7385 19.4677 9.74108C19.4737 9.74365 19.4795 9.74641 19.4854 9.74936C19.4912 9.75234 19.4969 9.7555 19.5024 9.75886C19.508 9.76222 19.5135 9.76577 19.5188 9.7695C19.5242 9.77322 19.5294 9.77712 19.5345 9.78122C19.5395 9.78531 19.5445 9.78956 19.5492 9.79397C19.554 9.7984 19.5587 9.80298 19.5631 9.80772C19.5676 9.81246 19.5719 9.81735 19.5761 9.8224C19.5802 9.82742 19.5842 9.83259 19.588 9.8379C19.5917 9.84318 19.5953 9.8486 19.5987 9.85415C19.6022 9.8597 19.6054 9.86536 19.6084 9.87115C19.6115 9.87691 19.6143 9.88277 19.6169 9.88872C19.6196 9.8947 19.622 9.90074 19.6242 9.90686C19.6264 9.913 19.6284 9.91921 19.6302 9.92547C19.632 9.93173 19.6336 9.93805 19.635 9.94443C19.6363 9.95079 19.6375 9.9572 19.6384 9.96365C19.6393 9.9701 19.64 9.97658 19.6405 9.98308C19.641 9.98958 19.6413 9.99609 19.6413 10.0026L19.6413 11.6788C19.6413 12.0415 19.4676 12.3889 19.1705 12.6022L13.9773 16.3599L19.1705 20.1176C19.1887 20.1308 19.2065 20.1445 19.2239 20.1587C19.2413 20.1729 19.2583 20.1876 19.2749 20.2028C19.2914 20.218 19.3075 20.2337 19.3231 20.2499C19.3387 20.266 19.3539 20.2826 19.3685 20.2997C19.3831 20.3167 19.3972 20.3342 19.4109 20.3521C19.4245 20.37 19.4375 20.3883 19.45 20.407C19.4625 20.4256 19.4745 20.4446 19.4859 20.464C19.4973 20.4834 19.5081 20.5031 19.5183 20.5231C19.5285 20.5431 19.5381 20.5634 19.5471 20.584C19.5562 20.6046 19.5646 20.6254 19.5724 20.6465C19.5801 20.6676 19.5873 20.6889 19.5938 20.7104C19.6003 20.7319 19.6062 20.7536 19.6115 20.7754C19.6167 20.7973 19.6213 20.8193 19.6252 20.8414C19.6292 20.8635 19.6325 20.8858 19.6351 20.9081C19.6377 20.9304 19.6396 20.9528 19.6409 20.9752C19.6422 20.9977 19.6429 21.0201 19.6428 21.0426L19.6428 22.7173C19.6428 22.9489 19.3777 23.0845 19.1887 22.9489L10.4025 16.5915C10.3979 16.5882 10.3935 16.5848 10.3892 16.5812C10.3849 16.5776 10.3807 16.5739 10.3766 16.57C10.3725 16.5662 10.3686 16.5623 10.3647 16.5582C10.3608 16.5541 10.3571 16.5499 10.3535 16.5456C10.3499 16.5414 10.3464 16.537 10.343 16.5325C10.3396 16.528 10.3364 16.5234 10.3334 16.5187C10.3302 16.514 10.3273 16.5093 10.3245 16.5044C10.3217 16.4996 10.319 16.4946 10.3165 16.4896C10.3139 16.4846 10.3116 16.4796 10.3094 16.4744C10.3071 16.4693 10.305 16.464 10.3031 16.4588C10.3012 16.4535 10.2994 16.4482 10.2978 16.4428C10.2962 16.4375 10.2948 16.4321 10.2934 16.4266C10.2921 16.4211 10.291 16.4156 10.29 16.4101C10.2891 16.4046 10.2882 16.3991 10.2876 16.3935C10.2869 16.3879 10.2864 16.3824 10.2861 16.3768C10.2858 16.3711 10.2856 16.3655 10.2856 16.3599C10.2856 16.3543 10.2858 16.3487 10.2861 16.3431C10.2864 16.3375 10.2869 16.3319 10.2876 16.3264C10.2882 16.3208 10.2891 16.3153 10.29 16.3097C10.291 16.3042 10.2921 16.2987 10.2934 16.2933C10.2948 16.2878 10.2962 16.2824 10.2978 16.277C10.2994 16.2716 10.3012 16.2663 10.3031 16.2611C10.305 16.2558 10.3071 16.2506 10.3094 16.2455C10.3116 16.2403 10.3139 16.2352 10.3165 16.2302C10.319 16.2252 10.3217 16.2203 10.3245 16.2154C10.3273 16.2106 10.3302 16.2058 10.3334 16.2011C10.3364 16.1965 10.3396 16.1919 10.343 16.1874C10.3464 16.1829 10.3499 16.1785 10.3535 16.1742C10.3571 16.1699 10.3608 16.1658 10.3647 16.1617C10.3686 16.1576 10.3725 16.1536 10.3766 16.1498C10.3807 16.146 10.3849 16.1423 10.3892 16.1387C10.3935 16.1351 10.3979 16.1316 10.4025 16.1283Z" d="M10.4025 16.1283L19.1887 9.77097C19.1941 9.76721 19.1995 9.76361 19.205 9.76018C19.2106 9.75678 19.2162 9.75356 19.222 9.75054C19.2278 9.74754 19.2337 9.74473 19.2396 9.74211C19.2456 9.73947 19.2517 9.73705 19.2578 9.73486C19.2639 9.73265 19.2701 9.73065 19.2764 9.72886C19.2827 9.72708 19.289 9.7255 19.2954 9.72415C19.3017 9.72279 19.3082 9.72166 19.3146 9.72075C19.3211 9.71985 19.3275 9.71916 19.334 9.71868C19.3405 9.71821 19.347 9.71794 19.3535 9.7179C19.3601 9.71787 19.3666 9.71808 19.3731 9.7185C19.3796 9.71891 19.3861 9.71954 19.3925 9.7204C19.399 9.72125 19.4054 9.72234 19.4118 9.72365C19.4182 9.72493 19.4245 9.72645 19.4308 9.72818C19.4371 9.7299 19.4433 9.73184 19.4495 9.734C19.4556 9.73615 19.4617 9.7385 19.4677 9.74108C19.4737 9.74365 19.4795 9.74641 19.4854 9.74936C19.4912 9.75234 19.4969 9.7555 19.5024 9.75886C19.508 9.76222 19.5135 9.76577 19.5188 9.7695C19.5242 9.77322 19.5294 9.77712 19.5345 9.78122C19.5395 9.78531 19.5445 9.78956 19.5492 9.79397C19.554 9.7984 19.5587 9.80298 19.5631 9.80772C19.5676 9.81246 19.5719 9.81735 19.5761 9.8224C19.5802 9.82742 19.5842 9.83259 19.588 9.8379C19.5917 9.84318 19.5953 9.8486 19.5987 9.85415C19.6022 9.8597 19.6054 9.86536 19.6084 9.87115C19.6115 9.87691 19.6143 9.88277 19.6169 9.88872C19.6196 9.8947 19.622 9.90074 19.6242 9.90686C19.6264 9.913 19.6284 9.91921 19.6302 9.92547C19.632 9.93173 19.6336 9.93805 19.635 9.94443C19.6363 9.95079 19.6375 9.9572 19.6384 9.96365C19.6393 9.9701 19.64 9.97658 19.6405 9.98308C19.641 9.98958 19.6413 9.99609 19.6413 10.0026L19.6413 11.6788C19.6413 12.0415 19.4676 12.3889 19.1705 12.6022L13.9773 16.3599L19.1705 20.1176C19.1887 20.1308 19.2065 20.1445 19.2239 20.1587C19.2413 20.1729 19.2583 20.1876 19.2749 20.2028C19.2914 20.218 19.3075 20.2337 19.3231 20.2499C19.3387 20.266 19.3539 20.2826 19.3685 20.2997C19.3831 20.3167 19.3972 20.3342 19.4109 20.3521C19.4245 20.37 19.4375 20.3883 19.45 20.407C19.4625 20.4256 19.4745 20.4446 19.4859 20.464C19.4973 20.4834 19.5081 20.5031 19.5183 20.5231C19.5285 20.5431 19.5381 20.5634 19.5471 20.584C19.5562 20.6046 19.5646 20.6254 19.5724 20.6465C19.5801 20.6676 19.5873 20.6889 19.5938 20.7104C19.6003 20.7319 19.6062 20.7536 19.6115 20.7754C19.6167 20.7973 19.6213 20.8193 19.6252 20.8414C19.6292 20.8635 19.6325 20.8858 19.6351 20.9081C19.6377 20.9304 19.6396 20.9528 19.6409 20.9752C19.6422 20.9977 19.6429 21.0201 19.6428 21.0426L19.6428 22.7173C19.6428 22.9489 19.3777 23.0845 19.1887 22.9489L10.4025 16.5915C10.3979 16.5882 10.3935 16.5848 10.3892 16.5812C10.3849 16.5776 10.3807 16.5739 10.3766 16.57C10.3725 16.5662 10.3686 16.5623 10.3647 16.5582C10.3608 16.5541 10.3571 16.5499 10.3535 16.5456C10.3499 16.5414 10.3464 16.537 10.343 16.5325C10.3396 16.528 10.3364 16.5234 10.3334 16.5187C10.3302 16.514 10.3273 16.5093 10.3245 16.5044C10.3217 16.4996 10.319 16.4946 10.3165 16.4896C10.3139 16.4846 10.3116 16.4796 10.3094 16.4744C10.3071 16.4693 10.305 16.464 10.3031 16.4588C10.3012 16.4535 10.2994 16.4482 10.2978 16.4428C10.2962 16.4375 10.2948 16.4321 10.2934 16.4266C10.2921 16.4211 10.291 16.4156 10.29 16.4101C10.2891 16.4046 10.2882 16.3991 10.2876 16.3935C10.2869 16.3879 10.2864 16.3824 10.2861 16.3768C10.2858 16.3711 10.2856 16.3655 10.2856 16.3599C10.2856 16.3543 10.2858 16.3487 10.2861 16.3431C10.2864 16.3375 10.2869 16.3319 10.2876 16.3264C10.2882 16.3208 10.2891 16.3153 10.29 16.3097C10.291 16.3042 10.2921 16.2987 10.2934 16.2933C10.2948 16.2878 10.2962 16.2824 10.2978 16.277C10.2994 16.2716 10.3012 16.2663 10.3031 16.2611C10.305 16.2558 10.3071 16.2506 10.3094 16.2455C10.3116 16.2403 10.3139 16.2352 10.3165 16.2302C10.319 16.2252 10.3217 16.2203 10.3245 16.2154C10.3273 16.2106 10.3302 16.2058 10.3334 16.2011C10.3364 16.1965 10.3396 16.1919 10.343 16.1874C10.3464 16.1829 10.3499 16.1785 10.3535 16.1742C10.3571 16.1699 10.3608 16.1658 10.3647 16.1617C10.3686 16.1576 10.3725 16.1536 10.3766 16.1498C10.3807 16.146 10.3849 16.1423 10.3892 16.1387C10.3935 16.1351 10.3979 16.1316 10.4025 16.1283Z"
fill="rgba(var(--color-base2), 1)" /> fill="rgba(var(--color-base2), 1)"/>
</g> </g>
<defs> <defs>
<linearGradient id="linear_fill_2442_491_1" x1="14.793701171875" y1="16.00537109375" x2="14.7939453125" <linearGradient id="linear_fill_2442_491_1" x1="14.793701171875" y1="16.00537109375" x2="14.7939453125"
y2="-6.678619384765625" gradientUnits="userSpaceOnUse"> y2="-6.678619384765625" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2" /> <stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2"/>
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0" /> <stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0"/>
</linearGradient> </linearGradient>
<linearGradient id="linear_border_2442_491_0" x1="32" y1="-1.27423095703125" x2="4.303466796875" <linearGradient id="linear_border_2442_491_0" x1="32" y1="-1.27423095703125" x2="4.303466796875"
y2="29.435516357421875" gradientUnits="userSpaceOnUse"> y2="29.435516357421875" gradientUnits="userSpaceOnUse">
<stop offset="0.0625" stop-color="rgb(var(--color-base1))" /> <stop offset="0.0625" stop-color="rgb(var(--color-base1))"/>
<stop offset="1" stop-color="var(--color-border1)" /> <stop offset="1" stop-color="var(--color-border1)"/>
</linearGradient> </linearGradient>
<filter id="filter_2442_492" x="6.28564453125" y="5.717864990234375" width="17.357177734375" <filter id="filter_2442_492" x="6.28564453125" y="5.717864990234375" width="17.357177734375"
height="21.36663818359375" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> height="21.36663818359375" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="feFloodId_2442_492" /> <feFlood flood-opacity="0" result="feFloodId_2442_492"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha_2442_492" /> result="hardAlpha_2442_492"/>
<feOffset dx="0" dy="0" /> <feOffset dx="0" dy="0"/>
<feGaussianBlur stdDeviation="2" /> <feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha_2442_492" operator="out" /> <feComposite in2="hardAlpha_2442_492" operator="out"/>
<feColorMatrix type="matrix" <feColorMatrix type="matrix"
values="0 0 0 0 0.1450980392156863 0 0 0 0 0.7686274509803922 0 0 0 0 0.7686274509803922 0 0 0 1 0" /> values="0 0 0 0 0.1450980392156863 0 0 0 0 0.7686274509803922 0 0 0 0 0.7686274509803922 0 0 0 1 0"/>
<feBlend mode="normal" in2="feFloodId_2442_492" result="dropShadow_1_2442_492" /> <feBlend mode="normal" in2="feFloodId_2442_492" result="dropShadow_1_2442_492"/>
<feBlend mode="normal" in="SourceGraphic" in2="dropShadow_1_2442_492" result="shape_2442_492" /> <feBlend mode="normal" in="SourceGraphic" in2="dropShadow_1_2442_492" result="shape_2442_492"/>
</filter> </filter>
</defs> </defs>
</svg> </svg>
@ -105,16 +105,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n' import {useI18n} from 'vue-i18n'
import { useRouter } from 'vue-router' import {useRouter} from 'vue-router'
import { bus } from '@/utils/bus' import {bus} from '@/utils/bus'
import leftSideSecond from '@/views/components/leftSide/leftSideSecond.vue' import leftSideSecond from '@/views/components/leftSide/leftSideSecond.vue'
import { ElMessage, ElLoading } from 'element-plus' import {ElMessage, ElLoading} from 'element-plus'
const { ipcRenderer } = require('electron') const {ipcRenderer} = require('electron')
const router = useRouter() // 路由实例 const router = useRouter() // 路由实例
const { t } = useI18n() const {t} = useI18n()
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
const menuList: any = ref([ const menuList: any = ref([
// 方案推演 // 方案推演
@ -274,7 +274,9 @@ const handleClick = (item: any, e) => {
if ((window as any).checkAuthIsValid) { if ((window as any).checkAuthIsValid) {
console.log('打开态势推演') console.log('打开态势推演')
ipcRenderer.send('toggle-fullscreen', true) ipcRenderer.send('toggle-fullscreen', true)
router.push({ path: '/ts' }) window['earth'].destroy()
window['earth'] = null
router.push({path: '/ts'})
} else { } else {
ElMessage({ ElMessage({
@ -447,7 +449,7 @@ const clickMenu = (item: any) => {
align-items: center; align-items: center;
position: relative; position: relative;
>.item_icon_bg { > .item_icon_bg {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -459,7 +461,7 @@ const clickMenu = (item: any) => {
// background: url('../../../assets/images/hongse/left1.png') no-repeat; // background: url('../../../assets/images/hongse/left1.png') no-repeat;
// background-size: 100% 100%; // background-size: 100% 100%;
>.item_icon_bg_hover { > .item_icon_bg_hover {
opacity: 1 !important; opacity: 1 !important;
} }
} }
@ -493,7 +495,8 @@ const clickMenu = (item: any) => {
// background-size: 100% 100%; // background-size: 100% 100%;
transition: all 0.3s ease; transition: all 0.3s ease;
cursor: pointer; cursor: pointer;
>svg {
> svg {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }

View File

@ -1,13 +1,21 @@
import { $changeComponentShow } from '@/utils/communication' import {$changeComponentShow} from '@/utils/communication'
import { useTreeNode } from './treeNode' import {useTreeNode} from './treeNode'
import { TreeApi } from '@/api/tree' import {TreeApi} from '@/api/tree'
import { initMapData } from '../../../../common/initMapData' import {initMapData} from '../../../../common/initMapData'
import { ElMessage } from 'element-plus' import {ElMessage} from 'element-plus'
export const useTree = () => { export const useTree = () => {
const rightMenuRef: any = ref() //右键菜单的实例 const rightMenuRef: any = ref() //右键菜单的实例
const treeObj = ref() //树形的实例 const treeObj = ref() //树形的实例
const { getSelectedNodes, showRightMenu, cusUpdateNode, cusSelectNode, getSameLevel, cusNodeIcon, nodeType } = useTreeNode() //树上一系列的方法hooks const {
getSelectedNodes,
showRightMenu,
cusUpdateNode,
cusSelectNode,
getSameLevel,
cusNodeIcon,
nodeType
} = useTreeNode() //树上一系列的方法hooks
const nodes: any = ref([]) const nodes: any = ref([])
/** /**
* 用于捕获zTree上鼠标按键按下后的事件回调函数 * 用于捕获zTree上鼠标按键按下后的事件回调函数
@ -79,8 +87,7 @@ export const useTree = () => {
let t = window.earth.entityMap.get(n.id) let t = window.earth.entityMap.get(n.id)
if (t) { if (t) {
return t return t
} } else {
else {
if (n.parentId) { if (n.parentId) {
return getEntityObject(window.treeObj.getNodeByParam("id", n.parentId, null)) return getEntityObject(window.treeObj.getNodeByParam("id", n.parentId, null))
} }
@ -89,8 +96,7 @@ export const useTree = () => {
} }
entityObject = getEntityObject(treeNode) entityObject = getEntityObject(treeNode)
entityObject.flyTo(treeNode.id) entityObject.flyTo(treeNode.id)
} } else if (treeNode.sourceType === "roam") {
else if (treeNode.sourceType === "roam") {
// 飞行漫游 // 飞行漫游
ElMessage({ ElMessage({
message: '单击鼠标右键可结束当前漫游', message: '单击鼠标右键可结束当前漫游',
@ -99,8 +105,7 @@ export const useTree = () => {
let params = JSON.parse(treeNode.params) let params = JSON.parse(treeNode.params)
YJ.Global.FlyRoam.flyTo((window as any).earth, params.points); YJ.Global.FlyRoam.flyTo((window as any).earth, params.points);
return; return;
} } else {
else {
if (treeNode.sourceType == 'pressModel') { if (treeNode.sourceType == 'pressModel') {
entityObject = (window as any).pressModelEntities.get(treeNode.id) entityObject = (window as any).pressModelEntities.get(treeNode.id)
} else { } else {
@ -222,29 +227,29 @@ export const useTree = () => {
* 成为同级前一个节点,"next":成为同级后一个节点》 * 成为同级前一个节点,"next":成为同级后一个节点》
* @returns {boolean} 返回 falsezTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数 * @returns {boolean} 返回 falsezTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数
*/ */
// @ts-ignore // @ts-ignore
const beforeDrop = ( const beforeDrop = (
treeId: any, treeId: any,
treeNodes: any, treeNodes: any,
targetNode: any, targetNode: any,
moveType: any moveType: any
) => { ) => {
if ( if (
['prev', 'next', 'inner'].includes(moveType) && ['prev', 'next', 'inner'].includes(moveType) &&
['pressModel', 'terrainDig'].includes(treeNodes[0].sourceType) ['pressModel', 'terrainDig'].includes(treeNodes[0].sourceType)
) { ) {
return false
}
if (['prev', 'next'].includes(moveType)) {
let parent = treeObj.value.getNodeByParam('id', targetNode.parentId, null)
if (parent && !nodeType[parent.sourceType].allowChildren) return false
}
if (targetNode) {
if (moveType == 'inner' && !nodeType[targetNode.sourceType].allowChildren) {
return false return false
} }
if (['prev', 'next'].includes(moveType)) {
let parent = treeObj.value.getNodeByParam('id', targetNode.parentId, null)
if (parent && !nodeType[parent.sourceType].allowChildren) return false
}
if (targetNode) {
if (moveType == 'inner' && !nodeType[targetNode.sourceType].allowChildren) {
return false
}
}
} }
}
/** /**
* 捕获 checkbox / radio 被勾选 或 取消勾选的事件回调函数 * 捕获 checkbox / radio 被勾选 或 取消勾选的事件回调函数
* @param event * @param event
@ -289,8 +294,7 @@ export const useTree = () => {
} }
) )
window.treeObj.checkNode(parentNode, false, true); window.treeObj.checkNode(parentNode, false, true);
} } else {
else {
p_ids.push( p_ids.push(
{ {
id: parentNode.id, id: parentNode.id,
@ -307,17 +311,17 @@ export const useTree = () => {
let ids = [...p_ids] let ids = [...p_ids]
// 更新节点状态修改地图资源状态 // 更新节点状态修改地图资源状态
function sourceStatus(node) { function sourceStatus(node) {
ids.push({ id: node.id, isShow: node.isShow ? 1 : 0 }) ids.push({id: node.id, isShow: node.isShow ? 1 : 0})
if (node.sourceType === 'directory') { if (node.sourceType === 'directory') {
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
node.children.forEach((item) => { node.children.forEach((item) => {
sourceStatus(item) sourceStatus(item)
}) })
} }
} } else {
else {
let params = JSON.parse(node.params) let params = JSON.parse(node.params)
let entityObject let entityObject
if (node.sourceType == 'pressModel') { if (node.sourceType == 'pressModel') {
@ -332,7 +336,7 @@ export const useTree = () => {
height: params.height, height: params.height,
name: node.sourceName name: node.sourceName
}) })
(window as any).pressModelEntities.set(node.id, entityObject) (window as any).pressModelEntities.set(node.id, entityObject)
} }
} else { } else {
@ -347,7 +351,7 @@ export const useTree = () => {
"sourceName": node.sourceName, "sourceName": node.sourceName,
"isShow": node.isShow ? 1 : 0, "isShow": node.isShow ? 1 : 0,
} }
cusUpdateNode({ id: node.id, sourceName: node.sourceName, params: JSON.stringify(params) }) cusUpdateNode({id: node.id, sourceName: node.sourceName, params: JSON.stringify(params)})
} }
} }
} }
@ -368,7 +372,6 @@ export const useTree = () => {
} }
// let source_ids = []; // let source_ids = [];
// nodes.forEach((item) => { // nodes.forEach((item) => {
// if (item.isHidden == false) { // if (item.isHidden == false) {
@ -499,7 +502,7 @@ export const useTree = () => {
check: { check: {
enable: true, enable: true,
nocheckInherit: false, nocheckInherit: false,
chkboxType: { Y: 'ps', N: 's' } chkboxType: {Y: 'ps', N: 's'}
}, },
view: { view: {
selectedMulti: true selectedMulti: true
@ -604,7 +607,7 @@ export const useTree = () => {
brightness: 1 brightness: 1
}) })
} }
res.data.list[i].svg = await cusNodeIcon(res.data.list[i]); res.data.list[i].icon = await cusNodeIcon(res.data.list[i]);
} }
} }
zNodes.value = res.data.list zNodes.value = res.data.list
@ -683,12 +686,11 @@ export const useTree = () => {
layers.push( layers.push(
{ {
sourceType: zNodes.value[i].sourceType, sourceType: zNodes.value[i].sourceType,
params: { ...detail, ...params } params: {...detail, ...params}
} }
) )
} } else {
else { initMapData(zNodes.value[i].sourceType, {...detail, ...params}, null)
initMapData(zNodes.value[i].sourceType, { ...detail, ...params }, null)
} }
} }
layers.sort((obj1, obj2) => { layers.sort((obj1, obj2) => {