新增盘点管理路由配置注释说明
This commit is contained in:
115
src/api/assets/operation/count/index.ts
Normal file
115
src/api/assets/operation/count/index.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { newService } from '/@/utils/request';
|
||||
|
||||
// 盘点任务查询参数
|
||||
export interface InventoryCountQueryParams {
|
||||
title?: string;
|
||||
status?: number;
|
||||
countType?: number;
|
||||
warehouseId?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 盘点任务创建/更新参数
|
||||
export interface InventoryCountParams {
|
||||
id?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
warehouseId?: string;
|
||||
zoneId?: string;
|
||||
locationId?: string;
|
||||
assetSkuId?: string;
|
||||
countType?: number;
|
||||
scope?: number;
|
||||
plannedStartTime?: string;
|
||||
plannedEndTime?: string;
|
||||
assigneeId?: string;
|
||||
participants?: string[];
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
// 获取盘点任务列表
|
||||
export function listInventoryCounts(params?: InventoryCountQueryParams) {
|
||||
return newService({
|
||||
url: '/inventory/count/listInventoryCounts',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取盘点任务详情
|
||||
export function getInventoryCount(id: string) {
|
||||
return newService({
|
||||
url: '/inventory/count/getInventoryCount',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 创建盘点任务
|
||||
export function createInventoryCount(data: InventoryCountParams) {
|
||||
return newService({
|
||||
url: '/inventory/count/createInventoryCount',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新盘点任务
|
||||
export function updateInventoryCount(data: InventoryCountParams) {
|
||||
return newService({
|
||||
url: '/inventory/count/updateInventoryCount',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除盘点任务
|
||||
export function deleteInventoryCount(id: string) {
|
||||
return newService({
|
||||
url: '/inventory/count/deleteInventoryCount',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 完成盘点
|
||||
export function completeInventoryCount(id: string) {
|
||||
return newService({
|
||||
url: '/inventory/count/completeInventoryCount',
|
||||
method: 'post',
|
||||
data: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 取消盘点
|
||||
export function cancelInventoryCount(id: string[], reason?: string) {
|
||||
return newService({
|
||||
url: '/inventory/count/cancelInventoryCount',
|
||||
method: 'post',
|
||||
data: { id, reason },
|
||||
});
|
||||
}
|
||||
|
||||
// 导出盘点模板
|
||||
export function exportInventoryCountTemplate() {
|
||||
return newService({
|
||||
url: '/inventory/count/exportInventoryCountTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
// 上传盘点Excel
|
||||
export function importInventoryCount(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
return newService({
|
||||
url: '/inventory/count/importInventoryCount',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -65,6 +65,20 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 盘点管理路由配置(供后端菜单配置参考)
|
||||
*
|
||||
* 父级菜单: 库存作业 (/assets/operation)
|
||||
*
|
||||
* 盘点菜单配置:
|
||||
* - 路由路径: /assets/operation/count
|
||||
* - 组件路径: assets/operation/count/index
|
||||
* - 路由名称: assetsOperationCount
|
||||
* - 菜单名称: 盘点
|
||||
* - 图标: ele-Document
|
||||
* - API权限: api/v1/assets/operation/count
|
||||
*/
|
||||
|
||||
export const demoRoutes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/demo',
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="form.id ? '编辑盘点任务' : '新增盘点任务'"
|
||||
width="700px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="任务名称" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入任务名称" maxlength="50" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="任务描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入任务描述" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="盘点类型" prop="countType">
|
||||
<el-select v-model="form.countType" placeholder="请选择盘点类型" style="width: 100%">
|
||||
<el-option label="明盘" :value="1" />
|
||||
<el-option label="盲盘" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="盘点范围" prop="warehouseIds">
|
||||
<div class="scope-select-box">
|
||||
<div class="scope-tags" v-if="scopeDisplayText">
|
||||
<el-tag type="info" size="small">{{ getScopeLabel(form.scope) }}</el-tag>
|
||||
<el-tag v-for="name in selectedWarehouseNames" :key="name" size="small" style="margin-left: 4px;">{{ name }}</el-tag>
|
||||
<el-tag v-for="name in selectedZoneNames" :key="name" size="small" type="success" style="margin-left: 4px;">{{ name }}</el-tag>
|
||||
<el-tag v-for="name in selectedLocationNames" :key="name" size="small" type="warning" style="margin-left: 4px;">{{ name }}</el-tag>
|
||||
</div>
|
||||
<el-button type="primary" link @click="openScopeDrawer">
|
||||
<el-icon><ele-Setting /></el-icon>
|
||||
{{ scopeDisplayText ? '修改' : '选择盘点范围' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 盘点范围选择抽屉 -->
|
||||
<ScopeSelectDrawer ref="scopeDrawerRef" @confirm="onScopeConfirm" />
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划开始" prop="plannedStartTime">
|
||||
<el-date-picker
|
||||
v-model="form.plannedStartTime"
|
||||
type="datetime"
|
||||
placeholder="请选择计划开始时间"
|
||||
style="width: 100%"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划结束" prop="plannedEndTime">
|
||||
<el-date-picker
|
||||
v-model="form.plannedEndTime"
|
||||
type="datetime"
|
||||
placeholder="请选择计划结束时间"
|
||||
style="width: 100%"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="负责人" prop="assigneeId">
|
||||
<el-input v-model="form.assigneeId" placeholder="请输入负责人" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="参与人员" prop="participants">
|
||||
<el-input v-model="participantsInput" placeholder="请输入参与人员,多人用逗号分隔" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" maxlength="500" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { createInventoryCount, updateInventoryCount, getInventoryCount } from '/@/api/assets/operation/count';
|
||||
import ScopeSelectDrawer from './scopeSelectDrawer.vue';
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance>();
|
||||
const scopeDrawerRef = ref();
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
id: '',
|
||||
title: '',
|
||||
description: '',
|
||||
warehouseIds: [] as string[],
|
||||
zoneIds: [] as string[],
|
||||
locationIds: [] as string[],
|
||||
countType: undefined as number | undefined,
|
||||
scope: 1 as number,
|
||||
plannedStartTime: '',
|
||||
plannedEndTime: '',
|
||||
assigneeId: '',
|
||||
participants: [] as string[],
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 选中的名称(用于显示)
|
||||
const selectedWarehouseNames = ref<string[]>([]);
|
||||
const selectedZoneNames = ref<string[]>([]);
|
||||
const selectedLocationNames = ref<string[]>([]);
|
||||
|
||||
// 参与人员输入框
|
||||
const participantsInput = ref('');
|
||||
|
||||
// 盘点范围显示文本
|
||||
const scopeDisplayText = computed(() => {
|
||||
return form.warehouseIds.length > 0;
|
||||
});
|
||||
|
||||
// 获取盘点范围标签
|
||||
const getScopeLabel = (scope: number) => {
|
||||
const labels: Record<number, string> = { 1: '按仓库盘点', 2: '按库区盘点', 3: '按库位盘点', 4: '按SKU盘点', 5: '按资产盘点' };
|
||||
return labels[scope] || '';
|
||||
};
|
||||
|
||||
// 表单校验规则
|
||||
const rules = reactive<FormRules>({
|
||||
title: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||||
countType: [{ required: true, message: '请选择盘点类型', trigger: 'change' }],
|
||||
assigneeId: [{ required: true, message: '请输入负责人', trigger: 'blur' }],
|
||||
warehouseIds: [{
|
||||
required: true,
|
||||
message: '请选择盘点范围',
|
||||
trigger: 'change',
|
||||
validator: (_rule: any, _value: any, callback: any) => {
|
||||
// 按SKU盘点(4)和按资产盘点(5)不需要选择仓库
|
||||
if (form.scope >= 4) {
|
||||
callback();
|
||||
} else if (form.warehouseIds.length === 0) {
|
||||
callback(new Error('请选择盘点范围'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}],
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = async (row?: any) => {
|
||||
resetForm();
|
||||
|
||||
if (row?.id) {
|
||||
try {
|
||||
const res: any = await getInventoryCount(row.id);
|
||||
if (res.code === 0 && res.data) {
|
||||
const data = res.data;
|
||||
form.id = data.id || '';
|
||||
form.title = data.title || '';
|
||||
form.description = data.description || '';
|
||||
form.countType = data.countType;
|
||||
form.scope = data.scope || 1;
|
||||
form.plannedStartTime = data.plannedStartTime || '';
|
||||
form.plannedEndTime = data.plannedEndTime || '';
|
||||
form.assigneeId = data.assigneeId || '';
|
||||
form.remark = data.remark || '';
|
||||
// 处理仓库/库区/库位ID(后端返回warehouseIDs,前端使用warehouseIds)
|
||||
form.warehouseIds = Array.isArray(data.warehouseIDs) ? data.warehouseIDs : (data.warehouseIDs ? [data.warehouseIDs] : []);
|
||||
form.zoneIds = Array.isArray(data.zoneIDs) ? data.zoneIDs : (data.zoneIDs ? [data.zoneIDs] : []);
|
||||
form.locationIds = Array.isArray(data.locationIDs) ? data.locationIDs : (data.locationIDs ? [data.locationIDs] : []);
|
||||
// 回显参与人员
|
||||
if (data.participants && Array.isArray(data.participants)) {
|
||||
participantsInput.value = data.participants.join(',');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取盘点任务详情失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
form.id = '';
|
||||
form.title = '';
|
||||
form.description = '';
|
||||
form.warehouseIds = [];
|
||||
form.zoneIds = [];
|
||||
form.locationIds = [];
|
||||
form.countType = undefined;
|
||||
form.scope = 1;
|
||||
form.plannedStartTime = '';
|
||||
form.plannedEndTime = '';
|
||||
form.assigneeId = '';
|
||||
form.participants = [];
|
||||
form.remark = '';
|
||||
participantsInput.value = '';
|
||||
selectedWarehouseNames.value = [];
|
||||
selectedZoneNames.value = [];
|
||||
selectedLocationNames.value = [];
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
// 打开盘点范围选择抽屉
|
||||
const openScopeDrawer = () => {
|
||||
scopeDrawerRef.value?.openDrawer({
|
||||
scope: form.scope,
|
||||
warehouseIds: form.warehouseIds,
|
||||
zoneIds: form.zoneIds,
|
||||
locationIds: form.locationIds,
|
||||
});
|
||||
};
|
||||
|
||||
// 盘点范围选择确认
|
||||
const onScopeConfirm = (data: any) => {
|
||||
form.scope = data.scope;
|
||||
form.warehouseIds = data.warehouseIds;
|
||||
form.zoneIds = data.zoneIds;
|
||||
form.locationIds = data.locationIds;
|
||||
selectedWarehouseNames.value = data.warehouseNames;
|
||||
selectedZoneNames.value = data.zoneNames;
|
||||
selectedLocationNames.value = data.locationNames;
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
// 构建提交数据
|
||||
const submitData: any = {
|
||||
title: form.title,
|
||||
description: form.description || undefined,
|
||||
countType: form.countType,
|
||||
scope: form.scope,
|
||||
plannedStartTime: form.plannedStartTime || undefined,
|
||||
plannedEndTime: form.plannedEndTime || undefined,
|
||||
participants: participantsInput.value ? participantsInput.value.split(',').map(s => s.trim()).filter(s => s) : undefined,
|
||||
remark: form.remark || undefined,
|
||||
};
|
||||
|
||||
// 添加选中的仓库/库区/库位ID数组
|
||||
if (form.warehouseIds.length > 0) submitData.warehouseIDs = form.warehouseIds;
|
||||
if (form.zoneIds.length > 0) submitData.zoneIDs = form.zoneIds;
|
||||
if (form.locationIds.length > 0) submitData.locationIDs = form.locationIds;
|
||||
if (form.assigneeId) submitData.assigneeId = form.assigneeId;
|
||||
|
||||
let res: any;
|
||||
if (form.id) {
|
||||
submitData.id = form.id;
|
||||
res = await updateInventoryCount(submitData);
|
||||
} else {
|
||||
res = await createInventoryCount(submitData);
|
||||
}
|
||||
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(form.id ? '修改成功' : '新增成功');
|
||||
emit('refresh');
|
||||
handleClose();
|
||||
} else {
|
||||
ElMessage.error(res.message || '操作失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存盘点任务失败:', error);
|
||||
ElMessage.error('操作失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scope-select-box {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
.scope-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
373
src/views/assets/operation/count/component/scopeSelectDrawer.vue
Normal file
373
src/views/assets/operation/count/component/scopeSelectDrawer.vue
Normal file
@@ -0,0 +1,373 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="visible"
|
||||
title="选择盘点范围"
|
||||
direction="rtl"
|
||||
size="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="scope-select-container">
|
||||
<!-- 盘点范围类型选择 -->
|
||||
<div class="scope-type-section">
|
||||
<div class="section-title">盘点范围类型</div>
|
||||
<el-radio-group v-model="scopeType" @change="onScopeTypeChange">
|
||||
<el-radio :value="1">按仓库盘点</el-radio>
|
||||
<el-radio :value="2">按库区盘点</el-radio>
|
||||
<el-radio :value="3">按库位盘点</el-radio>
|
||||
<el-radio :value="4">按SKU盘点</el-radio>
|
||||
<el-radio :value="5">按资产盘点</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<!-- 仓库选择 - 仅当盘点范围<=3时显示 -->
|
||||
<div v-if="scopeType <= 3" class="select-section">
|
||||
<div class="section-title">
|
||||
选择仓库
|
||||
<span class="required">*</span>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="selectedWarehouseIds"
|
||||
placeholder="请选择仓库"
|
||||
style="width: 100%"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
@change="onWarehouseChange"
|
||||
>
|
||||
<el-option v-for="item in warehouseOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- 库区选择 - 仅当盘点范围为2或3时显示 -->
|
||||
<div v-if="scopeType === 2 || scopeType === 3" class="select-section">
|
||||
<div class="section-title">
|
||||
选择库区
|
||||
<span v-if="scopeType >= 2" class="required">*</span>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="selectedZoneIds"
|
||||
placeholder="请先选择仓库"
|
||||
style="width: 100%"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
:disabled="selectedWarehouseIds.length === 0"
|
||||
@change="onZoneChange"
|
||||
>
|
||||
<el-option v-for="item in zoneOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- 库位选择 - 仅当盘点范围为3时显示 -->
|
||||
<div v-if="scopeType === 3" class="select-section">
|
||||
<div class="section-title">
|
||||
选择库位
|
||||
<span v-if="scopeType >= 3" class="required">*</span>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="selectedLocationIds"
|
||||
placeholder="请先选择库区"
|
||||
style="width: 100%"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
:disabled="selectedZoneIds.length === 0"
|
||||
>
|
||||
<el-option v-for="item in locationOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- 已选择的摘要 -->
|
||||
<div class="selected-summary">
|
||||
<div class="section-title">已选择</div>
|
||||
<div class="summary-content">
|
||||
<div v-if="scopeType <= 3 && selectedWarehouseIds.length > 0" class="summary-item">
|
||||
<span class="label">仓库:</span>
|
||||
<el-tag v-for="id in selectedWarehouseIds" :key="id" size="small" style="margin: 2px;">
|
||||
{{ getWarehouseName(id) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="(scopeType === 2 || scopeType === 3) && selectedZoneIds.length > 0" class="summary-item">
|
||||
<span class="label">库区:</span>
|
||||
<el-tag v-for="id in selectedZoneIds" :key="id" size="small" type="success" style="margin: 2px;">
|
||||
{{ getZoneName(id) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="scopeType === 3 && selectedLocationIds.length > 0" class="summary-item">
|
||||
<span class="label">库位:</span>
|
||||
<el-tag v-for="id in selectedLocationIds" :key="id" size="small" type="warning" style="margin: 2px;">
|
||||
{{ getLocationName(id) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="scopeType <= 3 && selectedWarehouseIds.length === 0" class="empty-tip">暂未选择</div>
|
||||
<div v-if="scopeType >= 4" class="empty-tip">无需选择仓库</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { listWarehouses } from '/@/api/assets/warehouse';
|
||||
import { listZones } from '/@/api/assets/zone';
|
||||
import { listLocations } from '/@/api/assets/location';
|
||||
|
||||
const emit = defineEmits(['confirm']);
|
||||
|
||||
const visible = ref(false);
|
||||
const scopeType = ref(1);
|
||||
const selectedWarehouseIds = ref<string[]>([]);
|
||||
const selectedZoneIds = ref<string[]>([]);
|
||||
const selectedLocationIds = ref<string[]>([]);
|
||||
|
||||
const warehouseOptions = ref<any[]>([]);
|
||||
const zoneOptions = ref<any[]>([]);
|
||||
const locationOptions = ref<any[]>([]);
|
||||
|
||||
// 打开抽屉
|
||||
const openDrawer = async (data?: { scope: number; warehouseIds: string[]; zoneIds: string[]; locationIds: string[] }) => {
|
||||
// 重置
|
||||
scopeType.value = data?.scope || 1;
|
||||
selectedWarehouseIds.value = data?.warehouseIds || [];
|
||||
selectedZoneIds.value = data?.zoneIds || [];
|
||||
selectedLocationIds.value = data?.locationIds || [];
|
||||
|
||||
// 加载仓库列表
|
||||
await loadWarehouses();
|
||||
|
||||
// 如果有已选仓库,加载库区
|
||||
if (selectedWarehouseIds.value.length > 0 && scopeType.value >= 2) {
|
||||
await loadZones();
|
||||
}
|
||||
|
||||
// 如果有已选库区,加载库位
|
||||
if (selectedZoneIds.value.length > 0 && scopeType.value >= 3) {
|
||||
await loadLocations();
|
||||
}
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 加载仓库列表
|
||||
const loadWarehouses = async () => {
|
||||
try {
|
||||
const res: any = await listWarehouses({ pageNum: 1, pageSize: 100 });
|
||||
warehouseOptions.value = (res.data?.list || []).map((item: any) => ({
|
||||
id: item.id,
|
||||
name: item.warehouseName,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('加载仓库列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载库区列表
|
||||
const loadZones = async () => {
|
||||
if (selectedWarehouseIds.value.length === 0) {
|
||||
zoneOptions.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const allZones: any[] = [];
|
||||
for (const warehouseId of selectedWarehouseIds.value) {
|
||||
const res: any = await listZones({ warehouseId, pageNum: 1, pageSize: 100 });
|
||||
const list = res.data?.list || res.data?.items || res.data || [];
|
||||
const zones = (Array.isArray(list) ? list : []).map((item: any) => ({
|
||||
id: item.id || item._id,
|
||||
name: item.zoneName || item.name,
|
||||
warehouseId: item.warehouseId,
|
||||
}));
|
||||
allZones.push(...zones);
|
||||
}
|
||||
zoneOptions.value = allZones;
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载库位列表
|
||||
const loadLocations = async () => {
|
||||
if (selectedZoneIds.value.length === 0) {
|
||||
locationOptions.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const allLocations: any[] = [];
|
||||
for (const zoneId of selectedZoneIds.value) {
|
||||
const res: any = await listLocations({ zoneId, pageNum: 1, pageSize: 100 });
|
||||
const list = res.data?.list || res.data?.items || res.data || [];
|
||||
const locations = (Array.isArray(list) ? list : []).map((item: any) => ({
|
||||
id: item.id || item._id,
|
||||
name: item.locationName || item.name,
|
||||
zoneId: item.zoneId,
|
||||
}));
|
||||
allLocations.push(...locations);
|
||||
}
|
||||
locationOptions.value = allLocations;
|
||||
} catch (error) {
|
||||
console.error('加载库位列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 盘点范围类型变化
|
||||
const onScopeTypeChange = () => {
|
||||
// 清空下级选择
|
||||
if (scopeType.value < 2) {
|
||||
selectedZoneIds.value = [];
|
||||
zoneOptions.value = [];
|
||||
}
|
||||
if (scopeType.value < 3) {
|
||||
selectedLocationIds.value = [];
|
||||
locationOptions.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
// 仓库变化
|
||||
const onWarehouseChange = async () => {
|
||||
selectedZoneIds.value = [];
|
||||
selectedLocationIds.value = [];
|
||||
zoneOptions.value = [];
|
||||
locationOptions.value = [];
|
||||
|
||||
if (scopeType.value >= 2) {
|
||||
await loadZones();
|
||||
}
|
||||
};
|
||||
|
||||
// 库区变化
|
||||
const onZoneChange = async () => {
|
||||
selectedLocationIds.value = [];
|
||||
locationOptions.value = [];
|
||||
|
||||
if (scopeType.value >= 3) {
|
||||
await loadLocations();
|
||||
}
|
||||
};
|
||||
|
||||
// 获取仓库名称
|
||||
const getWarehouseName = (id: string) => {
|
||||
return warehouseOptions.value.find(item => item.id === id)?.name || id;
|
||||
};
|
||||
|
||||
// 获取库区名称
|
||||
const getZoneName = (id: string) => {
|
||||
return zoneOptions.value.find(item => item.id === id)?.name || id;
|
||||
};
|
||||
|
||||
// 获取库位名称
|
||||
const getLocationName = (id: string) => {
|
||||
return locationOptions.value.find(item => item.id === id)?.name || id;
|
||||
};
|
||||
|
||||
// 关闭抽屉
|
||||
const handleClose = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
// 验证 - 按SKU盘点(4)和按资产盘点(5)不需要选择仓库
|
||||
if (scopeType.value <= 3 && selectedWarehouseIds.value.length === 0) {
|
||||
ElMessage.warning('请选择仓库');
|
||||
return;
|
||||
}
|
||||
|
||||
if ((scopeType.value === 2 || scopeType.value === 3) && selectedZoneIds.value.length === 0) {
|
||||
ElMessage.warning('请选择库区');
|
||||
return;
|
||||
}
|
||||
|
||||
if (scopeType.value === 3 && selectedLocationIds.value.length === 0) {
|
||||
ElMessage.warning('请选择库位');
|
||||
return;
|
||||
}
|
||||
|
||||
emit('confirm', {
|
||||
scope: scopeType.value,
|
||||
warehouseIds: selectedWarehouseIds.value,
|
||||
zoneIds: selectedZoneIds.value,
|
||||
locationIds: selectedLocationIds.value,
|
||||
// 用于显示的名称
|
||||
warehouseNames: selectedWarehouseIds.value.map(id => getWarehouseName(id)),
|
||||
zoneNames: selectedZoneIds.value.map(id => getZoneName(id)),
|
||||
locationNames: selectedLocationIds.value.map(id => getLocationName(id)),
|
||||
});
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openDrawer,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scope-select-container {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.scope-type-section {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.section-title .required {
|
||||
color: #f56c6c;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.select-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.selected-summary {
|
||||
margin-top: 24px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.summary-content {
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.summary-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.summary-item .label {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="visible"
|
||||
title="选择仓库"
|
||||
direction="rtl"
|
||||
size="400px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="warehouse-select-container">
|
||||
<div class="search-box">
|
||||
<el-input v-model="searchKeyword" placeholder="搜索仓库名称" clearable>
|
||||
<template #prefix>
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<div class="select-all">
|
||||
<el-checkbox v-model="selectAll" :indeterminate="isIndeterminate" @change="handleSelectAll">
|
||||
全选
|
||||
</el-checkbox>
|
||||
<span class="selected-count">已选 {{ selectedIds.length }} 个</span>
|
||||
</div>
|
||||
|
||||
<div class="warehouse-list" v-loading="loading">
|
||||
<el-checkbox-group v-model="selectedIds" @change="handleSelectionChange">
|
||||
<div v-for="item in filteredList" :key="item.id" class="warehouse-item">
|
||||
<el-checkbox :label="item.id">
|
||||
<div class="warehouse-info">
|
||||
<span class="warehouse-name">{{ item.warehouseName }}</span>
|
||||
<span class="warehouse-code">{{ item.warehouseCode }}</span>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
<el-empty v-if="filteredList.length === 0" description="暂无数据" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { listWarehouses } from '/@/api/assets/warehouse';
|
||||
|
||||
const emit = defineEmits(['confirm']);
|
||||
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const searchKeyword = ref('');
|
||||
const warehouseList = ref<any[]>([]);
|
||||
const selectedIds = ref<string[]>([]);
|
||||
|
||||
// 过滤后的列表
|
||||
const filteredList = computed(() => {
|
||||
if (!searchKeyword.value) return warehouseList.value;
|
||||
const keyword = searchKeyword.value.toLowerCase();
|
||||
return warehouseList.value.filter(item =>
|
||||
item.warehouseName?.toLowerCase().includes(keyword) ||
|
||||
item.warehouseCode?.toLowerCase().includes(keyword)
|
||||
);
|
||||
});
|
||||
|
||||
// 全选状态
|
||||
const selectAll = computed({
|
||||
get: () => selectedIds.value.length === warehouseList.value.length && warehouseList.value.length > 0,
|
||||
set: () => {}
|
||||
});
|
||||
|
||||
// 半选状态
|
||||
const isIndeterminate = computed(() => {
|
||||
return selectedIds.value.length > 0 && selectedIds.value.length < warehouseList.value.length;
|
||||
});
|
||||
|
||||
// 加载仓库列表
|
||||
const loadWarehouseList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res: any = await listWarehouses({ pageNum: 1, pageSize: 1000 });
|
||||
warehouseList.value = res.data?.list || [];
|
||||
} catch (error) {
|
||||
console.error('加载仓库列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 打开抽屉
|
||||
const openDrawer = (ids: string[] = []) => {
|
||||
selectedIds.value = [...ids];
|
||||
loadWarehouseList();
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 关闭抽屉
|
||||
const handleClose = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
// 全选/取消全选
|
||||
const handleSelectAll = (val: boolean) => {
|
||||
if (val) {
|
||||
selectedIds.value = warehouseList.value.map(item => item.id);
|
||||
} else {
|
||||
selectedIds.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
// 选择变化
|
||||
const handleSelectionChange = () => {
|
||||
// 触发更新
|
||||
};
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
const selectedItems = warehouseList.value.filter(item => selectedIds.value.includes(item.id));
|
||||
emit('confirm', selectedIds.value, selectedItems);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
// 获取选中的仓库名称
|
||||
const getSelectedNames = () => {
|
||||
return warehouseList.value
|
||||
.filter(item => selectedIds.value.includes(item.id))
|
||||
.map(item => item.warehouseName)
|
||||
.join('、');
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openDrawer,
|
||||
getSelectedNames,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.warehouse-select-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.search-box {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.select-all {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.selected-count {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.warehouse-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
||||
.warehouse-item {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.warehouse-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.warehouse-name {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.warehouse-code {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
357
src/views/assets/operation/count/index.vue
Normal file
357
src/views/assets/operation/count/index.vue
Normal file
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<div class="inventory-count-page">
|
||||
<div class="inventory-count-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="inventory-count-search mb15">
|
||||
<el-form :inline="true" :model="tableData.param">
|
||||
<el-form-item label="关键词">
|
||||
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入关键词" clearable style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="盘点类型">
|
||||
<el-select size="default" v-model="tableData.param.countType" placeholder="请选择盘点类型" clearable style="width: 150px">
|
||||
<el-option label="明盘" :value="1" />
|
||||
<el-option label="盲盘" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select size="default" v-model="tableData.param.status" placeholder="请选择状态" clearable style="width: 120px">
|
||||
<el-option label="草稿" :value="1" />
|
||||
<el-option label="已计划" :value="2" />
|
||||
<el-option label="进行中" :value="3" />
|
||||
<el-option label="已提交" :value="4" />
|
||||
<el-option label="已完成" :value="5" />
|
||||
<el-option label="已取消" :value="6" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="getList">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" @click="onResetQuery">
|
||||
<el-icon><ele-Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="onOpenAdd">
|
||||
<el-icon><ele-Plus /></el-icon>
|
||||
新增
|
||||
</el-button>
|
||||
<el-button size="default" type="warning" @click="onExportTemplate">
|
||||
<el-icon><ele-Download /></el-icon>
|
||||
导出模板
|
||||
</el-button>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
accept=".xlsx,.xls"
|
||||
:on-change="handleImportChange"
|
||||
style="display: inline-block; margin-left: 10px;"
|
||||
>
|
||||
<el-button size="default" type="info" :loading="importLoading">
|
||||
<el-icon><ele-Upload /></el-icon>
|
||||
导入
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" border>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="countNo" label="盘点编号" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="title" label="任务名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="countTypeText" label="盘点类型" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getCountTypeTag(scope.row.countType)">{{ scope.row.countTypeText || getCountTypeLabel(scope.row.countType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="scopeText" label="盘点范围" width="100" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.scopeText || getScopeLabel(scope.row.scope) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="warehouseName" label="仓库" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="statusText" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusTag(scope.row.status)">{{ scope.row.statusText || getStatusLabel(scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="progress" label="进度" width="80" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.progress || 0 }}%
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="assigneeName" label="负责人" width="100" align="center" />
|
||||
<el-table-column prop="createdAt" label="创建时间" width="170" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
|
||||
<el-button link type="danger" @click="onDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<div class="mt15" style="text-align: right">
|
||||
<el-pagination
|
||||
v-model:current-page="tableData.param.pageNum"
|
||||
v-model:page-size="tableData.param.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="tableData.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<EditInventoryCount ref="editRef" @refresh="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'assetsOperationCount',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { listInventoryCounts, deleteInventoryCount, completeInventoryCount, cancelInventoryCount, exportInventoryCountTemplate, importInventoryCount } from '/@/api/assets/operation/count';
|
||||
import type { UploadFile } from 'element-plus';
|
||||
import EditInventoryCount from './component/editInventoryCount.vue';
|
||||
|
||||
const editRef = ref();
|
||||
const uploadRef = ref();
|
||||
const importLoading = ref(false);
|
||||
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
countType: undefined as number | undefined,
|
||||
status: undefined as number | undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
// 获取盘点类型标签
|
||||
const getCountTypeTag = (type: number) => {
|
||||
const tagMap: Record<number, string> = {
|
||||
0: 'primary',
|
||||
1: 'success',
|
||||
2: 'warning',
|
||||
};
|
||||
return tagMap[type] || 'info';
|
||||
};
|
||||
|
||||
// 获取盘点类型文本
|
||||
const getCountTypeLabel = (type: number) => {
|
||||
const labelMap: Record<number, string> = {
|
||||
1: '明盘',
|
||||
2: '盲盘',
|
||||
};
|
||||
return labelMap[type] || '未知';
|
||||
};
|
||||
|
||||
// 获取盘点范围文本
|
||||
const getScopeLabel = (scope: number) => {
|
||||
const labelMap: Record<number, string> = {
|
||||
1: '按仓库盘点',
|
||||
2: '按库区盘点',
|
||||
3: '按库位盘点',
|
||||
4: '按SKU盘点',
|
||||
5: '按资产盘点',
|
||||
};
|
||||
return labelMap[scope] || '未知';
|
||||
};
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusTag = (status: number) => {
|
||||
const tagMap: Record<number, string> = {
|
||||
1: 'info', // 草稿
|
||||
2: 'primary', // 已计划
|
||||
3: 'warning', // 进行中
|
||||
4: '', // 已提交
|
||||
5: 'success', // 已完成
|
||||
6: 'danger', // 已取消
|
||||
};
|
||||
return tagMap[status] || 'info';
|
||||
};
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusLabel = (status: number) => {
|
||||
const labelMap: Record<number, string> = {
|
||||
1: '草稿',
|
||||
2: '已计划',
|
||||
3: '进行中',
|
||||
4: '已提交',
|
||||
5: '已完成',
|
||||
6: '已取消',
|
||||
};
|
||||
return labelMap[status] || '未知';
|
||||
};
|
||||
|
||||
// 获取列表
|
||||
const getList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
const res: any = await listInventoryCounts(tableData.param);
|
||||
tableData.data = res.data?.list || [];
|
||||
tableData.total = res.data?.total || 0;
|
||||
} catch (error) {
|
||||
console.error('获取盘点任务列表失败:', error);
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置查询
|
||||
const onResetQuery = () => {
|
||||
tableData.param.keyword = '';
|
||||
tableData.param.countType = undefined;
|
||||
tableData.param.status = undefined;
|
||||
tableData.param.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
// 新增
|
||||
const onOpenAdd = () => {
|
||||
editRef.value?.openDialog();
|
||||
};
|
||||
|
||||
// 编辑
|
||||
const onEdit = (row: any) => {
|
||||
editRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 完成盘点
|
||||
const onComplete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定要完成盘点任务【${row.title}】吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
try {
|
||||
const res: any = await completeInventoryCount(row.id);
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('操作成功');
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.message || '操作失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('完成盘点失败:', error);
|
||||
}
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
// 取消盘点
|
||||
const onCancel = (row: any) => {
|
||||
ElMessageBox.prompt(`请输入取消原因`, '取消盘点任务', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPlaceholder: '请输入取消原因',
|
||||
}).then(async ({ value }) => {
|
||||
try {
|
||||
const res: any = await cancelInventoryCount([row.id], value);
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('操作成功');
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.message || '操作失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('取消盘点失败:', error);
|
||||
}
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
// 删除
|
||||
const onDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定要删除盘点任务【${row.title}】吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
try {
|
||||
const res: any = await deleteInventoryCount(row.id);
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.message || '删除失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除盘点任务失败:', error);
|
||||
}
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
// 导出模板
|
||||
const onExportTemplate = async () => {
|
||||
try {
|
||||
const res = await exportInventoryCountTemplate();
|
||||
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = '盘点模板.xlsx';
|
||||
link.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
ElMessage.success('导出成功');
|
||||
} catch (error) {
|
||||
console.error('导出模板失败:', error);
|
||||
ElMessage.error('导出模板失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 导入文件变化
|
||||
const handleImportChange = async (file: UploadFile) => {
|
||||
if (!file.raw) return;
|
||||
|
||||
importLoading.value = true;
|
||||
try {
|
||||
const res = await importInventoryCount(file.raw);
|
||||
if (res.data.code === 200) {
|
||||
ElMessage.success('导入成功');
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.data.msg || '导入失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('导入失败:', error);
|
||||
ElMessage.error('导入失败');
|
||||
} finally {
|
||||
importLoading.value = false;
|
||||
uploadRef.value?.clearFiles();
|
||||
}
|
||||
};
|
||||
|
||||
// 分页大小变化
|
||||
const onSizeChange = (size: number) => {
|
||||
tableData.param.pageSize = size;
|
||||
tableData.param.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
// 页码变化
|
||||
const onCurrentChange = (page: number) => {
|
||||
tableData.param.pageNum = page;
|
||||
getList();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.inventory-count-page {
|
||||
padding: 15px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user