feat(bom+inbound): BOM子件跳转规格修复 + 成品/半成品按钮迁移到标题行

This commit is contained in:
DXC
2026-04-28 10:10:45 +08:00
parent e08eaff40a
commit 97e7618bf3
3 changed files with 127 additions and 30 deletions

View File

@ -83,13 +83,26 @@
</div>
</el-option>
</el-select>
<el-link
v-if="form.parent_id"
type="primary"
:underline="false"
style="margin-left: 12px; font-size: 13px;"
@click="openParentMaterial"
>
<el-icon style="margin-right: 4px"><EditPen /></el-icon>前往修改基础信息
</el-link>
</el-form-item>
</el-col>
</el-row>
<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-form-item>
</el-col>
<el-col :span="16"></el-col>
</el-row>
<el-row :gutter="20">
@ -135,34 +148,45 @@
/>
<el-table :data="filteredChildren" border style="width: 100%; margin-bottom: 15px" max-height="300">
<el-table-column label="子件物料" min-width="280" v-if="hasFormFieldPermission('child_id')">
<el-table-column label="子件物料" min-width="250" v-if="hasFormFieldPermission('child_id')">
<template #default="{ row, $index }">
<!-- ====== 改造:子件下拉 - 远程搜索 + 懒加载 ====== -->
<el-select
v-model="row.child_id"
placeholder="请搜索原料"
filterable
remote
reserve-keyword
:remote-method="(q: string) => handleRemoteSearch(q, 'child', $index)"
:loading="selectLoading"
style="width: 100%"
:loading-text="`正在加载第 ${childQueryParams.page} 页...`"
:popper-class="`bom-loadmore-popper child-popper-${$index}`"
@visible-change="(visible: boolean) => handleVisibleChange(visible, 'child', $index)"
>
<el-option
v-for="item in getChildOptions($index)"
:key="item.id"
:label="`${item.name} (${item.spec})`"
:value="item.id"
<div style="display: flex; align-items: center; gap: 8px;">
<el-select
v-model="row.child_id"
placeholder="请搜索原料"
filterable
remote
reserve-keyword
style="flex: 1;"
:remote-method="(q: string) => handleRemoteSearch(q, 'child', $index)"
:loading="selectLoading"
:loading-text="`正在加载第 ${childQueryParams.page} 页...`"
:popper-class="`bom-loadmore-popper child-popper-${$index}`"
@visible-change="(visible: boolean) => handleVisibleChange(visible, 'child', $index)"
>
<div class="option-row">
<span class="option-name">{{ item.name }}</span>
<span class="option-spec">{{ item.spec }}</span>
</div>
</el-option>
</el-select>
<el-option
v-for="item in getChildOptions($index)"
:key="item.id"
:label="`${item.name} (${item.spec})`"
:value="item.id"
>
<div class="option-row">
<span class="option-name">{{ item.name }}</span>
<span class="option-spec">{{ item.spec }}</span>
</div>
</el-option>
</el-select>
<el-tooltip content="前往修改基础信息" placement="top" v-if="row.child_id">
<el-button
type="primary"
link
:icon="EditPen"
@click.stop="openMaterialInNewTab(row.child_id, getChildSpec($index))"
style="font-size: 16px; padding: 4px;"
/>
</el-tooltip>
</div>
</template>
</el-table-column>
@ -204,7 +228,8 @@
import { ref, reactive, onMounted, computed, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox, FormInstance, FormRules } from 'element-plus'
import { Plus, Search } from '@element-plus/icons-vue'
import { Plus, Search, EditPen } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { getBomList, getBomDetail, saveBom, deleteBom } from '@/api/bom'
import { getMaterialBaseList } from '@/api/inbound/stock'
import { useUserStore } from '@/stores/user'
@ -233,6 +258,7 @@ interface ChildRow {
const userStore = useUserStore()
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const dialogVisible = ref(false)
const saving = ref(false)
@ -467,6 +493,31 @@ const filteredChildren = computed(() => {
})
})
// 获取子件规格(从 childDropdownStates 缓存中查找)
const getChildSpec = (index: number): string => {
const state = childDropdownStates.value.get(index)
if (!state || !form.children[index]?.child_id) return ''
const material = state.options.find((m: MaterialBase) => m.id === form.children[index].child_id)
return material?.spec || ''
}
// 在新标签页打开基础信息编辑
const openMaterialInNewTab = (targetId: number | null, keyword: string = '') => {
if (!targetId) return ElMessage.warning('请先选择物料')
const routeUrl = router.resolve({
path: '/material',
query: { edit_id: targetId, keyword }
})
window.open(routeUrl.href, '_blank')
}
const openParentMaterial = () => {
if (!form.parent_id) return ElMessage.warning('请先选择父件')
const parent = parentOptions.value.find((p: MaterialBase) => p.id === form.parent_id)
const keyword = parent?.spec || parent?.name || ''
openMaterialInNewTab(form.parent_id, keyword)
}
// 列与权限Code的映射关系数据库中的code
const permissionMap: Record<string, string> = {
bom_no: 'bom_manage:bom_no',

View File

@ -250,9 +250,18 @@
<div class="form-card basic-card">
<div class="card-title">
<div style="display: flex; align-items: center;">
<div style="display: flex; align-items: center; gap: 8px;">
<el-icon class="icon"><Box /></el-icon>
<span>1. 基础信息</span>
<el-link
v-if="form.base_id"
type="primary"
:underline="false"
style="font-size: 13px;"
@click="openMaterialInNewTab"
>
<el-icon style="margin-right: 4px"><EditPen /></el-icon>前往修改基础信息
</el-link>
</div>
</div>
<div class="card-content">
@ -561,7 +570,7 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch, computed } from 'vue'
import { Plus, Setting, Refresh, Search, Box, House, Link, InfoFilled, Printer, Camera, Picture } from '@element-plus/icons-vue'
import { Plus, Setting, Refresh, Search, Box, House, Link, InfoFilled, Printer, Camera, Picture, EditPen } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElLoading } from 'element-plus'
import dayjs from 'dayjs'
@ -621,6 +630,20 @@ const vLoadmore = {
const userStore = useUserStore()
const router = useRouter()
// 在新标签页打开基础信息编辑
const openMaterialInNewTab = () => {
if (!form.base_id) return ElMessage.warning('请先选择物料')
const routeUrl = router.resolve({
path: '/material',
query: {
edit_id: form.base_id,
keyword: form.spec_model || form.material_name || ''
}
})
window.open(routeUrl.href, '_blank')
}
const loading = ref(false)
const submitting = ref(false)
const visible = ref(false)

View File

@ -287,9 +287,18 @@
<div class="form-card basic-card">
<div class="card-title">
<div style="display: flex; align-items: center;">
<div style="display: flex; align-items: center; gap: 8px;">
<el-icon class="icon"><Box/></el-icon>
<span>1. 基础信息</span>
<el-link
v-if="form.base_id"
type="primary"
:underline="false"
style="font-size: 13px;"
@click="openMaterialInNewTab"
>
<el-icon style="margin-right: 4px"><EditPen /></el-icon>前往修改基础信息
</el-link>
</div>
<span class="sub-title" v-if="dialogStatus === 'create'"> (请先搜索选择半成品物料)</span>
</div>
@ -616,7 +625,7 @@
<script setup lang="ts">
import {ref, reactive, onMounted, watch, computed} from 'vue'
import {Plus, Setting, Refresh, Search, Lock, Box, House, InfoFilled, Link, Printer, Camera, Picture} from '@element-plus/icons-vue'
import {Plus, Setting, Refresh, Search, Lock, Box, House, InfoFilled, Link, Printer, Camera, Picture, EditPen} from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import {ElMessage, ElLoading} from 'element-plus'
import dayjs from 'dayjs'
@ -678,6 +687,20 @@ const vLoadmore = {
// ------------------------------------
const userStore = useUserStore()
const router = useRouter()
// 在新标签页打开基础信息编辑
const openMaterialInNewTab = () => {
if (!form.base_id) return ElMessage.warning('请先选择物料')
const routeUrl = router.resolve({
path: '/material',
query: {
edit_id: form.base_id,
keyword: form.spec_model || form.material_name || ''
}
})
window.open(routeUrl.href, '_blank')
}
const loading = ref(false)
const submitting = ref(false)
const visible = ref(false)