u
This commit is contained in:
1 parent
26721a142e
commit
840d33ef3b
32 files changed
+2068
-590
No files matched your search
@@ -1,15 +1,15 @@
|
||||
# Application
|
||||
# 应用名称(用于标题、日志等)
|
||||
PUBLIC_APP_NAME=g3hy2026
|
||||
PUBLIC_APP_NAME=g3ocr
|
||||
|
||||
# Server
|
||||
# 应用部署基础路径(路由和静态资源 base)
|
||||
PUBLIC_SERVER_PATH=/
|
||||
PUBLIC_SERVER_PATH=/g3ocr/
|
||||
# 本地开发服务器端口
|
||||
PUBLIC_SERVER_PORT=8080
|
||||
|
||||
# API
|
||||
# 后端 API 基础地址
|
||||
PUBLIC_API_BASE_URL=http://127.0.0.1:8085/api
|
||||
PUBLIC_API_BASE_URL=http://ser369.g3soft.cn:80/api
|
||||
|
||||
PUBLIC_ALIYUN_BUCKET = g3hd
|
||||
@@ -25,6 +25,8 @@
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^3.0.4",
|
||||
"pinia-plugin-persistedstate": "^4.7.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"qrcode.vue": "^3.8.0",
|
||||
"uuid": "^13.0.0",
|
||||
"vue": "^3.5.26",
|
||||
"vue-router": "^5.0.3",
|
||||
|
||||
+207
@@ -56,6 +56,12 @@ importers:
|
||||
pinia-plugin-persistedstate:
|
||||
specifier: ^4.7.1
|
||||
version: 4.7.1(pinia@3.0.4(vue@3.5.30))
|
||||
qrcode:
|
||||
specifier: ^1.5.4
|
||||
version: 1.5.4
|
||||
qrcode.vue:
|
||||
specifier: ^3.8.0
|
||||
version: 3.8.0(vue@3.5.30)
|
||||
uuid:
|
||||
specifier: ^13.0.0
|
||||
version: 13.0.0
|
||||
@@ -918,6 +924,10 @@ packages:
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1020,6 +1030,10 @@ packages:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
camelcase@5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
caniuse-lite@1.0.30001778:
|
||||
resolution: {integrity: sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==}
|
||||
|
||||
@@ -1038,6 +1052,9 @@ packages:
|
||||
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
|
||||
engines: {node: '>= 20.19.0'}
|
||||
|
||||
cliui@6.0.0:
|
||||
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -1109,6 +1126,10 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decamelize@1.2.0:
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
deepmerge@4.3.1:
|
||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1124,6 +1145,9 @@ packages:
|
||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
dijkstrajs@1.0.3:
|
||||
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
|
||||
|
||||
dom-serializer@2.0.0:
|
||||
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||
|
||||
@@ -1161,6 +1185,9 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.3.0
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
emojis-list@3.0.0:
|
||||
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
|
||||
engines: {node: '>= 4'}
|
||||
@@ -1254,6 +1281,10 @@ packages:
|
||||
file-saver@2.0.5:
|
||||
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
|
||||
|
||||
find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
follow-redirects@1.15.11:
|
||||
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
@@ -1285,6 +1316,10 @@ packages:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1355,6 +1390,10 @@ packages:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-glob@4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1417,6 +1456,10 @@ packages:
|
||||
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
locate-path@5.0.0:
|
||||
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
lodash-es@4.17.23:
|
||||
resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==}
|
||||
|
||||
@@ -1580,12 +1623,28 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
p-limit@2.3.0:
|
||||
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
p-locate@4.1.0:
|
||||
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
p-try@2.2.0:
|
||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
package-manager-detector@1.6.0:
|
||||
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
|
||||
|
||||
pako@1.0.11:
|
||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
||||
|
||||
path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-is-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1635,6 +1694,10 @@ packages:
|
||||
pkg-types@2.3.0:
|
||||
resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
|
||||
|
||||
pngjs@5.0.0:
|
||||
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
postcss@8.5.8:
|
||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -1652,6 +1715,16 @@ packages:
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
qrcode.vue@3.8.0:
|
||||
resolution: {integrity: sha512-+XKbSKvQu158zlHsJm+HObGUQM3Q+9Oq6yb2op/6lMM2gwOiiG9uIhujvrSV5UoTjrzR0BcNxCdW2kk7KE4NEg==}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
qrcode@1.5.4:
|
||||
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
|
||||
quansync@0.2.11:
|
||||
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
|
||||
|
||||
@@ -1676,6 +1749,13 @@ packages:
|
||||
reduce-configs@1.1.1:
|
||||
resolution: {integrity: sha512-EYtsVGAQarE8daT54cnaY1PIknF2VB78ug6Zre2rs36EsJfC40EG6hmTU2A2P1ZuXnKAt2KI0fzOGHcX7wzdPw==}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
require-main-filename@2.0.0:
|
||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
||||
|
||||
resize-observer-polyfill@1.5.1:
|
||||
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
||||
|
||||
@@ -1846,6 +1926,9 @@ packages:
|
||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||
hasBin: true
|
||||
|
||||
set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
|
||||
setimmediate@1.0.5:
|
||||
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
|
||||
|
||||
@@ -1876,12 +1959,20 @@ packages:
|
||||
ssr-window@3.0.0:
|
||||
resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string_decoder@1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
|
||||
string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-literal@3.1.0:
|
||||
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
|
||||
|
||||
@@ -2056,9 +2147,16 @@ packages:
|
||||
webpack-virtual-modules@0.6.2:
|
||||
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||
|
||||
which-module@2.0.1:
|
||||
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
|
||||
|
||||
wildcard@1.1.2:
|
||||
resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==}
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
@@ -2071,6 +2169,9 @@ packages:
|
||||
xmlchars@2.2.0:
|
||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||
|
||||
y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
|
||||
yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
|
||||
@@ -2079,6 +2180,14 @@ packages:
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
yargs-parser@18.1.3:
|
||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
yargs@15.4.1:
|
||||
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
zip-stream@4.1.1:
|
||||
resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -2995,6 +3104,8 @@ snapshots:
|
||||
|
||||
acorn@8.16.0: {}
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
@@ -3128,6 +3239,8 @@ snapshots:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
camelcase@5.3.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001778: {}
|
||||
|
||||
chainsaw@0.1.0:
|
||||
@@ -3148,6 +3261,12 @@ snapshots:
|
||||
dependencies:
|
||||
readdirp: 5.0.0
|
||||
|
||||
cliui@6.0.0:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 6.2.0
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -3205,6 +3324,8 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
decamelize@1.2.0: {}
|
||||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
defu@6.1.4: {}
|
||||
@@ -3214,6 +3335,8 @@ snapshots:
|
||||
detect-libc@2.1.2:
|
||||
optional: true
|
||||
|
||||
dijkstrajs@1.0.3: {}
|
||||
|
||||
dom-serializer@2.0.0:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
@@ -3275,6 +3398,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emojis-list@3.0.0: {}
|
||||
|
||||
end-of-stream@1.4.5:
|
||||
@@ -3371,6 +3496,11 @@ snapshots:
|
||||
|
||||
file-saver@2.0.5: {}
|
||||
|
||||
find-up@4.1.0:
|
||||
dependencies:
|
||||
locate-path: 5.0.0
|
||||
path-exists: 4.0.0
|
||||
|
||||
follow-redirects@1.15.11: {}
|
||||
|
||||
form-data@4.0.5:
|
||||
@@ -3396,6 +3526,8 @@ snapshots:
|
||||
|
||||
gensync@1.0.0-beta.2: {}
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -3472,6 +3604,8 @@ snapshots:
|
||||
is-extglob@2.1.1:
|
||||
optional: true
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-glob@4.0.3:
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
@@ -3526,6 +3660,10 @@ snapshots:
|
||||
pkg-types: 2.3.0
|
||||
quansync: 0.2.11
|
||||
|
||||
locate-path@5.0.0:
|
||||
dependencies:
|
||||
p-locate: 4.1.0
|
||||
|
||||
lodash-es@4.17.23: {}
|
||||
|
||||
lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.23)(lodash@4.17.23):
|
||||
@@ -3674,10 +3812,22 @@ snapshots:
|
||||
'@oxfmt/binding-win32-ia32-msvc': 0.40.0
|
||||
'@oxfmt/binding-win32-x64-msvc': 0.40.0
|
||||
|
||||
p-limit@2.3.0:
|
||||
dependencies:
|
||||
p-try: 2.2.0
|
||||
|
||||
p-locate@4.1.0:
|
||||
dependencies:
|
||||
p-limit: 2.3.0
|
||||
|
||||
p-try@2.2.0: {}
|
||||
|
||||
package-manager-detector@1.6.0: {}
|
||||
|
||||
pako@1.0.11: {}
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
path-is-absolute@1.0.1: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
@@ -3713,6 +3863,8 @@ snapshots:
|
||||
exsolve: 1.0.8
|
||||
pathe: 2.0.3
|
||||
|
||||
pngjs@5.0.0: {}
|
||||
|
||||
postcss@8.5.8:
|
||||
dependencies:
|
||||
nanoid: 3.3.11
|
||||
@@ -3727,6 +3879,16 @@ snapshots:
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
qrcode.vue@3.8.0(vue@3.5.30):
|
||||
dependencies:
|
||||
vue: 3.5.30
|
||||
|
||||
qrcode@1.5.4:
|
||||
dependencies:
|
||||
dijkstrajs: 1.0.3
|
||||
pngjs: 5.0.0
|
||||
yargs: 15.4.1
|
||||
|
||||
quansync@0.2.11: {}
|
||||
|
||||
readable-stream@2.3.8:
|
||||
@@ -3756,6 +3918,10 @@ snapshots:
|
||||
|
||||
reduce-configs@1.1.1: {}
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
require-main-filename@2.0.0: {}
|
||||
|
||||
resize-observer-polyfill@1.5.1: {}
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
@@ -3889,6 +4055,8 @@ snapshots:
|
||||
|
||||
semver@6.3.1: {}
|
||||
|
||||
set-blocking@2.0.0: {}
|
||||
|
||||
setimmediate@1.0.5: {}
|
||||
|
||||
slate-history@0.66.0(slate@0.72.8):
|
||||
@@ -3912,6 +4080,12 @@ snapshots:
|
||||
|
||||
ssr-window@3.0.0: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string_decoder@1.1.1:
|
||||
dependencies:
|
||||
safe-buffer: 5.1.2
|
||||
@@ -3920,6 +4094,10 @@ snapshots:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-literal@3.1.0:
|
||||
dependencies:
|
||||
js-tokens: 9.0.1
|
||||
@@ -4117,8 +4295,16 @@ snapshots:
|
||||
|
||||
webpack-virtual-modules@0.6.2: {}
|
||||
|
||||
which-module@2.0.1: {}
|
||||
|
||||
wildcard@1.1.2: {}
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
xe-utils@3.9.1: {}
|
||||
@@ -4127,10 +4313,31 @@ snapshots:
|
||||
|
||||
xmlchars@2.2.0: {}
|
||||
|
||||
y18n@4.0.3: {}
|
||||
|
||||
yallist@3.1.1: {}
|
||||
|
||||
yaml@2.8.2: {}
|
||||
|
||||
yargs-parser@18.1.3:
|
||||
dependencies:
|
||||
camelcase: 5.3.1
|
||||
decamelize: 1.2.0
|
||||
|
||||
yargs@15.4.1:
|
||||
dependencies:
|
||||
cliui: 6.0.0
|
||||
decamelize: 1.2.0
|
||||
find-up: 4.1.0
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
require-main-filename: 2.0.0
|
||||
set-blocking: 2.0.0
|
||||
string-width: 4.2.3
|
||||
which-module: 2.0.1
|
||||
y18n: 4.0.3
|
||||
yargs-parser: 18.1.3
|
||||
|
||||
zip-stream@4.1.1:
|
||||
dependencies:
|
||||
archiver-utils: 3.0.4
|
||||
|
||||
@@ -124,7 +124,6 @@ const gridInnerLabelStyle = computed(() => {
|
||||
background-color: #f9f9f9;
|
||||
border-right: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
|
||||
@@ -26,6 +26,11 @@ const menuList = ref([
|
||||
icon: "lucide:box",
|
||||
path: "/container",
|
||||
},
|
||||
{
|
||||
label: "手机二维码",
|
||||
icon: "lucide:scan-qr-code",
|
||||
path: "/phone",
|
||||
},
|
||||
{
|
||||
label: "系统管理",
|
||||
icon: "lucide:settings",
|
||||
|
||||
@@ -87,6 +87,40 @@ export function loadPageDataApi(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页加载表格数据
|
||||
* @param {Object} params 参数对象
|
||||
* @param {number} params.start 当前页
|
||||
* @param {number} params.end 每页条数
|
||||
* @param {string} params.viewName 视图名称
|
||||
* @param {string} [params.searchCondition] 搜索条件
|
||||
* @param {string} [params.orderField] 排序字段
|
||||
* @param {string[]} [params.searchColumns] 搜索列
|
||||
* @returns {Promise<{
|
||||
* success: boolean,
|
||||
* data: Array<Record<string, any>>,
|
||||
* code: number,
|
||||
* message: string
|
||||
* }>} 返回 Promise 对象
|
||||
*/
|
||||
export function loadRangeDataApi(
|
||||
{ start, end, viewName, searchCondition = "", orderField = "", searchColumns = [] },
|
||||
config = {},
|
||||
) {
|
||||
return httpPost(
|
||||
"/data/range",
|
||||
{
|
||||
start,
|
||||
end,
|
||||
viewName,
|
||||
searchCondition,
|
||||
orderField,
|
||||
searchColumns,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
|
||||
export function saveObjectApi(data) {
|
||||
return httpPost("/data/saveObject", data);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,15 @@ export const routes = [
|
||||
moduleId: "v_container",
|
||||
},
|
||||
},
|
||||
// ==================== Phone ====================
|
||||
{
|
||||
path: "/phone",
|
||||
component: () => import("@/views/phone/index.vue"),
|
||||
meta: {
|
||||
title: "手机二维码",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
// ==================== 系统管理 ====================
|
||||
{
|
||||
path: "/system/field",
|
||||
|
||||
@@ -13,7 +13,7 @@ const userStore = useUserStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
|
||||
const form = ref({
|
||||
orgid: userStore.userInfo.orgid,
|
||||
orgid: 'g3hd',
|
||||
userid: userStore.userInfo.userid,
|
||||
password: "",
|
||||
});
|
||||
@@ -130,7 +130,7 @@ async function onVcodeSuccess() {
|
||||
<div class="tip">登录</div>
|
||||
<div class="split"></div>
|
||||
<div class="form">
|
||||
<div class="form-item">
|
||||
<!-- <div class="form-item">
|
||||
<div class="label required">机构码</div>
|
||||
|
||||
<el-input v-model="form.orgid">
|
||||
@@ -138,7 +138,7 @@ async function onVcodeSuccess() {
|
||||
<G3Icon icon="lucide:building" size="18" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="form-item">
|
||||
<div class="label required">账号</div>
|
||||
<el-input v-model="form.userid">
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<script lang="js" setup>
|
||||
import { loadDataBySqlApi } from "@/request/api";
|
||||
import { loadDataApi, loadDataBySqlApi, loadRangeDataApi } from "@/request/api";
|
||||
import { useThrottle } from "@/utils/throttle";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { saveAs } from "file-saver";
|
||||
import JSZip from "jszip";
|
||||
import { getAliyunFileBlob } from "@/utils/file";
|
||||
import { formatToDate } from "@/utils/time";
|
||||
|
||||
const viewName = "v_container";
|
||||
|
||||
const visible = defineModel(false);
|
||||
|
||||
@@ -22,7 +28,7 @@ const chunkModeForm = ref({
|
||||
pageSize: 100,
|
||||
});
|
||||
|
||||
const total = ref(0);
|
||||
const allTotal = ref(0);
|
||||
const loadingTotal = ref(false);
|
||||
|
||||
function handleResetForm() {
|
||||
@@ -65,12 +71,7 @@ const fetchTotalThrottle = useThrottle(async () => {
|
||||
await fetchTotal();
|
||||
}, 300);
|
||||
|
||||
async function fetchTotal() {
|
||||
if (!visible.value) {
|
||||
return;
|
||||
}
|
||||
loadingTotal.value = true;
|
||||
|
||||
function buildSearchCondition() {
|
||||
let searchCondition = [];
|
||||
|
||||
if (searchForm.value.startTime) {
|
||||
@@ -82,9 +83,7 @@ async function fetchTotal() {
|
||||
}
|
||||
|
||||
if (searchForm.value.containerNo) {
|
||||
searchCondition.push(
|
||||
`b_container_no LIKE '%${searchForm.value.containerNo}%'`,
|
||||
);
|
||||
searchCondition.push(`b_container_no LIKE '%${searchForm.value.containerNo}%'`);
|
||||
}
|
||||
|
||||
if (searchForm.value.username) {
|
||||
@@ -92,33 +91,320 @@ async function fetchTotal() {
|
||||
}
|
||||
|
||||
// 拼接 WHERE 条件
|
||||
const whereClause = searchCondition.length
|
||||
? "WHERE " + searchCondition.join(" AND ")
|
||||
: "";
|
||||
const whereClause = searchCondition.length ? "WHERE " + searchCondition.join(" AND ") : "";
|
||||
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
async function fetchTotal() {
|
||||
if (!visible.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadingTotal.value = true;
|
||||
|
||||
// 构建 SQL 获取总数
|
||||
const sql = `SELECT COUNT(*) as total FROM v_container ${whereClause}`;
|
||||
const sql = `SELECT COUNT(*) as total FROM ${viewName} ${buildSearchCondition()}`;
|
||||
|
||||
try {
|
||||
const res = await loadDataBySqlApi(sql);
|
||||
if (res.success) {
|
||||
total.value = res.data[0]?.total || 0;
|
||||
allTotal.value = res.data[0]?.total || 0;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("获取总数失败", err);
|
||||
total.value = 0;
|
||||
allTotal.value = 0;
|
||||
} finally {
|
||||
loadingTotal.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
if (total === 0) {
|
||||
async function fetchDatas() {
|
||||
const response = await loadDataApi(
|
||||
viewName,
|
||||
buildSearchCondition(),
|
||||
"b_inputdatetime DESC, b_id DESC",
|
||||
["b_id", "b_container_no", "b_inputdatetime"],
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
return response.data;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function handleDownload() {
|
||||
if (allTotal.value === 0) {
|
||||
ElMessage.warning("无有效数据可操作");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (searchForm.value.mode === "ALL") {
|
||||
downloadAll();
|
||||
} else if (searchForm.value.mode === "SLICE") {
|
||||
downloadSlice();
|
||||
} else if (searchForm.value.mode === "CHUNK") {
|
||||
downloadChunk();
|
||||
}
|
||||
}
|
||||
|
||||
async function runWithLimit(tasks, limit = 3) {
|
||||
const results = [];
|
||||
const executing = [];
|
||||
|
||||
for (const task of tasks) {
|
||||
const p = task().then((res) => {
|
||||
executing.splice(executing.indexOf(p), 1);
|
||||
return res;
|
||||
});
|
||||
|
||||
results.push(p);
|
||||
executing.push(p);
|
||||
|
||||
if (executing.length >= limit) {
|
||||
await Promise.race(executing);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(results);
|
||||
}
|
||||
|
||||
async function downloadAll() {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: "正在下载并打包文件,请稍候...",
|
||||
});
|
||||
|
||||
try {
|
||||
// 获取所有记录
|
||||
const records = await fetchDatas();
|
||||
|
||||
if (!records.length) {
|
||||
ElMessage.warning("无有效数据");
|
||||
return;
|
||||
}
|
||||
|
||||
const zip = new JSZip();
|
||||
let finished = 0;
|
||||
let totalFiles = 0;
|
||||
|
||||
// 1. 收集所有下载任务
|
||||
const allTasks = [];
|
||||
|
||||
for (const item of records) {
|
||||
const fileRes = await loadDataApi("bf_file", `father='${item.b_id}'`, "mx_xh asc");
|
||||
const files = (fileRes.success && fileRes.data) || [];
|
||||
totalFiles += files.length;
|
||||
|
||||
// 按 年/月/日/集装箱号 生成层级文件夹
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD"); // 2026/03/27
|
||||
const containerFolderName = item.b_container_no;
|
||||
let folder = zip.folder(ymdFolderName);
|
||||
folder = folder ? folder.folder(containerFolderName) : zip.folder(containerFolderName);
|
||||
|
||||
files.forEach((file, idx) => {
|
||||
allTasks.push(async () => {
|
||||
try {
|
||||
const blob = await getAliyunFileBlob(file.mx_mapfilename);
|
||||
const fileName = buildFileName(item.b_container_no, idx + 1, file.mx_filename) || "未命名文件";
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
console.error(item.b_container_no + "下载失败:", file.mx_mapfilename, e);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished}/${totalFiles} 个文件...`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 并发执行下载任务,限制同时 3 个
|
||||
await runWithLimit(allTasks, 3);
|
||||
|
||||
loading.setText("正在生成压缩包...");
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
|
||||
// 3. 保存压缩包
|
||||
saveAs(content, buildZipName("ALL"));
|
||||
|
||||
ElMessage.success("下载完成");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
// 按区间下载
|
||||
async function downloadSlice() {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: "正在下载并打包文件,请稍候...",
|
||||
});
|
||||
|
||||
try {
|
||||
let start = Math.max(1, Math.min(sliceModeForm.value.startPage || 1, allTotal.value));
|
||||
let end = Math.max(1, Math.min(sliceModeForm.value.endPage || 1, allTotal.value));
|
||||
if (start > end) [start, end] = [end, start];
|
||||
sliceModeForm.value.startPage = start;
|
||||
sliceModeForm.value.endPage = end;
|
||||
|
||||
const dataRes = await loadRangeDataApi({
|
||||
start,
|
||||
end,
|
||||
viewName,
|
||||
searchCondition: buildSearchCondition(),
|
||||
orderField: "b_inputdatetime DESC, b_id DESC",
|
||||
searchColumns: ["b_id", "b_container_no", "b_inputdatetime"],
|
||||
});
|
||||
|
||||
if (!dataRes.success || !dataRes.data.length) {
|
||||
ElMessage.warning("无有效数据");
|
||||
return;
|
||||
}
|
||||
|
||||
const records = dataRes.data;
|
||||
const zip = new JSZip();
|
||||
let finished = 0;
|
||||
const allTasks = [];
|
||||
|
||||
records.forEach((item) => {
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD");
|
||||
const containerFolderName = item.b_container_no;
|
||||
const folderPromise = loadDataApi("bf_file", `father='${item.b_id}'`, "mx_xh asc");
|
||||
|
||||
allTasks.push(async () => {
|
||||
const fileRes = await folderPromise;
|
||||
if (!fileRes.success) {
|
||||
console.error("获取附件失败:", item.b_container_no);
|
||||
return;
|
||||
}
|
||||
|
||||
const folder = zip.folder(ymdFolderName)?.folder(containerFolderName) || zip.folder(containerFolderName);
|
||||
|
||||
const files = fileRes.data || [];
|
||||
const fileTasks = files.map((file, idx) => async () => {
|
||||
try {
|
||||
const blob = await getAliyunFileBlob(file.mx_mapfilename);
|
||||
const fileName = buildFileName(item.b_container_no, idx + 1, file.mx_filename) || "未命名文件";
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
console.error(item.b_container_no + "下载失败:", file.mx_mapfilename, e);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished} / ${records.length} 个文件...`);
|
||||
}
|
||||
});
|
||||
|
||||
await runWithLimit(fileTasks, 3);
|
||||
});
|
||||
});
|
||||
|
||||
await runWithLimit(allTasks, 3);
|
||||
|
||||
loading.setText("正在生成压缩包...");
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
saveAs(content, buildZipName("SLICE"));
|
||||
ElMessage.success("下载完成");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error("下载失败");
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
// 分页拆分导出
|
||||
async function downloadChunk() {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: "正在下载并打包文件,请稍候...",
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await fetchDatas();
|
||||
if (!records?.length) {
|
||||
ElMessage.warning("无有效数据");
|
||||
return;
|
||||
}
|
||||
|
||||
const zip = new JSZip();
|
||||
const pageSize = chunkModeForm.value.pageSize || 10;
|
||||
const totalPages = Math.ceil(records.length / pageSize);
|
||||
let finished = 0;
|
||||
|
||||
const allPageTasks = [];
|
||||
|
||||
for (let pageIndex = 0; pageIndex < totalPages; pageIndex++) {
|
||||
const startIndex = pageIndex * pageSize;
|
||||
const endIndex = Math.min((pageIndex + 1) * pageSize, records.length);
|
||||
const pageRecords = records.slice(startIndex, endIndex);
|
||||
const pageFolderName = `${startIndex + 1}-${endIndex}`;
|
||||
const pageFolder = zip.folder(pageFolderName);
|
||||
|
||||
pageRecords.forEach((item) => {
|
||||
allPageTasks.push(async () => {
|
||||
const fileRes = await loadDataApi("bf_file", `father='${item.b_id}'`, "mx_xh asc");
|
||||
if (!fileRes.success) {
|
||||
console.error("获取附件失败:", item.b_container_no);
|
||||
return;
|
||||
}
|
||||
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD");
|
||||
const containerFolderName = item.b_container_no;
|
||||
const folder = pageFolder.folder(ymdFolderName)?.folder(containerFolderName) || pageFolder.folder(containerFolderName);
|
||||
|
||||
const files = fileRes.data || [];
|
||||
const fileTasks = files.map((file, idx) => async () => {
|
||||
try {
|
||||
const blob = await getAliyunFileBlob(file.mx_mapfilename);
|
||||
const fileName = buildFileName(item.b_container_no, idx + 1, file.mx_filename) || "未命名文件";
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
console.error(item.b_container_no + "下载失败:", file.mx_mapfilename, e);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished} 个文件...`);
|
||||
}
|
||||
});
|
||||
|
||||
await runWithLimit(fileTasks, 3);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
await runWithLimit(allPageTasks, 3);
|
||||
|
||||
loading.setText("正在生成压缩包...");
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
saveAs(content, buildZipName("CHUNK"));
|
||||
ElMessage.success("下载完成");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error("下载失败");
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
|
||||
function buildFileName(containerNo, index, fileName) {
|
||||
const formattedIndex = String(index).padStart(2, "0");
|
||||
|
||||
return `${containerNo}_${formattedIndex}.${fileName.split(".").pop()}`;
|
||||
}
|
||||
|
||||
function buildZipName(mode) {
|
||||
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
||||
|
||||
switch (mode) {
|
||||
case "ALL":
|
||||
return `全部下载_${dateStr}.zip`;
|
||||
case "SLICE":
|
||||
return `下载第${sliceModeForm.value.startPage}-${sliceModeForm.value.endPage}条_${dateStr}.zip`;
|
||||
case "CHUNK":
|
||||
return `分页下载_每${chunkModeForm.value.pageSize}条_${dateStr}.zip`;
|
||||
default:
|
||||
return `下载数据_${dateStr}.zip`;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -137,7 +423,7 @@ function handleExport() {
|
||||
<div class="total">
|
||||
共
|
||||
<span class="num" v-loading="loadingTotal">
|
||||
{{ total }}
|
||||
{{ allTotal }}
|
||||
</span>
|
||||
条数据
|
||||
</div>
|
||||
@@ -195,9 +481,9 @@ function handleExport() {
|
||||
<div class="label">模式</div>
|
||||
<div class="content">
|
||||
<el-radio-group v-model="searchForm.mode">
|
||||
<el-radio label="ALL">全部导出</el-radio>
|
||||
<el-radio label="SLICE">按页区间导出</el-radio>
|
||||
<el-radio label="CHUNK">分页拆分导出</el-radio>
|
||||
<el-radio value="ALL">全部导出</el-radio>
|
||||
<el-radio value="SLICE">按区间导出</el-radio>
|
||||
<el-radio value="CHUNK">分页拆分导出</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
@@ -205,16 +491,16 @@ function handleExport() {
|
||||
v-if="searchForm.mode === 'SLICE'"
|
||||
style="margin-top: 8px; display: flex; align-items: center"
|
||||
>
|
||||
<el-input placeholder="起始页" />
|
||||
<el-input placeholder="起始页" v-model="sliceModeForm.startPage" />
|
||||
<el-divider direction="vertical" />
|
||||
<el-input placeholder="终止页" />
|
||||
<el-input placeholder="终止页" v-model="sliceModeForm.endPage" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="searchForm.mode === 'CHUNK'"
|
||||
style="margin-top: 8px; display: flex; align-items: center"
|
||||
>
|
||||
<el-input placeholder="分页大小" />
|
||||
<el-input placeholder="分页大小" v-model="chunkModeForm.pageSize" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -226,7 +512,7 @@ function handleExport() {
|
||||
</el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button type="primary">
|
||||
<el-button type="primary" @click="handleDownload">
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:cloud-download" />
|
||||
</el-icon>
|
||||
|
||||
@@ -17,6 +17,8 @@ import { usePermissionStore } from "@/store/permission";
|
||||
import { ExportVxeTableExcel, exportExcel } from "@/utils/excel";
|
||||
import HighDownloadDialog from "./high-download-dialog.vue";
|
||||
|
||||
const viewName = "v_container";
|
||||
|
||||
const tableRef = ref();
|
||||
|
||||
const permissionStore = usePermissionStore();
|
||||
@@ -55,14 +57,10 @@ const fileCategories = [
|
||||
},
|
||||
];
|
||||
|
||||
const viewName = "v_container";
|
||||
|
||||
const showPreview = ref(false);
|
||||
const previewIndex = ref(-1);
|
||||
const previewImageList = computed(() => {
|
||||
return tableData.value
|
||||
.map((item) => item.b_container_img)
|
||||
.filter((img) => img);
|
||||
return tableData.value.map((item) => item.b_container_img).filter((img) => img);
|
||||
});
|
||||
|
||||
const currentRow = ref({});
|
||||
@@ -195,12 +193,9 @@ async function deleteRows(rows = []) {
|
||||
const safeDeleteIds = deleteIds.map((id) => Number(id));
|
||||
|
||||
// 使用安全的 SQL 查询
|
||||
const fileRes = await loadDataApi(
|
||||
"bf_file",
|
||||
`father IN (${safeDeleteIds.join(",")})`,
|
||||
"",
|
||||
["subid"],
|
||||
);
|
||||
const fileRes = await loadDataApi("bf_file", `father IN (${safeDeleteIds.join(",")})`, "", [
|
||||
"subid",
|
||||
]);
|
||||
|
||||
if (!fileRes.success) {
|
||||
return;
|
||||
@@ -276,11 +271,7 @@ async function handleDownloadOne(data) {
|
||||
});
|
||||
|
||||
try {
|
||||
const fileRes = await loadDataApi(
|
||||
"bf_file",
|
||||
`father = ${data.b_id}`,
|
||||
"mx_xh asc",
|
||||
);
|
||||
const fileRes = await loadDataApi("bf_file", `father = ${data.b_id}`, "mx_xh asc");
|
||||
|
||||
if (!fileRes.success) {
|
||||
ElMessage.error("获取附件失败");
|
||||
@@ -288,11 +279,7 @@ async function handleDownloadOne(data) {
|
||||
}
|
||||
|
||||
const downloadFiles = fileRes.data.map((item, index) => ({
|
||||
mx_filename: buildFileName(
|
||||
data.b_container_no,
|
||||
index + 1,
|
||||
item.mx_filename,
|
||||
),
|
||||
mx_filename: buildFileName(data.b_container_no, index + 1, item.mx_filename),
|
||||
mx_mapfilename: item.mx_mapfilename,
|
||||
}));
|
||||
|
||||
@@ -347,73 +334,54 @@ async function handleDownloadBatch() {
|
||||
text: "正在下载并打包文件,请稍候...",
|
||||
});
|
||||
|
||||
const zip = new JSZip();
|
||||
|
||||
try {
|
||||
let total = 0;
|
||||
const zip = new JSZip();
|
||||
let finished = 0;
|
||||
let totalFiles = 0;
|
||||
|
||||
// 1. 收集所有下载任务
|
||||
const allTasks = [];
|
||||
|
||||
for (const item of records) {
|
||||
const fileRes = await loadDataApi(
|
||||
"bf_file",
|
||||
`father = '${item.b_id}'`,
|
||||
"",
|
||||
);
|
||||
if (fileRes.success) {
|
||||
total += (fileRes.data || []).length;
|
||||
}
|
||||
}
|
||||
const fileRes = await loadDataApi("bf_file", `father='${item.b_id}'`, "mx_xh asc");
|
||||
const files = (fileRes.success && fileRes.data) || [];
|
||||
totalFiles += files.length;
|
||||
|
||||
for (const item of records) {
|
||||
const folderName = `${item.b_container_no}_${formatToDate(item.b_inputdatetime)}`;
|
||||
// 按 年/月/日/集装箱号 生成层级文件夹
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD"); // 2026/03/27
|
||||
const containerFolderName = item.b_container_no;
|
||||
let folder = zip.folder(ymdFolderName);
|
||||
folder = folder ? folder.folder(containerFolderName) : zip.folder(containerFolderName);
|
||||
|
||||
const folder = zip.folder(folderName);
|
||||
|
||||
const fileRes = await loadDataApi(
|
||||
"bf_file",
|
||||
`father = '${item.b_id}'`,
|
||||
"mx_xh asc",
|
||||
);
|
||||
|
||||
if (!fileRes.success) {
|
||||
ElMessage.error("获取附件失败");
|
||||
continue;
|
||||
}
|
||||
|
||||
const files = fileRes.data || [];
|
||||
|
||||
const tasks = files.map((file, index) => async () => {
|
||||
const fileUrl = file.mx_mapfilename;
|
||||
|
||||
try {
|
||||
const blob = getAliyunFileBlob(fileUrl);
|
||||
|
||||
const fileName =
|
||||
buildFileName(item.b_container_no, index + 1, file.mx_filename) ||
|
||||
"未命名文件";
|
||||
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
ElMessage.error(item.b_container_no + "箱号部分图片下载失败");
|
||||
console.error("下载失败:", fileUrl);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished}/${total} 个文件...`);
|
||||
}
|
||||
files.forEach((file, idx) => {
|
||||
allTasks.push(async () => {
|
||||
try {
|
||||
const blob = await getAliyunFileBlob(file.mx_mapfilename);
|
||||
const fileName =
|
||||
buildFileName(item.b_container_no, idx + 1, file.mx_filename) || "未命名文件";
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
console.error(item.b_container_no + "下载失败:", file.mx_mapfilename, e);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished}/${totalFiles} 个文件...`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await runWithLimit(tasks, 3);
|
||||
}
|
||||
|
||||
// 2. 并发执行下载任务,限制同时 3 个
|
||||
await runWithLimit(allTasks, 3);
|
||||
|
||||
loading.setText("正在生成压缩包...");
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
|
||||
saveAs(content, "批量下载.zip");
|
||||
// 3. 保存压缩包
|
||||
saveAs(content, "批量下载");
|
||||
|
||||
ElMessage.success("下载完成");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("打包失败");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
@@ -424,109 +392,6 @@ function buildFileName(containerNo, index, fileName) {
|
||||
|
||||
return `${containerNo}_${formattedIndex}.${fileName.split(".").pop()}`;
|
||||
}
|
||||
|
||||
function testExport() {
|
||||
const options = {
|
||||
columns: [
|
||||
{
|
||||
label: "基础信息",
|
||||
field: "basicInfo",
|
||||
width: 120,
|
||||
children: [
|
||||
{
|
||||
label: "姓名",
|
||||
field: "name",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: "年龄",
|
||||
field: "age",
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
label: "头像",
|
||||
field: "avatar",
|
||||
width: 100,
|
||||
type: "image",
|
||||
imageWidth: 80,
|
||||
imageHeight: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "联系方式",
|
||||
field: "contactInfo",
|
||||
width: 160,
|
||||
children: [
|
||||
{
|
||||
label: "电话",
|
||||
field: "phone",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: "邮箱",
|
||||
field: "email",
|
||||
width: 200,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "其他信息",
|
||||
field: "otherInfo",
|
||||
width: 100,
|
||||
children: [
|
||||
{
|
||||
label: "地址信息",
|
||||
field: "address",
|
||||
width: 150,
|
||||
children: [
|
||||
{ label: "省份", field: "province", width: 80 },
|
||||
{ label: "城市", field: "city", width: 80 },
|
||||
],
|
||||
},
|
||||
{ label: "备注", field: "remark", width: 200 },
|
||||
],
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: "张三",
|
||||
age: 25,
|
||||
phone: "13800138000",
|
||||
email: "zhangsan@example.com",
|
||||
province: "浙江",
|
||||
city: "杭州",
|
||||
remark: "测试数据1",
|
||||
avatar:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAQAElEQVR4AezdDXojR7kFYHNXAisJ7ISshLASclcCWQnsBLpmxpnxjGVJ3fV/3jxWbMvqqjrvZ6IjexL+78VfBAgQIECAQJyAAhA3coEJECBAgMDLiwLgu4AAAQIECAQKKACBQxeZAAECBLIFSnoFoCi4ESBAgACBMAEFIGzg4hIgQIBAusDn/ArAZwd/J0CAAAECUQIKQNS4hSVAgACBdIHX/ArAq4T3BAgQIEAgSEABCBq2qAQIECCQLvA1vwLw1cJHBAgQIEAgRkABiBm1oAQIECCQLvBtfgXgWw0fEyBAgACBEAEFIGTQYhIgQIBAusDb/ArAWw+fESBAgACBCAEFIGLMQhIgQIBAusD3+RWA70V8ToAAAQIEAgQUgIAhi0iAAAEC6QI/5lcAfjRxDwECBAgQ2F5AAdh+xAISIECAQLrAe/kVgPdU3EeAAAECBDYXUAA2H7B4BAgQIJAu8H5+BeB9F/cSIECAAIGtBRSArccrHAECBAikC9zKrwDcknE/AQIECBDYWEAB2Hi4ohEgQIBAusDt/ArAbRtfIUCAAAEC2wooANuOVjACBAgQSBf4KL8C8JGOrxEgQIAAgU0FFIBNBysWAQIECKQLfJxfAfjYx1cJECBAgMCWAgrAlmMVigABAgTSBe7lVwDuCfk6AQIECBDYUEAB2HCoIhEgQIBAusD9/ArAfSOPIECAAAEC2wkoANuNVCACBAgQSBd4JL8C8IiSxxAgQIAAgc0EFIDNBioOAQIECKQLPJZfAXjMyaMIECBAgMBWAgrAVuMUhgABAgTSBR7NrwA8KuVxBAgQIEBgIwEFYKNhikKAAAEC6QKP51cAHrfySAIECBAgsI2AArDNKAUhQIAAgXSBZ/IrAM9oeSwBAgQIENhEQAHYZJBiECBAgEC6wHP5FYDnvDyaAAECBAhsIaAAbDFGIQgQIEAgXeDZ/ArAs2IeT4AAAQIENhBQADYYoggECBAgkC7wfH4F4HkzVxAgQIAAgeUFFIDlRygAAQIECKQLnMmvAJxRcw0BAgQIEFhcQAFYfICOT4AAAQLpAufyKwDn3FxFgAABAgSWFlAAlh6fwxMgQIBAusDZ/ArAWTnXESBAgACBhQUUgIWH5+gECBAgkC5wPr8CcN7OlQQIECBAYFkBBWDZ0Tk4AQIECKQLXMmvAFzRcy0BAgQIEFhUQAFYdHCOTYAAAQLpAtfyKwDX/FxNgAABAgSWFFAAlhybQxMgQIBAusDV/ArAVUHXEyBAgACBBQUUgAWH5sgECBAgkC5wPb8CcN3QCgQIECBAYDkBBWC5kTkwAQIECKQL1MivANRQtAYBAgQIEFhMQAFYbGCOS4AAAQLpAnXyKwB1HK1CgAABAgSWElAAlhqXwxIgQIBAukCt/ApALUnrECBAgACBhQQUgIWG5agECBAgkC5QL78CUM/SSgQIECBAYBkBBWCZUTkoAQIECKQL1MyvANTUtBYBAgQIEFhEQAFYZFCOSYAAAQLpAnXzKwB1Pa1GgAABAgSWEFAAlhiTQxIgQIBAukDt/ApAbVHrESBAgACBBQQUgAWG5IgECBAgkC5QP78CUN/UigQIECBAYHoBBWD6ETkgAQIECKQLtMivALRQtSYBAgQIEJhcQAGYfECOR4AAAQLpAm3yKwBtXK1KgAABAgSmFlAAph6PwxEgQIBAukCr/ApAK1nrEiBAgACBiQUUgImH42gECBAgkC7QLr8C0M7WygQIECBAYFoBBWDa0TgYAQIECKQLtMyvALTUtTYBAgQIEJhUQAGYdDCORYAAAQLpAm3zKwBtfa1OgAABAgSmFFAAphyLQxEgQIBAukDr/ApAa2HrEyBAgACBCQUUgAmH4kgECBAgkC7QPr8C0N7YDgQIECBAYDoBBWC6kTgQAQIECKQL9MivAPRQtgcBAgQIEJhMQAGYbCCOQ4AAAQLpAn3yKwB9nO1CgAABAgSmElAAphqHwxAgQIBAukCv/ApAL2n7ECBAgACBiQQUgImG4SgECBAgkC7QL78C0M/aTgQIECBAYBoBBWCaUTgIAQIECKQL9MyvAPTUthcBAgQIEJhEQAGYZBCOQYAAAQLpAn3zKwB9ve1GgAABAgSmEFAAphiDQxAgQIBAukDv/ApAb3H7ESBAgACBCQQUgAmG4AgECBAgkC7QP78C0N/cjgQIECBAYLiAAjB8BA5AgAABAukCI/IrACPU7UmAAAECBAYLKACDB2B7AgQIEEgXGJNfARjjblcCBAgQIDBUQAEYym9zAgQIEEgXGJVfARglb18CBAgQIDBQQAEYiG9rAgQIEEgXGJdfARhnb2cCBAgQIDBMQAEYRm9jAgQIEEgXGJlfARipb28CBAgQIDBIQAEYBG9bAgQIEEgXGJtfARjrb3cCBAgQIDBEQAEYwm5TAgQIEEgXGJ1fARg9AfsTIECAAIEBAgrAAHRbEiBAgEC6wPj8CsD4GTgBAQIECBDoLqAAdCe3IQECBAikC8yQXwGYYQrOQIAAAQIEOgsoAJ3BbUeAAAEC6QJz5FcA5piDUxAgQIAAga4CCkBXbpsRIECAQLrALPkVgFkm4RwECBAgQKCjgALQEdtWBAgQIJAuME9+BWCeWTgJAQIECBDoJqAAdKO2EQECBAikC8yUXwGYaRrOQoAAAQIEOgkoAJ2gbUOAAAEC6QJz5VcA5pqH0xAgQIAAgS4CCkAXZpsQIECAQLrAbPkVgNkm4jwECBAgQKCDgALQAdkWBAgQIJAuMF9+BWC+mTgRAQIECBBoLqAANCe2AQECBAikC8yYXwGYcSrORIAAAQIEGgsoAI2BLU+AAAEC6QJz5lcA5pyLUxEgQIAAgaYCCkBTXosTIECAQLrArPkVgFkn41wECBAgQKChgALQENfSBAgQIJAuMG9+BWDe2TgZAQIECBBoJqAANKO1MAECBAikC8ycXwGYeTrORoAAAQIEGgkoAI1gLUuAAAEC6QJz51cA5p6P0xEgQIAAgSYCCkATVosSIECAQLrA7PkVgNkn5HwECBAgQKCBgALQANWSBAgQIJAuMH9+BWD+GTkhAQIECBCoLqAAVCe1IAECBAikC6yQXwFYYUrOSIAAAQIEKgsoAJVBLUeAAAEC6QJr5FcA1piTUxIgQIAAgaoCCkBVTosRIECAQLrAKvkVgFUm5ZwECBAgQKCigAJQEdNSBAgQIJAusE5+BWCdWTkpAQIECBCoJqAAVKO0EAECBAikC6yUXwFYaVrOSoAAAQIEKgkoAJUgLUOAAAEC6QJr5VcA1pqX0xIgQIAAgSoCCkAVRosQIECAQLrAavkVgNUm5rwECBAgQKCCgAJQAdESBAgQIJAusF5+BWC9mTkxAQIECBC4LKAAXCa0AAECBAikC6yYXwFYcWrOTIAAAQIELgooABcBXU6AAAEC6QJr5lcA1pybUxMgQIAAgUsCCsAlPhcTIECAQLrAqvkVgFUn59wECBAgQOCCgAJwAc+lBAgQIJAusG5+BWDd2Tk5AQIECBA4LaAAnKZzIQECBAikC6ycXwFYeXrOToAAAQIETgooACfhXEaAAAEC6QJr51cA1p6f0xMgQIAAgVMCCsApNhcRIECAQLrA6vkVgDYT/Mex7H+Db389sq/yljynZ7P/+xhquf3zeF++x/92vP/zcVv57VmD5MeX2ZfbTvNf+Xv38tkVgMuEFiAQI/DHI2m5lSf9UvJ+OT4vTwblSaEUgnL/cZe3TQXK7MutzNn8X9afsgKw/gwlIDBaoDwplCeEUgZKESifjz6T/fsJlHmbfz/vajspANUoLUSAwCHw+kRQfj1wfOotTCBm/jvMVQHYYYoyEJhLoLwiLL8eKL8aKB/PdTqnaS1QZm7+rZUrrK8AVEC0BAEC7wqUJ4Lya4Hy/t0HuHNrgTL3Tee/x9wUgD3mKAWBWQVenwTKHxyb9YzO1U7A/NvZXl5ZAbhMaAECBO4IlCcBfzjwDtLGX95u/rvMSgHYZZJyEJhboDwJlB8Hz31Kp2slYP6tZC+sqwBcwHMpAQJPCZQngfKTgKcu8uBtBDaZ/zbzeFEA9pmlJARWECh/FqDcVjirM9YXKLMvt/orW/FpAQXgaTIXECBwQaC8CvTfCLgAuPily89/cf83x1cA3nD4hACBDgLlFWC5ddjKFhMKlNmX24RHyzqSApA1b2kJzCLgpwCzTGLMORad/xisVrsqAK1krUuAwEcC5UfBH33d1/YWMP8J5qsATDAERyAQKFCeAPwYOHDwXyIvOf8vZ9/mnQKwzSgFIbCcwE/LndiBawqYf03NE2spACfQXEKAQBUBPwGowrjsIovNf1nnmwdXAG7S+AIBAgQIENhXQAHYd7aSEZhdoPweePYzOl87gaXm345h3MoKwDh7OxMgQIAAgWECCsAwehsTiBfwCjD7W2Ch+e85KAVgz7lKRYAAAQIEPhRQAD7k8UUCBAgQSBfYNb8CsOtk5SJAgAABAh8IKAAf4PgSAQIECKQL7JtfAdh3tpIRIECAAIGbAgrATRpfIECAAIF0gZ3zKwA7T1c2AgQIECBwQ0ABuAHjbgIECBBIF9g7vwKw93ylI0CAAAEC7wooAO+yuJMAAQIE0gV2z68AtJnwz8eyfxh4+/XY29tjAiPnNMPejynt+6gZZjDyDPtOVrK7AgrAXSIPIECAAIE8gf0TKwD7z1hCAgQIECDwg4AC8AOJOwgQIEAgXSAhvwKQMGUZCRAgQIDAdwIKwHcgPiVAgACBdIGM/ApAxpylJECAAAECbwQUgDccPiFAgACBdIGU/ApAyqTlJECAAAEC3wgoAN9g+JAAAQIE0gVy8isAObOWlAABAgQI/C6gAPxO4QMCBAgQSBdIyq8AJE1bVgIECBAg8EVAAfgC4R0BAgQIpAtk5VcAsuYtLQECBAgQ+CSgAHLine truncated
|
||||
},
|
||||
{
|
||||
name: "李四",
|
||||
age: 30,
|
||||
phone: "13900139000",
|
||||
email: "lisi@example.com",
|
||||
province: "江苏",
|
||||
city: "南京",
|
||||
remark: "测试数据2",
|
||||
avatar:
|
||||
"data:image/png;base64,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 truncated
|
||||
},
|
||||
],
|
||||
footer: [
|
||||
{
|
||||
name: "总计",
|
||||
age: 55,
|
||||
phone: "",
|
||||
email: "",
|
||||
province: "",
|
||||
city: "",
|
||||
remark: "2条记录",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
exportExcel(options);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -649,9 +514,6 @@ function testExport() {
|
||||
<el-dropdown-item @click="ExportVxeTableExcel(tableRef)">
|
||||
导出Execl
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="ExportVxeTableExcel(tableRef)">
|
||||
高级导出
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@@ -683,14 +545,7 @@ function testExport() {
|
||||
show-overflow
|
||||
show-header-overflow
|
||||
>
|
||||
<vxe-column
|
||||
field="seq"
|
||||
type="seq"
|
||||
width="50"
|
||||
align="center"
|
||||
title=" "
|
||||
fixed="left"
|
||||
/>
|
||||
<vxe-column field="seq" type="seq" width="50" align="center" title=" " fixed="left" />
|
||||
<vxe-column type="checkbox" width="50" align="center" fixed="left" />
|
||||
<vxe-column
|
||||
v-for="column in columns"
|
||||
@@ -711,12 +566,7 @@ function testExport() {
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{
|
||||
formatValueByFormat(
|
||||
row[column.col_FieldName],
|
||||
column.col_DisplayFormat,
|
||||
)
|
||||
}}
|
||||
{{ formatValueByFormat(row[column.col_FieldName], column.col_DisplayFormat) }}
|
||||
</template>
|
||||
</template>
|
||||
</vxe-column>
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<script lang="js" setup>
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import QRCode from "qrcode";
|
||||
import { loadDataApi } from "@/request/api";
|
||||
import { useUserStore } from "@/store/user";
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 用户二维码数据
|
||||
const userData = ref([]);
|
||||
|
||||
// 主二维码链接
|
||||
const mainUrl = "http://ser215.g3soft.cn:8088/g3ocr-app/#/pages-sub/upload/index";
|
||||
|
||||
// Element Plus 图片查看器控制
|
||||
const showPreview = ref(false);
|
||||
const previewIndex = ref(0);
|
||||
const srcList = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
// loadUserDatas();
|
||||
});
|
||||
|
||||
async function loadUserDatas() {
|
||||
const response = await loadDataApi("b_user", `b_id <> 'g3soft' AND b_canuse = '1'`, "", ["b_id"]);
|
||||
if (response.success) {
|
||||
response.data.forEach((item) => {
|
||||
userData.value.push({
|
||||
account: item.b_id,
|
||||
url: `${mainUrl}?orgid=${encodeURIComponent(userStore.userInfo.orgid)}&bid=${encodeURIComponent(item.b_id)}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 base64
|
||||
async function generateQrBase64(urls) {
|
||||
srcList.value = [];
|
||||
for (const item of urls) {
|
||||
const dataUrl = await QRCode.toDataURL(item, { width: 400 });
|
||||
srcList.value.push(dataUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 打开预览
|
||||
async function openPreview(index) {
|
||||
const urls = [mainUrl, ...userData.value.map((u) => u.url)];
|
||||
await generateQrBase64(urls);
|
||||
previewIndex.value = index;
|
||||
showPreview.value = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<!-- 主二维码 -->
|
||||
<div class="qr-section main-qr">
|
||||
<h2>统一入口</h2>
|
||||
<qrcode-vue :value="mainUrl" :size="220" :margin="2" @click.native="openPreview(0)" />
|
||||
</div>
|
||||
<el-divider />
|
||||
|
||||
<!-- 用户二维码 -->
|
||||
<!-- <div class="qr-section user-qr">
|
||||
<h2>用户二维码(免登录,需要启用该账户!)</h2>
|
||||
<div class="user-qr-list">
|
||||
<div v-for="(user, index) in userData" :key="index" class="user-qr-item">
|
||||
<div class="account-name">{{ user.account }}</div>
|
||||
<qrcode-vue
|
||||
:value="user.url"
|
||||
:size="200"
|
||||
@click.native="openPreview(index + 1)"
|
||||
:margin="2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Element Plus 图片查看器 -->
|
||||
<el-image-viewer
|
||||
v-if="showPreview"
|
||||
:url-list="srcList"
|
||||
:initial-index="previewIndex"
|
||||
show-progress
|
||||
@close="showPreview = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@/styles/mixins.scss" as *;
|
||||
|
||||
.page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.qr-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.user-qr {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.qr-section h2 {
|
||||
margin-bottom: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-qr-list {
|
||||
@include flexGapWrap(10px, 36px);
|
||||
}
|
||||
|
||||
.user-qr-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
margin-bottom: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
@@ -75,6 +75,18 @@ async function loadTableDatas() {
|
||||
searchCondition += `b_inputdatetime <= '${searchForm.value.endTime}' AND `;
|
||||
}
|
||||
|
||||
if (searchForm.value.datas) {
|
||||
searchCondition += `b_datas LIKE '${searchForm.value.datas}' AND `;
|
||||
}
|
||||
|
||||
if (searchForm.value.option) {
|
||||
searchCondition += `b_option LIKE '${searchForm.value.option}' AND `;
|
||||
}
|
||||
|
||||
if (searchForm.value.table) {
|
||||
searchCondition += `b_table LIKE '${searchForm.value.table}' AND `;
|
||||
}
|
||||
|
||||
if (searchCondition.endsWith(" AND ")) {
|
||||
searchCondition = searchCondition.slice(0, -4);
|
||||
}
|
||||
@@ -163,16 +175,16 @@ function handleSearchReset() {
|
||||
</G3Grid>
|
||||
|
||||
<div class="search-extra">
|
||||
<el-button type="primary">
|
||||
<el-button type="primary" @click="handleSearch">
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:search" @click="handleSearch" />
|
||||
<G3Icon icon="lucide:search" />
|
||||
</el-icon>
|
||||
搜索
|
||||
</el-button>
|
||||
|
||||
<el-button>
|
||||
<el-button @click="handleSearchReset">
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:refresh-ccw" @click="handleSearchReset" />
|
||||
<G3Icon icon="lucide:refresh-ccw" />
|
||||
</el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
|
||||
+1063
-147
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user