From 80cca114a9211b1510c9777f5a597d429efe90da Mon Sep 17 00:00:00 2001 From: dhr <2216804034@qq.com> Date: Tue, 23 Sep 2025 20:36:47 +0800 Subject: [PATCH] 0922 --- .env.development | 2 +- src/api/zhinengxunjian/baoxiou/index.ts | 8 + src/api/zhinengxunjian/gongdan/index.ts | 57 + src/api/zhinengxunjian/jiedian/index.ts | 57 + src/api/zhinengxunjian/qiangxiu/index.ts | 57 + src/utils/request.ts | 8 +- .../zhinengxunjian/InspectionManagement.vue | 4 +- src/views/zhinengxunjian/baoxiuguanli.vue | 1034 ++++++++--- src/views/zhinengxunjian/baoxiujilu.vue | 1172 ++++++++++-- src/views/zhinengxunjian/gongdanliebiao.vue | 1131 +++++++++--- src/views/zhinengxunjian/index.vue | 2 +- src/views/zhinengxunjian/paidanjilu.vue | 74 +- src/views/zhinengxunjian/qiangxiuguanli.vue | 1629 ++++++++++++++--- src/views/zhinengxunjian/qiangxiujilu.vue | 1049 +++++++++-- src/views/zhinengxunjian/shiyanguanli.vue | 4 +- src/views/zhinengxunjian/shiyanjilu.vue | 2 +- src/views/zhinengxunjian/shiyanrenwu.vue | 4 +- src/views/zhinengxunjian/xunjianjihua.vue | 4 +- src/views/zhinengxunjian/xunjianrenwu.vue | 4 +- 19 files changed, 5107 insertions(+), 1195 deletions(-) create mode 100644 src/api/zhinengxunjian/gongdan/index.ts create mode 100644 src/api/zhinengxunjian/jiedian/index.ts create mode 100644 src/api/zhinengxunjian/qiangxiu/index.ts diff --git a/.env.development b/.env.development index f7ff9da..f9304df 100644 --- a/.env.development +++ b/.env.development @@ -5,7 +5,7 @@ VITE_APP_TITLE = 新能源场站智慧运维平台 VITE_APP_ENV = 'development' # 开发环境 -VITE_APP_BASE_API = 'http://192.168.110.149:18899' +VITE_APP_BASE_API = 'http://192.168.110.210:18899' # 应用访问路径 例如使用前缀 /admin/ VITE_APP_CONTEXT_PATH = '/' diff --git a/src/api/zhinengxunjian/baoxiou/index.ts b/src/api/zhinengxunjian/baoxiou/index.ts index 4c0c107..0a680e3 100644 --- a/src/api/zhinengxunjian/baoxiou/index.ts +++ b/src/api/zhinengxunjian/baoxiou/index.ts @@ -47,3 +47,11 @@ export const uploadbaoxiu = (data) => { data: data }); }; + +export const baoxiuRecord = (data) => { + return request({ + url: '/ops/report/record', + method: 'get', + params: data + }); +}; diff --git a/src/api/zhinengxunjian/gongdan/index.ts b/src/api/zhinengxunjian/gongdan/index.ts new file mode 100644 index 0000000..781d8d2 --- /dev/null +++ b/src/api/zhinengxunjian/gongdan/index.ts @@ -0,0 +1,57 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +//查询列表 +export const gongdanlist = (query) => { + return request({ + url: '/ops/order/list', + method: 'get', + params: query + }); +}; +//新增待办事项 +export const addgongdan = (data) => { + return request({ + url: '/ops/order', + method: 'post', + data: data + }); +}; +//修改待办事项 +export const updategongdan = (data) => { + return request({ + url: '/ops/order', + method: 'put', + data: data + }); +}; +//删除待办事项 + +export function delgongdan(ids) { + return request({ + url: `/ops/order/${ids}`, // 拼接ids作为路径参数 + method: 'delete' + }); +} + +export const gongdanDetail = (id) => { + return request({ + url: `/ops/order/${id}`, + method: 'get' + }); +}; + +export const uploadgongdan = (data) => { + return request({ + url: '/resource/oss/upload', + method: 'post', + data: data + }); +}; + +export const gongdanRecord = (data) => { + return request({ + url: '/ops/order/record', + method: 'get', + params: data + }); +}; diff --git a/src/api/zhinengxunjian/jiedian/index.ts b/src/api/zhinengxunjian/jiedian/index.ts new file mode 100644 index 0000000..c38b3ec --- /dev/null +++ b/src/api/zhinengxunjian/jiedian/index.ts @@ -0,0 +1,57 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +//查询列表 +export const jiedianlist = (query) => { + return request({ + url: '/ops/node/list', + method: 'get', + params: query + }); +}; +//新增待办事项 +export const addjiedian = (data) => { + return request({ + url: '/ops/node', + method: 'post', + data: data + }); +}; +//修改待办事项 +export const updatejiedian = (data) => { + return request({ + url: '/ops/node', + method: 'put', + data: data + }); +}; +//删除待办事项 + +export function deljiedian(ids) { + return request({ + url: `/ops/node/${ids}`, // 拼接ids作为路径参数 + method: 'delete' + }); +} + +export const jiedianDetail = (id) => { + return request({ + url: `/ops/node/${id}`, + method: 'get' + }); +}; + +export const uploadjiedian = (data) => { + return request({ + url: '/resource/oss/upload', + method: 'post', + data: data + }); +}; + +export const jiedianRecord = (data) => { + return request({ + url: '/ops/node/record', + method: 'get', + params: data + }); +}; diff --git a/src/api/zhinengxunjian/qiangxiu/index.ts b/src/api/zhinengxunjian/qiangxiu/index.ts new file mode 100644 index 0000000..bb717c0 --- /dev/null +++ b/src/api/zhinengxunjian/qiangxiu/index.ts @@ -0,0 +1,57 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +//查询列表 +export const qiangxiulist = (query) => { + return request({ + url: '/ops/repair/list', + method: 'get', + params: query + }); +}; +//新增待办事项 +export const addqiangxiu = (data) => { + return request({ + url: '/ops/repair', + method: 'post', + data: data + }); +}; +//修改待办事项 +export const updateqiangxiu = (data) => { + return request({ + url: '/ops/repair', + method: 'put', + data: data + }); +}; +//删除待办事项 + +export function delqiangxiu(ids) { + return request({ + url: `/ops/repair/${ids}`, // 拼接ids作为路径参数 + method: 'delete' + }); +} + +export const qiangxiuDetail = (id) => { + return request({ + url: `/ops/repair/${id}`, + method: 'get' + }); +}; + +export const uploadqiangxiu = (data) => { + return request({ + url: '/resource/oss/upload', + method: 'post', + data: data + }); +}; + +export const qiangxiuRecord = (data) => { + return request({ + url: '/ops/repair/record', + method: 'get', + params: data + }); +}; diff --git a/src/utils/request.ts b/src/utils/request.ts index f3b06ad..ca0e341 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -23,12 +23,18 @@ export const globalHeaders = () => { }; }; +// 设置默认请求头 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'; +axios.defaults.headers['Accept'] = 'application/json, text/plain, */*'; axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID; // 创建 axios 实例 const service = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_API, - timeout: 50000 + timeout: 50000, + headers: { + 'Content-Type': 'application/json;charset=utf-8', + 'Accept': 'application/json, text/plain, */*' + } }); // 请求拦截器 diff --git a/src/views/zhinengxunjian/InspectionManagement.vue b/src/views/zhinengxunjian/InspectionManagement.vue index 8ab639d..aaab44b 100644 --- a/src/views/zhinengxunjian/InspectionManagement.vue +++ b/src/views/zhinengxunjian/InspectionManagement.vue @@ -48,8 +48,8 @@
- 搜索 - 手动创建计划 + 搜索 + 手动创建计划
diff --git a/src/views/zhinengxunjian/baoxiuguanli.vue b/src/views/zhinengxunjian/baoxiuguanli.vue index 58c6ad7..08cb703 100644 --- a/src/views/zhinengxunjian/baoxiuguanli.vue +++ b/src/views/zhinengxunjian/baoxiuguanli.vue @@ -34,24 +34,21 @@
- -
-
- 搜索 - 手动创建任务 + 搜索 + 手动创建任务
@@ -72,7 +69,7 @@
报修时间 - {{ task.reportTime }} + {{ task.createTime }}
报修人 @@ -82,11 +79,7 @@ 维修人 {{ task.maintainer }}
- -
- 预计完成 - {{ task.expectedCompleteTime }} -
+
状态 {{ task.statusText }} @@ -159,12 +152,6 @@ - - - - - - @@ -173,29 +160,9 @@ - - -
-
- -
点击或拖拽图片至此处上传
-
支持JPG、PNG格式,最多3张
-
-
-
-
已选择{{ createTaskForm.fileList.length }}张图片,将在提交时上传
@@ -222,7 +189,196 @@ + + +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+

