针对于条形码生成进行修改
This commit is contained in:
@ -11,7 +11,7 @@
|
||||
@keyup.enter="fetchData"
|
||||
>
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="fetchData" />
|
||||
<el-button :icon="Search" @click="fetchData"/>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
@ -27,11 +27,15 @@
|
||||
<el-checkbox-group v-model="visibleColumnProps" class="column-selector">
|
||||
<div class="col-group-title">基础信息</div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12" v-for="c in baseColumns" :key="c.prop"><el-checkbox :label="c.prop">{{ c.label }}</el-checkbox></el-col>
|
||||
<el-col :span="12" v-for="c in baseColumns" :key="c.prop">
|
||||
<el-checkbox :label="c.prop">{{ c.label }}</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="col-group-title" style="margin-top:10px">库存与商务</div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12" v-for="c in stockColumns" :key="c.prop"><el-checkbox :label="c.prop">{{ c.label }}</el-checkbox></el-col>
|
||||
<el-col :span="12" v-for="c in stockColumns" :key="c.prop">
|
||||
<el-checkbox :label="c.prop">{{ c.label }}</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-checkbox-group>
|
||||
</el-popover>
|
||||
@ -80,8 +84,12 @@
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop.includes('link')">
|
||||
<el-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank" :underline="false">
|
||||
<el-icon><Link /></el-icon> 查看
|
||||
<el-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank"
|
||||
:underline="false">
|
||||
<el-icon>
|
||||
<Link/>
|
||||
</el-icon>
|
||||
查看
|
||||
</el-link>
|
||||
</template>
|
||||
|
||||
@ -94,7 +102,10 @@
|
||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="warning" size="default" @click="handlePrint(row)">
|
||||
<el-icon><Printer /></el-icon> 打印
|
||||
<el-icon>
|
||||
<Printer/>
|
||||
</el-icon>
|
||||
打印
|
||||
</el-button>
|
||||
<el-button link type="primary" size="default" @click="handleUpdate(row)">编辑</el-button>
|
||||
<el-popconfirm title="确定删除该条记录吗?不可恢复。" @confirm="handleDelete(row)" width="220">
|
||||
@ -132,7 +143,9 @@
|
||||
|
||||
<div class="form-card basic-card">
|
||||
<div class="card-title">
|
||||
<el-icon class="icon"><Box /></el-icon>
|
||||
<el-icon class="icon">
|
||||
<Box/>
|
||||
</el-icon>
|
||||
<span>1. 基础信息</span>
|
||||
<span class="sub-title" v-if="dialogStatus === 'create'"> (请先搜索锁定物料)</span>
|
||||
</div>
|
||||
@ -172,18 +185,38 @@
|
||||
</el-col>
|
||||
<el-col :span="14" style="display: flex; align-items: center;">
|
||||
<span class="search-tip">
|
||||
<el-icon><InfoFilled /></el-icon> 未输入时展示最新物料;输入关键词进行精确搜索。
|
||||
<el-icon><InfoFilled/></el-icon> 未输入时展示最新物料;输入关键词进行精确搜索。
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="read-only-grid">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8"><el-form-item label="名称"><el-input v-model="form.material_name" disabled class="is-text-view" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="规格型号"><el-input v-model="form.spec_model" disabled class="is-text-view" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="单位"><el-input v-model="form.unit" disabled class="is-text-view" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="类别"><el-input v-model="form.category" disabled class="is-text-view" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="类型"><el-input v-model="form.material_type" disabled class="is-text-view" /></el-form-item></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="form.material_name" disabled class="is-text-view"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="规格型号">
|
||||
<el-input v-model="form.spec_model" disabled class="is-text-view"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="单位">
|
||||
<el-input v-model="form.unit" disabled class="is-text-view"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="类别">
|
||||
<el-input v-model="form.category" disabled class="is-text-view"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="类型">
|
||||
<el-input v-model="form.material_type" disabled class="is-text-view"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
@ -191,7 +224,9 @@
|
||||
|
||||
<div class="form-card inbound-card">
|
||||
<div class="card-title">
|
||||
<el-icon class="icon"><House /></el-icon>
|
||||
<el-icon class="icon">
|
||||
<House/>
|
||||
</el-icon>
|
||||
<span>2. 入库详情</span>
|
||||
</div>
|
||||
|
||||
@ -201,28 +236,38 @@
|
||||
<el-form-item label="编码/SKU" prop="sku">
|
||||
<el-input
|
||||
v-model="form.sku"
|
||||
placeholder="系统自动生成 (0000000X)"
|
||||
placeholder="系统自动生成 (000000000X)"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="入库日期" prop="in_date">
|
||||
<el-date-picker v-model="form.in_date" type="date" value-format="YYYY-MM-DD" style="width:100%" disabled />
|
||||
<el-date-picker v-model="form.in_date" type="date" value-format="YYYY-MM-DD" style="width:100%"
|
||||
disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="条码" prop="barcode">
|
||||
<el-input v-model="form.barcode" placeholder="扫描条码"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="库位" prop="warehouse_location">
|
||||
<el-input v-model="form.warehouse_location" placeholder="例如: A-01-02"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6"><el-form-item label="条码" prop="barcode"><el-input v-model="form.barcode" placeholder="扫描条码" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="库位" prop="warehouse_location"><el-input v-model="form.warehouse_location" placeholder="例如: A-01-02" /></el-form-item></el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="identity-panel">
|
||||
<el-row>
|
||||
<el-col :span="24" style="margin-bottom: 8px;">
|
||||
<el-radio-group v-model="entryMode" @change="handleEntryModeChange" :disabled="modeLocked" size="small" class="custom-radio-group">
|
||||
<el-radio-group v-model="entryMode" @change="handleEntryModeChange" :disabled="modeLocked"
|
||||
size="small" class="custom-radio-group">
|
||||
<el-radio-button label="batch">按批号入库 (Batch)</el-radio-button>
|
||||
<el-radio-button label="serial">按序列号入库 (SN)</el-radio-button>
|
||||
</el-radio-group>
|
||||
<span v-if="modeLocked" class="locked-msg"><el-icon><Lock /></el-icon> 历史锁定</span>
|
||||
<span v-if="modeLocked" class="locked-msg"><el-icon><Lock/></el-icon> 历史锁定</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@ -257,27 +302,28 @@
|
||||
<el-row :gutter="20" style="margin-top: 10px;">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="入库数量" prop="in_quantity">
|
||||
<el-input-number v-model="form.in_quantity" :min="1" controls-position="right" style="width:100%" class="strong-input" />
|
||||
<el-input-number v-model="form.in_quantity" :min="1" controls-position="right" style="width:100%"
|
||||
class="strong-input"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<template v-if="dialogStatus === 'update'">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="当前库存" prop="stock_quantity">
|
||||
<el-input-number v-model="form.stock_quantity" disabled style="width:100%" :controls="false" />
|
||||
<el-input-number v-model="form.stock_quantity" disabled style="width:100%" :controls="false"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="当前可用" prop="available_quantity">
|
||||
<el-input-number v-model="form.available_quantity" disabled style="width:100%" :controls="false" />
|
||||
<el-input-number v-model="form.available_quantity" disabled style="width:100%" :controls="false"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="库存状态" prop="status">
|
||||
<el-select v-model="form.status" style="width:100%">
|
||||
<el-option label="在库" value="在库" />
|
||||
<el-option label="出库" value="出库" />
|
||||
<el-option label="损耗" value="损耗" />
|
||||
<el-option label="在库" value="在库"/>
|
||||
<el-option label="出库" value="出库"/>
|
||||
<el-option label="损耗" value="损耗"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -292,7 +338,11 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12"><el-form-item label="到货图片" prop="arrival_photo"><el-input v-model="form.arrival_photo" placeholder="输入图片 URL" /></el-form-item></el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="到货图片" prop="arrival_photo">
|
||||
<el-input v-model="form.arrival_photo" placeholder="输入图片 URL"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="divider-text">商务与采购信息</div>
|
||||
@ -314,15 +364,22 @@
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6"><el-form-item label="汇率"><el-input-number v-model="form.exchange_rate" :precision="2" controls-position="right" style="width:100%"/></el-form-item></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="汇率">
|
||||
<el-input-number v-model="form.exchange_rate" :precision="2" controls-position="right"
|
||||
style="width:100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="含税单价" prop="unit_price">
|
||||
<el-input-number v-model="form.unit_price" :precision="4" controls-position="right" style="width:100%" />
|
||||
<el-input-number v-model="form.unit_price" :precision="4" controls-position="right"
|
||||
style="width:100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="总价">
|
||||
<el-input-number v-model="form.total_price" :precision="2" disabled :controls="false" style="width:100%" class="total-price-input"/>
|
||||
<el-input-number v-model="form.total_price" :precision="2" disabled :controls="false"
|
||||
style="width:100%" class="total-price-input"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -370,8 +427,16 @@
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12"><el-form-item label="原始链接"><el-input v-model="form.source_link" placeholder="http://" /></el-form-item></el-col>
|
||||
<el-col :span="12"><el-form-item label="详情链接"><el-input v-model="form.detail_link" placeholder="http://" /></el-form-item></el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="原始链接">
|
||||
<el-input v-model="form.source_link" placeholder="http://"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="详情链接">
|
||||
<el-input v-model="form.detail_link" placeholder="http://"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
@ -398,7 +463,7 @@
|
||||
>
|
||||
<div style="text-align: center;">
|
||||
<div v-loading="printLoading" class="preview-box">
|
||||
<img v-if="previewUrl" :src="previewUrl" alt="Label Preview" style="width: 100%; border: 1px solid #ccc;" />
|
||||
<img v-if="previewUrl" :src="previewUrl" alt="Label Preview" style="width: 100%; border: 1px solid #ccc;"/>
|
||||
<div v-else class="empty-preview">正在生成预览...</div>
|
||||
</div>
|
||||
|
||||
@ -411,7 +476,10 @@
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="printVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="printing" @click="confirmPrint">
|
||||
<el-icon><Printer /></el-icon> 确认打印
|
||||
<el-icon>
|
||||
<Printer/>
|
||||
</el-icon>
|
||||
确认打印
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
@ -421,9 +489,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, watch } from 'vue'
|
||||
import { Plus, Setting, Refresh, Search, Lock, Box, House, InfoFilled, Link, Printer } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {ref, reactive, onMounted, watch} from 'vue'
|
||||
import {Plus, Setting, Refresh, Search, Lock, Box, House, InfoFilled, Link, Printer} from '@element-plus/icons-vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
getBuyList,
|
||||
@ -432,7 +500,7 @@ import {
|
||||
deleteBuyInbound,
|
||||
searchMaterialBase
|
||||
} from '@/api/inbound/buy'
|
||||
import { getLabelPreview, executePrint } from '@/api/common/print'
|
||||
import {getLabelPreview, executePrint} from '@/api/common/print'
|
||||
|
||||
// ------------------------------------
|
||||
// 状态与变量
|
||||
@ -445,7 +513,7 @@ const dialogStatus = ref<'create' | 'update'>('create')
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const formRef = ref()
|
||||
const queryParams = reactive({ page: 1, pageSize: 15, keyword: '' })
|
||||
const queryParams = reactive({page: 1, pageSize: 15, keyword: ''})
|
||||
const materialOptions = ref<any[]>([])
|
||||
|
||||
// 打印相关变量
|
||||
@ -460,37 +528,37 @@ const modeLocked = ref(false)
|
||||
|
||||
// 列定义
|
||||
const baseColumns = [
|
||||
{ prop: 'material_name', label: '名称' },
|
||||
{ prop: 'category', label: '类别' },
|
||||
{ prop: 'material_type', label: '类型' },
|
||||
{ prop: 'spec_model', label: '规格型号' },
|
||||
{ prop: 'unit', label: '单位' },
|
||||
{prop: 'material_name', label: '名称'},
|
||||
{prop: 'category', label: '类别'},
|
||||
{prop: 'material_type', label: '类型'},
|
||||
{prop: 'spec_model', label: '规格型号'},
|
||||
{prop: 'unit', label: '单位'},
|
||||
]
|
||||
|
||||
const stockColumns = [
|
||||
{ prop: 'id', label: 'ID', minWidth: '60' },
|
||||
{ prop: 'base_id', label: 'BaseID', minWidth: '80' },
|
||||
{ prop: 'sku', label: 'SKU', minWidth: '120' },
|
||||
{ prop: 'inbound_date', label: '入库日期', minWidth: '120' },
|
||||
{ prop: 'barcode', label: '条码', minWidth: '120' },
|
||||
{ prop: 'serial_number', label: '序列号', minWidth: '150' },
|
||||
{ prop: 'batch_number', label: '批号', minWidth: '150' },
|
||||
{ prop: 'status', label: '状态', minWidth: '100' },
|
||||
{ prop: 'inspection_status', label: '到检', minWidth: '100' },
|
||||
{ prop: 'qty_inbound', label: '入库量', minWidth: '100' },
|
||||
{ prop: 'qty_stock', label: '库存数', minWidth: '100' },
|
||||
{ prop: 'qty_available', label: '可用数', minWidth: '100' },
|
||||
{ prop: 'warehouse_loc', label: '库位', minWidth: '120' },
|
||||
{ prop: 'unit_price', label: '单价', minWidth: '120' },
|
||||
{ prop: 'total_price', label: '总价', minWidth: '120' },
|
||||
{ prop: 'currency', label: '币种', minWidth: '80' },
|
||||
{ prop: 'exchange_rate', label: '汇率', minWidth: '80' },
|
||||
{ prop: 'supplier_name', label: '供应商', minWidth: '150' },
|
||||
{ prop: 'purchaser', label: '采购人', minWidth: '100' },
|
||||
{ prop: 'purchaser_email', label: '邮箱', minWidth: '150' },
|
||||
{ prop: 'source_link', label: '采购链接', minWidth: '100' },
|
||||
{ prop: 'detail_link', label: '详情链接', minWidth: '100' },
|
||||
{ prop: 'arrival_photo', label: '到货图', minWidth: '100' }
|
||||
{prop: 'id', label: 'ID', minWidth: '60'},
|
||||
{prop: 'base_id', label: 'BaseID', minWidth: '80'},
|
||||
{prop: 'sku', label: 'SKU', minWidth: '120'},
|
||||
{prop: 'inbound_date', label: '入库日期', minWidth: '120'},
|
||||
{prop: 'barcode', label: '条码', minWidth: '120'},
|
||||
{prop: 'serial_number', label: '序列号', minWidth: '150'},
|
||||
{prop: 'batch_number', label: '批号', minWidth: '150'},
|
||||
{prop: 'status', label: '状态', minWidth: '100'},
|
||||
{prop: 'inspection_status', label: '到检', minWidth: '100'},
|
||||
{prop: 'qty_inbound', label: '入库量', minWidth: '100'},
|
||||
{prop: 'qty_stock', label: '库存数', minWidth: '100'},
|
||||
{prop: 'qty_available', label: '可用数', minWidth: '100'},
|
||||
{prop: 'warehouse_loc', label: '库位', minWidth: '120'},
|
||||
{prop: 'unit_price', label: '单价', minWidth: '120'},
|
||||
{prop: 'total_price', label: '总价', minWidth: '120'},
|
||||
{prop: 'currency', label: '币种', minWidth: '80'},
|
||||
{prop: 'exchange_rate', label: '汇率', minWidth: '80'},
|
||||
{prop: 'supplier_name', label: '供应商', minWidth: '150'},
|
||||
{prop: 'purchaser', label: '采购人', minWidth: '100'},
|
||||
{prop: 'purchaser_email', label: '邮箱', minWidth: '150'},
|
||||
{prop: 'source_link', label: '采购链接', minWidth: '100'},
|
||||
{prop: 'detail_link', label: '详情链接', minWidth: '100'},
|
||||
{prop: 'arrival_photo', label: '到货图', minWidth: '100'}
|
||||
]
|
||||
|
||||
const allColumns = [...baseColumns, ...stockColumns]
|
||||
@ -516,7 +584,7 @@ const visibleColumnProps = ref(getSavedColumns())
|
||||
|
||||
watch(visibleColumnProps, (newVal) => {
|
||||
localStorage.setItem(STORAGE_KEY_COLS, JSON.stringify(newVal))
|
||||
}, { deep: true })
|
||||
}, {deep: true})
|
||||
|
||||
|
||||
const form = reactive({
|
||||
@ -554,7 +622,9 @@ const saveToHistory = (key: string, value: string) => {
|
||||
list.unshift(value)
|
||||
if (list.length > 20) list = list.slice(0, 20) // 最多存20条
|
||||
localStorage.setItem(key, JSON.stringify(list))
|
||||
} catch (e) { console.error('save history failed', e) }
|
||||
} catch (e) {
|
||||
console.error('save history failed', e)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取历史 (String 类型)
|
||||
@ -562,8 +632,10 @@ const getHistoryList = (key: string): any[] => {
|
||||
try {
|
||||
const existing = localStorage.getItem(key)
|
||||
const list = existing ? JSON.parse(existing) : []
|
||||
return list.map((v: string) => ({ value: v }))
|
||||
} catch (e) { return [] }
|
||||
return list.map((v: string) => ({value: v}))
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 保存物料历史 (Object 类型)
|
||||
@ -574,17 +646,20 @@ const saveMaterialHistory = (item: any) => {
|
||||
const existing = localStorage.getItem(key)
|
||||
let list = existing ? JSON.parse(existing) : []
|
||||
list = list.filter((i: any) => i.id !== item.id)
|
||||
list.unshift({ ...item, isHistory: true })
|
||||
list.unshift({...item, isHistory: true})
|
||||
if (list.length > 10) list = list.slice(0, 10)
|
||||
localStorage.setItem(key, JSON.stringify(list))
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
const getMaterialHistory = () => {
|
||||
try {
|
||||
const existing = localStorage.getItem(HISTORY_KEYS.MATERIAL)
|
||||
return existing ? JSON.parse(existing) : []
|
||||
} catch (e) { return [] }
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -600,7 +675,7 @@ const createFilter = (queryString: string) => {
|
||||
// 辅助函数:从当前表格提取
|
||||
const getTableDataUnique = (field: string) => {
|
||||
const uniqueItems = Array.from(new Set(tableData.value.map((i: any) => i[field]).filter(Boolean)))
|
||||
return uniqueItems.map(i => ({ value: i }))
|
||||
return uniqueItems.map(i => ({value: i}))
|
||||
}
|
||||
|
||||
// 通用查询: 历史记录 + 当前页面数据
|
||||
@ -632,9 +707,9 @@ const handleEmailSelect = (item: any) => saveToHistory(HISTORY_KEYS.EMAIL, item.
|
||||
|
||||
// 4. 币种 (固定+过滤)
|
||||
const currencyOptions = [
|
||||
{ value: 'CNY', desc: '人民币' },
|
||||
{ value: 'USD', desc: '美元' },
|
||||
{ value: 'EUR', desc: '欧元' }
|
||||
{value: 'CNY', desc: '人民币'},
|
||||
{value: 'USD', desc: '美元'},
|
||||
{value: 'EUR', desc: '欧元'}
|
||||
]
|
||||
const querySearchCurrency = (queryString: string, cb: any) => {
|
||||
const results = queryString ? currencyOptions.filter(createFilter(queryString)) : currencyOptions
|
||||
@ -657,7 +732,7 @@ const handleSearchMaterial = async (query: string) => {
|
||||
searchLoading.value = true
|
||||
try {
|
||||
const res: any = await searchMaterialBase(query)
|
||||
const apiResults = (res.data || []).map((i: any) => ({ ...i, isHistory: false }))
|
||||
const apiResults = (res.data || []).map((i: any) => ({...i, isHistory: false}))
|
||||
|
||||
if (!query) {
|
||||
const history = getMaterialHistory()
|
||||
@ -715,10 +790,10 @@ const validateIdentity = (rule: any, value: any, callback: any) => {
|
||||
}
|
||||
|
||||
const rules = {
|
||||
base_id: [{ required: true, message: '请选择物料', trigger: 'change' }],
|
||||
in_quantity: [{ required: true, message: '请输入数量', trigger: 'blur' }],
|
||||
serial_number: [{ validator: validateIdentity, trigger: 'blur' }, { validator: validateUnique, trigger: 'blur' }],
|
||||
batch_number: [{ validator: validateIdentity, trigger: 'blur' }, { validator: validateUnique, trigger: 'blur' }]
|
||||
base_id: [{required: true, message: '请选择物料', trigger: 'change'}],
|
||||
in_quantity: [{required: true, message: '请输入数量', trigger: 'blur'}],
|
||||
serial_number: [{validator: validateIdentity, trigger: 'blur'}, {validator: validateUnique, trigger: 'blur'}],
|
||||
batch_number: [{validator: validateIdentity, trigger: 'blur'}, {validator: validateUnique, trigger: 'blur'}]
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
@ -726,7 +801,7 @@ const rules = {
|
||||
// ------------------------------------
|
||||
const checkHistoryAndSetMode = async (baseId: number) => {
|
||||
try {
|
||||
const res: any = await getBuyList({ page: 1, pageSize: 1000 })
|
||||
const res: any = await getBuyList({page: 1, pageSize: 1000})
|
||||
const allItems = res.data.items || []
|
||||
const historyItems = allItems.filter((item: any) => item.base_id === baseId)
|
||||
|
||||
@ -749,7 +824,7 @@ const checkHistoryAndSetMode = async (baseId: number) => {
|
||||
form.batch_number = '000001'
|
||||
}
|
||||
|
||||
if(formRef.value) {
|
||||
if (formRef.value) {
|
||||
formRef.value.clearValidate('serial_number')
|
||||
formRef.value.clearValidate('batch_number')
|
||||
}
|
||||
@ -771,10 +846,10 @@ const handleEntryModeChange = (val: string) => {
|
||||
if (val === 'batch') {
|
||||
form.serial_number = ''
|
||||
form.batch_number = '000001'
|
||||
if(formRef.value) formRef.value.clearValidate('serial_number')
|
||||
if (formRef.value) formRef.value.clearValidate('serial_number')
|
||||
} else {
|
||||
form.batch_number = ''
|
||||
if(formRef.value) formRef.value.clearValidate('batch_number')
|
||||
if (formRef.value) formRef.value.clearValidate('batch_number')
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,7 +863,9 @@ const fetchData = async () => {
|
||||
const res: any = await getBuyList(queryParams)
|
||||
tableData.value = res.data.items || []
|
||||
total.value = res.data.total || 0
|
||||
} finally { loading.value = false }
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCreate = () => {
|
||||
@ -943,7 +1020,7 @@ const handlePrint = async (row: any) => {
|
||||
try {
|
||||
const res: any = await getLabelPreview(printData)
|
||||
previewUrl.value = res.data
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
ElMessage.error('预览生成失败')
|
||||
} finally {
|
||||
printLoading.value = false
|
||||
@ -956,7 +1033,7 @@ const confirmPrint = async () => {
|
||||
await executePrint(currentPrintData.value)
|
||||
ElMessage.success('指令已发送')
|
||||
printVisible.value = false
|
||||
} catch(e: any) {
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e.msg || '打印失败')
|
||||
} finally {
|
||||
printing.value = false
|
||||
@ -980,7 +1057,7 @@ const resetForm = () => {
|
||||
}
|
||||
|
||||
const getStatusType = (status: string) => {
|
||||
const map: any = { '在库': 'success', '出库': 'info', '损耗': 'danger' }
|
||||
const map: any = {'在库': 'success', '出库': 'info', '损耗': 'danger'}
|
||||
return map[status] || 'warning'
|
||||
}
|
||||
|
||||
@ -1009,30 +1086,70 @@ onMounted(() => fetchData())
|
||||
background: #fff;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.left-tools {
|
||||
flex: 0 0 350px;
|
||||
}
|
||||
|
||||
.right-tools {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-weight: 500;
|
||||
}
|
||||
.left-tools { flex: 0 0 350px; }
|
||||
.right-tools { display: flex; gap: 10px; align-items: center; }
|
||||
.action-btn { font-weight: 500; }
|
||||
|
||||
/* 表格美化 */
|
||||
.modern-table {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:deep(.table-header-gray th) {
|
||||
background-color: #f8f9fb !important;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
height: 50px;
|
||||
}
|
||||
.tag-sn { color: #409EFF; font-weight: bold; font-family: monospace; }
|
||||
.tag-bn { color: #67C23A; font-weight: bold; font-family: monospace; }
|
||||
.money-text { font-family: 'Consolas', monospace; color: #303133; }
|
||||
.stock-num { font-weight: bold; color: #333; font-size: 15px; }
|
||||
.avail-num { font-weight: bold; color: #67C23A; font-size: 15px; }
|
||||
.sum-tag { margin-left: 4px; transform: scale(0.9); }
|
||||
|
||||
.tag-sn {
|
||||
color: #409EFF;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.tag-bn {
|
||||
color: #67C23A;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.money-text {
|
||||
font-family: 'Consolas', monospace;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.stock-num {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.avail-num {
|
||||
font-weight: bold;
|
||||
color: #67C23A;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.sum-tag {
|
||||
margin-left: 4px;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
/* 弹窗核心样式调整 */
|
||||
:deep(.el-dialog__body) {
|
||||
@ -1066,14 +1183,38 @@ onMounted(() => fetchData())
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.card-title .icon { margin-right: 8px; font-size: 18px; color: #409EFF; }
|
||||
.card-title .sub-title { font-size: 12px; color: #909399; font-weight: normal; margin-left: 10px; }
|
||||
|
||||
.card-content { padding: 15px 20px; }
|
||||
.card-title .icon {
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
.card-title .sub-title {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
font-weight: normal;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
/* 基础信息卡片 */
|
||||
.basic-card { border-left: 4px solid #409EFF; }
|
||||
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
|
||||
.basic-card {
|
||||
border-left: 4px solid #409EFF;
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.is-text-view :deep(.el-input__wrapper) {
|
||||
box-shadow: none !important;
|
||||
background-color: #f5f7fa;
|
||||
@ -1081,10 +1222,17 @@ onMounted(() => fetchData())
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.is-text-view :deep(.el-input__inner) { color: #606266; font-weight: 500; font-size: 13px; }
|
||||
|
||||
.is-text-view :deep(.el-input__inner) {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 入库信息卡片 */
|
||||
.inbound-card { border-left: 4px solid #67C23A; }
|
||||
.inbound-card {
|
||||
border-left: 4px solid #67C23A;
|
||||
}
|
||||
|
||||
/* 身份区域 (SN/BN) */
|
||||
.identity-panel {
|
||||
@ -1094,11 +1242,33 @@ onMounted(() => fetchData())
|
||||
padding: 12px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.custom-radio-group { margin-bottom: 10px; }
|
||||
.locked-msg { font-size: 12px; color: #e6a23c; margin-left: 15px; }
|
||||
.prefix-tag { font-weight: bold; font-size: 12px; padding: 0 5px; border-radius: 4px; }
|
||||
.prefix-tag.bn { color: #67C23A; background: #f0f9eb; }
|
||||
.prefix-tag.sn { color: #409EFF; background: #ecf5ff; }
|
||||
|
||||
.custom-radio-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.locked-msg {
|
||||
font-size: 12px;
|
||||
color: #e6a23c;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.prefix-tag {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
padding: 0 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.prefix-tag.bn {
|
||||
color: #67C23A;
|
||||
background: #f0f9eb;
|
||||
}
|
||||
|
||||
.prefix-tag.sn {
|
||||
color: #409EFF;
|
||||
background: #ecf5ff;
|
||||
}
|
||||
|
||||
/* 分割线 */
|
||||
.divider-text {
|
||||
@ -1110,13 +1280,20 @@ onMounted(() => fetchData())
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.divider-text::before, .divider-text::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
.divider-text::before { margin-right: 15px; }
|
||||
.divider-text::after { margin-left: 15px; }
|
||||
|
||||
.divider-text::before {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.divider-text::after {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/* 底部按钮 */
|
||||
.dialog-footer {
|
||||
@ -1128,10 +1305,27 @@ onMounted(() => fetchData())
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center;}
|
||||
.opt-name { font-weight: bold; }
|
||||
.opt-spec { color: #8492a6; font-size: 13px; margin-right: 10px; }
|
||||
.total-price-input :deep(.el-input__inner) { color: #F56C6C; font-weight: bold; }
|
||||
.option-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.opt-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.opt-spec {
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.total-price-input :deep(.el-input__inner) {
|
||||
color: #F56C6C;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.preview-box {
|
||||
min-height: 150px;
|
||||
@ -1141,5 +1335,8 @@ onMounted(() => fetchData())
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.empty-preview { color: #909399; }
|
||||
|
||||
.empty-preview {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user