修改基础信息启用停用内容,进行修复

This commit is contained in:
dxc
2026-01-30 11:21:10 +08:00
parent 06ba2d7563
commit 482c5a2cb2
4 changed files with 509 additions and 285 deletions

View File

@ -0,0 +1,57 @@
# app/models/base.py
from app.extensions import db
class MaterialBase(db.Model):
"""
基础信息表模型
对应数据库表: material_base
"""
__tablename__ = 'material_base'
# 1. 基础字段
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False, comment='基础信息名称')
category = db.Column(db.String(100), comment='类别')
material_type = db.Column(db.String(100), comment='类型')
spec_model = db.Column(db.String(255), comment='规格型号')
unit = db.Column(db.String(50), comment='计量单位')
# 可见等级
visibility_level = db.Column(db.Integer, default=0, comment='信息可见等级')
# 链接与图片
manual_link = db.Column(db.Text, comment='通用说明书')
product_image = db.Column(db.Text, comment='通用产品图')
# 启用状态
is_enabled = db.Column(db.Boolean, default=True, comment='是否启用')
# ============================================================
# 关联关系区域
# ============================================================
# 1. 关联采购库存 (StockBuy)
stock_buys = db.relationship('StockBuy', back_populates='material', lazy='dynamic')
# 2. 关联半成品库存 (StockSemi)
stock_semis = db.relationship('StockSemi', back_populates='material', lazy='dynamic')
# 3. 关联成品库存 (StockProduct)
stock_products = db.relationship('StockProduct', back_populates='material', lazy='dynamic')
def to_dict(self):
"""
序列化方法
"""
return {
'id': self.id,
'name': self.name,
'category': self.category,
'type': self.material_type, # 前端字段映射
'spec': self.spec_model, # 前端字段映射
'unit': self.unit,
'visibilityLevel': self.visibility_level,
'generalManual': self.manual_link,
'generalImage': self.product_image,
'isEnabled': 1 if self.is_enabled else 0,
}

View File

@ -1,57 +0,0 @@
# app/models/material.py
from app.extensions import db
class MaterialBase(db.Model):
"""
基础信息表模型
对应数据库表: material_base
"""
__tablename__ = 'material_base'
# 1. 基础字段
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False, comment='基础信息名称')
category = db.Column(db.String(100), comment='类别')
material_type = db.Column(db.String(100), comment='类型')
spec_model = db.Column(db.String(255), comment='规格型号')
unit = db.Column(db.String(50), comment='计量单位')
# 可见等级
visibility_level = db.Column(db.Integer, default=0, comment='信息可见等级')
# 链接与图片
manual_link = db.Column(db.Text, comment='通用说明书')
product_image = db.Column(db.Text, comment='通用产品图')
# 启用状态
is_enabled = db.Column(db.Boolean, default=True, comment='是否启用')
# ============================================================
# 关联关系区域
# ============================================================
# 1. 关联采购库存 (StockBuy)
stock_buys = db.relationship('StockBuy', back_populates='material', lazy='dynamic')
# 2. 关联半成品库存 (StockSemi)
stock_semis = db.relationship('StockSemi', back_populates='material', lazy='dynamic')
# 3. 关联成品库存 (StockProduct)
stock_products = db.relationship('StockProduct', back_populates='material', lazy='dynamic')
def to_dict(self):
"""
序列化方法
"""
return {
'id': self.id,
'name': self.name,
'category': self.category,
'type': self.material_type, # 前端字段映射
'spec': self.spec_model, # 前端字段映射
'unit': self.unit,
'visibilityLevel': self.visibility_level,
'generalManual': self.manual_link,
'generalImage': self.product_image,
'isEnabled': 1 if self.is_enabled else 0,
}

View File