任务基本信息

+
+
+
+ 任务ID: + {{ detailData.id || '-' }} +
+
+ 任务名称: + {{ detailData.name || '未命名' }} +
+
+
+
+ 任务状态: + {{ getStatusText(detailData.status) }} +
+
+ 任务等级: + {{ getPriorityText(detailData.level) }} +
+
+
+
+ 任务类型: + {{ detailData.type === '1' ? '硬件故障' : detailData.type === '2' ? '软件故障' : '-' }} +
+
+ 报修时间: + {{ formatDate(detailData.createTime) }} +
+
+
+
+ + +
+

报修人信息

+
+
+
+ 报修人: + {{ detailData.reportName || '-' }} +
+
+ 联系人: + {{ detailData.reportName || '-' }} +
+
+
+
+ 联系电话: + {{ detailData.reportPhone || '-' }} +
+
+ 维修人: + {{ detailData.sendPersonVo?.userName || '-' }} +
+
+
+
+ + +
+

报修详情

+
+
+
+ 故障位置: + {{ detailData.position || '-' }} +
+
+
+
+ 详细描述: + {{ detailData.reportInfo || '-' }} +
+
+ +
+
+ 完成时间: + {{ formatDate(detailData.completeTime) }} +
+
+
+
+ + +
+

故障图片

