0925
This commit is contained in:
@ -137,7 +137,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="输入任务名称" />
|
||||
@ -192,6 +192,27 @@
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 步骤条区域 -->
|
||||
<el-form-item label="执行步骤" prop="steps">
|
||||
<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>
|
||||
<span class="dialog-footer">
|
||||
@ -215,7 +236,7 @@
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">任务状态:</span>
|
||||
<span class="info-value" :class="getStatusClass(detailData.status)">
|
||||
<span class="info-value" :class="getTaskStatusClass(detailData.status)">
|
||||
{{ getStatusText(detailData.status) }}
|
||||
</span>
|
||||
</div>
|
||||
@ -260,7 +281,7 @@
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">联系电话:</span>
|
||||
<span class="info-value">{{ detailData.personInfo.phone }}</span>
|
||||
<span class="info-value">{{ detailData.personInfo.phonenumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="detailData.personInfo" class="info-row">
|
||||
@ -268,10 +289,6 @@
|
||||
<span class="info-label">性别:</span>
|
||||
<span class="info-value">{{ detailData.personInfo.sex === '1' ? '男' : '女' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">民族:</span>
|
||||
<span class="info-value">{{ detailData.personInfo.nation }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-info">暂无执行人信息</div>
|
||||
</div>
|
||||
@ -307,6 +324,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.testFinal || detailData.failReason" class="detail-card">
|
||||
<h3 class="card-title">执行结果信息</h3>
|
||||
@ -346,8 +383,10 @@ import router from '@/router';
|
||||
import { syrenwulist, syrenwuDetail, addsyrenwu, updatesyrenwu } from '@/api/zhinengxunjian/shiyan/renwu';
|
||||
import { shiyanlist } from '@/api/zhinengxunjian/shiyan';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian/index';
|
||||
import { addjiedian } from '@/api/zhinengxunjian/jiedian/index';
|
||||
// 引入Element Plus组件(提示/空状态/骨架屏/弹窗)
|
||||
import { ElMessage, ElEmpty, ElSkeleton, ElForm, ElMessageBox } from 'element-plus';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
|
||||
/**
|
||||
* 根据任务ID获取完整的任务详情数据
|
||||
@ -379,6 +418,25 @@ const loading = ref(false);
|
||||
// 筛选条件(与接口参数对应)
|
||||
const taskStatus = ref(''); // 任务状态:1=待执行,2=暂停(已延期),3=失败,4=执行中,5=已完成
|
||||
const planType = ref(''); // 关联计划ID:1=每日,2=每周,3=每月
|
||||
|
||||
/**
|
||||
* 将节点数据按模块分组
|
||||
* @param {Array} nodes - 节点数据数组
|
||||
* @returns {Array} 分组后的模块数组
|
||||
*/
|
||||
const groupNodesByModule = (nodes) => {
|
||||
if (!nodes || !Array.isArray(nodes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 这里简单地将所有节点放在一个默认模块下,实际应用中可以根据节点数据的module字段进行分组
|
||||
const defaultGroup = {
|
||||
module: '测试步骤',
|
||||
items: nodes
|
||||
};
|
||||
|
||||
return [defaultGroup];
|
||||
};
|
||||
const executor = ref('all'); // 执行人ID:all=全部
|
||||
|
||||
// 用户列表(通过xunjianUserlist接口获取)
|
||||
@ -420,15 +478,58 @@ const getStatusText = (status) => {
|
||||
* @param {string} status - 任务状态码
|
||||
* @returns {string} 样式类名
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取步骤状态对应的样式类
|
||||
* @param {string|number} status - 步骤状态码
|
||||
* @returns {string} 样式类名
|
||||
*/
|
||||
const getStatusClass = (status) => {
|
||||
// 处理可能的数字输入
|
||||
const statusStr = status?.toString() || '';
|
||||
const statusClassMap = {
|
||||
'1': 'status-pending',
|
||||
'2': 'status-delayed',
|
||||
'3': 'status-failed',
|
||||
'4': 'status-running',
|
||||
'5': 'status-completed'
|
||||
'3': 'status-executing',
|
||||
'4': 'status-completed'
|
||||
};
|
||||
return statusClassMap[status] || '';
|
||||
return statusClassMap[statusStr] || 'status-unknown';
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化日期时间(用于步骤条)
|
||||
* @param {string} dateTime - 日期时间字符串
|
||||
* @returns {string} 格式化后的日期时间
|
||||
*/
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取步骤状态文本
|
||||
* @param {string|number} status - 步骤状态码
|
||||
* @returns {string} 状态文本
|
||||
*/
|
||||
const getStepStatusText = (status) => {
|
||||
const statusStr = status?.toString() || '';
|
||||
const statusMap = {
|
||||
'1': '待执行',
|
||||
'2': '执行中',
|
||||
'3': '已完成',
|
||||
'4': '已延期'
|
||||
};
|
||||
return statusMap[statusStr] || '未知状态';
|
||||
};
|
||||
|
||||
// 创建任务弹窗
|
||||
@ -441,7 +542,8 @@ const createTaskForm = ref({
|
||||
relatedPlan: '', // 关联计划ID(接口testPlanId)
|
||||
executor: '', // 执行人ID(接口person)
|
||||
workTimeRange1: null, // 工作时间段1
|
||||
workTimeRange2: null // 工作时间段2
|
||||
workTimeRange2: null, // 工作时间段2
|
||||
steps: [{ name: '', intendedPurpose: '', intendedTime: '' }] // 步骤数据数组
|
||||
});
|
||||
// 创建任务表单规则
|
||||
const createTaskRules = {
|
||||
@ -453,6 +555,21 @@ const createTaskRules = {
|
||||
executor: [{ required: true, message: '请选择执行人', trigger: 'change' }]
|
||||
};
|
||||
|
||||
// 添加步骤
|
||||
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);
|
||||
};
|
||||
|
||||
// 构建timeInfo字符串
|
||||
const getTaskTimeInfoString = () => {
|
||||
const timeInfoArray = [];
|
||||
@ -831,6 +948,48 @@ const handleSaveTask = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证所有步骤
|
||||
const hasEmptyStep = createTaskForm.value.steps.some((step) => !step.name.trim() || !step.intendedPurpose.trim());
|
||||
if (hasEmptyStep) {
|
||||
ElMessage.warning('请填写完整所有步骤信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理步骤数据
|
||||
let nodeIds = '';
|
||||
if (createTaskForm.value.steps && createTaskForm.value.steps.length > 0) {
|
||||
// 过滤非空步骤并映射为所需格式
|
||||
const validSteps = createTaskForm.value.steps
|
||||
.filter((step) => step.name.trim() && step.intendedPurpose.trim())
|
||||
.map((step, index) => ({
|
||||
createTime: new Date().toISOString(),
|
||||
updateTime: new Date().toISOString(),
|
||||
params: {},
|
||||
module: 3,
|
||||
code: index + 1,
|
||||
name: step.name,
|
||||
intendedPurpose: step.intendedPurpose,
|
||||
intendedTime: step.intendedTime ? new Date(step.intendedTime).toISOString() : new Date().toISOString(),
|
||||
finishTime: '',
|
||||
remark: '',
|
||||
status: 2
|
||||
}));
|
||||
|
||||
if (validSteps.length > 0) {
|
||||
try {
|
||||
// 调用addjiedian接口获取nodeIds
|
||||
const jiedianResponse = await addjiedian(validSteps);
|
||||
if (jiedianResponse.code === 200 && jiedianResponse.msg) {
|
||||
nodeIds = jiedianResponse.msg; // 直接使用字符串格式,不转换为数组
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加节点失败:', error);
|
||||
ElMessage.error('添加执行步骤失败');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const createParams = {
|
||||
createDept: 0, // 可根据实际情况从全局状态获取
|
||||
createBy: 0, // 可根据实际情况从全局状态获取当前用户ID
|
||||
@ -863,7 +1022,8 @@ const handleSaveTask = async () => {
|
||||
finalInfo: '',
|
||||
pauseFor: '',
|
||||
pauseTime: now.toISOString(),
|
||||
planFinishTime: createTaskForm.value.timeRange[1] // 计划完成时间
|
||||
planFinishTime: createTaskForm.value.timeRange[1], // 计划完成时间
|
||||
nodeIds: nodeIds // 步骤节点ID数组
|
||||
};
|
||||
|
||||
// 3. 调用创建接口
|
||||
@ -904,7 +1064,10 @@ const handleCancelCreateTask = () => {
|
||||
inspectionTarget: '',
|
||||
timeRange: [],
|
||||
relatedPlan: '',
|
||||
executor: ''
|
||||
executor: '',
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null,
|
||||
steps: [{ name: '', intendedPurpose: '', intendedTime: '' }]
|
||||
};
|
||||
};
|
||||
|
||||
@ -954,6 +1117,9 @@ const pagedTasks = computed(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@import url('./css/step-bars.css');
|
||||
@import url('./css/detail-dialog.css');
|
||||
|
||||
/* 原有样式不变,新增无数据提示样式 */
|
||||
.inspection-tasks {
|
||||
padding: 20px;
|
||||
@ -1068,6 +1234,27 @@ const pagedTasks = computed(() => {
|
||||
background-color: #52c41a;
|
||||
}
|
||||
|
||||
/* 自定义步骤条样式覆盖 */
|
||||
.custom-steps .el-step__description {
|
||||
white-space: pre-wrap;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.module-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.module-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f2f5;
|
||||
}
|
||||
|
||||
/* 卡片悬停效果 */
|
||||
.task-card:hover {
|
||||
transform: translateY(-3px);
|
||||
@ -1206,7 +1393,8 @@ const pagedTasks = computed(() => {
|
||||
color: #165dff;
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
.start-btn,
|
||||
.report-btn {
|
||||
background-color: #165dff;
|
||||
border-color: #165dff;
|
||||
}
|
||||
@ -1221,11 +1409,6 @@ const pagedTasks = computed(() => {
|
||||
border-color: #00b42a;
|
||||
}
|
||||
|
||||
.report-btn {
|
||||
background-color: #86909c;
|
||||
border-color: #86909c;
|
||||
}
|
||||
|
||||
/* 分页区域样式 */
|
||||
.pagination-section {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user