From 633568cff8a45c9f92aec1ec5edb5a09a3b0d8a4 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期六, 14 三月 2026 13:26:38 +0800
Subject: [PATCH] fix: 隐患地点需要拍照而不是文字描述,需要可预览。
---
src/pages/equipmentManagement/upkeepTask/components/formDia.vue | 659 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 659 insertions(+), 0 deletions(-)
diff --git a/src/pages/equipmentManagement/upkeepTask/components/formDia.vue b/src/pages/equipmentManagement/upkeepTask/components/formDia.vue
new file mode 100644
index 0000000..15fe952
--- /dev/null
+++ b/src/pages/equipmentManagement/upkeepTask/components/formDia.vue
@@ -0,0 +1,659 @@
+<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>
+ <up-input v-model="form.taskName"
+ placeholder="璇疯緭鍏ヤ换鍔″悕绉�"
+ border="none"
+ customStyle="background: #f7f8fa; padding: 0 20rpx; min-height: 72rpx; border-radius: 12rpx;" />
+ </view>
+ <view class="form-item">
+ <text class="label">璁惧</text>
+ <view class="picker-value inspector-picker"
+ @click="openDevicePopup">
+ <text>{{ deviceNamesText || "璇烽�夋嫨璁惧" }}</text>
+ <u-icon name="arrow-right"
+ size="14"
+ color="#999" />
+ </view>
+ <view class="inspector-tags"
+ v-if="form.deviceIds?.length">
+ <view v-for="id in form.deviceIds"
+ :key="id"
+ class="inspector-tag"
+ @click="toggleDevice(id)">
+ <text>{{ getDeviceName(id) }}</text>
+ <u-icon name="close"
+ size="11"
+ color="#1677ff" />
+ </view>
+ </view>
+ </view>
+ <view class="form-item">
+ <text class="label">褰曞叆浜�</text>
+ <picker mode="selector"
+ :range="userList"
+ range-key="nickName"
+ :value="inspectorIndex"
+ @change="onInspectorChange">
+ <view class="picker-value">{{ form.registrant || "璇烽�夋嫨褰曞叆浜�" }}</view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <text class="label">鐧昏鏃堕棿</text>
+ <picker mode="date"
+ :value="form.registrationDate || todayStr"
+ @change="onRegistrationDateChange">
+ <view class="picker-value">{{ form.registrationDate || "璇烽�夋嫨鐧昏鏃堕棿" }}</view>
+ </picker>
+ </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 class="form-item"
+ v-if="form.frequencyType === 'QUARTERLY'">
+ <text class="label">瀛e害鏃ユ湡涓庢椂闂�</text>
+ <picker mode="date"
+ :value="quarterlyDate"
+ @change="onQuarterlyDateChange">
+ <view class="picker-value">{{ quarterlyDate || "璇烽�夋嫨鏃ユ湡" }}</view>
+ </picker>
+ <picker mode="time"
+ :value="quarterlyTime"
+ @change="onQuarterlyTimeChange">
+ <view class="picker-value">{{ quarterlyTime || "璇烽�夋嫨鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <text class="label">澶囨敞</text>
+ <u-textarea v-model="form.remarks"
+ placeholder="璇疯緭鍏ュ娉�"
+ :height="80"
+ count />
+ </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="showDevicePopup"
+ mode="bottom"
+ :round="16"
+ :zIndex="1100"
+ @close="closeDevicePopup">
+ <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 deviceOptions"
+ :key="item.id"
+ class="inspector-row"
+ @click="toggleDevice(item.id)">
+ <text class="inspector-name">{{ item.deviceName }}</text>
+ <u-icon v-if="(form.deviceIds || []).includes(item.id)"
+ 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="closeDevicePopup">纭畾</u-button>
+ </view>
+ </view>
+ </u-popup>
+</template>
+
+<script setup>
+ import { computed, reactive, ref } from "vue";
+ import useUserStore from "@/store/modules/user";
+ import {
+ deviceMaintenanceTaskAdd,
+ deviceMaintenanceTaskEdit,
+ } from "@/api/equipmentManagement/upkeep.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
+ import { getDeviceLedger } from "@/api/equipmentManagement/ledger.js";
+
+ const emit = defineEmits(["closeDia"]);
+ const userStore = useUserStore();
+ const dialogVisitable = ref(false);
+ const operationType = ref("add");
+ const deviceOptions = ref([]);
+ const userList = ref([]);
+ const showDevicePopup = ref(false);
+
+ const todayStr = ref("");
+ try {
+ const d = new Date();
+ todayStr.value = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
+ } catch (e) {}
+
+ const defaultForm = () => ({
+ id: undefined,
+ taskName: "",
+ deviceIds: [],
+ registrantId: undefined,
+ registrant: "",
+ registrationDate: "",
+ remarks: "",
+ frequencyType: "",
+ frequencyDetail: "",
+ week: "",
+ time: "",
+ });
+
+ const form = reactive(defaultForm());
+
+ const frequencyOptions = [
+ { label: "姣忔棩", value: "DAILY" },
+ { label: "姣忓懆", value: "WEEKLY" },
+ { label: "姣忔湀", value: "MONTHLY" },
+ { label: "瀛e害", value: "QUARTERLY" },
+ ];
+
+ 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 quarterlyDate = ref("");
+ const quarterlyTime = ref("");
+
+ 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 inspectorIndex = computed(() => {
+ const index = userList.value.findIndex(item => String(item.userId) === String(form.registrantId));
+ return index >= 0 ? index : 0;
+ });
+
+ const deviceNamesText = computed(() => {
+ if (!form.deviceIds?.length) return "";
+ return form.deviceIds
+ .map(id => getDeviceName(id))
+ .filter(Boolean)
+ .join("銆�");
+ });
+
+ function getDeviceName(id) {
+ const d = deviceOptions.value.find(item => String(item.id) === String(id));
+ return d?.deviceName || "";
+ }
+
+ const resetForm = () => {
+ Object.assign(form, defaultForm());
+ monthlyDate.value = "";
+ monthlyTime.value = "";
+ quarterlyDate.value = "";
+ quarterlyTime.value = "";
+ showDevicePopup.value = false;
+ };
+
+ const normalizeIdList = val => {
+ if (!val) return [];
+ if (Array.isArray(val)) return val.map(v => (Number.isNaN(Number(v)) ? v : Number(v)));
+ if (typeof val === "string") {
+ const s = val.trim();
+ if (s.startsWith("[") && s.endsWith("]")) {
+ try {
+ const arr = JSON.parse(s);
+ return Array.isArray(arr) ? arr : [];
+ } catch {
+ return [];
+ }
+ }
+ return s.split(",").map(v => v.trim()).filter(Boolean).map(v => (Number.isNaN(Number(v)) ? v : Number(v)));
+ }
+ return [];
+ };
+
+ 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) {
+ const y = new Date().getFullYear();
+ const m = new Date().getMonth() + 1;
+ monthlyDate.value = `${y}-${String(m).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
+ }
+ if (time) monthlyTime.value = time;
+ };
+
+ const parseQuarterlyDetail = detail => {
+ if (!detail || typeof detail !== "string") return;
+ const parts = detail.split(",");
+ if (parts.length >= 3) {
+ const [mm, dd, time] = parts;
+ const y = new Date().getFullYear();
+ quarterlyDate.value = `${y}-${String(mm).padStart(2, "0")}-${String(dd).padStart(2, "0")}`;
+ quarterlyTime.value = time || "";
+ }
+ };
+
+ const openDialog = async (type, row) => {
+ operationType.value = type;
+ dialogVisitable.value = true;
+ resetForm();
+ try {
+ const [userRes, deviceRes] = await Promise.all([
+ userListNoPageByTenantId(),
+ getDeviceLedger(),
+ ]);
+ userList.value = userRes?.data || [];
+ deviceOptions.value = deviceRes?.data || [];
+ if (type === "edit" && row) {
+ Object.assign(form, {
+ ...defaultForm(),
+ ...row,
+ deviceIds: normalizeIdList(row.deviceIds ?? row.taskIds ?? row.deviceIds),
+ });
+ if (!form.registrationDate && row.registrationDate) form.registrationDate = row.registrationDate;
+ if (row.registrantId) form.registrantId = row.registrantId;
+ if (row.registrant) form.registrant = row.registrant;
+ if (form.frequencyType === "WEEKLY") parseWeeklyDetail(form.frequencyDetail);
+ if (form.frequencyType === "MONTHLY") parseMonthlyDetail(form.frequencyDetail);
+ if (form.frequencyType === "QUARTERLY") parseQuarterlyDetail(form.frequencyDetail);
+ } else {
+ form.registrationDate = todayStr.value;
+ const userInfo = await userStore.getInfo();
+ if (userInfo?.user?.userId) {
+ form.registrantId = userInfo.user.userId;
+ form.registrant = userInfo.user.nickName || userInfo.user.userName || "";
+ }
+ }
+ } catch (error) {
+ uni.showToast({
+ title: "鍒濆鍖栧け璐�",
+ icon: "none",
+ });
+ }
+ };
+
+ const openDevicePopup = () => {
+ showDevicePopup.value = true;
+ };
+
+ const closeDevicePopup = () => {
+ showDevicePopup.value = false;
+ };
+
+ const toggleDevice = id => {
+ const ids = form.deviceIds || [];
+ if (ids.includes(id)) {
+ form.deviceIds = ids.filter(i => i !== id);
+ } else {
+ form.deviceIds = [...ids, id];
+ }
+ };
+
+ const onInspectorChange = e => {
+ const index = Number(e?.detail?.value ?? 0);
+ const user = userList.value[index];
+ if (user) {
+ form.registrantId = user.userId;
+ form.registrant = user.nickName || "";
+ }
+ };
+
+ const onRegistrationDateChange = e => {
+ form.registrationDate = e?.detail?.value || "";
+ };
+
+ 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 = "";
+ quarterlyDate.value = "";
+ quarterlyTime.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 onQuarterlyDateChange = e => {
+ quarterlyDate.value = e?.detail?.value || "";
+ };
+
+ const onQuarterlyTimeChange = e => {
+ quarterlyTime.value = e?.detail?.value || "";
+ };
+
+ const validateForm = () => {
+ if (!form.taskName?.trim()) {
+ uni.showToast({ title: "璇疯緭鍏ヤ换鍔″悕绉�", icon: "none" });
+ return false;
+ }
+ if (!form.deviceIds?.length) {
+ uni.showToast({ title: "璇烽�夋嫨璁惧", icon: "none" });
+ return false;
+ }
+ if (!form.registrantId && !form.registrant) {
+ uni.showToast({ title: "璇烽�夋嫨褰曞叆浜�", icon: "none" });
+ return false;
+ }
+ if (!form.registrationDate) {
+ 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;
+ }
+ if (form.frequencyType === "QUARTERLY" && (!quarterlyDate.value || !quarterlyTime.value)) {
+ uni.showToast({ title: "璇烽�夋嫨瀛e害鏃ユ湡鍜屾椂闂�", 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}`;
+ }
+ if (form.frequencyType === "QUARTERLY") {
+ const [y, m, d] = (quarterlyDate.value || "").split("-");
+ return `${m},${d},${quarterlyTime.value}`;
+ }
+ return form.frequencyDetail || "";
+ };
+
+ const submitForm = async () => {
+ if (!validateForm()) return;
+ try {
+ const payload = {
+ id: form.id,
+ taskName: form.taskName.trim(),
+ deviceIds: JSON.stringify(form.deviceIds || []),
+ registrantId: form.registrantId,
+ registrant: form.registrant,
+ registrationDate: form.registrationDate,
+ frequencyType: form.frequencyType,
+ frequencyDetail: buildFrequencyDetail(),
+ remarks: form.remarks || "",
+ status: "0",
+ active: true,
+ deleted: 0,
+ };
+ if (operationType.value === "edit" && form.id) {
+ await deviceMaintenanceTaskEdit(payload);
+ } else {
+ delete payload.id;
+ await deviceMaintenanceTaskAdd(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>
--
Gitblit v1.9.3