This commit is contained in:
dhr
2025-09-24 16:37:09 +08:00
parent 80cca114a9
commit 9913a7854c
15 changed files with 1943 additions and 435 deletions

View File

@ -91,27 +91,37 @@
<template #default="scope">
<!-- 已接单状态 -->
<template v-if="scope.row.status === '已接单'">
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">查看详情</el-button>
<el-button type="text" @click="handleFollow(scope.row)" class="action-btn">跟踪</el-button>
<el-button type="text" @click="handleCancel(scope.row)" class="action-btn cancel-btn">删除</el-button>
<el-button type="text" @click="handleEdit(scope.row)" class="action-btn">编辑</el-button>
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
</template>
<!-- 已派单状态 -->
<template v-else-if="scope.row.status === '已派单'">
<el-button type="text" @click="handleSetTrack(scope.row)" class="action-btn">
{{ scope.row.point === '1' ? '取消跟踪' : '跟踪' }}
</el-button>
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
</template>
<!-- 待派单状态 -->
<template v-else-if="scope.row.status === '待派单'">
<el-button type="text" @click="handleAssign(scope.row)" class="action-btn">派单</el-button>
<el-button type="text" @click="handleEdit(scope.row)" class="action-btn">编辑</el-button>
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
</template>
<!-- 执行中状态 -->
<template v-else-if="scope.row.status === '执行中'">
<el-button type="text" @click="handleCommunicate(scope.row)" class="action-btn">沟通</el-button>
<el-button type="text" @click="handleViewProgress(scope.row)" class="action-btn">查看进度</el-button>
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
</template>
<!-- 已完成状态 -->
<template v-else-if="scope.row.status === '已完成'">
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
<el-button type="text" @click="handleArchive(scope.row)" class="action-btn">归档</el-button>
<el-button type="text" @click="handleViewDetail(scope.row)" class="action-btn">详情</el-button>
</template>
<!-- 默认显示 -->
@ -172,7 +182,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="截止时间*" prop="deadline">
<el-date-picker v-model="createForm.deadline" type="date" placeholder="yyyy/mm/日" format="yyyy/MM/dd" value-format="yyyy/MM/dd" />
<el-date-picker v-model="createForm.deadline" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD" />
</el-form-item>
</el-col>
</el-row>
@ -189,11 +199,7 @@
</el-col>
<el-col :span="12">
<el-form-item label="相关设备/系统">
<el-select v-model="createForm.relatedEquipment" placeholder="请填写相关设备或系统名称" filterable allow-create>
<el-option label="设备A" value="设备A" />
<el-option label="设备B" value="设备B" />
<el-option label="系统1" value="系统1" />
</el-select>
<el-input v-model="createForm.relatedEquipment" placeholder="请输入相关设备或系统名称" />
</el-form-item>
</el-col>
</el-row>
@ -201,7 +207,10 @@
<div class="steps-container">
<div class="step-item" v-for="(step, index) in createForm.steps" :key="index">
<div class="step-number">{{ index + 1 }}</div>
<el-input v-model="step.content" placeholder="输入试验步骤" />
<el-input v-model="step.content" placeholder="输入试验步骤" style="flex: 1; margin-right: 10px" />
<el-button v-if="createForm.steps.length > 1" type="text" class="delete-step-btn" @click="deleteStep(index)" style="color: #f56c6c">
删除
</el-button>
</div>
<el-button type="text" class="add-step-btn" @click="addStep">添加步骤</el-button>
</div>
@ -275,7 +284,7 @@
</div>
<div class="detail-item">
<span class="detail-label">创建时间</span>
<span class="detail-value">{{ detailData.sendOrderTime ? formatDate(detailData.sendOrderTime) : '-' }}</span>
<span class="detail-value">{{ detailData.createTime ? formatDate(detailData.createTime) : '-' }}</span>
</div>
</div>
<div class="info-row">
@ -332,9 +341,7 @@
v-for="(node, index) in group.items"
:key="node.id"
:title="node.name"
:description="`目的: ${node.intendedPurpose || '-'}\n预计时间: ${
node.intendedTime ? formatDate(node.intendedTime) : '-'
}\n完成时间: ${node.finishTime ? formatDate(node.finishTime) : '-'}\n备注: ${node.remark || '-'}`"
:description="`目的: ${node.intendedPurpose || '-'}`"
/>
</el-steps>
</div>
@ -381,6 +388,25 @@
</span>
</template>
</el-dialog>
<!-- 派单弹窗 -->
<el-dialog v-model="assignDialogVisible" title="派单" width="400px" :before-close="cancelAssign">
<div class="assign-dialog-content">
<div class="form-group">
<label class="form-label">选择执行人:</label>
<el-select v-model="selectedExecutor" placeholder="请选择执行人" style="width: 100%" :loading="loadingUsers" filterable>
<el-option v-for="item in executors" :key="item.userId" :label="item.userName" :value="item.userId" />
</el-select>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelAssign">取消</el-button>
<el-button type="primary" @click="confirmAssign" :loading="assignLoading">确定</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
</template>
@ -388,8 +414,9 @@
<script setup>
import { ref, computed, reactive } from 'vue';
import router from '@/router';
import { gongdanlist, addgongdan, gongdanDetail, uploadgongdan } from '@/api/zhinengxunjian/gongdan/index';
import { gongdanlist, addgongdan, updategongdan, gongdanDetail, uploadgongdan } from '@/api/zhinengxunjian/gongdan/index';
import { addjiedian } from '@/api/zhinengxunjian/jiedian';
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian';
import ImageUpload from '@/components/ImageUpload/index.vue';
import { ElMessageBox } from 'element-plus';
@ -442,7 +469,7 @@ const fetchWorkOrderList = async () => {
type: mapCodeToType(item.type),
priority: mapCodeToPriority(item.level),
creator: item.sendOrderPersonVo?.userName || '',
createTime: item.sendOrderTime ? formatDate(item.sendOrderTime) : '',
createTime: item.createTime ? formatDate(item.createTime) : item.sendOrderTime ? formatDate(item.sendOrderTime) : '',
deadline: item.endTime ? formatDate(item.endTime) : '',
status: mapCodeToStatus(item.status),
executor: item.getOrderPersonVo?.userName || '',
@ -530,19 +557,18 @@ const mapCodeToPriority = (code) => {
return priorityMap[codeStr] || code;
};
// 日期格式化函数
// 日期格式化函数 - 支持datetime格式
const formatDate = (dateString) => {
if (!dateString) return '';
const date = new Date(dateString);
return date
.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
.replace(/\//g, '-');
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
// 返回与datetime选择器value-format一致的格式
return `${year}/${month}/${day} ${hours}:${minutes}`;
};
// 初始化加载数据
@ -692,18 +718,252 @@ const handleCancel = (row) => {
const handleCommunicate = (row) => {
console.log('沟通:', row);
// 这里可以实现沟通功能,例如打开沟通弹窗或跳转到沟通页面
};
const handleArchive = (row) => {
console.log('归档:', row);
};
// 编辑工单
const handleEdit = (row) => {
console.log('编辑工单:', row);
// 实现编辑功能,可能需要打开编辑弹窗并加载工单数据
// 派单弹窗相关状态
const assignDialogVisible = ref(false);
const assignLoading = ref(false);
const currentTaskId = ref('');
const currentTaskInfo = ref(null); // 存储当前工单的完整信息
const selectedExecutor = ref('');
const executors = ref([]);
const loadingUsers = ref(false);
// 派单功能
const handleAssign = async (row) => {
console.log('派单:', row);
currentTaskId.value = row.id;
currentTaskInfo.value = row; // 保存完整的工单信息
selectedExecutor.value = '';
try {
// 调用xunjianUserlist接口获取用户列表
loadingUsers.value = true;
const res = await xunjianUserlist();
if (res && res.code === 200 && res.rows && Array.isArray(res.rows)) {
// 过滤有效用户并格式化数据
executors.value = res.rows
.filter((user) => user.userId && user.userName)
.map((user) => ({
userId: user.userId.toString(),
userName: user.userName
}));
} else {
ElMessage.error('获取用户列表失败');
}
} catch (error) {
console.error('获取用户列表异常:', error);
ElMessage.error('获取用户列表失败,请稍后重试');
} finally {
loadingUsers.value = false;
}
// 打开派单弹窗
assignDialogVisible.value = true;
};
// 确认派单
const confirmAssign = async () => {
if (!selectedExecutor.value) {
ElMessage.warning('请选择执行人');
return;
}
try {
assignLoading.value = true;
// 调用updategongdan接口来执行派单操作
// 从执行人列表中查找选中的执行人信息
const selectedExecutorInfo = executors.value.find((item) => item.userId === selectedExecutor.value);
// 先获取完整的工单详情,确保有所有必要字段(与编辑弹窗一样的方式)
const detailResponse = await gongdanDetail(currentTaskId.value);
if (detailResponse.code !== 200) {
ElMessage.error('获取工单详情失败');
return;
}
// 获取完整的工单数据
const workOrderDetail = detailResponse.data;
// 在完整工单数据基础上进行修改(与编辑弹窗一样的方式)
const updateData = {
...workOrderDetail,
// 状态更新为已派单根据系统状态映射2表示已派单
status: 2,
// 设置执行人ID
handler: selectedExecutor.value,
// 设置执行人姓名
handlerName: selectedExecutorInfo?.userName || '',
// 设置派单人ID根据qiangxiujilu.vue的实现同时提供getOrderPerson和sendPerson两个字段
getOrderPerson: selectedExecutor.value,
sendPerson: selectedExecutor.value,
// 设置派单人Vo对象包含id和userName
getOrderPersonVo: selectedExecutorInfo
? {
id: selectedExecutor.value,
userName: selectedExecutorInfo.userName
}
: null,
// 更新时间
updateTime: new Date().toISOString(),
// 根据用户要求,在派单时设置派单时间
sendOrderTime: new Date().toISOString(),
// 确保类型字段正确
type: workOrderDetail.type || 1
};
const response = await updategongdan(updateData);
if (response.code === 200) {
ElMessage.success('派单成功');
assignDialogVisible.value = false;
// 刷新工单列表以显示更新后的状态
fetchWorkOrderList();
} else {
ElMessage.error(response.msg || '派单失败');
}
} catch (error) {
console.error('派单异常:', error);
ElMessage.error('派单失败,请稍后重试');
} finally {
assignLoading.value = false;
}
};
// 取消派单
const cancelAssign = () => {
assignDialogVisible.value = false;
selectedExecutor.value = '';
currentTaskId.value = '';
};
// 跟踪功能 - 已接单状态
const handleFollow = (row) => {
console.log('跟踪:', row);
// 这里可以实现跟踪功能,例如显示工单跟踪记录或打开跟踪记录页面
};
// 设置跟踪功能 - 已派单状态
const handleSetTrack = async (row) => {
try {
// 获取当前point值默认为2不跟踪
const currentPoint = row.point || '2';
// 确定新的point值和操作类型
const newPoint = currentPoint === '1' ? '2' : '1';
const operationText = currentPoint === '1' ? '取消跟踪' : '设置跟踪';
// 弹出确认对话框
await ElMessageBox.confirm(`确定要${operationText}该工单吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
// 获取完整的工单详情
const detailResponse = await gongdanDetail(row.id);
if (detailResponse.code !== 200) {
ElMessage.error('获取工单详情失败');
return;
}
// 获取完整的工单数据
const workOrderDetail = detailResponse.data;
// 在完整工单数据基础上进行修改
const updateData = {
...workOrderDetail,
// 切换point值1表示跟踪2表示不跟踪
point: newPoint,
// 更新时间
updateTime: new Date().toISOString()
};
const response = await updategongdan(updateData);
if (response.code === 200) {
ElMessage.success(`${operationText}成功`);
// 刷新工单列表以显示更新后的状态
fetchWorkOrderList();
} else {
ElMessage.error(response.msg || `${operationText}失败`);
}
} catch (error) {
if (error === 'cancel') {
// 用户取消操作,不做处理
return;
}
console.error('设置跟踪异常:', error);
ElMessage.error('设置跟踪失败,请稍后重试');
}
};
// 编辑工单
const handleEdit = async (row) => {
console.log('编辑工单:', row);
try {
// 获取工单详情
const detailResponse = await gongdanDetail(row.id);
if (detailResponse.code !== 200) {
ElMessage.error('获取工单详情失败');
return;
}
const workOrderDetail = detailResponse.data;
// 填充表单数据(与新增工单使用同一套表单)
createForm.title = workOrderDetail.title || '';
createForm.type = mapCodeToType(workOrderDetail.type) || '维护保养';
createForm.priority = mapCodeToPriority(workOrderDetail.level) || '低';
createForm.deadline = workOrderDetail.endTime ? formatDate(workOrderDetail.endTime) : '';
createForm.description = workOrderDetail.info || '';
createForm.location = workOrderDetail.position || '';
createForm.relatedEquipment = workOrderDetail.device || '';
createForm.file = workOrderDetail.fileId || '';
createForm.resultDescription = workOrderDetail.results || '';
createForm.needAssignee = !!workOrderDetail.executor;
// 填充步骤数据从nodes数组中提取并按code排序
if (workOrderDetail.nodes && Array.isArray(workOrderDetail.nodes)) {
// 复制nodes数组并按code升序排序与groupNodesByModule函数保持一致的排序逻辑
const sortedNodes = [...workOrderDetail.nodes].sort((a, b) => (a.code || 0) - (b.code || 0));
// 转换为createForm.steps所需的格式
createForm.steps = sortedNodes.map((node) => ({
content: node.intendedPurpose || ''
}));
// 确保至少有一个空步骤
if (createForm.steps.length === 0) {
createForm.steps = [{ content: '' }];
}
} else {
// 如果没有nodes数据重置为默认的一个空步骤
createForm.steps = [{ content: '' }];
}
// 存储当前编辑的工单ID用于区分是创建还是编辑操作
editingWorkOrderId.value = row.id;
// 保存原始创建时间
originalCreateTime.value = workOrderDetail.createTime || '';
// 打开新增工单的弹窗
createDialogVisible.value = true;
} catch (error) {
console.error('打开编辑工单弹窗过程中发生错误:', error);
ElMessage.error('打开编辑工单弹窗失败');
}
};
// 编辑状态下的工单ID
const editingWorkOrderId = ref('');
// 保存原始创建时间(编辑工单时使用)
const originalCreateTime = ref('');
// 查看工单进度
const handleViewProgress = (row) => {
console.log('查看工单进度:', row);
@ -750,6 +1010,16 @@ const addStep = () => {
createForm.steps.push({ content: '' });
};
// 删除试验步骤
const deleteStep = (index) => {
// 确保至少保留一个步骤
if (createForm.steps.length <= 1) {
ElMessage.warning('至少需要保留一个步骤');
return;
}
createForm.steps.splice(index, 1);
};
// 提交创建工单
const submitCreate = async () => {
// 表单验证
@ -795,23 +1065,17 @@ const submitCreate = async () => {
// 准备工单数据
const workOrderData = {
createTime: new Date().toISOString(),
// 编辑模式下使用原始创建时间,创建模式下使用当前时间
createTime: editingWorkOrderId.value && originalCreateTime.value ? originalCreateTime.value : new Date().toISOString(),
updateTime: new Date().toISOString(),
params: {},
module: 1, //
projectId: 1, // 假设项目ID为1
module: 1,
projectId: 1,
title: createForm.title,
type: mapTypeToCode(createForm.type),
level: mapPriorityToCode(createForm.priority),
// 修复RangeError: 添加日期有效性检查
endTime: createForm.deadline
? (() => {
const deadlineDate = new Date(createForm.deadline);
return isNaN(deadlineDate.getTime()) ? new Date().toISOString() : deadlineDate.toISOString();
})()
: new Date().toISOString(),
// 采用与shiyanguanli页面相同的日期处理方式
endTime: createForm.deadline ? new Date(createForm.deadline).toISOString() : '',
info: createForm.description,
position: createForm.location,
device: createForm.relatedEquipment || '',
@ -820,18 +1084,35 @@ const submitCreate = async () => {
nodeIds: nodeIds,
results: createForm.resultDescription || '',
status: 1, // 待派单 1待派单2已派单3执行中4已完成
sendOrderTime: new Date().toISOString(),
sendOrderTime: '', // 根据用户要求,只有在派单并选择人员后才赋值
getOrderTime: '',
finishiOrderTime: '',
orderResult: '', // 验收结果1通过2需整改
point: ''
point: '2', // 默认不跟踪2表示不跟踪1表示跟踪
createDept: '',
createBy: '',
handlerDept: '',
handler: '',
handlerName: ''
};
// 然后调用addgongdan接口
const gongdanResponse = await addgongdan(workOrderData);
let response;
// 区分创建和编辑操作
if (editingWorkOrderId.value) {
// 编辑操作调用updategongdan接口
const updateData = {
...workOrderData,
id: editingWorkOrderId.value
};
response = await updategongdan(updateData);
} else {
// 创建操作调用addgongdan接口
response = await addgongdan(workOrderData);
}
if (gongdanResponse.code === 200) {
ElMessage.success('工单创建成功');
if (response.code === 200) {
const successMessage = editingWorkOrderId.value ? '工单编辑成功' : '工单创建成功';
ElMessage.success(successMessage);
createDialogVisible.value = false;
// 重置表单
@ -843,10 +1124,15 @@ const submitCreate = async () => {
}
});
// 重置编辑状态
editingWorkOrderId.value = '';
originalCreateTime.value = '';
// 刷新工单列表
fetchWorkOrderList();
} else {
ElMessage.error('工单创建失败');
const errorMessage = editingWorkOrderId.value ? '工单编辑失败' : '工单创建失败';
ElMessage.error(errorMessage);
}
} catch (error) {
// 增加详细的错误信息日志