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 }}
+
+
库存与商务
-
- {{ 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 }}
+
+
+ {{ 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 }}
+
+
生产与库存
-
- {{ 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,