+
+
+ +
+ +
+
+
+
+
+
+ + 加载中... +
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + +
@@ -230,9 +386,9 @@ import { ref, computed, onMounted } from 'vue'; import router from '@/router'; import TitleComponent from './TitleComponent.vue'; -import { baoxiulist, baoxiuDetail, delbaoxiu, updatebaoxiu, addbaoxiu, uploadbaoxiu } from '@/api/zhinengxunjian/baoxiou/index'; +import { baoxiulist, baoxiuDetail, updatebaoxiu, addbaoxiu } from '@/api/zhinengxunjian/baoxiou/index'; import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian'; -import { ElMessage } from 'element-plus'; +import { ElMessage, ElLoading } from 'element-plus'; // 激活的选项卡 const activeTab = ref('task'); @@ -241,6 +397,17 @@ const taskStatus = ref(''); const planType = ref(''); const executor = ref(''); +// 详情弹窗相关 +const detailDialogVisible = ref(false); +const detailData = ref(null); +const isDetailLoading = ref(false); + +// 关闭详情弹窗 +const handleCloseDetailDialog = () => { + detailDialogVisible.value = false; + detailData.value = null; +}; + // 任务数据 - 初始为空数组 const tasks = ref([]); @@ -250,6 +417,14 @@ const pageSize = ref(8); const total = ref(0); const loading = ref(false); +// 分配任务弹窗相关 +const assignDialogVisible = ref(false); +const assignTaskForm = ref({ taskId: '', sendPerson: '' }); +const assignTaskRules = { + sendPerson: [{ required: true, message: '请选择维修人', trigger: 'change' }] +}; +const assignTaskFormRef = ref(null); + // 获取报修任务列表 defineExpose({ getTaskList }); async function getTaskList() { @@ -274,16 +449,24 @@ async function getTaskList() { leftLineClass: getLeftLineClass(item.status, item.level), priorityClass: getPriorityClass(item.level), priority: getPriorityText(item.level), - reportTime: formatDate(item.reportTime), + // 修复报修时间字段名,使用与模板一致的createTime + createTime: formatDate(item.createTime || item.reportTime), + // 修复报修人字段,使用reportName reporter: item.reportName || '未知报修人', - maintainer: item.sendPerson ? `维修人ID: ${item.sendPerson}` : '未分配', - expectedCompleteTime: getExpectedCompleteTime(item.status), + // 修复维修人字段,从sendPersonVo对象中获取用户名 + maintainer: item.sendPersonVo?.userName || '未分配', + completeTime: item.completeTime ? formatDate(item.completeTime) : '', actionText: getActionText(item.status), actionClass: getActionClass(item.status), reportInfo: item.reportInfo, position: item.position, - fileUrl: item.fileUrl + fileUrl: item.fileUrl, + + reportPhone: item.reportPhone || '', + type: item.type || '', + // 保留原始数据用于详情查看 + sendPersonVo: item.sendPersonVo })); } else { tasks.value = []; @@ -371,20 +554,6 @@ function getActionClass(status) { return actionMap[status] || 'view-btn'; } -// 获取预计完成时间(根据状态和优先级估算) -function getExpectedCompleteTime(status) { - if (status === '3') return ''; // 已完成任务不需要显示预计时间 - - const now = new Date(); - // 简单估算:待处理任务默认当天18:00前完成,处理中任务默认2小时内完成 - if (status === '1') { - now.setHours(18, 0, 0, 0); - } else { - now.setHours(now.getHours() + 2); - } - return formatDate(now); -} - // 格式化日期时间 function formatDate(date) { if (!date) return ''; @@ -438,7 +607,7 @@ const createTaskForm = ref({ faultLocation: '', contactPerson: '', contactPhone: '', - sendPerson: '', // 指派维修人 + sendPerson: '未分配维修人', // 指派维修人 file: '' // 上传的文件列表 }); @@ -449,8 +618,7 @@ const createTaskRules = { detailedDescription: [{ required: true, message: '请输入详细描述', trigger: 'blur' }], faultLocation: [{ required: true, message: '请输入故障位置', trigger: 'blur' }], contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }], - contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }], - sendPerson: [{ required: true, message: '请选择维修人', trigger: 'change' }] + contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }] }; // 用户列表(维修人) @@ -464,9 +632,9 @@ const getUsersList = async () => { const res = await xunjianUserlist(); // 根据接口返回格式,成功码是200,用户数据在rows数组中 if (res.code === 200 && res.rows && Array.isArray(res.rows)) { - // 映射用户数据,使用id作为value,userName作为显示名称 + // 映射用户数据,将id转换为字符串以避免大整数精度问题 usersList.value = res.rows.map((user) => ({ - id: user.id, + id: String(user.id), name: user.userName })); } else { @@ -481,86 +649,7 @@ const getUsersList = async () => { } }; const isSubmitting = ref(false); // 防止重复提交的状态标记 -const isUploading = ref(false); // 防止重复上传的状态标记 -// 上传文件方法 -const uploadFiles = async (files) => { - // 防止重复上传 - if (isUploading.value) { - ElMessage.warning('数据正在处理中,请稍候...'); - return []; - } - try { - isUploading.value = true; - const formData = new FormData(); - - // 关键修复:将字段名从'files'改为'file',匹配后端要求的'file'字段 - files.forEach((file) => { - formData.append('file', file.raw); // 这里将'files'改为'file' - }); - - const res = await uploadbaoxiu(formData); - - if (res.code === 200 && res.data && Array.isArray(res.data)) { - return res.data.map((item) => ({ - fileId: item.ossId, - fileUrl: item.url - })); - } else { - console.error('文件上传失败:', res.msg); - throw new Error(res.msg || '文件上传失败'); - } - } catch (error) { - console.error('文件上传异常:', error); - if (error.message.includes('重复提交')) { - throw new Error('操作过于频繁,请稍后再试'); - } - throw error; - } finally { - isUploading.value = false; - } -}; - -const handleFileChange = (file, fileList) => { - // 只处理刚添加的文件 - if (file.status === 'ready') { - // 验证文件格式和大小 - const isJPG = file.raw.type === 'image/jpeg' || file.raw.type === 'image/jpg'; - const isPNG = file.raw.type === 'image/png'; - const isLt2M = file.size / 1024 / 1024 < 2; - - if (!isJPG && !isPNG) { - ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!'); - // 从文件列表中移除不符合要求的文件 - createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid); - return; - } - - if (!isLt2M) { - ElMessage.error('上传图片大小不能超过 2MB!'); - // 从文件列表中移除不符合要求的文件 - createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid); - return; - } - - // 保存验证通过的文件到表单 - createTaskForm.value.fileList = fileList; - } -}; -const handleExceed = (files, fileList) => { - ElMessage.warning(`当前限制选择 3 张图片,本次选择了 ${files.length} 张,共选择了 ${files.length + fileList.length} 张`); -}; - -// 文件移除前的钩子 -const beforeRemove = (file, fileList) => { - return window.confirm(`确定移除 ${file.name}?`); -}; - -// 文件移除时的钩子 -const handleRemove = (file, fileList) => { - createTaskForm.value.fileList = fileList; - ElMessage.info(`已移除 ${file.name}`); -}; // 创建任务 const handleCreateTask = async () => { createTaskDialogVisible.value = true; @@ -580,21 +669,6 @@ const handleSaveTask = async () => { // 先验证表单 await createTaskFormRef.value.validate(); - // 上传选中的文件 - let fileIds = []; - let fileUrls = []; - - if (createTaskForm.value.fileList && createTaskForm.value.fileList.length > 0) { - ElMessage.info(`开始上传 ${createTaskForm.value.fileList.length} 张图片...`); - const uploadResults = await uploadFiles(createTaskForm.value.fileList); - - // 提取上传结果 - fileIds = uploadResults.map((result) => result.fileId); - fileUrls = uploadResults.map((result) => result.fileUrl); - - ElMessage.success(`图片上传成功,共 ${uploadResults.length} 张`); - } - // 准备请求数据 const requestData = { projectId: 1, @@ -602,11 +676,10 @@ const handleSaveTask = async () => { type: mapRepairType(createTaskForm.value.repairType), status: '1', // 默认为待处理状态 level: mapPriorityLevel(createTaskForm.value.priority), - sendPerson: parseInt(createTaskForm.value.sendPerson), + reportInfo: createTaskForm.value.detailedDescription, position: createTaskForm.value.faultLocation, - fileId: fileIds.join(','), // 用逗号分隔多个文件ID - fileUrl: fileUrls.join(','), // 用逗号分隔多个文件URL + fileId: createTaskForm.value.file, reportName: createTaskForm.value.contactPerson, reportPhone: createTaskForm.value.contactPhone }; @@ -683,52 +756,6 @@ function mapPriorityLevel(priority) { return levelMap[priority] || '2'; } -// 文件上传前的校验 -async function beforeUpload(file) { - const isJPG = file.type === 'image/jpeg' || file.type === 'image/jpg'; - const isPNG = file.type === 'image/png'; - const isLt2M = file.size / 1024 / 1024 < 2; - - if (!isJPG && !isPNG) { - ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!'); - return false; - } - if (!isLt2M) { - ElMessage.error('上传图片大小不能超过 2MB!'); - return false; - } - - try { - // 直接上传文件 - const uploadResult = await uploadFile(file); - // 存储文件信息到表单 - createTaskForm.value.fileList = [ - { - ...file, - fileId: uploadResult.fileId, - fileUrl: uploadResult.fileUrl - } - ]; - ElMessage.success('图片上传成功'); - } catch (error) { - ElMessage.error('图片上传失败,请重试'); - } - - // 阻止自动上传 - return false; -} - -// 文件上传成功处理 -function handleUploadSuccess(response, file, fileList) { - // 这个函数实际上不会被调用,因为auto-upload=false - // 真正的上传逻辑在beforeUpload函数中处理 -} - -// 文件上传失败处理 -function handleUploadError(err, file, fileList) { - ElMessage.error('上传失败,请稍后重试'); -} - // 取消创建报修任务 const handleCancelCreateTask = () => { createTaskDialogVisible.value = false; @@ -749,15 +776,275 @@ const handleCurrentChange = (val) => { }; // 查看任务详情 -const handleView = (task) => { - console.log('查看任务详情:', task); +const handleView = async (task) => { + try { + if (!task || !task.id) { + ElMessage.warning('任务ID不存在,请刷新页面重试'); + console.error('任务缺少有效id,任务数据:', task); + return; + } + + isDetailLoading.value = true; + detailData.value = null; + + const loading = ElLoading.service({ + lock: true, + text: '加载详情中...', + background: 'rgba(255, 255, 255, 0.7)' + }); + + try { + const response = await baoxiuDetail(task.id); + + // 注意:这里使用code === 200判断成功,与项目中其他详情接口保持一致 + if (response.code === 200 && response.data) { + detailData.value = response.data; + detailDialogVisible.value = true; + } else { + const errorMsg = response.msg || '未知错误'; + console.error(`获取任务详情失败: ${errorMsg}`); + ElMessage.error(`获取任务详情失败:${errorMsg}`); + } + } finally { + loading.close(); + isDetailLoading.value = false; + } + } catch (error) { + console.error('获取任务详情出错:', error); + ElMessage.error('获取任务详情出错,请重试'); + } +}; +// 拆分逗号分隔的图片URL为数组 +const splitImageUrls = (urlString) => { + if (!urlString) return []; + // 拆分并过滤空字符串(处理可能的首尾逗号或连续逗号) + return urlString.split(',').filter((url) => url.trim().length > 0); }; -// 处理选项卡点击 -const handleTabClick = () => { - currentPage.value = 1; +// 处理图片加载失败 +const handleImageError = (event, index) => { + // 可以设置一个默认图片占位符 + event.target.src = ''; + console.error(`图片加载失败: 索引 ${index}`); }; +// 处理任务操作按钮点击事件 +const handleAction = async (task) => { + try { + if (!task || !task.id) { + ElMessage.warning('任务ID不存在,请刷新页面重试'); + console.error('任务缺少有效id,任务数据:', task); + return; + } + + // 点击分配按钮:打开分配弹窗 + if (task.actionText === '分配') { + // 重置表单并设置任务ID + assignTaskForm.value = { taskId: task.id, sendPerson: '' }; + assignDialogVisible.value = true; + + // 打开弹窗时获取用户列表 + if (usersList.value.length === 0) { + await getUsersList(); + } + if (usersList.value.length === 0) { + ElMessage.error('无可用维修人员,请先配置维修人员信息'); + assignDialogVisible.value = false; + } + } + + // 点击跟进按钮:原有逻辑 + else if (task.actionText === '跟进') { + resultDialogVisible.value = true; + currentTaskId.value = task.id; + } + + // 其他操作(如评价) + else { + console.log('其他操作:', task.actionText); + } + } catch (error) { + console.error('任务操作失败:', error, '当前任务数据:', task); + ElMessage.error('操作失败,请联系技术支持'); + } +}; + +// 提交分配任务 +const handleSubmitAssign = async () => { + if (!assignTaskFormRef.value) return; + + try { + await assignTaskFormRef.value.validate(); + + // 找到原始任务数据 + const originalTask = tasks.value.find((t) => t.id === assignTaskForm.value.taskId); + if (!originalTask) { + ElMessage.warning('未找到任务完整数据,请刷新重试'); + return; + } + + // 找到选中的维修人员 + const selectedUser = usersList.value.find((u) => u.id === assignTaskForm.value.sendPerson); + if (!selectedUser) { + ElMessage.error('未找到选中的维修人员'); + return; + } + + // 构造更新参数 + const updateData = { + id: assignTaskForm.value.taskId, + status: '2', // 处理中状态 + sendPerson: selectedUser.id, + sendPersonName: selectedUser.name, + sendPersonVo: { + id: selectedUser.id, + userName: selectedUser.name + }, + // 包含后端所需的其他必要字段 + name: originalTask.title, + type: mapRepairType(originalTask.type || 'all'), + level: mapPriorityLevel(originalTask.priority), + reportName: originalTask.reporter, + reportPhone: originalTask.reportPhone || '', + position: originalTask.position || '', + reportInfo: originalTask.reportInfo || '', + projectId: 1 + }; + + // 调用接口更新 + const response = await updatebaoxiu(updateData); + if (response.code === 200) { + ElMessage.success(`任务已分配给【${selectedUser.name}】,状态更新为处理中`); + assignDialogVisible.value = false; + getTaskList(); // 刷新列表 + } else { + const errorMsg = response.msg || '未知错误'; + console.error(`任务分配失败:${errorMsg},请求参数:`, updateData); + ElMessage.error(`分配失败:${errorMsg}`); + } + } catch (error) { + if (error instanceof Error) { + ElMessage.error(`操作失败:${error.message}`); + } else if (error !== false) { + ElMessage.error('操作失败:未知错误'); + } + } +}; + +// 关闭分配弹窗 +const handleCloseAssign = () => { + assignDialogVisible.value = false; + if (assignTaskFormRef.value) { + assignTaskFormRef.value.clearValidate(); + } +}; + +// 结果输入弹窗相关状态 +const resultDialogVisible = ref(false); +const currentTaskId = ref(''); +const reportFinal = ref(''); + +// 处理结果表单验证规则 +const resultFormRules = { + reportFinal: [ + { + required: true, + message: '请输入处理结果', + trigger: 'blur' + }, + { + min: 5, + max: 500, + message: '处理结果长度在 5 到 500 个字符之间', + trigger: 'blur' + } + ] +}; + +// 表单引用 +const resultFormRef = ref(null); + +// 保存结果 +const handleSaveResult = async () => { + try { + if (!currentTaskId.value) { + ElMessage.warning('任务ID不存在'); + return; + } + + if (!reportFinal.value.trim()) { + ElMessage.warning('请输入处理结果'); + return; + } + + // 1. 查找当前任务的完整数据 + const originalTask = tasks.value.find((t) => t.id === currentTaskId.value); + if (!originalTask) { + ElMessage.warning('未找到任务完整数据,请刷新重试'); + console.error('未找到任务完整数据,任务ID:', currentTaskId.value); + return; + } + + // 2. 生成当前时间作为完成时间 + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + const reportFinishTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + + // 3. 构造完整的更新参数(与任务分配时使用相同的参数集) + const updateData = { + // ① 任务基础标识(必传) + id: currentTaskId.value, // 任务ID(核心主键) + + // ② 状态流转参数(必传) + status: '3', // 状态:3=已完成 + statusText: '已完成', // 状态文本 + reportFinal: reportFinal.value, // 处理结果 + reportFinishTime: reportFinishTime, // 完成时间 + completeTime: reportFinishTime, // 完成时间(向后兼容字段) + + // ③ 复用原始任务数据中的所有必要字段 + name: originalTask.title, // 任务名称(原始任务标题) + type: mapRepairType(originalTask.type || 'all'), // 任务类型(映射为后端需要的格式) + level: mapPriorityLevel(originalTask.priority), // 优先级(映射为后端需要的格式) + reportName: originalTask.reporter, // 报修人姓名 + reportPhone: originalTask.reportPhone || '', // 报修人电话 + position: originalTask.position || '', // 故障位置 + reportInfo: originalTask.reportInfo || '', // 报修详情 + + // ④ 维修人员信息(保留原有分配的维修人员) + sendPerson: originalTask.sendPersonVo?.id || '', // 维修人员ID + sendPersonName: originalTask.sendPersonVo?.userName || '', // 维修人员姓名 + sendPersonVo: originalTask.sendPersonVo || {}, // 维修人员完整信息 + + // ⑤ 其他必要参数 + pageNum: currentPage.value, // 分页参数 + pageSize: pageSize.value, + projectId: 1 // 项目ID + }; + + const response = await updatebaoxiu(updateData); + + if (response.code === 200) { + ElMessage.success('处理结果已保存'); + resultDialogVisible.value = false; + reportFinal.value = ''; + currentTaskId.value = ''; + getTaskList(); + } else { + const errorMsg = response.msg || '未知错误'; + console.error(`保存处理结果失败: ${errorMsg}`); + ElMessage.error(`保存处理结果失败:${errorMsg}`); + } + } catch (error) { + console.error('保存处理结果失败:', error); + ElMessage.error('保存失败,请重试'); + } +}; const handleInspectionManagement1 = () => { router.push('/rili/baoxiuguanli'); }; @@ -801,73 +1088,6 @@ onMounted(async () => { min-height: 100vh; } -/* 上传图片区域样式 */ -.upload-container { - width: 100%; -} - -.upload-box { - border: 2px dashed #dcdfe6; - border-radius: 8px; - padding: 40px 20px; - text-align: center; - cursor: pointer; - background-color: #f8f9fa; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; - overflow: hidden; -} - -.upload-box::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(64, 158, 255, 0.1), transparent); - transition: all 0.6s ease; -} - -.upload-box:hover { - border-color: #409eff; - background-color: #ecf5ff; - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15); -} - -.upload-box:hover::before { - left: 100%; -} - -.avatar-uploader-icon { - font-size: 40px; - color: #c0c4cc; - margin-bottom: 12px; - transition: color 0.3s; -} - -.upload-box:hover .avatar-uploader-icon { - color: #409eff; -} - -.upload-text { - font-size: 14px; - color: #606266; - font-weight: 500; - margin-bottom: 6px; - transition: color 0.3s; -} - -.upload-box:hover .upload-text { - color: #409eff; -} - -.upload-hint { - font-size: 12px; - color: #909399; -} - /* 美化弹窗样式 */ .beautiful-dialog { border-radius: 12px; @@ -917,6 +1137,124 @@ onMounted(async () => { border-top: 1px solid #f0f2f5; text-align: center; } +.custom-experiment-dialog .el-dialog__body { + max-height: 60vh; + overflow-y: auto; + padding: 24px; +} + +/* 详情卡片样式 */ +.detail-card { + background-color: #fff; + border-radius: 8px; + padding: 20px; + margin-bottom: 20px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); + border: 1px solid #f0f2f5; +} + +.card-title { + font-size: 16px; + font-weight: 600; + color: #1d2129; + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 2px solid #409eff; +} + +.card-content { + padding: 0 4px; +} + +/* 信息行和信息项样式 */ +.info-row { + display: flex; + margin-bottom: 16px; + flex-wrap: wrap; +} + +.info-item { + flex: 0 0 50%; + margin-bottom: 12px; + display: flex; + align-items: flex-start; +} + +.info-item.full-width { + flex: 0 0 100%; +} + +.info-label { + font-weight: 500; + color: #86909c; + margin-right: 8px; + min-width: 80px; + flex-shrink: 0; +} + +.info-value { + color: #4e5969; + flex: 1; + word-break: break-all; + font-size: 14px; +} + +/* 故障原因样式 */ +.fail-reason { + color: #ff4d4f; + font-weight: 500; +} + +/* 加载状态 */ +.skeleton-loading { + display: flex; + flex-direction: column; + gap: 16px; +} + +.skeleton-card { + background-color: #f5f5f5; + border-radius: 8px; + padding: 16px; +} + +.skeleton-header { + height: 20px; + width: 30%; + background-color: #e0e0e0; + border-radius: 4px; + margin-bottom: 12px; +} + +.skeleton-content { + display: flex; + flex-direction: column; + gap: 8px; +} + +.skeleton-row { + height: 16px; + background-color: #e0e0e0; + border-radius: 4px; +} + +/* 无数据提示 */ +.no-info { + text-align: center; + color: #909399; + padding: 60px 20px; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .custom-experiment-dialog { + width: 95% !important; + } + + .info-item { + flex: 0 0 100%; + } +} /* 美化表单样式 */ .elegant-form .el-form-item { @@ -1048,10 +1386,6 @@ onMounted(async () => { .elegant-form .el-form-item { margin-bottom: 20px; } - - .upload-box { - padding: 30px 15px; - } } /* 选项卡样式 */ @@ -1369,24 +1703,6 @@ onMounted(async () => { color: #fff; } -.avatar-uploader .el-upload-list { - margin-top: 12px; -} - -.avatar-uploader .el-upload-list__item { - border-radius: 6px; - margin-bottom: 8px; - transition: all 0.2s; -} - -.avatar-uploader .el-upload-list__item:hover { - transform: translateX(4px); -} - -.upload-tip { - margin-top: 10px; - font-size: 12px; -} /* 响应式设计 */ @media (max-width: 1200px) { .task-cards { @@ -1458,4 +1774,120 @@ onMounted(async () => { cursor: pointer; user-select: none; } + +/* 详情弹窗样式 */ +.custom-experiment-dialog { + .detail-content { + max-height: 60vh; + overflow-y: auto; + padding-right: 10px; + } + + .detail-section { + margin-bottom: 24px; + } + + .section-title { + font-size: 16px; + font-weight: 500; + color: #303133; + margin-bottom: 16px; + padding-bottom: 8px; + border-bottom: 1px solid #f0f2f5; + } + + .detail-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + .detail-item { + display: flex; + flex-direction: column; + } + + .detail-label { + font-size: 14px; + color: #909399; + margin-bottom: 4px; + } + + .detail-value { + font-size: 14px; + color: #303133; + } + + .detail-textarea { + margin-bottom: 16px; + } + + .detail-text { + font-size: 14px; + color: #303133; + line-height: 1.6; + word-wrap: break-word; + white-space: pre-wrap; + } + + /* 多图片展示容器样式 */ + .images-container { + display: flex; + flex-wrap: wrap; + gap: 16px; + margin-top: 12px; + padding: 10px; + background-color: #f9f9f9; + border-radius: 8px; + } + + /* 单个图片项样式 */ + .image-item { + flex: 0 0 auto; + width: 200px; /* 固定宽度 */ + height: 160px; /* 固定高度 */ + border-radius: 6px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + transition: transform 0.3s ease; + } + + .image-item:hover { + transform: scale(1.03); + } + + /* 图片样式 */ + .detail-image { + width: 100%; + height: 100%; + object-fit: cover; /* 保持比例填充容器 */ + display: block; + } + + /* 图片加载失败样式 */ + .detail-image[src=''] { + background-color: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + color: #999; + font-size: 12px; + } + + .no-info { + text-align: center; + color: #909399; + padding: 40px 0; + } +} + +@media (max-width: 768px) { + .custom-experiment-dialog { + width: 90% !important; + + .detail-grid { + grid-template-columns: 1fr; + } + } +} diff --git a/src/views/zhinengxunjian/baoxiujilu.vue b/src/views/zhinengxunjian/baoxiujilu.vue index bd22772..8ff61e1 100644 --- a/src/views/zhinengxunjian/baoxiujilu.vue +++ b/src/views/zhinengxunjian/baoxiujilu.vue @@ -28,16 +28,16 @@
- - - + + +
- - - + + +
@@ -58,7 +58,7 @@ />
- 搜索 + 搜索
@@ -68,8 +68,8 @@

