src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -1,304 +1,489 @@
<template>
   <FormDialog
      v-model="dialogVisitable"
      :title="operationType === 'add' ? '新增保养任务' : '编辑保养任务'"
      width="800px"
      :operation-type="operationType"
      @confirm="submitForm"
      @cancel="cancel"
      @close="cancel"
   >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
         <el-row>
            <el-col :span="12">
               <el-form-item label="设备名称" prop="taskId">
                  <el-select v-model="form.taskId" @change="setDeviceModel" filterable>
                     <el-option
                        v-for="(item, index) in deviceOptions"
                        :key="index"
                        :label="item.deviceName"
                        :value="item.id"
                     ></el-option>
                  </el-select>
               </el-form-item>
            </el-col>
            <el-col :span="12">
               <el-form-item label="规格型号">
                  <el-input
                     v-model="form.deviceModel"
                     placeholder="请输入规格型号"
                     disabled
                  />
               </el-form-item>
            </el-col>
         </el-row>
         <el-row>
            <el-col :span="12">
               <el-form-item label="录入人" prop="inspector">
                  <el-select
                     v-model="form.inspector"
                     filterable
                     default-first-option
                     :reserve-keyword="false"
                     placeholder="请选择"
                     clearable
                  >
                     <el-option
                        v-for="item in userList"
                        :label="item.nickName"
                        :value="item.userId"
                        :key="item.userId"
                     />
                  </el-select>
               </el-form-item>
            </el-col>
            <el-col :span="12">
               <el-form-item label="登记时间" prop="registrationDate">
                  <el-date-picker
                     v-model="form.registrationDate"
                     type="date"
                     placeholder="选择登记日期"
                     format="YYYY-MM-DD"
                     value-format="YYYY-MM-DD"
                     style="width: 100%"
                  />
               </el-form-item>
            </el-col>
         </el-row>
         <el-row>
            <el-col :span="12">
               <el-form-item label="任务频率" prop="frequencyType">
                  <el-select v-model="form.frequencyType" placeholder="请选择" clearable>
                     <el-option label="每日" value="DAILY"/>
                     <el-option label="每周" value="WEEKLY"/>
                     <el-option label="每月" value="MONTHLY"/>
                     <el-option label="季度" value="QUARTERLY"/>
                  </el-select>
               </el-form-item>
            </el-col>
            <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
               <el-form-item label="日期" prop="frequencyDetail">
                  <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm"
                                          value-format="HH:mm" />
               </el-form-item>
            </el-col>
            <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
               <el-form-item label="日期" prop="frequencyDetail">
                  <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%">
                     <el-option label="周一" value="MON"/>
                     <el-option label="周二" value="TUE"/>
                     <el-option label="周三" value="WED"/>
                     <el-option label="周四" value="THU"/>
                     <el-option label="周五" value="FRI"/>
                     <el-option label="周六" value="SAT"/>
                     <el-option label="周日" value="SUN"/>
                  </el-select>
                  <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm"
                                          value-format="HH:mm"  style="width: 50%"/>
               </el-form-item>
            </el-col>
            <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
               <el-form-item label="日期" prop="frequencyDetail">
                  <el-date-picker
                     v-model="form.frequencyDetail"
                     type="datetime"
                     clearable
                     placeholder="选择开始日期"
                     format="DD,HH:mm"
                     value-format="DD,HH:mm"
                  />
               </el-form-item>
            </el-col>
            <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
               <el-form-item label="日期" prop="frequencyDetail">
                  <el-date-picker
                     v-model="form.frequencyDetail"
                     type="datetime"
                     clearable
                     placeholder="选择开始日期"
                     format="MM,DD,HH:mm"
                     value-format="MM,DD,HH:mm"
                  />
               </el-form-item>
            </el-col>
         </el-row>
         <el-row>
            <el-col :span="12">
               <el-form-item label="备注" prop="remarks">
                  <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
               </el-form-item>
            </el-col>
         </el-row>
      </el-form>
   </FormDialog>
  <FormDialog
    v-model="dialogVisitable"
    :title="operationType === 'add' ? '新增保养任务' : '编辑保养任务'"
    width="800px"
    :operation-type="operationType"
    @confirm="submitForm"
    @cancel="cancel"
    @close="cancel"
  >
    <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
      <el-row>
        <el-col :span="12">
          <el-form-item label="所属区域" prop="areaId">
            <el-tree-select
              v-model="form.areaId"
              :data="areaOptions"
              :props="areaTreeProps"
              node-key="id"
              value-key="id"
              check-strictly
              clearable
              filterable
              placeholder="请选择所属区域"
              style="width: 100%"
              @change="handleAreaChange"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="设备名称" prop="deviceLedgerIds">
            <el-select
              v-model="form.deviceLedgerIds"
              filterable
              clearable
              multiple
              collapse-tags
              collapse-tags-tooltip
              placeholder="请选择设备"
              style="width: 100%"
              @change="setDeviceModels"
            >
              <el-option
                v-for="item in deviceOptions"
                :key="item.id"
                :label="item.deviceName"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="规格型号">
            <el-input
              v-model="form.deviceModel"
              placeholder="自动带出规格型号"
              disabled
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="录入人" prop="inspector">
            <el-select
              v-model="form.inspector"
              filterable
              default-first-option
              :reserve-keyword="false"
              placeholder="请选择"
              clearable
            >
              <el-option
                v-for="item in userList"
                :key="item.userId"
                :label="item.nickName"
                :value="item.userId"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="登记时间" prop="registrationDate">
            <el-date-picker
              v-model="form.registrationDate"
              type="date"
              placeholder="选择登记日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="width: 100%"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="任务频率" prop="frequencyType">
            <el-select v-model="form.frequencyType" placeholder="请选择" clearable>
              <el-option label="每日" value="DAILY" />
              <el-option label="每周" value="WEEKLY" />
              <el-option label="每月" value="MONTHLY" />
              <el-option label="季度" value="QUARTERLY" />
              <el-option label="每年" value="YEARLY" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12" v-if="form.frequencyType === 'DAILY'">
          <el-form-item label="日期" prop="frequencyDetail">
            <el-time-picker
              v-model="form.frequencyDetail"
              placeholder="选择时间"
              format="HH:mm"
              value-format="HH:mm"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" v-if="form.frequencyType === 'WEEKLY'">
          <el-form-item label="日期" prop="frequencyDetail">
            <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%">
              <el-option label="周一" value="MON" />
              <el-option label="周二" value="TUE" />
              <el-option label="周三" value="WED" />
              <el-option label="周四" value="THU" />
              <el-option label="周五" value="FRI" />
              <el-option label="周六" value="SAT" />
              <el-option label="周日" value="SUN" />
            </el-select>
            <el-time-picker
              v-model="form.time"
              placeholder="选择时间"
              format="HH:mm"
              value-format="HH:mm"
              style="width: 50%"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" v-if="form.frequencyType === 'MONTHLY'">
          <el-form-item label="日期" prop="frequencyDetail">
            <el-date-picker
              v-model="form.frequencyDetail"
              type="datetime"
              clearable
              placeholder="选择开始日期"
              format="DD,HH:mm"
              value-format="DD,HH:mm"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY'">
          <el-form-item label="日期" prop="frequencyDetail">
            <el-date-picker
              v-model="form.frequencyDetail"
              type="datetime"
              clearable
              placeholder="选择开始日期"
              format="MM,DD,HH:mm"
              value-format="MM,DD,HH:mm"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" v-if="form.frequencyType === 'YEARLY'">
          <el-form-item label="日期" prop="frequencyDetail">
            <el-date-picker
              v-model="form.frequencyDetail"
              type="datetime"
              clearable
              placeholder="选择开始日期"
              format="MM,DD,HH:mm"
              value-format="MM,DD,HH:mm"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="备注" prop="remarks">
            <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </FormDialog>
