三个基础入库页面修改新增弹窗内容展示,下拉框以及弹窗屏幕大小自适应性
This commit is contained in:
@ -71,15 +71,37 @@
|
|||||||
<div class="card-title"><el-icon class="icon"><Box /></el-icon><span>1. 基础信息</span></div>
|
<div class="card-title"><el-icon class="icon"><Box /></el-icon><span>1. 基础信息</span></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: 20px;">
|
||||||
<el-col :span="14">
|
<el-col :span="10">
|
||||||
<el-form-item label="物料搜索" prop="base_id">
|
<el-form-item label="物料搜索" prop="base_id">
|
||||||
<el-select v-model="form.base_id" filterable remote reserve-keyword placeholder="搜名称/规格..." :remote-method="handleSearchMaterial" :loading="searchLoading" style="width: 100%" @change="onMaterialSelected">
|
<el-select
|
||||||
|
v-model="form.base_id"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="搜名称/规格..."
|
||||||
|
:remote-method="handleSearchMaterial"
|
||||||
|
@visible-change="handleMaterialDropdownVisible"
|
||||||
|
:loading="searchLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="onMaterialSelected"
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
<el-option v-for="item in materialOptions" :key="item.id" :label="item.name" :value="item.id">
|
<el-option v-for="item in materialOptions" :key="item.id" :label="item.name" :value="item.id">
|
||||||
<div class="option-item"><span class="opt-name">{{ item.name }}</span><span class="opt-spec">{{ item.spec }}</span></div>
|
<div class="option-item">
|
||||||
|
<span class="opt-name">{{ item.name }}</span>
|
||||||
|
<span class="opt-spec">{{ item.spec }}</span>
|
||||||
|
<el-tag v-if="item.isHistory" size="small" type="info" effect="plain">历史</el-tag>
|
||||||
|
<el-tag v-else size="small" type="success" effect="plain">系统</el-tag>
|
||||||
|
</div>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="14" style="display: flex; align-items: center;">
|
||||||
|
<span class="search-tip">
|
||||||
|
<el-icon><InfoFilled /></el-icon> 未输入时展示最新物料;输入关键词进行精确搜索。
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div class="read-only-grid">
|
<div class="read-only-grid">
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
@ -140,7 +162,19 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="8"><el-form-item label="订单号"><el-input v-model="form.order_id" placeholder="关联销售订单" /></el-form-item></el-col>
|
<el-col :span="8"><el-form-item label="订单号"><el-input v-model="form.order_id" placeholder="关联销售订单" /></el-form-item></el-col>
|
||||||
<el-col :span="8"><el-form-item label="负责人"><el-input v-model="form.production_manager" /></el-form-item></el-col>
|
<el-col :span="8">
|
||||||
|
<el-form-item label="负责人">
|
||||||
|
<el-autocomplete
|
||||||
|
v-model="form.production_manager"
|
||||||
|
:fetch-suggestions="querySearchManager"
|
||||||
|
placeholder="输入或选择负责人"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
:trigger-on-focus="true"
|
||||||
|
@select="handleManagerSelect"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="8"><el-form-item label="产品定价"><el-input-number v-model="form.sale_price" :precision="2" style="width:100%"><template #prefix>¥</template></el-input-number></el-form-item></el-col>
|
<el-col :span="8"><el-form-item label="产品定价"><el-input-number v-model="form.sale_price" :precision="2" style="width:100%"><template #prefix>¥</template></el-input-number></el-form-item></el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
@ -172,7 +206,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted, watch } from 'vue'
|
import { ref, reactive, onMounted, watch } from 'vue'
|
||||||
import { Plus, Setting, Refresh, Search, Box, House, Link } from '@element-plus/icons-vue'
|
import { Plus, Setting, Refresh, Search, Box, House, Link, InfoFilled } from '@element-plus/icons-vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
// 引用更新后的 product.ts
|
// 引用更新后的 product.ts
|
||||||
@ -228,6 +262,87 @@ const rules = {
|
|||||||
in_quantity: [{ required: true, message: '必填', trigger: 'blur' }]
|
in_quantity: [{ required: true, message: '必填', trigger: 'blur' }]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// 历史记录管理器 (Local Storage)
|
||||||
|
// ------------------------------------
|
||||||
|
const HISTORY_KEYS = {
|
||||||
|
PRODUCTION_MANAGER: 'history_product_managers',
|
||||||
|
MATERIAL: 'history_product_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)
|
||||||
|
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) : []
|
||||||
|
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))
|
||||||
|
const allList = Array.from(map.values())
|
||||||
|
const results = queryString ? allList.filter(createFilter(queryString)) : allList
|
||||||
|
cb(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 负责人
|
||||||
|
const querySearchManager = (qs: string, cb: any) => mixedSearch(qs, 'production_manager', HISTORY_KEYS.PRODUCTION_MANAGER, cb)
|
||||||
|
const handleManagerSelect = (item: any) => saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, item.value)
|
||||||
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
@ -237,19 +352,37 @@ const fetchData = async () => {
|
|||||||
} finally { loading.value = false }
|
} finally { loading.value = false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// 物料搜索逻辑 (优化)
|
||||||
|
// ------------------------------------
|
||||||
|
const handleMaterialDropdownVisible = (visible: boolean) => {
|
||||||
|
if (visible) {
|
||||||
|
if (materialOptions.value.length === 0) {
|
||||||
|
handleSearchMaterial('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleSearchMaterial = async (query: string) => {
|
const handleSearchMaterial = async (query: string) => {
|
||||||
if (query) {
|
|
||||||
searchLoading.value = true
|
searchLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res: any = await searchMaterialBase(query)
|
const res: any = await searchMaterialBase(query)
|
||||||
materialOptions.value = res.data || []
|
const apiResults = (res.data || []).map((i: any) => ({ ...i, isHistory: false }))
|
||||||
} finally { searchLoading.value = false }
|
if (!query) {
|
||||||
|
const history = getMaterialHistory()
|
||||||
|
const historyIds = new Set(history.map((h: any) => h.id))
|
||||||
|
const filteredApi = apiResults.filter((apiItem: any) => !historyIds.has(apiItem.id))
|
||||||
|
materialOptions.value = [...history, ...filteredApi]
|
||||||
|
} else {
|
||||||
|
materialOptions.value = apiResults
|
||||||
}
|
}
|
||||||
|
} finally { searchLoading.value = false }
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMaterialSelected = (val: number) => {
|
const onMaterialSelected = (val: number) => {
|
||||||
const item = materialOptions.value.find(i => i.id === val)
|
const item = materialOptions.value.find(i => i.id === val)
|
||||||
if (item) {
|
if (item) {
|
||||||
|
saveMaterialHistory(item)
|
||||||
form.material_name = item.name
|
form.material_name = item.name
|
||||||
form.spec_model = item.spec
|
form.spec_model = item.spec
|
||||||
form.material_type = item.type
|
form.material_type = item.type
|
||||||
@ -261,6 +394,7 @@ const handleCreate = () => {
|
|||||||
resetForm()
|
resetForm()
|
||||||
form.in_date = dayjs().format('YYYY-MM-DD')
|
form.in_date = dayjs().format('YYYY-MM-DD')
|
||||||
visible.value = true
|
visible.value = true
|
||||||
|
materialOptions.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUpdate = (row: any) => {
|
const handleUpdate = (row: any) => {
|
||||||
@ -272,6 +406,13 @@ const handleUpdate = (row: any) => {
|
|||||||
} else {
|
} else {
|
||||||
form.production_time_range = []
|
form.production_time_range = []
|
||||||
}
|
}
|
||||||
|
// 编辑模式下填充当前物料
|
||||||
|
materialOptions.value = [{
|
||||||
|
id: row.base_id,
|
||||||
|
name: row.material_name,
|
||||||
|
spec: row.spec_model,
|
||||||
|
isHistory: false
|
||||||
|
}]
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +427,10 @@ const submitForm = async () => {
|
|||||||
}
|
}
|
||||||
if(dialogStatus.value === 'create') await createProductInbound(payload)
|
if(dialogStatus.value === 'create') await createProductInbound(payload)
|
||||||
else await updateProductInbound(form.id!, payload)
|
else await updateProductInbound(form.id!, payload)
|
||||||
|
|
||||||
|
// 保存历史
|
||||||
|
saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, form.production_manager)
|
||||||
|
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
visible.value = false
|
visible.value = false
|
||||||
fetchData()
|
fetchData()
|
||||||
@ -334,7 +479,9 @@ onMounted(() => fetchData())
|
|||||||
.production-card { border-left: 4px solid #E6A23C; }
|
.production-card { border-left: 4px solid #E6A23C; }
|
||||||
.identity-panel { background: #fffbf0; border: 1px dashed #e6a23c; padding: 15px; margin: 10px 0; border-radius: 6px; }
|
.identity-panel { background: #fffbf0; border: 1px dashed #e6a23c; padding: 15px; margin: 10px 0; border-radius: 6px; }
|
||||||
.prefix-tag.sn { color: #409EFF; background: #ecf5ff; padding: 0 5px; font-weight: bold; }
|
.prefix-tag.sn { color: #409EFF; background: #ecf5ff; padding: 0 5px; font-weight: bold; }
|
||||||
.option-item { display: flex; justify-content: space-between; width: 100%; }
|
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center; }
|
||||||
.opt-spec { color: #8492a6; font-size: 12px; }
|
.opt-name { font-weight: bold; }
|
||||||
|
.opt-spec { color: #8492a6; font-size: 12px; margin-right: 10px; }
|
||||||
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background: #f5f7fa; border-bottom: 1px solid #dcdfe6; }
|
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background: #f5f7fa; border-bottom: 1px solid #dcdfe6; }
|
||||||
|
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
|
||||||
</style>
|
</style>
|
||||||
@ -141,38 +141,42 @@
|
|||||||
|
|
||||||
<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: 20px;">
|
||||||
<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"
|
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>
|
||||||
|
<el-tag v-else size="small" type="success" 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>
|
||||||
|
|
||||||
@ -303,7 +307,19 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="8"><el-form-item label="生产负责人"><el-input v-model="form.production_manager" /></el-form-item></el-col>
|
<el-col :span="8">
|
||||||
|
<el-form-item label="生产负责人">
|
||||||
|
<el-autocomplete
|
||||||
|
v-model="form.production_manager"
|
||||||
|
:fetch-suggestions="querySearchManager"
|
||||||
|
placeholder="输入或选择负责人"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
:trigger-on-focus="true"
|
||||||
|
@select="handleManagerSelect"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<el-form-item label="生产时间">
|
<el-form-item label="生产时间">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
@ -481,6 +497,93 @@ const form = reactive({
|
|||||||
detail_link: ''
|
detail_link: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// 历史记录管理器 (Local Storage)
|
||||||
|
// ------------------------------------
|
||||||
|
const HISTORY_KEYS = {
|
||||||
|
PRODUCTION_MANAGER: 'history_production_managers',
|
||||||
|
MATERIAL: 'history_semi_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) : []
|
||||||
|
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))
|
||||||
|
|
||||||
|
const allList = Array.from(map.values())
|
||||||
|
const results = queryString ? allList.filter(createFilter(queryString)) : allList
|
||||||
|
cb(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 生产负责人
|
||||||
|
const querySearchManager = (qs: string, cb: any) => mixedSearch(qs, 'production_manager', HISTORY_KEYS.PRODUCTION_MANAGER, cb)
|
||||||
|
const handleManagerSelect = (item: any) => saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, item.value)
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
// 逻辑校验规则
|
// 逻辑校验规则
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
@ -573,23 +676,41 @@ const handleEntryModeChange = (val: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// 物料搜索逻辑 (优化:支持空查询加载默认值)
|
||||||
|
// ------------------------------------
|
||||||
|
const handleMaterialDropdownVisible = (visible: boolean) => {
|
||||||
|
if (visible) {
|
||||||
|
if (materialOptions.value.length === 0) {
|
||||||
|
handleSearchMaterial('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleSearchMaterial = async (query: string) => {
|
const handleSearchMaterial = async (query: string) => {
|
||||||
if (query) {
|
|
||||||
searchLoading.value = true
|
searchLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res: any = await searchMaterialBase(query)
|
const res: any = await searchMaterialBase(query)
|
||||||
materialOptions.value = res.data || []
|
const apiResults = (res.data || []).map((i: any) => ({ ...i, isHistory: false }))
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
const history = getMaterialHistory()
|
||||||
|
const historyIds = new Set(history.map((h: any) => h.id))
|
||||||
|
const filteredApi = apiResults.filter((apiItem: any) => !historyIds.has(apiItem.id))
|
||||||
|
materialOptions.value = [...history, ...filteredApi]
|
||||||
|
} else {
|
||||||
|
materialOptions.value = apiResults
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
searchLoading.value = false
|
searchLoading.value = false
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
materialOptions.value = []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMaterialSelected = (val: number) => {
|
const onMaterialSelected = (val: number) => {
|
||||||
const item = materialOptions.value.find(i => i.id === val)
|
const item = materialOptions.value.find(i => i.id === val)
|
||||||
if (item) {
|
if (item) {
|
||||||
|
saveMaterialHistory(item)
|
||||||
|
|
||||||
form.material_name = item.name
|
form.material_name = item.name
|
||||||
form.spec_model = item.spec
|
form.spec_model = item.spec
|
||||||
form.category = item.category
|
form.category = item.category
|
||||||
@ -621,6 +742,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) => {
|
||||||
@ -673,6 +796,14 @@ const handleUpdate = (row: any) => {
|
|||||||
form.quality_report_link = row.quality_report_link
|
form.quality_report_link = row.quality_report_link
|
||||||
form.detail_link = row.detail_link
|
form.detail_link = row.detail_link
|
||||||
|
|
||||||
|
// 编辑模式下,把当前物料塞入选项,防止显示为 ID
|
||||||
|
materialOptions.value = [{
|
||||||
|
id: row.base_id,
|
||||||
|
name: row.material_name,
|
||||||
|
spec: row.spec_model,
|
||||||
|
category: row.category
|
||||||
|
}]
|
||||||
|
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,6 +831,10 @@ const submitForm = async () => {
|
|||||||
await updateSemiInbound(form.id!, payload)
|
await updateSemiInbound(form.id!, payload)
|
||||||
ElMessage.success('更新成功')
|
ElMessage.success('更新成功')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存生产负责人信息到历史记录
|
||||||
|
saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, form.production_manager)
|
||||||
|
|
||||||
await fetchData()
|
await fetchData()
|
||||||
visible.value = false
|
visible.value = false
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -824,6 +959,7 @@ onMounted(() => fetchData())
|
|||||||
|
|
||||||
/* 基础信息卡片 (蓝色调,示读) */
|
/* 基础信息卡片 (蓝色调,示读) */
|
||||||
.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;
|
||||||
@ -876,8 +1012,8 @@ onMounted(() => fetchData())
|
|||||||
/* 底部按钮 */
|
/* 底部按钮 */
|
||||||
.dialog-footer { display: flex; justify-content: flex-end; gap: 15px; margin-top: 20px; }
|
.dialog-footer { display: flex; justify-content: flex-end; gap: 15px; margin-top: 20px; }
|
||||||
.info-alert { font-size: 12px; color: #909399; margin-top: 10px; display: flex; align-items: center; gap: 5px; }
|
.info-alert { font-size: 12px; color: #909399; margin-top: 10px; display: flex; align-items: center; gap: 5px; }
|
||||||
.option-item { display: flex; justify-content: space-between; width: 100%; }
|
.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>
|
||||||
Reference in New Issue
Block a user