本月报修数

-

24

-

较上月 +4.2%

+

{{ statsLoading ? '加载中...' : statsData.byzbxs }}

+

较上月:{{ statsData.bxsjszzzl }}

本月报修数 @@ -79,8 +79,8 @@

平均处理时长

-

3.5小时

-

较上月 -0.6小时

+

{{ statsLoading ? '加载中...' : statsData.pjclsc }}

+

较上月:{{ statsData.clscjszzzl }}

平均处理时长 @@ -90,7 +90,7 @@

待处理报修

-

15

+

{{ statsLoading ? '加载中...' : statsData.dclbx }}

需及时处理

@@ -101,8 +101,8 @@

完成率

-

92%

-

较上月 +2.1%

+

{{ statsLoading ? '加载中...' : statsData.wcl }}%

+

{{ statsData.wcljszzzl }}%

完成率 @@ -112,24 +112,44 @@
- - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - @@ -153,13 +173,210 @@
+ + + +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+

任务基本信息

+
+
+
+ 任务ID: + {{ detailData.id || '-' }} +
+
+ 任务名称: + {{ detailData.name || '未命名' }} +
+
+
+
+ 任务状态: + {{ getStatusText(detailData.status) }} +
+
+ 任务等级: + {{ getPriorityText(detailData.level) }} +
+
+
+
+ 任务类型: + {{ detailData.type === '1' ? '硬件故障' : detailData.type === '2' ? '软件故障' : '-' }} +
+
+ 报修时间: + {{ formatDate(detailData.createTime) }} +
+
+
+
+ + +
+

