Commit 65e91500 by 杨子

feat: 添加Lodop打印支持并优化仓库管理功能

- 新增Lodop打印插件及相关安装文件
- 添加二维码打印组件QrcodePrintDialog
- 优化仓库、库区、货架选择组件LocationCascaderSelect
- 新增RFID和PTL标签选择对话框组件
- 优化物资选择对话框,支持快速新增物资
- 调整物资管理页面,隐藏RFID相关字段
- 优化库存管理页面,调整查询条件和显示字段
- 修改主题色为绿色系
- 添加Tailwind CSS支持并配置与Element Plus的兼容
parent 51fd2e02
......@@ -7,6 +7,7 @@
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<script src="/lodop/LodopFuncs.js"></script>
<title>WMS仓库管理系统</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
......@@ -209,6 +210,9 @@
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
</div>
<object id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0>
<embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0 pluginspage="install_lodop32.exe"></embed>
</object>
<script type="module" src="/src/main.js"></script>
</body>
......
......@@ -43,7 +43,10 @@
},
"devDependencies": {
"@vitejs/plugin-vue": "5.2.4",
"autoprefixer": "^10.4.23",
"postcss": "^8.5.6",
"sass-embedded": "1.89.1",
"tailwindcss": "3",
"unplugin-auto-import": "0.18.6",
"unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "6.3.5",
......
......@@ -83,10 +83,19 @@ importers:
devDependencies:
'@vitejs/plugin-vue':
specifier: 5.2.4
version: 5.2.4(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1))(vue@3.5.16)
version: 5.2.4(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1))(vue@3.5.16)
autoprefixer:
specifier: ^10.4.23
version: 10.4.23(postcss@8.5.6)
postcss:
specifier: ^8.5.6
version: 8.5.6
sass-embedded:
specifier: 1.89.1
version: 1.89.1
tailwindcss:
specifier: '3'
version: 3.4.19
unplugin-auto-import:
specifier: 0.18.6
version: 0.18.6(@vueuse/core@13.3.0(vue@3.5.16))(rollup@4.53.3)
......@@ -95,16 +104,20 @@ importers:
version: 1.0.1
vite:
specifier: 6.3.5
version: 6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)
version: 6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)
vite-plugin-compression:
specifier: 0.5.1
version: 0.5.1(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1))
version: 0.5.1(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1))
vite-plugin-svg-icons:
specifier: 2.0.1
version: 2.0.1(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1))
version: 2.0.1(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1))
packages:
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
'@antfu/utils@0.7.10':
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
......@@ -306,9 +319,19 @@ packages:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
......@@ -639,6 +662,16 @@ packages:
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
engines: {node: '>=12'}
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
arr-diff@4.0.0:
resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==}
engines: {node: '>=0.10.0'}
......@@ -682,6 +715,13 @@ packages:
engines: {node: '>= 4.5.0'}
hasBin: true
autoprefixer@10.4.23:
resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
......@@ -696,9 +736,17 @@ packages:
resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==}
engines: {node: '>=0.10.0'}
baseline-browser-mapping@2.9.9:
resolution: {integrity: sha512-V8fbOCSeOFvlDj7LLChUcqbZrdKD9RU/VR260piF1790vT0mfLSwGc/Qzxv3IqiTukOpNtItePa0HBpMAj7MDg==}
hasBin: true
big.js@5.2.2:
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
birpc@2.9.0:
resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==}
......@@ -719,6 +767,11 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
browserslist@4.28.1:
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
......@@ -738,6 +791,13 @@ packages:
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
camelcase-css@2.0.1:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
caniuse-lite@1.0.30001760:
resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==}
chalk@1.1.3:
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
engines: {node: '>=0.10.0'}
......@@ -746,6 +806,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
class-utils@0.3.6:
resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==}
engines: {node: '>=0.10.0'}
......@@ -779,6 +843,10 @@ packages:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
commander@7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
......@@ -822,6 +890,11 @@ packages:
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
engines: {node: '>= 6'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
csso@4.2.0:
resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
engines: {node: '>=8.0.0'}
......@@ -896,6 +969,12 @@ packages:
delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
dom-serializer@0.2.2:
resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==}
......@@ -936,6 +1015,9 @@ packages:
engines: {node: '>=14'}
hasBin: true
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
element-plus@2.10.7:
resolution: {integrity: sha512-bL4yhepL8/0NEQA5+N2Q6ZVKLipIDkiQjK2mqtSmGh6CxJk1yaBMdG5HXfYkbk1htNcT3ULk9g23lzT323JGcA==}
peerDependencies:
......@@ -990,6 +1072,10 @@ packages:
engines: {node: '>=18'}
hasBin: true
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
......@@ -1094,6 +1180,9 @@ packages:
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
engines: {node: '>= 6'}
fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
fragment-cache@0.2.1:
resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
engines: {node: '>=0.10.0'}
......@@ -1145,6 +1234,10 @@ packages:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
glob-parent@6.0.2:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
glob@10.5.0:
resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
hasBin: true
......@@ -1262,6 +1355,10 @@ packages:
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
engines: {node: '>= 0.4'}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-boolean-object@1.2.2:
resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
engines: {node: '>= 0.4'}
......@@ -1273,6 +1370,10 @@ packages:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
is-core-module@2.16.1:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
is-data-descriptor@1.0.1:
resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==}
engines: {node: '>= 0.4'}
......@@ -1413,6 +1514,10 @@ packages:
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
jiti@1.21.7:
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
hasBin: true
js-base64@2.6.4:
resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
......@@ -1454,6 +1559,13 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
loader-utils@1.4.2:
resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==}
engines: {node: '>=4.0.0'}
......@@ -1569,6 +1681,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
......@@ -1578,11 +1693,18 @@ packages:
resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==}
engines: {node: '>=0.10.0'}
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
nopt@7.2.1:
resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
hasBin: true
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
normalize-wheel-es@1.2.0:
resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
......@@ -1600,6 +1722,10 @@ packages:
resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==}
engines: {node: '>=0.10.0'}
object-hash@3.0.0:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
......@@ -1642,6 +1768,9 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
path-scurry@1.11.1:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
......@@ -1666,6 +1795,10 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
pinia@3.0.2:
resolution: {integrity: sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==}
peerDependencies:
......@@ -1675,6 +1808,10 @@ packages:
typescript:
optional: true
pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'}
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
......@@ -1689,11 +1826,54 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
peerDependencies:
postcss: ^8.0.0
postcss-js@4.1.0:
resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==}
engines: {node: ^12 || ^14 || >= 16}
peerDependencies:
postcss: ^8.4.21
postcss-load-config@6.0.1:
resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
engines: {node: '>= 18'}
peerDependencies:
jiti: '>=1.21.0'
postcss: '>=8.0.9'
tsx: ^4.8.1
yaml: ^2.4.2
peerDependenciesMeta:
jiti:
optional: true
postcss:
optional: true
tsx:
optional: true
yaml:
optional: true
postcss-nested@6.2.0:
resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
engines: {node: '>=12.0'}
peerDependencies:
postcss: ^8.2.14
postcss-prefix-selector@1.16.1:
resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==}
peerDependencies:
postcss: '>4 <9'
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
postcss@5.2.18:
resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==}
engines: {node: '>=0.12'}
......@@ -1745,10 +1925,17 @@ packages:
quill@1.3.7:
resolution: {integrity: sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==}
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
......@@ -1773,6 +1960,11 @@ packages:
resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
deprecated: https://github.com/lydell/resolve-url#deprecated
resolve@1.22.11:
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
engines: {node: '>= 0.4'}
hasBin: true
ret@0.1.15:
resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
engines: {node: '>=0.12'}
......@@ -2078,6 +2270,11 @@ packages:
strip-literal@2.1.1:
resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==}
sucrase@3.35.1:
resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
superjson@2.2.6:
resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==}
engines: {node: '>=16'}
......@@ -2098,6 +2295,10 @@ packages:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
engines: {node: '>=10'}
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
svg-baker@1.7.0:
resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==}
......@@ -2114,6 +2315,18 @@ packages:
resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
engines: {node: '>=16.0.0'}
tailwindcss@3.4.19:
resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==}
engines: {node: '>=14.0.0'}
hasBin: true
thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
engines: {node: '>=0.8'}
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
tiny-emitter@2.1.0:
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
......@@ -2141,6 +2354,9 @@ packages:
resolution: {integrity: sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==}
engines: {node: '>= 0.4'}
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
......@@ -2211,6 +2427,12 @@ packages:
resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==}
engines: {node: '>=0.10.0'}
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
urix@0.1.0:
resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
deprecated: Please see https://github.com/lydell/urix#deprecated
......@@ -2348,6 +2570,8 @@ packages:
snapshots:
'@alloc/quick-lru@5.2.0': {}
'@antfu/utils@0.7.10': {}
'@babel/helper-string-parser@7.27.1': {}
......@@ -2469,8 +2693,20 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.31
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.31':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
......@@ -2586,9 +2822,9 @@ snapshots:
'@types/web-bluetooth@0.0.21': {}
'@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1))(vue@3.5.16)':
'@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1))(vue@3.5.16)':
dependencies:
vite: 6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)
vite: 6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)
vue: 3.5.16
'@vue-office/docx@1.6.3(vue-demi@0.14.10(vue@3.5.16))(vue@3.5.16)':
......@@ -2768,6 +3004,15 @@ snapshots:
ansi-styles@6.2.3: {}
any-promise@1.3.0: {}
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
arg@5.0.2: {}
arr-diff@4.0.0: {}
arr-flatten@1.1.0: {}
......@@ -2801,6 +3046,15 @@ snapshots:
atob@2.1.2: {}
autoprefixer@10.4.23(postcss@8.5.6):
dependencies:
browserslist: 4.28.1
caniuse-lite: 1.0.30001760
fraction.js: 5.3.4
picocolors: 1.1.1
postcss: 8.5.6
postcss-value-parser: 4.2.0
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.1.0
......@@ -2825,8 +3079,12 @@ snapshots:
mixin-deep: 1.3.2
pascalcase: 0.1.1
baseline-browser-mapping@2.9.9: {}
big.js@5.2.2: {}
binary-extensions@2.3.0: {}
birpc@2.9.0: {}
bluebird@3.7.2: {}
......@@ -2856,6 +3114,14 @@ snapshots:
dependencies:
fill-range: 7.1.1
browserslist@4.28.1:
dependencies:
baseline-browser-mapping: 2.9.9
caniuse-lite: 1.0.30001760
electron-to-chromium: 1.5.267
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
buffer-builder@0.2.0: {}
cache-base@1.0.1:
......@@ -2887,6 +3153,10 @@ snapshots:
call-bind-apply-helpers: 1.0.2
get-intrinsic: 1.3.0
camelcase-css@2.0.1: {}
caniuse-lite@1.0.30001760: {}
chalk@1.1.3:
dependencies:
ansi-styles: 2.2.1
......@@ -2900,6 +3170,18 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
braces: 3.0.3
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
class-utils@0.3.6:
dependencies:
arr-union: 3.1.0
......@@ -2934,6 +3216,8 @@ snapshots:
commander@10.0.1: {}
commander@4.1.1: {}
commander@7.2.0: {}
component-emitter@1.3.1: {}
......@@ -2979,6 +3263,8 @@ snapshots:
css-what@6.2.2: {}
cssesc@3.0.0: {}
csso@4.2.0:
dependencies:
css-tree: 1.1.3
......@@ -3053,6 +3339,10 @@ snapshots:
delegate@3.2.0: {}
didyoumean@1.2.2: {}
dlv@1.1.3: {}
dom-serializer@0.2.2:
dependencies:
domelementtype: 2.3.0
......@@ -3107,6 +3397,8 @@ snapshots:
minimatch: 9.0.1
semver: 7.7.3
electron-to-chromium@1.5.267: {}
element-plus@2.10.7(vue@3.5.16):
dependencies:
'@ctrl/tinycolor': 3.6.1
......@@ -3247,6 +3539,8 @@ snapshots:
'@esbuild/win32-ia32': 0.25.12
'@esbuild/win32-x64': 0.25.12
escalade@3.2.0: {}
escape-html@1.0.3: {}
escape-string-regexp@1.0.5: {}
......@@ -3355,6 +3649,8 @@ snapshots:
hasown: 2.0.2
mime-types: 2.1.35
fraction.js@5.3.4: {}
fragment-cache@0.2.1:
dependencies:
map-cache: 0.2.2
......@@ -3415,6 +3711,10 @@ snapshots:
dependencies:
is-glob: 4.0.3
glob-parent@6.0.2:
dependencies:
is-glob: 4.0.3
glob@10.5.0:
dependencies:
foreground-child: 3.3.1
......@@ -3538,6 +3838,10 @@ snapshots:
dependencies:
has-bigints: 1.1.0
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
is-boolean-object@1.2.2:
dependencies:
call-bound: 1.0.4
......@@ -3547,6 +3851,10 @@ snapshots:
is-callable@1.2.7: {}
is-core-module@2.16.1:
dependencies:
hasown: 2.0.2
is-data-descriptor@1.0.1:
dependencies:
hasown: 2.0.2
......@@ -3680,6 +3988,8 @@ snapshots:
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
jiti@1.21.7: {}
js-base64@2.6.4: {}
js-beautify@1.14.11:
......@@ -3717,6 +4027,10 @@ snapshots:
kind-of@6.0.3: {}
lilconfig@3.1.3: {}
lines-and-columns@1.2.4: {}
loader-utils@1.4.2:
dependencies:
big.js: 5.2.2
......@@ -3835,6 +4149,12 @@ snapshots:
ms@2.1.3: {}
mz@2.7.0:
dependencies:
any-promise: 1.3.0
object-assign: 4.1.1
thenify-all: 1.6.0
nanoid@3.3.11: {}
nanomatch@1.2.13:
......@@ -3853,10 +4173,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
node-releases@2.0.27: {}
nopt@7.2.1:
dependencies:
abbrev: 2.0.0
normalize-path@3.0.0: {}
normalize-wheel-es@1.2.0: {}
nprogress@0.2.0: {}
......@@ -3873,6 +4197,8 @@ snapshots:
define-property: 0.2.5
kind-of: 3.2.2
object-hash@3.0.0: {}
object-inspect@1.13.4: {}
object-is@1.1.6:
......@@ -3913,6 +4239,8 @@ snapshots:
path-key@3.1.1: {}
path-parse@1.0.7: {}
path-scurry@1.11.1:
dependencies:
lru-cache: 10.4.3
......@@ -3930,11 +4258,15 @@ snapshots:
picomatch@4.0.3: {}
pify@2.3.0: {}
pinia@3.0.2(vue@3.5.16):
dependencies:
'@vue/devtools-api': 7.7.9
vue: 3.5.16
pirates@4.0.7: {}
pkg-types@1.3.1:
dependencies:
confbox: 0.1.8
......@@ -3951,10 +4283,41 @@ snapshots:
possible-typed-array-names@1.1.0: {}
postcss-import@15.1.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.11
postcss-js@4.1.0(postcss@8.5.6):
dependencies:
camelcase-css: 2.0.1
postcss: 8.5.6
postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6):
dependencies:
lilconfig: 3.1.3
optionalDependencies:
jiti: 1.21.7
postcss: 8.5.6
postcss-nested@6.2.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 6.1.2
postcss-prefix-selector@1.16.1(postcss@5.2.18):
dependencies:
postcss: 5.2.18
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-value-parser@4.2.0: {}
postcss@5.2.18:
dependencies:
chalk: 1.1.3
......@@ -4025,12 +4388,20 @@ snapshots:
parchment: 1.1.4
quill-delta: 3.6.3
read-cache@1.0.0:
dependencies:
pify: 2.3.0
readable-stream@3.6.2:
dependencies:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
readdirp@3.6.0:
dependencies:
picomatch: 2.3.1
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
......@@ -4062,6 +4433,12 @@ snapshots:
resolve-url@0.2.1: {}
resolve@1.22.11:
dependencies:
is-core-module: 2.16.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
ret@0.1.15: {}
reusify@1.1.0: {}
......@@ -4400,6 +4777,16 @@ snapshots:
dependencies:
js-tokens: 9.0.1
sucrase@3.35.1:
dependencies:
'@jridgewell/gen-mapping': 0.3.13
commander: 4.1.1
lines-and-columns: 1.2.4
mz: 2.7.0
pirates: 4.0.7
tinyglobby: 0.2.15
ts-interface-checker: 0.1.13
superjson@2.2.6:
dependencies:
copy-anything: 4.0.5
......@@ -4418,6 +4805,8 @@ snapshots:
dependencies:
has-flag: 4.0.0
supports-preserve-symlinks-flag@1.0.0: {}
svg-baker@1.7.0:
dependencies:
bluebird: 3.7.2
......@@ -4452,6 +4841,42 @@ snapshots:
sync-message-port@1.1.3: {}
tailwindcss@3.4.19:
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
chokidar: 3.6.0
didyoumean: 1.2.2
dlv: 1.1.3
fast-glob: 3.3.3
glob-parent: 6.0.2
is-glob: 4.0.3
jiti: 1.21.7
lilconfig: 3.1.3
micromatch: 4.0.8
normalize-path: 3.0.0
object-hash: 3.0.0
picocolors: 1.1.1
postcss: 8.5.6
postcss-import: 15.1.0(postcss@8.5.6)
postcss-js: 4.1.0(postcss@8.5.6)
postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)
postcss-nested: 6.2.0(postcss@8.5.6)
postcss-selector-parser: 6.1.2
resolve: 1.22.11
sucrase: 3.35.1
transitivePeerDependencies:
- tsx
- yaml
thenify-all@1.6.0:
dependencies:
thenify: 3.3.1
thenify@3.3.1:
dependencies:
any-promise: 1.3.0
tiny-emitter@2.1.0: {}
tinyglobby@0.2.15:
......@@ -4485,6 +4910,8 @@ snapshots:
typedarray.prototype.slice: 1.0.5
which-typed-array: 1.1.19
ts-interface-checker@0.1.13: {}
tslib@2.3.0: {}
tslib@2.8.1: {}
......@@ -4603,6 +5030,12 @@ snapshots:
has-value: 0.3.1
isobject: 3.0.1
update-browserslist-db@1.2.3(browserslist@4.28.1):
dependencies:
browserslist: 4.28.1
escalade: 3.2.0
picocolors: 1.1.1
urix@0.1.0: {}
use@3.1.1: {}
......@@ -4613,16 +5046,16 @@ snapshots:
vary@1.1.2: {}
vite-plugin-compression@0.5.1(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)):
vite-plugin-compression@0.5.1(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)):
dependencies:
chalk: 4.1.2
debug: 4.4.3
fs-extra: 10.1.0
vite: 6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)
vite: 6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)
transitivePeerDependencies:
- supports-color
vite-plugin-svg-icons@2.0.1(vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)):
vite-plugin-svg-icons@2.0.1(vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)):
dependencies:
'@types/svgo': 2.6.4
cors: 2.8.5
......@@ -4632,11 +5065,11 @@ snapshots:
pathe: 0.2.0
svg-baker: 1.7.0
svgo: 2.8.0
vite: 6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1)
vite: 6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1)
transitivePeerDependencies:
- supports-color
vite@6.3.5(@types/node@25.0.2)(sass-embedded@1.89.1):
vite@6.3.5(@types/node@25.0.2)(jiti@1.21.7)(sass-embedded@1.89.1):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
......@@ -4647,6 +5080,7 @@ snapshots:
optionalDependencies:
'@types/node': 25.0.2
fsevents: 2.3.3
jiti: 1.21.7
sass-embedded: 1.89.1
vue-cropper@1.1.1: {}
......
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
\ No newline at end of file
//==本JS是加载Lodop插件或Web打印服务CLodop/Lodop7的综合示例,可直接使用,建议理解后融入自己程序==
//用双端口加载主JS文件Lodop.js(或CLodopfuncs.js兼容老版本)以防其中某端口被占:
var MainJS ="CLodopfuncs.js",
URL_WS1 = "ws://localhost:8000/"+MainJS, //ws用8000/18000
URL_WS2 = "ws://localhost:18000/"+MainJS,
URL_HTTP1 = "http://localhost:8000/"+MainJS, //http用8000/18000
URL_HTTP2 = "http://localhost:18000/"+MainJS,
URL_HTTP3 = "https://localhost.lodop.net:8443/"+MainJS; //https用8000/8443
var CreatedOKLodopObject, CLodopIsLocal, LoadJsState;
//==判断是否需要CLodop(那些不支持插件的浏览器):==
function needCLodop() {
try {
var ua = navigator.userAgent;
if (ua.match(/Windows\sPhone/i) ||
ua.match(/iPhone|iPod|iPad/i) ||
ua.match(/Android/i) ||
ua.match(/Edge\D?\d+/i))
return true;
var verTrident = ua.match(/Trident\D?\d+/i);
var verIE = ua.match(/MSIE\D?\d+/i);
var verOPR = ua.match(/OPR\D?\d+/i);
var verFF = ua.match(/Firefox\D?\d+/i);
var x64 = ua.match(/x64/i);
if ((!verTrident) && (!verIE) && (x64)) return true;
else if (verFF) {
verFF = verFF[0].match(/\d+/);
if ((verFF[0] >= 41) || (x64)) return true;
} else if (verOPR) {
verOPR = verOPR[0].match(/\d+/);
if (verOPR[0] >= 32) return true;
} else if ((!verTrident) && (!verIE)) {
var verChrome = ua.match(/Chrome\D?\d+/i);
if (verChrome) {
verChrome = verChrome[0].match(/\d+/);
if (verChrome[0] >= 41) return true;
}
}
return false;
} catch (err) {
return true;
}
}
//==检查加载成功与否,如没成功则用http(s)再试==
//==低版本CLODOP6.561/Lodop7.043及前)用本方法==
function checkOrTryHttp() {
if (window.getCLodop) {
LoadJsState = "complete";
return true;
}
if (LoadJsState == "loadingB" || LoadJsState == "complete") return;
LoadJsState = "loadingB";
var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
var JS1 = document.createElement("script")
,JS2 = document.createElement("script")
,JS3 = document.createElement("script");
JS1.src = URL_HTTP1;
JS2.src = URL_HTTP2;
JS3.src = URL_HTTP3;
JS1.onload = JS2.onload = JS3.onload = JS2.onerror = JS3.onerror=function(){LoadJsState = "complete";}
JS1.onerror = function(e) {
if (window.location.protocol !== 'https:')
head.insertBefore(JS2, head.firstChild); else
head.insertBefore(JS3, head.firstChild);
}
head.insertBefore(JS1,head.firstChild);
}
//==加载Lodop对象的主过程:==
(function loadCLodop(){
if (!needCLodop()) return;
CLodopIsLocal = !!((URL_WS1 + URL_WS2).match(/\/\/localho|\/\/127.0.0./i));
LoadJsState = "loadingA";
if (!window.WebSocket && window.MozWebSocket) window.WebSocket=window.MozWebSocket;
//ws方式速度快(小于200ms)且可避免CORS错误,但要求Lodop版本足够新:
try {
var WSK1=new WebSocket(URL_WS1);
WSK1.onopen = function(e) { setTimeout("checkOrTryHttp()",200); }
WSK1.onmessage = function(e) {if (!window.getCLodop) eval(e.data);}
WSK1.onerror = function(e) {
var WSK2=new WebSocket(URL_WS2);
WSK2.onopen = function(e) {setTimeout("checkOrTryHttp()",200);}
WSK2.onmessage = function(e) {if (!window.getCLodop) eval(e.data);}
WSK2.onerror= function(e) {checkOrTryHttp();}
}
} catch(e){
checkOrTryHttp();
}
})();
//==获取LODOP对象主过程,判断是否安装、需否升级:==
// 显示HTML格式的弹框
function showHtmlAlert(htmlContent) {
// 创建遮罩层
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; display:flex; justify-content:center; align-items:center;';
// 创建弹窗容器
var alertBox = document.createElement('div');
alertBox.style.cssText = 'background:white; border-radius:8px; padding:20px; max-width:500px; box-shadow:0 4px 20px rgba(0,0,0,0.3);';
// 设置HTML内容
alertBox.innerHTML = htmlContent;
// 添加a标签样式
var style = document.createElement('style');
style.textContent = 'a { color: blue !important; text-decoration: underline !important; }';
alertBox.appendChild(style);
// 重写a标签下载功能
var links = alertBox.querySelectorAll('a');
links.forEach(function(link) {
link.addEventListener('click', function(e) {
var url = this.getAttribute('href');
// 判断是否为下载链接(排除协议链接等非下载链接)
if (url && (url.endsWith('.exe') || url.endsWith('.tar.gz') || url.endsWith('.zip'))) {
e.preventDefault();
// 创建隐藏的下载链接
var downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = url.split('/').pop();
downloadLink.style.display = 'none';
// 添加到页面并触发点击
document.body.appendChild(downloadLink);
downloadLink.click();
// 清理
document.body.removeChild(downloadLink);
}
// 对于非下载链接(如CLodop.protocol:setup),不进行特殊处理,使用默认行为
});
});
// 创建关闭按钮
var closeBtn = document.createElement('button');
closeBtn.textContent = '关闭';
closeBtn.style.cssText = 'margin-top:15px; padding:8px 16px; background:#1890ff; color:white; border:none; border-radius:4px; cursor:pointer; float:right;';
closeBtn.onclick = function() {
document.body.removeChild(overlay);
};
// 添加关闭按钮
alertBox.appendChild(document.createElement('br'));
alertBox.appendChild(closeBtn);
// 添加到页面
overlay.appendChild(alertBox);
document.body.appendChild(overlay);
}
function getLodop(oOBJECT, oEMBED) {
var strFontTag = "<br><font color='#FF00FF'>打印控件";
var strLodopInstall = strFontTag + "未安装!点击这里<a href='/lodop/install_lodop32.exe' target='_self'>执行安装</a>";
var strLodopUpdate = strFontTag + "需要升级!点击这里<a href='/lodop/install_lodop32.exe' target='_self'>执行升级</a>";
var strLodop64Install = strFontTag + "未安装!点击这里<a href='/lodop/install_lodop64.exe' target='_self'>执行安装</a>";
var strLodop64Update = strFontTag + "需要升级!点击这里<a href='/lodop/install_lodop64.exe' target='_self'>执行升级</a>";
var strCLodopInstallA = "<br><font color='#FF00FF'>Web打印服务CLodop未安装启动,点击这里<a href='/lodop/CLodop_Setup_for_Win32NT.exe' target='_self'>下载执行安装</a>";
var strCLodopInstallB = "<br>(若此前已安装过,可<a href='CLodop.protocol:setup' target='_self'>点这里直接再次启动</a>)";
var strCLodopUpdate = "<br><font color='#FF00FF'>Web打印服务CLodop需升级!点击这里<a href='/lodop/CLodop_Setup_for_Win32NT.exe' target='_self'>执行升级</a>";
var strLodop7FontTag = "<br><font color='#FF00FF'>Web打印服务Lodop7";
var strLodop7HrefX86 = "点击这里<a href='/lodop/Lodop7_Linux_X86_64.tar.gz' target='_self'>下载安装</a>(下载后解压,点击lodop文件开始执行)";
var strLodop7HrefARM = "点击这里<a href='/lodop/Lodop7_Linux_ARM64.tar.gz' target='_self'>下载安装</a>(下载后解压,点击lodop文件开始执行)";
var strLodop7Install_X86 = strLodop7FontTag + "未安装启动," + strLodop7HrefX86;
var strLodop7Install_ARM = strLodop7FontTag + "未安装启动," + strLodop7HrefARM;
var strLodop7Update_X86 = strLodop7FontTag + "需升级," + strLodop7HrefX86;
var strLodop7Update_ARM = strLodop7FontTag + "需升级," + strLodop7HrefARM;
var strInstallOK = ",成功后请刷新本页面或重启浏览器。</font>";
var LODOP;
try {
var isWinIE = (/MSIE/i.test(navigator.userAgent)) || (/Trident/i.test(navigator.userAgent));
var isWinIE64 = isWinIE && (/x64/i.test(navigator.userAgent));
var isLinuxX86 = (/Linux/i.test(navigator.platform)) && (/x86/i.test(navigator.platform));
var isLinuxARM = (/Linux/i.test(navigator.platform)) && (/aarch/i.test(navigator.platform));
if (needCLodop() || isLinuxX86 || isLinuxARM) {
try {
LODOP = window.getCLodop();
} catch (err) {}
if (!LODOP && LoadJsState !== "complete") {
if (!LoadJsState)
showHtmlAlert("未曾加载Lodop主JS文件,请先调用loadCLodop过程."); else
showHtmlAlert("打印插件还未加载完成,请稍等一下再操作.");
return;
}
var strAlertMessage;
if (!LODOP) {
if (isLinuxX86)
strAlertMessage = strLodop7Install_X86;
else if (isLinuxARM)
strAlertMessage = strLodop7Install_ARM;
else
strAlertMessage = strCLodopInstallA + (CLodopIsLocal ? strCLodopInstallB : "");
showHtmlAlert(strAlertMessage + strInstallOK);
return;
} else {
if (isLinuxX86 && LODOP.CVERSION < "7.1.0.5")
strAlertMessage = strLodop7Update_X86;
else if (isLinuxARM && LODOP.CVERSION < "7.1.0.5")
strAlertMessage = strLodop7Update_ARM;
else if (CLODOP.CVERSION < "6.6.2.8")
strAlertMessage = strCLodopUpdate;
if (strAlertMessage)
showHtmlAlert(strAlertMessage + strInstallOK);
}
} else {
//==如果页面有Lodop插件就直接使用,否则新建:==
if (oOBJECT || oEMBED) {
if (isWinIE)
LODOP = oOBJECT;
else
LODOP = oEMBED;
} else if (!CreatedOKLodopObject) {
LODOP = document.createElement("object");
LODOP.setAttribute("width", 0);
LODOP.setAttribute("height", 0);
LODOP.setAttribute("style", "position:absolute;left:0px;top:-100px;width:0px;height:0px;");
if (isWinIE)
LODOP.setAttribute("classid", "clsid:2105C259-1E0C-4534-8141-A753534CB4CA");
else
LODOP.setAttribute("type", "application/x-print-lodop");
document.documentElement.appendChild(LODOP);
CreatedOKLodopObject = LODOP;
} else
LODOP = CreatedOKLodopObject;
//==Lodop插件未安装时提示下载地址:==
if ((!LODOP) || (!LODOP.VERSION)) {
showHtmlAlert((isWinIE64 ? strLodop64Install : strLodopInstall) + strInstallOK);
return LODOP;
}
if (LODOP.VERSION < "6.2.2.6") {
showHtmlAlert((isWinIE64 ? strLodop64Update : strLodopUpdate) + strInstallOK);
}
}
//===如下空白位置适合调用统一功能(如注册语句、语言选择等):=======================
//===============================================================================
return LODOP;
} catch (err) {
showHtmlAlert("getLodop出错:" + err);
}
}
import request from '@/utils/request'
// 生成入库单号
export function generateInboundOrderNo() {
return request({
url: '/ware/codeGenerator/generateInboundOrderNo',
method: 'get'
})
}
// 生成出库单号
export function generateOutboundOrderNo() {
return request({
url: '/ware/codeGenerator/generateOutboundOrderNo',
method: 'get'
})
}
// 生成批次号
export function generateBatchNo() {
return request({
url: '/ware/codeGenerator/generateBatchNo',
method: 'get'
})
}
......@@ -17,7 +17,7 @@ export function getWmsInboundOrder(orderId) {
})
}
// 新增入库单
// 新增入库单
export function addWmsInboundOrder(data) {
return request({
url: '/ware/wmsInboundOrder',
......@@ -25,8 +25,24 @@ export function addWmsInboundOrder(data) {
data: data
})
}
// 保存入库单
export function saveWmsInboundOrder(data) {
return request({
url: '/ware/wmsInboundOrder/saveInBound',
method: 'post',
data: data
})
}
// 入库功能(添加到库存)
export function addToInventory(data) {
return request({
url: '/ware/wmsInboundOrder/addMy',
method: 'post',
data: data
})
}
// 修改入库单
// 修改入库单
export function updateWmsInboundOrder(data) {
return request({
url: '/ware/wmsInboundOrder',
......@@ -34,6 +50,15 @@ export function updateWmsInboundOrder(data) {
data: data
})
}
// 修改入库单明细
export function updateWmsInboundOrderItem(data) {
return request({
url: '/ware/wmsInboundOrder/updateItem',
method: 'put',
data: data
})
}
// 删除入库单主
export function delWmsInboundOrder(orderId) {
......@@ -42,3 +67,10 @@ export function delWmsInboundOrder(orderId) {
method: 'delete'
})
}
export function delWmsInboundOrderItem(orderId, itemId) {
return request({
url: '/ware/wmsInboundOrder/deleteItem/' + orderId + '/' + itemId,
method: 'delete'
})
}
@use './tailwind.css';
@use './mixin.scss';
@use './transition.scss';
@use './element-ui.scss';
......@@ -5,6 +6,7 @@
@use './btn.scss';
@use './ruoyi.scss';
body {
height: 100%;
margin: 0;
......
@tailwind base;
@tailwind components;
@tailwind utilities;
......@@ -32,7 +32,7 @@ $base-sub-menu-background: #1e3e08;
$base-sub-menu-hover: #152d06;
// 组件变量
$--color-primary: #409EFF;
$--color-primary: #2b580c;
$--color-success: #67C23A;
$--color-warning: #E6A23C;
$--color-danger: #F56C6C;
......@@ -78,6 +78,7 @@ $--color-info: #909399;
/* splitpanes default-theme 变量 */
--splitpanes-default-bg: #ffffff;
--el-color-primary: #{$--color-primary} !important;
}
// 暗黑模式变量
......
<template>
<div class="location-cascader">
<el-form :model="form" label-width="80px">
<el-form-item label="仓库" v-if="!modelValue.warehouseId">
<el-select v-model="form.warehouseId" placeholder="请选择仓库" @change="handleWarehouseChange">
<el-option
v-for="warehouse in warehouseList"
:key="warehouse.warehouseId"
:label="warehouse.warehouseName"
:value="warehouse.warehouseId"
/>
</el-select>
</el-form-item>
<el-form-item label="库区">
<el-select v-model="form.areaId" placeholder="请选择库区" @change="handleAreaChange" :disabled="!form.warehouseId">
<el-option
v-for="area in areaList"
:key="area.areaId"
:label="area.areaName"
:value="area.areaId"
/>
</el-select>
</el-form-item>
<el-form-item label="货架">
<el-select v-model="form.locationId" placeholder="请选择货架" :disabled="!form.areaId">
<el-option
v-for="location in locationList"
:key="location.locationId"
:label="location.locationCode"
:value="location.locationId"
/>
</el-select>
</el-form-item>
</el-form>
</div>
</template>
<script setup name="LocationCascaderSelect">
import { ref, reactive, watch } from 'vue'
import { listWmsWarehouse } from "@/api/ware/wmsWarehouse"
import { listWmsArea } from "@/api/ware/wmsArea"
import { listWmsLocation } from "@/api/ware/wmsLocation"
const props = defineProps({
modelValue: {
type: Object,
default: () => ({
warehouseId: null,
areaId: null,
locationId: null
})
}
})
const emit = defineEmits(['update:modelValue'])
// 表单数据
const form = reactive({
warehouseId: props.modelValue.warehouseId,
areaId: props.modelValue.areaId,
locationId: props.modelValue.locationId
})
// 监听props变化,同步本地状态
watch(() => props.modelValue, (newVal) => {
form.warehouseId = newVal.warehouseId
form.areaId = newVal.areaId
form.locationId = newVal.locationId
}, { deep: true })
// 仓库列表
const warehouseList = ref([])
// 库区列表
const areaList = ref([])
// 货架列表
const locationList = ref([])
// 加载状态
const loading = ref(false)
// 初始化获取仓库列表
const initWarehouseList = () => {
loading.value = true
listWmsWarehouse({ pageNum: 1, pageSize: 100 }).then(response => {
warehouseList.value = response.rows
loading.value = false
}).catch(error => {
console.error('获取仓库列表失败:', error)
loading.value = false
})
}
// 获取库区列表
const getAreaList = (warehouseId) => {
if (!warehouseId) {
areaList.value = []
form.areaId = null
form.locationId = null
locationList.value = []
return
}
loading.value = true
listWmsArea({ pageNum: 1, pageSize: 100, warehouseId: warehouseId }).then(response => {
areaList.value = response.rows
loading.value = false
}).catch(error => {
console.error('获取库区列表失败:', error)
loading.value = false
})
}
// 获取货架列表
const getLocationList = (areaId) => {
if (!areaId) {
locationList.value = []
form.locationId = null
return
}
loading.value = true
listWmsLocation({ pageNum: 1, pageSize: 100, areaId: areaId }).then(response => {
locationList.value = response.rows
loading.value = false
}).catch(error => {
console.error('获取货架列表失败:', error)
loading.value = false
})
}
// 仓库选择变化
const handleWarehouseChange = (warehouseId) => {
getAreaList(warehouseId)
updateModelValue()
}
// 库区选择变化
const handleAreaChange = (areaId) => {
getLocationList(areaId)
updateModelValue()
}
// 监听表单变化,更新modelValue
watch(
() => [form.warehouseId, form.areaId, form.locationId],
() => {
updateModelValue()
},
{ deep: true }
)
// 更新modelValue
const updateModelValue = () => {
emit('update:modelValue', {
warehouseId: form.warehouseId,
areaId: form.areaId,
locationId: form.locationId
})
}
// 初始化
initWarehouseList()
// 如果初始有仓库ID,获取对应库区和货架
if (props.modelValue.warehouseId) {
getAreaList(props.modelValue.warehouseId)
if (props.modelValue.areaId) {
getLocationList(props.modelValue.areaId)
}
}
</script>
<style scoped>
.location-cascader {
padding: 10px;
background-color: #f5f7fa;
border-radius: 4px;
}
</style>
\ No newline at end of file
......@@ -48,6 +48,7 @@
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="success" icon="Plus" @click="handleAddMaterial">新增</el-button>
</el-form-item>
</el-form>
......@@ -77,12 +78,80 @@
</div>
</template>
</el-dialog>
<!-- 新增物资对话框 -->
<el-dialog :title="addMaterialTitle" v-model="addMaterialVisible" width="800px" append-to-body>
<el-form ref="addMaterialRef" :model="addMaterialForm" :rules="addMaterialRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="物资编码" prop="materialCode">
<el-input v-model="addMaterialForm.materialCode" placeholder="请输入物资编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物资名称" prop="materialName">
<el-input v-model="addMaterialForm.materialName" placeholder="请输入物资名称" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="物资分类" prop="categoryId">
<el-tree-select
v-model="addMaterialForm.categoryId"
:data="materialCategoryOptions"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
value-key="categoryId"
placeholder="请选择物资分类"
check-strictly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规格型号" prop="specification">
<el-input v-model="addMaterialForm.specification" placeholder="请输入规格型号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计量单位" prop="unit">
<el-input v-model="addMaterialForm.unit" placeholder="请输入计量单位" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产厂家" prop="manufacturer">
<el-input v-model="addMaterialForm.manufacturer" placeholder="请输入生产厂家" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="安全库存" prop="safetyStock">
<el-input v-model.number="addMaterialForm.safetyStock" placeholder="请输入安全库存" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-switch v-model="addMaterialForm.status" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitAddMaterial">确 定</el-button>
<el-button @click="cancelAddMaterial">取 消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="MaterialSelectDialog">
import { ref, reactive, watch } from 'vue'
import { listWmsMaterial } from "@/api/ware/wmsMaterial"
import { listWmsMaterial, addWmsMaterial } from "@/api/ware/wmsMaterial"
import { listWmsMaterialCategory } from "@/api/ware/wmsMaterialCategory"
import { ElMessage } from 'element-plus'
const props = defineProps({
visible: {
......@@ -121,6 +190,42 @@ const selectedMaterials = ref([])
// 物资分类树选项
const materialCategoryOptions = ref([])
// 新增物资相关
const addMaterialVisible = ref(false)
const addMaterialTitle = ref('新增物资')
const addMaterialForm = reactive({
materialCode: '',
materialName: '',
categoryId: null,
specification: '',
unit: '',
manufacturer: '',
safetyStock: null,
status: true
})
// 新增物资表单验证规则
const addMaterialRules = reactive({
materialCode: [
{ required: true, message: '物资编码不能为空', trigger: 'blur' }
],
materialName: [
{ required: true, message: '物资名称不能为空', trigger: 'blur' }
],
categoryId: [
{ required: true, message: '物资分类不能为空', trigger: 'change' }
],
specification: [
{ required: true, message: '规格型号不能为空', trigger: 'blur' }
],
unit: [
{ required: true, message: '计量单位不能为空', trigger: 'blur' }
]
})
// 新增物资表单引用
const addMaterialRef = ref(null)
// 查询参数
const queryParams = reactive({
pageNum: 1,
......@@ -173,6 +278,46 @@ const handleCancel = () => {
dialogVisible.value = false
}
// 打开新增物资对话框
const handleAddMaterial = () => {
addMaterialTitle.value = '新增物资'
// 重置新增表单
if (addMaterialRef.value) {
addMaterialRef.value.resetFields()
}
// 设置默认状态为启用
addMaterialForm.status = true
addMaterialVisible.value = true
}
// 提交新增物资
const submitAddMaterial = () => {
// 表单验证
if (!addMaterialRef.value) return
addMaterialRef.value.validate((valid) => {
if (valid) {
// 提交新增请求
addWmsMaterial(addMaterialForm).then(response => {
// 关闭新增对话框
addMaterialVisible.value = false
// 刷新物资列表
handleQuery()
// 提示新增成功
ElMessage.success('新增物资成功')
}).catch(error => {
console.error('新增物资失败:', error)
ElMessage.error('新增物资失败,请重试')
})
}
})
}
// 取消新增物资
const cancelAddMaterial = () => {
addMaterialVisible.value = false
}
// 查询物资分类下拉树结构
const getTreeselect = () => {
return new Promise((resolve) => {
......
<template>
<el-dialog :title="title" v-model="dialogVisible" width="1000px" append-to-body>
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px">
<el-form-item label="天线编码" prop="antennaCode">
<el-input
v-model="queryParams.antennaCode"
placeholder="请输入天线编码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="读写器ID" prop="readerId">
<el-input
v-model="queryParams.readerId"
placeholder="请输入读写器ID"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库ID" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库ID"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="安装位置" prop="installationLocation">
<el-input
v-model="queryParams.installationLocation"
placeholder="请输入安装位置"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="ptlTagList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="天线ID" align="center" prop="antennaId" />
<el-table-column label="天线编码" align="center" prop="antennaCode" />
<el-table-column label="读写器ID" align="center" prop="readerId" />
<el-table-column label="仓库ID" align="center" prop="warehouseId" />
<el-table-column label="库区ID" align="center" prop="areaId" />
<el-table-column label="货架ID" align="center" prop="locationId" />
<el-table-column label="安装位置" align="center" prop="installationLocation" />
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handleQuery"
/>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleConfirm">确 定</el-button>
<el-button @click="handleCancel">取 消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="PtlTagSelectDialog">
import { ref, reactive, watch } from 'vue'
import { listWmsRfidAntenna } from "@/api/ware/wmsRfidAntenna"
const props = defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '选择PTL标签'
}
})
const emit = defineEmits(['update:visible', 'confirm', 'cancel'])
// 本地对话框可见性状态
const dialogVisible = ref(false)
// 监听props.visible变化,更新对话框可见性
watch(() => props.visible, (newVal) => {
dialogVisible.value = newVal
})
// 监听dialogVisible变化,向父组件发送更新
watch(dialogVisible, (newVal) => {
emit('update:visible', newVal)
})
// 表格加载状态
const loading = ref(false)
// 分页总条数
const total = ref(0)
// 查询参数
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
antennaCode: undefined,
readerId: undefined,
warehouseId: undefined,
installationLocation: undefined
})
// 表格数据
const ptlTagList = ref([])
// 选中的数据
const selectionList = ref([])
// 初始化
const init = () => {
selectionList.value = []
ptlTagList.value = []
queryParams.pageNum = 1
queryParams.pageSize = 10
queryParams.antennaCode = undefined
queryParams.readerId = undefined
queryParams.warehouseId = undefined
queryParams.installationLocation = undefined
}
// 查询数据
const handleQuery = () => {
loading.value = true
listWmsRfidAntenna(queryParams).then(response => {
ptlTagList.value = response.rows
total.value = response.total
loading.value = false
})
}
// 重置查询
const resetQuery = () => {
queryParams.antennaCode = undefined
queryParams.readerId = undefined
queryParams.warehouseId = undefined
queryParams.installationLocation = undefined
handleQuery()
}
// 处理选择变化
const handleSelectionChange = (selection) => {
selectionList.value = selection
}
// 处理确认选择
const handleConfirm = () => {
if (selectionList.value.length === 0) {
ElMessage.warning('请选择一条记录')
return
}
emit('confirm', selectionList.value)
dialogVisible.value = false
}
// 处理取消
const handleCancel = () => {
emit('cancel')
dialogVisible.value = false
}
// 当对话框打开时初始化数据
watch(() => dialogVisible.value, (newVal) => {
if (newVal) {
init()
handleQuery()
}
})
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
</style>
\ No newline at end of file
<template>
<el-dialog
:title="title"
:model-value="visible"
@update:model-value="handleClose"
width="600px"
append-to-body
>
<el-form :model="form" label-width="120px">
<!-- 尺寸选择 -->
<el-form-item label="二维码尺寸">
<el-radio-group v-model="form.sizeType" @change="handleSizeChange">
<el-radio label="default">系统默认尺寸</el-radio>
<el-radio label="custom">自定义尺寸</el-radio>
</el-radio-group>
</el-form-item>
<!-- 默认尺寸选择 -->
<el-form-item label="默认尺寸" v-if="form.sizeType === 'default'">
<el-select v-model="form.defaultSize" placeholder="请选择尺寸">
<el-option label="20mm×20mm" :value="{width: 20, height: 20}" />
<el-option label="30mm×30mm" :value="{width: 30, height: 30}" />
<el-option label="40mm×40mm" :value="{width: 40, height: 40}" />
<el-option label="50mm×50mm" :value="{width: 50, height: 50}" />
<el-option label="60mm×60mm" :value="{width: 60, height: 60}" />
</el-select>
</el-form-item>
<!-- 自定义尺寸 -->
<el-form-item label="自定义尺寸" v-if="form.sizeType === 'custom'">
<el-row :gutter="10">
<el-col :span="11">
<el-input-number
v-model="form.customWidth"
:min="10"
:max="200"
:step="1"
placeholder="宽度(mm)"
style="width: 100%"
/>
</el-col>
<el-col :span="2" style="text-align: center; line-height: 38px;">×</el-col>
<el-col :span="11">
<el-input-number
v-model="form.customHeight"
:min="10"
:max="200"
:step="1"
placeholder="高度(mm)"
style="width: 100%"
/>
</el-col>
</el-row>
</el-form-item>
<!-- 预览区域 -->
<el-form-item label="二维码预览">
<div class="qrcode-preview-container">
<div
class="qrcode-preview"
:style="{
width: previewSize.width + 'px',
height: previewSize.height + 'px',
border: '1px solid #dcdfe6'
}"
>
<!-- 这里使用假的二维码预览,实际应该使用二维码生成库 -->
<div class="qrcode-placeholder" v-if="!previewVisible">
点击预览按钮生成二维码
</div>
<div v-else>
<!-- 实际项目中应该使用qrcode库生成二维码 -->
<div class="qrcode-content">
<svg width="100%" height="100%" viewBox="0 0 100 100">
<rect width="100" height="100" fill="white" />
<!-- 简单的二维码样式 -->
<rect x="10" y="10" width="80" height="80" fill="none" stroke="#333" stroke-width="2" />
<rect x="20" y="20" width="10" height="10" fill="#333" />
<rect x="45" y="20" width="10" height="10" fill="#333" />
<rect x="70" y="20" width="10" height="10" fill="#333" />
<rect x="20" y="45" width="10" height="10" fill="#333" />
<rect x="45" y="45" width="10" height="10" fill="#333" />
<rect x="70" y="45" width="10" height="10" fill="#333" />
<rect x="20" y="70" width="10" height="10" fill="#333" />
<rect x="45" y="70" width="10" height="10" fill="#333" />
<rect x="70" y="70" width="10" height="10" fill="#333" />
</svg>
</div>
<div class="qrcode-value" v-if="qrcodeValue">{{ qrcodeValue }}</div>
</div>
</div>
</div>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handlePreview">预览二维码</el-button>
<el-button type="primary" @click="handlePrint">打印</el-button>
<el-button @click="cancel">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, computed, watch } from 'vue'
// 组件属性
const props = defineProps({
title: {
type: String,
default: '打印二维码'
},
visible: {
type: Boolean,
default: false
},
qrcodeValue: {
type: String,
default: ''
}
})
// 组件事件
const emit = defineEmits(['update:visible', 'print'])
// 表单数据
const form = reactive({
sizeType: 'default', // default: 默认尺寸, custom: 自定义尺寸
defaultSize: { width: 40, height: 40 }, // 默认尺寸
customWidth: 40, // 自定义宽度(mm)
customHeight: 40 // 自定义高度(mm)
})
// 预览相关
const previewVisible = ref(false)
const previewSize = computed(() => {
// 将毫米转换为像素进行预览 (1mm ≈ 3.7795275591px)
const scale = 3.7795275591
let width, height
if (form.sizeType === 'default') {
width = form.defaultSize.width
height = form.defaultSize.height
} else {
width = form.customWidth
height = form.customHeight
}
return {
width: width * scale,
height: height * scale
}
})
// 尺寸变化处理
function handleSizeChange() {
if (form.sizeType === 'custom') {
// 切换到自定义尺寸时,使用当前默认尺寸的值
form.customWidth = form.defaultSize.width
form.customHeight = form.defaultSize.height
}
}
// 预览二维码
function handlePreview() {
previewVisible.value = true
}
// 打印
function handlePrint() {
// 获取当前选择的尺寸 (mm)
let width, height
if (form.sizeType === 'default') {
width = form.defaultSize.width
height = form.defaultSize.height
} else {
width = form.customWidth
height = form.customHeight
}
// 调用父组件的打印方法
emit('print', {
width,
height,
qrcodeValue: props.qrcodeValue
})
// 关闭对话框
cancel()
}
// 处理对话框关闭
function handleClose(newVal) {
emit('update:visible', newVal)
}
// 取消
function cancel() {
emit('update:visible', false)
}
</script>
<style scoped>
.qrcode-preview-container {
display: flex;
justify-content: center;
margin-top: 10px;
}
.qrcode-preview {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10px;
background-color: #f5f7fa;
}
.qrcode-placeholder {
color: #909399;
text-align: center;
}
.qrcode-content {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.qrcode-value {
margin-top: 10px;
text-align: center;
font-size: 14px;
color: #606266;
}
</style>
\ No newline at end of file
<template>
<el-dialog :title="title" v-model="dialogVisible" width="1200px" append-to-body>
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px">
<el-form-item label="标签编码" prop="tagCode">
<el-input
v-model="queryParams.tagCode"
placeholder="请输入标签编码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="EPC编码" prop="epcCode">
<el-input
v-model="queryParams.epcCode"
placeholder="请输入EPC编码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="TID编码" prop="tidCode">
<el-input
v-model="queryParams.tidCode"
placeholder="请输入TID编码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="标签类型" prop="tagType">
<el-input
v-model="queryParams.tagType"
placeholder="请输入标签类型"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="标签状态" prop="tagStatus">
<el-input
v-model="queryParams.tagStatus"
placeholder="请输入标签状态"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="rfidTagList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="标签ID" align="center" prop="tagId" />
<el-table-column label="标签编码" align="center" prop="tagCode" />
<el-table-column label="EPC编码" align="center" prop="epcCode" />
<el-table-column label="TID编码" align="center" prop="tidCode" />
<el-table-column label="标签类型" align="center" prop="tagType" />
<el-table-column label="标签状态" align="center" prop="tagStatus" />
<el-table-column label="最后读取时间" align="center" prop="lastReadTime">
<template #default="scope">
<span>{{ parseTime(scope.row.lastReadTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handleQuery"
/>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleConfirm"> </el-button>
<el-button @click="handleCancel"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="RfidTagSelectDialog">
import { ref, reactive, watch } from 'vue'
import { listWmsRfidTag } from "@/api/ware/wmsRfidTag"
import { parseTime } from "@/utils/ruoyi"
const props = defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '选择RFID标签'
}
})
const emit = defineEmits(['update:visible', 'confirm', 'cancel'])
// 本地对话框可见性状态
const dialogVisible = ref(false)
// 监听props.visible变化,更新对话框可见性
watch(() => props.visible, (newVal) => {
dialogVisible.value = newVal
})
// 监听dialogVisible变化,向父组件发送更新
watch(dialogVisible, (newVal) => {
emit('update:visible', newVal)
})
// 表格加载状态
const loading = ref(false)
// 分页总条数
const total = ref(0)
// 查询参数
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
tagCode: undefined,
epcCode: undefined,
tidCode: undefined,
tagType: undefined,
tagStatus: undefined
})
// 表格数据
const rfidTagList = ref([])
// 选中的数据
const selectionList = ref([])
// 初始化
const init = () => {
selectionList.value = []
rfidTagList.value = []
queryParams.pageNum = 1
queryParams.pageSize = 10
queryParams.tagCode = undefined
queryParams.epcCode = undefined
queryParams.tidCode = undefined
queryParams.tagType = undefined
queryParams.tagStatus = undefined
}
// 查询数据
const handleQuery = () => {
loading.value = true
listWmsRfidTag(queryParams).then(response => {
rfidTagList.value = response.rows
total.value = response.total
loading.value = false
})
}
// 重置查询
const resetQuery = () => {
queryParams.tagCode = undefined
queryParams.epcCode = undefined
queryParams.tidCode = undefined
queryParams.tagType = undefined
queryParams.tagStatus = undefined
handleQuery()
}
// 处理选择变化
const handleSelectionChange = (selection) => {
selectionList.value = selection
}
// 处理确认选择
const handleConfirm = () => {
if (selectionList.value.length === 0) {
ElMessage.warning('请选择一条记录')
return
}
emit('confirm', selectionList.value)
dialogVisible.value = false
}
// 处理取消
const handleCancel = () => {
emit('cancel')
dialogVisible.value = false
}
// 当对话框打开时初始化数据
watch(() => dialogVisible.value, (newVal) => {
if (newVal) {
init()
handleQuery()
}
})
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
</style>
\ No newline at end of file
......@@ -2,28 +2,17 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="库区编码" prop="areaCode">
<el-input
v-model="queryParams.areaCode"
placeholder="请输入库区编码"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.areaCode" placeholder="请输入库区编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="库区名称" prop="areaName">
<el-input
v-model="queryParams.areaName"
placeholder="请输入库区名称"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.areaName" placeholder="请输入库区名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="所属仓库" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入所属仓库ID"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.warehouseId" placeholder="请选择仓库" readonly clearable style="width: 280px;">
<template #append>
<el-button type="primary" @click="openQueryWarehouseSelect">选择仓库</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
......@@ -33,54 +22,25 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['ware:wmsArea:add']"
>新增</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['ware:wmsArea:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['ware:wmsArea:edit']"
>修改</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['ware:wmsArea:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['ware:wmsArea:remove']"
>删除</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['ware:wmsArea:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['ware:wmsArea:export']"
>导出</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['ware:wmsArea:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="wmsAreaList"
default-expand-all
@selection-change="handleSelectionChange"
row-key="areaId"
:tree-props="{ children: 'children' }"
>
<el-table v-loading="loading" :data="wmsAreaList" default-expand-all @selection-change="handleSelectionChange"
row-key="areaId" :tree-props="{ children: 'children' }">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="库区编码" align="center" prop="areaCode" />
<el-table-column label="库区名称" align="center" prop="areaName" />
......@@ -97,13 +57,16 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['ware:wmsArea:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['ware:wmsArea:remove']">删除</el-button>
<el-button link type="primary" icon="Plus" @click="handleAddSub(scope.row)" v-hasPermi="['ware:wmsArea:add']">添加下级</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['ware:wmsArea:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['ware:wmsArea:remove']">删除</el-button>
<el-button link type="primary" icon="Plus" @click="handleAddSub(scope.row)"
v-hasPermi="['ware:wmsArea:add']">添加下级</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改库区信息对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="wmsAreaRef" :model="form" :rules="rules" label-width="80px">
......@@ -114,23 +77,15 @@
<el-input v-model="form.areaName" placeholder="请输入库区名称" />
</el-form-item>
<el-form-item label="所属仓库" prop="warehouseId">
<el-row :gutter="10">
<el-col :span="18">
<el-input v-model="form.warehouseId" placeholder="请选择仓库" readonly />
</el-col>
<el-col :span="6">
<el-input v-model="form.warehouseId" placeholder="请选择仓库" readonly clearable>
<template #append>
<el-button type="primary" @click="openWarehouseSelect">选择仓库</el-button>
</el-col>
</el-row>
</template>
</el-input>
</el-form-item>
<el-form-item label="父库区" prop="parentId">
<el-cascader
v-model="form.parentId"
:options="wmsAreaOptions"
:props="{ value: 'areaId', label: 'areaName', checkStrictly: true }"
placeholder="请选择父库区"
clearable
/>
<el-cascader v-model="form.parentId" :options="wmsAreaOptions"
:props="{ value: 'areaId', label: 'areaName', checkStrictly: true }" placeholder="请选择父库区" clearable />
</el-form-item>
<el-form-item label="温度范围" prop="temperatureRange">
<el-input v-model="form.temperatureRange" placeholder="请输入温度范围" />
......@@ -154,12 +109,8 @@
</el-dialog>
<!-- 仓库选择对话框组件 -->
<WarehouseSelectDialog
ref="warehouseSelectDialogRef"
v-model:visible="warehouseDialogVisible"
title="选择仓库"
@confirm="handleWarehouseConfirm"
/>
<WarehouseSelectDialog ref="warehouseSelectDialogRef" v-model:visible="warehouseDialogVisible" title="选择仓库"
@confirm="handleWarehouseConfirm" />
</div>
</template>
......@@ -170,7 +121,7 @@ import { handleTree } from "@/utils/ruoyi"
const { proxy } = getCurrentInstance()
const {sys_normal_disable} = proxy.useDict('sys_normal_disable')
const { sys_normal_disable } = proxy.useDict('sys_normal_disable')
const wmsAreaList = ref([])
const open = ref(false)
......@@ -186,6 +137,8 @@ const title = ref("")
const warehouseDialogVisible = ref(false)
// 仓库选择对话框实例引用
const warehouseSelectDialogRef = ref(null)
// 标记当前是否为查询表单的仓库选择
const isQueryWarehouseSelect = ref(false)
// 库区下拉树选项
const wmsAreaOptions = ref([])
......@@ -333,12 +286,12 @@ function submitForm() {
/** 删除按钮操作 */
function handleDelete(row) {
const _areaIds = row.areaId || ids.value
proxy.$modal.confirm('是否确认删除库区信息编号为"' + _areaIds + '"的数据项?').then(function() {
proxy.$modal.confirm('是否确认删除库区信息编号为"' + _areaIds + '"的数据项?').then(function () {
return delWmsArea(_areaIds)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}).catch(() => { })
}
/** 导出按钮操作 */
......@@ -348,8 +301,18 @@ function handleExport() {
}, `wmsArea_${new Date().getTime()}.xlsx`)
}
/** 打开仓库选择对话框 */
/** 打开搜索表单仓库选择对话框 */
function openQueryWarehouseSelect() {
isQueryWarehouseSelect.value = true
warehouseDialogVisible.value = true
if (warehouseSelectDialogRef.value) {
warehouseSelectDialogRef.value.handleQuery()
}
}
/** 打开编辑表单仓库选择对话框 */
function openWarehouseSelect() {
isQueryWarehouseSelect.value = false
warehouseDialogVisible.value = true
if (warehouseSelectDialogRef.value) {
warehouseSelectDialogRef.value.handleQuery()
......@@ -360,7 +323,11 @@ function openWarehouseSelect() {
function handleWarehouseConfirm(selectedWarehouses) {
if (selectedWarehouses.length > 0) {
const warehouse = selectedWarehouses[0]
form.value.warehouseId = warehouse.warehouseId
if (isQueryWarehouseSelect.value) {
queryParams.value.warehouseId = warehouse.warehouseId
} else {
form.value.warehouseId = warehouse.warehouseId
}
// 可以根据需要添加更多仓库信息字段
}
}
......
......@@ -2,100 +2,20 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="入库单号" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入入库单号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库ID" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库ID"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="供应商ID" prop="supplierId">
<el-input
v-model="queryParams.supplierId"
placeholder="请输入供应商ID"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.orderNo" placeholder="请输入入库单号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="关联单号" prop="relatedOrderNo">
<el-input
v-model="queryParams.relatedOrderNo"
placeholder="请输入关联单号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="申请人" prop="applicantId">
<el-input
v-model="queryParams.applicantId"
placeholder="请输入申请人"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="申请时间" prop="applyTime">
<el-date-picker clearable
v-model="queryParams.applyTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择申请时间">
</el-date-picker>
</el-form-item>
<el-form-item label="预计到货日期" prop="expectedArrivalDate">
<el-date-picker clearable
v-model="queryParams.expectedArrivalDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择预计到货日期">
</el-date-picker>
</el-form-item>
<el-form-item label="实际到货日期" prop="actualArrivalDate">
<el-date-picker clearable
v-model="queryParams.actualArrivalDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择实际到货日期">
</el-date-picker>
</el-form-item>
<el-form-item label="质检员" prop="qualityCheckerId">
<el-input
v-model="queryParams.qualityCheckerId"
placeholder="请输入质检员"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.relatedOrderNo" placeholder="请输入关联单号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="质检时间" prop="qualityCheckTime">
<el-date-picker clearable
v-model="queryParams.qualityCheckTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择质检时间">
</el-date-picker>
</el-form-item>
<el-form-item label="上架员" prop="putawayPersonId">
<el-input
v-model="queryParams.putawayPersonId"
placeholder="请输入上架员"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="上架时间" prop="putawayTime">
<el-date-picker clearable
v-model="queryParams.putawayTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择上架时间">
</el-date-picker>
<el-form-item label="仓库" prop="warehouseId">
<el-row :gutter="10">
<el-col :span="18">
<el-input v-model="queryParams.warehouseId" placeholder="请选择仓库" readonly clearable />
</el-col>
<el-col :span="6">
<el-button type="primary" @click="openQueryWarehouseSelect">选择仓库</el-button>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
......@@ -105,42 +25,8 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['ware:wmsInboundOrder:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['ware:wmsInboundOrder:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['ware:wmsInboundOrder:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['ware:wmsInboundOrder:export']"
>导出</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['ware:wmsInboundOrder:add']">新增</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
......@@ -148,34 +34,34 @@
<el-table v-loading="loading" :data="wmsInboundOrderList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="入库单号" align="center" prop="orderNo" width="180" fixed="left" />
<el-table-column label="入库类型" align="center" prop="orderType" >
<el-table-column label="入库类型" align="center" prop="orderType">
<template #default="scope">
<dict-tag :options="inbound_type" :value="scope.row.orderType" />
</template>
</el-table-column>
</el-table-column>
<el-table-column label="仓库ID" align="center" prop="warehouseId" />
<el-table-column label="供应商ID" align="center" prop="supplierId" />
<el-table-column label="关联单号" align="center" prop="relatedOrderNo" />
<el-table-column label="总数量" align="center" prop="totalQuantity" />
<el-table-column label="总金额" align="center" prop="totalAmount" />
<el-table-column label="单据状态" align="center" prop="orderStatus" />
<el-table-column label="申请人" align="center" prop="applicantId" />
<el-table-column label="申请时间" align="center" prop="applyTime" width="180">
<!-- <el-table-column label="单据状态" align="center" prop="orderStatus" /> -->
<el-table-column label="入库人" align="center" prop="applicantId" />
<el-table-column label="入库时间" align="center" prop="applyTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="预计到货日期" align="center" prop="expectedArrivalDate" width="180">
<!-- <el-table-column label="预计到货日期" align="center" prop="expectedArrivalDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.expectedArrivalDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column label="实际到货日期" align="center" prop="actualArrivalDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.actualArrivalDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="质检员" align="center" prop="qualityCheckerId" />
<!-- <el-table-column label="质检员" align="center" prop="qualityCheckerId" />
<el-table-column label="质检时间" align="center" prop="qualityCheckTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.qualityCheckTime, '{y}-{m}-{d}') }}</span>
......@@ -188,35 +74,37 @@
<span>{{ parseTime(scope.row.putawayTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="审批状态" align="center" prop="approvalStatus" />
<el-table-column label="审批状态" align="center" prop="approvalStatus" /> -->
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200" fixed="right">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="400" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['ware:wmsInboundOrder:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['ware:wmsInboundOrder:remove']">删除</el-button>
<el-button link type="primary" icon="Document" @click="handlePrint(scope.row)" v-hasPermi="['ware:wmsInboundOrder:print']">打印</el-button>
<el-button v-if="scope.row.orderStatus === '0'" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['ware:wmsInboundOrder:edit']">修改入库单</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['ware:wmsInboundOrder:remove']">删除</el-button>
<el-button link type="primary" icon="Document" @click="handlePrint(scope.row)"
v-hasPermi="['ware:wmsInboundOrder:print']">打印入库单</el-button>
<el-button link type="primary" icon="Check" @click="handleInventory(scope.row)"
v-hasPermi="['ware:wmsInboundOrder:inventory']">入库</el-button>
<el-button v-if="scope.row.orderStatus !== '0'" link type="primary" icon="SetUp" @click="handleAdjustInventory(scope.row)"
v-hasPermi="['ware:wmsInboundOrder:adjust']">调整入库明细信息</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改入库单主对话框 -->
<el-dialog :title="title" v-model="open" width="1500px" append-to-body>
<el-form ref="wmsInboundOrderRef" :model="form" :rules="rules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="入库单号" prop="orderNo">
<el-input v-model="form.orderNo" placeholder="请输入入库单号" />
<el-input v-model="form.orderNo" placeholder="请输入入库单号" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="仓库" prop="warehouseId">
<el-row :gutter="10">
<el-col :span="18">
......@@ -228,9 +116,7 @@
</el-row>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="供应商" prop="supplierId">
<el-row :gutter="10">
<el-col :span="18">
......@@ -242,64 +128,56 @@
</el-row>
</el-form-item>
</el-col>
<el-col :span="12">
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="关联单号" prop="relatedOrderNo">
<el-input v-model="form.relatedOrderNo" placeholder="请输入关联单号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="总数量" prop="totalQuantity">
<el-input v-model="form.totalQuantity" placeholder="请输入总数量" />
<el-input v-model="form.totalQuantity" placeholder="请输入总数量" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="总金额" prop="totalAmount">
<el-input v-model="form.totalAmount" placeholder="请输入总金额" />
<el-input v-model="form.totalAmount" placeholder="请输入总金额" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="申请人" prop="applicantId">
<el-input v-model="form.applicantId" placeholder="请输入申请人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="申请时间" prop="applyTime">
<el-date-picker clearable
v-model="form.applyTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择申请时间">
</el-date-picker>
<el-col :span="8">
<el-form-item label="入库人" prop="applicantId">
<el-input v-model="form.applicantId" placeholder="请输入申请人" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="预计到货日期" prop="expectedArrivalDate">
<el-date-picker clearable
v-model="form.expectedArrivalDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择预计到货日期">
<el-col :span="8">
<el-form-item label="入库时间" prop="applyTime">
<el-date-picker clearable v-model="form.applyTime" type="date" value-format="YYYY-MM-DD"
placeholder="请选择申请时间" disabled >
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="实际到货日期" prop="actualArrivalDate">
<el-date-picker clearable
v-model="form.actualArrivalDate"
type="date"
value-format="YYYY-MM-DD"
<el-date-picker clearable v-model="form.actualArrivalDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择实际到货日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="预计到货日期" prop="expectedArrivalDate">
<el-date-picker clearable v-model="form.expectedArrivalDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择预计到货日期">
</el-date-picker>
</el-form-item>
</el-col> -->
</el-row>
<!-- <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="质检员" prop="qualityCheckerId">
<el-input v-model="form.qualityCheckerId" placeholder="请输入质检员" />
......@@ -307,16 +185,13 @@
</el-col>
<el-col :span="12">
<el-form-item label="质检时间" prop="qualityCheckTime">
<el-date-picker clearable
v-model="form.qualityCheckTime"
type="date"
value-format="YYYY-MM-DD"
<el-date-picker clearable v-model="form.qualityCheckTime" type="date" value-format="YYYY-MM-DD"
placeholder="请选择质检时间">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
</el-row> -->
<!-- <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="上架员" prop="putawayPersonId">
<el-input v-model="form.putawayPersonId" placeholder="请输入上架员" />
......@@ -324,89 +199,108 @@
</el-col>
<el-col :span="12">
<el-form-item label="上架时间" prop="putawayTime">
<el-date-picker clearable
v-model="form.putawayTime"
type="date"
value-format="YYYY-MM-DD"
<el-date-picker clearable v-model="form.putawayTime" type="date" value-format="YYYY-MM-DD"
placeholder="请选择上架时间">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-row> -->
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
<!-- 入库单明细 -->
<el-divider>入库单明细</el-divider>
<el-row :gutter="20" style="margin-bottom: 10px;">
<el-col :span="24" style="text-align: right;">
<el-button type="primary" size="small" icon="Plus" @click="addDetail">添加明细</el-button>
<el-button v-if="title !== '修改入库单'" type="primary" size="small" icon="Plus" @click="addDetail">添加明细</el-button>
</el-col>
</el-row>
<el-table :data="form.details" border style="width: 100%">
<el-table :data="form.items" border style="width: 100%">
<el-table-column prop="materialName" label="物资名称" width="150">
<template #default="scope">
<el-input v-model="scope.row.materialName" placeholder="请输入物资名称" size="small" />
<el-input v-model="scope.row.materialName" placeholder="请输入物资名称" size="small" disabled />
</template>
</el-table-column>
<el-table-column prop="planQuantity" label="计划数量" width="100">
<template #default="scope">
<el-input v-model.number="scope.row.planQuantity" placeholder="请输入计划数量" size="small" />
<el-input
v-model.number="scope.row.planQuantity"
placeholder="请输入计划数量"
size="small"
type="number"
:precision="3"
:step="0.001"
/>
</template>
</el-table-column>
<el-table-column prop="actualQuantity" label="实际数量" width="100">
<template #default="scope">
<el-input v-model.number="scope.row.actualQuantity" placeholder="请输入实际数量" size="small" />
<el-input
v-model.number="scope.row.actualQuantity"
placeholder="请输入实际数量"
size="small"
@change="calculateAmount(scope.row)"
type="number"
:precision="3"
:step="0.001"
/>
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" width="80">
<template #default="scope">
<el-input v-model="scope.row.unit" placeholder="请输入单位" size="small" />
<el-input v-model="scope.row.unit" placeholder="请输入单位" size="small" disabled />
</template>
</el-table-column>
<el-table-column prop="unitPrice" label="单价" width="100">
<template #default="scope">
<el-input v-model.number="scope.row.unitPrice" placeholder="请输入单价" size="small" />
<el-input
v-model.number="scope.row.unitPrice"
placeholder="请输入单价"
size="small"
@change="calculateAmount(scope.row)"
type="number"
:precision="2"
:step="0.01"
/>
</template>
</el-table-column>
<el-table-column prop="amount" label="金额" width="100">
<template #default="scope">
<el-input v-model.number="scope.row.amount" placeholder="请输入金额" size="small" />
<el-input
v-model.number="scope.row.amount"
placeholder="请输入金额"
size="small"
disabled
type="number"
:precision="2"
/>
</template>
</el-table-column>
<el-table-column prop="batchNo" label="批次号" width="120">
<el-table-column prop="batchNo" label="批次号" width="180">
<template #default="scope">
<el-input v-model="scope.row.batchNo" placeholder="请输入批次号" size="small" />
</template>
</el-table-column>
<el-table-column prop="productionDate" label="生产日期" width="150">
<el-table-column prop="productionDate" label="生产日期" width="180">
<template #default="scope">
<el-date-picker clearable
v-model="scope.row.productionDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择生产日期"
size="small">
<el-date-picker clearable v-model="scope.row.productionDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择生产日期" size="small" format="YYYY-MM-DD" class="!w-full">
</el-date-picker>
</template>
</el-table-column>
<el-table-column prop="expirationDate" label="失效日期" width="150">
<el-table-column prop="expirationDate" label="失效日期" width="180">
<template #default="scope">
<el-date-picker clearable
v-model="scope.row.expirationDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择失效日期"
size="small">
<el-date-picker clearable v-model="scope.row.expirationDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择失效日期" size="small" format="YYYY-MM-DD" class="!w-full">
</el-date-picker>
</template>
</el-table-column>
<el-table-column prop="qualityStatus" label="质检状态" width="100">
<!-- <el-table-column prop="qualityStatus" label="质检状态" width="100">
<template #default="scope">
<el-input v-model="scope.row.qualityStatus" placeholder="请输入质检状态" size="small" />
</template>
......@@ -415,8 +309,8 @@
<template #default="scope">
<el-input v-model.number="scope.row.checkQuantity" placeholder="请输入质检数量" size="small" />
</template>
</el-table-column>
<el-table-column prop="unqualifiedQuantity" label="不合格数量" width="120">
</el-table-column> -->
<!-- <el-table-column prop="unqualifiedQuantity" label="不合格数量" width="120">
<template #default="scope">
<el-input v-model.number="scope.row.unqualifiedQuantity" placeholder="请输入不合格数量" size="small" />
</template>
......@@ -425,25 +319,31 @@
<template #default="scope">
<el-input v-model="scope.row.unqualifiedReason" placeholder="请输入不合格原因" size="small" />
</template>
</el-table-column>
<el-table-column prop="storageLocation" label="存储货架" width="120">
<template #default="scope">
<el-input v-model="scope.row.storageLocation" placeholder="请输入存储货架" size="small" />
</template>
</el-table-column>
<el-table-column prop="putawayStatus" label="上架状态" width="100">
</el-table-column> -->
<el-table-column prop="locationId" label="货架" width="300">
<template #default="scope">
<el-input v-model="scope.row.putawayStatus" placeholder="请输入上架状态" size="small" />
<LocationCascaderSelect
:model-value="{warehouseId: form.warehouseId, areaId: scope.row.areaId, locationId: scope.row.locationId}"
@update:model-value="(value) => {
scope.row.warehouseId = value.warehouseId;
scope.row.areaId = value.areaId;
scope.row.locationId = value.locationId;
}"
/>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" width="150">
<template #default="scope">
<el-input type="textarea" v-model="scope.row.remark" placeholder="请输入备注" size="small" />
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center" fixed="right">
<el-table-column label="操作" width="80" align="center" fixed="right">
<template #default="scope">
<el-button type="danger" size="small" icon="Delete" @click="deleteDetail(scope.$index)">删除</el-button>
<el-button type="danger" size="small" icon="Delete" @click="deleteDetail(scope.$index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
......@@ -457,41 +357,219 @@
</el-dialog>
<!-- 物资选择对话框组件 -->
<MaterialSelectDialog
ref="materialSelectDialogRef"
v-model:visible="materialDialogVisible"
title="选择物资"
@confirm="handleMaterialConfirm"
/>
<MaterialSelectDialog ref="materialSelectDialogRef" v-model:visible="materialDialogVisible" title="选择物资"
@confirm="handleMaterialConfirm" />
<!-- 仓库选择对话框组件 -->
<WarehouseSelectDialog
ref="warehouseSelectDialogRef"
v-model:visible="warehouseDialogVisible"
title="选择仓库"
@confirm="handleWarehouseConfirm"
/>
<WarehouseSelectDialog ref="warehouseSelectDialogRef" v-model:visible="warehouseDialogVisible" title="选择仓库"
@confirm="handleWarehouseConfirm" />
<!-- 供应商选择对话框组件 -->
<SupplierSelectDialog
ref="supplierSelectDialogRef"
v-model:visible="supplierDialogVisible"
title="选择供应商"
@confirm="handleSupplierConfirm"
<SupplierSelectDialog ref="supplierSelectDialogRef" v-model:visible="supplierDialogVisible" title="选择供应商"
@confirm="handleSupplierConfirm" />
<!-- RFID标签选择对话框组件 -->
<RfidTagSelectDialog ref="rfidTagSelectDialogRef" v-model:visible="rfidTagDialogVisible" title="选择RFID标签"
@confirm="handleRfidTagConfirm" />
<!-- PTL标签选择对话框组件 -->
<PtlTagSelectDialog ref="ptlTagSelectDialogRef" v-model:visible="ptlTagDialogVisible" title="选择PTL标签"
@confirm="handlePtlTagConfirm" />
<!-- 二维码打印对话框组件 -->
<QrcodePrintDialog
ref="qrcodePrintDialogRef"
v-model:visible="qrcodePrintDialogVisible"
:qrcode-value="currentQrcodeValue"
@print="handleQrcodePrint"
/>
<!-- 入库对话框 -->
<el-dialog
title="入库操作"
v-model="inventoryDialogVisible"
width="1200px"
append-to-body
>
<el-form :model="inventoryQueryParams" ref="inventoryQueryRef" :inline="true" label-width="120px">
<el-form-item label="批次号" prop="batchNo">
<el-input
v-model="inventoryQueryParams.batchNo"
placeholder="请输入或扫描批次号"
clearable
@keyup.enter="handleInventoryQuery"
@input="handleBatchNoInput"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleInventoryQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetInventoryQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="inventoryDetailList" border style="width: 100%; margin-top: 20px;" height="600px">
<!-- <el-table-column prop="materialCode" label="物资编码" width="150" /> -->
<el-table-column prop="wmsMaterial.materialName" label="物资名称" width="200" />
<el-table-column prop="batchNo" label="批次号" width="150" />
<el-table-column prop="actualQuantity" label="数量" width="100" />
<el-table-column prop="unitPrice" label="单价" width="100" />
<el-table-column label="金额" width="100">
<template #default="scope">
<span>{{ scope.row.amount }}</span>
</template>
</el-table-column>
<el-table-column prop="wmsWarehouse.warehouseName" label="仓库" width="100" />
<el-table-column prop="wmsArea.areaName" label="库区" width="100" />
<el-table-column prop="wmsLocation.locationName" label="货架" width="100" />
<el-table-column prop="storageLocation" label="PTL标签" width="180">
<template #default="scope">
<el-input v-model="scope.row.storageLocation" placeholder="请选择PTL标签" size="small" readonly />
<el-button slot="append" type="primary" size="small" @click="openPtlTagSelect(scope.$index)">选择</el-button>
</template>
</el-table-column>
<el-table-column prop="rfidTagIds" label="RFID标签" width="180">
<template #default="scope">
<el-input v-model="scope.row.rfidTagIds" placeholder="请选择RFID标签" size="small" readonly />
<el-button slot="append" type="primary" size="small" @click="openRfidTagSelect(scope.$index)">选择</el-button>
</template>
</el-table-column>
<el-table-column prop="wmsInboundOrderItemId" label="操作" width="100" fixed="right">
<template #default="scope">
<el-button type="primary" size="small" @click="handleExportQrcode(scope.row)">打印二维码</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="inventoryDialogVisible = false"> </el-button>
<el-button type="primary" @click="confirmInventory">确认入库</el-button>
</div>
</template>
</el-dialog>
<!-- 入库明细调整对话框 -->
<el-dialog
title="调整入库明细信息"
v-model="adjustInventoryDialogVisible"
width="1200px"
append-to-body
>
<el-table :data="adjustInventoryDetailList" border style="width: 100%" height="600px">
<el-table-column prop="wmsMaterial.materialName" label="物资名称" width="200" />
<el-table-column prop="batchNo" label="批次号" width="150" />
<el-table-column prop="actualQuantity" label="数量" width="120">
<template #default="scope">
<el-input
v-if="scope.row.isEditing"
v-model.number="scope.row.actualQuantity"
placeholder="请输入实际数量"
size="small"
type="number"
:precision="3"
:step="0.001"
@input="() => {
scope.row.amount = scope.row.actualQuantity && scope.row.unitPrice ? (scope.row.actualQuantity * scope.row.unitPrice).toFixed(2) : '0.00'
}"
/>
<span v-else>{{ scope.row.actualQuantity }}</span>
</template>
</el-table-column>
<el-table-column prop="unitPrice" label="单价" width="100">
<template #default="scope">
<el-input
v-if="scope.row.isEditing"
v-model.number="scope.row.unitPrice"
placeholder="请输入单价"
size="small"
type="number"
:precision="2"
:step="0.01"
@input="() => {
scope.row.amount = scope.row.actualQuantity && scope.row.unitPrice ? (scope.row.actualQuantity * scope.row.unitPrice).toFixed(2) : '0.00'
}"
/>
<span v-else>{{ scope.row.unitPrice }}</span>
</template>
</el-table-column>
<el-table-column label="金额" width="100">
<template #default="scope">
<span>{{ scope.row.amount }}</span>
</template>
</el-table-column>
<el-table-column prop="locationId" label="货架" width="300">
<template #default="scope">
<LocationCascaderSelect
v-if="scope.row.isEditing"
:model-value="{warehouseId: currentAdjustOrder.warehouseId, areaId: scope.row.areaId, locationId: scope.row.locationId}"
@update:model-value="(value) => {
scope.row.warehouseId = value.warehouseId;
scope.row.areaId = value.areaId;
scope.row.locationId = value.locationId;
}"
/>
<span v-else>{{ scope.row.wmsLocation?.locationName }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="180" align="center">
<template #default="scope">
<el-button
v-if="!scope.row.isEditing"
type="primary"
size="small"
icon="Edit"
@click="handleEditDetail(scope.row)"
>
编辑
</el-button>
<el-button
v-else
type="success"
size="small"
icon="Check"
@click="handleSaveDetail(scope.row)"
>
保存
</el-button>
<el-button
type="danger"
size="small"
icon="Delete"
@click="handleDelDetail(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="adjustInventoryDialogVisible = false"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="WmsInboundOrder">
import { listWmsInboundOrder, getWmsInboundOrder, delWmsInboundOrder, addWmsInboundOrder, updateWmsInboundOrder } from "@/api/ware/wmsInboundOrder"
import { listWmsInboundOrder, getWmsInboundOrder, delWmsInboundOrder, addWmsInboundOrder, updateWmsInboundOrder, delWmsInboundOrderItem, updateWmsInboundOrderItem, saveWmsInboundOrder, addToInventory } from "@/api/ware/wmsInboundOrder"
import { generateBatchNo, generateInboundOrderNo } from "@/api/ware/codeGenerator"
import MaterialSelectDialog from "@/components/MaterialSelectDialog.vue"
import WarehouseSelectDialog from "@/components/WarehouseSelectDialog.vue"
import SupplierSelectDialog from "@/components/SupplierSelectDialog.vue"
import LocationCascaderSelect from "@/components/LocationCascaderSelect.vue"
import RfidTagSelectDialog from "@/components/RfidTagSelectDialog.vue"
import PtlTagSelectDialog from "@/components/PtlTagSelectDialog.vue"
import QrcodePrintDialog from "@/components/QrcodePrintDialog.vue"
import { listWmsMaterial } from "@/api/ware/wmsMaterial"
import useUserStore from '@/store/modules/user'
import { listWmsInboundOrderItem } from "@/api/ware/wmsInboundOrderItem"
const { proxy } = getCurrentInstance()
const {inbound_type} = proxy.useDict('inbound_type')
const { inbound_type } = proxy.useDict('inbound_type')
const wmsInboundOrderList = ref([])
const open = ref(false)
......@@ -518,6 +596,48 @@ const supplierDialogVisible = ref(false)
// 供应商选择对话框实例引用
const supplierSelectDialogRef = ref(null)
// RFID标签选择对话框状态
const rfidTagDialogVisible = ref(false)
// RFID标签选择对话框实例引用
const rfidTagSelectDialogRef = ref(null)
// PTL标签选择对话框状态
const ptlTagDialogVisible = ref(false)
// PTL标签选择对话框实例引用
const ptlTagSelectDialogRef = ref(null)
// 二维码打印对话框状态
const qrcodePrintDialogVisible = ref(false)
// 二维码打印对话框实例引用
const qrcodePrintDialogRef = ref(null)
const inventoryQueryRef = ref(null)
// 入库对话框状态
const inventoryDialogVisible = ref(false)
// 当前入库的入库单
const currentInventoryOrder = ref(null)
// 入库查询参数
const inventoryQueryParams = ref({
batchNo: null
})
// 入库明细列表
const inventoryDetailList = ref([])
// 入库明细调整对话框状态
const adjustInventoryDialogVisible = ref(false)
// 当前调整的入库单
const currentAdjustOrder = ref(null)
// 入库明细调整列表
const adjustInventoryDetailList = ref([])
// 记录当前编辑的明细行索引
const currentEditingRowIndex = ref(-1)
// 当前选中的入库单
const currentRow = ref(null)
// 当前要打印的二维码值
const currentQrcodeValue = ref('')
const data = reactive({
......@@ -559,6 +679,157 @@ const data = reactive({
const { queryParams, form, rules } = toRefs(data)
// 入库相关方法
// 打开入库对话框
function handleInventory(row) {
currentInventoryOrder.value = row
inventoryDetailList.value = []
resetInventoryQuery()
inventoryDialogVisible.value = true
}
// 处理批次号输入(支持扫描枪)
function handleBatchNoInput() {
// 扫描枪通常会自动添加换行符,这里可以根据实际情况调整
if (inventoryQueryParams.value.batchNo && inventoryQueryParams.value.batchNo.endsWith('\n')) {
inventoryQueryParams.value.batchNo = inventoryQueryParams.value.batchNo.trim()
handleInventoryQuery()
}
}
// 入库明细查询
function handleInventoryQuery() {
if (!inventoryQueryParams.value.batchNo) {
proxy.$message.warning('请输入批次号')
return
}
listWmsInboundOrderItem({ batchNo: inventoryQueryParams.value.batchNo }).then(response => {
if(response.rows.length){
const currentOrder = response.rows[0];
if(currentOrder.putawayStatus === '1'){
proxy.$message.warning('该批次号已上架,不能重复上架')
}else{
inventoryDetailList.value = [currentOrder];
}
}else{
proxy.$message.warning('未查询到相关入库明细')
}
}).catch(error => {
proxy.$message.error('查询入库明细失败:' + error.message)
})
}
// 重置入库查询
function resetInventoryQuery() {
inventoryQueryParams.value = {
batchNo: null
}
}
// 确认入库
function confirmInventory() {
if (inventoryDetailList.value.length === 0) {
proxy.$message.warning('请先添加入库明细')
return
}
proxy.$messageBox.confirm('确定要执行入库操作吗?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
currentInventoryOrder.value.items = inventoryDetailList.value;
// 调用入库API
addToInventory(currentInventoryOrder.value).then(response => {
proxy.$message.success('入库成功')
inventoryDialogVisible.value = false
getList() // 刷新列表
}).catch(error => {
proxy.$message.error('入库失败:' + error.message)
})
}).catch(() => {
// 取消操作
})
}
// 调整已入库信息相关方法
// 打开调整入库信息对话框
function handleAdjustInventory(row) {
currentAdjustOrder.value = row
// 深拷贝明细列表,避免直接修改原数据
listWmsInboundOrderItem({ orderId: row.orderId, pageSize: 1000, pageNum: 1 }).then(response => {
adjustInventoryDetailList.value = response.rows.map(item => ({
...item,
isEditing: false // 添加编辑状态标志
}))
adjustInventoryDialogVisible.value = true
}).catch(error => {
proxy.$message.error('查询入库明细失败:' + error.message)
})
}
// 编辑明细
function handleEditDetail(row) {
// 保存原始值,以便取消编辑时恢复
row.originalData = JSON.parse(JSON.stringify(row))
row.isEditing = true
}
// 保存明细
function handleSaveDetail(row) {
// 计算金额
if (row.actualQuantity && row.unitPrice) {
row.amount = (row.actualQuantity * row.unitPrice).toFixed(2)
} else {
row.amount = '0.00'
}
// 调用更新接口
updateWmsInboundOrderItem(row).then(response => {
proxy.$message.success('保存成功')
row.isEditing = false
}).catch(error => {
proxy.$message.error('保存失败:' + error.message)
// 恢复原始值
if (row.originalData) {
Object.assign(row, row.originalData)
delete row.originalData
}
})
}
// 删除明细
function handleDelDetail(row) {
proxy.$messageBox.confirm('确定要删除这条明细吗?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 调用删除接口
delWmsInboundOrderItem(row.itemId).then(response => {
proxy.$message.success('删除成功')
// 从列表中移除
const index = adjustInventoryDetailList.value.findIndex(item => item.itemId === row.itemId)
if (index !== -1) {
adjustInventoryDetailList.value.splice(index, 1)
}
// 从原入库单中移除
const originalIndex = currentAdjustOrder.value.items.findIndex(item => item.itemId === row.itemId)
if (originalIndex !== -1) {
currentAdjustOrder.value.items.splice(originalIndex, 1)
}
}).catch(error => {
proxy.$message.error('删除失败:' + error.message)
})
}).catch(() => {
// 取消操作
})
}
/** 查询入库单主列表 */
function getList() {
loading.value = true
......@@ -580,13 +851,13 @@ function reset() {
form.value = {
orderId: null,
orderNo: null,
orderType: '0',
orderType: '0', // 默认采购入库
warehouseId: null,
supplierId: null,
relatedOrderNo: null,
totalQuantity: null,
totalAmount: null,
orderStatus: null,
orderStatus: '0', // 默认未上架 1 部分上架 2 全部上架
applicantId: null,
applyTime: null,
expectedArrivalDate: null,
......@@ -602,7 +873,7 @@ function reset() {
createTime: null,
updateBy: null,
updateTime: null,
details: []
items: []
}
proxy.resetForm("wmsInboundOrderRef")
}
......@@ -631,9 +902,24 @@ function handleAdd() {
reset()
open.value = true
title.value = "添加入库单主"
// 获取当前用户信息
const userStore = useUserStore()
// 设置申请人为当前用户
form.value.applicantId = userStore.id
// 设置申请时间为当前时间
form.value.applyTime = new Date().toISOString().split('T')[0]
// 调用接口生成入库单号
generateInboundOrderNo().then(response => {
form.value.orderNo = response.msg;
}).catch(error => {
console.error('生成入库单号失败:', error)
proxy.$modal.msgError('生成入库单号失败,请重试')
})
}
/** 打开仓库选择对话框 */
/** 打开仓库选择对话框(用于表单) */
function openWarehouseSelect() {
warehouseDialogVisible.value = true
if (warehouseSelectDialogRef.value) {
......@@ -641,11 +927,22 @@ function openWarehouseSelect() {
}
}
/** 打开仓库选择对话框(用于搜索) */
/** 打开搜索仓库选择对话框 */
function openQueryWarehouseSelect() {
warehouseDialogVisible.value = true
if (warehouseSelectDialogRef.value) {
warehouseSelectDialogRef.value.handleQuery()
}
}
/** 处理仓库选择结果 */
function handleWarehouseConfirm(selectedWarehouses) {
if (selectedWarehouses.length > 0) {
const warehouse = selectedWarehouses[0]
// 同时更新表单和搜索参数
form.value.warehouseId = warehouse.warehouseId
queryParams.value.warehouseId = warehouse.warehouseId
// 可以根据需要添加更多仓库信息字段
}
}
......@@ -674,7 +971,7 @@ function handleUpdate(row) {
getWmsInboundOrder(_orderId).then(response => {
form.value = response.data
open.value = true
title.value = "修改入库单"
title.value = "修改入库单"
})
}
......@@ -684,14 +981,14 @@ function submitForm() {
proxy.$refs["wmsInboundOrderRef"].validate(valid => {
if (valid) {
// 验证入库单明细
if (!form.value.details || form.value.details.length === 0) {
if (!form.value.items || form.value.items.length === 0) {
proxy.$modal.msgError("请至少添加一条入库单明细")
return
}
// 验证每条明细的必填字段
for (let i = 0; i < form.value.details.length; i++) {
const detail = form.value.details[i]
for (let i = 0; i < form.value.items.length; i++) {
const detail = form.value.items[i]
if (!detail.materialId) {
proxy.$modal.msgError(`第${i + 1}条明细的物资ID不能为空`)
return
......@@ -706,29 +1003,21 @@ function submitForm() {
return
}
}
// 提交数据
if (form.value.orderId != null) {
updateWmsInboundOrder(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addWmsInboundOrder(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
// 提交数据,统一调用saveWmsInboundOrder接口
saveWmsInboundOrder(form.value).then(response => {
proxy.$modal.msgSuccess(title.value === '新增入库单' ? "新增成功" : "修改成功")
open.value = false
getList()
})
}
})
}
/** 添加明细 */
function addDetail() {
if (!form.value.details) {
form.value.details = []
if (!form.value.items) {
form.value.items = []
}
// 打开物资选择对话框
materialDialogVisible.value = true
......@@ -737,16 +1026,48 @@ function addDetail() {
materialSelectDialogRef.value.handleQuery()
}
/** 打开PTL标签选择对话框 */
function openPtlTagSelect(rowIndex) {
currentEditingRowIndex.value = rowIndex
ptlTagDialogVisible.value = true
}
/** 处理PTL标签选择确认 */
function handlePtlTagConfirm(selectedPtlTags) {
if (selectedPtlTags.length > 0) {
const ptlTag = selectedPtlTags[0]
// 使用天线编码作为PTL标签值
// form.value.items[currentEditingRowIndex.value].storageLocation = ptlTag.antennaCode
inventoryDetailList.value[currentEditingRowIndex.value].storageLocation = ptlTag.antennaCode
}
}
/** 打开RFID标签选择对话框 */
function openRfidTagSelect(rowIndex) {
currentEditingRowIndex.value = rowIndex
rfidTagDialogVisible.value = true
}
/** 处理RFID标签选择确认 */
function handleRfidTagConfirm(selectedRfidTags) {
if (selectedRfidTags.length > 0) {
const rfidTag = selectedRfidTags[0]
// 使用标签编码作为RFID标签值
// form.value.items[currentEditingRowIndex.value].rfidTagIds = rfidTag.tagCode
inventoryDetailList.value[currentEditingRowIndex.value].rfidTagIds = rfidTag.tagCode
}
}
/** 处理物资选择确认 */
function handleMaterialConfirm(selectedMaterials) {
if (selectedMaterials.length === 0) {
proxy.$modal.msgWarning("请至少选择一个物资")
return
}
// 将选中的物资添加到明细列表
selectedMaterials.forEach(material => {
form.value.details.push({
const newItem = {
materialId: material.materialId,
materialName: material.materialName,
planQuantity: null,
......@@ -762,26 +1083,86 @@ function handleMaterialConfirm(selectedMaterials) {
unqualifiedQuantity: null,
unqualifiedReason: null,
storageLocation: null,
putawayStatus: null,
warehouseId: null, // 仓库ID
areaId: null, // 库区ID
locationId: null, // 货架ID
putawayStatus: '0', // 默认待上架
remark: null
}
// 调用接口生成批次号
generateBatchNo().then(response => {
newItem.batchNo = response.msg;
form.value.items.push(newItem)
}).catch(error => {
console.error('生成批次号失败:', error)
})
})
}
/** 计算明细金额 */
function calculateAmount(row) {
// 实际数量 * 单价 = 金额
if (row.actualQuantity && row.unitPrice) {
// 计算金额并保留2位小数
row.amount = Number((row.actualQuantity * row.unitPrice).toFixed(2))
} else {
row.amount = null
}
// 更新主表总数量和总金额
updateTotal()
}
/** 更新主表总数量和总金额 */
function updateTotal() {
if (!form.value.items || form.value.items.length === 0) {
form.value.totalQuantity = 0
form.value.totalAmount = 0
return
}
// 计算总数量(实际数量之和)
const totalQuantity = form.value.items.reduce((sum, item) => {
return sum + (item.actualQuantity || 0)
}, 0)
// 计算总金额(金额之和)
const totalAmount = form.value.items.reduce((sum, item) => {
return sum + (item.amount || 0)
}, 0)
form.value.totalQuantity = totalQuantity
form.value.totalAmount = totalAmount
}
/** 删除明细 */
function deleteDetail(index) {
form.value.details.splice(index, 1)
const item = form.value.items[index]
if (item.itemId) {
// 已有ID的明细,标记为删除
item.delFlag = 1
// 从显示列表中移除
form.value.items.splice(index, 1)
} else {
// 新增的明细,直接删除
form.value.items.splice(index, 1)
}
// 更新主表总数量和总金额
updateTotal()
}
// 移除了编辑和保存明细的功能
// 所有修改直接在表单中进行,统一通过saveWmsInboundOrder保存
/** 删除按钮操作 */
function handleDelete(row) {
const _orderIds = row.orderId || ids.value
proxy.$modal.confirm('是否确认删除入库单主编号为"' + _orderIds + '"的数据项?').then(function() {
proxy.$modal.confirm('是否确认删除?').then(function () {
return delWmsInboundOrder(_orderIds)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}).catch(() => { })
}
/** 导出按钮操作 */
......@@ -798,7 +1179,7 @@ function handlePrint(row) {
const orderData = response.data
// 创建打印窗口
const printWindow = window.open('', '_blank')
// 构建打印内容
let printContent = `
<!DOCTYPE html>
......@@ -911,10 +1292,10 @@ function handlePrint(row) {
</thead>
<tbody>
`
// 添加明细数据
if (orderData.details && orderData.details.length > 0) {
orderData.details.forEach(detail => {
if (orderData.items && orderData.items.length > 0) {
orderData.items.forEach(detail => {
printContent += `
<tr>
<td>${detail.materialName}</td>
......@@ -937,7 +1318,7 @@ function handlePrint(row) {
</tr>
`
}
// 完成打印内容
printContent += `
</tbody>
......@@ -950,18 +1331,102 @@ function handlePrint(row) {
</body>
</html>
`
// 写入打印窗口
printWindow.document.write(printContent)
printWindow.document.close()
// 执行打印
printWindow.print()
// 关闭打印窗口
printWindow.close()
})
}
function CreatePrintPage() {
LODOP = getLodop(document.getElementById('LODOP1'), document.getElementById('LODOP_EM1'));
LODOP.PRINT_INITA(0, 0, 800, 1600, "打印控件功能演示_Lodop功能_打印条码");
LODOP.ADD_PRINT_BARCODE(28, 34, 307, 47, "128A", "123456789012");
LODOP.ADD_PRINT_BARCODE(88, 32, 206, 78, "128B", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "FontSize", 18);
LODOP.ADD_PRINT_BARCODE(107, 255, 161, 64, "128C", "888888");
LODOP.SET_PRINT_STYLEA(0, "Color", "#FF0000");
LODOP.ADD_PRINT_BARCODE(179, 42, 130, 47, "128Auto", "12345678901");
LODOP.ADD_PRINT_BARCODE(252, 42, 153, 54, "EAN8", "12345678");
LODOP.SET_PRINT_STYLEA(0, "Angle", 180);
LODOP.ADD_PRINT_BARCODE(173, 244, 235, 172, "EAN13", "1234567890123");
LODOP.SET_PRINT_STYLEA(0, "Angle", 35);
LODOP.ADD_PRINT_BARCODE(351, 34, 360, 36, "EAN128A", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "ShowBarText", 0);
LODOP.ADD_PRINT_BARCODE(403, 34, 360, 47, "EAN128B", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "AlignJustify", 2);
LODOP.ADD_PRINT_BARCODE(462, 34, 360, 47, "EAN128C", "123456789012");
LODOP.ADD_PRINT_BARCODE(513, 34, 360, 47, "Code39", "*123ABC4567890*");
LODOP.SET_PRINT_STYLEA(0, "Color", "#0000FF");
LODOP.ADD_PRINT_BARCODE(570, 34, 360, 47, "39Extended", "*1234567890*");
LODOP.ADD_PRINT_BARCODE(621, 34, 360, 47, "2_5interleaved", "123456789012");
LODOP.ADD_PRINT_BARCODE(677, 34, 360, 47, "2_5industrial", "123456789012");
LODOP.ADD_PRINT_BARCODE(729, 34, 360, 47, "2_5matrix", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Color", "#408080");
LODOP.ADD_PRINT_BARCODE(787, 34, 360, 47, "UPC_A", "089600124569");
LODOP.ADD_PRINT_BARCODE(844, 34, 135, 64, "UPC_E0", "08960007");
LODOP.ADD_PRINT_BARCODE(65, 595, 45, 95, "UPC_E1", "1122333");
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(87, 676, 57, 122, "UPCsupp2", "12345");
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(359, 435, 78, 181, "UPCsupp5", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(309, 579, 44, 238, "Code93", "BJ100080");
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(241, 663, 73, 246, "93Extended", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Angle", -90);
LODOP.ADD_PRINT_BARCODE(583, 419, 58, 251, "MSI", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Color", "#FF00FF");
LODOP.SET_PRINT_STYLEA(0, "ShowBarText", 0);
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(589, 504, 74, 270, "PostNet", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Angle", 90);
LODOP.ADD_PRINT_BARCODE(565, 626, 115, 253, "Codabar", "123456789012");
LODOP.SET_PRINT_STYLEA(0, "Angle", 285);
LODOP.ADD_PRINT_BARCODE(30, 405, 176, 67, "PDF417", "我是pdf417value");
LODOP.ADD_PRINT_BARCODE(130, 434, 168, 146, "QRCode", "1234567890版本7的最大值是122个字符123123");
LODOP.SET_PRINT_STYLEA(0, "GroundColor", "#0080FF");
};
function handleExportQrcode(row) {
currentRow.value = row
// 这里假设二维码内容是入库单号,实际项目中可以根据需求调整
currentQrcodeValue.value = row.orderNo
qrcodePrintDialogVisible.value = true
}
/** 处理二维码打印 */
function handleQrcodePrint(params) {
const { width, height, qrcodeValue } = params
// 使用LODOP打印二维码
const LODOP = getLodop(document.getElementById('LODOP1'), document.getElementById('LODOP_EM1'))
// 设置打印纸张大小(自定义纸张)
// LODOP.PRINT_INITA(0, 0, width * 3.7795275591, height * 3.7795275591, '打印二维码')
// 或者设置为标签打印模式
LODOP.PRINT_INIT('打印二维码')
LODOP.SET_PRINT_PAGESIZE(1, width * 10, height * 10, '自定义二维码标签')
// 添加二维码
// 参数:top, left, width, height, type, value
// 注意:这里的单位是缇(1mm = 10缇)
LODOP.ADD_PRINT_BARCODE(10, 10, width * 10 - 20, height * 10 - 20, 'QRCode', qrcodeValue)
// 设置二维码样式
LODOP.SET_PRINT_STYLEA(0, 'GroundColor', '#FFFFFF')
// 执行打印
LODOP.PRINT_DESIGN() // 打印设计模式,方便调整
// LODOP.PRINT() // 直接打印
}
getList()
</script>
</script>
\ No newline at end of file
......@@ -33,14 +33,6 @@
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="批号" prop="lotNo">
<el-input
v-model="queryParams.lotNo"
placeholder="请输入批号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="生产日期" prop="productionDate">
<el-date-picker clearable
v-model="queryParams.productionDate"
......@@ -82,20 +74,11 @@
/>
</el-form-item>
<el-form-item label="是否FIFO管理" prop="isFifo">
<el-input
v-model="queryParams.isFifo"
placeholder="请输入是否FIFO管理"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="最后RFID检测时间" prop="lastRfidDetectTime">
<el-date-picker clearable
v-model="queryParams.lastRfidDetectTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择最后RFID检测时间">
</el-date-picker>
<el-radio-group v-model="queryParams.isFifo">
<el-radio v-for="item in sys_yes_no" :label="item.value" :key="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
......@@ -159,10 +142,7 @@
<el-table-column label="物资ID" align="center" prop="materialId" />
<el-table-column label="仓库ID" align="center" prop="warehouseId" />
<el-table-column label="货架ID" align="center" prop="locationId" />
<el-table-column label="货架编码" align="center" prop="locationCode" />
<el-table-column label="货架名称" align="center" prop="locationName" />
<el-table-column label="批次号" align="center" prop="batchNo" />
<el-table-column label="批号" align="center" prop="lotNo" />
<el-table-column label="生产日期" align="center" prop="productionDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.productionDate, '{y}-{m}-{d}') }}</span>
......@@ -192,14 +172,18 @@
</el-table-column>
<el-table-column label="RFID标签" align="center" prop="rfidTag" />
<el-table-column label="条形码" align="center" prop="barcode" />
<el-table-column label="是否FIFO管理" align="center" prop="isFifo" />
<el-table-column label="是否FIFO管理" align="center" prop="isFifo">
<template #default="scope">
<dict-tag :options="sys_yes_no" :value="scope.row.isFifo" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="RFID绑定数量" align="center" prop="rfidBindingCount" />
<el-table-column label="最后RFID检测时间" align="center" prop="lastRfidDetectTime" width="180">
<!-- <el-table-column label="最后RFID检测时间" align="center" prop="lastRfidDetectTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.lastRfidDetectTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column label="RFID覆盖率" align="center" prop="rfidCoverageRate" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220" fixed="right">
<template #default="scope">
......@@ -383,7 +367,11 @@
</el-col>
<el-col :span="12">
<el-form-item label="是否FIFO管理" prop="isFifo">
<el-input v-model="form.isFifo" placeholder="请输入是否FIFO管理" />
<el-radio-group v-model="form.isFifo">
<el-radio v-for="item in sys_yes_no" :label="item.value" :key="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
......@@ -591,6 +579,7 @@ import InventoryFlowDialog from "@/components/InventoryFlowDialog.vue"
import { View, CircleCheckFilled, CircleCloseFilled } from '@element-plus/icons-vue'
const { proxy } = getCurrentInstance()
const {sys_yes_no} = proxy.useDict('sys_yes_no')
const wmsInventoryList = ref([])
const open = ref(false)
......
......@@ -96,7 +96,11 @@
<el-table-column label="长度" align="center" prop="length" />
<el-table-column label="宽度" align="center" prop="width" />
<el-table-column label="高度" align="center" prop="height" />
<el-table-column label="状态" align="center" prop="status" />
<el-table-column label="状态" align="center" prop="status" width="80">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="RFID天线ID" align="center" prop="rfidAntennaId" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
......@@ -192,6 +196,8 @@ import AreaSelectTreeDialog from "@/components/AreaSelectTreeDialog.vue"
const { proxy } = getCurrentInstance()
const {sys_normal_disable} = proxy.useDict('sys_normal_disable')
const wmsLocationList = ref([])
const open = ref(false)
const loading = ref(true)
......
......@@ -129,9 +129,9 @@
</el-row>
<el-table v-loading="loading" :data="wmsMaterialList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="物资编码" align="center" prop="materialCode" width="150" />
<el-table-column label="物资名称" align="center" prop="materialName" />
<el-table-column type="selection" width="55" align="center" fixed="left" />
<el-table-column label="物资编码" align="center" prop="materialCode" width="150" fixed="left" />
<el-table-column label="物资名称" align="center" prop="materialName" fixed="left"/>
<el-table-column label="物资分类" align="center" prop="categoryId" />
<el-table-column label="规格型号" align="center" prop="specification" />
<el-table-column label="计量单位" align="center" prop="unit" />
......@@ -188,13 +188,13 @@
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否RFID管理" align="center" prop="isRfidManaged" width="100">
<!-- <el-table-column label="是否RFID管理" align="center" prop="isRfidManaged" width="100">
<template #default="scope">
<dict-tag :options="custom_yes_no" :value="scope.row.isRfidManaged" />
</template>
</el-table-column>
<el-table-column label="RFID标签" align="center" prop="rfidStandard" />
<el-table-column label="RFID粘贴位置" align="center" prop="rfidPosition" />
<el-table-column label="RFID粘贴位置" align="center" prop="rfidPosition" /> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['ware:wmsMaterial:edit']">修改</el-button>
......@@ -351,7 +351,7 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="是否RFID管理" prop="isRfidManaged">
<el-input v-model="form.isRfidManaged" placeholder="请输入是否RFID管理" />
......@@ -369,10 +369,10 @@
<el-input v-model="form.rfidPosition" placeholder="请输入RFID粘贴位置" />
</el-form-item>
</el-col>
</el-row>
</el-row> -->
<!-- 自定义属性扩展 -->
<el-divider>自定义属性</el-divider>
<!-- <el-divider>自定义属性</el-divider>
<el-form-item>
<el-button type="primary" plain size="small" @click="showCustomAttrDialog = true">添加属性</el-button>
<el-table :data="form.customAttributes" border style="margin-top: 10px;">
......@@ -390,7 +390,7 @@
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form-item> -->
</el-form>
<!-- 自定义属性编辑对话框 -->
......
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
corePlugins: {
preflight: false, // 禁用Tailwind的基础样式,避免与Element Plus的CSS变量冲突
},
}
\ No newline at end of file
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
const baseUrl = 'http://192.168.19.88:10011' // 后端接口
......@@ -62,6 +64,8 @@ export default defineConfig(({ mode, command }) => {
css: {
postcss: {
plugins: [
tailwindcss(),
autoprefixer(),
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment