|
|
|
@@ -428,9 +428,7 @@ function relabelOptionLabel(option: typeof relabelInboundOptions.value[number])
|
|
|
|
|
}
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
const saving = ref(false)
|
|
|
|
|
const cartonTemplateInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const skuTemplateInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const mixedTemplateInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const unifiedTemplateInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const transferCartonMarkInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const relabelFileInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
const relabelFileScope = ref<'CARTON_TOTAL' | 'SKU_TOTAL' | 'ITEM'>('CARTON_TOTAL')
|
|
|
|
@@ -827,110 +825,62 @@ async function importTransferCartonMarks(event: Event) {
|
|
|
|
|
for (const row of cargoRows.value) row.customerCartonMarks = imported.filter((item) => item.SKU.trim().toUpperCase() === row.sku.trim().toUpperCase()).map((item) => item['客户箱唛号'].trim()).join('\n')
|
|
|
|
|
ElMessage.success(`已导入 ${imported.length} 个客户箱唛`)
|
|
|
|
|
}
|
|
|
|
|
function downloadRelabelTemplate(templateType: RelabelTemplateType) {
|
|
|
|
|
function relabelTemplateTypeForMode(mode: LabelingMode): RelabelTemplateType {
|
|
|
|
|
return mode === 'carton' ? 'carton' : mode === 'sku' ? 'sku' : 'mixed'
|
|
|
|
|
}
|
|
|
|
|
function relabelTemplateTypeLabel(type: RelabelTemplateType) {
|
|
|
|
|
return type === 'carton' ? '只换箱唛' : type === 'sku' ? '只换 SKU 标签' : 'SKU 和箱唛都换'
|
|
|
|
|
}
|
|
|
|
|
function parseRelabelTemplateType(value: string): RelabelTemplateType | null {
|
|
|
|
|
const normalized = value.trim().toUpperCase().replaceAll(' ', '')
|
|
|
|
|
if (['只换箱唛', '箱号关联', '箱唛换标', 'CARTON', 'CARTON_LABEL'].includes(normalized)) return 'carton'
|
|
|
|
|
if (['只换SKU标签', 'SKU关联', 'SKU换标', 'SKU', 'SKU_LABEL'].includes(normalized)) return 'sku'
|
|
|
|
|
if (['SKU和箱唛都换', 'SKU混箱', 'SKU混箱换标', '混箱', 'MIXED', 'CARTON_AND_SKU'].includes(normalized)) return 'mixed'
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
function downloadRelabelTemplate() {
|
|
|
|
|
if (!cargoRows.value.length) { ElMessage.warning('请先选择有库存的历史入仓单'); return }
|
|
|
|
|
const cartonTemplate = templateType === 'carton'
|
|
|
|
|
const mixedTemplate = templateType === 'mixed'
|
|
|
|
|
const includeDestination = false
|
|
|
|
|
const templateType = relabelTemplateTypeForMode(labelingMode.value)
|
|
|
|
|
const cartonMarkHeader = props.service === 'transfer' ? '客户箱唛号' : '仓库唛头'
|
|
|
|
|
const header = cartonTemplate
|
|
|
|
|
? ['明细行标识', cartonMarkHeader, '新FBA箱唛', ...(includeDestination ? ['FBA目的仓'] : []), 'FBA货件编号', '备注']
|
|
|
|
|
: ['明细行标识', cartonMarkHeader, '旧SKU标签', '新SKU标签', '换标数量(件)',
|
|
|
|
|
...(mixedTemplate ? ['新FBA箱唛', ...(includeDestination ? ['FBA目的仓'] : []), 'FBA货件编号'] : []), '备注']
|
|
|
|
|
const rows = cargoRows.value.map((item) => cartonTemplate
|
|
|
|
|
? [item.id, item.cartonMark, item.fbaCartonMark, ...(includeDestination ? [item.destinationWarehouseId] : []), item.shipmentNo, item.remark]
|
|
|
|
|
: [item.id, item.cartonMark, item.sku, '', 1,
|
|
|
|
|
...(mixedTemplate ? [item.fbaCartonMark, ...(includeDestination ? [item.destinationWarehouseId] : []), item.shipmentNo] : []), item.remark])
|
|
|
|
|
const header = ['明细行标识', '贴标类型', cartonMarkHeader, '旧SKU标签', '新SKU标签', '换标数量(件)', '新FBA箱唛', 'FBA货件编号', '备注']
|
|
|
|
|
const rows = cargoRows.value.map((item) => [item.id, relabelTemplateTypeLabel(templateType), props.service === 'transfer' ? item.customerCartonMarks : item.cartonMark, item.sku, '', 1, '', 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'
|
|
|
|
|
: mixedTemplate ? '贴标申请-SKU混箱换标模板.csv' : '贴标申请-SKU关联模板.csv'
|
|
|
|
|
anchor.click(); URL.revokeObjectURL(url)
|
|
|
|
|
const url = URL.createObjectURL(blob); const anchor = document.createElement('a'); anchor.href = url; anchor.download = '贴标申请-统一明细关联模板.csv'; anchor.click(); URL.revokeObjectURL(url)
|
|
|
|
|
}
|
|
|
|
|
function parseCsvLine(line: string) {
|
|
|
|
|
const values: string[] = []; let value = ''; let quoted = false
|
|
|
|
|
for (let index = 0; index < line.length; index += 1) {
|
|
|
|
|
const char = line[index]
|
|
|
|
|
if (char === '"') { if (quoted && line[index + 1] === '"') { value += '"'; index += 1 } else quoted = !quoted }
|
|
|
|
|
else if (char === ',' && !quoted) { values.push(value.trim()); value = '' }
|
|
|
|
|
else value += char
|
|
|
|
|
}
|
|
|
|
|
for (let index = 0; index < line.length; index += 1) { const char = line[index]; if (char === '"') { if (quoted && line[index + 1] === '"') { value += '"'; index += 1 } else quoted = !quoted } else if (char === ',' && !quoted) { values.push(value.trim()); value = '' } else value += char }
|
|
|
|
|
values.push(value.trim()); return values
|
|
|
|
|
}
|
|
|
|
|
async function importRelabelTemplate(event: Event, templateType: RelabelTemplateType) {
|
|
|
|
|
const input = event.target as HTMLInputElement; const file = input.files?.[0]; input.value = ''
|
|
|
|
|
if (!file) return
|
|
|
|
|
async function importRelabelTemplate(event: Event) {
|
|
|
|
|
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 }
|
|
|
|
|
// Accept both the current display name and legacy template header while keeping the internal key stable.
|
|
|
|
|
const headers = parseCsvLine(lines[0]).map((name) => name === '仓库唛头' || name === '客户箱唛号' || name === '旧唛头' ? '旧箱唛' : name)
|
|
|
|
|
if (templateType !== 'carton') {
|
|
|
|
|
const mixedTemplate = templateType === 'mixed'
|
|
|
|
|
const required = ['明细行标识', '旧箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)',
|
|
|
|
|
...(mixedTemplate ? ['新FBA箱唛', 'FBA货件编号'] : [])]
|
|
|
|
|
if (required.some((name) => !headers.includes(name))) {
|
|
|
|
|
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) => item['旧箱唛'] || item['新SKU标签'] || item['新FBA箱唛'])
|
|
|
|
|
if (!imported.length || imported.some((item) => required.some((key) => !item[key]))) {
|
|
|
|
|
ElMessage.error('仓库唛头、旧 SKU 标签、新 SKU 标签和换标数量必须填写完整'); return
|
|
|
|
|
}
|
|
|
|
|
const rows: ImportedRelabelBinding[] = []
|
|
|
|
|
for (const item of imported) {
|
|
|
|
|
const quantity = Number(item['换标数量(件)'])
|
|
|
|
|
if (!Number.isInteger(quantity) || quantity < 1) {
|
|
|
|
|
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: source.id,
|
|
|
|
|
cartonMark: item['旧箱唛'].trim(),
|
|
|
|
|
originalSku: item['旧SKU标签'].trim(),
|
|
|
|
|
newSku: item['新SKU标签'].trim(),
|
|
|
|
|
quantity,
|
|
|
|
|
fbaCartonMark: mixedTemplate ? item['新FBA箱唛'].trim() : '',
|
|
|
|
|
destinationWarehouseId: form.destination,
|
|
|
|
|
remark: item['备注'] || '',
|
|
|
|
|
templateType,
|
|
|
|
|
selected: true,
|
|
|
|
|
shipmentNo: mixedTemplate ? item['FBA货件编号'].trim() : '',
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
importedRelabelBindings.value = rows
|
|
|
|
|
ElMessage.success(`已读取 ${rows.length} 条绑定关系,请选择后导入到明细`)
|
|
|
|
|
return
|
|
|
|
|
const requiredHeaders = ['明细行标识', '贴标类型', '旧箱唛', '旧SKU标签', '新SKU标签', '换标数量(件)', '新FBA箱唛', 'FBA货件编号', '备注']
|
|
|
|
|
if (requiredHeaders.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['明细行标识'] || item['贴标类型'] || item['旧箱唛'] || item['新SKU标签'] || item['新FBA箱唛'])
|
|
|
|
|
if (!imported.length) { ElMessage.error('模板中没有可导入的明细'); return }
|
|
|
|
|
const rows: ImportedRelabelBinding[] = []; let detectedType: RelabelTemplateType | null = null
|
|
|
|
|
for (const item of imported) {
|
|
|
|
|
const templateType = parseRelabelTemplateType(item['贴标类型']); if (!templateType) { ElMessage.error(`明细行 ${item['明细行标识']} 的贴标类型无效`); return }
|
|
|
|
|
if (detectedType && detectedType !== templateType) { ElMessage.error('同一份明细文件只能包含一种贴标类型,请拆分后分别提交换标单'); return }
|
|
|
|
|
detectedType = templateType
|
|
|
|
|
const source = cargoRows.value.find((row) => String(row.id) === item['明细行标识']); if (!source) { ElMessage.error(`明细行 ${item['明细行标识']} 不属于当前库存,请重新下载模板`); return }
|
|
|
|
|
const quantity = Number(item['换标数量(件)']); const requiresSku = templateType !== 'carton'; const requiresCarton = templateType !== 'sku'
|
|
|
|
|
if (!item['旧箱唛'] || (requiresSku && (!item['旧SKU标签'] || !item['新SKU标签'])) || !Number.isInteger(quantity) || quantity < 1 || (requiresCarton && (!item['新FBA箱唛'] || !item['FBA货件编号']))) { ElMessage.error(`明细行 ${item['明细行标识']} 未按“${relabelTemplateTypeLabel(templateType)}”填写完整`); return }
|
|
|
|
|
rows.push({ id: ++skuRelabelSequence, sourceRowId: source.id, cartonMark: item['旧箱唛'].trim(), originalSku: (item['旧SKU标签'] || source.sku).trim(), newSku: item['新SKU标签'].trim(), quantity: templateType === 'carton' ? 1 : quantity, fbaCartonMark: item['新FBA箱唛'].trim(), destinationWarehouseId: form.destination, remark: item['备注'] || '', templateType, selected: true, shipmentNo: item['FBA货件编号'].trim() })
|
|
|
|
|
}
|
|
|
|
|
const required = ['明细行标识', '旧箱唛', '新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['旧箱唛'] || item['新FBA箱唛'])
|
|
|
|
|
if (!imported.length || imported.some((item) => required.some((key) => !item[key]))) {
|
|
|
|
|
ElMessage.error('模板中的明细行、仓库唛头、新 FBA 箱唛和货件编号必须填写完整'); return
|
|
|
|
|
const keys = rows.map((row) => detectedType === 'carton' ? String(row.sourceRowId) : `${row.cartonMark.toUpperCase()}|${row.originalSku.toUpperCase()}`)
|
|
|
|
|
if (new Set(keys).size !== keys.length) { ElMessage.error('存在重复箱明细或重复的箱内 SKU,请合并后重新上传'); return }
|
|
|
|
|
const cartonTargets = new Map<string, string>()
|
|
|
|
|
for (const row of rows) {
|
|
|
|
|
const key = row.cartonMark.toUpperCase()
|
|
|
|
|
const target = `${row.fbaCartonMark}|${row.shipmentNo}`
|
|
|
|
|
if (detectedType === 'mixed' && cartonTargets.has(key) && cartonTargets.get(key) !== target) { ElMessage.error('同一箱内的 SKU 必须填写相同的新 FBA 箱唛和货件编号'); return }
|
|
|
|
|
cartonTargets.set(key, target)
|
|
|
|
|
}
|
|
|
|
|
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 !== imported.length || [...importedByRow.keys()].some((id) => !cargoRows.value.some((row) => String(row.id) === id))) {
|
|
|
|
|
ElMessage.error('模板存在重复或不属于当前库存的明细行,请重新下载模板'); 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: form.destination, remark: item['备注'] || '', templateType,
|
|
|
|
|
selected: true, shipmentNo: item['FBA货件编号'] })
|
|
|
|
|
}
|
|
|
|
|
importedRelabelBindings.value = bindings
|
|
|
|
|
ElMessage.success(`已读取 ${bindings.length} 条箱号关联,请选择后导入到明细`)
|
|
|
|
|
importedRelabelBindings.value = rows; ElMessage.success(`已读取 ${rows.length} 条绑定关系,请选择后导入到明细`)
|
|
|
|
|
}
|
|
|
|
|
function selectAllImportedBindings(value: boolean) {
|
|
|
|
|
for (const item of importedRelabelBindings.value) item.selected = value
|
|
|
|
@@ -1795,13 +1745,11 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {
|
|
|
|
|
<section class="warehouse-file-group">
|
|
|
|
|
<div class="warehouse-file-group__heading"><div><strong><span>2</span>明细关联模板</strong></div><em>按需使用</em></div>
|
|
|
|
|
<div class="warehouse-template-list">
|
|
|
|
|
<div><span><strong>SKU 关联</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('sku')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="skuTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div>
|
|
|
|
|
<div><span><strong>箱号关联</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('carton')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="cartonTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div>
|
|
|
|
|
<div><span><strong>SKU 混箱</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('mixed')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="mixedTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div>
|
|
|
|
|
<div><span><strong>统一贴标明细</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate()"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="unifiedTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
<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')"><input ref="cartonTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectCartonTotalFile"><input ref="skuTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectSkuTotalFile">␍ <div v-if="isReturnRelabelSource" class="warehouse-table-scroll">
|
|
|
|
|
<input ref="unifiedTemplateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate"><input ref="cartonTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectCartonTotalFile"><input ref="skuTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectSkuTotalFile">␍ <div v-if="isReturnRelabelSource" class="warehouse-table-scroll">
|
|
|
|
|
<el-input v-model="returnCartonQuery" clearable placeholder="" />␍ <template v-if="returnLooseCandidates.length">
|
|
|
|
|
<div class="warehouse-section-heading"><h3>可用包裹</h3><el-button text type="primary" native-type="button" :aria-expanded="!availableSkusCollapsed" aria-controls="return-available-skus" @click="availableSkusCollapsed = !availableSkusCollapsed">{{ availableSkusCollapsed ? '展开明细' : '收起明细' }}</el-button></div>
|
|
|
|
|
<table v-show="!availableSkusCollapsed" id="return-available-skus" class="warehouse-edit-table"><thead><tr><th>包裹识别码</th><th>来源退货单</th><th>SKU</th><th>SKU 换标结果</th><th>剩余可换(件)</th><th>操作</th></tr></thead><tbody><template v-for="source in returnLooseCandidates" :key="source.returnCartonId"><tr v-for="sku in source.skuItems" :key="sku.skuCode"><td>{{ source.cartonMark }}</td><td>{{ source.inboundOrderNo }}</td><td>{{ sku.skuCode }}</td><td><div v-for="conversion in (source.skuConversions || []).filter(item => item.status !== 'REVERSED')" :key="`${conversion.relabelNo}-${conversion.oldSkuCode}-${conversion.newSkuCode}`">{{ conversion.oldSkuCode }} → {{ conversion.newSkuCode }}:已换 {{ conversion.quantity }} 件{{ conversion.status === 'APPLIED' ? '(待确认)' : '' }}</div><span v-if="!source.skuConversions?.some(item => item.status !== 'REVERSED')">尚未换标</span></td><td>{{ sku.quantity }}</td><td><el-button size="small" :disabled="inventoryQuantity(source.availablePackages) <= 0" @click="labelingMode === 'sku' ? addReturnSkuBinding(source, sku.skuCode) : addReturnBoxBinding(source)">添加贴标</el-button></td></tr></template><tr v-if="!returnLooseCandidates.length"><td colspan="6">暂无可用包裹库存</td></tr></tbody></table>
|
|
|
|
@@ -1871,8 +1819,8 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {
|
|
|
|
|
<input ref="cartonTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectCartonTotalFile"><input ref="skuTotalCreateInput" class="warehouse-hidden-input" type="file" accept="application/pdf,.pdf" @change="selectSkuTotalFile">
|
|
|
|
|
</section>
|
|
|
|
|
<section class="warehouse-file-group warehouse-transfer-template-group">
|
|
|
|
|
<div class="warehouse-file-group__heading"><div><strong><span>3</span>明细关联模板</strong></div><em>按需使用</em></div><div class="warehouse-template-list"><div><span><strong>SKU 关联</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('sku')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="skuTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div><div><span><strong>箱号关联</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('carton')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="cartonTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div><div><span><strong>SKU 混箱</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate('mixed')"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="mixedTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div></div>
|
|
|
|
|
<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 class="warehouse-file-group__heading"><div><strong><span>3</span>明细关联模板</strong></div><em>按需使用</em></div><div class="warehouse-template-list"><div><span><strong>统一贴标明细</strong></span><el-button size="small" :disabled="!cargoRows.length" @click="downloadRelabelTemplate()"><Download :size="15" />下载模板</el-button><el-button type="primary" plain size="small" :disabled="!cargoRows.length" @click="unifiedTemplateInput?.click()"><Upload :size="15" />上传文件</el-button></div></div>
|
|
|
|
|
<input ref="unifiedTemplateInput" class="warehouse-hidden-input" type="file" accept=".csv,text/csv" @change="importRelabelTemplate">
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="importedRelabelBindings.length" class="warehouse-import-preview"><div class="warehouse-section-heading"><div><strong>待导入绑定关系</strong></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></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></tr></tbody></table></div></div>
|
|
|
|
|