修复:完善装填状态与确认权限
This commit is contained in:
@@ -1075,6 +1075,13 @@ test('入库页面只允许 DRAFT 变更并以 authoritative 详情和独立确
|
|||||||
assertButtonsUsePermission(source, 'handleConfirm', 'business:inbound:confirm')
|
assertButtonsUsePermission(source, 'handleConfirm', 'business:inbound:confirm')
|
||||||
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:inbound:query', 'business:inbound:add'\]\)/)
|
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:inbound:query', 'business:inbound:add'\]\)/)
|
||||||
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:inbound:query', 'business:inbound:edit'\]\)/)
|
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:inbound:query', 'business:inbound:edit'\]\)/)
|
||||||
|
const confirmButton = extractButtonBlocks(source, 'handleConfirm')[0]
|
||||||
|
assert.match(confirmButton, /v-if="scope\.row\.status === 'DRAFT'"/)
|
||||||
|
assert.doesNotMatch(source, /canConfirmInbound/)
|
||||||
|
assert.doesNotMatch(
|
||||||
|
source,
|
||||||
|
/proxy\.\$auth\.hasPermiAnd\(\['business:inbound:query', 'business:inbound:confirm'\]\)/
|
||||||
|
)
|
||||||
const addButton = extractButtonBlocks(source, 'handleAdd')[0]
|
const addButton = extractButtonBlocks(source, 'handleAdd')[0]
|
||||||
assert.match(addButton, /:disabled="[^"]*operationPending[^"]*optionLoading[^"]*detailLoading[^"]*open[^"]*"/)
|
assert.match(addButton, /:disabled="[^"]*operationPending[^"]*optionLoading[^"]*detailLoading[^"]*open[^"]*"/)
|
||||||
const addSource = extractNamedFunction(source, 'handleAdd')
|
const addSource = extractNamedFunction(source, 'handleAdd')
|
||||||
@@ -1143,6 +1150,7 @@ test('入库页面只允许 DRAFT 变更并以 authoritative 详情和独立确
|
|||||||
assert.match(ensureSource, /createIdempotencyKey\(\)/)
|
assert.match(ensureSource, /createIdempotencyKey\(\)/)
|
||||||
assert.match(ensureSource, /confirmIdempotency\.key/)
|
assert.match(ensureSource, /confirmIdempotency\.key/)
|
||||||
const confirmSource = extractNamedFunction(source, 'handleConfirm')
|
const confirmSource = extractNamedFunction(source, 'handleConfirm')
|
||||||
|
assert.doesNotMatch(confirmSource, /canConfirmInbound|business:inbound:query/)
|
||||||
assert.ok(
|
assert.ok(
|
||||||
confirmSource.indexOf('confirmLoading.value = true') < confirmSource.indexOf('proxy.$modal.confirm('),
|
confirmSource.indexOf('confirmLoading.value = true') < confirmSource.indexOf('proxy.$modal.confirm('),
|
||||||
'入库确认必须在打开二次确认框前加锁'
|
'入库确认必须在打开二次确认框前加锁'
|
||||||
@@ -1155,6 +1163,16 @@ test('入库页面只允许 DRAFT 变更并以 authoritative 详情和独立确
|
|||||||
assert.doesNotMatch(confirmCatch, /clearConfirmIdempotency\(\)[\s\S]*?(?:loadError|msgError)/)
|
assert.doesNotMatch(confirmCatch, /clearConfirmIdempotency\(\)[\s\S]*?(?:loadError|msgError)/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('装填扫码 pending 期间禁用全部业务输入', async () => {
|
||||||
|
const source = await readFile(path.join(frontendRoot, businessPageContracts.filling.relativePath), 'utf8')
|
||||||
|
|
||||||
|
for (const field of ['strainId', 'batchNo', 'packageSpec', 'initialPackages']) {
|
||||||
|
const businessControl = source.match(new RegExp(`<[^>]+v-model="form\\.${field}"[^>]*>`))?.[0]
|
||||||
|
assert.ok(businessControl, `缺少装填 ${field} 业务控件`)
|
||||||
|
assert.match(businessControl, /:disabled="[^"]*scanLoading[^"]*"/, `装填扫码 pending 时必须禁用 ${field}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('装填页面锁定扫码上下文、校验正整数并在失败重试时保留幂等键', async () => {
|
test('装填页面锁定扫码上下文、校验正整数并在失败重试时保留幂等键', async () => {
|
||||||
const source = await readFile(path.join(frontendRoot, businessPageContracts.filling.relativePath), 'utf8')
|
const source = await readFile(path.join(frontendRoot, businessPageContracts.filling.relativePath), 'utf8')
|
||||||
|
|
||||||
@@ -1166,42 +1184,59 @@ test('装填页面锁定扫码上下文、校验正整数并在失败重试时
|
|||||||
assert.match(source, /pallet\.palletCode \|\| `#\$\{pallet\.palletId\}`/)
|
assert.match(source, /pallet\.palletCode \|\| `#\$\{pallet\.palletId\}`/)
|
||||||
assert.match(source, /getFillingStrainOptions\(\)/)
|
assert.match(source, /getFillingStrainOptions\(\)/)
|
||||||
|
|
||||||
|
const clearPayloadSource = extractNamedFunction(source, 'clearFillingPayload')
|
||||||
|
assert.match(clearPayloadSource, /clearFillingIdempotencyKey\(\)/)
|
||||||
|
assert.match(clearPayloadSource, /scannedPallet\.value = null/)
|
||||||
|
for (const [field, emptyValue] of [
|
||||||
|
['qrToken', "''"],
|
||||||
|
['warehouseId', 'undefined'],
|
||||||
|
['strainId', 'undefined'],
|
||||||
|
['batchNo', "''"],
|
||||||
|
['packageSpec', "''"],
|
||||||
|
['initialPackages', 'undefined']
|
||||||
|
]) {
|
||||||
|
const fieldPattern = new RegExp(`(?:form\\.value\\.${field}\\s*=\\s*${emptyValue}|${field}:\\s*${emptyValue})`)
|
||||||
|
assert.match(clearPayloadSource, fieldPattern, `装填载荷清理必须重置 ${field}`)
|
||||||
|
}
|
||||||
|
assert.match(extractNamedFunction(source, 'resetFillingOperation'), /clearFillingPayload\(\)/)
|
||||||
|
|
||||||
const scanSource = extractNamedFunction(source, 'handleFillingScan')
|
const scanSource = extractNamedFunction(source, 'handleFillingScan')
|
||||||
const scanCallIndex = scanSource.indexOf('scanFillingPallet(')
|
const scanCallIndex = scanSource.indexOf('scanFillingPallet(')
|
||||||
assert.ok(scanCallIndex >= 0, '装填扫码必须调用 scanFillingPallet')
|
assert.ok(scanCallIndex >= 0, '装填扫码必须调用 scanFillingPallet')
|
||||||
const scanPrefix = scanSource.slice(0, scanCallIndex)
|
const scanPrefix = scanSource.slice(0, scanCallIndex)
|
||||||
const clearKeyIndex = scanPrefix.indexOf('clearFillingIdempotencyKey()')
|
const clearPayloadIndex = scanPrefix.indexOf('clearFillingPayload()')
|
||||||
const scanPendingIndex = scanPrefix.indexOf('scanLoading.value = true')
|
const scanPendingIndex = scanPrefix.indexOf('scanLoading.value = true')
|
||||||
assert.ok(
|
assert.ok(
|
||||||
clearKeyIndex >= 0 && scanPendingIndex >= 0 && clearKeyIndex < scanPendingIndex,
|
clearPayloadIndex >= 0 && scanPendingIndex >= 0 && clearPayloadIndex < scanPendingIndex,
|
||||||
'新装填扫码必须在进入 pending 前明确清除旧幂等键'
|
'新装填扫码必须在进入 pending 前清除旧业务载荷'
|
||||||
|
)
|
||||||
|
const scanSuccessSource = extractPromiseCallback(scanSource, 'then')
|
||||||
|
const scanSuccessGuardIndex = scanSuccessSource.indexOf('if (!isCurrentScanRequest(scanContext)) return')
|
||||||
|
const invalidStateIndex = scanSuccessSource.indexOf("if (pallet.flowState !== 'EMPTY_IN_WAREHOUSE')")
|
||||||
|
const invalidStateClearIndex = scanSuccessSource.indexOf('clearFillingPayload()', invalidStateIndex)
|
||||||
|
const invalidStateErrorIndex = scanSuccessSource.indexOf("scanError.value = '该托盘当前不可装填'", invalidStateIndex)
|
||||||
|
assert.ok(
|
||||||
|
scanSuccessGuardIndex >= 0 &&
|
||||||
|
invalidStateIndex > scanSuccessGuardIndex &&
|
||||||
|
invalidStateClearIndex > invalidStateIndex &&
|
||||||
|
invalidStateErrorIndex > invalidStateClearIndex,
|
||||||
|
'不可装填响应必须在当前请求门禁后、写入错误状态前清除业务载荷'
|
||||||
|
)
|
||||||
|
const scanCatchSource = extractPromiseCallback(scanSource, 'catch')
|
||||||
|
const scanCatchGuardIndex = scanCatchSource.indexOf('if (!isCurrentScanRequest(scanContext)) return')
|
||||||
|
const scanCatchClearIndex = scanCatchSource.indexOf('clearFillingPayload()')
|
||||||
|
const scanCatchErrorIndex = scanCatchSource.indexOf("scanError.value = '托盘扫码校验失败,请检查后重试'")
|
||||||
|
assert.ok(
|
||||||
|
scanCatchGuardIndex >= 0 && scanCatchClearIndex > scanCatchGuardIndex && scanCatchErrorIndex > scanCatchClearIndex,
|
||||||
|
'装填扫码异常必须在当前请求门禁后、写入错误状态前清除业务载荷'
|
||||||
)
|
)
|
||||||
assert.match(scanPrefix, /scannedPallet\.value = null/, '新装填扫码前必须清除旧托盘')
|
|
||||||
for (const [field, emptyValue] of [
|
|
||||||
['qrToken', "''"],
|
|
||||||
['warehouseId', 'undefined'],
|
|
||||||
['strainId', 'undefined'],
|
|
||||||
['batchNo', "''"],
|
|
||||||
['packageSpec', "''"],
|
|
||||||
['initialPackages', 'undefined']
|
|
||||||
]) {
|
|
||||||
const fieldPattern = new RegExp(`(?:form\\.value\\.${field}\\s*=\\s*${emptyValue}|${field}:\\s*${emptyValue})`)
|
|
||||||
assert.match(scanPrefix, fieldPattern, `新装填扫码前必须清除旧 ${field}`)
|
|
||||||
}
|
|
||||||
const invalidSource = extractNamedFunction(source, 'handleScanInvalid')
|
const invalidSource = extractNamedFunction(source, 'handleScanInvalid')
|
||||||
assert.match(invalidSource, /clearFillingIdempotencyKey\(\)/)
|
const invalidClearIndex = invalidSource.indexOf('clearFillingPayload()')
|
||||||
assert.match(invalidSource, /scannedPallet\.value = null/)
|
const invalidErrorIndex = invalidSource.indexOf('scanError.value = message')
|
||||||
for (const [field, emptyValue] of [
|
assert.ok(
|
||||||
['qrToken', "''"],
|
invalidClearIndex >= 0 && invalidErrorIndex > invalidClearIndex,
|
||||||
['warehouseId', 'undefined'],
|
'装填扫码输入失败后必须先清除业务载荷再展示错误'
|
||||||
['strainId', 'undefined'],
|
)
|
||||||
['batchNo', "''"],
|
|
||||||
['packageSpec', "''"],
|
|
||||||
['initialPackages', 'undefined']
|
|
||||||
]) {
|
|
||||||
const fieldPattern = new RegExp(`(?:form\\.value\\.${field}\\s*=\\s*${emptyValue}|${field}:\\s*${emptyValue})`)
|
|
||||||
assert.match(invalidSource, fieldPattern, `装填扫码输入失败后必须清除旧 ${field}`)
|
|
||||||
}
|
|
||||||
const fillingSubmitButton = extractButtonBlocks(source, 'submitFilling')[0]
|
const fillingSubmitButton = extractButtonBlocks(source, 'submitFilling')[0]
|
||||||
assert.match(fillingSubmitButton, /:disabled="[^"]*!scannedPallet[^"]*"/)
|
assert.match(fillingSubmitButton, /:disabled="[^"]*!scannedPallet[^"]*"/)
|
||||||
|
|
||||||
@@ -1225,6 +1260,18 @@ test('装填页面锁定扫码上下文、校验正整数并在失败重试时
|
|||||||
assert.match(source, /watch\([\s\S]*?if \(!submitLoading\.value\) clearFillingIdempotencyKey\(\)/)
|
assert.match(source, /watch\([\s\S]*?if \(!submitLoading\.value\) clearFillingIdempotencyKey\(\)/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('发货详情仅在 remainingPackages 缺失时回退快照并保留 null', async () => {
|
||||||
|
const source = await readFile(path.join(frontendRoot, businessPageContracts.shipment.relativePath), 'utf8')
|
||||||
|
const detailSuccessSource = extractPromiseCallback(extractNamedFunction(source, 'handleUpdate'), 'then')
|
||||||
|
|
||||||
|
assert.match(
|
||||||
|
detailSuccessSource,
|
||||||
|
/remainingPackages:\s*item\.remainingPackages\s*===\s*undefined\s*\?\s*\(?\s*item\.packageQty\s*\?\?\s*null\s*\)?\s*:\s*item\.remainingPackages/,
|
||||||
|
'发货详情仅在 remainingPackages 缺失时回退确认快照 packageQty,并保留 null'
|
||||||
|
)
|
||||||
|
assert.doesNotMatch(detailSuccessSource, /item\.remainingPackages\s*\?\?\s*item\.packageQty/)
|
||||||
|
})
|
||||||
|
|
||||||
test('发货页面只允许 DRAFT 变更、展示只读余量并复用确认幂等键', async () => {
|
test('发货页面只允许 DRAFT 变更、展示只读余量并复用确认幂等键', async () => {
|
||||||
const source = await readFile(path.join(frontendRoot, businessPageContracts.shipment.relativePath), 'utf8')
|
const source = await readFile(path.join(frontendRoot, businessPageContracts.shipment.relativePath), 'utf8')
|
||||||
|
|
||||||
@@ -1235,6 +1282,13 @@ test('发货页面只允许 DRAFT 变更、展示只读余量并复用确认幂
|
|||||||
assertButtonsUsePermission(source, 'handleConfirm', 'business:shipment:confirm')
|
assertButtonsUsePermission(source, 'handleConfirm', 'business:shipment:confirm')
|
||||||
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:shipment:query', 'business:shipment:add'\]\)/)
|
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:shipment:query', 'business:shipment:add'\]\)/)
|
||||||
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:shipment:query', 'business:shipment:edit'\]\)/)
|
assert.match(source, /proxy\.\$auth\.hasPermiAnd\(\['business:shipment:query', 'business:shipment:edit'\]\)/)
|
||||||
|
const confirmButton = extractButtonBlocks(source, 'handleConfirm')[0]
|
||||||
|
assert.match(confirmButton, /v-if="scope\.row\.status === 'DRAFT'"/)
|
||||||
|
assert.doesNotMatch(source, /canConfirmShipment/)
|
||||||
|
assert.doesNotMatch(
|
||||||
|
source,
|
||||||
|
/proxy\.\$auth\.hasPermiAnd\(\['business:shipment:query', 'business:shipment:confirm'\]\)/
|
||||||
|
)
|
||||||
const addButton = extractButtonBlocks(source, 'handleAdd')[0]
|
const addButton = extractButtonBlocks(source, 'handleAdd')[0]
|
||||||
assert.match(addButton, /:disabled="[^"]*operationPending[^"]*optionLoading[^"]*detailLoading[^"]*open[^"]*"/)
|
assert.match(addButton, /:disabled="[^"]*operationPending[^"]*optionLoading[^"]*detailLoading[^"]*open[^"]*"/)
|
||||||
const addSource = extractNamedFunction(source, 'handleAdd')
|
const addSource = extractNamedFunction(source, 'handleAdd')
|
||||||
@@ -1298,17 +1352,13 @@ test('发货页面只允许 DRAFT 变更、展示只读余量并复用确认幂
|
|||||||
assert.match(source, /const detail = response\.data;/)
|
assert.match(source, /const detail = response\.data;/)
|
||||||
assert.match(source, /\(Array\.isArray\(detail\.items\) \? detail\.items : \[\]\)\.map\(\(item\) => \(\{[\s\S]*?palletId: item\.palletId/)
|
assert.match(source, /\(Array\.isArray\(detail\.items\) \? detail\.items : \[\]\)\.map\(\(item\) => \(\{[\s\S]*?palletId: item\.palletId/)
|
||||||
assert.match(source, /item\.palletCode \|\| `#\$\{item\.palletId\}`/)
|
assert.match(source, /item\.palletCode \|\| `#\$\{item\.palletId\}`/)
|
||||||
assert.match(
|
|
||||||
detailSuccessSource,
|
|
||||||
/remainingPackages:\s*item\.remainingPackages\s*\?\?\s*item\.packageQty\s*\?\?\s*null/,
|
|
||||||
'发货详情必须优先使用当前余量,仅以确认快照 packageQty 回退'
|
|
||||||
)
|
|
||||||
assert.doesNotMatch(source, /remainingPackages\s*[-+]=|Math\.(?:max|min)\([^)]*remainingPackages/)
|
assert.doesNotMatch(source, /remainingPackages\s*[-+]=|Math\.(?:max|min)\([^)]*remainingPackages/)
|
||||||
assert.match(extractNamedFunction(source, 'handleShipmentScan'), /remainingPackages:\s*pallet\.remainingPackages/)
|
assert.match(extractNamedFunction(source, 'handleShipmentScan'), /remainingPackages:\s*pallet\.remainingPackages/)
|
||||||
|
|
||||||
const ensureSource = extractNamedFunction(source, 'ensureConfirmIdempotencyKey')
|
const ensureSource = extractNamedFunction(source, 'ensureConfirmIdempotencyKey')
|
||||||
assert.match(ensureSource, /createIdempotencyKey\(\)/)
|
assert.match(ensureSource, /createIdempotencyKey\(\)/)
|
||||||
const confirmSource = extractNamedFunction(source, 'handleConfirm')
|
const confirmSource = extractNamedFunction(source, 'handleConfirm')
|
||||||
|
assert.doesNotMatch(confirmSource, /canConfirmShipment|business:shipment:query/)
|
||||||
assert.ok(
|
assert.ok(
|
||||||
confirmSource.indexOf('confirmLoading.value = true') < confirmSource.indexOf('proxy.$modal.confirm('),
|
confirmSource.indexOf('confirmLoading.value = true') < confirmSource.indexOf('proxy.$modal.confirm('),
|
||||||
'发货确认必须在打开二次确认框前加锁'
|
'发货确认必须在打开二次确认框前加锁'
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
filterable
|
filterable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:loading="optionLoading"
|
:loading="optionLoading"
|
||||||
:disabled="operationPending || optionLoading"
|
:disabled="operationPending || scanLoading || optionLoading"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="option in strainOptions"
|
v-for="option in strainOptions"
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
maxlength="64"
|
maxlength="64"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
placeholder="请输入生产批次"
|
placeholder="请输入生产批次"
|
||||||
:disabled="operationPending"
|
:disabled="operationPending || scanLoading"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="包装规格" prop="packageSpec">
|
<el-form-item label="包装规格" prop="packageSpec">
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
maxlength="64"
|
maxlength="64"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
placeholder="请输入包装规格"
|
placeholder="请输入包装规格"
|
||||||
:disabled="operationPending"
|
:disabled="operationPending || scanLoading"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="初始包数" prop="initialPackages">
|
<el-form-item label="初始包数" prop="initialPackages">
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
:precision="0"
|
:precision="0"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:disabled="operationPending"
|
:disabled="operationPending || scanLoading"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -285,6 +285,19 @@ function clearFillingIdempotencyKey() {
|
|||||||
fillingIdempotencyKey.value = ''
|
fillingIdempotencyKey.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearFillingPayload() {
|
||||||
|
clearFillingIdempotencyKey()
|
||||||
|
scannedPallet.value = null
|
||||||
|
form.value = {
|
||||||
|
qrToken: '',
|
||||||
|
warehouseId: undefined,
|
||||||
|
strainId: undefined,
|
||||||
|
batchNo: '',
|
||||||
|
packageSpec: '',
|
||||||
|
initialPackages: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function ensureFillingIdempotencyKey() {
|
function ensureFillingIdempotencyKey() {
|
||||||
if (!fillingIdempotencyKey.value) {
|
if (!fillingIdempotencyKey.value) {
|
||||||
fillingIdempotencyKey.value = createIdempotencyKey()
|
fillingIdempotencyKey.value = createIdempotencyKey()
|
||||||
@@ -296,9 +309,7 @@ function resetFillingOperation() {
|
|||||||
dialogSession += 1
|
dialogSession += 1
|
||||||
invalidateOptionRequest()
|
invalidateOptionRequest()
|
||||||
invalidateScanRequest()
|
invalidateScanRequest()
|
||||||
clearFillingIdempotencyKey()
|
clearFillingPayload()
|
||||||
scannedPallet.value = null
|
|
||||||
form.value = { qrToken: '', warehouseId: undefined, strainId: undefined, batchNo: '', packageSpec: '', initialPackages: undefined }
|
|
||||||
optionError.value = ''
|
optionError.value = ''
|
||||||
scanError.value = ''
|
scanError.value = ''
|
||||||
formError.value = ''
|
formError.value = ''
|
||||||
@@ -337,9 +348,7 @@ function resetQuery() {
|
|||||||
|
|
||||||
function handleFillingScan(qrToken) {
|
function handleFillingScan(qrToken) {
|
||||||
if (operationPending.value || scanLoading.value) return
|
if (operationPending.value || scanLoading.value) return
|
||||||
clearFillingIdempotencyKey()
|
clearFillingPayload()
|
||||||
scannedPallet.value = null
|
|
||||||
form.value = { qrToken: '', warehouseId: undefined, strainId: undefined, batchNo: '', packageSpec: '', initialPackages: undefined }
|
|
||||||
const scanContext = { generation: ++scanGeneration, dialogSession, qrToken }
|
const scanContext = { generation: ++scanGeneration, dialogSession, qrToken }
|
||||||
scanLoading.value = true
|
scanLoading.value = true
|
||||||
scanError.value = ''
|
scanError.value = ''
|
||||||
@@ -347,6 +356,7 @@ function handleFillingScan(qrToken) {
|
|||||||
if (!isCurrentScanRequest(scanContext)) return
|
if (!isCurrentScanRequest(scanContext)) return
|
||||||
const pallet = response.data
|
const pallet = response.data
|
||||||
if (pallet.flowState !== 'EMPTY_IN_WAREHOUSE') {
|
if (pallet.flowState !== 'EMPTY_IN_WAREHOUSE') {
|
||||||
|
clearFillingPayload()
|
||||||
scanError.value = '该托盘当前不可装填'
|
scanError.value = '该托盘当前不可装填'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -361,6 +371,7 @@ function handleFillingScan(qrToken) {
|
|||||||
form.value.warehouseId = pallet.warehouseId
|
form.value.warehouseId = pallet.warehouseId
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
if (!isCurrentScanRequest(scanContext)) return
|
if (!isCurrentScanRequest(scanContext)) return
|
||||||
|
clearFillingPayload()
|
||||||
scanError.value = '托盘扫码校验失败,请检查后重试'
|
scanError.value = '托盘扫码校验失败,请检查后重试'
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
if (!isCurrentScanRequest(scanContext)) return
|
if (!isCurrentScanRequest(scanContext)) return
|
||||||
@@ -369,9 +380,7 @@ function handleFillingScan(qrToken) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleScanInvalid(message) {
|
function handleScanInvalid(message) {
|
||||||
clearFillingIdempotencyKey()
|
clearFillingPayload()
|
||||||
scannedPallet.value = null
|
|
||||||
form.value = { qrToken: '', warehouseId: undefined, strainId: undefined, batchNo: '', packageSpec: '', initialPackages: undefined }
|
|
||||||
scanError.value = message
|
scanError.value = message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
v-hasPermi="['business:inbound:remove']"
|
v-hasPermi="['business:inbound:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 'DRAFT' && canConfirmInbound"
|
v-if="scope.row.status === 'DRAFT'"
|
||||||
link
|
link
|
||||||
type="success"
|
type="success"
|
||||||
icon="CircleCheck"
|
icon="CircleCheck"
|
||||||
@@ -232,7 +232,6 @@ const editDetailReady = ref(false)
|
|||||||
const isEdit = computed(() => Boolean(form.value.inboundId))
|
const isEdit = computed(() => Boolean(form.value.inboundId))
|
||||||
const canAddInbound = computed(() => proxy.$auth.hasPermiAnd(['business:inbound:query', 'business:inbound:add']))
|
const canAddInbound = computed(() => proxy.$auth.hasPermiAnd(['business:inbound:query', 'business:inbound:add']))
|
||||||
const canEditInbound = computed(() => proxy.$auth.hasPermiAnd(['business:inbound:query', 'business:inbound:edit']))
|
const canEditInbound = computed(() => proxy.$auth.hasPermiAnd(['business:inbound:query', 'business:inbound:edit']))
|
||||||
const canConfirmInbound = computed(() => proxy.$auth.hasPermiAnd(['business:inbound:query', 'business:inbound:confirm']))
|
|
||||||
const operationPending = computed(() => submitLoading.value || deleteLoading.value || confirmLoading.value)
|
const operationPending = computed(() => submitLoading.value || deleteLoading.value || confirmLoading.value)
|
||||||
let listGeneration = 0
|
let listGeneration = 0
|
||||||
let optionGeneration = 0
|
let optionGeneration = 0
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
v-hasPermi="['business:shipment:remove']"
|
v-hasPermi="['business:shipment:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 'DRAFT' && canConfirmShipment"
|
v-if="scope.row.status === 'DRAFT'"
|
||||||
link
|
link
|
||||||
type="success"
|
type="success"
|
||||||
icon="CircleCheck"
|
icon="CircleCheck"
|
||||||
@@ -245,7 +245,6 @@ const editDetailReady = ref(false)
|
|||||||
const isEdit = computed(() => Boolean(form.value.shipmentId))
|
const isEdit = computed(() => Boolean(form.value.shipmentId))
|
||||||
const canAddShipment = computed(() => proxy.$auth.hasPermiAnd(['business:shipment:query', 'business:shipment:add']))
|
const canAddShipment = computed(() => proxy.$auth.hasPermiAnd(['business:shipment:query', 'business:shipment:add']))
|
||||||
const canEditShipment = computed(() => proxy.$auth.hasPermiAnd(['business:shipment:query', 'business:shipment:edit']))
|
const canEditShipment = computed(() => proxy.$auth.hasPermiAnd(['business:shipment:query', 'business:shipment:edit']))
|
||||||
const canConfirmShipment = computed(() => proxy.$auth.hasPermiAnd(['business:shipment:query', 'business:shipment:confirm']))
|
|
||||||
const operationPending = computed(() => submitLoading.value || deleteLoading.value || confirmLoading.value)
|
const operationPending = computed(() => submitLoading.value || deleteLoading.value || confirmLoading.value)
|
||||||
let listGeneration = 0
|
let listGeneration = 0
|
||||||
let optionGeneration = 0
|
let optionGeneration = 0
|
||||||
@@ -429,7 +428,10 @@ function handleUpdate(row) {
|
|||||||
strainCode: item.strainCode,
|
strainCode: item.strainCode,
|
||||||
strainName: item.strainName,
|
strainName: item.strainName,
|
||||||
batchNo: item.batchNo,
|
batchNo: item.batchNo,
|
||||||
remainingPackages: item.remainingPackages ?? item.packageQty ?? null
|
remainingPackages:
|
||||||
|
item.remainingPackages === undefined
|
||||||
|
? (item.packageQty ?? null)
|
||||||
|
: item.remainingPackages
|
||||||
}))
|
}))
|
||||||
hydratingForm = false
|
hydratingForm = false
|
||||||
editDetailReady.value = true
|
editDetailReady.value = true
|
||||||
|
|||||||
Reference in New Issue
Block a user