feat: 升级预警批量设置交互,引入批量操作模式切换,提升界面整洁度与体验

This commit is contained in:
dxc
2026-03-11 13:28:11 +08:00
parent d2d9abe201
commit e224a07a47
3 changed files with 84 additions and 20 deletions

View File

@ -123,7 +123,8 @@ def get_list():
'orderByColumn': request.args.get('orderByColumn', ''), 'orderByColumn': request.args.get('orderByColumn', ''),
'isAsc': request.args.get('isAsc', None), 'isAsc': request.args.get('isAsc', None),
'advancedFilters': advanced_filters_list, '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() user_permissions = get_current_user_permissions()

View File

@ -198,6 +198,11 @@ class MaterialBaseService:
# 必须使用 filter() 而非 filter_by(),因为 query 是 join 后的复杂查询 # 必须使用 filter() 而非 filter_by(),因为 query 是 join 后的复杂查询
query = query.filter(MaterialBase.is_enabled == is_active) 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. 高级动态筛选 # 3. 高级动态筛选
advanced_filters = filters.get('advancedFilters', []) advanced_filters = filters.get('advancedFilters', [])
if advanced_filters: if advanced_filters:

View File

@ -62,6 +62,17 @@
<el-option label="禁用" :value="false" /> <el-option label="禁用" :value="false" />
</el-select> </el-select>
<el-select
v-model="queryParams.has_stock"
placeholder="库存状态"
clearable
style="width: 120px; margin-right: 10px;"
@change="handleQuery"
>
<el-option label="全部" value="" />
<el-option label="仅看有库存" value="true" />
</el-select>
<el-button type="primary" plain @click="handleQuery">搜索</el-button> <el-button type="primary" plain @click="handleQuery">搜索</el-button>
<el-button plain @click="resetQuery">重置</el-button> <el-button plain @click="resetQuery">重置</el-button>
<el-popover <el-popover
@ -99,15 +110,32 @@
</el-button> </el-button>
<!-- 批量设置预警按钮 (需要 edit_warning 权限) --> <!-- 批量设置预警按钮 (需要 edit_warning 权限) -->
<el-button <template v-if="userStore.hasPermission('material_list:edit_warning')">
v-if="userStore.hasPermission('material_list:edit_warning')" <!-- 常规状态 -->
type="warning" <el-button
plain v-if="!isBatchMode"
@click="handleBatchSetWarning" type="warning"
style="margin-right: 10px" plain
> @click="enterBatchMode"
<el-icon style="margin-right: 5px"><Bell /></el-icon>批量设置预警 style="margin-right: 10px"
</el-button> >
<el-icon style="margin-right: 5px"><Bell /></el-icon>批量设置预警
</el-button>
<!-- 批量模式 -->
<template v-if="isBatchMode">
<el-button
type="warning"
:disabled="selectedItems.length === 0"
@click="handleBatchSetWarning"
style="margin-right: 10px"
>
确认批量设置 (已选 {{ selectedItems.length }} )
</el-button>
<el-button plain @click="exitBatchMode" style="margin-right: 10px">
退出批量操作
</el-button>
</template>
</template>
<el-button v-if="userStore.hasPermission('material_list:operation')" type="primary" @click="handleAdd" style="margin-right: 10px"> <el-button v-if="userStore.hasPermission('material_list:operation')" type="primary" @click="handleAdd" style="margin-right: 10px">
<el-icon style="margin-right: 5px"><Plus /></el-icon>新增 <el-icon style="margin-right: 5px"><Plus /></el-icon>新增
@ -154,6 +182,7 @@
</div> </div>
<el-table <el-table
ref="tableRef"
v-loading="loading" v-loading="loading"
:data="tableData" :data="tableData"
border border
@ -161,8 +190,10 @@
:size="tableSize" :size="tableSize"
:row-class-name="tableRowClassName" :row-class-name="tableRowClassName"
@sort-change="handleSortChange" @sort-change="handleSortChange"
@selection-change="handleSelectionChange"
style="width: 100%; margin-top: 15px" style="width: 100%; margin-top: 15px"
> >
<el-table-column v-if="isBatchMode" type="selection" width="55" />
<el-table-column v-if="columns.id.visible" prop="id" label="ID" min-width="80" align="center" fixed="left" /> <el-table-column v-if="columns.id.visible" prop="id" label="ID" min-width="80" align="center" fixed="left" />
<el-table-column v-if="columns.companyName.visible" prop="companyName" label="所属公司" min-width="100" align="center" show-overflow-tooltip sortable="custom"> <el-table-column v-if="columns.companyName.visible" prop="companyName" label="所属公司" min-width="100" align="center" show-overflow-tooltip sortable="custom">
@ -534,10 +565,11 @@ interface QueryParams {
category: string; category: string;
type: string; type: string;
company: string; company: string;
isEnabled?: boolean; // 已修改为布尔值可选 isEnabled?: boolean;
orderByColumn: string; orderByColumn: string;
isAsc: string | undefined; isAsc: string | undefined;
advancedFilters?: any[]; advancedFilters?: any[];
has_stock?: string;
} }
interface CascaderOption { interface CascaderOption {
@ -551,6 +583,7 @@ const loading = ref(false);
const exportLoading = ref(false); // 导出加载状态 const exportLoading = ref(false); // 导出加载状态
const total = ref(0); const total = ref(0);
const tableData = ref<MaterialBaseVO[]>([]); const tableData = ref<MaterialBaseVO[]>([]);
const tableRef = ref<InstanceType<typeof ElTable>>();
const submitLoading = ref(false); const submitLoading = ref(false);
const tableSize = ref<'large' | 'default' | 'small'>('large'); const tableSize = ref<'large' | 'default' | 'small'>('large');
const advancedFilterVisible = ref(false); const advancedFilterVisible = ref(false);
@ -589,6 +622,24 @@ const cameraDialogVisible = ref(false);
const cameraRef = ref<InstanceType<typeof WebRtcCamera> | null>(null); const cameraRef = ref<InstanceType<typeof WebRtcCamera> | null>(null);
const currentCameraField = ref<'generalImage' | 'generalManual'>('generalImage'); const currentCameraField = ref<'generalImage' | 'generalManual'>('generalImage');
// 复选框选中数据
const selectedItems = ref<MaterialBaseVO[]>([]);
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({ const warningDialog = reactive({
visible: false, visible: false,
@ -701,7 +752,8 @@ const queryParams = reactive<QueryParams>({
isEnabled: undefined, isEnabled: undefined,
orderByColumn: '', orderByColumn: '',
isAsc: undefined, isAsc: undefined,
advancedFilters: [] advancedFilters: [],
has_stock: ''
}); });
// --- 弹窗与表单相关 --- // --- 弹窗与表单相关 ---
@ -920,6 +972,10 @@ const resetQuery = () => {
queryParams.isEnabled = undefined; queryParams.isEnabled = undefined;
queryParams.orderByColumn = ''; queryParams.orderByColumn = '';
queryParams.isAsc = undefined; queryParams.isAsc = undefined;
queryParams.has_stock = '';
selectedItems.value = [];
tableRef.value?.clearSelection();
isBatchMode.value = false;
handleQuery(); handleQuery();
}; };
@ -1098,16 +1154,15 @@ const handleDelete = (row: MaterialBaseVO) => {
// 批量设置预警 // 批量设置预警
const handleBatchSetWarning = () => { const handleBatchSetWarning = () => {
// 获取已选择的行(如果有选中的行则使用选中的行,否则使用当前页所有行) if (selectedItems.value.length === 0) {
const selectedRows = tableData.value.filter((row: MaterialBaseVO) => (row as any)._checked); ElMessage.warning('请先勾选需要设置预警的物料');
if (selectedRows.length > 0) { return;
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;
} }
// 使用已选中的行
warningDialog.selectedIds = selectedItems.value.map((row: MaterialBaseVO) => row.id);
warningDialog.selectedCount = selectedItems.value.length;
// 重置表单 // 重置表单
warningForm.isEnabled = false; warningForm.isEnabled = false;
warningForm.redThreshold = undefined; warningForm.redThreshold = undefined;
@ -1149,6 +1204,9 @@ const submitWarning = async () => {
await batchSetWarning(data); await batchSetWarning(data);
ElMessage.success('预警设置成功'); ElMessage.success('预警设置成功');
warningDialog.visible = false; warningDialog.visible = false;
selectedItems.value = []; // 清除选中状态
tableRef.value?.clearSelection(); // 清除表格勾选状态
isBatchMode.value = false; // 退出批量模式
getList(); getList();
} catch (error: any) { } catch (error: any) {
ElMessage.error(error?.msg || '设置失败'); ElMessage.error(error?.msg || '设置失败');