BOM 配方管理:禁止编辑原数据,引入另存为(深拷贝+清 ID)+ 只读查看模式(点击编号进只读弹窗)
This commit is contained in:
@ -35,7 +35,7 @@
|
||||
<el-table :data="group.items" border style="width: 100%">
|
||||
<el-table-column v-if="hasColumnPermission('bom_no')" prop="bom_no" label="BOM编号" min-width="180" sortable>
|
||||
<template #default="{ row }">
|
||||
<span style="cursor: pointer; color: #409EFF;" @click="handleEdit(row)">{{ row.bom_no }}</span>
|
||||
<span style="cursor: pointer; color: #409EFF;" @click="handleView(row)">{{ row.bom_no }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasColumnPermission('parent_name')" prop="parent_name" label="父件名称" min-width="150" show-overflow-tooltip />
|
||||
@ -51,9 +51,8 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasColumnPermission('child_count')" prop="child_count" label="子件数" width="80" align="center" />
|
||||
<el-table-column v-if="userStore.hasPermission('bom_manage:operation')" label="操作" width="250" align="center" fixed="right">
|
||||
<el-table-column v-if="userStore.hasPermission('bom_manage:operation')" label="操作" width="200" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="success" link @click="handleSaveAs(row)">另存为</el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
@ -80,7 +79,7 @@
|
||||
:remote-method="(q: string) => handleRemoteSearch(q, 'parent')"
|
||||
:loading="selectLoading"
|
||||
style="width: 100%"
|
||||
:disabled="isEditMode"
|
||||
:disabled="isReadOnlyMode || isEditMode"
|
||||
class="beautified-select"
|
||||
popper-class="bom-loadmore-popper parent-popper"
|
||||
@visible-change="(visible: boolean) => handleVisibleChange(visible, 'parent')"
|
||||
@ -99,7 +98,7 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-link
|
||||
v-if="form.parent_id"
|
||||
v-if="form.parent_id && !isReadOnlyMode"
|
||||
type="primary"
|
||||
:underline="false"
|
||||
style="margin-left: 12px; font-size: 13px;"
|
||||
@ -114,7 +113,7 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="是否启用" prop="is_enabled" v-if="hasFormFieldPermission('is_enabled')">
|
||||
<el-switch v-model="form.is_enabled" active-text="启用" inactive-text="禁用" :disabled="!userStore.hasPermission('bom_manage:operation')" />
|
||||
<el-switch v-model="form.is_enabled" active-text="启用" inactive-text="禁用" :disabled="isReadOnlyMode || !userStore.hasPermission('bom_manage:operation')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16"></el-col>
|
||||
@ -131,19 +130,19 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="备注" v-if="hasFormFieldPermission('remark')">
|
||||
<el-input v-model="form.remark" placeholder="备注信息(可选)" />
|
||||
<el-input v-model="form.remark" placeholder="备注信息(可选)" :disabled="isReadOnlyMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="版本号" prop="version" v-if="hasFormFieldPermission('version')">
|
||||
<template v-if="isSaveAsMode">
|
||||
<el-radio-group v-model="form.versionUpgradeType" @change="onVersionUpgradeTypeChange">
|
||||
<el-radio-group v-model="form.versionUpgradeType" :disabled="isReadOnlyMode" @change="onVersionUpgradeTypeChange">
|
||||
<el-radio-button label="minor">升级次版本 ({{ versionOptions.minor }})</el-radio-button>
|
||||
<el-radio-button label="major">升级主版本 ({{ versionOptions.major }})</el-radio-button>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input v-model="form.version" placeholder="如: V1.0" />
|
||||
<el-input v-model="form.version" placeholder="如: V1.0" :disabled="isReadOnlyMode" />
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -160,6 +159,7 @@
|
||||
clearable
|
||||
style="width: 300px; margin-bottom: 10px;"
|
||||
:prefix-icon="Search"
|
||||
:disabled="isReadOnlyMode"
|
||||
/>
|
||||
|
||||
<el-table :data="filteredChildren" border style="width: 100%; margin-bottom: 15px" max-height="300">
|
||||
@ -178,6 +178,7 @@
|
||||
:loading="selectLoading"
|
||||
:loading-text="`正在加载第 ${childQueryParams.page} 页...`"
|
||||
:popper-class="`bom-loadmore-popper child-popper-${row.rowKey}`"
|
||||
:disabled="isReadOnlyMode"
|
||||
@visible-change="(visible: boolean) => handleVisibleChange(visible, 'child', row.rowKey)"
|
||||
>
|
||||
<el-option
|
||||
@ -192,7 +193,7 @@
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-tooltip content="前往修改基础信息" placement="top" v-if="row.child_id">
|
||||
<el-tooltip content="前往修改基础信息" placement="top" v-if="row.child_id && !isReadOnlyMode">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@ -207,32 +208,32 @@
|
||||
|
||||
<el-table-column label="用量" width="140" v-if="hasFormFieldPermission('dosage')">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.dosage" :min="0" :precision="0" style="width: 100%" :controls="false" />
|
||||
<el-input-number v-model="row.dosage" :min="0" :precision="0" style="width: 100%" :controls="false" :disabled="isReadOnlyMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="备注" width="150" v-if="hasFormFieldPermission('remark')">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.remark" placeholder="备注" />
|
||||
<el-input v-model="row.remark" placeholder="备注" :disabled="isReadOnlyMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="60" align="center" v-if="userStore.hasPermission('bom_manage:operation')">
|
||||
<template #default="{ row }">
|
||||
<el-button type="danger" link @click="removeChild(row.rowKey)">删</el-button>
|
||||
<el-button v-if="!isReadOnlyMode" type="danger" link @click="removeChild(row.rowKey)">删</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div style="margin-top: 10px; text-align: center;" v-if="hasFormFieldPermission('child_id')">
|
||||
<div style="margin-top: 10px; text-align: center;" v-if="hasFormFieldPermission('child_id') && !isReadOnlyMode">
|
||||
<el-button type="primary" plain :icon="Plus" @click="addChild" style="width: 100%">添加一行子件</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="submitForm">保存</el-button>
|
||||
<el-button @click="dialogVisible = false">{{ isReadOnlyMode ? '关闭' : '取消' }}</el-button>
|
||||
<el-button v-if="!isReadOnlyMode" type="primary" :loading="saving" @click="submitForm">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -280,6 +281,7 @@ const dialogVisible = ref(false)
|
||||
const saving = ref(false)
|
||||
const isEditMode = ref(false)
|
||||
const isSaveAsMode = ref(false)
|
||||
const isReadOnlyMode = ref(false)
|
||||
let originalVersion = ''
|
||||
let currentBomNo = ''
|
||||
let originalChildren: ChildRow[] = []
|
||||
@ -674,27 +676,80 @@ const handleCreate = () => {
|
||||
dialogTitle.value = '新建 BOM'
|
||||
isEditMode.value = false
|
||||
isSaveAsMode.value = false
|
||||
isReadOnlyMode.value = false
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleEdit = async (row: BomItem) => {
|
||||
const handleView = async (row: BomItem) => {
|
||||
await loadDetail(row.bom_no, row.version)
|
||||
dialogTitle.value = '编辑 BOM'
|
||||
isEditMode.value = true
|
||||
dialogTitle.value = '查看 BOM'
|
||||
isEditMode.value = false
|
||||
isSaveAsMode.value = false
|
||||
isReadOnlyMode.value = true
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleSaveAs = async (row: BomItem) => {
|
||||
await loadDetail(row.bom_no, row.version)
|
||||
dialogTitle.value = '另存为新版/变体'
|
||||
isEditMode.value = true
|
||||
isSaveAsMode.value = true
|
||||
originalVersion = form.version
|
||||
// 1. 重置 form 基础状态
|
||||
resetForm()
|
||||
|
||||
// 2. 获取源 BOM 详情(不通过 loadDetail,显式走"深拷贝+清 ID"路径)
|
||||
const res = await getBomDetail(row.bom_no, row.version)
|
||||
if (res.code !== 200) return
|
||||
const raw = JSON.parse(JSON.stringify(res.data))
|
||||
|
||||
// 3. ★ 核心:显式深拷贝 + 清除所有主键 ID(防止后端误判为更新操作)
|
||||
if ('id' in raw) delete raw.id
|
||||
if ('bom_id' in raw) delete raw.bom_id
|
||||
if (Array.isArray(raw.children)) {
|
||||
raw.children.forEach((c: any) => {
|
||||
if ('id' in c) delete c.id
|
||||
if ('bom_id' in c) delete c.bom_id
|
||||
})
|
||||
}
|
||||
|
||||
// 4. 把"已清除 ID 的纯净数据"写入 form(保留子件下拉回显 + 父件下拉回显)
|
||||
form.children = raw.children.map((child: any, idx: number) => ({
|
||||
rowKey: idx,
|
||||
child_id: child.child_id,
|
||||
dosage: child.dosage,
|
||||
remark: child.remark || ''
|
||||
}))
|
||||
form.children.forEach((child, idx) => {
|
||||
initChildDropdownState(idx)
|
||||
if (child.child_id) {
|
||||
const state = childDropdownStates.value.get(idx)!
|
||||
state.options = [{
|
||||
id: raw.children[idx].child_id,
|
||||
name: raw.children[idx].child_name || '未知物料',
|
||||
spec: raw.children[idx].child_spec || ''
|
||||
}]
|
||||
state.hasMore = false
|
||||
}
|
||||
})
|
||||
if (raw.parent_id) {
|
||||
form.parent_id = raw.parent_id
|
||||
parentOptions.value = [{
|
||||
id: raw.parent_id,
|
||||
name: raw.parent_name || '未知产品',
|
||||
spec: raw.parent_spec || ''
|
||||
}]
|
||||
}
|
||||
form.bom_no = (raw.parent_spec || row.bom_no).split('/')[0].trim()
|
||||
form.remark = raw.remark || ''
|
||||
|
||||
// 5. 设置"另存为"模式特有状态(版本升级单选 + 子件变更检测)
|
||||
originalVersion = raw.version || ''
|
||||
currentBomNo = row.bom_no
|
||||
originalChildren = JSON.parse(JSON.stringify(form.children))
|
||||
form.versionUpgradeType = 'minor'
|
||||
form.version = versionOptions.value.minor
|
||||
|
||||
// 6. 弹窗状态机:标题"新增 BOM",父件可改,启用版本升级单选
|
||||
dialogTitle.value = '新增 BOM'
|
||||
isEditMode.value = false
|
||||
isSaveAsMode.value = true
|
||||
isReadOnlyMode.value = false
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
@ -768,6 +823,7 @@ const resetForm = () => {
|
||||
form.is_enabled = true
|
||||
form.children = []
|
||||
isSaveAsMode.value = false
|
||||
isReadOnlyMode.value = false
|
||||
originalVersion = ''
|
||||
currentBomNo = ''
|
||||
childSearchKeyword.value = ''
|
||||
@ -864,9 +920,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
if (existingBom) {
|
||||
// ★ 情况 A:已经有BOM了,直接打开编辑(查看)弹窗
|
||||
// ★ 情况 A:已经有BOM了,直接打开只读查看弹窗
|
||||
ElMessage.success('检测到该物料已有 BOM,已自动为您打开');
|
||||
handleEdit(existingBom);
|
||||
handleView(existingBom);
|
||||
} else {
|
||||
// ★ 情况 B:还没建过BOM,打开新建并注入父件
|
||||
handleCreate();
|
||||
|
||||
Reference in New Issue
Block a user