优化
This commit is contained in:
@@ -21,8 +21,10 @@ import {
|
||||
type ServiceType = 'labeling' | 'transfer' | 'disposal' | 'relabel'
|
||||
type PageMode = 'list' | 'create' | 'detail'
|
||||
type LabelingMode = 'carton' | 'sku' | 'carton_and_sku'
|
||||
interface CargoRow { id: number; sku: string; name: string; quantity: number; availableQuantity?: number; sourceOrderId?: string; sourceInventoryBalanceId?: string; sourceInventoryPositionId?: string; sourceInboundOrderId?: string; sourceInboundOrderNo?: string; sourceInboundCode?: string; sourceWarehouseName?: string; palletNo?: string; warehouseLocationCode?: string; fnsku: string; shipmentNo: string; newSkuCode: string; shippingMark: string; cartonMark: string; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
|
||||
type RelabelTemplateType = 'carton' | 'sku' | 'mixed'
|
||||
interface CargoRow { id: number; included?: boolean; sku: string; name: string; quantity: number; availableQuantity?: number; sourceOrderId?: string; sourceInventoryBalanceId?: string; sourceInventoryPositionId?: string; sourceInboundOrderId?: string; sourceInboundOrderNo?: string; sourceInboundCode?: string; sourceWarehouseName?: string; palletNo?: string; warehouseLocationCode?: string; fnsku: string; shipmentNo: string; newSkuCode: string; shippingMark: string; cartonMark: string; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
|
||||
interface SkuRelabelRow { id: number; sourceRowId: number | null; cartonMark: string; originalSku: string; newSku: string; quantity: number; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
|
||||
interface ImportedRelabelBinding extends SkuRelabelRow { templateType: RelabelTemplateType; selected: boolean; shipmentNo: string }
|
||||
interface ServiceConfig { title: string; createTitle: string; numberLabel: string; emptyText: string; columns: string[] }
|
||||
|
||||
const props = defineProps<{ service: ServiceType }>()
|
||||
@@ -54,6 +56,8 @@ const cargoRows = ref<CargoRow[]>([])
|
||||
const labelingMode = ref<LabelingMode>('carton')
|
||||
const shippingLabelFile = ref<File | null>(null)
|
||||
const skuRelabelRows = ref<SkuRelabelRow[]>([])
|
||||
const importedRelabelBindings = ref<ImportedRelabelBinding[]>([])
|
||||
const cartonDetailRows = computed(() => cargoRows.value.filter((row) => row.included))
|
||||
const labelingModeHint = computed(() => labelingMode.value === 'carton'
|
||||
? '只替换外箱箱唛,不修改箱内商品 SKU 标签;按箱填写新的 FBA 箱唛和目的仓。'
|
||||
: labelingMode.value === 'sku'
|
||||
@@ -89,7 +93,9 @@ const relabelInboundOptions = computed(() => {
|
||||
})
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const templateInput = ref<HTMLInputElement | null>(null)
|
||||
const cartonTemplateInput = ref<HTMLInputElement | null>(null)
|
||||
const skuTemplateInput = ref<HTMLInputElement | null>(null)
|
||||
const mixedTemplateInput = ref<HTMLInputElement | null>(null)
|
||||
let cargoSequence = 0
|
||||
let skuRelabelSequence = 0
|
||||
|
||||
@@ -102,6 +108,7 @@ function resetForm() {
|
||||
cargoRows.value = []
|
||||
labelingMode.value = 'carton'
|
||||
skuRelabelRows.value = []
|
||||
importedRelabelBindings.value = []
|
||||
discardCandidates.value = []
|
||||
selectedDiscardOrderId.value = ''
|
||||
relabelCandidates.value = []
|
||||
@@ -127,6 +134,22 @@ function addSkuRelabelRow() {
|
||||
fbaCartonMark: '', destinationWarehouseId: source?.destinationWarehouseId || '', remark: '' })
|
||||
}
|
||||
function removeSkuRelabelRow(id: number) { skuRelabelRows.value = skuRelabelRows.value.filter((row) => row.id !== id) }
|
||||
function applyExistingSkuBinding(row: SkuRelabelRow) {
|
||||
if (!row.originalSku.trim() || row.newSku.trim()) return
|
||||
const mapping = skuRelabelRows.value.find((item) => item.id !== row.id
|
||||
&& item.originalSku.trim().toUpperCase() === row.originalSku.trim().toUpperCase() && item.newSku.trim())
|
||||
if (mapping) row.newSku = mapping.newSku
|
||||
}
|
||||
function applyExistingCartonBinding(row: SkuRelabelRow) {
|
||||
if (!row.cartonMark.trim()) return
|
||||
const cartonMark = row.cartonMark.trim().toUpperCase()
|
||||
const mapping = cargoRows.value.find((item) => item.cartonMark.trim().toUpperCase() === cartonMark && item.fbaCartonMark.trim())
|
||||
|| skuRelabelRows.value.find((item) => item.id !== row.id
|
||||
&& item.cartonMark.trim().toUpperCase() === cartonMark && item.fbaCartonMark.trim())
|
||||
if (!mapping) return
|
||||
if (!row.fbaCartonMark.trim()) row.fbaCartonMark = mapping.fbaCartonMark
|
||||
if (!row.destinationWarehouseId) row.destinationWarehouseId = mapping.destinationWarehouseId
|
||||
}
|
||||
function selectShippingLabel(event: Event) { shippingLabelFile.value = (event.target as HTMLInputElement).files?.[0] || null }
|
||||
function buildSkuRelabelItems(): RelabelCreate['items'] {
|
||||
const groups = new Map<string, SkuRelabelRow[]>()
|
||||
@@ -145,7 +168,7 @@ function buildSkuRelabelItems(): RelabelCreate['items'] {
|
||||
throw new Error('填写的箱唛数量超过当前入仓单可用库存箱数')
|
||||
}
|
||||
return [...groups.entries()].map(([_, rows], groupIndex) => {
|
||||
const source = anchors[groupIndex]
|
||||
const source = cargoRows.value.find((item) => item.id === rows[0].sourceRowId) || anchors[groupIndex]
|
||||
if (!source?.sourceInventoryBalanceId || !source.sourceInventoryPositionId || !source.sourceInboundOrderId) {
|
||||
throw new Error('来源库存已变化,请重新选择有库存的历史入仓单')
|
||||
}
|
||||
@@ -180,32 +203,40 @@ function buildSkuRelabelItems(): RelabelCreate['items'] {
|
||||
}
|
||||
function addRelabelCargoRow() {
|
||||
if (!selectedRelabelInboundOrderId.value) { ElMessage.warning('请先选择有库存的历史入仓单'); return }
|
||||
ElMessage.info('货物明细已按所选入仓单的可用库存带出,请直接编辑现有明细')
|
||||
const source = cargoRows.value.find((row) => !row.included)
|
||||
if (!source) { ElMessage.warning('所选入仓单没有更多可添加的库存箱'); return }
|
||||
source.included = true
|
||||
}
|
||||
function removeCargoRow(id: number) {
|
||||
const item = cargoRows.value.find((row) => row.id === id)
|
||||
if (props.service === 'labeling' && item?.sourceInventoryBalanceId) {
|
||||
Object.assign(item, { included: false, shipmentNo: '', cartonMark: '', fbaCartonMark: '', destinationWarehouseId: '', remark: '' })
|
||||
return
|
||||
}
|
||||
cargoRows.value = cargoRows.value.filter((row) => row.id !== id)
|
||||
}
|
||||
function clearRelabelRows() { cargoRows.value = []; selectedRelabelInboundOrderId.value = '' }
|
||||
function clearRelabelRows() {
|
||||
for (const row of cargoRows.value) Object.assign(row, { included: false, shipmentNo: '', cartonMark: '', fbaCartonMark: '', destinationWarehouseId: '', remark: '' })
|
||||
}
|
||||
function csvCell(value: string | number | undefined) { return `"${String(value ?? '').replaceAll('"', '""')}"` }
|
||||
function downloadRelabelTemplate() {
|
||||
function downloadRelabelTemplate(templateType: RelabelTemplateType) {
|
||||
if (!cargoRows.value.length) { ElMessage.warning('请先选择有库存的历史入仓单'); return }
|
||||
const cartonTemplate = labelingMode.value === 'carton'
|
||||
const combinedTemplate = labelingMode.value === 'carton_and_sku'
|
||||
const cartonTemplate = templateType === 'carton'
|
||||
const mixedTemplate = templateType === 'mixed'
|
||||
const header = cartonTemplate
|
||||
? ['明细行标识', '本次箱数', '商品SKU', '中文品名', 'FBA货件编号', '我方箱唛', 'FBA箱唛', 'FBA目的仓', '备注']
|
||||
: ['我方箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)',
|
||||
...(combinedTemplate ? ['新FBA箱唛', 'FBA目的仓'] : []), '备注']
|
||||
const rows = cartonTemplate
|
||||
? cargoRows.value.map((item) => [item.id, item.quantity, item.sku, item.name, item.shipmentNo,
|
||||
item.cartonMark, item.fbaCartonMark, item.destinationWarehouseId, item.remark])
|
||||
: skuRelabelRows.value.map((item) => [item.cartonMark, item.originalSku, item.newSku, item.quantity,
|
||||
...(combinedTemplate ? [item.fbaCartonMark, item.destinationWarehouseId] : []), item.remark])
|
||||
? ['明细行标识', '旧箱唛', '新FBA箱唛', 'FBA目的仓', 'FBA货件编号', '备注']
|
||||
: ['明细行标识', '旧箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)',
|
||||
...(mixedTemplate ? ['新FBA箱唛', 'FBA目的仓', 'FBA货件编号'] : []), '备注']
|
||||
const rows = cargoRows.value.map((item) => cartonTemplate
|
||||
? [item.id, item.cartonMark, item.fbaCartonMark, item.destinationWarehouseId, item.shipmentNo, item.remark]
|
||||
: [item.id, item.cartonMark, item.sku, '', 1,
|
||||
...(mixedTemplate ? [item.fbaCartonMark, item.destinationWarehouseId, item.shipmentNo] : []), item.remark])
|
||||
const blob = new Blob([`\uFEFF${[header, ...rows].map((row) => row.map(csvCell).join(',')).join('\r\n')}\r\n`], { type: 'text/csv;charset=utf-8' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const anchor = document.createElement('a')
|
||||
anchor.href = url
|
||||
anchor.download = cartonTemplate ? '贴标申请-箱唛换标模板.csv'
|
||||
: combinedTemplate ? '贴标申请-SKU和箱唛换标模板.csv' : '贴标申请-SKU换标模板.csv'
|
||||
anchor.download = cartonTemplate ? '贴标申请-箱号关联模板.csv'
|
||||
: mixedTemplate ? '贴标申请-SKU混箱换标模板.csv' : '贴标申请-SKU关联模板.csv'
|
||||
anchor.click(); URL.revokeObjectURL(url)
|
||||
}
|
||||
function parseCsvLine(line: string) {
|
||||
@@ -218,76 +249,112 @@ function parseCsvLine(line: string) {
|
||||
}
|
||||
values.push(value.trim()); return values
|
||||
}
|
||||
async function importRelabelTemplate(event: Event) {
|
||||
async function importRelabelTemplate(event: Event, templateType: RelabelTemplateType) {
|
||||
const input = event.target as HTMLInputElement; const file = input.files?.[0]; input.value = ''
|
||||
if (!file) return
|
||||
const lines = (await file.text()).replace(/^\uFEFF/, '').split(/\r?\n/).filter((line) => line.trim())
|
||||
if (lines.length < 2) { ElMessage.error('模板中没有可导入的明细'); return }
|
||||
const headers = parseCsvLine(lines[0])
|
||||
if (labelingMode.value !== 'carton') {
|
||||
const combinedTemplate = labelingMode.value === 'carton_and_sku'
|
||||
const required = ['我方箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)',
|
||||
...(combinedTemplate ? ['新FBA箱唛', 'FBA目的仓'] : [])]
|
||||
if (templateType !== 'carton') {
|
||||
const mixedTemplate = templateType === 'mixed'
|
||||
const required = ['明细行标识', '旧箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)',
|
||||
...(mixedTemplate ? ['新FBA箱唛', 'FBA目的仓', 'FBA货件编号'] : [])]
|
||||
if (required.some((name) => !headers.includes(name))) {
|
||||
ElMessage.error('SKU 换标模板格式不正确,请重新下载当前换标类型的模板'); return
|
||||
ElMessage.error('SKU 关联模板格式不正确,请重新下载 SKU 关联模板'); return
|
||||
}
|
||||
const imported = lines.slice(1).map(parseCsvLine)
|
||||
.map((values) => Object.fromEntries(headers.map((key, index) => [key, values[index] || ''])))
|
||||
.filter((item) => Object.values(item).some(Boolean))
|
||||
.filter((item) => item['旧箱唛'] || item['新SKU标签'] || item['新FBA箱唛'])
|
||||
if (!imported.length || imported.some((item) => required.some((key) => !item[key]))) {
|
||||
ElMessage.error('我方箱唛、旧 SKU 标签、新 SKU 标签和换标数量必须填写完整'); return
|
||||
ElMessage.error('旧箱唛、旧 SKU 标签、新 SKU 标签和换标数量必须填写完整'); return
|
||||
}
|
||||
const rows: SkuRelabelRow[] = []
|
||||
const rows: ImportedRelabelBinding[] = []
|
||||
for (const item of imported) {
|
||||
const quantity = Number(item['换标数量(件)'])
|
||||
if (!Number.isInteger(quantity) || quantity < 1) {
|
||||
ElMessage.error(`箱唛 ${item['我方箱唛']} 的换标数量必须是大于 0 的整数`); return
|
||||
ElMessage.error(`箱唛 ${item['旧箱唛']} 的换标数量必须是大于 0 的整数`); return
|
||||
}
|
||||
const source = cargoRows.value.find((row) => String(row.id) === item['明细行标识'])
|
||||
if (!source) { ElMessage.error(`明细行 ${item['明细行标识']} 不属于当前库存,请重新下载模板`); return }
|
||||
rows.push({
|
||||
id: ++skuRelabelSequence,
|
||||
sourceRowId: null,
|
||||
cartonMark: item['我方箱唛'].trim(),
|
||||
sourceRowId: source.id,
|
||||
cartonMark: item['旧箱唛'].trim(),
|
||||
originalSku: item['旧SKU标签'].trim(),
|
||||
newSku: item['新SKU标签'].trim(),
|
||||
quantity,
|
||||
fbaCartonMark: combinedTemplate ? item['新FBA箱唛'].trim() : '',
|
||||
destinationWarehouseId: combinedTemplate ? item['FBA目的仓'].trim() : '',
|
||||
fbaCartonMark: mixedTemplate ? item['新FBA箱唛'].trim() : '',
|
||||
destinationWarehouseId: mixedTemplate ? item['FBA目的仓'].trim() : '',
|
||||
remark: item['备注'] || '',
|
||||
templateType,
|
||||
selected: true,
|
||||
shipmentNo: mixedTemplate ? item['FBA货件编号'].trim() : '',
|
||||
})
|
||||
}
|
||||
skuRelabelRows.value = rows
|
||||
ElMessage.success(`已导入 ${rows.length} 条 SKU 换标明细`)
|
||||
importedRelabelBindings.value = rows
|
||||
ElMessage.success(`已读取 ${rows.length} 条绑定关系,请选择后导入到明细`)
|
||||
return
|
||||
}
|
||||
const required = ['明细行标识', '本次箱数', 'FBA货件编号', '我方箱唛', 'FBA箱唛', 'FBA目的仓']
|
||||
if (required.some((name) => !headers.includes(name))) { ElMessage.error('模板格式不正确,请重新下载模板填写'); return }
|
||||
const required = ['明细行标识', '旧箱唛', '新FBA箱唛', 'FBA目的仓', 'FBA货件编号']
|
||||
if (required.some((name) => !headers.includes(name))) { ElMessage.error('箱号关联模板格式不正确,请重新下载箱号关联模板'); return }
|
||||
const imported = lines.slice(1).map(parseCsvLine)
|
||||
.map((values) => Object.fromEntries(headers.map((key, index) => [key, values[index] || ''])))
|
||||
.filter((item) => item['明细行标识'])
|
||||
.filter((item) => item['旧箱唛'] || item['新FBA箱唛'])
|
||||
if (!imported.length || imported.some((item) => required.some((key) => !item[key]))) {
|
||||
ElMessage.error('模板中的明细行、箱数、货件、箱唛和 FBA 目的仓必须填写完整'); return
|
||||
ElMessage.error('模板中的明细行、旧箱唛、新 FBA 箱唛、FBA 目的仓和货件编号必须填写完整'); return
|
||||
}
|
||||
if (new Set(imported.map((item) => item['明细行标识'])).size !== imported.length) {
|
||||
ElMessage.error('模板中的明细行标识不能重复'); return
|
||||
}
|
||||
const importedByRow = new Map(imported.map((item) => [item['明细行标识'], item]))
|
||||
if (importedByRow.size !== cargoRows.value.length || cargoRows.value.some((row) => !importedByRow.has(String(row.id)))) {
|
||||
ElMessage.error('模板明细与当前已选入仓单库存不一致,请重新下载模板'); return
|
||||
if (importedByRow.size !== imported.length || [...importedByRow.keys()].some((id) => !cargoRows.value.some((row) => String(row.id) === id))) {
|
||||
ElMessage.error('模板存在重复或不属于当前库存的明细行,请重新下载模板'); return
|
||||
}
|
||||
for (const row of cargoRows.value) {
|
||||
const item = importedByRow.get(String(row.id))!
|
||||
const quantity = Number(item['本次箱数'])
|
||||
if (!Number.isInteger(quantity) || quantity < 1 || quantity > Number(row.availableQuantity || 0)) {
|
||||
ElMessage.error(`明细行 ${row.id} 的本次箱数不正确或超过可用库存`); return
|
||||
const bindings: ImportedRelabelBinding[] = []
|
||||
for (const [rowId, item] of importedByRow) {
|
||||
const row = cargoRows.value.find((candidate) => String(candidate.id) === rowId)!
|
||||
bindings.push({ id: ++skuRelabelSequence, sourceRowId: row.id, cartonMark: item['旧箱唛'],
|
||||
originalSku: row.sku, newSku: '', quantity: 1, fbaCartonMark: item['新FBA箱唛'],
|
||||
destinationWarehouseId: item['FBA目的仓'], remark: item['备注'] || '', templateType,
|
||||
selected: true, shipmentNo: item['FBA货件编号'] })
|
||||
}
|
||||
importedRelabelBindings.value = bindings
|
||||
ElMessage.success(`已读取 ${bindings.length} 条箱号关联,请选择后导入到明细`)
|
||||
}
|
||||
function selectAllImportedBindings(value: boolean) {
|
||||
for (const item of importedRelabelBindings.value) item.selected = value
|
||||
}
|
||||
function importSelectedBindingsToDetails() {
|
||||
const selected = importedRelabelBindings.value.filter((item) => item.selected)
|
||||
if (!selected.length) { ElMessage.warning('请至少选择一条绑定关系'); return }
|
||||
const templateType = selected[0].templateType
|
||||
if (selected.some((item) => item.templateType !== templateType)) { ElMessage.warning('请重新上传同一种绑定模板'); return }
|
||||
if (templateType === 'carton') {
|
||||
for (const binding of selected) {
|
||||
const source = cargoRows.value.find((row) => row.id === binding.sourceRowId)
|
||||
if (!source) continue
|
||||
Object.assign(source, { included: true, quantity: 1, shipmentNo: binding.shipmentNo,
|
||||
cartonMark: binding.cartonMark, fbaCartonMark: binding.fbaCartonMark,
|
||||
destinationWarehouseId: binding.destinationWarehouseId, remark: binding.remark })
|
||||
}
|
||||
row.quantity = quantity
|
||||
row.shipmentNo = item['FBA货件编号']
|
||||
row.cartonMark = item['我方箱唛']
|
||||
row.fbaCartonMark = item['FBA箱唛']
|
||||
row.destinationWarehouseId = item['FBA目的仓']
|
||||
row.remark = item['备注'] || ''
|
||||
labelingMode.value = 'carton'
|
||||
} else {
|
||||
const importedRows = selected.map(({ templateType: _, selected: __, shipmentNo, ...item }) => item)
|
||||
for (const item of importedRows) {
|
||||
skuRelabelRows.value = skuRelabelRows.value.filter((row) => !(row.cartonMark.trim().toUpperCase() === item.cartonMark.trim().toUpperCase()
|
||||
&& row.originalSku.trim().toUpperCase() === item.originalSku.trim().toUpperCase()))
|
||||
skuRelabelRows.value.push(item)
|
||||
if (templateType === 'mixed') {
|
||||
const source = cargoRows.value.find((row) => row.id === item.sourceRowId)
|
||||
const shipmentNo = selected.find((binding) => binding.id === item.id)?.shipmentNo || ''
|
||||
if (source) Object.assign(source, { included: true, cartonMark: item.cartonMark,
|
||||
fbaCartonMark: item.fbaCartonMark, destinationWarehouseId: item.destinationWarehouseId, shipmentNo })
|
||||
}
|
||||
}
|
||||
labelingMode.value = templateType === 'mixed' ? 'carton_and_sku' : 'sku'
|
||||
}
|
||||
ElMessage.success(`已导入 ${imported.length} 条关联面单明细`)
|
||||
importedRelabelBindings.value = importedRelabelBindings.value.filter((item) => !item.selected)
|
||||
ElMessage.success(`已将 ${selected.length} 条绑定关系导入本次换标明细`)
|
||||
}
|
||||
function selectDiscardInbound(orderId: string) {
|
||||
const candidate = discardCandidates.value.find((item) => item.orderId === orderId)
|
||||
@@ -356,14 +423,15 @@ async function load() {
|
||||
function query() { void load() }
|
||||
async function submit() {
|
||||
const primaryWarehouse = props.service === 'relabel' ? form.sourceWarehouse : form.warehouse
|
||||
const relabelRows = labelingMode.value === 'carton' ? cargoRows.value : skuRelabelRows.value
|
||||
const relabelRows = labelingMode.value === 'carton' ? cartonDetailRows.value : skuRelabelRows.value
|
||||
const invalidCargo = props.service === 'disposal'
|
||||
? !selectedDiscardOrderId.value || cargoRows.value.every((item) => item.quantity < 1)
|
||||
|| cargoRows.value.some((item) => item.quantity < 0 || item.quantity > Number(item.availableQuantity || 0))
|
||||
: relabelRows.length === 0 || (props.service === 'labeling' && labelingMode.value !== 'carton'
|
||||
? skuRelabelRows.value.some((item) => !item.cartonMark || !item.originalSku || !item.newSku || item.quantity < 1
|
||||
|| (labelingMode.value === 'carton_and_sku' && (!item.fbaCartonMark || !item.destinationWarehouseId)))
|
||||
: cargoRows.value.some((item) => (props.service !== 'labeling' && !item.sku) || !item.name || item.quantity < 1))
|
||||
: cargoRows.value.some((item) => (props.service !== 'labeling' && !item.sku) || !item.name
|
||||
|| (props.service !== 'labeling' && item.quantity < 1)))
|
||||
if ((props.service === 'relabel' && !form.inboundNo) || (props.service !== 'disposal' && !primaryWarehouse) || invalidCargo) {
|
||||
ElMessage.warning('请填写必填信息和完整的货物明细'); return
|
||||
}
|
||||
@@ -377,10 +445,10 @@ async function submit() {
|
||||
&& form.relabel && !shippingLabelFile.value) {
|
||||
ElMessage.warning('选择打印面单时必须上传面单文件'); return
|
||||
}
|
||||
if (props.service === 'labeling' && labelingMode.value === 'carton' && cargoRows.value.some((item) => !item.shipmentNo || !item.cartonMark || !item.fbaCartonMark)) {
|
||||
if (props.service === 'labeling' && labelingMode.value === 'carton' && cartonDetailRows.value.some((item) => !item.shipmentNo || !item.cartonMark || !item.fbaCartonMark)) {
|
||||
ElMessage.warning('请上传关联面单,确保每箱的我方箱唛和 FBA 箱唛完整'); return
|
||||
}
|
||||
if (props.service === 'labeling' && labelingMode.value === 'carton' && cargoRows.value.some((item) => !item.destinationWarehouseId || !item.sourceInventoryPositionId)) {
|
||||
if (props.service === 'labeling' && labelingMode.value === 'carton' && cartonDetailRows.value.some((item) => !item.destinationWarehouseId || !item.sourceInventoryPositionId)) {
|
||||
ElMessage.warning('请选择有库存的历史入仓单,并为每项填写 FBA 目的仓'); return
|
||||
}
|
||||
if (props.service === 'disposal' && !form.reason) {
|
||||
@@ -402,7 +470,7 @@ async function submit() {
|
||||
if (props.service === 'labeling') {
|
||||
const sourceInboundOrders = [...new Set(cargoRows.value.map((item) => item.sourceInboundOrderNo || item.sourceInboundCode).filter((value): value is string => Boolean(value)))].join('、').slice(0, 128)
|
||||
const items = labelingMode.value === 'carton'
|
||||
? cargoRows.value.map((item) => ({ sourceInventoryBalanceId: item.sourceInventoryBalanceId!, sourceInventoryPositionId: item.sourceInventoryPositionId!, sourceInboundOrderId: item.sourceInboundOrderId!, skuCode: item.sku, productNameZh: item.name, totalPackageCount: item.quantity, notifiedPackageCount: item.quantity, shipmentNo: item.shipmentNo, trackingCode: form.trackingNo || undefined, newSkuCode: undefined, labelRequirement: form.requirement || undefined, cartonMark: item.cartonMark, fbaCartonMark: item.fbaCartonMark, destinationFbaWarehouseCode: item.destinationWarehouseId, operationType: 'CARTON_LABEL' as const, skuItems: [], remark: item.remark || undefined }))
|
||||
? cartonDetailRows.value.map((item) => ({ sourceInventoryBalanceId: item.sourceInventoryBalanceId!, sourceInventoryPositionId: item.sourceInventoryPositionId!, sourceInboundOrderId: item.sourceInboundOrderId!, skuCode: item.sku, productNameZh: item.name, totalPackageCount: 1, notifiedPackageCount: 1, shipmentNo: item.shipmentNo, trackingCode: form.trackingNo || undefined, newSkuCode: undefined, labelRequirement: form.requirement || undefined, cartonMark: item.cartonMark, fbaCartonMark: item.fbaCartonMark, destinationFbaWarehouseCode: item.destinationWarehouseId, operationType: 'CARTON_LABEL' as const, skuItems: [], remark: item.remark || undefined }))
|
||||
: buildSkuRelabelItems()
|
||||
const created = await createRelabel({ customerOrderNo: sourceInboundOrders || '贴标申请', operationWarehouseId: form.warehouse, labelDeadline: form.labelDeadline, contactName: form.contact, contactPhone: form.phone, chargeAmount: form.chargeAmount, remark: form.remark || undefined, idempotencyKey, items,
|
||||
deliveryMethod: labelingMode.value === 'sku' ? undefined : form.deliveryMethod as 'TRUCK' | 'EXPRESS' | 'TRUCK_PICKUP' | 'EXPRESS_PICKUP',
|
||||
@@ -496,6 +564,7 @@ function selectTransferFbaAvailability(value: string | number | boolean | undefi
|
||||
async function selectOperationWarehouse() {
|
||||
cargoRows.value = []
|
||||
skuRelabelRows.value = []
|
||||
importedRelabelBindings.value = []
|
||||
selectedRelabelInboundOrderId.value = ''
|
||||
relabelCandidates.value = []
|
||||
const warehouse = operationWarehouses.value.find((item) => String(item.id) === form.warehouse)
|
||||
@@ -512,7 +581,7 @@ function selectRelabelInventory(inboundOrderId: string) {
|
||||
.filter((candidate) => String(candidate.inboundOrderId) === inboundOrderId)
|
||||
.flatMap((candidate) => candidate.positions.flatMap((position) => Array.from({ length: Math.min(position.availablePackages, 500) }, () => ({
|
||||
id: ++cargoSequence, sku: candidate.skuCode || '', name: candidate.productNameZh || '库存货物',
|
||||
quantity: 1, availableQuantity: 1,
|
||||
included: false, quantity: 1, availableQuantity: 1,
|
||||
sourceInventoryBalanceId: String(candidate.inventoryBalanceId), sourceInventoryPositionId: String(position.positionId),
|
||||
sourceInboundOrderId: String(candidate.inboundOrderId), sourceInboundOrderNo: candidate.inboundOrderNo,
|
||||
sourceInboundCode: candidate.inboundCode, sourceWarehouseName: candidate.overseasWarehouseName,
|
||||
@@ -520,7 +589,9 @@ function selectRelabelInventory(inboundOrderId: string) {
|
||||
fnsku: '', shipmentNo: '', newSkuCode: '', shippingMark: '', cartonMark: '', fbaCartonMark: '',
|
||||
destinationWarehouseId: candidate.destinationFbaWarehouseCode || '', remark: '',
|
||||
})))).slice(0, 500)
|
||||
if (cargoRows.value.length) cargoRows.value[0].included = true
|
||||
skuRelabelRows.value = []
|
||||
importedRelabelBindings.value = []
|
||||
shippingLabelFile.value = null
|
||||
if (labelingMode.value !== 'carton') addSkuRelabelRow()
|
||||
}
|
||||
@@ -597,9 +668,15 @@ function selectRelabelInventory(inboundOrderId: string) {
|
||||
<div class="warehouse-section-heading warehouse-labeling-heading">
|
||||
<h3>货物明细</h3>
|
||||
<div class="warehouse-template-actions">
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate"><Download :size="15" />下载{{ labelingMode === 'carton' ? '箱唛' : 'SKU' }}模板</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="templateInput?.click()"><Upload :size="15" />上传{{ labelingMode === 'carton' ? '箱唛' : 'SKU' }}模板</el-button>
|
||||
<input ref="templateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate">
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('sku')"><Download :size="15" />下载 SKU 关联模板</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="skuTemplateInput?.click()"><Upload :size="15" />上传 SKU 关联</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('carton')"><Download :size="15" />下载箱号关联模板</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="cartonTemplateInput?.click()"><Upload :size="15" />上传箱号关联</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('mixed')"><Download :size="15" />下载 SKU 混箱模板</el-button>
|
||||
<el-button size="small" :disabled="!cargoRows.length" @click="mixedTemplateInput?.click()"><Upload :size="15" />上传 SKU 混箱</el-button>
|
||||
<input ref="skuTemplateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate($event, 'sku')">
|
||||
<input ref="cartonTemplateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate($event, 'carton')">
|
||||
<input ref="mixedTemplateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate($event, 'mixed')">
|
||||
</div>
|
||||
</div>
|
||||
<div class="warehouse-labeling-mode">
|
||||
@@ -611,13 +688,17 @@ function selectRelabelInventory(inboundOrderId: string) {
|
||||
</el-radio-group>
|
||||
<p>{{ labelingModeHint }}</p>
|
||||
</div>
|
||||
<div v-if="importedRelabelBindings.length" class="warehouse-import-preview">
|
||||
<div class="warehouse-section-heading"><div><strong>待导入绑定关系</strong><p>可只勾选本次需要换标的部分,也可以全选后一次导入。</p></div><div><el-checkbox :model-value="importedRelabelBindings.every((item) => item.selected)" @change="selectAllImportedBindings(Boolean($event))">全选</el-checkbox><el-button type="primary" size="small" @click="importSelectedBindingsToDetails">导入到明细</el-button></div></div>
|
||||
<div class="warehouse-table-scroll"><table class="warehouse-binding-preview-table"><thead><tr><th>选择</th><th>关系类型</th><th>旧箱唛</th><th>旧 SKU</th><th>新 SKU</th><th>数量</th><th>新 FBA 箱唛</th><th>FBA 目的仓</th></tr></thead><tbody><tr v-for="item in importedRelabelBindings" :key="item.id"><td><el-checkbox v-model="item.selected" /></td><td>{{ item.templateType === 'mixed' ? 'SKU 混箱换标' : item.templateType === 'carton' ? '箱号关联' : 'SKU 关联' }}</td><td>{{ item.cartonMark }}</td><td>{{ item.originalSku || '—' }}</td><td>{{ item.newSku || '—' }}</td><td>{{ item.quantity }}</td><td>{{ item.fbaCartonMark || '—' }}</td><td>{{ warehouseDisplay(item.destinationWarehouseId) }}</td></tr></tbody></table></div>
|
||||
</div>
|
||||
<div class="warehouse-section-heading warehouse-tab-actions">
|
||||
<p>系统只提供历史入仓单的大概库存位置,不代表箱唛已绑定具体托盘。</p>
|
||||
<div><strong>绑定明细</strong><p>上传后在下方回显,也可以手动添加;SKU 与箱号关联通过旧箱唛合并。系统只提供大概库存位置,不代表箱唛已绑定具体托盘。</p></div>
|
||||
<div v-if="labelingMode === 'carton'"><el-button type="primary" size="small" @click="addRelabelCargoRow"><Plus :size="15" />手动添加行</el-button><el-button size="small" @click="clearRelabelRows">清空</el-button></div>
|
||||
<div v-else><el-button type="primary" size="small" @click="addSkuRelabelRow"><Plus :size="15" />添加 SKU 明细</el-button><el-button size="small" @click="skuRelabelRows = []">清空</el-button></div>
|
||||
</div>
|
||||
<div v-if="labelingMode === 'carton'" class="warehouse-table-scroll"><table class="warehouse-edit-table warehouse-label-table"><thead><tr><th>商品 SKU</th><th>中文品名 *</th><th>FBA 货件编号 *</th><th>箱数 *</th><th>我方箱唛 *</th><th>新 FBA 箱唛 *</th><th>FBA 目的仓 *</th><th>备注</th><th>操作</th></tr></thead><tbody><tr v-for="row in cargoRows" :key="row.id"><td><el-input v-model="row.sku" placeholder="选填" /></td><td><el-input v-model="row.name" placeholder="请输入中文品名" /></td><td><el-input v-model="row.shipmentNo" placeholder="请输入FBA货件编号" /></td><td><el-input-number v-model="row.quantity" :min="1" :max="row.availableQuantity" controls-position="right" placeholder="请输入箱数" /></td><td><el-input v-model="row.cartonMark" placeholder="请输入我方箱唛" /></td><td><el-input v-model="row.fbaCartonMark" placeholder="请输入新的 FBA 箱唛" /></td><td><el-select v-model="row.destinationWarehouseId" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择 FBA 目的仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" /></el-select></td><td><el-input v-model="row.remark" type="textarea" :rows="2" maxlength="1000" show-word-limit placeholder="请输入明细备注" /></td><td><button type="button" class="warehouse-delete" title="删除" @click="removeCargoRow(row.id)"><Trash2 :size="16" />删除</button></td></tr><tr v-if="cargoRows.length === 0"><td colspan="9"><div class="warehouse-empty">请先选择仍有库存的历史入仓单,系统将带出可用库存明细</div></td></tr></tbody></table></div>
|
||||
<div v-else class="warehouse-table-scroll"><table class="warehouse-edit-table warehouse-sku-label-table"><thead><tr><th>我方箱唛 *</th><th>原 SKU *</th><th>换标后 SKU *</th><th>换标数量(件)*</th><th v-if="labelingMode === 'carton_and_sku'">新 FBA 箱唛 *</th><th v-if="labelingMode === 'carton_and_sku'">FBA 目的仓 *</th><th>备注</th><th>操作</th></tr></thead><tbody><tr v-for="row in skuRelabelRows" :key="row.id"><td><el-input v-model="row.cartonMark" placeholder="请输入我方箱唛" /></td><td><el-input v-model="row.originalSku" placeholder="请输入原 SKU" /></td><td><el-input v-model="row.newSku" placeholder="请输入换标后 SKU" /></td><td><el-input-number v-model="row.quantity" :min="1" :precision="0" controls-position="right" placeholder="请输入件数" /></td><td v-if="labelingMode === 'carton_and_sku'"><el-input v-model="row.fbaCartonMark" placeholder="请输入新的 FBA 箱唛" /></td><td v-if="labelingMode === 'carton_and_sku'"><el-select v-model="row.destinationWarehouseId" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择 FBA 目的仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" /></el-select></td><td><el-input v-model="row.remark" placeholder="请输入备注" /></td><td><button type="button" class="warehouse-delete" title="删除" @click="removeSkuRelabelRow(row.id)"><Trash2 :size="16" />删除</button></td></tr><tr v-if="skuRelabelRows.length === 0"><td :colspan="labelingMode === 'carton_and_sku' ? 8 : 6"><div class="warehouse-empty">暂无换标明细,请点击“添加 SKU 明细”</div></td></tr></tbody></table></div>
|
||||
<div v-if="labelingMode === 'carton'" class="warehouse-table-scroll"><table class="warehouse-edit-table warehouse-label-table"><thead><tr><th>商品 SKU</th><th>中文品名 *</th><th>FBA 货件编号 *</th><th>箱数</th><th>旧箱唛 *</th><th>新 FBA 箱唛 *</th><th>FBA 目的仓 *</th><th>备注</th><th>操作</th></tr></thead><tbody><tr v-for="row in cartonDetailRows" :key="row.id"><td><el-input v-model="row.sku" placeholder="选填" /></td><td><el-input v-model="row.name" placeholder="请输入中文品名" /></td><td><el-input v-model="row.shipmentNo" placeholder="请输入FBA货件编号" /></td><td><strong>1 箱</strong></td><td><el-input v-model="row.cartonMark" placeholder="请输入旧箱唛" /></td><td><el-input v-model="row.fbaCartonMark" placeholder="请输入新的 FBA 箱唛" /></td><td><el-select v-model="row.destinationWarehouseId" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择 FBA 目的仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" /></el-select></td><td><el-input v-model="row.remark" type="textarea" :rows="2" maxlength="1000" show-word-limit placeholder="请输入明细备注" /></td><td><button type="button" class="warehouse-delete" title="移出本次明细" @click="removeCargoRow(row.id)"><Trash2 :size="16" />移出</button></td></tr><tr v-if="cartonDetailRows.length === 0"><td colspan="9"><div class="warehouse-empty">暂无本次换标明细,请上传关系后导入或手动添加</div></td></tr></tbody></table></div>
|
||||
<div v-else class="warehouse-table-scroll"><table class="warehouse-edit-table warehouse-sku-label-table"><thead><tr><th>旧箱唛 *</th><th>旧 SKU *</th><th>新 SKU *</th><th>换标数量(件)*</th><th v-if="labelingMode === 'carton_and_sku'">新 FBA 箱唛 *</th><th v-if="labelingMode === 'carton_and_sku'">FBA 目的仓 *</th><th>备注</th><th>操作</th></tr></thead><tbody><tr v-for="row in skuRelabelRows" :key="row.id"><td><el-input v-model="row.cartonMark" placeholder="请输入旧箱唛" @change="applyExistingCartonBinding(row)" /></td><td><el-input v-model="row.originalSku" placeholder="请输入旧 SKU" @change="applyExistingSkuBinding(row)" /></td><td><el-input v-model="row.newSku" placeholder="请输入新 SKU" /></td><td><el-input-number v-model="row.quantity" :min="1" :precision="0" controls-position="right" placeholder="请输入件数" /></td><td v-if="labelingMode === 'carton_and_sku'"><el-input v-model="row.fbaCartonMark" placeholder="请输入新的 FBA 箱唛" /></td><td v-if="labelingMode === 'carton_and_sku'"><el-select v-model="row.destinationWarehouseId" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择 FBA 目的仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" /></el-select></td><td><el-input v-model="row.remark" placeholder="请输入备注" /></td><td><button type="button" class="warehouse-delete" title="删除" @click="removeSkuRelabelRow(row.id)"><Trash2 :size="16" />删除</button></td></tr><tr v-if="skuRelabelRows.length === 0"><td :colspan="labelingMode === 'carton_and_sku' ? 8 : 6"><div class="warehouse-empty">暂无绑定明细,请点击“添加 SKU 明细”</div></td></tr></tbody></table></div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="warehouse-section-heading"><h3>货物明细</h3><div v-if="props.service !== 'disposal'"><el-button type="primary" size="small" @click="addCargoRow"><Plus :size="15" />添加行</el-button><el-button size="small" @click="cargoRows = []">清空</el-button></div></div>
|
||||
@@ -662,4 +743,5 @@ function selectRelabelInventory(inboundOrderId: string) {
|
||||
.warehouse-labeling-tabs{margin-top:-8px}.warehouse-labeling-heading{align-items:flex-start}.warehouse-labeling-heading h3{margin-bottom:16px}.warehouse-template-actions{display:flex;gap:8px;padding-bottom:12px}.warehouse-tab-actions{align-items:center;margin:2px 0 14px}.warehouse-tab-actions p{margin:0;color:#7d8797;font-size:12px}.warehouse-tab-actions>div{display:flex;gap:8px}.warehouse-sku-notice{margin:0 0 14px;padding:10px 12px;border:1px solid #f2d39b;border-radius:4px;background:#fff8e8;color:#8a6116;font-size:12px}.warehouse-sku-label-table{min-width:980px}.warehouse-sku-label-table :deep(.el-input-number){width:160px}:deep(.warehouse-labeling-tabs>.el-tabs__header){margin-bottom:18px}:deep(.warehouse-labeling-tabs .el-tabs__item){height:42px;padding:0 26px;font-weight:600}.warehouse-labeling-mode{display:flex;align-items:center;gap:14px;margin:0 0 16px;padding:14px 16px;border:1px solid #dce5f5;border-radius:5px;background:#f7f9ff}.warehouse-labeling-mode>span{color:#34445c;font-size:13px;font-weight:650;white-space:nowrap}.warehouse-labeling-mode p{margin:0;color:#71809a;font-size:12px}.warehouse-labeling-mode :deep(.el-radio-group){display:flex;flex-shrink:0}.warehouse-labeling-mode :deep(.el-radio-button__inner){padding:8px 14px}
|
||||
.warehouse-relabel-detail-table{min-width:1420px}.warehouse-relabel-detail-table td strong{color:#253f67}
|
||||
.warehouse-native-file{min-height:32px;padding:5px 8px;border:1px solid #dcdfe6;border-radius:4px;background:#fff;color:#606266}.warehouse-fulfillment-grid{margin-bottom:18px}.warehouse-evidence{display:flex;align-items:center;gap:16px;padding:14px;border:1px solid #e7ebf1;border-radius:4px;background:#f8fafc}.warehouse-evidence>span{color:#71809a;font-size:12px}.warehouse-evidence>strong{color:#8a95a5;font-size:12px;font-weight:400}.warehouse-photo-actions{display:flex;flex-wrap:wrap;gap:8px}.warehouse-completion-remark{margin:10px 0 0;color:#596579;font-size:12px}
|
||||
.warehouse-template-actions{flex-wrap:wrap;justify-content:flex-end}.warehouse-import-preview{margin:0 0 16px;padding:14px;border:1px solid #cfe0f5;border-radius:5px;background:#f8fbff}.warehouse-import-preview .warehouse-section-heading{margin-bottom:10px}.warehouse-import-preview .warehouse-section-heading>div{display:flex;align-items:center;gap:10px}.warehouse-import-preview p{margin:0;color:#7d8797;font-size:12px}.warehouse-binding-preview-table{min-width:980px;background:#fff}
|
||||
</style>
|
||||
|
||||
@@ -27,21 +27,51 @@ test('客户贴标表单不展示客户单号、托盘和内部库存来源列',
|
||||
|
||||
test('贴标申请保留关联模板下载和上传入口', () => {
|
||||
assert.match(view, /downloadRelabelTemplate/)
|
||||
assert.match(view, /下载\{\{ labelingMode === 'carton' \? '箱唛' : 'SKU' \}\}模板/)
|
||||
assert.match(view, /templateInput\?\.click\(\)/)
|
||||
assert.match(view, /上传\{\{ labelingMode === 'carton' \? '箱唛' : 'SKU' \}\}模板/)
|
||||
assert.match(view, /下载 SKU 关联模板/)
|
||||
assert.match(view, /上传 SKU 关联/)
|
||||
assert.match(view, /下载箱号关联模板/)
|
||||
assert.match(view, /上传箱号关联/)
|
||||
assert.match(view, /下载 SKU 混箱模板/)
|
||||
assert.match(view, /上传 SKU 混箱/)
|
||||
assert.match(view, /skuTemplateInput\?\.click\(\)/)
|
||||
assert.match(view, /cartonTemplateInput\?\.click\(\)/)
|
||||
assert.match(view, /importRelabelTemplate/)
|
||||
assert.match(view, /明细行标识/)
|
||||
assert.match(view, /'明细行标识', '旧箱唛', '旧SKU标签', '新SKU标签'/)
|
||||
assert.match(view, /'旧箱唛', '新FBA箱唛', 'FBA目的仓'/)
|
||||
assert.match(view, /SKU 与箱号关联通过旧箱唛合并/)
|
||||
assert.doesNotMatch(view, /库存位置ID/)
|
||||
})
|
||||
|
||||
test('贴标货物明细支持手动添加和编辑', () => {
|
||||
assert.match(view, /手动添加行/)
|
||||
assert.match(view, /addRelabelCargoRow/)
|
||||
assert.match(view, /货物明细已按所选入仓单的可用库存带出/)
|
||||
assert.match(view, /所选入仓单没有更多可添加的库存箱/)
|
||||
assert.match(view, /<el-input v-model="row\.sku" :readonly="props\.service === 'disposal'"/)
|
||||
})
|
||||
|
||||
test('上传关系支持部分或全量选择后导入本次换标明细', () => {
|
||||
assert.match(view, /interface ImportedRelabelBinding/)
|
||||
assert.match(view, /待导入绑定关系/)
|
||||
assert.match(view, /全选/)
|
||||
assert.match(view, /导入到明细/)
|
||||
assert.match(view, /importSelectedBindingsToDetails/)
|
||||
assert.match(view, /item\.selected/)
|
||||
assert.match(view, /cartonDetailRows/)
|
||||
assert.match(view, /included: false/)
|
||||
assert.match(view, /cargoRows\.value\[0\]\.included = true/)
|
||||
})
|
||||
|
||||
test('箱唛换标一行固定代表一箱', () => {
|
||||
const cartonTable = view.match(/<div v-if="labelingMode === 'carton'" class="warehouse-table-scroll">.+?(?=<div v-else class="warehouse-table-scroll">)/s)?.[0]
|
||||
assert.ok(cartonTable)
|
||||
assert.match(cartonTable, /<th>箱数<\/th>/)
|
||||
assert.match(cartonTable, /<td><strong>1 箱<\/strong><\/td>/)
|
||||
assert.doesNotMatch(cartonTable, /v-model="row\.quantity"/)
|
||||
assert.doesNotMatch(view, /'本次箱数'/)
|
||||
assert.match(view, /totalPackageCount: 1, notifiedPackageCount: 1/)
|
||||
})
|
||||
|
||||
test('贴标货物明细通过单一换标类型选择三种模式', () => {
|
||||
assert.match(view, /<el-radio-group v-model="labelingMode" aria-label="换标类型">/)
|
||||
assert.match(view, /<el-radio-button value="carton">只换箱唛<\/el-radio-button>/)
|
||||
@@ -49,12 +79,14 @@ test('贴标货物明细通过单一换标类型选择三种模式', () => {
|
||||
assert.match(view, /<el-radio-button value="carton_and_sku">SKU 和箱唛都换<\/el-radio-button>/)
|
||||
assert.doesNotMatch(view, /el-tab-pane label="(?:箱唛换标|SKU 换标)"/)
|
||||
assert.match(view, /interface SkuRelabelRow/)
|
||||
assert.match(view, /原 SKU \*/)
|
||||
assert.match(view, /我方箱唛 \*/)
|
||||
assert.match(view, /旧 SKU \*/)
|
||||
assert.match(view, /旧箱唛 \*/)
|
||||
assert.match(view, /换标数量(件)\*/)
|
||||
assert.match(view, /旧SKU标签/)
|
||||
assert.match(view, /新SKU标签/)
|
||||
assert.match(view, /已导入 \$\{rows\.length\} 条 SKU 换标明细/)
|
||||
assert.match(view, /已读取 \$\{rows\.length\} 条绑定关系/)
|
||||
assert.match(view, /applyExistingSkuBinding/)
|
||||
assert.match(view, /applyExistingCartonBinding/)
|
||||
assert.match(view, /buildSkuRelabelItems/)
|
||||
assert.match(view, /CARTON_AND_SKU/)
|
||||
assert.match(view, /changeCarton/)
|
||||
|
||||
Reference in New Issue
Block a user