add
This commit is contained in:
		| @ -5,7 +5,7 @@ VITE_APP_TITLE = 煤科建管平台 | ||||
| VITE_APP_ENV = 'development' | ||||
|  | ||||
| # 开发环境 | ||||
| VITE_APP_BASE_API = 'http://192.168.110.180:8899' | ||||
| VITE_APP_BASE_API = 'http://192.168.110.210:8899' | ||||
|  | ||||
| # 无人机接口地址 | ||||
|  | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| import { MasterVO, MasterForm, MasterQuery } from '@/api/patch/master/types'; | ||||
| import { MasterVO, MasterForm, MasterQuery } from '@/api/patch/types'; | ||||
|  | ||||
| /** | ||||
|  * 查询派单列表 | ||||
| @ -33,7 +33,7 @@ export const getMaster = (id: string | number): AxiosPromise<MasterVO> => { | ||||
|  */ | ||||
| export const addMaster = (data: MasterForm) => { | ||||
|   return request({ | ||||
|     url: '/patch/', | ||||
|     url: '/patch', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| @ -45,7 +45,7 @@ export const addMaster = (data: MasterForm) => { | ||||
|  */ | ||||
| export const updateMaster = (data: MasterForm) => { | ||||
|   return request({ | ||||
|     url: '/patch/', | ||||
|     url: '/patch', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| @ -61,3 +61,47 @@ export const delMaster = (id: string | number | Array<string | number>) => { | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 完成进度 | ||||
|  * @param masterId | ||||
|  */ | ||||
| export function getProgressDetail(masterId: string | number) { | ||||
|   return request({ | ||||
|     url: `/patch/getProgressList/${masterId}`, // 你的后端进度详情接口地址 | ||||
|     method: 'get' | ||||
|   }); | ||||
| } | ||||
|  | ||||
| // 弹窗新增进度 | ||||
| export const addProgress = (data) => { | ||||
|   return request({ | ||||
|     url: '/patch/progress', | ||||
|     method: 'post', | ||||
|     data | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| // 弹窗修改进度 | ||||
| export const editProgress = (data) => { | ||||
|   return request({ | ||||
|     url: '/patch/editProgress', | ||||
|     method: 'put', | ||||
|     data | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| // 删除进度 | ||||
| export const deleteProgress = (id) => { | ||||
|   return request({ | ||||
|     url: `/removeProgress/{id}`, | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export const getUserName = () => { | ||||
|   return request({ | ||||
|     url: `/patch/findThis`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| @ -116,6 +116,7 @@ import { listContactTypeformtemplate } from '@/api/cory/contactformtemplate'; | ||||
| import { addContactnotice, delContactnotice, listContactnotice } from '@/api/cory/contactnotice'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const { wf_business_status } = toRefs(proxy?.useDict('wf_business_status')); | ||||
| // 获取用户 store | ||||
| const userStore = useUserStoreHook(); | ||||
| // 从 store 中获取项目列表和当前选中的项目 | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <!-- 搜索区域 --> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form ref="queryFormRef" :model="queryParams" :inline="true"> | ||||
|             <el-form-item label="项目ID" prop="projectId"> | ||||
|               <el-input v-model="queryParams.projectId" placeholder="请输入项目ID" clearable @keyup.enter="handleQuery" /> | ||||
|               <el-input v-model="queryParams.projectId" placeholder="请输入项目ID" clearable @keyup.enter="handleQuery" v-if="false" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="任务名称" prop="taskName"> | ||||
|               <el-input v-model="queryParams.taskName" placeholder="请输入任务名称" clearable @keyup.enter="handleQuery" /> | ||||
| @ -31,6 +32,7 @@ | ||||
|       </div> | ||||
|     </transition> | ||||
|  | ||||
|     <!-- 任务列表卡片 --> | ||||
|     <el-card shadow="never"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
| @ -52,10 +54,9 @@ | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="masterList" @selection-change="handleSelectionChange"> | ||||
|       <!-- 任务列表表格 --> | ||||
|       <el-table v-loading="loading" :data="masterList" @selection-change="handleSelectionChange" border> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column label="主键ID" align="center" prop="id" v-if="true" /> | ||||
|         <el-table-column label="项目ID" align="center" prop="projectId" /> | ||||
|         <el-table-column label="任务名称" align="center" prop="taskName" /> | ||||
|         <el-table-column label="任务描述" align="center" prop="describe" /> | ||||
|         <el-table-column label="计划完成时间" align="center" prop="pcd" width="180"> | ||||
| @ -68,8 +69,25 @@ | ||||
|             <span>{{ parseTime(scope.row.act, '{y}-{m}-{d}') }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="完成进度" align="center" prop="completionProgress" /> | ||||
|         <el-table-column label="任务状态" align="center" prop="taskStatus" /> | ||||
|         <!-- 完成进度列(点击打开进度详情) --> | ||||
|         <el-table-column prop="completionProgress" label="完成进度" align="center"> | ||||
|           <template #default="scope"> | ||||
|             <el-button type="text" @click="showProgressDetail(scope.row.id)" class="text-primary"> | ||||
|               {{ scope.row.completionProgress || '未设置' }} | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="任务状态" align="center" prop="taskStatus"> | ||||
|           <template #default="scope"> | ||||
|             <span | ||||
|               :class="[Number(scope.row.taskStatus) === 0 ? 'text-warning' : Number(scope.row.taskStatus) === 1 ? 'text-success' : 'text-danger']" | ||||
|             > | ||||
|               {{ | ||||
|                 Number(scope.row.taskStatus) === 0 ? '未完成' : Number(scope.row.taskStatus) === 1 ? '已完成' : `未知状态(${scope.row.taskStatus})` | ||||
|               }} | ||||
|             </span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="备注" align="center" prop="remark" /> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
| @ -83,33 +101,106 @@ | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|  | ||||
|       <!-- 进度详情弹窗 --> | ||||
|       <el-dialog :title="`进度详情(当前总进度:${currentTotalProgress}%)`" v-model="progressDialogVisible" width="1000px" destroy-on-close> | ||||
|         <div class="mb-4"> | ||||
|           <el-button type="primary" plain icon="Plus" size="small" @click="handleProgressAdd()" v-hasPermi="['patch:progress:add']"> | ||||
|             新增进度 | ||||
|           </el-button> | ||||
|         </div> | ||||
|         <el-table v-loading="progressLoading" :data="progressList" border empty-text="暂无进度数据" style="width: 100%"> | ||||
|           <el-table-column prop="slaveId" label="执行人ID" align="center" width="120" /> | ||||
|           <el-table-column prop="slaveName" label="执行人姓名" align="center" width="150" /> | ||||
|           <el-table-column prop="progress" label="进度" align="center" width="120" /> | ||||
|           <el-table-column prop="remark" label="备注" align="center" /> | ||||
|           <el-table-column prop="updateTime" label="更新时间" align="center" width="200"> | ||||
|             <template #default="scope"> | ||||
|               <span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="140"> | ||||
|             <template #default="scope"> | ||||
|               <el-tooltip content="修改进度" placement="top"> | ||||
|                 <el-button | ||||
|                   link | ||||
|                   type="primary" | ||||
|                   icon="Edit" | ||||
|                   size="small" | ||||
|                   @click="handleProgressUpdate(scope.row)" | ||||
|                   v-hasPermi="['patch:progress:edit']" | ||||
|                 ></el-button> | ||||
|               </el-tooltip> | ||||
|               <el-tooltip content="删除进度" placement="top"> | ||||
|                 <el-button | ||||
|                   link | ||||
|                   type="primary" | ||||
|                   icon="Delete" | ||||
|                   size="small" | ||||
|                   @click="handleProgressDelete(scope.row)" | ||||
|                   v-hasPermi="['patch:progress:remove']" | ||||
|                 ></el-button> | ||||
|               </el-tooltip> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </el-table> | ||||
|       </el-dialog> | ||||
|  | ||||
|       <!-- 新增/修改进度弹窗 --> | ||||
|       <el-dialog :title="progressDialog.title" v-model="progressDialog.visible" width="500px" append-to-body destroy-on-close> | ||||
|         <el-form ref="progressFormRef" :model="progressForm" :rules="progressRules" label-width="120px"> | ||||
|           <el-input v-model="progressForm.ordersId" placeholder="关联的任务ID" readonly style="color: #666; background: #f5f7fa" type="hidden" /> | ||||
|           <el-input v-model="progressForm.projectId" type="hidden" /> | ||||
|           <!-- 修改执行人姓名选择框 --> | ||||
|           <el-form-item label="执行人姓名" prop="slaveName"> | ||||
|             <el-select v-model="progressForm.slaveName" placeholder="请选择执行人姓名" clearable style="width: 100%" @change="handleSlaveChange"> | ||||
|               <el-option v-for="item in slaveOptions" :key="item.id" :label="item.name" :value="item.name" :data-id="item.id"></el-option> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-input v-model="progressForm.slaveId" placeholder="请输入执行人ID" v-if="false" /> | ||||
|  | ||||
|           <el-form-item label="进度" prop="progress"> | ||||
|             <el-input v-model="progressForm.progress" placeholder="请输入进度(0-100之间的数字)" type="number" @input="handleProgressInput" /> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="备注" prop="remark"> | ||||
|             <el-input v-model="progressForm.remark" type="textarea" placeholder="请输入备注" rows="3" /> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|         <template #footer> | ||||
|           <div class="dialog-footer"> | ||||
|             <el-button :loading="progressBtnLoading" type="primary" @click="submitProgressForm">确 定</el-button> | ||||
|             <el-button @click="cancelProgressForm">取 消</el-button> | ||||
|           </div> | ||||
|         </template> | ||||
|       </el-dialog> | ||||
|  | ||||
|       <!-- 分页组件 --> | ||||
|       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> | ||||
|     </el-card> | ||||
|     <!-- 添加或修改派单对话框 --> | ||||
|     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> | ||||
|       <el-form ref="masterFormRef" :model="form" :rules="rules" label-width="80px"> | ||||
|  | ||||
|     <!-- 新增/修改任务弹窗 --> | ||||
|     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body destroy-on-close> | ||||
|       <el-form ref="masterFormRef" :model="form" :rules="rules" label-width="100px"> | ||||
|         <el-form-item label="项目ID" prop="projectId"> | ||||
|           <el-input v-model="form.projectId" placeholder="请输入项目ID" /> | ||||
|           <el-input v-model="form.projectId" placeholder="请输入项目ID" :readonly="!!currentProjectId" :disabled="!!currentProjectId" /> | ||||
|           <template #help> | ||||
|             <span v-if="currentProjectId" class="text-success">已自动关联当前选中项目</span> | ||||
|           </template> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="任务名称" prop="taskName"> | ||||
|           <el-input v-model="form.taskName" placeholder="请输入任务名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="任务描述" prop="describe"> | ||||
|           <el-input v-model="form.describe" placeholder="请输入任务描述" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="计划完成时间" prop="pcd"> | ||||
|           <el-date-picker clearable v-model="form.pcd" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择计划完成时间"> | ||||
|           </el-date-picker> | ||||
|           <el-date-picker clearable v-model="form.pcd" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择计划完成时间" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="实际完成时间" prop="act"> | ||||
|           <el-date-picker clearable v-model="form.act" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择实际完成时间"> | ||||
|           </el-date-picker> | ||||
|           <el-date-picker clearable v-model="form.act" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择实际完成时间" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="完成进度" prop="completionProgress"> | ||||
|           <el-input v-model="form.completionProgress" placeholder="请输入完成进度" /> | ||||
|         <el-form-item label="任务描述" prop="describe"> | ||||
|           <el-input v-model="form.describe" type="textarea" placeholder="请输入任务描述" rows="3" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="备注" prop="remark"> | ||||
|           <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> | ||||
|           <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" rows="3" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
| @ -123,11 +214,123 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup name="Master" lang="ts"> | ||||
| import { listMaster, getMaster, delMaster, addMaster, updateMaster } from '@/api/patch'; | ||||
| // 1. 导入接口 | ||||
| import { | ||||
|   listMaster, | ||||
|   getMaster, | ||||
|   delMaster, | ||||
|   addMaster, | ||||
|   updateMaster, | ||||
|   getProgressDetail, | ||||
|   addProgress, | ||||
|   editProgress, | ||||
|   deleteProgress, | ||||
|   getUserName | ||||
| } from '@/api/patch'; | ||||
| import { MasterVO, MasterQuery, MasterForm } from '@/api/patch/types'; | ||||
|  | ||||
| // 2. 导入Vue核心依赖 | ||||
| import { getCurrentInstance, ComponentInternalInstance, onMounted, ref, reactive, toRefs, nextTick, computed, watch } from 'vue'; | ||||
| import type { ElFormInstance } from 'element-plus'; | ||||
|  | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
| // 获取用户 store | ||||
|  | ||||
| const userStore = useUserStoreHook(); | ||||
| // 从 store 中获取当前选中的项目ID | ||||
| const currentProject = computed(() => userStore.selectedProject); | ||||
| const currentProjectId = computed(() => currentProject.value?.id); | ||||
| // 1. 调整类型定义,匹配接口返回的字段 | ||||
| const slaveOptions = ref<Array<{ id: number; name: string }>>([]); | ||||
| // 在脚本中添加选择变化的处理函数 | ||||
| const handleSlaveChange = (name) => { | ||||
|   // 找到选中的用户对象 | ||||
|   const selectedUser = slaveOptions.value.find((item) => item.name === name); | ||||
|   if (selectedUser) { | ||||
|     // 自动填充userId到slaveId | ||||
|     progressForm.slaveId = selectedUser.id; | ||||
|   } else { | ||||
|     // 未选中时清空ID | ||||
|     progressForm.slaveId = ''; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| async function initSlaveOptions() { | ||||
|   try { | ||||
|     const response = await getUserName(); | ||||
|     // 确保获取到正确的数组数据(接口返回在data字段中) | ||||
|     const userDataList = Array.isArray(response?.data) ? response.data : []; | ||||
|  | ||||
|     // 转换数据结构,只提取需要的字段(userId作为id,nickName作为name) | ||||
|     slaveOptions.value = userDataList | ||||
|       .filter((item) => item?.userId && item?.nickName) // 过滤有效数据 | ||||
|       .map((item) => ({ | ||||
|         id: item.userId, // 使用userId作为选项的id | ||||
|         name: item.nickName // 使用nickName作为显示名称 | ||||
|       })); | ||||
|  | ||||
|     console.log('slaveOptions 已更新:', slaveOptions.value); | ||||
|   } catch (error) { | ||||
|     console.error('获取用户数据失败:', error); | ||||
|     slaveOptions.value = []; // 错误时重置为空数组 | ||||
|   } | ||||
| } | ||||
| initSlaveOptions(); | ||||
| // 3. 类型声明 | ||||
| interface DialogOption { | ||||
|   visible: boolean; | ||||
|   title: string; | ||||
| } | ||||
| interface PageData<F, Q> { | ||||
|   form: F; | ||||
|   queryParams: Q; | ||||
|   rules: Record<string, any[]>; | ||||
| } | ||||
| interface ProgressDetail { | ||||
|   id?: string | number; | ||||
|   ordersId: string | number; | ||||
|   slaveId: string | number; | ||||
|   slaveName: string; | ||||
|   progress: string; | ||||
|   remark?: string; | ||||
|   updateTime?: string; | ||||
|   projectId?: string | number; | ||||
| } | ||||
| interface ProgressForm extends Omit<ProgressDetail, 'updateTime'> {} | ||||
|  | ||||
| // 4. 获取组件实例 | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| // 5. 环境变量获取 | ||||
| const isDev = import.meta.env.MODE === 'development'; | ||||
|  | ||||
| // 6. 状态管理 | ||||
| const progressDialogVisible = ref(false); | ||||
| const progressList = ref<ProgressDetail[]>([]); | ||||
| const progressLoading = ref(false); | ||||
| const currentMasterId = ref<string | number>(''); | ||||
| const currentTotalProgress = ref<number>(0); // 当前任务的所有执行人进度总和 | ||||
|  | ||||
| const progressDialog = reactive<DialogOption>({ visible: false, title: '' }); | ||||
| const progressFormRef = ref<ElFormInstance>(); | ||||
| const progressForm = reactive<ProgressForm>({ | ||||
|   projectId: currentProjectId.value, | ||||
|   id: undefined, | ||||
|   ordersId: '', | ||||
|   slaveId: '', | ||||
|   slaveName: '', | ||||
|   progress: '', | ||||
|   remark: '' | ||||
| }); | ||||
| const progressBtnLoading = ref(false); | ||||
|  | ||||
| const progressRules = reactive<Record<string, any[]>>({ | ||||
|   ordersId: [{ required: true, message: '关联任务ID不能为空', trigger: 'blur' }], | ||||
|   slaveId: [{ required: true, message: '请输入执行人ID', trigger: 'blur' }], | ||||
|   slaveName: [{ required: true, message: '请输入执行人姓名', trigger: 'blur' }], | ||||
|   progress: [{ required: true, message: '请输入进度', trigger: 'blur' }] | ||||
| }); | ||||
|  | ||||
| const masterList = ref<MasterVO[]>([]); | ||||
| const buttonLoading = ref(false); | ||||
| const loading = ref(true); | ||||
| @ -139,15 +342,11 @@ const total = ref(0); | ||||
|  | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const masterFormRef = ref<ElFormInstance>(); | ||||
|  | ||||
| const dialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '' | ||||
| }); | ||||
| const dialog = reactive<DialogOption>({ visible: false, title: '' }); | ||||
|  | ||||
| const initFormData: MasterForm = { | ||||
|   id: undefined, | ||||
|   projectId: undefined, | ||||
|   projectId: currentProjectId.value, | ||||
|   taskName: undefined, | ||||
|   describe: undefined, | ||||
|   pcd: undefined, | ||||
| @ -156,12 +355,13 @@ const initFormData: MasterForm = { | ||||
|   taskStatus: undefined, | ||||
|   remark: undefined | ||||
| }; | ||||
|  | ||||
| const data = reactive<PageData<MasterForm, MasterQuery>>({ | ||||
|   form: { ...initFormData }, | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     projectId: undefined, | ||||
|     projectId: currentProjectId.value, // 默认查询当前项目的任务 | ||||
|     taskName: undefined, | ||||
|     describe: undefined, | ||||
|     pcd: undefined, | ||||
| @ -171,107 +371,332 @@ const data = reactive<PageData<MasterForm, MasterQuery>>({ | ||||
|     params: {} | ||||
|   }, | ||||
|   rules: { | ||||
|     id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }] | ||||
|     projectId: [{ required: true, message: '请输入项目ID', trigger: 'blur' }], | ||||
|     taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], | ||||
|     completionProgress: [{ required: true, message: '请输入完成进度', trigger: 'blur' }] | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| /** 查询派单列表 */ | ||||
| // 监听当前项目ID变化,自动更新相关数据 | ||||
| watch(currentProjectId, (newVal) => { | ||||
|   // 更新查询参数中的项目ID | ||||
|   queryParams.value.projectId = newVal; | ||||
|  | ||||
|   // 更新表单中的项目ID(如果是新增状态) | ||||
|   if (!form.value.id) { | ||||
|     form.value.projectId = newVal; | ||||
|   } | ||||
|  | ||||
|   // 更新进度表单中的项目ID | ||||
|   progressForm.projectId = newVal; | ||||
|  | ||||
|   // 重新加载任务列表 | ||||
|   getList(); | ||||
| }); | ||||
|  | ||||
| // 7. 核心方法 | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const res = await listMaster(queryParams.value); | ||||
|   masterList.value = res.rows; | ||||
|   total.value = res.total; | ||||
|   loading.value = false; | ||||
|   try { | ||||
|     const res = await listMaster(queryParams.value); | ||||
|     masterList.value = res.rows || []; | ||||
|     total.value = res.total || 0; | ||||
|   } catch (error) { | ||||
|     console.error('获取任务列表失败', error); | ||||
|     proxy?.$modal.msgError('获取任务列表失败'); | ||||
|     masterList.value = []; | ||||
|     total.value = 0; | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const showProgressDetail = async (masterId: string | number) => { | ||||
|   if (!masterId || (typeof masterId === 'string' && masterId.trim() === '')) { | ||||
|     proxy?.$modal.msgError('无效的任务ID,无法加载进度详情'); | ||||
|     return; | ||||
|   } | ||||
|   currentMasterId.value = masterId; | ||||
|  | ||||
|   progressDialogVisible.value = true; | ||||
|   progressLoading.value = true; | ||||
|   progressList.value = []; | ||||
|   currentTotalProgress.value = 0; // 重置总和 | ||||
|  | ||||
|   try { | ||||
|     const res = await getProgressDetail(masterId); | ||||
|     progressList.value = res.data || []; | ||||
|     // 计算所有执行人的进度总和 | ||||
|     currentTotalProgress.value = progressList.value.reduce((total, item) => { | ||||
|       const progressNum = Number(item.progress) || 0; | ||||
|       return total + progressNum; | ||||
|     }, 0); | ||||
|   } catch (error) { | ||||
|     console.error('获取进度详情失败', error); | ||||
|     proxy?.$modal.msgError('获取进度详情失败'); | ||||
|   } finally { | ||||
|     progressLoading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const resetProgressForm = () => { | ||||
|   progressForm.id = undefined; | ||||
|   progressForm.slaveId = ''; | ||||
|   progressForm.slaveName = ''; | ||||
|   progressForm.progress = ''; | ||||
|   progressForm.remark = ''; | ||||
|   progressForm.projectId = currentProjectId.value; // 重置时关联当前项目 | ||||
|  | ||||
|   progressFormRef.value?.resetFields(); | ||||
|  | ||||
|   nextTick(() => { | ||||
|     progressForm.ordersId = currentMasterId.value; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const handleProgressAdd = () => { | ||||
|   if (!currentMasterId.value) { | ||||
|     proxy?.$modal.msgError('请先从任务列表打开「进度详情」,再新增进度'); | ||||
|     return; | ||||
|   } | ||||
|   resetProgressForm(); | ||||
|   progressDialog.visible = true; | ||||
|   progressDialog.title = '新增进度'; | ||||
| }; | ||||
|  | ||||
| const handleProgressUpdate = (row: ProgressDetail) => { | ||||
|   progressForm.id = row.id; | ||||
|   progressForm.ordersId = row.ordersId; | ||||
|   progressForm.slaveId = row.slaveId; | ||||
|   progressForm.slaveName = row.slaveName; | ||||
|   progressForm.progress = row.progress; | ||||
|   progressForm.remark = row.remark || ''; | ||||
|   progressForm.projectId = row.projectId || currentProjectId.value; // 保持项目ID一致 | ||||
|   progressDialog.visible = true; | ||||
|   progressDialog.title = '修改进度'; | ||||
| }; | ||||
|  | ||||
| const submitProgressForm = () => { | ||||
|   progressFormRef.value?.validate(async (valid: boolean) => { | ||||
|     if (!valid) return; | ||||
|  | ||||
|     if (!progressForm.ordersId) { | ||||
|       proxy?.$modal.msgError('关联任务ID丢失,请关闭弹窗重新打开进度详情'); | ||||
|       progressBtnLoading.value = false; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     // 确保进度总和不超过100 | ||||
|     const newProgress = Number(progressForm.progress) || 0; | ||||
|     let expectedTotal = 0; | ||||
|  | ||||
|     if (progressForm.id) { | ||||
|       // 编辑场景:总和 = 当前总和 - 旧进度 + 新进度 | ||||
|       const oldProgressItem = progressList.value.find((item) => item.id === progressForm.id); | ||||
|       const oldProgress = oldProgressItem ? Number(oldProgressItem.progress) || 0 : 0; | ||||
|       expectedTotal = currentTotalProgress.value - oldProgress + newProgress; | ||||
|     } else { | ||||
|       // 新增场景:总和 = 当前总和 + 新进度 | ||||
|       expectedTotal = currentTotalProgress.value + newProgress; | ||||
|     } | ||||
|  | ||||
|     if (expectedTotal > 100) { | ||||
|       proxy?.$modal.msgError(`进度总和不能超过100%,当前预计总和为${expectedTotal}%`); | ||||
|       progressBtnLoading.value = false; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     progressBtnLoading.value = true; | ||||
|     try { | ||||
|       if (progressForm.id) { | ||||
|         await editProgress(progressForm); | ||||
|         proxy?.$modal.msgSuccess('修改进度成功'); | ||||
|       } else { | ||||
|         await addProgress(progressForm); | ||||
|         proxy?.$modal.msgSuccess('新增进度成功'); | ||||
|       } | ||||
|       progressDialog.visible = false; | ||||
|       await showProgressDetail(currentMasterId.value); // 刷新进度列表 | ||||
|       getList(); // 同步刷新任务列表 | ||||
|     } catch (error) { | ||||
|       console.error(`${progressForm.id ? '修改' : '新增'}进度失败`, error); | ||||
|       proxy?.$modal.msgError(`${progressForm.id ? '修改' : '新增'}进度失败`); | ||||
|     } finally { | ||||
|       progressBtnLoading.value = false; | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const cancelProgressForm = () => { | ||||
|   progressDialog.visible = false; | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| const handleProgressDelete = async (row: ProgressDetail) => { | ||||
|   if (!row.id) return; | ||||
|  | ||||
|   try { | ||||
|     await proxy?.$modal.confirm(`是否确认删除该进度记录?`); | ||||
|     await deleteProgress(row.id); | ||||
|     proxy?.$modal.msgSuccess('删除进度成功'); | ||||
|     await showProgressDetail(currentMasterId.value); | ||||
|     getList(); | ||||
|   } catch (error) { | ||||
|     console.error('删除进度失败', error); | ||||
|     if (error !== 'cancel') { | ||||
|       proxy?.$modal.msgError('删除进度失败'); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 取消按钮 */ | ||||
| const cancel = () => { | ||||
|   reset(); | ||||
|   form.value = { ...initFormData, projectId: currentProjectId.value }; | ||||
|   masterFormRef.value?.resetFields(); | ||||
|   dialog.visible = false; | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| /** 表单重置 */ | ||||
| const reset = () => { | ||||
|   form.value = { ...initFormData }; | ||||
|   form.value = { ...initFormData, projectId: currentProjectId.value }; | ||||
|   masterFormRef.value?.resetFields(); | ||||
| }; | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   // 重置查询时保留当前项目ID | ||||
|   queryParams.value.projectId = currentProjectId.value; | ||||
|   handleQuery(); | ||||
| }; | ||||
|  | ||||
| /** 多选框选中数据 */ | ||||
| const handleSelectionChange = (selection: MasterVO[]) => { | ||||
|   ids.value = selection.map((item) => item.id); | ||||
|   single.value = selection.length != 1; | ||||
|   multiple.value = !selection.length; | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = selection.length === 0; | ||||
| }; | ||||
|  | ||||
| /** 新增按钮操作 */ | ||||
| const handleAdd = () => { | ||||
|   reset(); | ||||
|   // 新增任务时自动填充当前项目ID | ||||
|   form.value.projectId = currentProjectId.value; | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '添加派单'; | ||||
| }; | ||||
|  | ||||
| /** 修改按钮操作 */ | ||||
| const handleUpdate = async (row?: MasterVO) => { | ||||
|   reset(); | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   const res = await getMaster(_id); | ||||
|   Object.assign(form.value, res.data); | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '修改派单'; | ||||
|   if (!_id) { | ||||
|     proxy?.$modal.msgWarning('请选择需要修改的任务'); | ||||
|     return; | ||||
|   } | ||||
|   try { | ||||
|     const res = await getMaster(_id); | ||||
|     Object.assign(form.value, res.data); | ||||
|     dialog.visible = true; | ||||
|     dialog.title = '修改派单'; | ||||
|   } catch (error) { | ||||
|     console.error('获取任务详情失败', error); | ||||
|     proxy?.$modal.msgError('获取任务详情失败'); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| const submitForm = () => { | ||||
|   masterFormRef.value?.validate(async (valid: boolean) => { | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       if (form.value.id) { | ||||
|         await updateMaster(form.value).finally(() => (buttonLoading.value = false)); | ||||
|       } else { | ||||
|         await addMaster(form.value).finally(() => (buttonLoading.value = false)); | ||||
|     if (!valid) return; | ||||
|     buttonLoading.value = true; | ||||
|     try { | ||||
|       // 确保提交时使用当前项目ID | ||||
|       if (!form.value.id && currentProjectId.value) { | ||||
|         form.value.projectId = currentProjectId.value; | ||||
|       } | ||||
|       proxy?.$modal.msgSuccess('操作成功'); | ||||
|  | ||||
|       if (form.value.id) await updateMaster(form.value); | ||||
|       else await addMaster(form.value); | ||||
|       proxy?.$modal.msgSuccess(`${form.value.id ? '修改' : '新增'}成功`); | ||||
|       dialog.visible = false; | ||||
|       await getList(); | ||||
|     } catch (error) { | ||||
|       console.error(`${form.value.id ? '修改' : '新增'}任务失败`, error); | ||||
|       proxy?.$modal.msgError(`${form.value.id ? '修改' : '新增'}任务失败`); | ||||
|     } finally { | ||||
|       buttonLoading.value = false; | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row?: MasterVO) => { | ||||
|   const _ids = row?.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除派单编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false)); | ||||
|   await delMaster(_ids); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
|   await getList(); | ||||
|   if (!_ids || (_ids instanceof Array && _ids.length === 0)) { | ||||
|     proxy?.$modal.msgWarning('请选择需要删除的任务'); | ||||
|     return; | ||||
|   } | ||||
|   try { | ||||
|     await proxy?.$modal.confirm(`是否确认删除选中的${row ? '任务' : '任务们'}?`); | ||||
|     await delMaster(_ids); | ||||
|     proxy?.$modal.msgSuccess('删除成功'); | ||||
|     await getList(); | ||||
|   } catch (error) { | ||||
|     console.error('删除任务失败', error); | ||||
|     if (error !== 'cancel') proxy?.$modal.msgError('删除任务失败'); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const handleProgressInput = () => { | ||||
|   let value = progressForm.progress; | ||||
|  | ||||
|   // 清除非数字字符(保留小数点) | ||||
|   if (typeof value === 'string') { | ||||
|     value = value.replace(/[^\d.]/g, ''); | ||||
|     // 确保只有一个小数点 | ||||
|     const dotIndex = value.indexOf('.'); | ||||
|     if (dotIndex !== -1) { | ||||
|       value = value.slice(0, dotIndex + 1) + value.slice(dotIndex + 1).replace(/\./g, ''); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // 转换为数字处理 | ||||
|   let num = Number(value); | ||||
|  | ||||
|   // 限制范围在0-100 | ||||
|   if (num < 0) num = 0; | ||||
|   if (num > 100) num = 100; | ||||
|  | ||||
|   // 处理空值情况 | ||||
|   if (value === '' || isNaN(num)) { | ||||
|     progressForm.progress = ''; | ||||
|   } else { | ||||
|     progressForm.progress = num.toString(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 导出按钮操作 */ | ||||
| const handleExport = () => { | ||||
|   proxy?.download( | ||||
|     'patch/patch/export', | ||||
|     { | ||||
|       ...queryParams.value | ||||
|     }, | ||||
|     `master_${new Date().getTime()}.xlsx` | ||||
|   ); | ||||
|   proxy?.download('patch/patch/export', { ...queryParams.value }, `任务列表_${new Date().getTime()}.xlsx`); | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .mb-4 { | ||||
|   margin-bottom: 16px; | ||||
| } | ||||
| .el-table .small-padding .cell { | ||||
|   padding: 0 5px; | ||||
| } | ||||
| .el-table .fixed-width { | ||||
|   width: 120px !important; | ||||
| } | ||||
| .el-table-column .el-button--text + .el-button--text { | ||||
|   margin-left: 10px; | ||||
| } | ||||
| </style> | ||||
|  | ||||
| @ -212,6 +212,7 @@ type ProgressCategoryOption = { | ||||
|   name: string; | ||||
|   children?: ProgressCategoryOption[]; | ||||
| }; | ||||
|  | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
| // 获取用户 store | ||||
| const userStore = useUserStoreHook(); | ||||
|  | ||||
| @ -4,28 +4,32 @@ | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form ref="queryFormRef" :model="queryParams" :inline="true"> | ||||
|             <el-form-item label="分包名称" prop="subpackageName"> | ||||
|               <el-input v-model="queryParams.subpackageName" placeholder="请输入分包名称" clearable @keyup.enter="handleQuery" /> | ||||
|             <el-form-item label="分包类型名称" prop="dictName"> | ||||
|               <el-input v-model="queryParams.dictName" placeholder="请输入分包类型名称" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="分包内容" prop="subpackageContext"> | ||||
|               <el-input v-model="queryParams.subpackageContext" placeholder="请输入分包内容" clearable @keyup.enter="handleQuery" /> | ||||
|             <el-form-item label="名称" prop="name"> | ||||
|               <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="限价" prop="limitPrice"> | ||||
|               <el-input v-model="queryParams.limitPrice" placeholder="请输入限价" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="计划招标时间" prop="planTenderTime"> | ||||
|               <el-date-picker clearable | ||||
|                 v-model="queryParams.planTenderTime" | ||||
|             <el-form-item label="计划招标时间" prop="plannedBiddingTime"> | ||||
|               <el-date-picker | ||||
|                 clearable | ||||
|                 v-model="queryParams.plannedBiddingTime" | ||||
|                 type="date" | ||||
|                 value-format="YYYY-MM-DD" | ||||
|                 placeholder="请选择计划招标时间" | ||||
|               /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="招标方式" prop="tenderMethod"> | ||||
|               <el-input v-model="queryParams.tenderMethod" placeholder="请输入招标方式" clearable @keyup.enter="handleQuery" /> | ||||
|             <el-form-item label="招标方式(公招,邀标)" prop="plannedBiddingMethod"> | ||||
|               <el-input v-model="queryParams.plannedBiddingMethod" placeholder="请输入招标方式(公招,邀标)" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="合同额" prop="contract"> | ||||
|               <el-input v-model="queryParams.contract" placeholder="请输入合同额" clearable @keyup.enter="handleQuery" /> | ||||
|             <el-form-item label="总价" prop="price"> | ||||
|               <el-input v-model="queryParams.price" placeholder="请输入总价" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="限价" prop="limitPrice"> | ||||
|               <el-input v-model="queryParams.limitPrice" placeholder="请输入限价" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="合同额" prop="contractPrice"> | ||||
|               <el-input v-model="queryParams.contractPrice" placeholder="请输入合同额" clearable @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
| @ -39,15 +43,9 @@ | ||||
|     <el-card shadow="never"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['plan:plan:add']">新增</el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['plan:plan:edit']">修改</el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['plan:plan:remove']">删除</el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['plan:plan:export']">导出</el-button> | ||||
|           </el-col> | ||||
| @ -57,28 +55,26 @@ | ||||
|  | ||||
|       <el-table v-loading="loading" :data="planList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column label="招标计划ID" align="center" prop="id" v-if="true" /> | ||||
|         <el-table-column label="分包类型" align="center" prop="subpackageType" /> | ||||
|         <el-table-column label="分包名称" align="center" prop="subpackageName" /> | ||||
|         <el-table-column label="分包内容" align="center" prop="subpackageContext" /> | ||||
|         <el-table-column label="限价" align="center" prop="limitPrice" /> | ||||
|         <el-table-column label="计划招标时间" align="center" prop="planTenderTime" width="180"> | ||||
|         <el-table-column label="主键ID" align="center" prop="id" v-if="false" /> | ||||
|         <el-table-column label="项目Id" align="center" prop="projectId" v-if="false" /> | ||||
|         <el-table-column label="分包类型名称" align="center" prop="dictName" /> | ||||
|         <el-table-column label="名称" align="center" prop="name" /> | ||||
|         <el-table-column label="计划招标时间" align="center" prop="plannedBiddingTime" width="180" v-if="false"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ parseTime(scope.row.planTenderTime, '{y}-{m}-{d}') }}</span> | ||||
|             <span>{{ parseTime(scope.row.plannedBiddingTime, '{y}-{m}-{d}') }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="招标方式" align="center" prop="tenderMethod" /> | ||||
|         <el-table-column label="招标文件(多个)" align="center" prop="tenderFile" /> | ||||
|         <el-table-column label="中标文件(单个)" align="center" prop="bidFile" /> | ||||
|         <el-table-column label="合同额" align="center" prop="contract" /> | ||||
|         <el-table-column label="招标方式(公招,邀标)" align="center" prop="plannedBiddingMethod" /> | ||||
|         <el-table-column label="总价" align="center" prop="price" v-if="false" /> | ||||
|         <el-table-column label="限价" align="center" prop="limitPrice" /> | ||||
|         <el-table-column label="合同额" align="center" prop="contractPrice" /> | ||||
|         <el-table-column label="分包内容" align="center" prop="content" /> | ||||
|         <el-table-column label="中标通知书" align="center" prop="bidFile" /> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-tooltip content="修改" placement="top"> | ||||
|               <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['plan:plan:edit']"></el-button> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip content="删除" placement="top"> | ||||
|               <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['plan:plan:remove']"></el-button> | ||||
|             </el-tooltip> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
| @ -87,35 +83,47 @@ | ||||
|     </el-card> | ||||
|     <!-- 添加或修改招标计划对话框 --> | ||||
|     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> | ||||
|       <el-form ref="planFormRef" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="分包名称" prop="subpackageName"> | ||||
|           <el-input v-model="form.subpackageName" placeholder="请输入分包名称" /> | ||||
|       <el-form ref="planFormRef" :model="form" :rules="rules" label-width="120px"> | ||||
|         <!-- 调整项目ID表单项:与目标代码一致,自动关联当前项目并显示提示 --> | ||||
|         <el-input v-model="form.projectId" placeholder="请输入项目ID" :readonly="!!currentProjectId" :disabled="!!currentProjectId" v-if="false" /> | ||||
|         <template #help> | ||||
|           <span v-if="currentProjectId" class="text-success">已自动关联当前选中项目</span> | ||||
|         </template> | ||||
|         <el-input v-model="form.id" placeholder="ID" readonly v-if="false" /> | ||||
|         <el-form-item label="分包类型名称" prop="dictName" v-if="false"> | ||||
|           <el-input v-model="form.dictName" placeholder="请输入分包类型名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="分包内容" prop="subpackageContext"> | ||||
|           <el-input v-model="form.subpackageContext" placeholder="请输入分包内容" /> | ||||
|  | ||||
|         <el-form-item label="名称" prop="name"> | ||||
|           <el-input v-model="form.name" placeholder="请输入名称" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="计划招标时间" prop="plannedBiddingTime" v-if="false"> | ||||
|           <el-date-picker clearable v-model="form.plannedBiddingTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择计划招标时间" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="招标方式(公招,邀标)" prop="plannedBiddingMethod"> | ||||
|           <el-input v-model="form.plannedBiddingMethod" placeholder="请输入招标方式(公招,邀标)" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="总价" prop="price" v-if="false"> | ||||
|           <el-input v-model="form.price" placeholder="请输入总价" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="限价" prop="limitPrice"> | ||||
|           <el-input v-model="form.limitPrice" placeholder="请输入限价" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="计划招标时间" prop="planTenderTime"> | ||||
|           <el-date-picker clearable | ||||
|             v-model="form.planTenderTime" | ||||
|             type="datetime" | ||||
|             value-format="YYYY-MM-DD HH:mm:ss" | ||||
|             placeholder="请选择计划招标时间"> | ||||
|           </el-date-picker> | ||||
|  | ||||
|         <el-form-item label="合同额" prop="contractPrice"> | ||||
|           <el-input v-model="form.contractPrice" placeholder="请输入合同额" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="招标方式" prop="tenderMethod"> | ||||
|           <el-input v-model="form.tenderMethod" placeholder="请输入招标方式" /> | ||||
|  | ||||
|         <el-form-item label="分包内容" prop="content"> | ||||
|           <el-input v-model="form.content" type="textarea" placeholder="请输入分包内容" rows="3" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="招标文件(多个)" prop="tenderFile"> | ||||
|           <file-upload v-model="form.tenderFile"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="中标文件(单个)" prop="bidFile"> | ||||
|           <file-upload v-model="form.bidFile"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="合同额" prop="contract"> | ||||
|           <el-input v-model="form.contract" placeholder="请输入合同额" /> | ||||
|  | ||||
|         <el-form-item label="中标通知书" prop="bidFile"> | ||||
|           <file-upload v-model="form.bidFile" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
| @ -131,6 +139,26 @@ | ||||
| <script setup name="Plan" lang="ts"> | ||||
| import { listPlan, getPlan, delPlan, addPlan, updatePlan } from '@/api/plan/plan'; | ||||
| import { PlanVO, PlanQuery, PlanForm } from '@/api/plan/plan/types'; | ||||
| import { getCurrentInstance, onMounted, ref, reactive, toRefs, computed, watch } from 'vue'; | ||||
| import type { ElFormInstance } from 'element-plus'; | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
|  | ||||
| // 1. 与目标代码一致:从用户Store获取当前选中项目及ID | ||||
| const userStore = useUserStoreHook(); | ||||
| const currentProject = computed(() => userStore.selectedProject); | ||||
| const currentProjectId = computed(() => currentProject.value?.id); | ||||
|  | ||||
| // 2. 类型定义(保持原有基础,新增projectId关联) | ||||
| interface DialogOption { | ||||
|   visible: boolean; | ||||
|   title: string; | ||||
| } | ||||
|  | ||||
| interface PageData<F, Q> { | ||||
|   form: F; | ||||
|   queryParams: Q; | ||||
|   rules: Record<string, any[]>; | ||||
| } | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| @ -151,135 +179,208 @@ const dialog = reactive<DialogOption>({ | ||||
|   title: '' | ||||
| }); | ||||
|  | ||||
| const initFormData: PlanForm = { | ||||
|   id: undefined, | ||||
|   subpackageType: undefined, | ||||
|   subpackageName: undefined, | ||||
|   subpackageContext: undefined, | ||||
| // 3. 初始化表单数据:新增projectId,默认关联当前选中项目ID(与目标代码一致) | ||||
| const initFormData: PlanForm & { dictName?: string; content?: string } = { | ||||
|   id: '1958116259107012609', | ||||
|   projectId: currentProjectId.value, // 初始关联当前项目ID | ||||
|   plannedBiddingMethod: undefined, | ||||
|   price: undefined, | ||||
|   limitPrice: undefined, | ||||
|   planTenderTime: undefined, | ||||
|   tenderMethod: undefined, | ||||
|   tenderFile: undefined, | ||||
|   contractPrice: undefined, | ||||
|   bidFile: undefined, | ||||
|   contract: undefined, | ||||
| } | ||||
| const data = reactive<PageData<PlanForm, PlanQuery>>({ | ||||
|   form: {...initFormData}, | ||||
|   dictName: '1', | ||||
|   name: 'test1', | ||||
|   content: 'trhbhbt' | ||||
| }; | ||||
|  | ||||
| // 4. 页面数据:查询参数默认携带当前项目ID(与目标代码一致) | ||||
| const data = reactive<PageData<typeof initFormData, PlanQuery & { dictName?: string; content?: string }>>({ | ||||
|   form: { ...initFormData }, | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     subpackageType: undefined, | ||||
|     subpackageName: undefined, | ||||
|     subpackageContext: undefined, | ||||
|     projectId: currentProjectId.value, // 查询参数默认关联当前项目 | ||||
|     dictName: undefined, | ||||
|     name: undefined, | ||||
|     plannedBiddingTime: undefined, | ||||
|     plannedBiddingMethod: undefined, | ||||
|     price: undefined, | ||||
|     limitPrice: undefined, | ||||
|     planTenderTime: undefined, | ||||
|     tenderMethod: undefined, | ||||
|     tenderFile: undefined, | ||||
|     contractPrice: undefined, | ||||
|     content: undefined, | ||||
|     bidFile: undefined, | ||||
|     contract: undefined, | ||||
|     params: { | ||||
|     } | ||||
|     params: {} | ||||
|   }, | ||||
|   rules: { | ||||
|     id: [ | ||||
|       { required: true, message: "招标计划ID不能为空", trigger: "blur" } | ||||
|     ], | ||||
|     projectId: [{ required: true, message: '请输入项目ID', trigger: 'blur' }], // 新增项目ID必填规则 | ||||
|     name: [{ required: true, message: '请输入名称', trigger: 'blur' }], | ||||
|     plannedBiddingMethod: [{ required: true, message: '请输入招标方式', trigger: 'blur' }], | ||||
|     limitPrice: [{ required: true, message: '请输入限价', trigger: 'blur' }], | ||||
|     contractPrice: [{ required: true, message: '请输入合同额', trigger: 'blur' }], | ||||
|     content: [{ required: true, message: '请输入分包内容', trigger: 'blur' }] | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| // 5. 与目标代码一致:监听当前项目ID变化,自动更新查询参数、表单数据并刷新列表 | ||||
| watch(currentProjectId, (newVal) => { | ||||
|   // 更新查询参数的项目ID | ||||
|   queryParams.value.projectId = newVal; | ||||
|   // 新增状态下更新表单项目ID | ||||
|   if (!form.value.id) { | ||||
|     form.value.projectId = newVal; | ||||
|   } | ||||
|   // 重新加载列表 | ||||
|   getList(); | ||||
| }); | ||||
|  | ||||
| /** 查询招标计划列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const res = await listPlan(queryParams.value); | ||||
|   planList.value = res.rows; | ||||
|   total.value = res.total; | ||||
|   loading.value = false; | ||||
| } | ||||
|   try { | ||||
|     const res = await listPlan(queryParams.value); | ||||
|     planList.value = res.rows || []; | ||||
|     total.value = res.total || 0; | ||||
|   } catch (error) { | ||||
|     console.error('获取招标计划列表失败', error); | ||||
|     proxy?.$modal.msgError('获取招标计划列表失败'); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 取消按钮 */ | ||||
| const cancel = () => { | ||||
|   reset(); | ||||
|   dialog.visible = false; | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 表单重置 */ | ||||
| /** 表单重置:重置时保留当前项目ID(与目标代码一致) */ | ||||
| const reset = () => { | ||||
|   form.value = {...initFormData}; | ||||
|   form.value = { ...initFormData, projectId: currentProjectId.value }; | ||||
|   planFormRef.value?.resetFields(); | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   getList(); | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 重置按钮操作 */ | ||||
| /** 重置按钮操作:保留当前项目ID(与目标代码一致) */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.projectId = currentProjectId.value; | ||||
|   handleQuery(); | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 多选框选中数据 */ | ||||
| const handleSelectionChange = (selection: PlanVO[]) => { | ||||
|   ids.value = selection.map(item => item.id); | ||||
|   single.value = selection.length != 1; | ||||
|   ids.value = selection.map((item) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 新增按钮操作 */ | ||||
| const handleAdd = () => { | ||||
|   reset(); | ||||
|   dialog.visible = true; | ||||
|   dialog.title = "添加招标计划"; | ||||
| } | ||||
|  | ||||
| /** 修改按钮操作 */ | ||||
| /** 修改按钮操作:回显数据时保留项目ID */ | ||||
| const handleUpdate = async (row?: PlanVO) => { | ||||
|   reset(); | ||||
|   const _id = row?.id || ids.value[0] | ||||
|   const res = await getPlan(_id); | ||||
|   Object.assign(form.value, res.data); | ||||
|   dialog.visible = true; | ||||
|   dialog.title = "修改招标计划"; | ||||
| } | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   if (!_id) { | ||||
|     proxy?.$modal.msgWarning('请选择需要修改的招标计划'); | ||||
|     return; | ||||
|   } | ||||
|   try { | ||||
|     const res = await getPlan(_id); | ||||
|     Object.assign(form.value, res.data, { | ||||
|       id: res.data.id || initFormData.id, | ||||
|       dictName: res.data.dictName || initFormData.dictName, | ||||
|       content: res.data.content || initFormData.content, | ||||
|       projectId: res.data.projectId || currentProjectId.value // 确保项目ID正确 | ||||
|     }); | ||||
|     dialog.visible = true; | ||||
|     dialog.title = '修改招标计划'; | ||||
|   } catch (error) { | ||||
|     console.error('获取招标计划详情失败', error); | ||||
|     proxy?.$modal.msgError('获取招标计划详情失败'); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| /** 提交按钮:新增时强制携带当前项目ID(与目标代码一致) */ | ||||
| const submitForm = () => { | ||||
|   planFormRef.value?.validate(async (valid: boolean) => { | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       if (form.value.id) { | ||||
|         await updatePlan(form.value).finally(() =>  buttonLoading.value = false); | ||||
|       } else { | ||||
|         await addPlan(form.value).finally(() =>  buttonLoading.value = false); | ||||
|       try { | ||||
|         // 新增时强制使用当前选中项目ID | ||||
|         if (!form.value.id && currentProjectId.value) { | ||||
|           form.value.projectId = currentProjectId.value; | ||||
|         } | ||||
|         if (form.value.id) { | ||||
|           await updatePlan(form.value); | ||||
|         } else { | ||||
|           await addPlan(form.value); | ||||
|         } | ||||
|         proxy?.$modal.msgSuccess('操作成功'); | ||||
|         dialog.visible = false; | ||||
|         await getList(); | ||||
|       } catch (error) { | ||||
|         console.error('操作失败', error); | ||||
|         proxy?.$modal.msgError('操作失败,请重试'); | ||||
|       } finally { | ||||
|         buttonLoading.value = false; | ||||
|       } | ||||
|       proxy?.$modal.msgSuccess("操作成功"); | ||||
|       dialog.visible = false; | ||||
|       await getList(); | ||||
|     } | ||||
|   }); | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| /** 删除按钮操作(原有逻辑不变) */ | ||||
| const handleDelete = async (row?: PlanVO) => { | ||||
|   const _ids = row?.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除招标计划编号为"' + _ids + '"的数据项?').finally(() => loading.value = false); | ||||
|   await delPlan(_ids); | ||||
|   proxy?.$modal.msgSuccess("删除成功"); | ||||
|   await getList(); | ||||
| } | ||||
|   if (!_ids || (_ids instanceof Array && _ids.length === 0)) { | ||||
|     proxy?.$modal.msgWarning('请选择需要删除的招标计划'); | ||||
|     return; | ||||
|   } | ||||
|   try { | ||||
|     await proxy?.$modal.confirm('是否确认删除选中的招标计划?'); | ||||
|     await delPlan(_ids); | ||||
|     proxy?.$modal.msgSuccess('删除成功'); | ||||
|     await getList(); | ||||
|   } catch (error) { | ||||
|     console.error('删除失败', error); | ||||
|     if (error !== 'cancel') { | ||||
|       proxy?.$modal.msgError('删除失败,请重试'); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 导出按钮操作 */ | ||||
| /** 导出按钮操作(原有逻辑不变) */ | ||||
| const handleExport = () => { | ||||
|   proxy?.download('plan/plan/export', { | ||||
|     ...queryParams.value | ||||
|   }, `plan_${new Date().getTime()}.xlsx`) | ||||
| } | ||||
|   proxy?.download( | ||||
|     'plan/plan/export', | ||||
|     { | ||||
|       ...queryParams.value | ||||
|     }, | ||||
|     `plan_${new Date().getTime()}.xlsx` | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .mb-4 { | ||||
|   margin-bottom: 16px; | ||||
| } | ||||
| .el-table .small-padding .cell { | ||||
|   padding: 0 5px; | ||||
| } | ||||
| .el-table .fixed-width { | ||||
|   width: 120px !important; | ||||
| } | ||||
| .el-table-column .el-button--text + .el-button--text { | ||||
|   margin-left: 10px; | ||||
| } | ||||
| </style> | ||||
|  | ||||
| @ -4,6 +4,16 @@ | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form ref="queryFormRef" :model="queryParams" :inline="true"> | ||||
|             <!-- 新增:搜索表单字段(可选,支持按新字段搜索) --> | ||||
|             <el-form-item label="供应商名称" prop="supplierName"> | ||||
|               <el-input v-model="queryParams.supplierName" placeholder="请输入供应商名称" maxlength="50" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="供应商负责人" prop="supplierPerson"> | ||||
|               <el-input v-model="queryParams.supplierPerson" placeholder="请输入负责人" maxlength="20" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="负责人电话" prop="personPhone"> | ||||
|               <el-input v-model="queryParams.personPhone" placeholder="请输入负责人电话" maxlength="11" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|               <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
| @ -42,11 +52,26 @@ | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <!-- 表格:新增3个字段列 --> | ||||
|       <el-table v-loading="loading" :data="supplierInputList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column label="" align="center" prop="id" v-if="true" /> | ||||
|         <el-table-column label="供应商类型" align="center" prop="supplierType" /> | ||||
|         <el-table-column label="入库资料" align="center" prop="inputFile" /> | ||||
|  | ||||
|         <el-table-column label="供应商名称" align="center" prop="supplierName" width="180" /> | ||||
|         <el-table-column label="供应商负责人" align="center" prop="supplierPerson" width="150" /> | ||||
|         <el-table-column label="负责人电话" align="center" prop="personPhone" width="150" /> | ||||
|         <el-table-column label="供应商类型" align="center" prop="supplierType" width="150" /> | ||||
|         <el-table-column label="状态" align="center" prop="state" width="150"> | ||||
|           <template #default="scope"> | ||||
|             <dict-tag :options="wf_business_status" :value="scope.row.state"></dict-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="入库资料" align="center" prop="inputFile" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-link :href="scope.row.inputFile" :underline="false" target="_blank" v-if="scope.row.inputFile"> | ||||
|               <el-button size="mini" class="el-icon-document">查看文件</el-button> | ||||
|             </el-link> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-tooltip content="修改" placement="top"> | ||||
| @ -73,10 +98,19 @@ | ||||
|  | ||||
|       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> | ||||
|     </el-card> | ||||
|     <!-- 添加或修改供应商入库对话框 --> | ||||
|  | ||||
|     <!-- 新增/修改对话框:添加3个字段表单 --> | ||||
|     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> | ||||
|       <el-form ref="supplierInputFormRef" :model="form" :rules="rules" label-width="100px"> | ||||
|         <!-- 新增的供应商类型下拉框 --> | ||||
|         <el-form-item label="供应商名称" prop="supplierName"> | ||||
|           <el-input v-model="form.supplierName" placeholder="请输入供应商名称" maxlength="50" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="供应商负责人" prop="supplierPerson"> | ||||
|           <el-input v-model="form.supplierPerson" placeholder="请输入供应商负责人" maxlength="20" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="负责人电话" prop="personPhone"> | ||||
|           <el-input v-model="form.personPhone" placeholder="请输入负责人电话" maxlength="11" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="供应商类型" prop="supplierType"> | ||||
|           <el-select v-model="form.supplierType" placeholder="请选择供应商类型"> | ||||
|             <el-option label="劳务" value="劳务"></el-option> | ||||
| @ -84,15 +118,20 @@ | ||||
|             <el-option label="物资设备" value="物资设备"></el-option> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="入库资料" prop="inputFile" l> | ||||
|         <el-form-item label="入库资料" prop="inputFile"> | ||||
|           <file-upload | ||||
|             v-model="form.inputFile" | ||||
|             :fileType="['doc', 'docx', 'pdf']" | ||||
|             :fileType="['pdf']" | ||||
|             :autoUpload="false" | ||||
|             ref="fileUploadRef" | ||||
|             :method="form.id ? 'put' : 'post'" | ||||
|             :data="{ supplierType: form.supplierType }" | ||||
|             :data="{ | ||||
|               supplierType: form.supplierType, | ||||
|               supplierName: form.supplierName, | ||||
|               supplierPerson: form.supplierPerson, | ||||
|               personPhone: form.personPhone, | ||||
|               id: form.id | ||||
|             }" | ||||
|             uploadUrl="/supplierInput/supplierInput" | ||||
|             :limit="1" | ||||
|             :onUploadSuccess="handleUploadSuccess" | ||||
| @ -132,6 +171,17 @@ | ||||
| import { listSupplierInput, getSupplierInput, delSupplierInput, addSupplierInput, updateSupplierInput } from '@/api/supplierInput/supplierInput'; | ||||
| import { SupplierInputVO, SupplierInputQuery, SupplierInputForm } from '@/api/supplierInput/supplierInput/types'; | ||||
|  | ||||
| // 补充类型定义(若types.ts未同步更新,需先在types.ts中添加以下字段) | ||||
| interface DialogOption { | ||||
|   visible: boolean; | ||||
|   title: string; | ||||
| } | ||||
| interface PageData<F, Q> { | ||||
|   form: F; | ||||
|   queryParams: Q; | ||||
|   rules: Record<string, any[]>; | ||||
| } | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const fileUploadRef = ref(null); | ||||
| const supplierInputList = ref<SupplierInputVO[]>([]); | ||||
| @ -150,9 +200,13 @@ const dialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '' | ||||
| }); | ||||
|  | ||||
| const { wf_business_status } = toRefs(proxy.useDict('wf_business_status')); | ||||
| // 初始化表单:添加3个新字段 | ||||
| const initFormData: SupplierInputForm = { | ||||
|   id: undefined, | ||||
|   supplierName: undefined, // 新增 | ||||
|   supplierPerson: undefined, // 新增 | ||||
|   personPhone: undefined, // 新增 | ||||
|   supplierType: undefined, | ||||
|   inputFile: undefined | ||||
| }; | ||||
| @ -162,12 +216,21 @@ const data = reactive<PageData<SupplierInputForm, SupplierInputQuery>>({ | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     supplierName: undefined, // 新增:搜索参数 | ||||
|     supplierPerson: undefined, // 新增:搜索参数 | ||||
|     personPhone: undefined, // 新增:搜索参数 | ||||
|     supplierType: undefined, | ||||
|     inputFile: undefined, | ||||
|     params: {} | ||||
|   }, | ||||
|   rules: { | ||||
|     // 添加供应商类型的验证规则 | ||||
|     // 新增:3个字段的验证规则 | ||||
|     supplierName: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }], | ||||
|     supplierPerson: [{ required: true, message: '请输入供应商负责人', trigger: 'blur' }], | ||||
|     personPhone: [ | ||||
|       { required: true, message: '请输入负责人电话', trigger: 'blur' }, | ||||
|       { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur' } | ||||
|     ], | ||||
|     supplierType: [{ required: true, message: '请选择供应商类型', trigger: 'change' }], | ||||
|     id: [{ required: true, message: '不能为空', trigger: 'blur' }] | ||||
|   } | ||||
| @ -208,6 +271,8 @@ const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   handleQuery(); | ||||
| }; | ||||
|  | ||||
| /** 文件上传成功回调 */ | ||||
| const handleUploadSuccess = () => { | ||||
|   proxy?.$modal.msgSuccess('操作成功'); | ||||
|   dialog.visible = false; | ||||
| @ -215,14 +280,16 @@ const handleUploadSuccess = () => { | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| /** 文件选择变更回调 */ | ||||
| const change = (fileList) => { | ||||
|   fileUrl.value = ''; | ||||
| }; | ||||
|  | ||||
| /** 多选框选中数据 */ | ||||
| const handleSelectionChange = (selection: SupplierInputVO[]) => { | ||||
|   ids.value = selection.map((item) => item.id); | ||||
|   single.value = selection.length != 1; | ||||
|   multiple.value = !selection.length; | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = selection.length === 0; | ||||
| }; | ||||
|  | ||||
| /** 新增按钮操作 */ | ||||
| @ -232,32 +299,42 @@ const handleAdd = () => { | ||||
|   dialog.title = '添加供应商入库'; | ||||
| }; | ||||
|  | ||||
| /** 修改按钮操作 */ | ||||
| /** 修改按钮操作:回显3个新字段数据 */ | ||||
| const handleUpdate = async (row?: SupplierInputVO) => { | ||||
|   reset(); | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   const res = await getSupplierInput(_id); | ||||
|   // Object.assign(form.value, res.data); | ||||
|   form.value = { | ||||
|     ...form.value, | ||||
|     ...res.data, | ||||
|     inputFile: '' | ||||
|     inputFile: '' // 清空文件上传绑定值(保持原有逻辑) | ||||
|   }; | ||||
|   fileUrl.value = res.data.inputFile; | ||||
|   // 确保新字段回显(若接口返回字段名一致,可省略此步;若不一致需手动映射) | ||||
|   form.value.supplierName = res.data.supplierName; | ||||
|   form.value.supplierPerson = res.data.supplierPerson; | ||||
|   form.value.personPhone = res.data.personPhone; | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '修改供应商入库'; | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| /** 提交按钮:文件上传携带新字段参数 */ | ||||
| const submitForm = () => { | ||||
|   supplierInputFormRef.value?.validate(async (valid: boolean) => { | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       fileUploadRef.value.submitUpload().then(() => { | ||||
|         proxy?.$modal.msgSuccess('操作成功'); | ||||
|         dialog.visible = false; | ||||
|         getList(); | ||||
|       }); | ||||
|       // 提交文件时携带所有表单参数(含新字段) | ||||
|       fileUploadRef.value | ||||
|         .submitUpload() | ||||
|         .then(() => { | ||||
|           proxy?.$modal.msgSuccess('操作成功'); | ||||
|           dialog.visible = false; | ||||
|           buttonLoading.value = false; | ||||
|           getList(); | ||||
|         }) | ||||
|         .catch(() => { | ||||
|           buttonLoading.value = false; // 上传失败重置加载状态 | ||||
|         }); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
| @ -265,27 +342,29 @@ const submitForm = () => { | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row?: SupplierInputVO) => { | ||||
|   const _ids = row?.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除供应商入库编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false)); | ||||
|   await delSupplierInput(_ids); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
|   await getList(); | ||||
|   try { | ||||
|     await proxy?.$modal.confirm(`是否确认删除供应商入库编号为"${_ids}"的数据项?`); | ||||
|     await delSupplierInput(_ids); | ||||
|     proxy?.$modal.msgSuccess('删除成功'); | ||||
|     await getList(); | ||||
|   } catch (error) { | ||||
|     // 取消删除不处理 | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 导出按钮操作 */ | ||||
| /** 导出按钮操作:携带新字段搜索参数 */ | ||||
| const handleExport = () => { | ||||
|   proxy?.download( | ||||
|     'supplierInput/supplierInput/export', | ||||
|     { | ||||
|       ...queryParams.value | ||||
|     }, | ||||
|     `supplierInput_${new Date().getTime()}.xlsx` | ||||
|   ); | ||||
|   proxy?.download('supplierInput/supplierInput/export', { ...queryParams.value }, `supplierInput_${new Date().getTime()}.xlsx`); | ||||
| }; | ||||
|  | ||||
| /** 页面挂载时加载列表 */ | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .pdf { | ||||
|   display: flex; | ||||
| @ -324,6 +403,7 @@ onMounted(() => { | ||||
|   align-items: center; | ||||
|   color: inherit; | ||||
| } | ||||
|  | ||||
| .Shadow { | ||||
|   align-items: center; | ||||
|   background-color: rgba(0, 0, 0, 0.5); | ||||
| @ -345,6 +425,7 @@ onMounted(() => { | ||||
| .ele-upload-list__item-content-action .el-link { | ||||
|   margin-right: 10px; | ||||
| } | ||||
|  | ||||
| .el-icon.avatar-uploader-icon { | ||||
|   border: 1px dashed #cdd0d6; | ||||
|   border-radius: 6px; | ||||
|  | ||||
							
								
								
									
										0
									
								
								src/views/tender/supplierInput/indexEdit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/views/tender/supplierInput/indexEdit.vue
									
									
									
									
									
										Normal file
									
								
							
		Reference in New Issue
	
	Block a user