Compare commits
4 Commits
7c9331d78a
...
f701ed7fc8
| Author | SHA1 | Date | |
|---|---|---|---|
| f701ed7fc8 | |||
| d53362f06f | |||
| 2574da03e5 | |||
| 6dfc540dc1 |
@ -844,7 +844,7 @@ const tempCategorySuffix = ref<string>('');
|
|||||||
|
|
||||||
const queryParams = reactive<QueryParams>({
|
const queryParams = reactive<QueryParams>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 100,
|
pageSize: 10,
|
||||||
keyword: '',
|
keyword: '',
|
||||||
searchField: 'all',
|
searchField: 'all',
|
||||||
category: '',
|
category: '',
|
||||||
|
|||||||
@ -150,9 +150,10 @@
|
|||||||
:sortable="isColumnSortable(col.prop) ? 'custom' : false"
|
:sortable="isColumnSortable(col.prop) ? 'custom' : false"
|
||||||
>
|
>
|
||||||
<template #default="scope" v-if="col.prop === 'material_name'">
|
<template #default="scope" v-if="col.prop === 'material_name'">
|
||||||
<span class="clickable-text" @click="handleUpdate(scope.row)">
|
<span v-if="userStore.hasPermission('inbound_buy:operation')" class="clickable-text" @click="handleUpdate(scope.row)">
|
||||||
{{ scope.row.material_name }}
|
{{ scope.row.material_name }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else>{{ scope.row.material_name }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope" v-else-if="col.prop === 'sn_bn'">
|
<template #default="scope" v-else-if="col.prop === 'sn_bn'">
|
||||||
|
|||||||
@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="tableData"
|
:data="displayData"
|
||||||
border
|
border
|
||||||
stripe
|
stripe
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@ -145,7 +145,7 @@
|
|||||||
>
|
>
|
||||||
<template v-for="col in allColumns" :key="col.prop">
|
<template v-for="col in allColumns" :key="col.prop">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-if="visibleColumnProps.includes(col.prop)"
|
v-if="visibleColumnProps.includes(col.prop) && hasColumnPermission(col.prop)"
|
||||||
:prop="col.prop"
|
:prop="col.prop"
|
||||||
:label="col.label"
|
:label="col.label"
|
||||||
:min-width="col.minWidth || '110'"
|
:min-width="col.minWidth || '110'"
|
||||||
@ -154,9 +154,10 @@
|
|||||||
>
|
>
|
||||||
|
|
||||||
<template #default="scope" v-if="col.prop === 'material_name'">
|
<template #default="scope" v-if="col.prop === 'material_name'">
|
||||||
<span class="clickable-text" @click="handleUpdate(scope.row)">
|
<span v-if="userStore.hasPermission('inbound_product:operation')" class="clickable-text" @click="handleUpdate(scope.row)">
|
||||||
{{ scope.row.material_name }}
|
{{ scope.row.material_name }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else>{{ scope.row.material_name }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope" v-else-if="col.prop === 'company_name'">
|
<template #default="scope" v-else-if="col.prop === 'company_name'">
|
||||||
@ -740,11 +741,14 @@ const permissionMap: Record<string, string> = {
|
|||||||
inbound_date: 'inbound_product:inbound_date',
|
inbound_date: 'inbound_product:inbound_date',
|
||||||
barcode: 'inbound_product:barcode',
|
barcode: 'inbound_product:barcode',
|
||||||
serial_number: 'inbound_product:serial_number',
|
serial_number: 'inbound_product:serial_number',
|
||||||
|
sn_bn: 'inbound_product:sn_bn',
|
||||||
batch_number: 'inbound_product:serial_number',
|
batch_number: 'inbound_product:serial_number',
|
||||||
status: 'inbound_product:status',
|
status: 'inbound_product:status',
|
||||||
quality_status: 'inbound_product:quality_status',
|
quality_status: 'inbound_product:quality_status',
|
||||||
in_quantity: 'inbound_product:in_quantity',
|
in_quantity: 'inbound_product:in_quantity',
|
||||||
|
qty_stock: 'inbound_product:qty_stock',
|
||||||
stock_quantity: 'inbound_product:stock_quantity',
|
stock_quantity: 'inbound_product:stock_quantity',
|
||||||
|
qty_available: 'inbound_product:qty_available',
|
||||||
available_quantity: 'inbound_product:available_quantity',
|
available_quantity: 'inbound_product:available_quantity',
|
||||||
warehouse_location: 'inbound_product:warehouse_location',
|
warehouse_location: 'inbound_product:warehouse_location',
|
||||||
bom_code: 'inbound_product:bom_code',
|
bom_code: 'inbound_product:bom_code',
|
||||||
@ -791,11 +795,46 @@ const initColumnPermissions = () => {
|
|||||||
visibleColumnProps.value = defaultVisibleCols
|
visibleColumnProps.value = defaultVisibleCols
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查列权限(移除权限限制,始终返回 true)
|
// 检查列权限
|
||||||
const hasColumnPermission = (prop: string) => {
|
const hasColumnPermission = (prop: string) => {
|
||||||
return true
|
if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const code = permissionMap[prop]
|
||||||
|
return code ? userStore.hasPermission(code) : false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ★ 智能聚合:当无序列号权限时,按 SKU 聚合库存
|
||||||
|
const displayData = computed(() => {
|
||||||
|
// 检查是否有序列号权限
|
||||||
|
const hasSnPermission = hasColumnPermission('sn_bn') || hasColumnPermission('serial_number')
|
||||||
|
if (hasSnPermission || !tableData.value.length) {
|
||||||
|
return tableData.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无权限时,按 SKU + 规格型号聚合
|
||||||
|
const aggMap = new Map<string, any>()
|
||||||
|
for (const item of tableData.value) {
|
||||||
|
const key = `${item.sku || ''}_${item.spec_model || item.spec || ''}`
|
||||||
|
if (aggMap.has(key)) {
|
||||||
|
const existing = aggMap.get(key)
|
||||||
|
// 累加库存数量
|
||||||
|
existing.qty_stock = (existing.qty_stock || 0) + (item.qty_stock || 0)
|
||||||
|
existing.qty_available = (existing.qty_available || 0) + (item.qty_available || 0)
|
||||||
|
existing.stock_quantity = (existing.stock_quantity || 0) + (item.stock_quantity || 0)
|
||||||
|
existing.available_quantity = (existing.available_quantity || 0) + (item.available_quantity || 0)
|
||||||
|
existing.in_quantity = (existing.in_quantity || 0) + (item.in_quantity || 0)
|
||||||
|
// 累加其他数量字段
|
||||||
|
existing.total_price = (existing.total_price || 0) + (item.total_price || 0)
|
||||||
|
existing.raw_material_cost = (existing.raw_material_cost || 0) + (item.raw_material_cost || 0)
|
||||||
|
existing.unit_total_cost = (existing.unit_total_cost || 0) + (item.unit_total_cost || 0)
|
||||||
|
} else {
|
||||||
|
aggMap.set(key, { ...item })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(aggMap.values())
|
||||||
|
})
|
||||||
|
|
||||||
const defaultVisibleCols = ['company_name', 'material_name', 'sku', 'serial_number', 'qty_stock', 'status', 'quality_status', 'product_photo', 'sale_price', 'order_id']
|
const defaultVisibleCols = ['company_name', 'material_name', 'sku', 'serial_number', 'qty_stock', 'status', 'quality_status', 'product_photo', 'sale_price', 'order_id']
|
||||||
const visibleColumnProps = ref(defaultVisibleCols)
|
const visibleColumnProps = ref(defaultVisibleCols)
|
||||||
|
|
||||||
|
|||||||
@ -158,7 +158,7 @@
|
|||||||
>
|
>
|
||||||
<template v-for="col in allColumns" :key="col.prop">
|
<template v-for="col in allColumns" :key="col.prop">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-if="visibleColumnProps.includes(col.prop)"
|
v-if="visibleColumnProps.includes(col.prop) && hasColumnPermission(col.prop)"
|
||||||
:prop="col.prop"
|
:prop="col.prop"
|
||||||
:label="col.label"
|
:label="col.label"
|
||||||
:min-width="col.minWidth || '140'"
|
:min-width="col.minWidth || '140'"
|
||||||
@ -166,9 +166,10 @@
|
|||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
>
|
>
|
||||||
<template #default="scope" v-if="col.prop === 'material_name'">
|
<template #default="scope" v-if="col.prop === 'material_name'">
|
||||||
<span class="clickable-text" @click="handleUpdate(scope.row)">
|
<span v-if="userStore.hasPermission('inbound_semi:operation')" class="clickable-text" @click="handleUpdate(scope.row)">
|
||||||
{{ scope.row.material_name }}
|
{{ scope.row.material_name }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else>{{ scope.row.material_name }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope" v-else-if="col.prop === 'company_name'">
|
<template #default="scope" v-else-if="col.prop === 'company_name'">
|
||||||
@ -808,40 +809,6 @@ const stockColumns = [
|
|||||||
]
|
]
|
||||||
const allColumns = [...baseColumns, ...stockColumns]
|
const allColumns = [...baseColumns, ...stockColumns]
|
||||||
|
|
||||||
// 列与权限Code的映射关系(数据库中的code)
|
|
||||||
const permissionMap: Record<string, string> = {
|
|
||||||
id: 'inbound_semi:id',
|
|
||||||
base_id: 'inbound_semi:base_id',
|
|
||||||
company_name: 'inbound_semi:company_name',
|
|
||||||
material_name: 'inbound_semi:material_name',
|
|
||||||
category: 'inbound_semi:category',
|
|
||||||
material_type: 'inbound_semi:material_type',
|
|
||||||
spec_model: 'inbound_semi:spec_model',
|
|
||||||
unit: 'inbound_semi:unit',
|
|
||||||
sku: 'inbound_semi:sku',
|
|
||||||
inbound_date: 'inbound_semi:inbound_date',
|
|
||||||
barcode: 'inbound_semi:barcode',
|
|
||||||
sn_bn: 'inbound_semi:sn_bn',
|
|
||||||
status: 'inbound_semi:status',
|
|
||||||
quality_status: 'inbound_semi:quality_status',
|
|
||||||
qty_inbound: 'inbound_semi:qty_inbound',
|
|
||||||
qty_stock: 'inbound_semi:qty_stock',
|
|
||||||
qty_available: 'inbound_semi:qty_available',
|
|
||||||
warehouse_loc: 'inbound_semi:warehouse_loc',
|
|
||||||
bom_code: 'inbound_semi:bom_code',
|
|
||||||
bom_version: 'inbound_semi:bom_version',
|
|
||||||
work_order_code: 'inbound_semi:work_order_code',
|
|
||||||
raw_material_cost: 'inbound_semi:raw_material_cost',
|
|
||||||
unit_total_cost: 'inbound_semi:unit_total_cost',
|
|
||||||
total_price: 'inbound_semi:total_price',
|
|
||||||
production_manager: 'inbound_semi:production_manager',
|
|
||||||
production_start_time: 'inbound_semi:production_start_time',
|
|
||||||
production_end_time: 'inbound_semi:production_end_time',
|
|
||||||
arrival_photo: 'inbound_semi:arrival_photo',
|
|
||||||
quality_report_link: 'inbound_semi:quality_report_link',
|
|
||||||
detail_link: 'inbound_semi:detail_link',
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据用户权限初始化列显示状态
|
// 根据用户权限初始化列显示状态
|
||||||
// 初始化列显示状态(移除权限限制,添加 localStorage 支持)
|
// 初始化列显示状态(移除权限限制,添加 localStorage 支持)
|
||||||
const initColumnPermissions = () => {
|
const initColumnPermissions = () => {
|
||||||
@ -871,9 +838,52 @@ const initColumnPermissions = () => {
|
|||||||
visibleColumnProps.value = defaultColumns
|
visibleColumnProps.value = defaultColumns
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查列权限(移除权限限制,始终返回 true)
|
// 列与权限Code的映射关系(数据库中的code)
|
||||||
|
const permissionMap: Record<string, string> = {
|
||||||
|
id: 'inbound_semi:id',
|
||||||
|
base_id: 'inbound_semi:base_id',
|
||||||
|
company_name: 'inbound_semi:company_name',
|
||||||
|
material_name: 'inbound_semi:material_name',
|
||||||
|
spec_model: 'inbound_semi:spec_model',
|
||||||
|
category: 'inbound_semi:category',
|
||||||
|
material_type: 'inbound_semi:material_type',
|
||||||
|
unit: 'inbound_semi:unit',
|
||||||
|
sku: 'inbound_semi:sku',
|
||||||
|
inbound_date: 'inbound_semi:inbound_date',
|
||||||
|
barcode: 'inbound_semi:barcode',
|
||||||
|
serial_number: 'inbound_semi:serial_number',
|
||||||
|
batch_number: 'inbound_semi:batch_number',
|
||||||
|
status: 'inbound_semi:status',
|
||||||
|
quality_status: 'inbound_semi:quality_status',
|
||||||
|
in_quantity: 'inbound_semi:in_quantity',
|
||||||
|
qty_inbound: 'inbound_semi:qty_inbound',
|
||||||
|
stock_quantity: 'inbound_semi:stock_quantity',
|
||||||
|
qty_stock: 'inbound_semi:qty_stock',
|
||||||
|
available_quantity: 'inbound_semi:available_quantity',
|
||||||
|
qty_available: 'inbound_semi:qty_available',
|
||||||
|
warehouse_location: 'inbound_semi:warehouse_location',
|
||||||
|
warehouse_loc: 'inbound_semi:warehouse_loc',
|
||||||
|
bom_code: 'inbound_semi:bom_code',
|
||||||
|
bom_version: 'inbound_semi:bom_version',
|
||||||
|
work_order_code: 'inbound_semi:work_order_code',
|
||||||
|
raw_material_cost: 'inbound_semi:raw_material_cost',
|
||||||
|
unit_total_cost: 'inbound_semi:unit_total_cost',
|
||||||
|
total_price: 'inbound_semi:total_price',
|
||||||
|
production_manager: 'inbound_semi:production_manager',
|
||||||
|
production_start_time: 'inbound_semi:production_start_time',
|
||||||
|
production_end_time: 'inbound_semi:production_end_time',
|
||||||
|
arrival_photo: 'inbound_semi:arrival_photo',
|
||||||
|
quality_report_link: 'inbound_semi:quality_report_link',
|
||||||
|
detail_link: 'inbound_semi:detail_link',
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查列权限
|
||||||
const hasColumnPermission = (prop: string) => {
|
const hasColumnPermission = (prop: string) => {
|
||||||
return true
|
if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const code = permissionMap[prop]
|
||||||
|
return code ? userStore.hasPermission(code) : false
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultColumns = ['company_name', 'material_name', 'spec_model', 'unit', 'inbound_date', 'sn_bn', 'status', 'quality_status', 'bom_code', 'work_order_code', 'qty_stock', 'qty_available', 'unit_total_cost', 'arrival_photo', 'quality_report_link']
|
const defaultColumns = ['company_name', 'material_name', 'spec_model', 'unit', 'inbound_date', 'sn_bn', 'status', 'quality_status', 'bom_code', 'work_order_code', 'qty_stock', 'qty_available', 'unit_total_cost', 'arrival_photo', 'quality_report_link']
|
||||||
|
|||||||
@ -473,9 +473,6 @@ const inputQty = ref<number | undefined>(undefined)
|
|||||||
const inputRemark = ref('')
|
const inputRemark = ref('')
|
||||||
const qtyInputRef = ref()
|
const qtyInputRef = ref()
|
||||||
|
|
||||||
// ★ 新增: 多人协同心跳刷新定时器
|
|
||||||
let syncTimer: any = null
|
|
||||||
|
|
||||||
// ★ 新增: 静默刷新数据(不弹loading)
|
// ★ 新增: 静默刷新数据(不弹loading)
|
||||||
const syncData = async () => {
|
const syncData = async () => {
|
||||||
try {
|
try {
|
||||||
@ -592,19 +589,8 @@ async function fetchBorrowedQuantities(items: StockItem[]): Promise<void> {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await checkServerDraft()
|
await checkServerDraft()
|
||||||
// ★ 启动多人协同心跳轮询(每5秒静默刷新)
|
|
||||||
syncTimer = setInterval(() => {
|
|
||||||
syncData()
|
|
||||||
}, 5000)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// ★ 新增: 组件卸载时清除定时器
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (syncTimer) {
|
|
||||||
clearInterval(syncTimer)
|
|
||||||
syncTimer = null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const checkServerDraft = async () => {
|
const checkServerDraft = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user