diff --git a/inventory-backend/app/api/v1/inbound/base.py b/inventory-backend/app/api/v1/inbound/base.py
index 3457771..50b0bae 100644
--- a/inventory-backend/app/api/v1/inbound/base.py
+++ b/inventory-backend/app/api/v1/inbound/base.py
@@ -123,7 +123,8 @@ def get_list():
'orderByColumn': request.args.get('orderByColumn', ''),
'isAsc': request.args.get('isAsc', None),
'advancedFilters': advanced_filters_list,
- 'enableWarningSort': request.args.get('enableWarningSort', 'false').lower() == 'true'
+ 'enableWarningSort': request.args.get('enableWarningSort', 'false').lower() == 'true',
+ 'has_stock': request.args.get('has_stock', '')
}
user_permissions = get_current_user_permissions()
diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py
index ae880b5..0c85933 100644
--- a/inventory-backend/app/services/inbound/base_service.py
+++ b/inventory-backend/app/services/inbound/base_service.py
@@ -198,6 +198,11 @@ class MaterialBaseService:
# 必须使用 filter() 而非 filter_by(),因为 query 是 join 后的复杂查询
query = query.filter(MaterialBase.is_enabled == is_active)
+ # 【新增】:库存状态筛选 (has_stock)
+ has_stock = filters.get('has_stock')
+ if has_stock and str(has_stock).lower() in ['true', '1', 'yes']:
+ query = query.filter(total_inv > 0)
+
# 3. 高级动态筛选
advanced_filters = filters.get('advancedFilters', [])
if advanced_filters:
diff --git a/inventory-web/src/views/material/list.vue b/inventory-web/src/views/material/list.vue
index e11de5e..ab654c6 100644
--- a/inventory-web/src/views/material/list.vue
+++ b/inventory-web/src/views/material/list.vue
@@ -62,6 +62,17 @@
+
+
+
+
+
搜索
重置
-
- 批量设置预警
-
+
+
+
+ 批量设置预警
+
+
+
+
+ 确认批量设置 (已选 {{ selectedItems.length }} 项)
+
+
+ 退出批量操作
+
+
+
新增
@@ -154,6 +182,7 @@
+
@@ -534,10 +565,11 @@ interface QueryParams {
category: string;
type: string;
company: string;
- isEnabled?: boolean; // 已修改为布尔值可选
+ isEnabled?: boolean;
orderByColumn: string;
isAsc: string | undefined;
advancedFilters?: any[];
+ has_stock?: string;
}
interface CascaderOption {
@@ -551,6 +583,7 @@ const loading = ref(false);
const exportLoading = ref(false); // 导出加载状态
const total = ref(0);
const tableData = ref([]);
+const tableRef = ref>();
const submitLoading = ref(false);
const tableSize = ref<'large' | 'default' | 'small'>('large');
const advancedFilterVisible = ref(false);
@@ -589,6 +622,24 @@ const cameraDialogVisible = ref(false);
const cameraRef = ref | null>(null);
const currentCameraField = ref<'generalImage' | 'generalManual'>('generalImage');
+// 复选框选中数据
+const selectedItems = ref([]);
+const handleSelectionChange = (selection: MaterialBaseVO[]) => {
+ selectedItems.value = selection;
+};
+
+// 批量操作模式
+const isBatchMode = ref(false);
+const enterBatchMode = () => {
+ selectedItems.value = [];
+ isBatchMode.value = true;
+};
+const exitBatchMode = () => {
+ selectedItems.value = [];
+ tableRef.value?.clearSelection(); // 清除表格勾选状态
+ isBatchMode.value = false;
+};
+
// 预警设置相关
const warningDialog = reactive({
visible: false,
@@ -701,7 +752,8 @@ const queryParams = reactive({
isEnabled: undefined,
orderByColumn: '',
isAsc: undefined,
- advancedFilters: []
+ advancedFilters: [],
+ has_stock: ''
});
// --- 弹窗与表单相关 ---
@@ -920,6 +972,10 @@ const resetQuery = () => {
queryParams.isEnabled = undefined;
queryParams.orderByColumn = '';
queryParams.isAsc = undefined;
+ queryParams.has_stock = '';
+ selectedItems.value = [];
+ tableRef.value?.clearSelection();
+ isBatchMode.value = false;
handleQuery();
};
@@ -1098,16 +1154,15 @@ const handleDelete = (row: MaterialBaseVO) => {
// 批量设置预警
const handleBatchSetWarning = () => {
- // 获取已选择的行(如果有选中的行则使用选中的行,否则使用当前页所有行)
- const selectedRows = tableData.value.filter((row: MaterialBaseVO) => (row as any)._checked);
- if (selectedRows.length > 0) {
- warningDialog.selectedIds = selectedRows.map((row: MaterialBaseVO) => row.id);
- warningDialog.selectedCount = selectedRows.length;
- } else {
- warningDialog.selectedIds = tableData.value.map((row: MaterialBaseVO) => row.id);
- warningDialog.selectedCount = tableData.value.length;
+ if (selectedItems.value.length === 0) {
+ ElMessage.warning('请先勾选需要设置预警的物料');
+ return;
}
+ // 使用已选中的行
+ warningDialog.selectedIds = selectedItems.value.map((row: MaterialBaseVO) => row.id);
+ warningDialog.selectedCount = selectedItems.value.length;
+
// 重置表单
warningForm.isEnabled = false;
warningForm.redThreshold = undefined;
@@ -1149,6 +1204,9 @@ const submitWarning = async () => {
await batchSetWarning(data);
ElMessage.success('预警设置成功');
warningDialog.visible = false;
+ selectedItems.value = []; // 清除选中状态
+ tableRef.value?.clearSelection(); // 清除表格勾选状态
+ isBatchMode.value = false; // 退出批量模式
getList();
} catch (error: any) {
ElMessage.error(error?.msg || '设置失败');