</template>
<script setup>
import { getCurrentInstance, reactive, ref, toRefs } from "vue";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { reactive, ref, getCurrentInstance, toRefs } from "vue";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import {
  getDeviceAreaTree,
  getDeviceAreaTreeWithDevices,
} from "@/api/equipmentManagement/deviceArea";
import {
  deviceMaintenanceTaskAdd,
  deviceMaintenanceTaskEdit,
} from "@/api/equipmentManagement/upkeep";
import { getCurrentDate } from "@/utils/index.js";
import useUserStore from "@/store/modules/user.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const { proxy } = getCurrentInstance();
const emit = defineEmits(["closeDia"]);
const dialogVisitable = ref(false);
const operationType = ref('add');
const operationType = ref("add");
const areaOptions = ref([]);
const deviceOptions = ref([]);
const userList = ref([]);
const areaTreeProps = {
  label: "areaName",
  children: "children",
};
const userStore = useUserStore();
const data = reactive({
   form: {
      taskId: undefined,
      taskName: undefined,
      // 录入人:单选一个用户 id
      inspector: undefined,
      remarks: '',
      frequencyType: '',
      frequencyDetail: '',
      week: '',
      time: '',
      deviceModel: undefined, // 规格型号
      registrationDate: ''
   },
   rules: {
      taskId: [{ required: true, message: "请选择设备", trigger: "change" },],
      inspector: [{ required: true, message: "请选择录入人", trigger: "blur" },],
      registrationDate: [{ required: true, message: "请选择登记时间", trigger: "change" }]
   }
})
const { form, rules } = toRefs(data)
const userList = ref([])
const loadDeviceName = async () => {
   const { data } = await getDeviceLedger();
   deviceOptions.value = data;
const data = reactive({
  form: {
    areaId: undefined,
    taskId: undefined,
    taskIds: [],
    taskIdsStr: undefined,
    deviceLedgerIds: [],
    deviceLedgerIdsStr: undefined,
    taskName: undefined,
    inspector: undefined,
    remarks: "",
    frequencyType: "",
    frequencyDetail: "",
    week: "",
    time: "",
    deviceModel: undefined,
    registrationDate: "",
  },
  rules: {
    areaId: [{ required: true, message: "请选择所属区域", trigger: "change" }],
    deviceLedgerIds: [{ required: true, message: "请选择设备", trigger: "change" }],
    inspector: [{ required: true, message: "请选择录入人", trigger: "change" }],
    registrationDate: [{ required: true, message: "请选择登记时间", trigger: "change" }],
  },
});
const { form, rules } = toRefs(data);
const loadAreaTree = async () => {
  const { data } = await getDeviceAreaTree();
  areaOptions.value = Array.isArray(data) ? data : [];
};
// 选择设备时,回填设备名称(taskName)和规格型号(deviceModel)
const setDeviceModel = (id) => {
   const option = deviceOptions.value.find((item) => item.id === id);
   if (option) {
      form.value.taskId = option.id;
      form.value.taskName = option.deviceName;
      form.value.deviceModel = option.deviceModel;
   }
}
const normalizeIdList = (value) => {
  if (Array.isArray(value)) {
    return value
      .map((item) => Number(item))
      .filter((item) => Number.isFinite(item));
  }
  if (typeof value === "string") {
    return value
      .split(",")
      .map((item) => Number(item.trim()))
      .filter((item) => Number.isFinite(item));
  }
  if (value !== undefined && value !== null && value !== "") {
    const numericValue = Number(value);
    return Number.isFinite(numericValue) ? [numericValue] : [];
  }
  return [];
};
// 打开弹框
const openDialog = async (type, row) => {
   dialogVisitable.value = true
   operationType.value = type
   // 重置表单
   resetForm();
   // 加载用户列表
   userListNoPageByTenantId().then((res) => {
      userList.value = res.data;
   });
   // 加载设备列表
   await loadDeviceName();
   if (type === 'edit' && row) {
      form.value = { ...row }
      // 编辑时用接口返回的 registrantId 回显录入人
      if (row.registrantId) {
         form.value.inspector = row.registrantId
      }
const getNodeDevices = (node) => {
  const candidates = [
    node?.deviceList,
    node?.devices,
    node?.deviceLedgerList,
    node?.deviceLedgers,
    node?.ledgerList,
    node?.ledgers,
  ];
  return candidates.find((item) => Array.isArray(item)) || [];
};
      // 如果有设备ID,自动设置设备信息
      if (form.value.taskId) {
         setDeviceModel(form.value.taskId);
      }
   } else if (type === 'add') {
      // 新增时设置登记日期为当天
      form.value.registrationDate = getCurrentDate();
      // 新增时设置录入人为当前登录账户
      form.value.inspector = userStore.id;
   }
}
const normalizeDevice = (item) => ({
  ...item,
  id: item.id ?? item.deviceLedgerId,
  deviceName: item.deviceName ?? item.name,
  deviceModel: item.deviceModel ?? item.model,
});
// 关闭对话框
const cancel = () => {
   resetForm()
   dialogVisitable.value = false
   emit('closeDia')
}
const collectDevices = (node) => {
  const currentDevices = getNodeDevices(node).map(normalizeDevice);
  const childDevices = (node?.children || []).flatMap((child) =>
    collectDevices(child)
  );
  const deviceMap = new Map();
  [...currentDevices, ...childDevices].forEach((item) => {
    if (item?.id !== undefined && item?.id !== null) {
      deviceMap.set(Number(item.id), item);
    }
  });
  return Array.from(deviceMap.values());
};
// 重置表单函数
const findAreaNode = (nodes, areaId) => {
  for (const node of nodes || []) {
    if (Number(node.id) === Number(areaId)) {
      return node;
    }
    const target = findAreaNode(node.children, areaId);
    if (target) {
      return target;
    }
  }
  return null;
};
const loadDevicesByArea = async (areaId) => {
  if (!areaId) {
    deviceOptions.value = [];
    return;
  }
  const { data } = await getDeviceAreaTreeWithDevices();
  const treeData = Array.isArray(data) ? data : [];
  const currentNode = findAreaNode(treeData, areaId);
  deviceOptions.value = currentNode ? collectDevices(currentNode) : [];
};
const syncDeviceFields = (deviceIds) => {
  const selectedIds = normalizeIdList(deviceIds);
  const selectedDevices = selectedIds
    .map((deviceId) =>
      deviceOptions.value.find((item) => Number(item.id) === Number(deviceId))
    )
    .filter(Boolean);
  form.value.deviceLedgerIds = selectedIds;
  form.value.deviceLedgerIdsStr = selectedIds.join(",");
  form.value.taskIds = [...selectedIds];
  form.value.taskIdsStr = selectedIds.join(",");
  form.value.taskId = selectedIds[0];
  form.value.taskName = selectedDevices
    .map((item) => item.deviceName)
    .filter(Boolean)
    .join(",");
  form.value.deviceModel = selectedDevices
    .map((item) => item.deviceModel || "-")
    .join(",");
};
const setDeviceModels = (deviceIds) => {
  syncDeviceFields(deviceIds);
};
const handleAreaChange = async (areaId) => {
  form.value.taskId = undefined;
  form.value.taskIds = [];
  form.value.taskIdsStr = undefined;
  form.value.deviceLedgerIds = [];
  form.value.deviceLedgerIdsStr = undefined;
  form.value.taskName = undefined;
  form.value.deviceModel = undefined;
  await loadDevicesByArea(areaId);
};
const resetForm = () => {
   if (proxy.$refs.formRef) {
      proxy.$refs.formRef.resetFields()
   }
   // 重置表单数据确保设备信息正确重置
   form.value = {
      taskId: undefined,
      taskName: undefined,
      inspector: undefined,
      inspector: undefined,
      remarks: '',
      frequencyType: '',
      frequencyDetail: '',
      week: '',
      time: '',
      deviceModel: undefined,
      registrationDate: ''
   }
}
  if (proxy.$refs.formRef) {
    proxy.$refs.formRef.resetFields();
  }
  form.value = {
    areaId: undefined,
    taskId: undefined,
    taskIds: [],
    taskIdsStr: undefined,
    deviceLedgerIds: [],
    deviceLedgerIdsStr: undefined,
    taskName: undefined,
    inspector: undefined,
    remarks: "",
    frequencyType: "",
    frequencyDetail: "",
    week: "",
    time: "",
    deviceModel: undefined,
    registrationDate: "",
  };
};
// 提交表单
const openDialog = async (type, row) => {
  dialogVisitable.value = true;
  operationType.value = type;
  resetForm();
  userListNoPageByTenantId().then((res) => {
    userList.value = res.data;
  });
  await loadAreaTree();
  if (type === "edit" && row) {
    form.value = {
      ...form.value,
      ...row,
      inspector: row.registrantId || row.inspector,
    };
    form.value.deviceLedgerIds = normalizeIdList(
      row.deviceLedgerIds ??
        row.deviceLedgerIdsStr ??
        row.taskIds ??
        row.taskIdsStr ??
        row.taskId
    );
    form.value.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(",");
    form.value.taskIds = [...form.value.deviceLedgerIds];
    form.value.taskIdsStr = form.value.deviceLedgerIds.join(",");
    form.value.taskId = form.value.deviceLedgerIds[0];
    if (form.value.areaId) {
      await loadDevicesByArea(form.value.areaId);
      syncDeviceFields(form.value.deviceLedgerIds);
    }
  } else {
    form.value.registrationDate = getCurrentDate();
    form.value.inspector = userStore.id;
    deviceOptions.value = [];
  }
};
const cancel = () => {
  resetForm();
  dialogVisitable.value = false;
  emit("closeDia");
};
const submitForm = () => {
   proxy.$refs["formRef"].validate(async valid => {
      if (valid) {
         try {
            const payload = { ...form.value }
            // 不再向后端传保养人字段,仅使用接口要求的 registrant / registrantId
            // 根据选择的"录入人"设置 registrant / registrantId
            if (payload.inspector) {
               const selectedUser = userList.value.find(
                  (u) => String(u.userId) === String(payload.inspector)
               )
               if (selectedUser) {
                  payload.registrantId = selectedUser.userId
                  payload.registrant = selectedUser.nickName
               }
            }
            delete payload.inspector
            delete payload.inspectorIds
            if (payload.frequencyType === 'WEEKLY') {
               let frequencyDetail = ''
               frequencyDetail = payload.week + ',' + payload.time
               payload.frequencyDetail = frequencyDetail
            }
            // 录入日期:直接使用表单里的 registrationDate 字段
            // 一些默认状态字段
            if (payload.status === undefined || payload.status === null || payload.status === '') {
               payload.status = '0' // 默认状态,可按实际枚举调整
            }
            payload.active = true
            payload.deleted = 0
            if (operationType.value === 'edit') {
               await deviceMaintenanceTaskEdit(payload)
            } else {
               await deviceMaintenanceTaskAdd(payload)
            }
            cancel()
            proxy.$modal.msgSuccess('提交成功')
         } catch (error) {
            proxy.$modal.msgError('提交失败,请重试')
         }
      }
   })
}
defineExpose({ openDialog })
  proxy.$refs.formRef.validate(async (valid) => {
    if (!valid) {
      return;
    }
    try {
      syncDeviceFields(form.value.deviceLedgerIds);
      const payload = { ...form.value };
      if (payload.inspector) {
        const selectedUser = userList.value.find(
          (item) => String(item.userId) === String(payload.inspector)
        );
        if (selectedUser) {
          payload.registrantId = selectedUser.userId;
          payload.registrant = selectedUser.nickName;
        }
      }
      delete payload.inspector;
      delete payload.inspectorIds;
      if (payload.frequencyType === "WEEKLY") {
        payload.frequencyDetail = `${payload.week},${payload.time}`;
      }
      if (
        payload.status === undefined ||
        payload.status === null ||
        payload.status === ""
      ) {
        payload.status = "0";
      }
      payload.deviceLedgerIds = [...form.value.deviceLedgerIds];
      payload.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(",");
      payload.taskIds = [...form.value.deviceLedgerIds];
      payload.taskIdsStr = form.value.deviceLedgerIds.join(",");
      payload.taskId = form.value.deviceLedgerIds[0];
      payload.taskName = form.value.taskName;
      payload.deviceModel = form.value.deviceModel || "-";
      payload.active = true;
      payload.deleted = 0;
      if (operationType.value === "edit") {
        await deviceMaintenanceTaskEdit(payload);
      } else {
        await deviceMaintenanceTaskAdd(payload);
      }
      cancel();
      proxy.$modal.msgSuccess("提交成功");
    } catch (error) {
      proxy.$modal.msgError("提交失败,请重试");
    }
  });
};
defineExpose({ openDialog });
</script>
<style scoped>
</style>
<style scoped></style>