完成巡检计划

This commit is contained in:
Zy
2026-04-21 14:43:21 +08:00
parent df20099dfd
commit 48852a33ec
7 changed files with 952 additions and 109 deletions

View File

@@ -12,7 +12,7 @@ export interface PlanVO {
/**
* 巡检人员ID多个用逗号分隔
*/
inspectorIds: string | number;
inspectorIds: string;
/**
* 执行周期,如:开始日期-结束日期
@@ -32,12 +32,12 @@ export interface PlanVO {
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting: number;
inspectSetting: string;
/**
* 计划路线,多个用逗号分隔
*/
routeIds: string | number;
routeIds: string;
/**
* 状态0-关闭1-开启
@@ -53,6 +53,23 @@ export interface PlanVO {
* 执行周期具体日期
*/
executeDay: string;
/** 巡检人员信息 */
inspectorList: {
'userId': string;
'userName': string;
'nickName': string;
'phonenumber': number;
}[];
/** 巡检路线 */
routeList: {
'id': string;
'routeName': string;
'description': string;
'totalPoints': string;
'estimatedTime': number;
'routeStatus': string;
}[];
}
export interface PlanForm extends BaseEntity {
@@ -69,7 +86,7 @@ export interface PlanForm extends BaseEntity {
/**
* 巡检人员ID多个用逗号分隔
*/
inspectorIds?: string | number;
inspectorIds?: string;
/**
* 执行周期,如:开始日期-结束日期
@@ -89,12 +106,12 @@ export interface PlanForm extends BaseEntity {
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting?: number;
inspectSetting?: string;
/**
* 计划路线,多个用逗号分隔
*/
routeIds?: string | number;
routeIds?: string;
/**
* 状态0-关闭1-开启
@@ -121,7 +138,7 @@ export interface PlanQuery extends PageQuery {
/**
* 巡检人员ID多个用逗号分隔
*/
inspectorIds?: string | number;
inspectorIds?: string;
/**
* 执行周期,如:开始日期-结束日期
@@ -141,12 +158,12 @@ export interface PlanQuery extends PageQuery {
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting?: number;
inspectSetting?: string;
/**
* 计划路线,多个用逗号分隔
*/
routeIds?: string | number;
routeIds?: string;
/**
* 状态0-关闭1-开启

View File

@@ -0,0 +1,62 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { TaskVO, TaskForm, TaskQuery } from './type';
/**
* 查询巡检任务列表
* @param query
* @returns {*}
*/
export const listTask = (query?: TaskQuery): AxiosPromise<TaskVO[]> => {
return request({
url: '/inspection/task/list',
method: 'get',
params: query
});
};
/**
* 查询巡检任务详细
* @param id
*/
export const getTask = (id: string | number): AxiosPromise<TaskVO> => {
return request({
url: '/inspection/task/' + id,
method: 'get'
});
};
/**
* 新增巡检任务
* @param data
*/
export const addTask = (data: TaskForm) => {
return request({
url: '/inspection/task',
method: 'post',
data: data
});
};
/**
* 修改巡检任务
* @param data
*/
export const updateTask = (data: TaskForm) => {
return request({
url: '/inspection/task',
method: 'put',
data: data
});
};
/**
* 删除巡检任务
* @param id
*/
export const delTask = (id: string | number | Array<string | number>) => {
return request({
url: '/inspection/task/' + id,
method: 'delete'
});
};

View File

@@ -0,0 +1,195 @@
export interface TaskVO {
/**
* 主键ID
*/
id: string | number;
/**
* 巡检任务名称
*/
taskName: string;
/**
* 关联巡检计划ID
*/
planId: string | number;
/**
* 巡检人员ID
*/
inspectorId: string | number;
/**
* 巡检路线ID
*/
routeId: string | number;
/**
* 起止日期
*/
taskTime: string;
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting: number;
/**
* 费用单位
*/
costUnit: string;
/**
* 状态0-待执行1-执行中2-已完成3-已超时
*/
status: string;
/**
* 实际开始时间
*/
actualStartTime: string;
/**
* 实际结束时间
*/
actualEndTime: string;
/**
* 备注
*/
remark: string;
/**
* 提醒时间
*/
remindTime: string;
}
export interface TaskForm extends BaseEntity {
/**
* 主键ID
*/
id?: string | number;
/**
* 巡检任务名称
*/
taskName?: string;
/**
* 关联巡检计划ID
*/
planId?: string | number;
/**
* 巡检人员ID
*/
inspectorId?: string | number;
/**
* 巡检路线ID
*/
routeId?: string | number;
/**
* 起止日期
*/
taskTime?: string;
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting?: number;
/**
* 费用单位
*/
costUnit?: string;
/**
* 状态0-待执行1-执行中2-已完成3-已超时
*/
status?: string;
/**
* 实际开始时间
*/
actualStartTime?: string;
/**
* 实际结束时间
*/
actualEndTime?: string;
/**
* 备注
*/
remark?: string;
/**
* 提醒时间
*/
remindTime?: string;
}
export interface TaskQuery extends PageQuery {
/**
* 巡检任务名称
*/
taskName?: string;
/**
* 关联巡检计划ID
*/
planId?: string | number;
/**
* 巡检人员ID
*/
inspectorId?: string | number;
/**
* 巡检路线ID
*/
routeId?: string | number;
/**
* 起止日期
*/
taskTime?: string;
/**
* 巡检设置0-必须拍照1-可以跳检
*/
inspectSetting?: number;
/**
* 费用单位
*/
costUnit?: string;
/**
* 状态0-待执行1-执行中2-已完成3-已超时
*/
status?: string;
/**
* 实际开始时间
*/
actualStartTime?: string;
/**
* 实际结束时间
*/
actualEndTime?: string;
/**
* 提醒时间
*/
remindTime?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -1,17 +1,18 @@
<template>
<div class="residentBox" @click="choiceResidentFun">
<slot v-if="$slots.default" />
<div v-else class="residentBox" @click="choiceResidentFun">
<div class="defaultbox" v-if="multipleSelection.length === 0">
<span>请选择</span>
<el-icon><Search /></el-icon>
</div>
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
<span>姓名{{ multipleSelection[0] && multipleSelection[0].nickName }}</span>
<span v-show="multipleSelection[0] && multipleSelection[0].phonenumber" class="ml-20px">联系方式{{ multipleSelection[0].phonenumber }}</span>
<span>姓名{{ multipleSelection[0]?.name }}</span>
</div>
</div>
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<el-table @row-click="handleRowClick" ref="multipleTableRef" :data="tableData" border>
<el-table @row-click="handleRowClick" ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" width="55" type="index" />
<el-table-column label="姓名" align="center" prop="nickName" />
@@ -20,17 +21,8 @@
<dict-tag :options="sys_user_sex" :value="row.sex" />
</template>
</el-table-column>
<el-table-column label="角色" align="center" width="85" prop="userType">
<template #default="{ row }">
<dict-tag :options="com_resident_type" :value="row.type" />
</template>
</el-table-column>
<el-table-column label="角色" align="center" width="85" prop="roleName" />
<el-table-column label="手机号码" align="center" prop="phonenumber" />
<el-table-column label="状态" align="center" width="85" prop="status">
<template #default="{ row }">
<dict-tag :options="com_certification_status" :value="row.status" />
</template>
</el-table-column>
</el-table>
<template #footer>
@@ -75,16 +67,31 @@ const props = defineProps({
returnvalue: {
type: String,
default: 'id'
},
titleName: {
type: String,
default: '选择维修人员'
},
userType: {
type: String,
default: 'repair'
},
isMultiple: {
type: Boolean,
default: false
}
});
const { userid } = toRefs(props);
const { userid, titleName, userType, returnvalue } = toRefs(props);
// ✅ 手动设置默认值(替代 withDefaults
const emit = defineEmits<{
change: [value: string | number | tableType];
change: [value: string | number | (string | number)[] | tableType | tableType[]]; // 支持返回数组
}>();
const dialog = ref({
dialogVisible: false,
dialogTitle: '选择维修人员'
dialogTitle: titleName.value
});
const queryParams = ref({
@@ -105,35 +112,30 @@ const multipleTableRef = ref();
const tableData = ref<tableType[]>([]);
const total = ref(0);
const loading = ref(false);
const treedata = ref([]);
// 存储选中项
const multipleSelection = ref<tableType[]>([]);
// 单选点击事件(完全替代 selection-change
const handleRowClick = (row: tableType) => {
multipleTableRef.value?.clearSelection();
multipleTableRef.value?.toggleRowSelection(row, true);
multipleSelection.value = [row];
};
const isMultiple = computed(() => props.isMultiple ?? false);
// 统一回显 userid 选中(安全版)
// 优化 handleUserSelection避免重复查找
const handleUserSelection = () => {
if (!userid.value || !tableData.value.length) return;
const target = tableData.value.find((item) => item.userId == userid.value);
if (target) {
if (target && !multipleSelection.value.some((sel) => sel.id === target.id)) {
multipleSelection.value = [target];
nextTick(() => {
multipleTableRef.value?.clearSelection();
multipleTableRef.value?.toggleRowSelection(target, true);
multipleTableRef.value?.setSelection([target]);
});
}
};
// 监听
// 监听优化:只在 userid 变化时触发
watch(userid, handleUserSelection, { immediate: true });
watch(tableData, handleUserSelection);
watch(tableData, () => {
if (userid.value) handleUserSelection(); // 仅在有 userid 时重新处理
});
// ====================== 方法 ======================
// 打开选择框
@@ -144,13 +146,46 @@ function choiceResidentFun() {
// 获取列表
function getlist() {
loading.value = true;
getUserByRoleKey().then((res) => {
getUserByRoleKey(userType.value)
.then((res) => {
tableData.value = res.data;
total.value = res.total;
})
.catch((error) => {
console.error('获取用户列表失败:', error);
})
.finally(() => {
loading.value = false;
});
}
// ==============================================
// ✅ 新增:处理 selection-change多选专用
// ==============================================
function handleSelectionChange(selection: tableType[]) {
if (isMultiple.value) {
multipleSelection.value = selection;
}
}
// ==============================================
// 最佳单选方案:点击行选中,无报错、无循环、最稳定
// ==============================================
// 优化 handleRowClick避免重复
function handleRowClick(row: tableType) {
if (isMultiple.value) {
const index = multipleSelection.value.findIndex((item) => item.id === row.id);
if (index > -1) {
multipleSelection.value.splice(index, 1);
multipleTableRef.value?.toggleRowSelection(row, false);
} else {
multipleSelection.value.push(row);
multipleTableRef.value?.toggleRowSelection(row, true);
}
} else {
multipleSelection.value = [row];
multipleTableRef.value?.setSelection([row]);
}
}
// 重置查询
function resetQuery() {
queryParams.value = {
@@ -175,21 +210,45 @@ function conback() {
resetQuery();
}
// 确定
// ==============================================
// ✅ 核心修改:根据 returnvalue 返回对应的值
// ==============================================
function confirm() {
dialog.value.dialogVisible = false;
console.log(multipleSelection.value, props.returnvalue);
if (multipleSelection.value.length > 0) {
if (props.returnvalue === 'id') {
emit('change', multipleSelection.value[0].userId);
} else if (props.returnvalue === 'value') {
if (isMultiple.value) {
// 多选
if (returnvalue.value === '*') {
// ✅ 返回整个对象数组
emit('change', multipleSelection.value);
} else {
// 返回指定字段数组
emit(
'change',
multipleSelection.value.map((item) => item[returnvalue.value as keyof tableType])
);
}
} else {
// 单选
if (returnvalue.value === '*') {
// ✅ 返回整个对象
emit('change', multipleSelection.value[0]);
} else {
console.log(multipleSelection.value[0], returnvalue.value);
// 返回指定字段
emit('change', multipleSelection.value[0][returnvalue.value as keyof tableType]);
}
}
}
}
// 初始化
getlist();
defineExpose({
open: () => {
dialog.value.dialogVisible = true;
}
});
</script>
<style scoped lang="scss">

View File

@@ -6,12 +6,27 @@
<div>基本信息</div>
</div>
<div class="bodybox">
<el-form label-width="100px" label-position="right">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="right">
<el-form-item label="巡检计划名称" prop="planName">
<el-input v-model="form.planName" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="巡检人员" prop="inspectorIds">
<el-input v-model="form.inspectorIds" placeholder="请输入"></el-input>
<div class="inspectorIdsBox">
<div v-for="(item, index) in checkoutUserlist" :key="index" class="inspector_items">
<div class="name">{{ item.nickName }}</div>
<i @click="handleDelete" class="deleteaction">
<el-icon><Delete /></el-icon>
</i>
</div>
<RepairUser @change="handleUserChange" returnvalue="*" :is-multiple="true" user-type="inspection" ref="RepairUserRef">
<template #default>
<div @click="handleAddUser" class="inspector_items add flex flex-items-center justify-center">
<el-icon><Plus /></el-icon>
<span class="ml-10px"> 添加 </span>
</div>
</template>
</RepairUser>
</div>
</el-form-item>
<el-form-item label="执行周期">
<el-date-picker
@@ -26,7 +41,7 @@
/>
</el-form-item>
<el-form-item label="任务时间">
<el-select v-model="form.taskTime" placeholder="Select" style="width: 100%">
<el-select v-model="form.taskTime" placeholder="选择任务时间段" style="width: 100%">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<div flex flex-wrap>
@@ -47,7 +62,7 @@
</div>
</el-form-item>
<el-form-item label="提醒时间">
<el-select v-model="form.remindTime" placeholder="Select" style="width: 100%">
<el-select v-model="form.remindTime" placeholder="请选择" style="width: 100%">
<el-option v-for="item in remindTimeoptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
@@ -58,13 +73,13 @@
</el-radio-group>
</el-form-item>
<el-form-item label="计划路线">
<el-select v-model="form.routeIds" placeholder="Select" style="width: 100%">
<el-option v-for="item in routeIdsoptions" :key="item.value" :label="item.label" :value="item.value" />
<el-select @change="handlChangeMap" v-model="form.routeIds" placeholder="请选择" style="width: 100%">
<el-option v-for="item in planlist" :key="item.value" :label="item.routeName" :value="item.id" />
</el-select>
<div class="mapbox"></div>
<div class="mapbox" id="PlanMapBox"></div>
</el-form-item>
<el-form-item>
<el-button type="primary">提交</el-button>
<el-button type="primary" @click="submit">提交</el-button>
<el-button @click="routeback">返回</el-button>
</el-form-item>
</el-form>
@@ -74,38 +89,52 @@
</template>
<script setup lang="ts">
import { listRoute } from '@/api/system/InspectionRoute';
import RepairUser from '@/components/Holder/repairUser.vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { numToWeek } from '@/utils/time';
import { Delete } from '@element-plus/icons-vue';
import { ref } from 'vue';
const route = useRoute();
import AMapLoader from '@amap/amap-jsapi-loader';
import { addPlan, getPlan, updatePlan } from '@/api/system/InspectionPlan';
const route = useRoute();
const router = useRouter();
const form = ref({
taskTime: 0,
remindTime: '',
startTime: '',
endTime: '',
inspectSetting: '',
routeIds: ''
id: null,
planName: '', // 巡检计划名称
inspectorIds: '', // 巡检人员
taskTime: '', // 任务时间段
executeCycle: '', // 执行周期
executeDay: '', // 执行周期具体的周几
remindTime: '', // 提醒时间
routeIds: '', // 计划路线id
inspectSetting: '1' // 巡检设置
});
const rules = ref({
planName: [{ required: true, message: '请输入巡检计划名称', trigger: 'blur' }],
inspectorIds: [{ required: true, message: '请选择巡检人员', trigger: 'blur' }],
executeCycle: [{ required: true, message: '请输入执行周期', trigger: 'blur' }],
routeIds: [{ required: true, message: '请选择路线', trigger: 'blur' }]
});
// 执行周期
const taskDateSplit = ' - ';
const taskDate = ref([]);
function handleTime(val) {
console.log(val);
function handleTime(val: string[]) {
taskDate.value = val;
form.value.startTime = val[0];
form.value.endTime = val[1];
form.value.executeCycle = `${val[0]}${taskDateSplit}${val[1]}`;
}
// 选择周几
const checkoutWeek = ref([]);
function checkoutWeekFun(val: number) {
if (!checkoutWeek.value.includes(val)) {
checkoutWeek.value.push(val);
form.value.executeDay = checkoutWeek.value.join(',');
} else {
checkoutWeek.value = checkoutWeek.value.filter((item) => item !== val);
}
console.log(val);
}
// 任务时间
@@ -118,47 +147,162 @@ const options = ref([
// 提醒时间
const remindTimeoptions = ref([
{
value: 0,
value: 10,
label: '任务开始前10分钟'
},
{
value: 1,
value: 15,
label: '任务开始前15分钟'
},
{
value: 2,
value: 20,
label: '任务开始前30分钟'
}
]);
// 计划路线
const routeIdsoptions = ref([
{
value: 0,
label: '常规巡更计划1'
},
{
value: 1,
label: '常规巡更计划2'
},
{
value: 2,
label: '常规巡更计划3'
}
]);
// 巡检计划id
const editid = ref(null);
function init() {
// 初始化
// 路线列表
const planlist = ref([]);
async function init() {
const res = await listRoute();
planlist.value = res.rows;
if (route.query.id) {
editid.value = route.query.id;
getPlan(editid.value).then((res) => {
form.value = {
id: res.data.id,
planName: res.data.planName, // 巡检计划名称
inspectorIds: res.data.inspectorIds, // 巡检人员
taskTime: res.data.taskTime, // 任务时间段
executeCycle: res.data.executeCycle, // 执行周期
executeDay: res.data.executeDay, // 执行周期具体的周几
remindTime: res.data.remindTime, // 提醒时间
routeIds: res.data.routeIds, // 计划路线id
inspectSetting: String(res.data.inspectSetting) // 巡检设置
};
taskDate.value = res.data.executeCycle.split(taskDateSplit);
checkoutWeek.value = res.data.executeDay
.split(',')
.map((item) => Number(item))
.filter((item) => item);
handlChangeMap(res.data.routeIds);
});
}
}
init();
// 选择 巡检人员
const RepairUserRef = ref<InstanceType<typeof RepairUser>>();
function handleAddUser() {
RepairUserRef.value.open();
}
const checkoutUserlist = ref([]);
function handleUserChange(val) {
checkoutUserlist.value = val;
}
function handleDelete(id) {
checkoutUserlist.value = checkoutUserlist.value.filter((item) => item.userId !== id);
}
// 返回
function routeback() {
router.back();
}
const AMapLib = ref(null);
const map = ref(null);
const mapReady = ref(false);
const markerlist = [];
function handlChangeMap(val) {
map.value.remove(markerlist);
if (val) {
const find = planlist.value.find((item) => item.id === val);
if (find) {
if (find.points && find.points.length > 0) {
find.points.forEach((item, index) => {
const lnglat = item.location.split(',').map(Number);
const marker = new AMapLib.value.Marker({
position: new AMapLib.value.LngLat(lnglat[0], lnglat[1]), //经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: item.pointName,
content: `
<div style="display:flex;align-items:center;justify-content:center;width:30px;height:30px;line-height:18px;border-radius:50%;background-color:rgba(26,117,255,0.3);">
<div
style=" width: 20px;
border-radius: 50%;
height: 20px;
line-height: 20px;
background-color: rgba(26,117,255,1);
color: #ffffff;
font-size: 20px;
text-align: center;"
>${index + 1}</div>
</div>`
});
//将创建的点标记添加到已有的地图实例:
map.value.add(marker);
markerlist.push(marker);
});
}
if (find.pathPoints && typeof find.pathPoints === 'string') {
const path = JSON.parse(find.pathPoints);
console.log(path);
//创建 Polyline 实例
const polyline = new AMapLib.value.Polyline({
path: path,
strokeWeight: 2, //线条宽度
strokeColor: 'red', //线条颜色
lineJoin: 'round' //折线拐点连接处样式
});
map.value.add(polyline);
markerlist.push(polyline);
}
map.value.setFitView();
}
}
}
onMounted(async () => {
await nextTick();
window._AMapSecurityConfig = { securityJsCode: '09534b3534d8da53968529a9ce164118' };
AMapLoader.load({
key: '8e302fe1be5f4db62bc734db23dca149',
version: '2.0',
plugins: ['AMap.Scale', 'AMap.Marker']
}).then(async (AMap) => {
AMapLib.value = AMap;
map.value = new AMap.Map('PlanMapBox', {
viewMode: '3D',
zoom: 11,
center: [116.397428, 39.90923]
});
mapReady.value = true;
});
});
const formRef = ref();
function submit() {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
form.value.inspectorIds = checkoutUserlist.value.map((item) => item.userId).join(',');
if (editid.value) {
updatePlan(form.value).then(() => {
ElMessage.success('编辑成功');
routeback();
});
} else {
addPlan(form.value).then(() => {
ElMessage.success('添加成功');
routeback();
});
}
}
});
}
</script>
<style scoped lang="scss">
@@ -171,6 +315,46 @@ function routeback() {
margin: 0 auto;
margin-top: 20px;
}
.inspectorIdsBox {
display: flex;
flex-wrap: wrap;
align-items: center;
.inspector_items {
width: 120px;
height: 40px;
line-height: 40px;
margin: 5px;
text-align: center;
border-radius: 5px;
background-color: #ddeaff;
display: flex;
align-items: center;
justify-content: center;
padding: 0 2px;
.name {
overflow: hidden;
text-overflow: ellipsis;
text-wrap: nowrap;
}
&.add {
background-color: #ddeaff25;
border: 1px dashed #ccc;
cursor: pointer;
&:hover {
background-color: rgba(221, 234, 255, 0.199);
border-color: #44a0ff;
color: #44a0ff;
}
}
.deleteaction {
margin-left: 10px;
cursor: pointer;
&:hover {
color: red;
}
}
}
}
.week-items {
width: 90px;
height: 30px;
@@ -178,7 +362,7 @@ function routeback() {
border-radius: 5px;
cursor: pointer;
margin: 10px 5px;
background-color: #ccc;
border: 1px solid #ccc;
color: #000;
display: flex;
align-items: center;
@@ -192,6 +376,7 @@ function routeback() {
&.active {
color: rgba(26, 117, 255, 1);
background-color: rgba(26, 117, 255, 0.15);
border: none;
}
}

View File

@@ -1,5 +1,5 @@
<template>
<div class="p-2">
<div class="h-full flex flex-col p-2">
<Pageheader></Pageheader>
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
@@ -17,7 +17,7 @@
</div>
</transition>
<el-card shadow="never">
<el-card class="flex-1" shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
@@ -38,13 +38,25 @@
<el-table v-loading="loading" border :data="planList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="巡检计划名称" align="center" prop="planName" />
<el-table-column label="巡检人员" align="center" prop="inspectorIds" />
<el-table-column label="巡检人员" align="center" prop="inspectorNames" show-overflow-tooltip />
<el-table-column label="执行周期" align="center" prop="executeCycle" />
<el-table-column label="执行星期" align="center">
<template #default="scope">
<span v-for="(item, index) in scope.row.executeDayNames" :key="index" class="pl-5px">{{ numToWeek(item) }}</span>
</template>
</el-table-column>
<el-table-column label="任务时间" align="center" prop="taskTime" />
<el-table-column label="巡检设置0-必须拍照1-可以跳检" align="center" prop="inspectSetting" />
<el-table-column label="计划路线" align="center" prop="routeIds" />
<el-table-column label="状态0-关闭1-开启" align="center" prop="status" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="巡检设置" align="center" prop="inspectSetting">
<template #default="scope">
<DictTag :options="com_inspection_plan_setting" :value="scope.row.inspectSetting"></DictTag>
</template>
</el-table-column>
<el-table-column label="计划路线" align="center" prop="routeNames" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" active-text="关闭" inactive-text="开启"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
@@ -65,10 +77,18 @@
<script setup name="Plan" lang="ts">
import { listPlan, getPlan, delPlan, addPlan, updatePlan } from '@/api/system/InspectionPlan/index';
import { PlanVO, PlanQuery, PlanForm } from '@/api/system/InspectionPlan/type';
import { numToWeek } from '@/utils/time';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_inspection_plan_setting } = toRefs<any>(proxy?.useDict('com_inspection_plan_setting'));
const planList = ref<PlanVO[]>([]);
interface planlistType extends PlanVO {
routeNames?: string;
inspectorNames?: string;
executeDayNames?: number[];
}
const planList = ref<planlistType[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
@@ -124,6 +144,15 @@ const getList = async () => {
loading.value = true;
const res = await listPlan(queryParams.value);
planList.value = res.rows;
planList.value.forEach((item) => {
item.routeNames = item.routeList.map((item) => item.routeName).join(',');
item.inspectorNames = item.inspectorList.map((item2) => item2.nickName).join(',');
item.executeDayNames = item.executeDay
.split(',')
.sort((a, b) => Number(a) - Number(b))
.map((item) => Number(item));
console.log(item.executeDayNames);
});
total.value = res.total;
loading.value = false;
};
@@ -163,14 +192,14 @@ const router = useRouter();
/** 新增按钮操作 */
const handleAdd = () => {
router.push({
path: '/tool/addInspectionPlan'
path: '/inspection/addPlan'
});
};
/** 修改按钮操作 */
const handleUpdate = async (row?: PlanVO) => {
router.push({
path: '/tool/addInspectionPlan',
path: '/inspection/addPlan',
query: {
id: row.id
}
@@ -197,7 +226,7 @@ const submitForm = () => {
/** 删除按钮操作 */
const handleDelete = async (row?: PlanVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除巡检计划编号为"' + _ids + '"的数据项').finally(() => (loading.value = false));
await proxy?.$modal.confirm('是否确认删除巡检计划?').finally(() => (loading.value = false));
await delPlan(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
@@ -218,3 +247,8 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.el-table {
height: calc(100% - 80px);
}
</style>

View File

@@ -1,12 +1,303 @@
<template>
<div class="p-2 h-full flex flex-col">
<Pageheader></Pageheader>
<div class="flex-1 color-gray flex h-full font-size-6 flex-center">系统还在维护中敬请期待...</div>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="执行状态" prop="taskName">
<el-input v-model="queryParams.taskName" placeholder="请输入巡检任务名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="巡检任务名称" prop="taskName">
<el-input v-model="queryParams.taskName" placeholder="请输入巡检任务名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="实际开始时间" prop="actualStartTime">
<el-date-picker
clearable
v-model="queryParams.actualStartTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择实际开始时间"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:task:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:task:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:task:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键ID" align="center" prop="id" v-if="true" />
<el-table-column label="巡检任务名称" align="center" prop="taskName" />
<el-table-column label="关联巡检计划ID" align="center" prop="planId" />
<el-table-column label="巡检人员ID" align="center" prop="inspectorId" />
<el-table-column label="巡检路线ID" align="center" prop="routeId" />
<el-table-column label="起止日期" align="center" prop="taskTime" />
<el-table-column label="巡检设置0-必须拍照1-可以跳检" align="center" prop="inspectSetting" />
<el-table-column label="费用单位" align="center" prop="costUnit" />
<el-table-column label="状态0-待执行1-执行中2-已完成3-已超时" align="center" prop="status" />
<el-table-column label="实际开始时间" align="center" prop="actualStartTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.actualStartTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="实际结束时间" align="center" prop="actualEndTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.actualEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="提醒时间" align="center" prop="remindTime" />
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:task:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:task:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改巡检任务对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="taskFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="巡检任务名称" prop="taskName">
<el-input v-model="form.taskName" placeholder="请输入巡检任务名称" />
</el-form-item>
<el-form-item label="关联巡检计划ID" prop="planId">
<el-input v-model="form.planId" placeholder="请输入关联巡检计划ID" />
</el-form-item>
<el-form-item label="巡检人员ID" prop="inspectorId">
<el-input v-model="form.inspectorId" placeholder="请输入巡检人员ID" />
</el-form-item>
<el-form-item label="巡检路线ID" prop="routeId">
<el-input v-model="form.routeId" placeholder="请输入巡检路线ID" />
</el-form-item>
<el-form-item label="起止日期" prop="taskTime">
<el-input v-model="form.taskTime" placeholder="请输入起止日期" />
</el-form-item>
<el-form-item label="巡检设置0-必须拍照1-可以跳检" prop="inspectSetting">
<el-input v-model="form.inspectSetting" placeholder="请输入巡检设置0-必须拍照1-可以跳检" />
</el-form-item>
<el-form-item label="费用单位" prop="costUnit">
<el-input v-model="form.costUnit" placeholder="请输入费用单位" />
</el-form-item>
<el-form-item label="实际开始时间" prop="actualStartTime">
<el-date-picker
clearable
v-model="form.actualStartTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择实际开始时间"
>
</el-date-picker>
</el-form-item>
<el-form-item label="实际结束时间" prop="actualEndTime">
<el-date-picker clearable v-model="form.actualEndTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择实际结束时间">
</el-date-picker>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="提醒时间" prop="remindTime">
<el-input v-model="form.remindTime" placeholder="请输入提醒时间" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
</script>
<script setup name="Task" lang="ts">
import { listTask, getTask, delTask, addTask, updateTask } from '@/api/system/InspectionTask/index';
import { TaskVO, TaskQuery, TaskForm } from '@/api/system/InspectionTask/type';
<style scoped lang="scss"></style>
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_inspection_task_status } = toRefs<any>(proxy?.useDict('com_inspection_task_status'));
const taskList = ref<TaskVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const taskFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: TaskForm = {
id: undefined,
taskName: undefined,
planId: undefined,
inspectorId: undefined,
routeId: undefined,
taskTime: undefined,
inspectSetting: undefined,
costUnit: undefined,
status: undefined,
actualStartTime: undefined,
actualEndTime: undefined,
remark: undefined,
remindTime: undefined
};
const data = reactive<PageData<TaskForm, TaskQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
taskName: undefined,
planId: undefined,
inspectorId: undefined,
routeId: undefined,
taskTime: undefined,
inspectSetting: undefined,
costUnit: undefined,
status: undefined,
actualStartTime: undefined,
actualEndTime: undefined,
remindTime: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
taskName: [{ required: true, message: '巡检任务名称不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询巡检任务列表 */
const getList = async () => {
loading.value = true;
const res = await listTask(queryParams.value);
taskList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
taskFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: TaskVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加巡检任务';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: TaskVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getTask(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改巡检任务';
};
/** 提交按钮 */
const submitForm = () => {
taskFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateTask(form.value).finally(() => (buttonLoading.value = false));
} else {
await addTask(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: TaskVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除巡检任务编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delTask(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/task/export',
{
...queryParams.value
},
`task_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>