From 034418df8a2de80b338f7d845409cf090fcb0328 Mon Sep 17 00:00:00 2001 From: dxc Date: Fri, 29 May 2026 14:26:52 +0800 Subject: [PATCH] =?UTF-8?q?V3.38=E7=89=88=E6=9C=AC=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=8C=E4=B8=89=E7=A7=8D=E5=85=A5=E5=BA=93=E6=8C=89=E7=85=A7?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E4=BF=A1=E6=81=AF=E5=86=85=E5=AE=B9=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory-web/src/App.vue | 2 +- inventory-web/src/views/stock/inbound/buy.vue | 90 +++++++++++++++--- .../src/views/stock/inbound/product.vue | 80 ++++++++++++++-- .../src/views/stock/inbound/semi.vue | 92 ++++++++++++++++--- 4 files changed, 223 insertions(+), 41 deletions(-) diff --git a/inventory-web/src/App.vue b/inventory-web/src/App.vue index 22e3ba8..4d81969 100644 --- a/inventory-web/src/App.vue +++ b/inventory-web/src/App.vue @@ -239,7 +239,7 @@ const handleLogout = () => { diff --git a/inventory-web/src/views/stock/inbound/buy.vue b/inventory-web/src/views/stock/inbound/buy.vue index 36cc209..b260efd 100644 --- a/inventory-web/src/views/stock/inbound/buy.vue +++ b/inventory-web/src/views/stock/inbound/buy.vue @@ -111,18 +111,32 @@ +
+ 列展示设置 + + 全选 + +
基础信息
- - {{ c.label }} - +
库存与商务
- - {{ c.label }} - +
@@ -193,6 +207,7 @@ :src="getImageUrl(getImagesOnly(scope.row[col.prop])[0])" :preview-src-list="getImagesOnly(scope.row[col.prop]).map(u => getImageUrl(u))" preview-teleported + hide-on-click-modal fit="cover" lazy > @@ -897,6 +912,8 @@ const operatorOptions = ref([ { value: 'le', label: '小于等于' } ]) +// ================= 第一步:声明基础数据 ================= + // 基础列 const baseColumns = [ {prop: 'company_name', label: '所属公司'}, @@ -937,6 +954,8 @@ const stockColumns = [ {prop: 'inspection_report', label: '检测报告', minWidth: '100'} ] +const allColumns = [...baseColumns, ...stockColumns] + // 列与权限Code的映射关系(数据库中的code) const permissionMap: Record = { id: 'inbound_buy:id', @@ -971,14 +990,15 @@ const permissionMap: Record = { inspection_report: 'inbound_buy:inspection_report' } -// 初始化列显示状态(纯权限驱动,废除本地缓存) -const initColumnPermissions = () => { - visibleColumnProps.value = allColumns - .filter(col => hasColumnPermission(col.prop)) - .map(col => col.prop) -} +// ================= 第二步:声明响应式变量 ================= +const visibleColumnProps = ref([]) -// 检查列权限 +// ================= 第三步:按依赖顺序放置方法和监听 ================= + +// 1. 获取唯一缓存 Key +const getStorageKey = () => `MOM_INBOUND_BUY_COLS_${userStore.username || 'DEFAULT'}`; + +// 2. 检查列权限(依赖 permissionMap) const hasColumnPermission = (prop: string) => { if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') { return true @@ -987,9 +1007,49 @@ const hasColumnPermission = (prop: string) => { return code ? userStore.hasPermission(code) : false } -const allColumns = [...baseColumns, ...stockColumns] +// 3. 初始化列权限(依赖 allColumns / hasColumnPermission / getStorageKey) +const initColumnPermissions = () => { + const allowedProps = allColumns + .filter(col => hasColumnPermission(col.prop)) + .map(col => col.prop); -const visibleColumnProps = ref([]) + const cachedData = localStorage.getItem(getStorageKey()); + if (cachedData) { + try { + const parsedCache = JSON.parse(cachedData); + visibleColumnProps.value = parsedCache.filter((prop: string) => allowedProps.includes(prop)); + return; + } catch (e) { + console.error('解析列缓存失败', e); + } + } + + visibleColumnProps.value = allowedProps; +}; + +// 4. 监听:只要用户勾选了列,就存入本地缓存 +watch(visibleColumnProps, (newVal) => { + localStorage.setItem(getStorageKey(), JSON.stringify(newVal)); +}, { deep: true }); + +// 5. 全选功能的计算属性和事件 +const isAllSelected = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length === allowedLength; +}); + +const isIndeterminate = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length < allowedLength; +}); + +const handleCheckAllChange = (val: boolean) => { + if (val) { + visibleColumnProps.value = allColumns.filter(c => hasColumnPermission(c.prop)).map(c => c.prop); + } else { + visibleColumnProps.value = []; + } +}; const form = reactive({ id: undefined, base_id: undefined as number | undefined, diff --git a/inventory-web/src/views/stock/inbound/product.vue b/inventory-web/src/views/stock/inbound/product.vue index 5fc7cb7..48b2d9d 100644 --- a/inventory-web/src/views/stock/inbound/product.vue +++ b/inventory-web/src/views/stock/inbound/product.vue @@ -123,9 +123,23 @@ 刷新 +
+ 列展示设置 + + 全选 + +
- {{ c.label }} +
@@ -193,6 +207,7 @@ :src="getImageUrl(getImagesOnly(scope.row[col.prop])[0])" :preview-src-list="getImagesOnly(scope.row[col.prop]).map(u => getImageUrl(u))" preview-teleported + hide-on-click-modal fit="cover" lazy > @@ -745,6 +760,8 @@ const scannerDialogVisible = ref(false) // 库位级联选择器数据 const warehouseOptions = ref([]) +// ================= 第一步:声明基础数据 ================= + // [核心优化] 所有列定义 const allColumns = [ { prop: 'company_name', label: '所属公司', minWidth: '100', sortable: true }, // [新增] @@ -810,15 +827,15 @@ const permissionMap: Record = { detail_link: 'inbound_product:detail_link', } -// 根据用户权限初始化列显示状态 -// 初始化列显示状态(纯权限驱动,废除本地缓存) -const initColumnPermissions = () => { - visibleColumnProps.value = allColumns - .filter(col => hasColumnPermission(col.prop)) - .map(col => col.prop) -} +// ================= 第二步:声明响应式变量 ================= +const visibleColumnProps = ref([]) -// 检查列权限 +// ================= 第三步:按依赖顺序放置方法和监听 ================= + +// 1. 获取唯一缓存 Key +const getStorageKey = () => `MOM_INBOUND_PROD_COLS_${userStore.username || 'DEFAULT'}`; + +// 2. 检查列权限(依赖 permissionMap) const hasColumnPermission = (prop: string) => { if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') { return true @@ -827,6 +844,50 @@ const hasColumnPermission = (prop: string) => { return code ? userStore.hasPermission(code) : false } +// 3. 初始化列权限(依赖 allColumns / hasColumnPermission / getStorageKey) +const initColumnPermissions = () => { + const allowedProps = allColumns + .filter(col => hasColumnPermission(col.prop)) + .map(col => col.prop); + + const cachedData = localStorage.getItem(getStorageKey()); + if (cachedData) { + try { + const parsedCache = JSON.parse(cachedData); + visibleColumnProps.value = parsedCache.filter((prop: string) => allowedProps.includes(prop)); + return; + } catch (e) { + console.error('解析列缓存失败', e); + } + } + + visibleColumnProps.value = allowedProps; +}; + +// 4. 监听:只要用户勾选了列,就存入本地缓存 +watch(visibleColumnProps, (newVal) => { + localStorage.setItem(getStorageKey(), JSON.stringify(newVal)); +}, { deep: true }); + +// 5. 全选功能的计算属性和事件 +const isAllSelected = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length === allowedLength; +}); + +const isIndeterminate = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length < allowedLength; +}); + +const handleCheckAllChange = (val: boolean) => { + if (val) { + visibleColumnProps.value = allColumns.filter(c => hasColumnPermission(c.prop)).map(c => c.prop); + } else { + visibleColumnProps.value = []; + } +}; + // ★ 智能聚合:当无序列号权限时,按 SKU 聚合库存 const displayData = computed(() => { // 检查是否有序列号权限 @@ -861,7 +922,6 @@ const displayData = computed(() => { }) const defaultVisibleCols = ['company_name', 'material_name', 'sku', 'serial_number', 'qty_stock', 'status', 'quality_status', 'product_photo', 'sale_price', 'order_id'] -const visibleColumnProps = ref([]) const form = reactive({ id: undefined, base_id: undefined as number | undefined, diff --git a/inventory-web/src/views/stock/inbound/semi.vue b/inventory-web/src/views/stock/inbound/semi.vue index 8da5441..459bb21 100644 --- a/inventory-web/src/views/stock/inbound/semi.vue +++ b/inventory-web/src/views/stock/inbound/semi.vue @@ -127,18 +127,32 @@ +
+ 列展示设置 + + 全选 + +
基础信息
- - {{ c.label }} - +
生产与库存
- - {{ c.label }} - +
@@ -216,6 +230,7 @@ :src="getImageUrl(getImagesOnly(scope.row[col.prop])[0])" :preview-src-list="getImagesOnly(scope.row[col.prop]).map(u => getImageUrl(u))" preview-teleported + hide-on-click-modal fit="cover" lazy > @@ -798,6 +813,8 @@ const warehouseOptions = ref([]) const entryMode = ref('batch') const modeLocked = ref(false) +// ================= 第一步:声明基础数据 ================= + // 列定义 const baseColumns = [ {prop: 'company_name', label: '所属公司', sortable: true}, // [新增] @@ -834,14 +851,8 @@ const stockColumns = [ {prop: 'quality_report_link', label: '质量报告', minWidth: '100', sortable: false}, {prop: 'detail_link', label: '详情链接', minWidth: '100', sortable: false}, ] -const allColumns = [...baseColumns, ...stockColumns] -// 初始化列显示状态(纯权限驱动,废除本地缓存) -const initColumnPermissions = () => { - visibleColumnProps.value = allColumns - .filter(col => hasColumnPermission(col.prop)) - .map(col => col.prop) -} +const allColumns = [...baseColumns, ...stockColumns] // 列与权限Code的映射关系(数据库中的code) const permissionMap: Record = { @@ -882,7 +893,15 @@ const permissionMap: Record = { detail_link: 'inbound_semi:detail_link', } -// 检查列权限 +// ================= 第二步:声明响应式变量 ================= +const visibleColumnProps = ref([]) + +// ================= 第三步:按依赖顺序放置方法和监听 ================= + +// 1. 获取唯一缓存 Key +const getStorageKey = () => `MOM_INBOUND_SEMI_COLS_${userStore.username || 'DEFAULT'}`; + +// 2. 检查列权限(依赖 permissionMap) const hasColumnPermission = (prop: string) => { if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') { return true @@ -891,8 +910,51 @@ const hasColumnPermission = (prop: string) => { return code ? userStore.hasPermission(code) : false } +// 3. 初始化列权限(依赖 allColumns / hasColumnPermission / getStorageKey) +const initColumnPermissions = () => { + const allowedProps = allColumns + .filter(col => hasColumnPermission(col.prop)) + .map(col => col.prop); + + const cachedData = localStorage.getItem(getStorageKey()); + if (cachedData) { + try { + const parsedCache = JSON.parse(cachedData); + visibleColumnProps.value = parsedCache.filter((prop: string) => allowedProps.includes(prop)); + return; + } catch (e) { + console.error('解析列缓存失败', e); + } + } + + visibleColumnProps.value = allowedProps; +}; + +// 4. 监听:只要用户勾选了列,就存入本地缓存 +watch(visibleColumnProps, (newVal) => { + localStorage.setItem(getStorageKey(), JSON.stringify(newVal)); +}, { deep: true }); + +// 5. 全选功能的计算属性和事件 +const isAllSelected = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length === allowedLength; +}); + +const isIndeterminate = computed(() => { + const allowedLength = allColumns.filter(c => hasColumnPermission(c.prop)).length; + return visibleColumnProps.value.length > 0 && visibleColumnProps.value.length < allowedLength; +}); + +const handleCheckAllChange = (val: boolean) => { + if (val) { + visibleColumnProps.value = allColumns.filter(c => hasColumnPermission(c.prop)).map(c => c.prop); + } else { + visibleColumnProps.value = []; + } +}; + 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 visibleColumnProps = ref([]) const form = reactive({ id: undefined, base_id: undefined as number | undefined,