2025-08-14 19:43:46 +08:00
|
|
|
|
<template>
|
2025-08-15 00:22:06 +08:00
|
|
|
|
<div class="overall-plan-material-supply">
|
|
|
|
|
<el-card shadow="always">
|
|
|
|
|
<template #header>
|
|
|
|
|
<el-row :gutter="10" class="mb8">
|
|
|
|
|
<el-form :inline="true">
|
|
|
|
|
<el-form-item v-if="state.masterData.status == 'draft'">
|
2025-08-26 21:00:46 +08:00
|
|
|
|
<el-button type="primary" icon="edit" @click="clickApprovalSheet1()">审批</el-button>
|
2025-08-15 00:22:06 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item v-if="state.masterData.status == 'waiting' || state.masterData.status == 'finish'">
|
2025-08-29 18:06:42 +08:00
|
|
|
|
<el-button icon="view" @click="lookApprovalFlow()" type="warning">查看流程</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<file-upload
|
|
|
|
|
upload-url="/design/totalsupplyplan/import"
|
|
|
|
|
v-model="file"
|
|
|
|
|
:limit="1"
|
|
|
|
|
:file-type="['xls', 'xlsx']"
|
|
|
|
|
:on-upload-success="handleSuccess"
|
|
|
|
|
>
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-button :disabled="state.masterData.status == 'finish'" type="primary" plain icon="upload">导入</el-button>
|
2025-08-29 18:06:42 +08:00
|
|
|
|
</file-upload>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-button type="primary" plain icon="Download" @click="handleExport">导出</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-button icon="Finished" @click="editApprovalSheet()" type="success" :disabled="state.masterData.status == 'finish'"
|
|
|
|
|
>一键全部保存</el-button
|
|
|
|
|
>
|
2025-08-15 00:22:06 +08:00
|
|
|
|
</el-form-item>
|
2025-09-04 18:42:45 +08:00
|
|
|
|
<!-- <el-form-item>
|
2025-09-02 19:00:50 +08:00
|
|
|
|
<el-button type="primary" @click="toggleExpandAll">{{ isExpandAll ? '一键收起' : '一键展开' }}</el-button>
|
2025-09-04 18:42:45 +08:00
|
|
|
|
</el-form-item> -->
|
2025-08-15 00:22:06 +08:00
|
|
|
|
</el-form>
|
|
|
|
|
<right-toolbar @queryTable="getMasterDataList"></right-toolbar>
|
|
|
|
|
</el-row>
|
|
|
|
|
</template>
|
|
|
|
|
</el-card>
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
<!-- 本地数据懒加载表格 -->
|
2025-08-15 00:22:06 +08:00
|
|
|
|
<el-table
|
|
|
|
|
:data="state.tableData"
|
|
|
|
|
v-loading="state.loading.list"
|
2025-09-02 19:00:50 +08:00
|
|
|
|
ref="tableRef"
|
2025-08-15 00:22:06 +08:00
|
|
|
|
stripe
|
|
|
|
|
style="width: 100%; margin-bottom: 20px; height: calc(100vh - 230px)"
|
|
|
|
|
row-key="id"
|
|
|
|
|
border
|
2025-08-29 18:54:43 +08:00
|
|
|
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
2025-09-04 18:42:45 +08:00
|
|
|
|
:lazy="true"
|
|
|
|
|
:load="loadLocalChildNodes"
|
|
|
|
|
@expand-change="handleExpandChange"
|
2025-08-15 00:22:06 +08:00
|
|
|
|
>
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-table-column align="center" prop="num" label="编号" />
|
2025-08-15 02:11:07 +08:00
|
|
|
|
<el-table-column prop="name" label="工程或费用名称" width="180" />
|
2025-08-15 00:22:06 +08:00
|
|
|
|
<el-table-column prop="unit" label="单位" />
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-table-column prop="specification" label="规格型号" width="80" />
|
|
|
|
|
<el-table-column prop="quantity" label="数量" width="100" />
|
2025-08-15 00:22:06 +08:00
|
|
|
|
<el-table-column prop="batchNumber" label="批次号" width="200" />
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
<!-- 优化的输入框列 -->
|
2025-08-29 18:06:42 +08:00
|
|
|
|
<el-table-column prop="brand" label="品牌">
|
|
|
|
|
<template #default="{ row }">
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-input
|
2025-09-04 18:42:45 +08:00
|
|
|
|
v-model.lazy="row.brand"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
:disabled="state.masterData.status != 'draft'"
|
2025-09-04 18:42:45 +08:00
|
|
|
|
v-if="!row.hasChildren"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
placeholder=""
|
|
|
|
|
clearable
|
2025-09-04 18:42:45 +08:00
|
|
|
|
:key="`brand-${row.id}`"
|
|
|
|
|
@change="handleInputChange(row, 'brand')"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
/>
|
2025-08-29 18:06:42 +08:00
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
2025-08-29 18:06:42 +08:00
|
|
|
|
<el-table-column prop="texture" label="材质">
|
|
|
|
|
<template #default="{ row }">
|
2025-08-29 20:59:59 +08:00
|
|
|
|
<el-input
|
2025-09-04 18:42:45 +08:00
|
|
|
|
v-model.lazy="row.texture"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
:disabled="state.masterData.status != 'draft'"
|
2025-09-04 18:42:45 +08:00
|
|
|
|
v-if="!row.hasChildren"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
placeholder=""
|
|
|
|
|
clearable
|
2025-09-04 18:42:45 +08:00
|
|
|
|
:key="`texture-${row.id}`"
|
|
|
|
|
@change="handleInputChange(row, 'texture')"
|
2025-08-29 20:59:59 +08:00
|
|
|
|
/>
|
2025-08-29 18:06:42 +08:00
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
2025-08-15 00:22:06 +08:00
|
|
|
|
</el-table>
|
2025-09-08 09:41:59 +08:00
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
<!-- 编辑弹窗 -->
|
2025-08-15 00:22:06 +08:00
|
|
|
|
<el-dialog v-model="visible" title="修改物料信息" :width="800" :close-on-click-modal="false" @close="handleClose">
|
|
|
|
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" class="space-y-4">
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="批次号" prop="batchNumber">
|
|
|
|
|
<el-input disabled v-model="formData.batchNumber" placeholder="请输入批次号" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="品牌" prop="brand">
|
|
|
|
|
<el-input v-model="formData.brand" placeholder="请输入品牌" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="材质" prop="texture">
|
|
|
|
|
<el-input v-model="formData.texture" placeholder="请输入材质" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="质量标准" prop="qualityStandard">
|
|
|
|
|
<el-input v-model="formData.qualityStandard" placeholder="请输入质量标准" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="使用部位" prop="partUsed">
|
|
|
|
|
<el-input v-model="formData.partUsed" placeholder="请输入使用部位" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="交货地点" prop="deliveryPoints">
|
|
|
|
|
<el-input v-model="formData.deliveryPoints" placeholder="请输入交货地点" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="预计使用日期" prop="dateService">
|
|
|
|
|
<el-date-picker v-model="formData.dateService" type="date" placeholder="选择预计使用日期" format="YYYY-MM-DD" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row>
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
<el-form-item label="备注" prop="remark">
|
|
|
|
|
<el-input v-model="formData.remark" placeholder="请输入备注信息" type="textarea" rows="3" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-form>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button @click="handleClose">取消</el-button>
|
|
|
|
|
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
2025-08-14 19:43:46 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup name="billofQuantities">
|
2025-09-04 18:42:45 +08:00
|
|
|
|
import { ref, reactive, onMounted, computed, getCurrentInstance, watch, onUnmounted } from 'vue';
|
|
|
|
|
import { ElMessage, ElLoading } from 'element-plus';
|
2025-08-15 00:22:06 +08:00
|
|
|
|
import {
|
|
|
|
|
obtainMasterDataList,
|
|
|
|
|
totalsupplyplan,
|
|
|
|
|
totalSupplyplanDetails,
|
2025-08-29 18:06:42 +08:00
|
|
|
|
materialChangeSupplyplan,
|
|
|
|
|
totalSupplyplanBatchEdit
|
2025-08-15 00:22:06 +08:00
|
|
|
|
} from '@/api/materials/overallPlanMaterialSupply/index';
|
2025-08-14 19:43:46 +08:00
|
|
|
|
import { useUserStoreHook } from '@/store/modules/user';
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
// 全局状态与实例获取
|
2025-08-14 19:43:46 +08:00
|
|
|
|
const userStore = useUserStoreHook();
|
|
|
|
|
const currentProject = computed(() => userStore.selectedProject);
|
|
|
|
|
const { proxy } = getCurrentInstance();
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
// 基础状态管理
|
2025-08-14 19:43:46 +08:00
|
|
|
|
const visible = ref(false);
|
|
|
|
|
const formRef = ref(null);
|
2025-09-04 18:42:45 +08:00
|
|
|
|
const tableRef = ref(null);
|
|
|
|
|
const file = ref(null);
|
|
|
|
|
const isExpandAll = ref(false);
|
|
|
|
|
const expandRowKeys = ref([]);
|
|
|
|
|
const editDataMap = ref(new Map()); // 用Map存储修改的数据,提高查询效率
|
|
|
|
|
const loadingInstance = ref(null);
|
|
|
|
|
const fullTreeData = ref([]); // 存储完整树形数据,用于本地懒加载
|
|
|
|
|
|
|
|
|
|
// 页面核心状态
|
2025-08-14 19:43:46 +08:00
|
|
|
|
const state = reactive({
|
2025-09-04 18:42:45 +08:00
|
|
|
|
tableData: [], // 初始只存放根节点
|
2025-08-15 00:22:06 +08:00
|
|
|
|
queryForm: {
|
|
|
|
|
projectId: currentProject.value?.id,
|
|
|
|
|
versions: '',
|
|
|
|
|
sheet: '',
|
|
|
|
|
pageSize: 20,
|
|
|
|
|
pageNum: 1
|
|
|
|
|
},
|
|
|
|
|
loading: {
|
|
|
|
|
versions: false,
|
|
|
|
|
sheets: false,
|
|
|
|
|
list: false
|
|
|
|
|
},
|
|
|
|
|
masterData: {}
|
2025-08-14 19:43:46 +08:00
|
|
|
|
});
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
2025-08-14 19:43:46 +08:00
|
|
|
|
// 表单数据
|
|
|
|
|
const formData = reactive({
|
2025-08-15 00:22:06 +08:00
|
|
|
|
batchNumber: '',
|
|
|
|
|
brand: '',
|
|
|
|
|
compileDate: '',
|
|
|
|
|
dateService: '',
|
|
|
|
|
deliveryPoints: '',
|
|
|
|
|
id: undefined,
|
|
|
|
|
name: '',
|
|
|
|
|
num: '',
|
|
|
|
|
partUsed: '',
|
|
|
|
|
planNumber: '',
|
|
|
|
|
projectId: undefined,
|
|
|
|
|
qualityStandard: '',
|
|
|
|
|
quantity: 0,
|
|
|
|
|
remark: '',
|
|
|
|
|
specification: '',
|
|
|
|
|
status: '',
|
|
|
|
|
texture: '',
|
|
|
|
|
unit: ''
|
2025-08-14 19:43:46 +08:00
|
|
|
|
});
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
2025-08-14 19:43:46 +08:00
|
|
|
|
// 表单验证规则
|
|
|
|
|
const formRules = reactive({
|
2025-08-15 00:22:06 +08:00
|
|
|
|
name: [
|
|
|
|
|
{ required: true, message: '请输入名称', trigger: 'blur' },
|
|
|
|
|
{ max: 100, message: '名称长度不能超过100个字符', trigger: 'blur' }
|
|
|
|
|
],
|
|
|
|
|
num: [
|
|
|
|
|
{ required: true, message: '请输入编号', trigger: 'blur' },
|
|
|
|
|
{ max: 50, message: '编号长度不能超过50个字符', trigger: 'blur' }
|
|
|
|
|
],
|
|
|
|
|
quantity: [
|
|
|
|
|
{ required: true, message: '请输入数量', trigger: 'blur' },
|
|
|
|
|
{ type: 'number', min: 0, message: '数量不能为负数', trigger: 'blur' }
|
|
|
|
|
],
|
|
|
|
|
compileDate: [{ required: true, message: '请选择编制日期', trigger: 'change' }]
|
2025-08-14 19:43:46 +08:00
|
|
|
|
});
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 本地数据懒加载实现:从完整数据中筛选子节点
|
|
|
|
|
*/
|
|
|
|
|
const loadLocalChildNodes = (row, treeNode, resolve) => {
|
|
|
|
|
// 避免重复加载
|
|
|
|
|
if (row.children && row.children.length > 0) {
|
|
|
|
|
resolve(row.children);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
loadingInstance.value = ElLoading.service({
|
|
|
|
|
target: tableRef.value.$el,
|
|
|
|
|
text: '加载中...',
|
|
|
|
|
background: 'rgba(255, 255, 255, 0.8)'
|
2025-09-02 19:00:50 +08:00
|
|
|
|
});
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 从完整数据中筛选当前行的子节点(假设父ID对应子节点的pid)
|
|
|
|
|
const childNodes = fullTreeData.value.filter((node) => node.pid === row.sid);
|
|
|
|
|
|
|
|
|
|
// 标记子节点是否有子节点
|
|
|
|
|
const formattedChildren = childNodes.map((node) => ({
|
|
|
|
|
...node,
|
|
|
|
|
hasChildren: fullTreeData.value.some((child) => child.pid === node.sid)
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// 缓存子节点到当前行
|
|
|
|
|
row.children = formattedChildren;
|
|
|
|
|
resolve(formattedChildren);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
resolve([]);
|
|
|
|
|
} finally {
|
|
|
|
|
loadingInstance.value?.close();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理展开状态变化
|
|
|
|
|
*/
|
|
|
|
|
const handleExpandChange = (row, expanded) => {
|
|
|
|
|
if (expanded) {
|
|
|
|
|
if (!expandRowKeys.value.includes(row.id)) {
|
|
|
|
|
expandRowKeys.value.push(row.id);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
expandRowKeys.value = expandRowKeys.value.filter((id) => id !== row.id);
|
|
|
|
|
}
|
2025-09-02 19:00:50 +08:00
|
|
|
|
};
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 一键展开/收起
|
|
|
|
|
*/
|
|
|
|
|
const toggleExpandAll = async () => {
|
|
|
|
|
isExpandAll.value = !isExpandAll.value;
|
|
|
|
|
|
|
|
|
|
if (isExpandAll.value) {
|
|
|
|
|
loadingInstance.value = ElLoading.service({
|
|
|
|
|
target: tableRef.value.$el,
|
|
|
|
|
text: '正在加载...',
|
|
|
|
|
background: 'rgba(255, 255, 255, 0.8)'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 递归加载所有层级子节点
|
|
|
|
|
const loadAllChildren = (nodes) => {
|
|
|
|
|
nodes.forEach((node) => {
|
|
|
|
|
const children = fullTreeData.value.filter((child) => child.pid === node.sid);
|
|
|
|
|
const formattedChildren = children.map((child) => ({
|
|
|
|
|
...child,
|
|
|
|
|
hasChildren: fullTreeData.value.some((c) => c.pid === child.sid)
|
|
|
|
|
}));
|
|
|
|
|
node.children = formattedChildren;
|
|
|
|
|
if (formattedChildren.length > 0) {
|
|
|
|
|
loadAllChildren(formattedChildren);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadAllChildren(state.tableData);
|
|
|
|
|
// 展开所有节点
|
|
|
|
|
state.tableData.forEach((row) => {
|
|
|
|
|
tableRef.value.toggleRowExpansion(row, true);
|
|
|
|
|
});
|
|
|
|
|
ElMessage.success('所有节点已展开');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error(`一键展开失败:${error.message}`);
|
|
|
|
|
} finally {
|
|
|
|
|
loadingInstance.value?.close();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 收起所有节点
|
|
|
|
|
state.tableData.forEach((row) => {
|
|
|
|
|
tableRef.value.toggleRowExpansion(row, false);
|
|
|
|
|
});
|
|
|
|
|
expandRowKeys.value = [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理输入框变化(优化性能)
|
|
|
|
|
*/
|
|
|
|
|
const handleInputChange = (row, field) => {
|
|
|
|
|
// 只记录修改过的数据,避免全量对比
|
|
|
|
|
if (!editDataMap.value.has(row.id)) {
|
|
|
|
|
editDataMap.value.set(row.id, { ...row });
|
|
|
|
|
}
|
|
|
|
|
const storedData = editDataMap.value.get(row.id);
|
|
|
|
|
storedData[field] = row[field];
|
|
|
|
|
editDataMap.value.set(row.id, storedData);
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 获取主数据列表(核心优化:拆分根节点和完整数据)
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
async function getMasterDataList() {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
try {
|
|
|
|
|
state.loading.list = true;
|
2025-09-04 18:42:45 +08:00
|
|
|
|
// 获取主数据
|
2025-08-15 00:22:06 +08:00
|
|
|
|
const masterDataRes = await obtainMasterDataList({
|
|
|
|
|
projectId: currentProject.value?.id
|
|
|
|
|
});
|
|
|
|
|
const { data: masterData } = masterDataRes;
|
2025-08-14 19:43:46 +08:00
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
if (!masterData[0]?.id) {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
state.tableData = [];
|
2025-09-04 18:42:45 +08:00
|
|
|
|
fullTreeData.value = [];
|
2025-08-15 00:22:06 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
state.masterData = masterData[0];
|
2025-09-04 18:42:45 +08:00
|
|
|
|
// 获取完整供应计划数据
|
2025-09-04 22:02:54 +08:00
|
|
|
|
const supplyPlanRes = await totalsupplyplan({ id: masterData[0].id, projectId: currentProject.value?.id });
|
2025-09-04 18:42:45 +08:00
|
|
|
|
const allData = supplyPlanRes.rows || [];
|
|
|
|
|
// 存储完整数据到本地
|
|
|
|
|
fullTreeData.value = [...allData];
|
|
|
|
|
// 初始只加载根节点(pid为空或0的节点)
|
|
|
|
|
const rootNodes = allData.filter((item) => !item.pid || item.pid == 0);
|
|
|
|
|
// 标记根节点是否有子节点
|
|
|
|
|
state.tableData = rootNodes.map((node) => ({
|
|
|
|
|
...node,
|
|
|
|
|
hasChildren: allData.some((child) => child.pid === node.sid)
|
|
|
|
|
}));
|
|
|
|
|
// 初始化可编辑数据映射
|
|
|
|
|
editDataMap.value.clear();
|
|
|
|
|
allData.forEach((item) => {
|
|
|
|
|
if (!item.hasChildren) {
|
|
|
|
|
// 只关注叶子节点
|
|
|
|
|
editDataMap.value.set(item.id, { ...item });
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-08-15 00:22:06 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
state.tableData = [];
|
2025-09-04 18:42:45 +08:00
|
|
|
|
fullTreeData.value = [];
|
2025-08-15 00:22:06 +08:00
|
|
|
|
} finally {
|
|
|
|
|
state.loading.list = false;
|
|
|
|
|
}
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取详情
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
async function totalSupplyplanDetail(id) {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
try {
|
|
|
|
|
const result = await totalSupplyplanDetails(id);
|
|
|
|
|
if (result?.code === 200) {
|
|
|
|
|
const detailData = result.data || {};
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
// 清空表单并赋值
|
2025-08-15 00:22:06 +08:00
|
|
|
|
Object.keys(formData).forEach((key) => {
|
|
|
|
|
formData[key] = undefined;
|
|
|
|
|
});
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
// 处理日期格式
|
2025-08-15 00:22:06 +08:00
|
|
|
|
const formatDate = (date) => {
|
|
|
|
|
if (!date) return '';
|
|
|
|
|
const d = typeof date === 'string' ? new Date(date) : date;
|
|
|
|
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
|
|
|
};
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
2025-08-15 00:22:06 +08:00
|
|
|
|
Object.assign(formData, {
|
|
|
|
|
...detailData,
|
|
|
|
|
compileDate: formatDate(detailData.compileDate),
|
|
|
|
|
dateService: formatDate(detailData.dateService)
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error(`获取详情失败: ${result?.msg || '未知错误'}`);
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
2025-08-15 00:22:06 +08:00
|
|
|
|
} catch (err) {
|
|
|
|
|
ElMessage.error(`接口请求失败: ${err.message}`);
|
|
|
|
|
console.error('详情接口错误:', err);
|
|
|
|
|
} finally {
|
|
|
|
|
state.loading.list = false;
|
|
|
|
|
}
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 一键保存修改
|
|
|
|
|
*/
|
2025-08-29 18:06:42 +08:00
|
|
|
|
const editApprovalSheet = async () => {
|
|
|
|
|
state.loading.list = true;
|
2025-09-04 18:42:45 +08:00
|
|
|
|
try {
|
|
|
|
|
// 只提交修改过的数据(从Map中获取)
|
|
|
|
|
const modifiedData = Array.from(editDataMap.value.values());
|
|
|
|
|
if (modifiedData.length === 0) {
|
|
|
|
|
ElMessage.info('没有数据需要修改');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-29 18:06:42 +08:00
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
await totalSupplyplanBatchEdit(modifiedData);
|
|
|
|
|
ElMessage.success('修改成功');
|
|
|
|
|
getMasterDataList(); // 重新加载数据
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error(`保存失败:${error.message}`);
|
|
|
|
|
} finally {
|
|
|
|
|
state.loading.list = false;
|
|
|
|
|
}
|
2025-08-29 18:06:42 +08:00
|
|
|
|
};
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 提交表单
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
const handleSubmit = async () => {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
try {
|
|
|
|
|
await formRef.value.validate();
|
2025-09-04 18:42:45 +08:00
|
|
|
|
await materialChangeSupplyplan(formData);
|
|
|
|
|
ElMessage.success('修改成功');
|
2025-08-15 00:22:06 +08:00
|
|
|
|
handleClose();
|
2025-09-04 18:42:45 +08:00
|
|
|
|
getMasterDataList();
|
2025-08-15 00:22:06 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('表单验证失败:', error);
|
|
|
|
|
}
|
2025-08-14 19:43:46 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
/**
|
|
|
|
|
* 导出数据
|
|
|
|
|
*/
|
2025-08-29 18:06:42 +08:00
|
|
|
|
const handleExport = async () => {
|
2025-09-04 18:42:45 +08:00
|
|
|
|
proxy?.download('/design/totalsupplyplan/export', { projectId: currentProject.value?.id }, `物资供应总计划.xlsx`, true);
|
2025-08-29 18:06:42 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
/**
|
|
|
|
|
* 关闭弹窗
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
const handleClose = () => {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
visible.value = false;
|
2025-09-04 18:42:45 +08:00
|
|
|
|
formRef.value?.resetFields();
|
2025-08-15 00:22:06 +08:00
|
|
|
|
Object.keys(formData).forEach((key) => {
|
|
|
|
|
formData[key] = undefined;
|
|
|
|
|
});
|
2025-08-14 19:43:46 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-09-04 18:42:45 +08:00
|
|
|
|
/**
|
|
|
|
|
* 审批
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
function clickApprovalSheet1() {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
proxy.$tab.closePage(proxy.$route);
|
|
|
|
|
proxy.$router.push({
|
2025-08-18 19:59:57 +08:00
|
|
|
|
path: `/approval/overallPlanMaterialSupply/indexEdit`,
|
2025-09-04 18:42:45 +08:00
|
|
|
|
query: { id: state.masterData.id, type: 'update' }
|
2025-08-15 00:22:06 +08:00
|
|
|
|
});
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 查看流程
|
|
|
|
|
*/
|
2025-08-14 19:43:46 +08:00
|
|
|
|
function lookApprovalFlow() {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
proxy.$router.push({
|
2025-08-18 19:59:57 +08:00
|
|
|
|
path: `/approval/overallPlanMaterialSupply/indexEdit`,
|
2025-09-04 18:42:45 +08:00
|
|
|
|
query: { id: state.masterData.id, type: 'view' }
|
2025-08-15 00:22:06 +08:00
|
|
|
|
});
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 监听项目变化
|
|
|
|
|
*/
|
|
|
|
|
const listeningProject = watch(
|
|
|
|
|
() => currentProject.value?.id,
|
|
|
|
|
(nid) => {
|
|
|
|
|
if (nid) getMasterDataList();
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 导入成功处理
|
|
|
|
|
const handleSuccess = () => {
|
|
|
|
|
ElMessage.success('导入成功');
|
2025-08-15 00:22:06 +08:00
|
|
|
|
getMasterDataList();
|
2025-09-04 18:42:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
if (currentProject.value?.id) {
|
|
|
|
|
getMasterDataList();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
listeningProject();
|
|
|
|
|
loadingInstance.value?.close();
|
2025-08-15 00:22:06 +08:00
|
|
|
|
});
|
2025-08-14 19:43:46 +08:00
|
|
|
|
</script>
|
2025-09-04 18:42:45 +08:00
|
|
|
|
|
2025-08-14 19:43:46 +08:00
|
|
|
|
<style>
|
|
|
|
|
.overall-plan-material-supply {
|
2025-08-15 00:22:06 +08:00
|
|
|
|
padding: 20px;
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-08-15 00:22:06 +08:00
|
|
|
|
.space-y-4 > .el-row {
|
|
|
|
|
margin-bottom: 16px;
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-08-15 00:22:06 +08:00
|
|
|
|
.space-y-4 > .el-row:last-child {
|
|
|
|
|
margin-bottom: 0;
|
2025-08-14 19:43:46 +08:00
|
|
|
|
}
|
|
|
|
|
</style>
|