0925
This commit is contained in:
@ -133,7 +133,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 添加新任务弹窗 -->
|
||||
<el-dialog v-model="createTaskDialogVisible" title="添加新任务" width="500px" :before-close="handleCancelCreateTask">
|
||||
<el-dialog v-model="createTaskDialogVisible" title="添加新任务" width="700px" :before-close="handleCancelCreateTask">
|
||||
<el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="80px">
|
||||
<el-form-item label="任务名称" prop="taskName">
|
||||
<el-input v-model="createTaskForm.taskName" placeholder="输入任务名称" />
|
||||
@ -211,6 +211,27 @@
|
||||
<el-option label="设备运行状态" value="5" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 步骤条 -->
|
||||
<el-form-item label="执行步骤" class="form-item" style="width: 100%">
|
||||
<div class="steps-container">
|
||||
<div class="step-item" v-for="(step, index) in createTaskForm.steps" :key="index">
|
||||
<div class="step-number">{{ index + 1 }}</div>
|
||||
<el-input v-model="step.name" placeholder="输入步骤名称" style="flex: 1; margin-right: 10px" />
|
||||
<el-input v-model="step.intendedPurpose" placeholder="输入预期目的" style="flex: 1; margin-right: 10px" />
|
||||
<el-date-picker
|
||||
v-model="step.intendedTime"
|
||||
type="datetime"
|
||||
placeholder="选择计划时间"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
value-format="YYYY-MM-DD HH:mm"
|
||||
style="width: 180px; margin-right: 10px"
|
||||
/>
|
||||
<el-button v-if="createTaskForm.steps.length > 1" type="text" @click="removeStep(index)" style="color: #f56c6c"> 删除 </el-button>
|
||||
</div>
|
||||
<el-button type="text" class="add-step-btn" @click="addStep">添加步骤</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
@ -304,7 +325,7 @@
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">联系电话:</span>
|
||||
<span class="info-value">{{ detailData.person?.phone || '-' }}</span>
|
||||
<span class="info-value">{{ detailData.person?.phonenumber || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
@ -312,10 +333,6 @@
|
||||
<span class="info-label">性别:</span>
|
||||
<span class="info-value">{{ detailData.person?.sex === '1' ? '男' : detailData.person?.sex === '2' ? '女' : '-' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">民族:</span>
|
||||
<span class="info-value">{{ detailData.person?.nation || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -356,6 +373,26 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 执行步骤信息卡片 -->
|
||||
<div v-if="detailData.nodes && detailData.nodes.length > 0" class="detail-card">
|
||||
<h3 class="card-title">执行步骤</h3>
|
||||
<div class="steps-container">
|
||||
<div v-for="(node, index) in detailData.nodes" :key="node.id || index" class="step-item">
|
||||
<div class="step-number">{{ node.code || index + 1 }}</div>
|
||||
<div class="step-info">
|
||||
<div class="step-name">{{ node.name || '未命名步骤' }}</div>
|
||||
<div class="step-purpose">{{ node.intendedPurpose || '无说明' }}</div>
|
||||
<div class="step-time">计划时间:{{ formatDateTime(node.intendedTime) }}</div>
|
||||
<div v-if="node.finishTime" class="step-finish-time">完成时间:{{ formatDateTime(node.finishTime) }}</div>
|
||||
<div v-if="node.remark" class="step-remark">备注:{{ node.remark }}</div>
|
||||
</div>
|
||||
<div class="step-status" :class="getStatusClass(node.status)">
|
||||
{{ getStepStatusText(node.status) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 执行结果信息卡片 -->
|
||||
<div v-if="detailData.taskType === '2' || detailData.taskType === 2" class="detail-card">
|
||||
<h3 class="card-title">延期信息</h3>
|
||||
@ -388,37 +425,10 @@
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
|
||||
import { xjrenwuDetail, xjrenwuExport, xjrenwulist, addxjrenwu, updatexjrenwu, delxjrenwu } from '@/api/zhinengxunjian/xunjian/renwu';
|
||||
import { xjrenwuDetail, xjrenwulist, addxjrenwu, updatexjrenwu } from '@/api/zhinengxunjian/xunjian/renwu';
|
||||
import { xunjianUserlist, xunjianlist } from '@/api/zhinengxunjian/xunjian/index';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
|
||||
// 根据任务类型获取对应的文本(1待执行2已延期3执行中4已完成)
|
||||
const getTaskTypeText = (type) => {
|
||||
const typeMap = {
|
||||
'1': '待执行',
|
||||
'2': '已延期',
|
||||
'3': '执行中',
|
||||
'4': '已完成'
|
||||
};
|
||||
// 处理可能的数字输入
|
||||
return typeMap[type.toString()] || '未知类型';
|
||||
};
|
||||
|
||||
// 根据问题类型获取对应的文本(1磁盘使用率2内存使用率3服务状态4响应时间5设备运行状态)
|
||||
const getProblemTypeText = (type) => {
|
||||
const problemTypeMap = {
|
||||
'1': '磁盘使用率',
|
||||
'2': '内存使用率',
|
||||
'3': '服务状态',
|
||||
'4': '响应时间',
|
||||
'5': '设备运行状态'
|
||||
};
|
||||
// 处理可能的数字输入
|
||||
return problemTypeMap[type.toString()] || '未知问题';
|
||||
};
|
||||
|
||||
// 激活的选项卡
|
||||
const activeTab = ref('task');
|
||||
import { addjiedian } from '@/api/zhinengxunjian/jiedian/index';
|
||||
import { ElMessage, ElLoading, ElForm } from 'element-plus';
|
||||
|
||||
// 筛选条件
|
||||
const taskStatus = ref('');
|
||||
@ -428,7 +438,7 @@ const executor = ref('');
|
||||
// 任务数据 - 初始为空数组,通过API获取
|
||||
const tasks = ref([]);
|
||||
|
||||
// 详情弹窗相关变量
|
||||
// 任务详情弹窗相关变量
|
||||
const detailDialogVisible = ref(false);
|
||||
const detailData = ref(null);
|
||||
const isDetailLoading = ref(false);
|
||||
@ -459,6 +469,34 @@ const getStatusClass = (status) => {
|
||||
return statusClassMap[statusStr] || 'status-unknown';
|
||||
};
|
||||
|
||||
// 格式化日期时间
|
||||
const formatDateTime = (dateTime) => {
|
||||
if (!dateTime) return '-';
|
||||
try {
|
||||
const date = new Date(dateTime);
|
||||
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');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
} catch (error) {
|
||||
return dateTime;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取步骤状态文本
|
||||
const getStepStatusText = (status) => {
|
||||
const statusStr = status?.toString() || '';
|
||||
const statusMap = {
|
||||
'1': '待执行',
|
||||
'2': '执行中',
|
||||
'3': '已完成',
|
||||
'4': '已延期'
|
||||
};
|
||||
return statusMap[statusStr] || '未知状态';
|
||||
};
|
||||
|
||||
// 状态映射配置
|
||||
const statusConfig = {
|
||||
pending: {
|
||||
@ -505,11 +543,7 @@ const getTaskList = async () => {
|
||||
const params = {
|
||||
pageSize: pageSize.value,
|
||||
pageNum: currentPage.value,
|
||||
personId: executor.value !== '' ? executor.value : undefined,
|
||||
// 根据任务状态映射到后端需要的taskType
|
||||
taskType: taskStatus.value ? mapTaskStatusToType(taskStatus.value) : undefined,
|
||||
// 添加计划类型筛选
|
||||
planType: planType.value || undefined
|
||||
personId: 1
|
||||
};
|
||||
|
||||
const response = await xjrenwulist(params);
|
||||
@ -583,44 +617,6 @@ const getTaskList = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 辅助函数:将前端状态映射为后端需要的taskType
|
||||
const mapTaskStatusToType = (status) => {
|
||||
const statusMap = {
|
||||
'pending': '1',
|
||||
'delayed': '2',
|
||||
'executing': '3',
|
||||
'completed': '4'
|
||||
};
|
||||
return statusMap[status] || '';
|
||||
};
|
||||
|
||||
// 根据person对象获取执行人姓名
|
||||
const getExecutorName = (person) => {
|
||||
if (person && typeof person === 'object' && person.userName) {
|
||||
return person.userName;
|
||||
}
|
||||
const executorMap = {
|
||||
'zhangming': '张明',
|
||||
'lihua': '李华',
|
||||
'wangqiang': '王强',
|
||||
'zhaowei': '赵伟'
|
||||
};
|
||||
return executorMap[person] || '未知用户';
|
||||
};
|
||||
|
||||
// 根据plan对象获取计划名称
|
||||
const getPlanName = (plan) => {
|
||||
if (plan && typeof plan === 'object' && plan.planName) {
|
||||
return plan.planName;
|
||||
}
|
||||
const planMap = {
|
||||
'daily': '每日巡检计划',
|
||||
'weekly': '每周巡检计划',
|
||||
'monthly': '每月巡检计划'
|
||||
};
|
||||
return planMap[plan] || '未知计划';
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
getTaskList();
|
||||
@ -675,10 +671,11 @@ const createTaskForm = ref({
|
||||
timeRange: [],
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null,
|
||||
relatedPlan: 'all',
|
||||
relatedPlan: '',
|
||||
executor: '',
|
||||
taskType: '1', // 默认待执行
|
||||
problemType: ''
|
||||
problemType: '',
|
||||
steps: [{ name: '', intendedPurpose: '', intendedTime: '' }] // 任务步骤数组
|
||||
});
|
||||
|
||||
const createTaskRules = {
|
||||
@ -694,6 +691,17 @@ const handleCreateTask = () => {
|
||||
openCreateTaskDialog();
|
||||
};
|
||||
|
||||
// 重置步骤表单
|
||||
const resetStepForm = () => {
|
||||
Object.keys(stepForm).forEach((key) => {
|
||||
stepForm[key] = '';
|
||||
});
|
||||
currentStep.value = 0;
|
||||
if (stepFormRef.value) stepFormRef.value.resetFields();
|
||||
if (deviceFormRef.value) deviceFormRef.value.resetFields();
|
||||
if (faultFormRef.value) faultFormRef.value.resetFields();
|
||||
};
|
||||
|
||||
// 构建timeInfo字符串
|
||||
const getTaskTimeInfoString = () => {
|
||||
const timeInfoArray = [];
|
||||
@ -719,6 +727,21 @@ const getTaskTimeInfoString = () => {
|
||||
return timeInfoArray.join(',');
|
||||
};
|
||||
|
||||
// 添加步骤
|
||||
const addStep = () => {
|
||||
createTaskForm.value.steps.push({ name: '', intendedPurpose: '', intendedTime: '' });
|
||||
};
|
||||
|
||||
// 删除步骤
|
||||
const removeStep = (index) => {
|
||||
// 确保至少保留一个步骤
|
||||
if (createTaskForm.value.steps.length <= 1) {
|
||||
ElMessage.warning('至少需要保留一个步骤');
|
||||
return;
|
||||
}
|
||||
createTaskForm.value.steps.splice(index, 1);
|
||||
};
|
||||
|
||||
// 保存任务
|
||||
const handleSaveTask = async () => {
|
||||
// 表单验证
|
||||
@ -727,6 +750,13 @@ const handleSaveTask = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证所有步骤
|
||||
const hasEmptyStep = createTaskForm.value.steps.some((step) => !step.name.trim() || !step.intendedPurpose.trim());
|
||||
if (hasEmptyStep) {
|
||||
ElMessage.warning('请填写完整所有步骤信息');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取timeInfo字符串
|
||||
const taskTimeInfo = getTaskTimeInfoString();
|
||||
@ -736,12 +766,45 @@ const handleSaveTask = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备步骤数据,与工单列表页面保持一致的格式
|
||||
const stepsData = createTaskForm.value.steps
|
||||
.filter((step) => step.name.trim() && step.intendedPurpose.trim())
|
||||
.map((step, index) => ({
|
||||
createTime: new Date().toISOString(),
|
||||
updateTime: new Date().toISOString(),
|
||||
params: {},
|
||||
module: 2,
|
||||
code: index + 1,
|
||||
name: step.name,
|
||||
intendedPurpose: step.intendedPurpose,
|
||||
intendedTime: step.intendedTime ? new Date(step.intendedTime).toISOString() : new Date().toISOString(),
|
||||
finishTime: '',
|
||||
remark: '',
|
||||
status: 2
|
||||
}));
|
||||
|
||||
// 调用添加节点接口,直接传递步骤数组
|
||||
const jiedianResponse = await addjiedian(stepsData);
|
||||
|
||||
if (jiedianResponse.code !== 200) {
|
||||
ElMessage.error('创建步骤失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取返回的ids,实际返回格式中msg字段包含ids字符串,data为null
|
||||
let nodeIds = '';
|
||||
if (jiedianResponse.code === 200 && jiedianResponse.msg) {
|
||||
nodeIds = jiedianResponse.msg;
|
||||
} else {
|
||||
ElMessage.warning('未获取到有效的步骤ID');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建接口所需的数据结构
|
||||
const apiData = {
|
||||
createDept: 0,
|
||||
createBy: 0,
|
||||
projectId: 1,
|
||||
|
||||
createTime: new Date().toISOString(),
|
||||
updateBy: 0,
|
||||
updateTime: new Date().toISOString(),
|
||||
params: {
|
||||
property1: 'string',
|
||||
@ -757,7 +820,8 @@ const handleSaveTask = async () => {
|
||||
personId: createTaskForm.value.executor !== 'all' ? createTaskForm.value.executor : 0,
|
||||
taskProgress: 0,
|
||||
taskType: createTaskForm.value.taskType,
|
||||
problemType: createTaskForm.value.problemType
|
||||
problemType: createTaskForm.value.problemType,
|
||||
nodeIds: nodeIds // 添加步骤ID字符串,与工单列表页面保持一致
|
||||
};
|
||||
|
||||
// 调用新增任务接口
|
||||
@ -774,10 +838,11 @@ const handleSaveTask = async () => {
|
||||
timeRange: [],
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null,
|
||||
relatedPlan: 'all',
|
||||
relatedPlan: '',
|
||||
executor: '',
|
||||
taskType: '1',
|
||||
problemType: ''
|
||||
problemType: '',
|
||||
steps: [{ name: '', intendedPurpose: '', intendedTime: '' }]
|
||||
};
|
||||
// 重新获取任务列表
|
||||
getTaskList();
|
||||
@ -846,11 +911,8 @@ const getPlansList = async () => {
|
||||
label: item.planName || `计划${item.id}`,
|
||||
value: item.id.toString()
|
||||
}));
|
||||
|
||||
planList.value.unshift({ label: '全部计划', value: 'all' });
|
||||
} catch (error) {
|
||||
console.error('获取计划列表失败:', error);
|
||||
planList.value = [{ label: '全部计划', value: 'all' }];
|
||||
}
|
||||
};
|
||||
|
||||
@ -868,8 +930,13 @@ const handleCancelCreateTask = () => {
|
||||
taskName: '',
|
||||
inspectionTarget: '',
|
||||
timeRange: [],
|
||||
relatedPlan: 'all',
|
||||
executor: 'all'
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null,
|
||||
relatedPlan: '',
|
||||
executor: '',
|
||||
taskType: '1',
|
||||
problemType: '',
|
||||
steps: [{ name: '', intendedPurpose: '', intendedTime: '' }]
|
||||
};
|
||||
};
|
||||
|
||||
@ -974,6 +1041,7 @@ const handleAction = async (task) => {
|
||||
const updateData = {
|
||||
...originalTask.rawData,
|
||||
id: task.id,
|
||||
startTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
||||
taskType: '3', // 3表示执行中
|
||||
status: 'executing',
|
||||
taskProgress: 0
|
||||
@ -1039,6 +1107,9 @@ const handleAction = async (task) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@import url('./css/step-bars.css');
|
||||
@import url('./css/detail-dialog.css');
|
||||
|
||||
.inspection-tasks {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
@ -1394,6 +1465,96 @@ const handleAction = async (task) => {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 步骤条展示样式 */
|
||||
.step-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.step-item:hover {
|
||||
background-color: #f5f7fa;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-color: #409eff;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-name {
|
||||
font-weight: 500;
|
||||
color: #1d2129;
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.step-purpose {
|
||||
color: #606266;
|
||||
margin-bottom: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.step-time,
|
||||
.step-finish-time,
|
||||
.step-remark {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.step-status {
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 步骤状态样式 */
|
||||
.step-status.status-pending {
|
||||
background-color: #e6f7ff;
|
||||
color: #1677ff;
|
||||
border: 1px solid #91d5ff;
|
||||
}
|
||||
|
||||
.step-status.status-executing {
|
||||
background-color: #fffbe6;
|
||||
color: #fa8c16;
|
||||
border: 1px solid #ffe58f;
|
||||
}
|
||||
|
||||
.step-status.status-completed {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
border: 1px solid #b7eb8f;
|
||||
}
|
||||
|
||||
.step-status.status-delayed {
|
||||
background-color: #fff2f0;
|
||||
color: #ff4d4f;
|
||||
border: 1px solid #ffccc7;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
@ -1573,4 +1734,11 @@ const handleAction = async (task) => {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.step-content {
|
||||
padding: 30px 20px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user