报修人信息

+
+
+
+ 报修人: + {{ detailData.reportName || '-' }} +
+
+ 联系人: + {{ detailData.reportName || '-' }} +
+
+
+
+ 联系电话: + {{ detailData.reportPhone || '-' }} +
+
+ 维修人: + {{ detailData.sendPersonVo?.userName || '-' }} +
+
+
+
+ + +
+

报修详情

+
+
+
+ 故障位置: + {{ detailData.position || '-' }} +
+
+
+
+ 详细描述: + {{ detailData.reportInfo || '-' }} +
+
+ +
+
+ 完成时间: + {{ formatDate(detailData.completeTime) }} +
+
+
+
+ + +
+

故障图片

+
+
+ +
+ +
+
+
+
+
+
+ + 加载中... +
+ + +
+ + + +
+
+ + +
+
+ +
+ + + +
+
+ + + + +
+
加载中...
+
+ +
- diff --git a/src/views/zhinengxunjian/shiyanguanli.vue b/src/views/zhinengxunjian/shiyanguanli.vue index c5d072b..10ca273 100644 --- a/src/views/zhinengxunjian/shiyanguanli.vue +++ b/src/views/zhinengxunjian/shiyanguanli.vue @@ -49,8 +49,8 @@ >
- 搜索 - 新增实验记录 + 搜索 + 新增实验记录
diff --git a/src/views/zhinengxunjian/shiyanjilu.vue b/src/views/zhinengxunjian/shiyanjilu.vue index 584bdfa..8903a9a 100644 --- a/src/views/zhinengxunjian/shiyanjilu.vue +++ b/src/views/zhinengxunjian/shiyanjilu.vue @@ -54,7 +54,7 @@ class="date-picker" > - 搜索 + 搜索
diff --git a/src/views/zhinengxunjian/shiyanrenwu.vue b/src/views/zhinengxunjian/shiyanrenwu.vue index b4fcced..684be72 100644 --- a/src/views/zhinengxunjian/shiyanrenwu.vue +++ b/src/views/zhinengxunjian/shiyanrenwu.vue @@ -49,8 +49,8 @@
- 搜索 - 手动创建任务 + 搜索 + 手动创建任务
diff --git a/src/views/zhinengxunjian/xunjianjihua.vue b/src/views/zhinengxunjian/xunjianjihua.vue index b7df85b..c011be8 100644 --- a/src/views/zhinengxunjian/xunjianjihua.vue +++ b/src/views/zhinengxunjian/xunjianjihua.vue @@ -12,7 +12,7 @@
筛选 - 导出数据 + 导出数据
@@ -54,7 +54,7 @@ >
- 搜索 + 搜索
diff --git a/src/views/zhinengxunjian/xunjianrenwu.vue b/src/views/zhinengxunjian/xunjianrenwu.vue index b982e51..3360946 100644 --- a/src/views/zhinengxunjian/xunjianrenwu.vue +++ b/src/views/zhinengxunjian/xunjianrenwu.vue @@ -42,8 +42,8 @@
- 搜索 - 手动创建任务 + 搜索 + 手动创建任务