@ -19,9 +19,10 @@ export function addMaterialBase(data: any) {
} }
// 3. 修改基础信息 (包含状态启用/禁用) // 3. 修改基础信息 (包含状态启用/禁用)
// 【修复点】: 必须在 URL 中拼接 data.id否则后端会报 405 Method Not Allowed
export function updateMaterialBase(data: any) { export function updateMaterialBase(data: any) {
return request({ return request({
url: '/inbound/base/', url: `/inbound/base/${data.id}`,
method: 'put', method: 'put',
data data
}) })
@ -30,7 +31,7 @@ export function updateMaterialBase(data: any) {
// 4. 删除基础信息 // 4. 删除基础信息
export function delMaterialBase(id: number) { export function delMaterialBase(id: number) {
return request({ return request({
url: `/inbound/base/${id}`, // 注意这里是反引号,用于拼接 URL url: `/inbound/base/${id}`,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -118,60 +118,63 @@
<el-dialog <el-dialog
v-model="visible" v-model="visible"
:title="dialogStatus === 'create' ? '新增采购入库' : '编辑入库信息'" :title="dialogStatus === 'create' ? '新增采购入库' : '编辑入库信息'"
width="1050px" width="1000px"
top="5vh" top="4vh"
destroy-on-close destroy-on-close
:close-on-click-modal="false" :close-on-click-modal="false"
class="stylish-dialog" class="stylish-dialog compact-layout"
> >
<el-form :model="form" label-width="110px" ref="formRef" :rules="rules" size="large" class="stylish-form"> <div class="dialog-scroll-container">
<el-form :model="form" label-width="100px" ref="formRef" :rules="rules" size="default" class="stylish-form">
<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>
<div class="card-content"> <div class="card-content">
<el-row :gutter="24" v-if="dialogStatus === 'create'" style="margin-bottom: 20px;"> <el-row :gutter="24" v-if="dialogStatus === 'create'" style="margin-bottom: 15px;">
<el-col :span="14"> <el-col :span="10">
<el-form-item label="物料搜索" prop="base_id" class="highlight-label"> <el-form-item label="物料搜索" prop="base_id" class="highlight-label">
<el-select <el-select
v-model="form.base_id" v-model="form.base_id"
filterable filterable
remote remote
reserve-keyword reserve-keyword
placeholder="输入名称 / 规格型号进行模糊搜索..." placeholder="输入名称或规格..."
:remote-method="handleSearchMaterial" :remote-method="handleSearchMaterial"
@visible-change="handleMaterialDropdownVisible"
:loading="searchLoading" :loading="searchLoading"
style="width: 100%" style="width: 100%"
@change="onMaterialSelected" @change="onMaterialSelected"
size="large" default-first-option
> >
<el-option <el-option
v-for="item in materialOptions" v-for="item in materialOptions"
:key="item.id" :key="item.id"
:label="item.name + ' [' + item.spec + ']'" :label="item.name"
:value="item.id" :value="item.id"
> >
<div class="option-item"> <div class="option-item">
<span class="opt-name">{{ item.name }}</span> <span class="opt-name">{{ item.name }}</span>
<span class="opt-spec">{{ item.spec }}</span> <span class="opt-spec">{{ item.spec }}</span>
<el-tag v-if="item.isHistory" size="small" type="info" effect="plain">历史</el-tag>
</div> </div>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="10"> <el-col :span="14" style="display: flex; align-items: center;">
<div class="info-alert"> <span class="search-tip">
<el-icon><InfoFilled /></el-icon> 仅展示状态为启用的基础物料 <el-icon><InfoFilled /></el-icon> 点击可查看最近使用的物料或输入关键词从云端搜索
</div> </span>
</el-col> </el-col>
</el-row> </el-row>
<div class="read-only-grid"> <div class="read-only-grid">
<el-row :gutter="24"> <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.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.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.unit" disabled class="is-text-view" /></el-form-item></el-col>
@ -189,7 +192,7 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<el-row :gutter="24"> <el-row :gutter="20">
<el-col :span="6"><el-form-item label="编码/SKU" prop="sku"><el-input v-model="form.sku" placeholder="选填" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="编码/SKU" prop="sku"><el-input v-model="form.sku" placeholder="选填" /></el-form-item></el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="入库日期" prop="in_date"> <el-form-item label="入库日期" prop="in_date">
@ -202,16 +205,16 @@
<div class="identity-panel"> <div class="identity-panel">
<el-row> <el-row>
<el-col :span="24" style="margin-bottom: 12px;"> <el-col :span="24" style="margin-bottom: 8px;">
<el-radio-group v-model="entryMode" @change="handleEntryModeChange" :disabled="modeLocked" 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>
<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-col>
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="批号" prop="batch_number"> <el-form-item label="批号" prop="batch_number">
<el-input <el-input
@ -239,7 +242,7 @@
</el-row> </el-row>
</div> </div>
<el-row :gutter="24" style="margin-top: 15px;"> <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" />
@ -282,8 +285,23 @@
<div class="divider-text">商务与采购信息</div> <div class="divider-text">商务与采购信息</div>
<el-row :gutter="24"> <el-row :gutter="20">
<el-col :span="6"><el-form-item label="币种"><el-input v-model="form.currency" /></el-form-item></el-col> <el-col :span="6">
<el-form-item label="币种">
<el-autocomplete
v-model="form.currency"
:fetch-suggestions="querySearchCurrency"
placeholder="币种"
style="width: 100%"
:trigger-on-focus="true"
>
<template #default="{ item }">
<span>{{ item.value }}</span>
<span style="float:right; color:#999; font-size:12px">{{ item.desc }}</span>
</template>
</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-col :span="6">
<el-form-item label="含税单价" prop="unit_price"> <el-form-item label="含税单价" prop="unit_price">
@ -297,13 +315,49 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="20">
<el-col :span="8"><el-form-item label="供应商"><el-input v-model="form.supplier_name" placeholder="供应商全称" /></el-form-item></el-col> <el-col :span="8">
<el-col :span="8"><el-form-item label="采购人"><el-input v-model="form.purchaser" /></el-form-item></el-col> <el-form-item label="供应商">
<el-col :span="8"><el-form-item label="采购邮箱"><el-input v-model="form.purchaser_email" /></el-form-item></el-col> <el-autocomplete
v-model="form.supplier_name"
:fetch-suggestions="querySearchSupplier"
placeholder="输入或选择供应商"
style="width: 100%"
clearable
:trigger-on-focus="true"
@select="handleSupplierSelect"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="采购人">
<el-autocomplete
v-model="form.purchaser"
:fetch-suggestions="querySearchPurchaser"
placeholder="输入采购人"
style="width: 100%"
clearable
:trigger-on-focus="true"
@select="handlePurchaserSelect"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="采购邮箱">
<el-autocomplete
v-model="form.purchaser_email"
:fetch-suggestions="querySearchEmail"
placeholder="输入邮箱"
style="width: 100%"
clearable
:trigger-on-focus="true"
@select="handleEmailSelect"
/>
</el-form-item>
</el-col>
</el-row> </el-row>
<el-row :gutter="24"> <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.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.detail_link" placeholder="http://" /></el-form-item></el-col>
</el-row> </el-row>
@ -311,6 +365,7 @@
</div> </div>
</el-form> </el-form>
</div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@ -392,7 +447,7 @@ const stockColumns = [
const allColumns = [...baseColumns, ...stockColumns] const allColumns = [...baseColumns, ...stockColumns]
// 表头持久化 // 表头持久化
const STORAGE_KEY = 'stock_buy_visible_columns' const STORAGE_KEY_COLS = 'stock_buy_visible_columns'
const defaultColumns = [ const defaultColumns = [
'material_name', 'category', 'material_type', 'spec_model', 'unit', 'material_name', 'category', 'material_type', 'spec_model', 'unit',
'inbound_date', 'serial_number', 'batch_number', 'status', 'inspection_status', 'inbound_date', 'serial_number', 'batch_number', 'status', 'inspection_status',
@ -401,7 +456,7 @@ const defaultColumns = [
const getSavedColumns = () => { const getSavedColumns = () => {
try { try {
const saved = localStorage.getItem(STORAGE_KEY) const saved = localStorage.getItem(STORAGE_KEY_COLS)
return saved ? JSON.parse(saved) : defaultColumns return saved ? JSON.parse(saved) : defaultColumns
} catch (e) { } catch (e) {
return defaultColumns return defaultColumns
@ -411,7 +466,7 @@ const getSavedColumns = () => {
const visibleColumnProps = ref(getSavedColumns()) const visibleColumnProps = ref(getSavedColumns())
watch(visibleColumnProps, (newVal) => { watch(visibleColumnProps, (newVal) => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(newVal)) localStorage.setItem(STORAGE_KEY_COLS, JSON.stringify(newVal))
}, { deep: true }) }, { deep: true })
@ -429,6 +484,163 @@ const form = reactive({
source_link: '', detail_link: '', arrival_photo: '' source_link: '', detail_link: '', arrival_photo: ''
}) })
// ------------------------------------
// 历史记录管理器 (Local Storage)
// ------------------------------------
const HISTORY_KEYS = {
SUPPLIER: 'history_suppliers',
PURCHASER: 'history_purchasers',
EMAIL: 'history_emails',
MATERIAL: 'history_materials'
}
// 保存历史 (String 类型)
const saveToHistory = (key: string, value: string) => {
if (!value) return
try {
const existing = localStorage.getItem(key)
let list = existing ? JSON.parse(existing) : []
// 移除旧的,添加到前面
list = list.filter((i: string) => i !== value)
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) }
}
// 获取历史 (String 类型)
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 [] }
}
// 保存物料历史 (Object 类型)
const saveMaterialHistory = (item: any) => {
if (!item || !item.id) return
const key = HISTORY_KEYS.MATERIAL
try {
const existing = localStorage.getItem(key)
let list = existing ? JSON.parse(existing) : []
// 必须保存完整对象,因为下拉框需要显示 name, spec 等
list = list.filter((i: any) => i.id !== item.id)
list.unshift({ ...item, isHistory: true }) // 标记为历史
if (list.length > 10) list = list.slice(0, 10)
localStorage.setItem(key, JSON.stringify(list))
} catch (e) {}
}
const getMaterialHistory = () => {
try {
const existing = localStorage.getItem(HISTORY_KEYS.MATERIAL)
return existing ? JSON.parse(existing) : []
} catch (e) { return [] }
}
// ------------------------------------
// Autocomplete 建议逻辑 (混合模式:历史+当前表格)
// ------------------------------------
const createFilter = (queryString: string) => {
return (item: any) => {
return (item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
}
}
// 辅助函数:从当前表格提取
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 }))
}
// 通用查询: 历史记录 + 当前页面数据
const mixedSearch = (queryString: string, tableField: string, storageKey: string, cb: any) => {
const tableList = getTableDataUnique(tableField)
const historyList = getHistoryList(storageKey)
// 合并去重
const map = new Map()
historyList.forEach(i => map.set(i.value, i))
tableList.forEach(i => map.set(i.value, i)) // 表格数据优先虽然value一样没区别
const allList = Array.from(map.values())
const results = queryString ? allList.filter(createFilter(queryString)) : allList
cb(results)
}
// 1. 供应商
const querySearchSupplier = (qs: string, cb: any) => mixedSearch(qs, 'supplier_name', HISTORY_KEYS.SUPPLIER, cb)
const handleSupplierSelect = (item: any) => saveToHistory(HISTORY_KEYS.SUPPLIER, item.value)
// 2. 采购人
const querySearchPurchaser = (qs: string, cb: any) => mixedSearch(qs, 'purchaser', HISTORY_KEYS.PURCHASER, cb)
const handlePurchaserSelect = (item: any) => saveToHistory(HISTORY_KEYS.PURCHASER, item.value)
// 3. 邮箱
const querySearchEmail = (qs: string, cb: any) => mixedSearch(qs, 'purchaser_email', HISTORY_KEYS.EMAIL, cb)
const handleEmailSelect = (item: any) => saveToHistory(HISTORY_KEYS.EMAIL, item.value)
// 4. 币种 (固定+过滤)
const currencyOptions = [
{ value: 'CNY', desc: '人民币' },
{ value: 'USD', desc: '美元' },
{ value: 'EUR', desc: '欧元' }
]
const querySearchCurrency = (queryString: string, cb: any) => {
const results = queryString ? currencyOptions.filter(createFilter(queryString)) : currencyOptions
cb(results)
}
// ------------------------------------
// 物料搜索逻辑 (支持历史回显 + API)
// ------------------------------------
// 下拉框展开时触发
const handleMaterialDropdownVisible = (visible: boolean) => {
if (visible) {
// 只有当列表为空时即没有进行API搜索时才填充历史记录
// 这样不会覆盖用户正在搜的结果
if (materialOptions.value.length === 0) {
materialOptions.value = getMaterialHistory()
}
}
}
const handleSearchMaterial = async (query: string) => {
if (query) {
searchLoading.value = true
try {
const res: any = await searchMaterialBase(query)
// 给 API 返回的数据加个标记,区分历史
const apiResults = (res.data || []).map((i: any) => ({ ...i, isHistory: false }))
materialOptions.value = apiResults
} finally {
searchLoading.value = false
}
} else {
// 搜索词清空时,恢复历史记录
materialOptions.value = getMaterialHistory()
}
}
// 选中物料后 -> 存入历史 -> 填充表单
const onMaterialSelected = (val: number) => {
const item = materialOptions.value.find(i => i.id === val)
if (item) {
// 存入历史
saveMaterialHistory(item)
form.material_name = item.name
form.spec_model = item.spec
form.category = item.category
form.unit = item.unit
form.material_type = item.type
checkHistoryAndSetMode(item.id)
}
}
// ------------------------------------ // ------------------------------------
// 逻辑校验规则 // 逻辑校验规则
// ------------------------------------ // ------------------------------------
@ -521,32 +733,6 @@ const handleEntryModeChange = (val: string) => {
} }
} }
const handleSearchMaterial = async (query: string) => {
if (query) {
searchLoading.value = true
try {
const res: any = await searchMaterialBase(query)
materialOptions.value = res.data || []
} finally {
searchLoading.value = false
}
} else {
materialOptions.value = []
}
}
const onMaterialSelected = (val: number) => {
const item = materialOptions.value.find(i => i.id === val)
if (item) {
form.material_name = item.name
form.spec_model = item.spec
form.category = item.category
form.unit = item.unit
form.material_type = item.type
checkHistoryAndSetMode(item.id)
}
}
watch(() => [form.in_quantity, form.unit_price], () => { watch(() => [form.in_quantity, form.unit_price], () => {
form.total_price = Number((form.in_quantity * form.unit_price).toFixed(4)) form.total_price = Number((form.in_quantity * form.unit_price).toFixed(4))
}) })
@ -568,6 +754,8 @@ const handleCreate = () => {
entryMode.value = 'batch' entryMode.value = 'batch'
form.batch_number = '' form.batch_number = ''
visible.value = true visible.value = true
// 每次打开弹窗时,先清空选项,让下拉时触发“历史加载”
materialOptions.value = []
} }
const handleUpdate = (row: any) => { const handleUpdate = (row: any) => {
@ -614,6 +802,14 @@ const handleUpdate = (row: any) => {
form.detail_link = row.detail_link form.detail_link = row.detail_link
form.arrival_photo = row.arrival_photo form.arrival_photo = row.arrival_photo
// 编辑模式下,把当前物料塞入选项,防止显示为 ID
materialOptions.value = [{
id: row.base_id,
name: row.material_name,
spec: row.spec_model,
category: row.category
}]
visible.value = true visible.value = true
} }
@ -635,6 +831,12 @@ const submitForm = async () => {
await updateBuyInbound(form.id!, payload) await updateBuyInbound(form.id!, payload)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} }
// 核心修改:提交成功时,保存供应商等信息到历史记录
saveToHistory(HISTORY_KEYS.SUPPLIER, form.supplier_name)
saveToHistory(HISTORY_KEYS.PURCHASER, form.purchaser)
saveToHistory(HISTORY_KEYS.EMAIL, form.purchaser_email)
await fetchData() await fetchData()
visible.value = false visible.value = false
} catch (e: any) { } catch (e: any) {
@ -688,7 +890,7 @@ onMounted(() => fetchData())
<style scoped> <style scoped>
/* 全局布局 */ /* 全局布局 */
.buy-module { .buy-module {
background: #f5f7fa; /* 整体背景微灰,突出内容 */ background: #f5f7fa;
padding: 20px; padding: 20px;
min-height: 100vh; min-height: 100vh;
} }
@ -727,21 +929,34 @@ onMounted(() => fetchData())
.avail-num { font-weight: bold; color: #67C23A; font-size: 15px; } .avail-num { font-weight: bold; color: #67C23A; font-size: 15px; }
.sum-tag { margin-left: 4px; transform: scale(0.9); } .sum-tag { margin-left: 4px; transform: scale(0.9); }
/* 弹窗与表单美化 */ /* 弹窗核心样式调整 */
:deep(.el-dialog__body) {
padding: 0;
overflow: hidden;
}
/* 内部滚动容器 */
.dialog-scroll-container {
padding: 15px 20px;
max-height: 70vh;
overflow-y: auto;
overflow-x: hidden;
}
.stylish-form .form-card { .stylish-form .form-card {
background: #fff; background: #fff;
border-radius: 8px; border-radius: 8px;
border: 1px solid #e4e7ed; border: 1px solid #e4e7ed;
margin-bottom: 20px; margin-bottom: 15px;
overflow: hidden; overflow: hidden;
} }
.card-title { .card-title {
background: #fcfcfc; background: #fcfcfc;
padding: 12px 20px; padding: 10px 20px;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;
font-weight: 600; font-weight: 600;
font-size: 15px; font-size: 14px;
color: #303133; color: #303133;
display: flex; display: flex;
align-items: center; align-items: center;
@ -749,10 +964,11 @@ onMounted(() => fetchData())
.card-title .icon { margin-right: 8px; font-size: 18px; color: #409EFF; } .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-title .sub-title { font-size: 12px; color: #909399; font-weight: normal; margin-left: 10px; }
.card-content { padding: 20px; } .card-content { padding: 15px 20px; }
/* 基础信息卡片 (蓝色调,示读) */ /* 基础信息卡片 */
.basic-card { border-left: 4px solid #409EFF; } .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) { .is-text-view :deep(.el-input__wrapper) {
box-shadow: none !important; box-shadow: none !important;
background-color: #f5f7fa; background-color: #f5f7fa;
@ -760,7 +976,7 @@ 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; } .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; }
@ -770,8 +986,8 @@ onMounted(() => fetchData())
background: #fffbf0; background: #fffbf0;
border: 1px dashed #e6a23c; border: 1px dashed #e6a23c;
border-radius: 6px; border-radius: 6px;
padding: 15px; padding: 12px;
margin-bottom: 20px; margin-bottom: 15px;
} }
.custom-radio-group { margin-bottom: 10px; } .custom-radio-group { margin-bottom: 10px; }
.locked-msg { font-size: 12px; color: #e6a23c; margin-left: 15px; } .locked-msg { font-size: 12px; color: #e6a23c; margin-left: 15px; }
@ -784,9 +1000,9 @@ onMounted(() => fetchData())
display: flex; display: flex;
align-items: center; align-items: center;
text-align: center; text-align: center;
margin: 30px 0 20px; margin: 20px 0 15px;
color: #909399; color: #909399;
font-size: 14px; font-size: 13px;
font-weight: 500; font-weight: 500;
} }
.divider-text::before, .divider-text::after { .divider-text::before, .divider-text::after {
@ -798,10 +1014,17 @@ onMounted(() => fetchData())
.divider-text::after { margin-left: 15px; } .divider-text::after { margin-left: 15px; }
/* 底部按钮 */ /* 底部按钮 */
.dialog-footer { display: flex; justify-content: flex-end; gap: 15px; margin-top: 20px; } .dialog-footer {
.info-alert { font-size: 12px; color: #909399; margin-top: 10px; display: flex; align-items: center; gap: 5px; } display: flex;
.option-item { display: flex; justify-content: space-between; width: 100%; } justify-content: flex-end;
gap: 15px;
padding: 15px 20px;
background: #fff;
border-top: 1px solid #ebeef5;
}
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center;}
.opt-name { font-weight: bold; } .opt-name { font-weight: bold; }
.opt-spec { color: #8492a6; font-size: 13px; } .opt-spec { color: #8492a6; font-size: 13px; margin-right: 10px; }
.total-price-input :deep(.el-input__inner) { color: #F56C6C; font-weight: bold; } .total-price-input :deep(.el-input__inner) { color: #F56C6C; font-weight: bold; }
</style> </style>