0924
This commit is contained in:
@ -34,7 +34,7 @@ export const delxunjian = (ids) => {
|
||||
//查询人员
|
||||
export const xunjianUserlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/constructionUser/list',
|
||||
url: '/system/user/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
|
||||
@ -605,13 +605,14 @@ const formatDate = (dateString) => {
|
||||
const getUsersList = async () => {
|
||||
try {
|
||||
const response = await xunjianUserlist();
|
||||
const userRows = response?.data?.rows || response?.rows || [];
|
||||
// 适配新接口格式:检查code为200且rows为数组
|
||||
const userRows = response.code === 200 && response.rows && Array.isArray(response.rows) ? response.rows : [];
|
||||
|
||||
userList.value = userRows
|
||||
.filter((item) => item && typeof item === 'object')
|
||||
.map((item, index) => ({
|
||||
label: item.userName || `用户${index + 1}`,
|
||||
value: item.id || `id_${index}`
|
||||
.map((item) => ({
|
||||
label: item.userName || '未知用户',
|
||||
value: String(item.userId || '') // 使用userId作为唯一标识
|
||||
}));
|
||||
|
||||
if (userList.value.length === 0) {
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
<div class="nav-tab active" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent>
|
||||
|
||||
<!-- 选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
@ -182,7 +179,6 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import * as echarts from 'echarts'; // 导入ECharts
|
||||
import renwuImage from '@/assets/images/renwu.png';
|
||||
|
||||
|
||||
@ -10,8 +10,6 @@
|
||||
<div class="nav-tab" @click="handleInspection6">工单管理</div>
|
||||
<div class="nav-tab" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="报修管理模块" subtitle="创建报修任务,跟进报修记录,管理维修进度"></TitleComponent>
|
||||
|
||||
<!-- 选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
@ -385,7 +383,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
|
||||
import { baoxiulist, baoxiuDetail, updatebaoxiu, addbaoxiu } from '@/api/zhinengxunjian/baoxiou/index';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
@ -632,10 +630,10 @@ const getUsersList = async () => {
|
||||
const res = await xunjianUserlist();
|
||||
// 根据接口返回格式,成功码是200,用户数据在rows数组中
|
||||
if (res.code === 200 && res.rows && Array.isArray(res.rows)) {
|
||||
// 映射用户数据,将id转换为字符串以避免大整数精度问题
|
||||
// 映射用户数据,使用userId字段作为唯一标识并转换为字符串以避免大整数精度问题
|
||||
usersList.value = res.rows.map((user) => ({
|
||||
id: String(user.id),
|
||||
name: user.userName
|
||||
id: String(user.userId || ''),
|
||||
name: user.userName || '未知用户'
|
||||
}));
|
||||
} else {
|
||||
usersList.value = [];
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
<div class="nav-tab" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="报修管理模块" subtitle="创建报修任务,跟进报修记录,管理维修进度"></TitleComponent>
|
||||
|
||||
<!-- 选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
@ -369,7 +366,6 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { baoxiulist, baoxiuDetail, baoxiuRecord, updatebaoxiu } from '@/api/zhinengxunjian/baoxiou/index';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian';
|
||||
@ -498,10 +494,10 @@ const getUsersList = async () => {
|
||||
const res = await xunjianUserlist();
|
||||
// 根据接口返回格式,成功码是200,用户数据在rows数组中
|
||||
if (res.code === 200 && res.rows && Array.isArray(res.rows)) {
|
||||
// 映射用户数据,将id转换为字符串以避免大整数精度问题
|
||||
// 映射用户数据,使用userId字段作为唯一标识并转换为字符串以避免大整数精度问题
|
||||
usersList.value = res.rows.map((user) => ({
|
||||
id: String(user.id),
|
||||
name: user.userName
|
||||
id: String(user.userId || ''),
|
||||
name: user.userName || '未知用户'
|
||||
}));
|
||||
} else {
|
||||
usersList.value = [];
|
||||
|
||||
@ -12,8 +12,6 @@
|
||||
<div class="nav-tab active" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent>
|
||||
|
||||
<!-- 选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
@ -139,7 +137,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
|
||||
|
||||
// 搜索和筛选条件
|
||||
const searchKeyword = ref('');
|
||||
|
||||
@ -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) {
|
||||
// 增加详细的错误信息日志
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -771,7 +771,7 @@ const getUsersList = async () => {
|
||||
try {
|
||||
const res = await xunjianUserlist();
|
||||
if (res.code === 200 && res.rows && Array.isArray(res.rows)) {
|
||||
usersList.value = res.rows.map((user) => ({ id: String(user.id), name: user.userName }));
|
||||
usersList.value = res.rows.map((user) => ({ id: String(user.userId || ''), name: user.userName || '未知用户' }));
|
||||
} else {
|
||||
usersList.value = [];
|
||||
ElMessage.error('获取用户列表失败');
|
||||
|
||||
@ -14,12 +14,7 @@
|
||||
|
||||
<!-- 页面标题和操作区 -->
|
||||
<div class="header-section">
|
||||
<TitleComponent title="抢修管理模块" subtitle="处理紧急抢修任务,跟踪抢修进度和记录"></TitleComponent>
|
||||
<div class="header-actions">
|
||||
<el-button class="filter-btn" @click="showFilter = !showFilter">
|
||||
筛选
|
||||
<i class="el-icon-arrow-down ml-1"></i>
|
||||
</el-button>
|
||||
<el-button type="primary" class="export-btn" @click="handleExport"> 导出数据 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
@ -32,7 +27,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 筛选栏 (默认隐藏) -->
|
||||
<div class="filter-bar" v-if="showFilter">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-container">
|
||||
<div class="filter-item">
|
||||
<el-select v-model="taskStatus" placeholder="任务状态">
|
||||
@ -370,7 +365,6 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import { qiangxiuDetail, qiangxiuRecord, qiangxiulist, updateqiangxiu } from '@/api/zhinengxunjian/qiangxiu';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian';
|
||||
import { ElMessage } from 'element-plus';
|
||||
@ -754,12 +748,12 @@ const handleAssign = async (record) => {
|
||||
try {
|
||||
const res = await xunjianUserlist();
|
||||
if (res && res.code === 200) {
|
||||
// 过滤无效数据+统一sysUserId为字符串
|
||||
// 过滤无效数据+统一userId为字符串
|
||||
executors.value = (res.rows || [])
|
||||
.filter((item) => item.sysUserId && item.userName)
|
||||
.filter((item) => item.userId && item.userName)
|
||||
.map((item) => ({
|
||||
userId: item.sysUserId.toString(), // 关键:使用sysUserId字段
|
||||
userName: item.userName
|
||||
userId: item.userId.toString(), // 使用userId字段
|
||||
userName: item.userName || '未知用户'
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
@ -1018,22 +1012,6 @@ const handleInspectionManagement2 = () => {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
background-color: #fff;
|
||||
color: #303133;
|
||||
border-color: #dcdfe6;
|
||||
}
|
||||
|
||||
.export-btn {
|
||||
background-color: #165dff;
|
||||
border-color: #165dff;
|
||||
}
|
||||
|
||||
/* 选项卡样式 */
|
||||
.tabs-wrapper {
|
||||
background-color: #fff;
|
||||
@ -1087,21 +1065,14 @@ const handleInspectionManagement2 = () => {
|
||||
.filter-actions {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
background-color: #f2f3f5;
|
||||
color: #303133;
|
||||
border-color: #f2f3f5;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.search-btn:hover {
|
||||
background-color: #e5e6eb;
|
||||
color: #303133;
|
||||
border-color: #e5e6eb;
|
||||
.search-btn,
|
||||
.export-btn,
|
||||
.create-btn {
|
||||
height: 36px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 统计卡片样式 */
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
<div class="nav-tab active" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent>
|
||||
|
||||
<!-- 选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
@ -133,7 +130,6 @@
|
||||
<script setup>
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
// 激活的选项卡
|
||||
|
||||
@ -424,6 +424,16 @@
|
||||
<div class="step-item" v-for="(step, index) in formData.steps" :key="index">
|
||||
<div class="step-number">{{ index + 1 }}</div>
|
||||
<el-input v-model="step.content" placeholder="输入试验步骤" />
|
||||
<el-button
|
||||
v-if="formData.steps.length > 1"
|
||||
type="text"
|
||||
size="small"
|
||||
class="delete-step-btn"
|
||||
@click="deleteStep(index)"
|
||||
style="color: #f56c6c"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button type="text" size="small" class="add-step-btn" @click="addStep">添加步骤</el-button>
|
||||
</div>
|
||||
@ -579,6 +589,7 @@ import router from '@/router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { shiyanDetail, shiyanlist, addshiyan, updateshiyan } from '@/api/zhinengxunjian/shiyan/index';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian/index';
|
||||
import { addjiedian } from '@/api/zhinengxunjian/jiedian/index';
|
||||
// 1. 选项卡状态管理
|
||||
const activeTab = ref('plan'); // 默认为"巡检计划"
|
||||
const timeRange = ref('month'); // 统计时间范围:月/周/日
|
||||
@ -839,20 +850,14 @@ const userList = ref([]);
|
||||
const getUsersList = async () => {
|
||||
try {
|
||||
const response = await xunjianUserlist();
|
||||
const userRows =
|
||||
response?.data?.rows && Array.isArray(response.data.rows)
|
||||
? response.data.rows
|
||||
: response?.rows && Array.isArray(response.rows)
|
||||
? response.rows
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
// 适配新接口格式:检查code为200且rows为数组
|
||||
const userRows = response.code === 200 && response.rows && Array.isArray(response.rows) ? response.rows : [];
|
||||
|
||||
userList.value = userRows
|
||||
.filter((item) => item && typeof item === 'object')
|
||||
.map((item, index) => ({
|
||||
label: item.userName || `用户${index + 1}`,
|
||||
value: item.id || `id_${index}`
|
||||
.map((item) => ({
|
||||
label: item.userName || '未知用户',
|
||||
value: String(item.userId || '') // 使用userId作为唯一标识
|
||||
}));
|
||||
|
||||
if (userList.value.length === 0) {
|
||||
@ -933,8 +938,40 @@ const handleSave = async () => {
|
||||
// 编辑模式:调用更新接口
|
||||
response = await updateshiyan(requestData);
|
||||
} else {
|
||||
// 处理步骤数据格式
|
||||
const stepsData = formData.value.steps
|
||||
.filter((step) => step.content.trim())
|
||||
.map((step, index) => ({
|
||||
createTime: new Date().toISOString(),
|
||||
updateTime: new Date().toISOString(),
|
||||
remark: step.content.trim(),
|
||||
status: '1', // 使用数字代码
|
||||
// module值为2(与工单列表的1不同)
|
||||
module: 2,
|
||||
sort: index + 1
|
||||
}));
|
||||
|
||||
// 首先调用addjiedian接口
|
||||
const jiedianResponse = await addjiedian(stepsData);
|
||||
|
||||
if (jiedianResponse.code !== 200) {
|
||||
ElMessage.error('创建步骤失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取返回的ids,实际返回格式中msg字段包含ids字符串
|
||||
let nodeIds = '';
|
||||
if (jiedianResponse.code === 200 && jiedianResponse.msg) {
|
||||
nodeIds = jiedianResponse.msg;
|
||||
} else {
|
||||
ElMessage.warning('未获取到有效的步骤ID');
|
||||
return;
|
||||
}
|
||||
|
||||
// 新增模式:调用添加接口(删除请求参数中的id,避免后端报错)
|
||||
const { id, ...addData } = requestData;
|
||||
// 添加nodeIds字段
|
||||
addData.nodeIds = nodeIds;
|
||||
response = await addshiyan(addData);
|
||||
}
|
||||
|
||||
@ -1041,10 +1078,22 @@ const handleEditRecord = async (row) => {
|
||||
const recordDetail = detailResponse.data.rows?.[0] || detailResponse.data;
|
||||
// 兼容两种数据结构:可能在rows数组中,也可能直接在data中
|
||||
|
||||
// 3. 处理testStep:将逗号分隔的字符串转换为步骤数组
|
||||
// 3. 处理步骤数据:优先从nodes数组中提取
|
||||
const steps = [];
|
||||
if (recordDetail.testStep) {
|
||||
// 拆分字符串(例如 "1. 213,2. 321" → ["1. 213", "2. 321"])
|
||||
// 如果有nodes数组,优先从nodes中提取步骤数据
|
||||
if (recordDetail.nodes && Array.isArray(recordDetail.nodes)) {
|
||||
// 复制nodes数组并按code升序排序
|
||||
const sortedNodes = [...recordDetail.nodes].sort((a, b) => (a.code || 0) - (b.code || 0));
|
||||
// 转换为所需的格式
|
||||
sortedNodes.forEach((node) => {
|
||||
if (node.intendedPurpose && node.intendedPurpose.trim()) {
|
||||
steps.push({ content: node.intendedPurpose.trim() });
|
||||
}
|
||||
});
|
||||
}
|
||||
// 如果nodes中没有数据,回退到从testStep字符串解析
|
||||
else if (recordDetail.testStep) {
|
||||
// 拆分字符串
|
||||
const stepItems = recordDetail.testStep.split(',');
|
||||
stepItems.forEach((stepText) => {
|
||||
// 移除序号前缀(如"1. "),只保留内容
|
||||
@ -1137,6 +1186,17 @@ const addStep = () => {
|
||||
formData.value.steps.push({ content: '' });
|
||||
};
|
||||
|
||||
// 删除步骤
|
||||
const deleteStep = (index) => {
|
||||
// 确保至少保留一个步骤
|
||||
if (formData.value.steps.length <= 1) {
|
||||
ElMessage.warning('至少需要保留一个步骤');
|
||||
return;
|
||||
}
|
||||
// 从数组中删除指定索引的步骤
|
||||
formData.value.steps.splice(index, 1);
|
||||
};
|
||||
|
||||
// 添加新设备
|
||||
const addEquipment = () => {
|
||||
if (newEquipment.value.trim()) {
|
||||
|
||||
@ -482,36 +482,13 @@ const getUsersList = async () => {
|
||||
try {
|
||||
const response = await xunjianUserlist({});
|
||||
if (response.code === 200) {
|
||||
// 从任务数据中提取用户信息
|
||||
const usersMap = new Map(); // 使用Map确保id唯一
|
||||
const tasks = response.rows || [];
|
||||
// 直接从接口返回的用户列表中提取信息
|
||||
const users = response.rows || [];
|
||||
|
||||
tasks.forEach((task) => {
|
||||
// 提取personInfo中的用户信息
|
||||
if (task.personInfo && task.personInfo.id && task.personInfo.userName) {
|
||||
usersMap.set(task.personInfo.id, {
|
||||
id: task.personInfo.id,
|
||||
userName: task.personInfo.userName
|
||||
});
|
||||
}
|
||||
|
||||
// 提取testPlan.persons中的用户信息
|
||||
if (task.testPlan && task.testPlan.persons && Array.isArray(task.testPlan.persons)) {
|
||||
task.testPlan.persons.forEach((person) => {
|
||||
if (person.id && person.userName) {
|
||||
usersMap.set(person.id, {
|
||||
id: person.id,
|
||||
userName: person.userName
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 将Map转换为下拉选择器需要的格式:{ label, value }
|
||||
userList.value = Array.from(usersMap.values()).map((user) => ({
|
||||
label: user.userName, // 显示在下拉框中的文本
|
||||
value: user.id // 选中后的值
|
||||
// 将用户数据转换为所需格式:包含id和userName以适配模板和getUserById函数
|
||||
userList.value = users.map((user) => ({
|
||||
id: user.userId, // 用于标识和查找
|
||||
userName: user.userName // 显示名称
|
||||
}));
|
||||
|
||||
// 调试信息,确认数据格式正确
|
||||
|
||||
@ -807,21 +807,14 @@ const planList = ref([]);
|
||||
const getUsersList = async () => {
|
||||
try {
|
||||
const response = await xunjianUserlist();
|
||||
|
||||
const userRows =
|
||||
response?.data?.rows && Array.isArray(response.data.rows)
|
||||
? response.data.rows
|
||||
: response?.rows && Array.isArray(response.rows)
|
||||
? response.rows
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
// 适配新接口格式:检查code为200且rows为数组
|
||||
const userRows = response.code === 200 && response.rows && Array.isArray(response.rows) ? response.rows : [];
|
||||
|
||||
userList.value = userRows
|
||||
.filter((item) => item && typeof item === 'object')
|
||||
.map((item, index) => ({
|
||||
label: item.userName || `用户${index + 1}`,
|
||||
value: item.id || `id_${index}`
|
||||
.map((item) => ({
|
||||
label: item.userName || '未知用户',
|
||||
value: String(item.userId || '') // 使用userId作为唯一标识
|
||||
}));
|
||||
|
||||
if (userList.value.length === 0) {
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
<div class="nav-tab" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<TitleComponent title="工单管理模块" subtitle="发起工单任务,跟踪流程记录和执行情况"></TitleComponent>
|
||||
|
||||
<!-- 子选项卡 -->
|
||||
<div class="tabs-wrapper">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
@ -220,7 +217,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import { gongdanlist, gongdanDetail, updategongdan, delgongdan } from '@/api/zhinengxunjian/gongdan/index';
|
||||
// 导入Element Plus的Steps组件
|
||||
import { ElSteps, ElStep } from 'element-plus';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user