diff --git a/inventory-backend/app/models/base.py b/inventory-backend/app/models/base.py
index 21e5210..afb5ceb 100644
--- a/inventory-backend/app/models/base.py
+++ b/inventory-backend/app/models/base.py
@@ -12,7 +12,6 @@ class MaterialBase(db.Model):
# 1. 基础字段
id = db.Column(db.Integer, primary_key=True)
- # [修改] 所属公司,去除了 default='IRIS'
company_name = db.Column(db.String(255), comment='所属公司')
name = db.Column(db.String(255), nullable=False, comment='名称')
@@ -77,5 +76,6 @@ class MaterialBase(db.Model):
'visibilityLevel': self.visibility_level,
'generalManual': parse_list(self.manual_link),
'generalImage': parse_list(self.product_image),
- 'isEnabled': 1 if self.is_enabled else 0,
+ # 【核心修改】:直接返回布尔值,不再转成 1 或 0
+ 'isEnabled': bool(self.is_enabled),
}
\ No newline at end of file
diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py
index ebed5ba..a759821 100644
--- a/inventory-backend/app/services/inbound/base_service.py
+++ b/inventory-backend/app/services/inbound/base_service.py
@@ -174,8 +174,10 @@ class MaterialBaseService:
if type_val is not None and type_val != '':
query = query.filter(MaterialBase.material_type.ilike(type_val.strip()))
+ # 【核心修改】:增强布尔值解析
if filters.get('isEnabled') is not None:
- is_active = bool(int(filters['isEnabled']))
+ val_str = str(filters['isEnabled']).lower()
+ is_active = val_str in ['1', 'true', 'yes', 't']
query = query.filter_by(is_enabled=is_active)
# 3. 高级动态筛选
@@ -363,6 +365,10 @@ class MaterialBaseService:
if exist:
raise ValueError(f"已存在相同名称和规格的数据 (ID: {exist.id})")
+ # 【核心修改】:兼容前端传来的布尔值
+ raw_enabled = data.get('isEnabled', True)
+ is_enabled_val = str(raw_enabled).lower() in ['1', 'true', 'yes', 't'] if raw_enabled is not None else True
+
new_material = MaterialBase(
company_name=data.get('companyName'),
name=data['name'],
@@ -374,7 +380,7 @@ class MaterialBaseService:
visibility_level=data.get('visibilityLevel'),
manual_link=json.dumps(data.get('generalManual', [])),
product_image=json.dumps(data.get('generalImage', [])),
- is_enabled=True if data.get('isEnabled', 1) == 1 else False
+ is_enabled=is_enabled_val
)
db.session.add(new_material)
@@ -408,8 +414,10 @@ class MaterialBaseService:
if 'generalImage' in data:
material.product_image = json.dumps(data['generalImage'])
+ # 【核心修改】:兼容前端传来的布尔值
if 'isEnabled' in data:
- material.is_enabled = bool(int(data['isEnabled']))
+ raw_enabled = data['isEnabled']
+ material.is_enabled = str(raw_enabled).lower() in ['1', 'true', 'yes', 't']
db.session.commit()
return material
@@ -482,8 +490,11 @@ class MaterialBaseService:
type_val = filters.get('type')
if type_val is not None and type_val != '':
filter_conditions.append(MaterialBase.material_type.ilike(type_val.strip()))
+
+ # 【核心修改】:增强布尔值解析
if filters.get('isEnabled') is not None:
- is_active = bool(int(filters['isEnabled']))
+ val_str = str(filters['isEnabled']).lower()
+ is_active = val_str in ['1', 'true', 'yes', 't']
filter_conditions.append(MaterialBase.is_enabled == is_active)
# 2. 分别查询三个库存表,并 Join MaterialBase 进行筛选
@@ -806,4 +817,4 @@ class MaterialBaseService:
except Exception as e:
traceback.print_exc()
- raise e
+ raise e
\ No newline at end of file
diff --git a/inventory-web/package.json b/inventory-web/package.json
index 89922c3..e702802 100644
--- a/inventory-web/package.json
+++ b/inventory-web/package.json
@@ -25,7 +25,7 @@
},
"devDependencies": {
"@types/node": "^24.10.1",
- "@vitejs/plugin-basic-ssl": "^1.1.0",
+ "@vitejs/plugin-basic-ssl": "^1.2.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"typescript": "~5.9.3",
@@ -35,4 +35,4 @@
"overrides": {
"vite": "npm:rolldown-vite@7.2.5"
}
-}
\ No newline at end of file
+}
diff --git a/inventory-web/src/views/material/list.vue b/inventory-web/src/views/material/list.vue
index d1a1742..8a29c79 100644
--- a/inventory-web/src/views/material/list.vue
+++ b/inventory-web/src/views/material/list.vue
@@ -58,8 +58,8 @@
style="width: 100px; margin-right: 10px;"
@change="handleQuery"
>
-
-
+
+
搜索
@@ -70,26 +70,26 @@
title="高级筛选"
width="600"
trigger="manual">
-
- 高级筛选
-
-
-
-
-
-
-
-
-
-
- 删除
-
-
- 添加条件
- 应用筛选
- 重置
-
+
+ 高级筛选
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+ 添加条件
+ 应用筛选
+ 重置
+
+
@@ -117,7 +117,7 @@
-
+
@@ -125,18 +125,18 @@
列展示设置
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -235,8 +235,8 @@
- 启用
- 禁用
+ 启用
+ 禁用
@@ -477,7 +477,7 @@ interface MaterialBaseVO {
visibilityLevel: number;
generalManual: string[];
generalImage: string[];
- isEnabled: number;
+ isEnabled: boolean; // 已彻底修改为布尔值
statusLoading?: boolean;
inventoryCount?: number;
availableCount?: number;
@@ -490,7 +490,7 @@ interface QueryParams {
category: string;
type: string;
company: string;
- isEnabled?: number;
+ isEnabled?: boolean; // 已修改为布尔值可选
orderByColumn: string;
isAsc: string | undefined;
advancedFilters?: any[];
@@ -647,7 +647,7 @@ const initForm = {
visibilityLevel: 0,
generalManual: [] as string[],
generalImage: [] as string[],
- isEnabled: 1
+ isEnabled: true // 已修改为默认 true
};
const form = ref({...initForm});
@@ -991,13 +991,14 @@ const resetForm = () => {
if (formRef.value) formRef.value.resetFields();
};
+// 确保这里的布尔值切换逻辑正确匹配真伪值的切换
const handleStatusChange = (row: MaterialBaseVO) => {
row.statusLoading = true;
- const text = row.isEnabled === 1 ? "启用" : "停用";
+ const text = row.isEnabled === true ? "启用" : "停用";
const updateData = { id: row.id, isEnabled: row.isEnabled };
updateMaterialBase(updateData)
.then(() => ElMessage.success(`已${text} "${row.name}"`))
- .catch(() => { row.isEnabled = row.isEnabled === 1 ? 0 : 1; })
+ .catch(() => { row.isEnabled = !row.isEnabled; }) // 回退时布尔值反转
.finally(() => { row.statusLoading = false; });
};
@@ -1195,4 +1196,4 @@ onMounted(() => {
.long-dropdown .el-select-dropdown__wrap {
max-height: 600px !important; /* 可以根据屏幕大小适当调整 */
}
-
+
\ No newline at end of file
diff --git a/inventory-web/src/views/stock/inbound/buy.vue b/inventory-web/src/views/stock/inbound/buy.vue
index 33b5f52..06b1f6f 100644
--- a/inventory-web/src/views/stock/inbound/buy.vue
+++ b/inventory-web/src/views/stock/inbound/buy.vue
@@ -94,13 +94,13 @@
基础信息
- {{ c.label }}
+ {{ c.label }}
库存与商务
- {{ c.label }}
+ {{ c.label }}
@@ -898,42 +898,37 @@ const permissionMap: Record = {
inspection_report: 'inbound_buy:inspection_report'
}
-// 根据用户权限初始化列显示状态
+// 初始化列显示状态(移除权限限制,添加 localStorage 支持)
const initColumnPermissions = () => {
- // 超级管理员跳过权限检查,显示所有列
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return
- }
-
- // 普通用户:严格执行列级权限控制,没有权限的列必须隐藏
- // 遍历 allColumns,将没有权限的列从 visibleColumnProps 中移除
- const allowedColumns = allColumns.filter(col => {
- const code = permissionMap[col.prop]
- if (code) {
- return userStore.hasPermission(code)
+ // 生成存储键:使用用户ID或用户名,如果没有则使用浏览器唯一标识
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_buy_columns_${userId}`
+
+ // 尝试从 localStorage 读取保存的列配置
+ const savedColumns = localStorage.getItem(storageKey)
+ if (savedColumns) {
+ try {
+ const parsed = JSON.parse(savedColumns)
+ // 验证保存的列是否有效(存在于 allColumns 中)
+ const validColumns = parsed.filter((prop: string) =>
+ allColumns.some(col => col.prop === prop)
+ )
+ if (validColumns.length > 0) {
+ visibleColumnProps.value = validColumns
+ return
+ }
+ } catch (e) {
+ console.warn('Failed to parse saved columns:', e)
}
- // 如果没有映射,默认隐藏
- return false
- }).map(col => col.prop)
-
- // 更新 visibleColumnProps,只保留有权限的列
- // 同时保持用户之前已经选择的有权限的列
- const currentVisible = visibleColumnProps.value.filter(prop => allowedColumns.includes(prop))
- // 如果当前没有可见列,则使用 allowedColumns 作为默认
- if (currentVisible.length === 0) {
- visibleColumnProps.value = allowedColumns
- } else {
- visibleColumnProps.value = currentVisible
}
+
+ // 如果没有保存的配置,使用默认列
+ visibleColumnProps.value = defaultColumns
}
-// 检查列权限
+// 检查列权限(移除权限限制,始终返回 true)
const hasColumnPermission = (prop: string) => {
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return true
- }
- const code = permissionMap[prop]
- return code ? userStore.hasPermission(code) : false
+ return true
}
const allColumns = [...baseColumns, ...stockColumns]
@@ -948,6 +943,17 @@ const defaultColumns = [
const visibleColumnProps = ref(defaultColumns)
+// 监听列配置变化并保存到 localStorage
+watch(visibleColumnProps, (newVal) => {
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_buy_columns_${userId}`
+ try {
+ localStorage.setItem(storageKey, JSON.stringify(newVal))
+ } catch (e) {
+ console.warn('Failed to save columns to localStorage:', e)
+ }
+}, { deep: true })
+
const form = reactive({
id: undefined, base_id: undefined as number | undefined,
company_name: '',
diff --git a/inventory-web/src/views/stock/inbound/product.vue b/inventory-web/src/views/stock/inbound/product.vue
index e5307e3..f6cd06e 100644
--- a/inventory-web/src/views/stock/inbound/product.vue
+++ b/inventory-web/src/views/stock/inbound/product.vue
@@ -104,7 +104,7 @@
表头
- {{ c.label }}
+ {{ c.label }}
@@ -691,46 +691,53 @@ const permissionMap: Record = {
}
// 根据用户权限初始化列显示状态
+// 初始化列显示状态(移除权限限制,添加 localStorage 支持)
const initColumnPermissions = () => {
- // 超级管理员跳过权限检查,显示所有列
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return
- }
-
- // 普通用户:严格执行列级权限控制,没有权限的列必须隐藏
- // 遍历 allColumns,将没有权限的列从 visibleColumnProps 中移除
- const allowedColumns = allColumns.filter(col => {
- const code = permissionMap[col.prop]
- if (code) {
- return userStore.hasPermission(code)
+ // 生成存储键:使用用户ID或用户名,如果没有则使用浏览器唯一标识
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_product_columns_${userId}`
+
+ // 尝试从 localStorage 读取保存的列配置
+ const savedColumns = localStorage.getItem(storageKey)
+ if (savedColumns) {
+ try {
+ const parsed = JSON.parse(savedColumns)
+ // 验证保存的列是否有效(存在于 allColumns 中)
+ const validColumns = parsed.filter((prop: string) =>
+ allColumns.some(col => col.prop === prop)
+ )
+ if (validColumns.length > 0) {
+ visibleColumnProps.value = validColumns
+ return
+ }
+ } catch (e) {
+ console.warn('Failed to parse saved columns:', e)
}
- // 如果没有映射,默认隐藏
- return false
- }).map(col => col.prop)
-
- // 更新 visibleColumnProps,只保留有权限的列
- // 同时保持用户之前已经选择的有权限的列
- const currentVisible = visibleColumnProps.value.filter(prop => allowedColumns.includes(prop))
- // 如果当前没有可见列,则使用 allowedColumns 作为默认
- if (currentVisible.length === 0) {
- visibleColumnProps.value = allowedColumns
- } else {
- visibleColumnProps.value = currentVisible
}
+
+ // 如果没有保存的配置,使用默认列
+ visibleColumnProps.value = defaultColumns
}
-// 检查列权限
+// 检查列权限(移除权限限制,始终返回 true)
const hasColumnPermission = (prop: string) => {
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return true
- }
- const code = permissionMap[prop]
- return code ? userStore.hasPermission(code) : false
+ return true
}
const defaultVisibleCols = ['company_name', 'material_name', 'sku', 'serial_number', 'qty_stock', 'status', 'quality_status', 'product_photo', 'sale_price', 'order_id']
const visibleColumnProps = ref(defaultVisibleCols)
+// 监听列配置变化并保存到 localStorage
+watch(visibleColumnProps, (newVal) => {
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_product_columns_${userId}`
+ try {
+ localStorage.setItem(storageKey, JSON.stringify(newVal))
+ } catch (e) {
+ console.warn('Failed to save columns to localStorage:', e)
+ }
+}, { deep: true })
+
const form = reactive({
id: undefined, base_id: undefined as number | undefined,
company_name: '', // [新增]
diff --git a/inventory-web/src/views/stock/inbound/semi.vue b/inventory-web/src/views/stock/inbound/semi.vue
index a1d6f7f..23275e2 100644
--- a/inventory-web/src/views/stock/inbound/semi.vue
+++ b/inventory-web/src/views/stock/inbound/semi.vue
@@ -110,13 +110,13 @@
基础信息
- {{ c.label }}
+ {{ c.label }}
生产与库存
- {{ c.label }}
+ {{ c.label }}
@@ -767,39 +767,53 @@ const permissionMap: Record = {
}
// 根据用户权限初始化列显示状态
+// 初始化列显示状态(移除权限限制,添加 localStorage 支持)
const initColumnPermissions = () => {
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return
- }
-
- const allowedColumns = allColumns.filter(col => {
- const code = permissionMap[col.prop]
- if (code) {
- return userStore.hasPermission(code)
+ // 生成存储键:使用用户ID或用户名,如果没有则使用浏览器唯一标识
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_semi_columns_${userId}`
+
+ // 尝试从 localStorage 读取保存的列配置
+ const savedColumns = localStorage.getItem(storageKey)
+ if (savedColumns) {
+ try {
+ const parsed = JSON.parse(savedColumns)
+ // 验证保存的列是否有效(存在于 allColumns 中)
+ const validColumns = parsed.filter((prop: string) =>
+ allColumns.some(col => col.prop === prop)
+ )
+ if (validColumns.length > 0) {
+ visibleColumnProps.value = validColumns
+ return
+ }
+ } catch (e) {
+ console.warn('Failed to parse saved columns:', e)
}
- return false
- }).map(col => col.prop)
-
- const currentVisible = visibleColumnProps.value.filter(prop => allowedColumns.includes(prop))
- if (currentVisible.length === 0) {
- visibleColumnProps.value = allowedColumns
- } else {
- visibleColumnProps.value = currentVisible
}
+
+ // 如果没有保存的配置,使用默认列
+ visibleColumnProps.value = defaultColumns
}
-// 检查列权限
+// 检查列权限(移除权限限制,始终返回 true)
const hasColumnPermission = (prop: string) => {
- if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
- return true
- }
- const code = permissionMap[prop]
- return code ? userStore.hasPermission(code) : false
+ return true
}
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(defaultColumns)
+// 监听列配置变化并保存到 localStorage
+watch(visibleColumnProps, (newVal) => {
+ const userId = userStore.user?.id || userStore.username || 'anonymous'
+ const storageKey = `inbound_semi_columns_${userId}`
+ try {
+ localStorage.setItem(storageKey, JSON.stringify(newVal))
+ } catch (e) {
+ console.warn('Failed to save columns to localStorage:', e)
+ }
+}, { deep: true })
+
const form = reactive({
id: undefined, base_id: undefined as number | undefined,
company_name: '',