<template>
|
<u-popup :show="dialogVisitable"
|
mode="center"
|
:round="12"
|
:zIndex="900"
|
@close="cancel">
|
<view class="popup-content">
|
<view class="popup-title">{{ operationType === "add" ? "新增巡检任务" : "编辑巡检任务" }}</view>
|
<view class="form-body">
|
<view class="form-item">
|
<text class="label">设备名称</text>
|
<picker mode="selector"
|
:range="deviceOptions"
|
range-key="deviceName"
|
:value="deviceIndex"
|
@change="onDeviceChange">
|
<view class="picker-value">{{ form.taskName || "请选择设备" }}</view>
|
</picker>
|
</view>
|
<view class="form-item">
|
<text class="label">巡检人</text>
|
<view class="picker-value inspector-picker"
|
@click="openInspectorPopup">
|
<text>{{ inspectorText || "请选择巡检人" }}</text>
|
<u-icon name="arrow-right"
|
size="14"
|
color="#999" />
|
</view>
|
<view class="inspector-tags"
|
v-if="form.inspector?.length">
|
<view v-for="userId in form.inspector"
|
:key="userId"
|
class="inspector-tag"
|
@click="toggleInspector(userId)">
|
<text>{{ getUserName(userId) }}</text>
|
<u-icon name="close"
|
size="11"
|
color="#1677ff" />
|
</view>
|
</view>
|
</view>
|
<view class="form-item">
|
<text class="label">备注</text>
|
<u-textarea v-model="form.remarks"
|
placeholder="请输入备注"
|
:height="80"
|
count />
|
</view>
|
<view class="form-item">
|
<text class="label">任务频率</text>
|
<picker mode="selector"
|
:range="frequencyOptions"
|
range-key="label"
|
:value="frequencyIndex"
|
@change="onFrequencyChange">
|
<view class="picker-value">{{ currentFrequencyLabel || "请选择任务频率" }}</view>
|
</picker>
|
</view>
|
<view class="form-item"
|
v-if="form.frequencyType === 'DAILY'">
|
<text class="label">时间</text>
|
<picker mode="time"
|
:value="form.frequencyDetail || '08:00'"
|
@change="onDailyTimeChange">
|
<view class="picker-value">{{ form.frequencyDetail || "请选择时间" }}</view>
|
</picker>
|
</view>
|
<view class="form-item"
|
v-if="form.frequencyType === 'WEEKLY'">
|
<text class="label">每周日期</text>
|
<picker mode="selector"
|
:range="weekOptions"
|
range-key="label"
|
:value="weekIndex"
|
@change="onWeekChange">
|
<view class="picker-value">{{ currentWeekLabel || "请选择星期" }}</view>
|
</picker>
|
</view>
|
<view class="form-item"
|
v-if="form.frequencyType === 'WEEKLY'">
|
<text class="label">每周时间</text>
|
<picker mode="time"
|
:value="form.time || '08:00'"
|
@change="onWeekTimeChange">
|
<view class="picker-value">{{ form.time || "请选择时间" }}</view>
|
</picker>
|
</view>
|
<view class="form-item"
|
v-if="form.frequencyType === 'MONTHLY'">
|
<text class="label">每月日期与时间</text>
|
<picker mode="date"
|
fields="day"
|
:value="monthlyDate"
|
@change="onMonthlyDateChange">
|
<view class="picker-value">{{ monthlyDate || "请选择日期" }}</view>
|
</picker>
|
<picker mode="time"
|
:value="monthlyTime"
|
@change="onMonthlyTimeChange">
|
<view class="picker-value">{{ monthlyTime || "请选择时间" }}</view>
|
</picker>
|
</view>
|
</view>
|
<view class="popup-footer">
|
<u-button @click="cancel">取消</u-button>
|
<u-button type="primary"
|
@click="submitForm">保存</u-button>
|
</view>
|
</view>
|
</u-popup>
|
<u-popup :show="showInspectorPopup"
|
mode="bottom"
|
:round="16"
|
:zIndex="1100"
|
@close="closeInspectorPopup">
|
<view class="inspector-popup">
|
<view class="inspector-header">
|
<text class="inspector-title">选择巡检人</text>
|
</view>
|
<scroll-view scroll-y
|
class="inspector-list">
|
<view v-for="item in userList"
|
:key="item.userId"
|
class="inspector-row"
|
@click="toggleInspector(item.userId)">
|
<text class="inspector-name">{{ item.nickName }}</text>
|
<u-icon v-if="form.inspector.includes(item.userId)"
|
name="checkmark-circle-fill"
|
color="#1677ff"
|
size="20" />
|
<u-icon v-else
|
name=""
|
color="#d5d8de"
|
size="20" />
|
</view>
|
</scroll-view>
|
<view class="inspector-footer">
|
<u-button @click="closeInspectorPopup">取消</u-button>
|
<u-button type="primary"
|
@click="confirmInspector">确定</u-button>
|
</view>
|
</view>
|
</u-popup>
|
</template>
|
|
<script setup>
|
import { computed, reactive, ref } from "vue";
|
import useUserStore from "@/store/modules/user";
|
import { addOrEditTimingTask } from "@/api/inspectionManagement/index.js";
|
import { userListNoPageByTenantId } from "@/api/system/user.js";
|
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
|
|
const emit = defineEmits(["closeDia"]);
|
const userStore = useUserStore();
|
const dialogVisitable = ref(false);
|
const operationType = ref("add");
|
const deviceOptions = ref([]);
|
const userList = ref([]);
|
const showInspectorPopup = ref(false);
|
|
const defaultForm = () => ({
|
id: undefined,
|
taskId: undefined,
|
taskName: "",
|
inspector: [],
|
inspectorIds: "",
|
remarks: "",
|
frequencyType: "",
|
frequencyDetail: "",
|
week: "",
|
time: "",
|
registrantId: undefined,
|
});
|
|
const form = reactive(defaultForm());
|
|
const frequencyOptions = [
|
{ label: "每日", value: "DAILY" },
|
{ label: "每周", value: "WEEKLY" },
|
{ label: "每月", value: "MONTHLY" },
|
];
|
|
const weekOptions = [
|
{ label: "周一", value: "MON" },
|
{ label: "周二", value: "TUE" },
|
{ label: "周三", value: "WED" },
|
{ label: "周四", value: "THU" },
|
{ label: "周五", value: "FRI" },
|
{ label: "周六", value: "SAT" },
|
{ label: "周日", value: "SUN" },
|
];
|
|
const monthlyDate = ref("");
|
const monthlyTime = ref("");
|
|
const deviceIndex = computed(() => {
|
const index = deviceOptions.value.findIndex(item => item.id === form.taskId);
|
return index >= 0 ? index : 0;
|
});
|
|
const frequencyIndex = computed(() => {
|
const index = frequencyOptions.findIndex(item => item.value === form.frequencyType);
|
return index >= 0 ? index : 0;
|
});
|
|
const weekIndex = computed(() => {
|
const index = weekOptions.findIndex(item => item.value === form.week);
|
return index >= 0 ? index : 0;
|
});
|
|
const currentFrequencyLabel = computed(() => {
|
return frequencyOptions.find(item => item.value === form.frequencyType)?.label || "";
|
});
|
|
const currentWeekLabel = computed(() => {
|
return weekOptions.find(item => item.value === form.week)?.label || "";
|
});
|
|
const inspectorText = computed(() => {
|
if (!form.inspector?.length) return "";
|
const nameMap = new Map(userList.value.map(item => [item.userId, item.nickName]));
|
return form.inspector.map(id => nameMap.get(id)).filter(Boolean).join("、");
|
});
|
|
const resetForm = () => {
|
Object.assign(form, defaultForm());
|
monthlyDate.value = "";
|
monthlyTime.value = "";
|
showInspectorPopup.value = false;
|
};
|
|
const loadBaseData = async () => {
|
const [userRes, deviceRes] = await Promise.all([
|
userListNoPageByTenantId(),
|
getDeviceLedger(),
|
]);
|
userList.value = userRes?.data || [];
|
deviceOptions.value = deviceRes?.data || [];
|
};
|
|
const parseWeeklyDetail = detail => {
|
if (!detail || typeof detail !== "string" || !detail.includes(",")) return;
|
const [week, time] = detail.split(",");
|
form.week = week || "";
|
form.time = time || "";
|
};
|
|
const parseMonthlyDetail = detail => {
|
if (!detail || typeof detail !== "string" || !detail.includes(",")) return;
|
const [day, time] = detail.split(",");
|
if (day) monthlyDate.value = `${new Date().getFullYear()}-${new Date().getMonth() + 1 < 10 ? `0${new Date().getMonth() + 1}` : new Date().getMonth() + 1}-${day.padStart(2, "0")}`;
|
if (time) monthlyTime.value = time;
|
};
|
|
const setDeviceModel = id => {
|
const matched = deviceOptions.value.find(item => item.id === id);
|
if (matched) {
|
form.taskId = matched.id;
|
form.taskName = matched.deviceName;
|
}
|
};
|
|
const openDialog = async (type, row) => {
|
operationType.value = type;
|
dialogVisitable.value = true;
|
resetForm();
|
try {
|
await loadBaseData();
|
if (type === "edit" && row) {
|
Object.assign(form, {
|
...defaultForm(),
|
...row,
|
inspector: String(row.inspectorIds || "")
|
.split(",")
|
.map(item => Number(item))
|
.filter(Boolean),
|
});
|
if (form.frequencyType === "WEEKLY") parseWeeklyDetail(form.frequencyDetail);
|
if (form.frequencyType === "MONTHLY") parseMonthlyDetail(form.frequencyDetail);
|
}
|
} catch (error) {
|
uni.showToast({
|
title: "初始化失败",
|
icon: "none",
|
});
|
}
|
};
|
|
const onDeviceChange = e => {
|
const index = Number(e?.detail?.value || 0);
|
const selected = deviceOptions.value[index];
|
if (!selected) return;
|
setDeviceModel(selected.id);
|
};
|
|
const getUserName = userId => {
|
const user = userList.value.find(item => item.userId === userId);
|
return user?.nickName || "";
|
};
|
|
const openInspectorPopup = () => {
|
showInspectorPopup.value = true;
|
};
|
|
const closeInspectorPopup = () => {
|
showInspectorPopup.value = false;
|
};
|
|
const toggleInspector = userId => {
|
if (form.inspector.includes(userId)) {
|
form.inspector = form.inspector.filter(id => id !== userId);
|
} else {
|
form.inspector = [...form.inspector, userId];
|
}
|
};
|
|
const confirmInspector = () => {
|
showInspectorPopup.value = false;
|
};
|
|
const onFrequencyChange = e => {
|
const index = Number(e?.detail?.value || 0);
|
const selected = frequencyOptions[index];
|
form.frequencyType = selected?.value || "";
|
form.frequencyDetail = "";
|
form.week = "";
|
form.time = "";
|
monthlyDate.value = "";
|
monthlyTime.value = "";
|
};
|
|
const onDailyTimeChange = e => {
|
form.frequencyDetail = e?.detail?.value || "";
|
};
|
|
const onWeekChange = e => {
|
const index = Number(e?.detail?.value || 0);
|
const selected = weekOptions[index];
|
form.week = selected?.value || "";
|
};
|
|
const onWeekTimeChange = e => {
|
form.time = e?.detail?.value || "";
|
};
|
|
const onMonthlyDateChange = e => {
|
monthlyDate.value = e?.detail?.value || "";
|
};
|
|
const onMonthlyTimeChange = e => {
|
monthlyTime.value = e?.detail?.value || "";
|
};
|
|
const validateForm = () => {
|
if (!form.taskId) {
|
uni.showToast({ title: "请选择设备", icon: "none" });
|
return false;
|
}
|
if (!form.inspector.length) {
|
uni.showToast({ title: "请选择巡检人", icon: "none" });
|
return false;
|
}
|
if (!form.frequencyType) {
|
uni.showToast({ title: "请选择任务频率", icon: "none" });
|
return false;
|
}
|
if (form.frequencyType === "DAILY" && !form.frequencyDetail) {
|
uni.showToast({ title: "请选择时间", icon: "none" });
|
return false;
|
}
|
if (form.frequencyType === "WEEKLY" && (!form.week || !form.time)) {
|
uni.showToast({ title: "请选择每周日期和时间", icon: "none" });
|
return false;
|
}
|
if (form.frequencyType === "MONTHLY" && (!monthlyDate.value || !monthlyTime.value)) {
|
uni.showToast({ title: "请选择每月日期和时间", icon: "none" });
|
return false;
|
}
|
return true;
|
};
|
|
const buildFrequencyDetail = () => {
|
if (form.frequencyType === "WEEKLY") return `${form.week},${form.time}`;
|
if (form.frequencyType === "MONTHLY") {
|
const day = monthlyDate.value.split("-")[2] || "";
|
return `${day},${monthlyTime.value}`;
|
}
|
return form.frequencyDetail;
|
};
|
|
const submitForm = async () => {
|
if (!validateForm()) return;
|
try {
|
const userInfo = await userStore.getInfo();
|
const payload = {
|
...form,
|
inspectorIds: form.inspector.join(","),
|
frequencyDetail: buildFrequencyDetail(),
|
registrantId: userInfo?.user?.userId,
|
};
|
delete payload.inspector;
|
delete payload.week;
|
delete payload.time;
|
await addOrEditTimingTask(payload);
|
uni.showToast({
|
title: "提交成功",
|
icon: "success",
|
});
|
cancel();
|
} catch (error) {
|
uni.showToast({
|
title: "提交失败,请重试",
|
icon: "none",
|
});
|
}
|
};
|
|
const cancel = () => {
|
dialogVisitable.value = false;
|
resetForm();
|
emit("closeDia");
|
};
|
|
defineExpose({ openDialog });
|
</script>
|
|
<style scoped lang="scss">
|
:deep(.uni-picker-container) {
|
z-index: 1200 !important;
|
}
|
|
.popup-content {
|
width: 88vw;
|
max-height: 80vh;
|
background: #fff;
|
border-radius: 20rpx;
|
overflow: hidden;
|
}
|
|
.popup-title {
|
text-align: center;
|
font-size: 32rpx;
|
color: #1f1f1f;
|
font-weight: 600;
|
padding: 24rpx 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.form-body {
|
padding: 24rpx;
|
max-height: 56vh;
|
overflow-y: auto;
|
}
|
|
.form-item {
|
margin-bottom: 20rpx;
|
}
|
|
.label {
|
display: block;
|
margin-bottom: 10rpx;
|
font-size: 24rpx;
|
color: #666;
|
}
|
|
.picker-value {
|
min-height: 72rpx;
|
background: #f7f8fa;
|
border-radius: 12rpx;
|
padding: 0 20rpx;
|
display: flex;
|
align-items: center;
|
color: #333;
|
font-size: 26rpx;
|
}
|
|
.inspector-picker {
|
justify-content: space-between;
|
}
|
|
.inspector-tags {
|
display: flex;
|
flex-wrap: wrap;
|
margin-top: 10rpx;
|
gap: 10rpx;
|
}
|
|
.inspector-tag {
|
display: flex;
|
align-items: center;
|
gap: 8rpx;
|
background: #edf3ff;
|
color: #1677ff;
|
font-size: 22rpx;
|
border-radius: 999rpx;
|
padding: 6rpx 14rpx;
|
}
|
|
.popup-footer {
|
display: flex;
|
gap: 16rpx;
|
padding: 20rpx 24rpx 24rpx;
|
border-top: 1rpx solid #f0f0f0;
|
}
|
|
.inspector-popup {
|
background: #fff;
|
border-radius: 24rpx 24rpx 0 0;
|
overflow: hidden;
|
max-height: 70vh;
|
padding-bottom: env(safe-area-inset-bottom);
|
}
|
|
.inspector-header {
|
padding: 24rpx;
|
text-align: center;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.inspector-title {
|
color: #1f1f1f;
|
font-size: 30rpx;
|
font-weight: 600;
|
}
|
|
.inspector-list {
|
max-height: 46vh;
|
padding: 0 24rpx;
|
}
|
|
.inspector-row {
|
min-height: 82rpx;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
border-bottom: 1rpx solid #f5f5f5;
|
}
|
|
.inspector-name {
|
font-size: 26rpx;
|
color: #333;
|
}
|
|
.inspector-footer {
|
display: flex;
|
gap: 16rpx;
|
padding: 20rpx 24rpx 24rpx;
|
}
|
</style>
|