diff --git a/src/api/mes/equipment.js b/src/api/mes/equipment.js
index b7bccd2..c62fb6e 100644
--- a/src/api/mes/equipment.js
+++ b/src/api/mes/equipment.js
@@ -31,3 +31,12 @@ export function getEquipmentRepairListByDeviceId(deviceId, params = {}) {
params: { deviceId, ...params }
})
}
+
+// 保养工单分页(planType=2为保养)
+export function getMaintenanceTicketPage(params = {}) {
+ return request({
+ url: '/admin-api/mes/ticket-management/page',
+ method: 'get',
+ params: { planType: '2', pageSize: 100, ...params }
+ })
+}
diff --git a/src/api/mes/sparepart.js b/src/api/mes/sparepart.js
index 1afc49a..161bb98 100644
--- a/src/api/mes/sparepart.js
+++ b/src/api/mes/sparepart.js
@@ -20,3 +20,12 @@ export function getSparepartDetail(id) {
params: { id }
})
}
+
+// 备件库存数量
+export function getSparepartStockCount(productId) {
+ return request({
+ url: '/admin-api/erp/stock/get-count',
+ method: 'get',
+ params: { productId }
+ })
+}
diff --git a/src/api/mes/sparepartInbound.js b/src/api/mes/sparepartInbound.js
index c4ff7a8..dd0656b 100644
--- a/src/api/mes/sparepartInbound.js
+++ b/src/api/mes/sparepartInbound.js
@@ -17,6 +17,15 @@ export function getSparepartInboundPage(params = {}) {
})
}
+// 备件入库单提交审核(提交后变为待审核状态)
+export function submitSparepartInbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-in/submit',
+ method: 'put',
+ data
+ })
+}
+
// 备件入库单审核(status: 20=通过, 1=驳回)
export function auditSparepartInbound(data) {
return request({
diff --git a/src/api/mes/sparepartOutbound.js b/src/api/mes/sparepartOutbound.js
index 5325f84..0fafdd3 100644
--- a/src/api/mes/sparepartOutbound.js
+++ b/src/api/mes/sparepartOutbound.js
@@ -1,5 +1,14 @@
import request from '@/utils/request'
+// 备件出库单创建
+export function createSparepartOutbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-out/create',
+ method: 'post',
+ data: { ...data, outType: '备件出库' }
+ })
+}
+
// 备件出库单分页查询
export function getSparepartOutboundPage(params = {}) {
return request({
@@ -9,6 +18,15 @@ export function getSparepartOutboundPage(params = {}) {
})
}
+// 备件出库单提交审核
+export function submitSparepartOutbound(data) {
+ return request({
+ url: '/admin-api/erp/stock-out/submit',
+ method: 'put',
+ data
+ })
+}
+
// 备件出库单审核(status: 20=通过, 1=驳回)
export function auditSparepartOutbound(data) {
return request({
diff --git a/src/hooks/useScannerInput.js b/src/hooks/useScannerInput.js
new file mode 100644
index 0000000..4de89c9
--- /dev/null
+++ b/src/hooks/useScannerInput.js
@@ -0,0 +1,203 @@
+import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
+
+const androidKeyCodeMap = {
+ 7: '0',
+ 8: '1',
+ 9: '2',
+ 10: '3',
+ 11: '4',
+ 12: '5',
+ 13: '6',
+ 14: '7',
+ 15: '8',
+ 16: '9',
+ 29: 'A',
+ 30: 'B',
+ 31: 'C',
+ 32: 'D',
+ 33: 'E',
+ 34: 'F',
+ 35: 'G',
+ 36: 'H',
+ 37: 'I',
+ 38: 'J',
+ 39: 'K',
+ 40: 'L',
+ 41: 'M',
+ 42: 'N',
+ 43: 'O',
+ 44: 'P',
+ 45: 'Q',
+ 46: 'R',
+ 47: 'S',
+ 48: 'T',
+ 49: 'U',
+ 50: 'V',
+ 51: 'W',
+ 52: 'X',
+ 53: 'Y',
+ 54: 'Z',
+ 55: ',',
+ 56: '.',
+ 69: '-',
+ 70: '=',
+ 71: '[',
+ 72: ']',
+ 73: '\\',
+ 74: ';',
+ 75: "'",
+ 76: '/',
+ 81: '+'
+}
+
+export function useScannerInput(options = {}) {
+ const minLength = Number(options.minLength ?? 3)
+ const commitDelay = Number(options.commitDelay ?? 120)
+ const uppercase = options.uppercase !== false
+ const ignoreInputTarget = options.ignoreInputTarget !== false
+ const hideKeyboardOnScan = options.hideKeyboardOnScan !== false
+ const hideKeyboardOnLeave = options.hideKeyboardOnLeave !== false
+ const onScan = typeof options.onScan === 'function' ? options.onScan : () => {}
+
+ let scannerBuffer = ''
+ let scannerTimer = null
+ let scannerListening = false
+ let plusKeyListening = false
+
+ function getScannerEventTarget() {
+ if (typeof document !== 'undefined') return document
+ if (typeof window !== 'undefined') return window
+ return null
+ }
+
+ function registerScannerListener() {
+ if (scannerListening) return
+ const target = getScannerEventTarget()
+ if (target?.addEventListener) {
+ target.addEventListener('keydown', handleScannerKeydown)
+ scannerListening = true
+ }
+ registerPlusKeyListener()
+ }
+
+ function unregisterScannerListener() {
+ const target = getScannerEventTarget()
+ if (scannerListening && target?.removeEventListener) {
+ target.removeEventListener('keydown', handleScannerKeydown)
+ }
+ scannerListening = false
+ unregisterPlusKeyListener()
+ clearScannerBuffer()
+ if (hideKeyboardOnLeave) hideSoftKeyboard()
+ }
+
+ function registerPlusKeyListener() {
+ if (plusKeyListening) return
+ if (typeof plus === 'undefined' || !plus?.key?.addEventListener) return
+ plus.key.addEventListener('keydown', handlePlusScannerKeydown)
+ plusKeyListening = true
+ }
+
+ function unregisterPlusKeyListener() {
+ if (!plusKeyListening) return
+ if (typeof plus !== 'undefined' && plus?.key?.removeEventListener) {
+ plus.key.removeEventListener('keydown', handlePlusScannerKeydown)
+ }
+ plusKeyListening = false
+ }
+
+ function handlePlusScannerKeydown(event) {
+ handleScannerKeydown({ ...event, isPlusKeyEvent: true })
+ }
+
+ function handleScannerKeydown(event) {
+ if (ignoreInputTarget) {
+ const targetTag = String(event?.target?.tagName || '').toLowerCase()
+ if (targetTag === 'input' || targetTag === 'textarea') return
+ }
+
+ const key = normalizeScannerKey(event)
+ if (!key) return
+ if (key === 'Enter') {
+ commitScannerBuffer()
+ return
+ }
+
+ scannerBuffer += key
+ if (scannerTimer) clearTimeout(scannerTimer)
+ scannerTimer = setTimeout(() => {
+ commitScannerBuffer()
+ }, commitDelay)
+ }
+
+ function normalizeScannerKey(event) {
+ if (event?.ctrlKey || event?.altKey || event?.metaKey) return ''
+ if (isAndroidPlusKeyEvent(event)) return normalizeAndroidKeyCode(event)
+
+ const key = event?.key
+ if (key === 'Enter' || key === 'Tab') return 'Enter'
+ if (typeof key === 'string' && key.length === 1) return uppercase ? key.toUpperCase() : key
+
+ const code = Number(event?.keyCode || event?.which || 0)
+ if (code === 13 || code === 9) return 'Enter'
+ if (code >= 48 && code <= 90) {
+ const value = String.fromCharCode(code)
+ return uppercase ? value.toUpperCase() : value
+ }
+ if (code >= 96 && code <= 105) return String(code - 96)
+ if (code === 189 || code === 109) return '-'
+ if (code === 190 || code === 110) return '.'
+ return ''
+ }
+
+ function isAndroidPlusKeyEvent(event) {
+ return Boolean(event?.isPlusKeyEvent)
+ }
+
+ function normalizeAndroidKeyCode(event) {
+ const code = Number(event?.keyCode || event?.which || 0)
+ if (code === 66 || code === 61 || code === 160) return 'Enter'
+ const value = androidKeyCodeMap[code] || ''
+ return uppercase ? value.toUpperCase() : value.toLowerCase()
+ }
+
+ function clearScannerBuffer() {
+ scannerBuffer = ''
+ if (scannerTimer) {
+ clearTimeout(scannerTimer)
+ scannerTimer = null
+ }
+ }
+
+ async function commitScannerBuffer() {
+ const value = scannerBuffer.trim()
+ clearScannerBuffer()
+ if (value.length < minLength) return
+ if (hideKeyboardOnScan) hideSoftKeyboard()
+ await onScan(value)
+ }
+
+ function hideSoftKeyboard() {
+ try {
+ uni.hideKeyboard()
+ } catch (e) {}
+ }
+
+ onShow(() => {
+ registerScannerListener()
+ })
+
+ onHide(() => {
+ unregisterScannerListener()
+ })
+
+ onUnload(() => {
+ unregisterScannerListener()
+ })
+
+ return {
+ clearScannerBuffer,
+ registerScannerListener,
+ unregisterScannerListener
+ }
+}
diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js
index fcd1e24..58581db 100644
--- a/src/locales/zh-CN.js
+++ b/src/locales/zh-CN.js
@@ -1396,7 +1396,7 @@ export default {
},
sparepartInbound: {
moduleName: '备件入库',
- tabPending: '待提交',
+ tabPending: '待入库',
tabAuditing: '待审核',
searchPlaceholder: '搜索入库单号',
sparepartInfo: '备件信息',
@@ -1404,7 +1404,7 @@ export default {
creator: '创建人',
quantity: '数量',
reviewer: '审核人',
- approve: '已通过',
+ approve: '已入库',
reject: '驳回',
confirmApprove: '确定审核通过该入库单吗?',
confirmReject: '确定驳回该入库单吗?',
@@ -1437,7 +1437,7 @@ export default {
},
sparepartOutbound: {
moduleName: '备件出库',
- tabPending: '待提交',
+ tabPending: '待出库',
tabAuditing: '待审核',
searchPlaceholder: '搜索出库单号',
sparepartInfo: '备件信息',
@@ -1445,7 +1445,7 @@ export default {
creator: '创建人',
quantity: '数量',
reviewer: '审核人',
- approve: '已通过',
+ approve: '已出库',
reject: '驳回',
confirmApprove: '确定审核通过该出库单吗?',
confirmReject: '确定驳回该出库单吗?',
diff --git a/src/pages.json b/src/pages.json
index 59bea2e..a9be7da 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -388,6 +388,13 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "sparepartInbound/sparepartConfirm",
+ "style": {
+ "navigationBarTitleText": "确认备件入库",
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "sparepartOutbound/index",
"style": {
@@ -402,6 +409,13 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "sparepartOutbound/sparepartConfirm",
+ "style": {
+ "navigationBarTitleText": "确认备件出库",
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "keypart/index",
diff --git a/src/pages_function/pages/equipmentLedger/index.vue b/src/pages_function/pages/equipmentLedger/index.vue
index a3662a1..d8ea078 100644
--- a/src/pages_function/pages/equipmentLedger/index.vue
+++ b/src/pages_function/pages/equipmentLedger/index.vue
@@ -7,14 +7,14 @@
{{ selectedLineLabel }}
-
+
@@ -82,7 +82,7 @@
@@ -525,7 +415,7 @@ onHide(() => {
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}
-/* ====== 操作按钮区 ====== */
+/* 操作按钮区 */
.action-row {
display: flex;
gap: 20rpx;
@@ -545,501 +435,135 @@ onHide(() => {
font-size: 28rpx;
font-weight: 600;
- .btn-icon-wrap {
- width: 44rpx;
- height: 44rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .btn-icon {
- font-size: 36rpx;
- color: #fff;
- }
-
- .btn-text {
- font-size: 28rpx;
- font-weight: 600;
- color: #fff;
- }
+ .btn-icon-wrap { width: 44rpx; height: 44rpx; display: flex; align-items: center; justify-content: center; }
+ .btn-icon { font-size: 36rpx; color: #fff; }
+ .btn-text { font-size: 28rpx; font-weight: 600; color: #fff; }
}
-/* ====== 已选备件区域 ====== */
-.sparepart-section {
- padding: 0;
-}
+/* 备件列表 */
+.sparepart-section { padding: 0; }
.section-title-bar {
- display: flex;
- align-items: center;
- gap: 10rpx;
+ display: flex; align-items: center; gap: 10rpx;
padding: 24rpx 24rpx 18rpx;
}
-
.section-bar-line {
- width: 6rpx;
- height: 32rpx;
- border-radius: 3rpx;
- background: #2563eb;
- flex-shrink: 0;
-}
-
-.section-title {
- font-size: 30rpx;
- font-weight: 700;
- color: #1a1a1a;
-}
-
-.sparepart-card {
- background: #fff;
- border-radius: 16rpx;
- padding: 24rpx;
- margin: 0 24rpx 20rpx;
- box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.04);
-}
-
-/* ====== 卡片上半部分:图片 + 信息 + 删除 ====== */
-.card-top {
- display: flex;
- position: relative;
-}
-
-.card-image-wrap {
- width: 160rpx;
- height: 160rpx;
- border-radius: 12rpx;
- overflow: hidden;
- background: #f8fafc;
- border: 1rpx solid #f0f0f0;
- flex-shrink: 0;
- margin-right: 20rpx;
-}
-
-.card-image {
- width: 100%;
- height: 100%;
-}
-
-.card-image-empty {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #f8fafc;
-}
-
-.empty-img-icon {
- font-size: 56rpx;
- opacity: 0.3;
-}
-
-/* 右侧信息区 */
-.card-info-right {
- flex: 1;
- min-width: 0;
-}
-
-.info-item {
- display: flex;
- align-items: center;
- margin-bottom: 8rpx;
-}
-
-.info-label {
- font-size: 26rpx;
- color: #6b7280;
- flex-shrink: 0;
-}
-
-.info-name {
- font-size: 30rpx;
- font-weight: 700;
- color: #0f172a;
-}
-
-.info-value {
- font-size: 26rpx;
- color: #374151;
-
- &.stock-highlight {
- color: #2563eb;
- font-weight: 500;
- }
-}
-
-/* 删除按钮 */
-.card-delete {
- position: absolute;
- top: -8rpx;
- right: -8rpx;
- width: 48rpx;
- height: 48rpx;
- border-radius: 24rpx;
- background: #fee2e2;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.delete-icon {
- font-size: 22rpx;
- color: #dc2626;
-}
-
-/* ====== 卡片下半部分:详细信息 ====== */
-.card-bottom {
- margin-top: 20rpx;
- padding-top: 20rpx;
- border-top: 1rpx solid #f0f0f0;
-}
-
-.detail-row {
- display: flex;
- align-items: center;
- margin-bottom: 14rpx;
-
- &:last-child {
- margin-bottom: 0;
- }
-
- &.two-col {
- justify-content: space-between;
- }
-}
-
-.detail-col {
- display: flex;
- align-items: center;
- flex: 1;
-}
-
-.detail-label {
- font-size: 24rpx;
- color: #9ca3af;
- flex-shrink: 0;
+ width: 6rpx; height: 32rpx; border-radius: 3rpx;
+ background: #2563eb; flex-shrink: 0;
}
+.section-title { font-size: 30rpx; font-weight: 700; color: #1a1a1a; }
+.required { color: #ef4444; margin-right: 2rpx; }
-.detail-value {
- font-size: 24rpx;
- color: #4b5563;
-}
+.item-list { padding: 0 24rpx; }
-/* ====== 入库数量 ====== */
-.inbound-qty-section {
- margin-top: 4rpx;
+.item-card {
+ position: relative; display: flex; align-items: center; justify-content: space-between;
+ background: #fff; border-radius: 14rpx; padding: 20rpx; margin-bottom: 16rpx;
+ box-shadow: 0 2rpx 12rpx rgba(15, 23, 42, 0.04);
}
+.item-delete-top { position: absolute; top: 10rpx; right: 10rpx; width: 40rpx; height: 40rpx; border-radius: 20rpx; background: #fee2e2; display: flex; align-items: center; justify-content: center; z-index: 1; .delete-icon { font-size: 20rpx; color: #dc2626; } }
-.qty-input-card {
- background: #fff;
- border-radius: 16rpx;
- padding: 24rpx;
- margin: 0 24rpx;
- box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.04);
+.item-left { display: flex; align-items: center; flex: 1; min-width: 0; padding-right: 36rpx; }
+.item-image-wrap {
+ width: 80rpx; height: 80rpx; border-radius: 10rpx; overflow: hidden;
+ background: #f8fafc; border: 1rpx solid #f0f0f0; flex-shrink: 0;
+ display: flex; align-items: center; justify-content: center;
}
-
-.form-field {
- display: flex;
- flex-direction: column;
- gap: 12rpx;
+.item-image { width: 100%; height: 100%; }
+.item-image-empty { font-size: 36rpx; opacity: 0.3; }
+.item-info { margin-left: 16rpx; flex: 1; min-width: 0; }
+.item-name {
+ font-size: 28rpx; font-weight: 600; color: #1a1a1a; display: block;
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
+.item-spec { font-size: 24rpx; color: #9ca3af; margin-top: 6rpx; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
-.form-label {
- font-size: 26rpx;
- color: #4b5563;
- font-weight: 500;
-}
+.item-right { display: flex; flex-direction: column; align-items: flex-end; margin-left: 16rpx; flex-shrink: 0; padding-right: 50rpx; }
+.item-qty-row { display: flex; flex-direction: column; align-items: flex-end; }
+.item-qty-label { font-size: 22rpx; color: #9ca3af; }
+.item-qty-value { font-size: 28rpx; font-weight: 700; color: #2563eb; margin-top: 4rpx; }
-.form-input {
- width: 100%;
- height: 88rpx;
- padding: 0 24rpx;
- font-size: 28rpx;
- color: #374151;
- background: #f8fafc;
- border-radius: 14rpx;
- box-sizing: border-box;
-}
+.empty-wrap { padding: 160rpx 0; text-align: center; }
+.empty-text { font-size: 28rpx; color: #94a3b8; }
-.form-suffix-text {
- display: block;
- margin-top: 10rpx;
- font-size: 24rpx;
- color: #9ca3af;
-}
-
-/* ====== 折算后库存数量(内嵌在入库数量卡片) ====== */
-.convert-row {
- margin-top: 20rpx;
- padding-top: 20rpx;
- border-top: 1rpx solid #f0f0f0;
- display: flex;
- align-items: center;
-}
-
-.convert-label-inline {
- font-size: 26rpx;
- color: #6b7280;
-}
-
-.convert-value-inline {
- font-size: 36rpx;
- font-weight: 700;
- color: #1f2937;
- margin-left: auto;
-}
+/* 入库信息区 */
+.form-section { padding-bottom: 16rpx; }
-.convert-unit-inline {
- font-size: 24rpx;
- color: #64748b;
- margin-left: 8rpx;
-}
-
-.convert-formula-inline {
- margin-top: 10rpx;
- font-size: 22rpx;
- color: #9ca3af;
-}
-
-/* ====== 供应商/经办人 选择行 ====== */
-.select-row-card {
+.form-row-card {
position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- background: #fff;
- border-radius: 16rpx;
- padding: 24rpx;
- margin: 0 24rpx 20rpx;
+ display: flex; align-items: center; justify-content: space-between;
+ background: #fff; border-radius: 16rpx; padding: 26rpx 24rpx; margin: 0 24rpx 16rpx;
box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.04);
-
- .dropdown-panel {
- position: absolute;
- top: 100%;
- left: 0;
- right: 0;
- z-index: 99;
- margin-top: 4rpx;
- background: #fff;
- border: 1rpx solid #e0e0e0;
- border-radius: 12rpx;
- box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
- overflow: hidden;
- }
-}
-
-.select-row-left {
- display: flex;
- align-items: center;
- flex-shrink: 0;
-}
-
-.select-row-icon {
- font-size: 36rpx;
- color: #3b82f6;
- margin-right: 16rpx;
- flex-shrink: 0;
-}
-
-.select-row-label {
- font-size: 28rpx;
- color: #374151;
-}
-
-.full-dropdown {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- font-size: 28rpx;
- color: #374151;
-
- .placeholder {
- color: #9ca3af;
- }
+ font-size: 28rpx; color: #374151;
+ .placeholder { color: #9ca3af; }
}
+.form-row-arrow { font-size: 20rpx; color: #999; flex-shrink: 0; }
-.select-row-dropdown {
- flex: 1;
- min-width: 0;
- margin-left: 24rpx;
-}
-
-/* ====== 仓库/库区 两行布局 ====== */
-.warehouse-area-rows {
- width: 100%;
- display: flex;
- flex-direction: column;
- gap: 16rpx;
-}
-
-.warehouse-area-row {
- display: flex;
- align-items: center;
-}
-
-.warehouse-area-label {
- width: 80rpx;
- font-size: 26rpx;
- color: #6b7280;
+/* 经办人下拉 */
+.dropdown-panel {
+ position: absolute; top: 100%; left: 0; right: 0; z-index: 200; margin-top: 4rpx;
+ background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx;
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1); overflow: hidden;
+}
+.dropdown-scroll { height: 360rpx; }
+.dropdown-item { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; border-bottom: 1rpx solid #f0f0f0;
+ &:last-child { border-bottom: 0; }
+ &.active { background: #f0f5ff; }
+}
+.dropdown-item-text { font-size: 27rpx; color: #333; }
+.dropdown-check { font-size: 28rpx; color: #2563eb; font-weight: 700; }
+.dropdown-empty { padding: 32rpx; text-align: center; color: #999; font-size: 26rpx; }
+
+/* 备注 */
+.remark-card { padding: 20rpx 24rpx; }
+.remark-textarea { width: 100%; min-height: 120rpx; font-size: 27rpx; color: #374151; line-height: 1.6; box-sizing: border-box; }
+.remark-placeholder { color: #bbb; }
+
+/* 附件 */
+.attachment-area { padding: 0 24rpx 16rpx; }
+.attachment-list { display: flex; flex-direction: column; gap: 12rpx; }
+
+.attachment-file-item {
+ display: flex; align-items: center; gap: 16rpx;
+ background: #fff; border-radius: 12rpx; padding: 18rpx 20rpx;
+ box-shadow: 0 2rpx 8rpx rgba(15, 23, 42, 0.03);
+}
+.file-icon {
+ width: 72rpx; height: 72rpx; border-radius: 10rpx;
+ background: #f1f5f9; display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
-
-.warehouse-area-dropdown {
- flex: 1;
- min-width: 0;
- position: relative;
-
- .dropdown-panel {
- position: absolute;
- top: 100%;
- left: 0;
- right: 0;
- z-index: 100;
- margin-top: 4rpx;
- background: #fff;
- border: 1rpx solid #e0e0e0;
- border-radius: 12rpx;
- box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
- overflow: hidden;
- }
-}
-
-.warehouse-area-card {
- align-items: flex-start;
- flex-wrap: wrap;
-}
-
-/* ====== 下拉选择器 ====== */
-.select-dropdown {
- position: relative;
- width: 100%;
-}
-
-.dropdown-input {
- display: flex;
- align-items: center;
- height: 64rpx;
- padding: 0 20rpx;
- border: 1rpx solid #e0e0e0;
- border-radius: 10rpx;
- background: #f9fafb;
-}
-
-.dropdown-value {
- flex: 1;
- font-size: 27rpx;
- color: #333;
-
- &.placeholder {
- color: #bbb;
- }
+.file-icon-text { font-size: 36rpx; }
+.file-info { flex: 1; min-width: 0; }
+.file-name {
+ font-size: 26rpx; color: #1f2937; display: block;
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
-
-.dropdown-arrow {
- font-size: 20rpx;
- color: #999;
+.file-size { font-size: 22rpx; color: #9ca3af; margin-top: 4rpx; display: block; }
+.file-delete {
+ width: 48rpx; height: 48rpx; border-radius: 24rpx;
+ background: #fee2e2; display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
+.delete-icon-sm { font-size: 22rpx; color: #dc2626; }
-.dropdown-panel {
- position: absolute;
- top: 68rpx;
- left: 0;
- right: 0;
- z-index: 99;
- background: #fff;
- border: 1rpx solid #e0e0e0;
+.attachment-add-file {
+ display: flex; align-items: center; justify-content: center; gap: 10rpx;
+ height: 88rpx; background: #fff; border: 2rpx dashed #cbd5e1;
border-radius: 12rpx;
- box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
- overflow: hidden;
-}
-
-.dropdown-scroll {
- max-height: 360rpx;
-}
-
-.dropdown-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 20rpx 24rpx;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:last-child {
- border-bottom: 0;
- }
-
- &.active {
- background: #f0f5ff;
- }
-}
-
-.dropdown-item-text {
- font-size: 27rpx;
- color: #333;
-}
-
-.dropdown-check {
- font-size: 28rpx;
- color: #2563eb;
- font-weight: 700;
}
+.add-icon { font-size: 32rpx; }
+.add-text { font-size: 26rpx; color: #6b7280; }
-.dropdown-empty {
- padding: 32rpx;
- text-align: center;
- color: #999;
- font-size: 26rpx;
-}
-
-/* ====== 空状态 ====== */
-.empty-wrap {
- padding: 160rpx 24rpx;
- text-align: center;
-}
-
-.empty-text {
- font-size: 28rpx;
- color: #94a3b8;
-}
-
-/* ====== 底部操作栏 ====== */
+/* 底部操作栏 */
.bottom-actions {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- display: flex;
- gap: 18rpx;
+ position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: 18rpx;
padding: 18rpx 24rpx calc(18rpx + env(safe-area-inset-bottom));
- background: #ffffff;
- box-shadow: 0 -8rpx 24rpx rgba(15, 23, 42, 0.06);
- z-index: 99;
-}
-
-.bottom-btn {
- flex: 1;
- height: 84rpx;
- line-height: 84rpx;
- text-align: center;
- border-radius: 16rpx;
- font-size: 30rpx;
- font-weight: 600;
-
- &:active {
- opacity: 0.85;
- }
+ background: #ffffff; box-shadow: 0 -8rpx 24rpx rgba(15, 23, 42, 0.06); z-index: 99;
}
-
-.cancel-btn {
- background: #eef2f7;
- color: #475569;
-}
-
-.confirm-btn {
- background: #1f4b79;
- color: #ffffff;
+.bottom-btn { flex: 1; height: 84rpx; line-height: 84rpx; text-align: center; border-radius: 16rpx; font-size: 30rpx; font-weight: 600;
+ &:active { opacity: 0.85; }
}
+.cancel-btn { background: #eef2f7; color: #475569; }
+.confirm-btn { background: #1f4b79; color: #ffffff; }
diff --git a/src/pages_function/pages/sparepartInbound/index.vue b/src/pages_function/pages/sparepartInbound/index.vue
index bdc7497..179d30a 100644
--- a/src/pages_function/pages/sparepartInbound/index.vue
+++ b/src/pages_function/pages/sparepartInbound/index.vue
@@ -71,10 +71,14 @@
{{ textValue(item.auditUserName) }}
-
+
+
+ 提交审核
+
+
- {{ t('sparepartInbound.approve') }}
- {{ t('sparepartInbound.reject') }}
+ 审核通过
+ 审核驳回
@@ -94,6 +98,43 @@
+
+
+
+
+
+
+
+
+
+ *审核人
+
+ {{ selectedAuditor ? selectedAuditor.label : '请选择' }}
+ ▼
+
+
+
+ {{ u.label }}
+ ✓
+
+
+
+
+
+
+
+ 备注
+
+
+
+
+
+
@@ -102,7 +143,8 @@ import { computed, nextTick, ref } from 'vue'
import { onShow, onUnload } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
-import { getSparepartInboundPage, auditSparepartInbound } from '@/api/mes/sparepartInbound'
+import { getSparepartInboundPage, auditSparepartInbound, submitSparepartInbound } from '@/api/mes/sparepartInbound'
+import { getSimpleUserList } from '@/api/mes/moldget'
const { t } = useI18n()
@@ -156,15 +198,15 @@ function formatDateTime(value) {
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}
-const STATUS_MAP = { 0: '待入库', 10: '待审核', 20: '已通过', 1: '已驳回' }
+const STATUS_MAP = { 0: '待入库', 10: '待审核', 20: '已入库', 1: '已驳回' }
function statusText(s) {
const num = Number(s)
return STATUS_MAP[num] || textValue(num)
}
function statusClass(s) {
const num = Number(s)
- if (num === 0) return 'text-warning'
- if (num === 10) return 'text-primary'
+ if (num === 0) return 'text-primary'
+ if (num === 10) return 'text-warning'
if (num === 20) return 'text-success'
if (num === 1) return 'text-danger'
return ''
@@ -292,6 +334,75 @@ async function handleReject(item) {
})
}
+// 提交审核弹框
+const showAuditModal = ref(false)
+const currentAuditItem = ref(null)
+const auditorOptions = ref([])
+const selectedAuditor = ref(null)
+const showAuditorDropdown = ref(false)
+const auditRemark = ref('')
+
+function openSubmitAudit(item) {
+ currentAuditItem.value = item
+ selectedAuditor.value = null
+ auditRemark.value = ''
+ showAuditModal.value = true
+ loadAuditorOptions()
+}
+
+function closeAuditModal() {
+ showAuditModal.value = false
+ currentAuditItem.value = null
+ showAuditorDropdown.value = false
+}
+
+function toggleAuditorDropdown() {
+ showAuditorDropdown.value = !showAuditorDropdown.value
+}
+
+function selectAuditor(u) {
+ selectedAuditor.value = u
+ showAuditorDropdown.value = false
+}
+
+async function loadAuditorOptions() {
+ if (auditorOptions.value.length) return
+ try {
+ const res = await getSimpleUserList()
+ const data = Array.isArray(res) ? res : (Array.isArray(res?.data) ? res.data : [])
+ auditorOptions.value = data.map((u) => ({
+ value: u.id || u.userId,
+ label: u.nickname || u.userName || u.name || String(u.id || '')
+ }))
+ } catch (e) {
+ console.error('loadAuditorOptions error', e)
+ }
+}
+
+async function confirmSubmitAudit() {
+ if (!selectedAuditor.value) {
+ uni.showToast({ title: '请选择审核人', icon: 'none' })
+ return
+ }
+ if (!currentAuditItem.value?.id) return
+
+ try {
+ uni.showLoading({ title: '提交中...', mask: true })
+ await submitSparepartInbound({
+ id: currentAuditItem.value.id,
+ auditUserId: selectedAuditor.value.value,
+ remark: auditRemark.value || undefined
+ })
+ uni.hideLoading()
+ uni.showToast({ title: '提交审核成功', icon: 'success' })
+ closeAuditModal()
+ fetchList(true)
+ } catch (e) {
+ uni.hideLoading()
+ uni.showToast({ title: '提交失败', icon: 'none' })
+ }
+}
+
function onScroll(event) {
showGoTop.value = (event?.detail?.scrollTop || 0) > 600
}
@@ -505,6 +616,11 @@ onUnload(() => {
color: #dc2626;
}
+ &.submit-btn {
+ background: #dbeafe;
+ color: #1d4ed8;
+ }
+
&:active {
opacity: 0.8;
}
@@ -591,4 +707,60 @@ onUnload(() => {
line-height: 1;
margin-top: -4rpx;
}
+
+/* ====== 提交审核弹框 ====== */
+.modal-overlay {
+ position: fixed; top: 0; left: 0; right: 0; bottom: 0;
+ background: rgba(0, 0, 0, 0.45); z-index: 999;
+ display: flex; align-items: center; justify-content: center;
+}
+.modal-card {
+ width: 640rpx; background: #fff; border-radius: 20rpx;
+ box-shadow: 0 16rpx 48rpx rgba(0,0,0,0.15);
+}
+.modal-header {
+ display: flex; align-items: center; justify-content: space-between;
+ padding: 32rpx 32rpx 20rpx; border-bottom: 1rpx solid #f0f0f0;
+}
+.modal-title { font-size: 32rpx; font-weight: 700; color: #1a1a1a; }
+.modal-close { font-size: 32rpx; color: #999; padding: 8rpx; }
+.modal-body { padding: 28rpx 32rpx; }
+.modal-field { margin-bottom: 28rpx;
+ &:last-child { margin-bottom: 0; }
+}
+.modal-label { font-size: 28rpx; color: #374151; font-weight: 500; margin-bottom: 14rpx; display: block; }
+.modal-label .required { color: #ef4444; }
+.modal-dropdown {
+ position: relative; display: flex; align-items: center; justify-content: space-between;
+ height: 80rpx; padding: 0 24rpx;
+ background: #f8fafc; border: 1rpx solid #e0e0e0; border-radius: 12rpx;
+ font-size: 28rpx; color: #374151;
+ .placeholder { color: #bbb; }
+ .dropdown-arrow { font-size: 20rpx; color: #999; }
+}
+.modal-textarea {
+ width: 100%; min-height: 140rpx; padding: 20rpx;
+ background: #f8fafc; border: 1rpx solid #e0e0e0;
+ border-radius: 12rpx; font-size: 27rpx; color: #374151;
+ box-sizing: border-box;
+}
+.textarea-placeholder { color: #bbb; }
+.dropdown-panel {
+ position: absolute; top: 100%; left: 0; right: 0; z-index: 200; margin-top: 4rpx;
+ background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx;
+ box-shadow: 0 8rpx 30rpx rgba(0,0,0,0.1); overflow: hidden;
+}
+.dropdown-scroll { height: 300rpx; }
+.dropdown-item { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; border-bottom: 1rpx solid #f0f0f0;
+ &:last-child { border-bottom: 0; }
+ &.active { background: #f0f5ff; }
+}
+.dropdown-item-text { font-size: 27rpx; color: #333; }
+.dropdown-check { font-size: 28rpx; color: #2563eb; font-weight: 700; }
+.modal-footer { display: flex; gap: 18rpx; padding: 24rpx 32rpx; border-top: 1rpx solid #f0f0f0; }
+.modal-btn { flex: 1; height: 80rpx; line-height: 80rpx; text-align: center; border-radius: 14rpx; font-size: 30rpx; font-weight: 600;
+ &:active { opacity: 0.85; }
+ &.cancel-btn { background: #f0f0f0; color: #6b7280; }
+ &.confirm-btn { background: #1f4b79; color: #fff; }
+}
diff --git a/src/pages_function/pages/sparepartInbound/sparepartConfirm.vue b/src/pages_function/pages/sparepartInbound/sparepartConfirm.vue
new file mode 100644
index 0000000..8a0ec6f
--- /dev/null
+++ b/src/pages_function/pages/sparepartInbound/sparepartConfirm.vue
@@ -0,0 +1,492 @@
+
+
+
+
+
+
+
+
+ 已选备件
+
+
+
+
+
+
+ 📦
+
+
+
+
+ 备件名称:
+ {{ textValue(sparepart.name) }}
+
+
+ 规格:
+ {{ textValue(sparepart.standard || sparepart.deviceSpec) }}
+
+
+ 当前库存:
+ {{ sparepart.count != null ? sparepart.count : 0 }}{{ textUnit(sparepart.unitName || sparepart.minStockUnitName || '个') }}
+
+
+
+
+
+
+ 采购单位:
+ {{ textValue(sparepart.purchaseUnitName) }}
+
+
+ 库存单位:
+ {{ textValue(sparepart.unitName || sparepart.minStockUnitName || '个') }}
+
+
+
+ 换算关系:
+ 1{{ textValue(sparepart.purchaseUnitName) }}={{ textValue(sparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(sparepart) }}
+
+
+
+
+
+
+
+ 入库数量
+
+
+
+ 入库数量
+
+ 单位:{{ textValue(sparepart.purchaseUnitName) }}
+
+
+ 折算后库存数量:
+ {{ calculatedStock }}
+ {{ stockUnitLabel(sparepart) }}
+
+
+ {{ inboundQty || 0 }}{{ textValue(sparepart.purchaseUnitName) }} × {{ textValue(sparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(sparepart) }} = {{ calculatedStock }}{{ stockUnitLabel(sparepart) }}
+
+
+
+
+
+
+ 供应商
+
+
+
+
+ {{ defaultSupplierName || '未配置默认供应商' }}
+
+
+
+
+
+
+
+ 仓库/库区
+
+
+
+
+ 仓库
+
+
+
+ {{ selectedWarehouse ? selectedWarehouse.label : '请选择' }}
+
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ 暂无数据
+
+
+
+
+
+ 库区
+
+
+
+ {{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}
+
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ 暂无数据
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确认
+
+
+
+
+
+
+
diff --git a/src/pages_function/pages/sparepartInbound/sparepartSelect.vue b/src/pages_function/pages/sparepartInbound/sparepartSelect.vue
index 7730636..c451d98 100644
--- a/src/pages_function/pages/sparepartInbound/sparepartSelect.vue
+++ b/src/pages_function/pages/sparepartInbound/sparepartSelect.vue
@@ -143,9 +143,15 @@ function handleConfirm() {
return
}
const item = sparepartList.value.find((d) => d.id === selectedId.value)
- // 存入 globalData 后再返回,目标页 onShow 中读取
- getApp().globalData._sparepartSelectResult = item || null
- uni.navigateBack()
+ if (!item) return
+ // 存入 globalData 后跳转到对应确认页
+ getApp().globalData._sparepartBeforeConfirm = item
+ const from = getApp().globalData._sparepartSelectFrom || 'inbound'
+ getApp().globalData._sparepartSelectFrom = null
+ const url = from === 'outbound'
+ ? '/pages_function/pages/sparepartOutbound/sparepartConfirm'
+ : '/pages_function/pages/sparepartInbound/sparepartConfirm'
+ uni.navigateTo({ url })
}
onShow(async () => {
diff --git a/src/pages_function/pages/sparepartOutbound/create.vue b/src/pages_function/pages/sparepartOutbound/create.vue
index 005d667..44831d6 100644
--- a/src/pages_function/pages/sparepartOutbound/create.vue
+++ b/src/pages_function/pages/sparepartOutbound/create.vue
@@ -5,202 +5,107 @@
-
-
-
+
扫备件码
-
-
-
+
选择备件
-
-
+
+
+
- 已选备件
+ *出库时间
-
-
-
-
-
- 📦
-
-
-
-
- 备件名称:
- {{ textValue(selectedSparepart.name) }}
-
-
- 规格:
- {{ textValue(selectedSparepart.standard || selectedSparepart.deviceSpec) }}
-
-
- 当前库存:
- {{ textValue(selectedSparepart.stock) }}{{ textUnit(selectedSparepart.minStockUnitName) }}
-
-
+
+
+ {{ outboundDate || '请选择出库时间' }}
+ ▼
-
-
-
- 采购单位:
- {{ textValue(selectedSparepart.purchaseUnitName) }}
-
-
- 库存单位:
- {{ textValue(selectedSparepart.unitName || selectedSparepart.minStockUnitName) }}
+
+
+
+
+
+ *经办人
+
+
+ {{ selectedOperator ? selectedOperator.label : '请选择经办人' }}
+ ▼
+
+
+
+ {{ item.label }}
+ ✓
-
-
- 换算关系:
- 1{{ textValue(selectedSparepart.purchaseUnitName) }}={{ textValue(selectedSparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(selectedSparepart) }}
-
+ 暂无数据
+
-
+
- 出库用途
+ 备注
-
-
-
- 维修领用
-
-
-
- 保养领用
-
+
-
-
+
+
- 关联信息
+ 附件
-
-
-
- 关联设备
-
-
- {{ selectedDevice ? selectedDevice.label : '请选择' }}
- ▼
-
-
-
-
- {{ item.label }}
- ✓
-
- 暂无设备数据
-
-
+
+
+
+ {{ getFileIcon(file.name) }}
+
+ {{ file.name }}
+ {{ formatFileSize(file.size) }}
+ ✕
-
- {{ selectedPurpose === 'repair' ? '维修单号' : '保养单号' }}
-
-
- {{ currentOrder ? currentOrder.label : '请选择' }}
- ▼
-
-
-
-
- {{ item.label }}
- ✓
-
- {{ selectedPurpose === 'repair' ? '暂无维修单' : '暂无保养单' }}
-
-
-
+
+ 选取文件
+
-
-
-
-
- 出库数量
-
-
-
- 出库数量
-
- 单位:{{ textValue(selectedSparepart.purchaseUnitName) }}
-
-
- 折算后库存数量:
- {{ calculatedStock }}
- {{ stockUnitLabel(selectedSparepart) }}
-
-
- {{ outboundQty || 0 }}{{ textValue(selectedSparepart.purchaseUnitName) }} × {{ textValue(selectedSparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(selectedSparepart) }} = {{ calculatedStock }}{{ stockUnitLabel(selectedSparepart) }}
-
-
-
-
-
-
- 经办人
-
-
-
-
- {{ selectedOperator ? selectedOperator.label : '请选择经办人' }}
-
- ▼
+
+
+
+
+ 出库清单({{ itemList.length }})
+
+
+
+ ✕
+
+
+
+ 📦
+
+
+ {{ item.productName }}
+ {{ item.productBarCode || '-' }}
+
-
-
-
- {{ item.label }}
- ✓
-
- 暂无数据
-
+
+
+ 出库数量
+ {{ item.inputCount }}{{ item.purchaseUnitName }}
+
-
-
-
-
- 请扫码或选择备件
+ 请扫码或选择备件
@@ -212,500 +117,197 @@
diff --git a/src/pages_function/pages/sparepartOutbound/index.vue b/src/pages_function/pages/sparepartOutbound/index.vue
index 985b2a6..d81d705 100644
--- a/src/pages_function/pages/sparepartOutbound/index.vue
+++ b/src/pages_function/pages/sparepartOutbound/index.vue
@@ -2,82 +2,40 @@
-
-
+
-
- {{ currentStatusLabel }}
-
-
+ {{ currentStatusLabel }}
{{ t('functionCommon.reset') }}
-
-
+
-
+
-
- {{ t('sparepartOutbound.sparepartInfo') }}
- {{ textValue(item.productNames) }}
-
-
- {{ t('sparepartOutbound.outboundTime') }}
- {{ formatDateTime(item.outTime || item.createTime) }}
-
-
- {{ t('sparepartOutbound.creator') }}
- {{ textValue(item.creatorName || item.creator) }}
-
-
- {{ t('sparepartOutbound.quantity') }}
- {{ textValue(item.totalCount) }}
-
-
- {{ t('sparepartOutbound.reviewer') }}
- {{ textValue(item.auditUserName) }}
-
+ {{ t('sparepartOutbound.sparepartInfo') }}{{ textValue(item.productNames) }}
+ {{ t('sparepartOutbound.outboundTime') }}{{ formatDateTime(item.outTime || item.createTime) }}
+ {{ t('sparepartOutbound.creator') }}{{ textValue(item.creatorName || item.creator) }}
+ {{ t('sparepartOutbound.quantity') }}{{ textValue(item.totalCount) }}
+ {{ t('sparepartOutbound.reviewer') }}{{ textValue(item.auditUserName) }}
+
+
+ 提交审核
-
- {{ t('sparepartOutbound.approve') }}
- {{ t('sparepartOutbound.reject') }}
+ 审核通过
+ 审核驳回
-
{{ t('functionCommon.loading') }}
{{ t('sparepartOutbound.empty') }}
{{ t('functionCommon.loadingMore') }}
@@ -85,46 +43,65 @@
-
-
-
-
-
-
-
- +
+
+
+ +
+
+
+
+
+
+
+
+ *审核人
+
+ {{ selectedAuditor ? selectedAuditor.label : '请选择' }}
+ ▼
+
+
+
+ {{ u.label }}
+ ✓
+
+
+
+
+
+
+ 备注
+
+
+
+
+
diff --git a/src/pages_function/pages/sparepartOutbound/sparepartConfirm.vue b/src/pages_function/pages/sparepartOutbound/sparepartConfirm.vue
new file mode 100644
index 0000000..be4321a
--- /dev/null
+++ b/src/pages_function/pages/sparepartOutbound/sparepartConfirm.vue
@@ -0,0 +1,590 @@
+
+
+
+
+
+
+
+ 已选备件
+
+
+
+
+
+ 📦
+
+
+ 备件名称:{{ textValue(sparepart.name) }}
+ 规格:{{ textValue(sparepart.standard || sparepart.deviceSpec) }}
+ 当前库存:{{ sparepart.count != null ? sparepart.count : 0 }}{{ textUnit(sparepart.unitName || sparepart.minStockUnitName || '个') }}
+
+
+
+
+ 采购单位:{{ textValue(sparepart.purchaseUnitName) }}
+ 库存单位:{{ textValue(sparepart.unitName || sparepart.minStockUnitName || '个') }}
+
+ 换算关系:1{{ textValue(sparepart.purchaseUnitName) }}={{ textValue(sparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(sparepart) }}
+
+
+
+
+
+
+ 出库用途
+
+
+
+
+ 维修领用
+
+
+
+ 保养领用
+
+
+
+ 其他出库
+
+
+
+
+
+ 关联信息
+
+
+
+
+ 关联设备
+
+
+ {{ selectedDevice ? selectedDevice.label : '请选择' }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ 加载中...
+ {{ selectedPurpose === 'maintain' ? '暂无保养设备' : '暂无设备数据' }}
+
+
+
+
+
+ {{ selectedPurpose === 'repair' ? '维修单号' : '保养单号' }}
+
+
+ {{ currentOrder ? currentOrder.label : '请选择' }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+ {{ selectedPurpose === 'repair' ? '暂无维修单' : '暂无保养单' }}
+
+
+
+
+
+
+
+
+
+ 出库数量
+
+
+
+ 出库数量
+
+ 单位:{{ textValue(sparepart.purchaseUnitName) }}
+
+
+ 出库后剩余库存:
+ {{ remainingStock }}
+ {{ stockUnitLabel(sparepart) }}
+
+ {{ currentStockText }}
+ {{ outboundQty || 0 }}{{ textValue(sparepart.purchaseUnitName) }} × {{ textValue(sparepart.purchaseUnitConvertQuantity) }}{{ stockUnitLabel(sparepart) }} = {{ calculatedStock }}{{ stockUnitLabel(sparepart) }}
+
+
+ ⚠
+
+ 当前库存不足,不能出库
+ 当前库存:{{ stockCount }}{{ stockUnitLabel(sparepart) }}({{ stockPackText }})
+ 本次出库:{{ calculatedStock }}{{ stockUnitLabel(sparepart) }}({{ outboundPackText }})
+
+
+
+
+
+
+ 供应商
+
+
+
+ {{ defaultSupplierName || '未配置默认供应商' }}
+
+
+
+
+
+ 仓库/库区
+
+
+
+
+ 仓库
+
+
+ {{ selectedWarehouse ? selectedWarehouse.label : '请选择' }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+ 库区
+
+
+ {{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}
+ ▼
+
+
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确认
+
+
+
+
+
+
+