针对于条形码生成进行修改
This commit is contained in:
@ -88,5 +88,5 @@ class StockBuy(db.Model):
|
|||||||
|
|
||||||
# [新增] 返回全局打印ID及其格式化字符串
|
# [新增] 返回全局打印ID及其格式化字符串
|
||||||
'global_print_id': self.global_print_id,
|
'global_print_id': self.global_print_id,
|
||||||
'global_print_id_str': f"{self.global_print_id:08d}" if self.global_print_id else ""
|
'global_print_id_str': f"{self.global_print_id:010d}" if self.global_print_id else ""
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ class BuyInboundService:
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# 2. 自动生成 SKU (格式: 00000001)
|
# 2. 自动生成 SKU (格式: 00000001)
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
generated_sku = f"{next_global_id:08d}"
|
generated_sku = str(next_global_id).zfill(10)
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# 3. 条码逻辑处理 (核心修改)
|
# 3. 条码逻辑处理 (核心修改)
|
||||||
|
|||||||
@ -26,12 +26,13 @@ class LabelPrintService:
|
|||||||
LABEL_HEIGHT = int(LABEL_HEIGHT_MM * DOTS_PER_MM)
|
LABEL_HEIGHT = int(LABEL_HEIGHT_MM * DOTS_PER_MM)
|
||||||
|
|
||||||
# 顶部留白: 10mm (120px) - 内容从这里开始
|
# 顶部留白: 10mm (120px) - 内容从这里开始
|
||||||
TOP_MARGIN_MM = 5
|
TOP_MARGIN_MM = 2
|
||||||
TOP_MARGIN_PX = int(TOP_MARGIN_MM * DOTS_PER_MM)
|
TOP_MARGIN_PX = int(TOP_MARGIN_MM * DOTS_PER_MM)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_font(size):
|
def _get_font(size):
|
||||||
"""获取字体"""
|
"""获取字体"""
|
||||||
|
# 尝试加载中文字体,否则乱码
|
||||||
font_names = ["simhei.ttf", "msyh.ttf", "SimHei.ttf", "arial.ttf"]
|
font_names = ["simhei.ttf", "msyh.ttf", "SimHei.ttf", "arial.ttf"]
|
||||||
base_dirs = [os.getcwd(), os.path.dirname(__file__)]
|
base_dirs = [os.getcwd(), os.path.dirname(__file__)]
|
||||||
|
|
||||||
@ -48,6 +49,10 @@ class LabelPrintService:
|
|||||||
生成真实的条形码图片
|
生成真实的条形码图片
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# 确保内容字符串有效
|
||||||
|
if not content:
|
||||||
|
content = "0000000000"
|
||||||
|
|
||||||
# 使用 Code128 编码(通用性最强)
|
# 使用 Code128 编码(通用性最强)
|
||||||
code128 = barcode.get('code128', content, writer=ImageWriter())
|
code128 = barcode.get('code128', content, writer=ImageWriter())
|
||||||
|
|
||||||
@ -85,31 +90,31 @@ class LabelPrintService:
|
|||||||
sku_code = data.get('sku')
|
sku_code = data.get('sku')
|
||||||
if not sku_code:
|
if not sku_code:
|
||||||
# 兜底逻辑:如果没有 SKU,尝试用 serial_number 或 global_id
|
# 兜底逻辑:如果没有 SKU,尝试用 serial_number 或 global_id
|
||||||
sku_code = data.get('serial_number') or str(data.get('global_print_id', '00000000')).zfill(8)
|
sku_code = data.get('serial_number') or str(data.get('global_print_id', '0000000000')).zfill(10)
|
||||||
|
|
||||||
# ==================== 绘制布局 ====================
|
# ==================== 绘制布局 ====================
|
||||||
|
|
||||||
# X 轴偏移 (5mm)
|
# X 轴偏移 (5mm)
|
||||||
GLOBAL_OFFSET_X = int(5 * LabelPrintService.DOTS_PER_MM)
|
GLOBAL_OFFSET_X = int(2 * LabelPrintService.DOTS_PER_MM)
|
||||||
|
|
||||||
# Y 轴起始: 10mm 处
|
# Y 轴起始: 10mm 处
|
||||||
CURRENT_Y = LabelPrintService.TOP_MARGIN_PX
|
CURRENT_Y = LabelPrintService.TOP_MARGIN_PX
|
||||||
|
|
||||||
# --- A. 绘制真实条形码 ---
|
# --- A. 绘制真实条形码 (内容为 SKU) ---
|
||||||
bc_w = int(28 * LabelPrintService.DOTS_PER_MM) # 条码宽约 28mm
|
bc_w = int(35 * LabelPrintService.DOTS_PER_MM) # 条码宽约 28mm
|
||||||
bc_h = int(6 * LabelPrintService.DOTS_PER_MM) # 条码高约 6mm
|
bc_h = int(10 * LabelPrintService.DOTS_PER_MM) # 条码高约 6mm
|
||||||
|
|
||||||
# 生成并粘贴条码
|
# 生成并粘贴条码
|
||||||
bc_img = LabelPrintService._generate_barcode_image(sku_code, bc_w, bc_h)
|
bc_img = LabelPrintService._generate_barcode_image(sku_code, bc_w, bc_h)
|
||||||
# 粘贴位置: (X, Y)
|
# 粘贴位置: (X, Y)
|
||||||
img.paste(bc_img, (GLOBAL_OFFSET_X - 5, CURRENT_Y))
|
img.paste(bc_img, (GLOBAL_OFFSET_X - 10, CURRENT_Y))
|
||||||
|
|
||||||
# 更新 Y 坐标 (条码高度 + 间距)
|
# 更新 Y 坐标 (条码高度 + 间距)
|
||||||
CURRENT_Y += bc_h + 5
|
CURRENT_Y += bc_h + 5
|
||||||
|
|
||||||
# --- B. 绘制文字 (统一加粗) ---
|
# --- B. 绘制文字 (统一加粗) ---
|
||||||
|
|
||||||
# 准备数据
|
# 准备数据 (名称、规格等)
|
||||||
name = str(data.get('material_name', '') or '-')
|
name = str(data.get('material_name', '') or '-')
|
||||||
if len(name) > 8: name = name[:7] + ".."
|
if len(name) > 8: name = name[:7] + ".."
|
||||||
|
|
||||||
@ -123,15 +128,43 @@ class LabelPrintService:
|
|||||||
attr = f"{cat}/{typ}"
|
attr = f"{cat}/{typ}"
|
||||||
if len(attr) > 11: attr = attr[:10] + ".."
|
if len(attr) > 11: attr = attr[:10] + ".."
|
||||||
|
|
||||||
# 底部显示的文字:SKU 编号
|
# -----------------------------------------------------------
|
||||||
sku_str = f"NO.{sku_code}"
|
# [修改点] 底部显示的文字:不再显示 NO.SKU,而是显示 SN 或 BN
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
bottom_text = ""
|
||||||
|
|
||||||
|
# 1. 优先检查前端是否传了明确的 print_no (打印值) 和 print_label (序/批)
|
||||||
|
if data.get('print_no'):
|
||||||
|
val = str(data.get('print_no'))
|
||||||
|
label_type = data.get('print_label', '')
|
||||||
|
|
||||||
|
if label_type == '序':
|
||||||
|
bottom_text = f"SN: {val}"
|
||||||
|
elif label_type == '批':
|
||||||
|
bottom_text = f"BN: {val}"
|
||||||
|
else:
|
||||||
|
bottom_text = f"NO: {val}"
|
||||||
|
|
||||||
|
# 2. 如果没有前端打印参数,检查数据中的序列号
|
||||||
|
elif data.get('serial_number'):
|
||||||
|
bottom_text = f"SN: {data.get('serial_number')}"
|
||||||
|
|
||||||
|
# 3. 检查数据中的批号
|
||||||
|
elif data.get('batch_number'):
|
||||||
|
bottom_text = f"BN: {data.get('batch_number')}"
|
||||||
|
|
||||||
|
# 4. 兜底 (如果什么都没有,才显示 SKU)
|
||||||
|
else:
|
||||||
|
bottom_text = f"NO: {sku_code}"
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
f"名: {name}",
|
f"名: {name}",
|
||||||
f"规: {spec}",
|
f"规: {spec}",
|
||||||
f"库: {loc}",
|
f"库: {loc}",
|
||||||
f"属: {attr}",
|
f"属: {attr}",
|
||||||
f"{sku_str}"
|
f"{bottom_text}" # 这里放置计算好的 SN/BN 文字
|
||||||
]
|
]
|
||||||
|
|
||||||
line_height = 36 # 行高 (字号30 + 6间距)
|
line_height = 36 # 行高 (字号30 + 6间距)
|
||||||
|
|||||||
@ -27,11 +27,15 @@
|
|||||||
<el-checkbox-group v-model="visibleColumnProps" class="column-selector">
|
<el-checkbox-group v-model="visibleColumnProps" class="column-selector">
|
||||||
<div class="col-group-title">基础信息</div>
|
<div class="col-group-title">基础信息</div>
|
||||||
<el-row :gutter="10">
|
<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>
|
</el-row>
|
||||||
<div class="col-group-title" style="margin-top:10px">库存与商务</div>
|
<div class="col-group-title" style="margin-top:10px">库存与商务</div>
|
||||||
<el-row :gutter="10">
|
<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-row>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
@ -80,8 +84,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope" v-else-if="col.prop.includes('link')">
|
<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-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank"
|
||||||
<el-icon><Link /></el-icon> 查看
|
:underline="false">
|
||||||
|
<el-icon>
|
||||||
|
<Link/>
|
||||||
|
</el-icon>
|
||||||
|
查看
|
||||||
</el-link>
|
</el-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -94,7 +102,10 @@
|
|||||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button link type="warning" size="default" @click="handlePrint(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>
|
||||||
<el-button link type="primary" size="default" @click="handleUpdate(row)">编辑</el-button>
|
<el-button link type="primary" size="default" @click="handleUpdate(row)">编辑</el-button>
|
||||||
<el-popconfirm title="确定删除该条记录吗?不可恢复。" @confirm="handleDelete(row)" width="220">
|
<el-popconfirm title="确定删除该条记录吗?不可恢复。" @confirm="handleDelete(row)" width="220">
|
||||||
@ -132,7 +143,9 @@
|
|||||||
|
|
||||||
<div class="form-card basic-card">
|
<div class="form-card basic-card">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<el-icon class="icon"><Box /></el-icon>
|
<el-icon class="icon">
|
||||||
|
<Box/>
|
||||||
|
</el-icon>
|
||||||
<span>1. 基础信息</span>
|
<span>1. 基础信息</span>
|
||||||
<span class="sub-title" v-if="dialogStatus === 'create'"> (请先搜索锁定物料)</span>
|
<span class="sub-title" v-if="dialogStatus === 'create'"> (请先搜索锁定物料)</span>
|
||||||
</div>
|
</div>
|
||||||
@ -179,11 +192,31 @@
|
|||||||
|
|
||||||
<div class="read-only-grid">
|
<div class="read-only-grid">
|
||||||
<el-row :gutter="20">
|
<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-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-form-item label="名称">
|
||||||
<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-input v-model="form.material_name" disabled class="is-text-view"/>
|
||||||
<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-form-item>
|
||||||
<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>
|
||||||
|
<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>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -191,7 +224,9 @@
|
|||||||
|
|
||||||
<div class="form-card inbound-card">
|
<div class="form-card inbound-card">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<el-icon class="icon"><House /></el-icon>
|
<el-icon class="icon">
|
||||||
|
<House/>
|
||||||
|
</el-icon>
|
||||||
<span>2. 入库详情</span>
|
<span>2. 入库详情</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -201,24 +236,34 @@
|
|||||||
<el-form-item label="编码/SKU" prop="sku">
|
<el-form-item label="编码/SKU" prop="sku">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.sku"
|
v-model="form.sku"
|
||||||
placeholder="系统自动生成 (0000000X)"
|
placeholder="系统自动生成 (000000000X)"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="入库日期" prop="in_date">
|
<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-form-item>
|
||||||
</el-col>
|
</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>
|
</el-row>
|
||||||
|
|
||||||
<div class="identity-panel">
|
<div class="identity-panel">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24" style="margin-bottom: 8px;">
|
<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="batch">按批号入库 (Batch)</el-radio-button>
|
||||||
<el-radio-button label="serial">按序列号入库 (SN)</el-radio-button>
|
<el-radio-button label="serial">按序列号入库 (SN)</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@ -257,7 +302,8 @@
|
|||||||
<el-row :gutter="20" style="margin-top: 10px;">
|
<el-row :gutter="20" style="margin-top: 10px;">
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="入库数量" prop="in_quantity">
|
<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-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
@ -292,7 +338,11 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</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>
|
</el-row>
|
||||||
|
|
||||||
<div class="divider-text">商务与采购信息</div>
|
<div class="divider-text">商务与采购信息</div>
|
||||||
@ -314,15 +364,22 @@
|
|||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</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-col :span="6">
|
||||||
<el-form-item label="含税单价" prop="unit_price">
|
<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-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="总价">
|
<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-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -370,8 +427,16 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="20">
|
<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-col :span="12"><el-form-item label="详情链接"><el-input v-model="form.detail_link" placeholder="http://" /></el-form-item></el-col>
|
<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>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -411,7 +476,10 @@
|
|||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="printVisible = false">取消</el-button>
|
<el-button @click="printVisible = false">取消</el-button>
|
||||||
<el-button type="primary" :loading="printing" @click="confirmPrint">
|
<el-button type="primary" :loading="printing" @click="confirmPrint">
|
||||||
<el-icon><Printer /></el-icon> 确认打印
|
<el-icon>
|
||||||
|
<Printer/>
|
||||||
|
</el-icon>
|
||||||
|
确认打印
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -554,7 +622,9 @@ const saveToHistory = (key: string, value: string) => {
|
|||||||
list.unshift(value)
|
list.unshift(value)
|
||||||
if (list.length > 20) list = list.slice(0, 20) // 最多存20条
|
if (list.length > 20) list = list.slice(0, 20) // 最多存20条
|
||||||
localStorage.setItem(key, JSON.stringify(list))
|
localStorage.setItem(key, JSON.stringify(list))
|
||||||
} catch (e) { console.error('save history failed', e) }
|
} catch (e) {
|
||||||
|
console.error('save history failed', e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取历史 (String 类型)
|
// 获取历史 (String 类型)
|
||||||
@ -563,7 +633,9 @@ const getHistoryList = (key: string): any[] => {
|
|||||||
const existing = localStorage.getItem(key)
|
const existing = localStorage.getItem(key)
|
||||||
const list = existing ? JSON.parse(existing) : []
|
const list = existing ? JSON.parse(existing) : []
|
||||||
return list.map((v: string) => ({value: v}))
|
return list.map((v: string) => ({value: v}))
|
||||||
} catch (e) { return [] }
|
} catch (e) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存物料历史 (Object 类型)
|
// 保存物料历史 (Object 类型)
|
||||||
@ -577,14 +649,17 @@ const saveMaterialHistory = (item: any) => {
|
|||||||
list.unshift({...item, isHistory: true})
|
list.unshift({...item, isHistory: true})
|
||||||
if (list.length > 10) list = list.slice(0, 10)
|
if (list.length > 10) list = list.slice(0, 10)
|
||||||
localStorage.setItem(key, JSON.stringify(list))
|
localStorage.setItem(key, JSON.stringify(list))
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMaterialHistory = () => {
|
const getMaterialHistory = () => {
|
||||||
try {
|
try {
|
||||||
const existing = localStorage.getItem(HISTORY_KEYS.MATERIAL)
|
const existing = localStorage.getItem(HISTORY_KEYS.MATERIAL)
|
||||||
return existing ? JSON.parse(existing) : []
|
return existing ? JSON.parse(existing) : []
|
||||||
} catch (e) { return [] }
|
} catch (e) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -788,7 +863,9 @@ const fetchData = async () => {
|
|||||||
const res: any = await getBuyList(queryParams)
|
const res: any = await getBuyList(queryParams)
|
||||||
tableData.value = res.data.items || []
|
tableData.value = res.data.items || []
|
||||||
total.value = res.data.total || 0
|
total.value = res.data.total || 0
|
||||||
} finally { loading.value = false }
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
@ -1011,9 +1088,20 @@ onMounted(() => fetchData())
|
|||||||
border-radius: 8px;
|
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; }
|
.left-tools {
|
||||||
.action-btn { font-weight: 500; }
|
flex: 0 0 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-tools {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
/* 表格美化 */
|
/* 表格美化 */
|
||||||
.modern-table {
|
.modern-table {
|
||||||
@ -1021,18 +1109,47 @@ onMounted(() => fetchData())
|
|||||||
overflow: hidden;
|
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) {
|
:deep(.table-header-gray th) {
|
||||||
background-color: #f8f9fb !important;
|
background-color: #f8f9fb !important;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
.tag-sn { color: #409EFF; font-weight: bold; font-family: monospace; }
|
|
||||||
.tag-bn { color: #67C23A; font-weight: bold; font-family: monospace; }
|
.tag-sn {
|
||||||
.money-text { font-family: 'Consolas', monospace; color: #303133; }
|
color: #409EFF;
|
||||||
.stock-num { font-weight: bold; color: #333; font-size: 15px; }
|
font-weight: bold;
|
||||||
.avail-num { font-weight: bold; color: #67C23A; font-size: 15px; }
|
font-family: monospace;
|
||||||
.sum-tag { margin-left: 4px; transform: scale(0.9); }
|
}
|
||||||
|
|
||||||
|
.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) {
|
:deep(.el-dialog__body) {
|
||||||
@ -1066,14 +1183,38 @@ onMounted(() => fetchData())
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
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; }
|
.basic-card {
|
||||||
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
|
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) {
|
.is-text-view :deep(.el-input__wrapper) {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
@ -1081,10 +1222,17 @@ onMounted(() => fetchData())
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding-left: 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) */
|
/* 身份区域 (SN/BN) */
|
||||||
.identity-panel {
|
.identity-panel {
|
||||||
@ -1094,11 +1242,33 @@ onMounted(() => fetchData())
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
.custom-radio-group { margin-bottom: 10px; }
|
|
||||||
.locked-msg { font-size: 12px; color: #e6a23c; margin-left: 15px; }
|
.custom-radio-group {
|
||||||
.prefix-tag { font-weight: bold; font-size: 12px; padding: 0 5px; border-radius: 4px; }
|
margin-bottom: 10px;
|
||||||
.prefix-tag.bn { color: #67C23A; background: #f0f9eb; }
|
}
|
||||||
.prefix-tag.sn { color: #409EFF; background: #ecf5ff; }
|
|
||||||
|
.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 {
|
.divider-text {
|
||||||
@ -1110,13 +1280,20 @@ onMounted(() => fetchData())
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider-text::before, .divider-text::after {
|
.divider-text::before, .divider-text::after {
|
||||||
content: '';
|
content: '';
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-bottom: 1px solid #ebeef5;
|
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 {
|
.dialog-footer {
|
||||||
@ -1128,10 +1305,27 @@ onMounted(() => fetchData())
|
|||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center;}
|
.option-item {
|
||||||
.opt-name { font-weight: bold; }
|
display: flex;
|
||||||
.opt-spec { color: #8492a6; font-size: 13px; margin-right: 10px; }
|
justify-content: space-between;
|
||||||
.total-price-input :deep(.el-input__inner) { color: #F56C6C; font-weight: bold; }
|
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 {
|
.preview-box {
|
||||||
min-height: 150px;
|
min-height: 150px;
|
||||||
@ -1141,5 +1335,8 @@ onMounted(() => fetchData())
|
|||||||
background: #f5f7fa;
|
background: #f5f7fa;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
.empty-preview { color: #909399; }
|
|
||||||
|
.empty-preview {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user