From a563ea879ef5fb6897e76d2df661e465dce2ab9b Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期一, 01 六月 2026 15:02:27 +0800
Subject: [PATCH] Merge branch 'dev_新疆_大罗素马铃薯new' of http://114.132.189.42:9002/r/product-inventory-management into dev_新疆_大罗素马铃薯new

---
 src/views/equipmentManagement/upkeep/Form/PlanModal.vue |  335 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 335 insertions(+), 0 deletions(-)

diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
new file mode 100644
index 0000000..e44d6af
--- /dev/null
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -0,0 +1,335 @@
+<template>
+  <FormDialog
+    v-model="visible"
+    :title="id ? '缂栬緫璁惧淇濆吇璁″垝' : '鏂板璁惧淇濆吇璁″垝'"
+    width="500px"
+    @confirm="sendForm"
+    @cancel="handleCancel"
+    @close="handleClose"
+  >
+    <el-form :model="form" label-width="100px">
+      <el-form-item label="鎵�灞炲尯鍩�">
+        <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-form-item label="璁惧鍚嶇О">
+        <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-form-item label="瑙勬牸鍨嬪彿">
+        <el-input
+          v-model="form.deviceModel"
+          placeholder="鑷姩甯﹀嚭瑙勬牸鍨嬪彿"
+          disabled
+        />
+      </el-form-item>
+      <el-form-item label="褰曞叆浜�">
+        <el-select
+          v-model="form.createUser"
+          placeholder="璇烽�夋嫨"
+          filterable
+          default-first-option
+          :reserve-keyword="false"
+          clearable
+        >
+          <el-option
+            v-for="item in userList"
+            :key="item.userId"
+            :label="item.nickName"
+            :value="item.userId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item v-if="id" label="淇濅慨鐘舵��">
+        <el-select v-model="form.status">
+          <el-option label="寰呬繚淇�" :value="0" />
+          <el-option label="瀹岀粨" :value="1" />
+          <el-option label="澶辫触" :value="2" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="璁″垝淇濆吇鏃ユ湡">
+        <el-date-picker
+          v-model="form.maintenancePlanTime"
+          style="width: 100%"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="date"
+          placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡"
+          clearable
+        />
+      </el-form-item>
+    </el-form>
+  </FormDialog>
+</template>
+
+<script setup>
+import { nextTick, onMounted, ref, unref } from "vue";
+import dayjs from "dayjs";
+import { ElMessage } from "element-plus";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import useFormData from "@/hooks/useFormData";
+import { userListNoPage } from "@/api/system/user.js";
+import {
+  addUpkeep,
+  editUpkeep,
+  getUpkeepById,
+} from "@/api/equipmentManagement/upkeep";
+import {
+  getDeviceAreaTree,
+  getDeviceAreaTreeWithDevices,
+} from "@/api/equipmentManagement/deviceArea";
+
+defineOptions({
+  name: "璁惧淇濆吇鏂板璁″垝",
+});
+
+const emits = defineEmits(["ok"]);
+
+const id = ref();
+const visible = ref(false);
+const loading = ref(false);
+const areaOptions = ref([]);
+const deviceOptions = ref([]);
+const userList = ref([]);
+const areaTreeProps = {
+  label: "areaName",
+  children: "children",
+};
+
+const { form, resetForm } = useFormData({
+  areaId: undefined,
+  deviceLedgerId: undefined,
+  deviceLedgerIds: [],
+  deviceLedgerIdsStr: undefined,
+  deviceName: undefined,
+  deviceModel: undefined,
+  maintenancePlanTime: undefined,
+  createUser: undefined,
+  status: 0,
+});
+
+const loadAreaTree = async () => {
+  const { data } = await getDeviceAreaTree();
+  areaOptions.value = Array.isArray(data) ? data : [];
+};
+
+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 getNodeDevices = (node) => {
+  const candidates = [
+    node?.deviceList,
+    node?.devices,
+    node?.deviceLedgerList,
+    node?.deviceLedgers,
+    node?.ledgerList,
+    node?.ledgers,
+  ];
+  return candidates.find((item) => Array.isArray(item)) || [];
+};
+
+const normalizeDevice = (item) => ({
+  ...item,
+  id: item.id ?? item.deviceLedgerId,
+  deviceName: item.deviceName ?? item.name,
+  deviceModel: item.deviceModel ?? item.model,
+});
+
+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.deviceLedgerIds = selectedIds;
+  form.deviceLedgerId = selectedIds[0];
+  form.deviceLedgerIdsStr = selectedIds.join(",");
+  form.deviceName = selectedDevices
+    .map((item) => item.deviceName)
+    .filter(Boolean)
+    .join(",");
+  form.deviceModel = selectedDevices
+    .map((item) => item.deviceModel || "-")
+    .join(",");
+};
+
+const setDeviceModels = (deviceIds) => {
+  syncDeviceFields(deviceIds);
+};
+
+const handleAreaChange = async (areaId) => {
+  form.deviceLedgerId = undefined;
+  form.deviceLedgerIds = [];
+  form.deviceLedgerIdsStr = undefined;
+  form.deviceName = undefined;
+  form.deviceModel = undefined;
+  await loadDevicesByArea(areaId);
+};
+
+const setForm = (data) => {
+  form.areaId = data.areaId;
+  form.deviceLedgerIds = normalizeIdList(
+    data.deviceLedgerIds ?? data.deviceLedgerIdsStr ?? data.deviceLedgerId
+  );
+  form.deviceLedgerId = form.deviceLedgerIds[0];
+  form.deviceLedgerIdsStr =
+    data.deviceLedgerIdsStr ?? form.deviceLedgerIds.join(",");
+  form.deviceName = data.deviceName;
+  form.deviceModel = data.deviceModel;
+  form.createUser = Number(data.createUser);
+  form.status = data.status;
+  form.maintenancePlanTime = data.maintenancePlanTime
+    ? dayjs(data.maintenancePlanTime).format("YYYY-MM-DD HH:mm:ss")
+    : undefined;
+};
+
+onMounted(() => {
+  loadAreaTree();
+  userListNoPage().then((res) => {
+    userList.value = res.data;
+  });
+});
+
+const openEdit = async (editId) => {
+  const { data } = await getUpkeepById(editId);
+  id.value = editId;
+  visible.value = true;
+  await nextTick();
+  await loadAreaTree();
+  setForm(data);
+  await loadDevicesByArea(form.areaId);
+  syncDeviceFields(form.deviceLedgerIds);
+};
+
+const sendForm = async () => {
+  loading.value = true;
+  try {
+    syncDeviceFields(form.deviceLedgerIds);
+    const payload = {
+      ...form,
+      deviceLedgerId: form.deviceLedgerIds[0],
+      deviceLedgerIds: [...form.deviceLedgerIds],
+      deviceLedgerIdsStr: form.deviceLedgerIds.join(","),
+      deviceModel: form.deviceModel || "-",
+    };
+    const { code } = id.value
+      ? await editUpkeep({ id: unref(id), ...payload })
+      : await addUpkeep(payload);
+    if (code === 200) {
+      ElMessage.success(`${id.value ? "缂栬緫" : "鏂板"}璁″垝鎴愬姛`);
+      visible.value = false;
+      emits("ok");
+    }
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleCancel = () => {
+  resetForm();
+  visible.value = false;
+};
+
+const handleClose = () => {
+  resetForm();
+  visible.value = false;
+};
+
+const openModal = async () => {
+  id.value = undefined;
+  visible.value = true;
+  await nextTick();
+  await loadAreaTree();
+  deviceOptions.value = [];
+};
+
+defineExpose({
+  openModal,
+  openEdit,
+});
+</script>
+
+<style lang="scss" scoped></style>

--
Gitblit v1.9.3