From a60d21cdda7df7733050315fc6462a70c273fcb4 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 04 二月 2026 17:01:02 +0800
Subject: [PATCH] Merge branch 'dev_new' of http://114.132.189.42:9002/r/product-inventory-APP-before into dev_new

---
 src/pages/safeProduction/emergencyPlanReview/detail.vue |  724 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 724 insertions(+), 0 deletions(-)

diff --git a/src/pages/safeProduction/emergencyPlanReview/detail.vue b/src/pages/safeProduction/emergencyPlanReview/detail.vue
new file mode 100644
index 0000000..6117254
--- /dev/null
+++ b/src/pages/safeProduction/emergencyPlanReview/detail.vue
@@ -0,0 +1,724 @@
+<template>
+  <view class="emergency-plan-detail">
+    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+    <PageHeader :title="isEdit ? '缂栬緫搴旀�ラ妗�' : '鏂板搴旀�ラ妗�'"
+                @back="goBack" />
+    <!-- 琛ㄥ崟鍖哄煙 -->
+    <u-form :model="form"
+            label-width="110"
+            :rules="rules"
+            ref="formRef">
+      <!-- 搴旀�ラ妗堢紪鐮� -->
+      <u-form-item label="搴旀�ラ妗堢紪鐮�"
+                   border-bottom
+                   required
+                   prop="planCode">
+        <up-input v-model="form.planCode"
+                  placeholder="璇疯緭鍏ュ簲鎬ラ妗堢紪鐮�"
+                  clearable />
+      </u-form-item>
+      <!-- 搴旀�ラ妗堝悕绉� -->
+      <u-form-item label="搴旀�ラ妗堝悕绉�"
+                   required
+                   border-bottom
+                   prop="planName">
+        <up-input v-model="form.planName"
+                  placeholder="璇疯緭鍏ュ簲鎬ラ妗堝悕绉�"
+                  clearable />
+      </u-form-item>
+      <!-- 鍙戝竷鐢熸晥鏃堕棿 -->
+      <u-form-item label="鍙戝竷鐢熸晥鏃堕棿"
+                   required
+                   border-bottom
+                   prop="publishTime">
+        <up-input v-model="form.publishTime"
+                  placeholder="璇烽�夋嫨鍙戝竷鐢熸晥鏃堕棿"
+                  readonly
+                  @click="showTime = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showTime = true"></up-icon>
+        </template>
+      </u-form-item>
+      <!-- 棰勬绫诲瀷 -->
+      <u-form-item label="棰勬绫诲瀷"
+                   prop="planType"
+                   required
+                   border-bottom>
+        <u-input v-model="emergencyPlanTypeLabel"
+                 placeholder="璇烽�夋嫨棰勬绫诲瀷"
+                 @click="showPlanTypeActionSheet = true"
+                 readonly />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showPlanTypeActionSheet = true"></up-icon>
+        </template>
+      </u-form-item>
+      <u-form-item label="鏍稿績璐d换浜�"
+                   prop="coreResponsorUserId"
+                   required
+                   border-bottom>
+        <u-input v-model="form.coreResponsorUserName"
+                 placeholder="璇烽�夋嫨鏍稿績璐d换浜�"
+                 @click="showUserActionSheet = true"
+                 readonly />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showUserActionSheet = true"></up-icon>
+        </template>
+      </u-form-item>
+      <!-- 澶囨敞 -->
+      <u-form-item label="澶囨敞"
+                   prop="remark">
+        <up-input v-model="form.remark"
+                  placeholder="璇疯緭鍏ュ娉�"
+                  type="textarea"
+                  rows="3"
+                  clearable />
+      </u-form-item>
+      <!-- 閫傜敤鑼冨洿 -->
+      <u-form-item label="閫傜敤鑼冨洿"
+                   required
+                   prop="applyScope">
+        <view class="checkbox-group">
+          <u-checkbox-group v-model="form.applyScope"
+                            @change="handleApplyScopeChange">
+            <u-checkbox shape="circle"
+                        size="32rpx"
+                        class="checkbox-item"
+                        v-for="(item, index) in applyScopeOptions"
+                        :key="index"
+                        :label="item.label"
+                        :name="item.value">
+            </u-checkbox>
+          </u-checkbox-group>
+        </view>
+      </u-form-item>
+      <!-- 搴旀�ュ缃楠� -->
+      <view class="exec-steps-container">
+        <view class="steps-header">
+          <text class="steps-title">澶勭疆姝ラ鍒楄〃</text>
+          <text class="steps-count">鍏� {{ execStepsList.length }} 涓楠�</text>
+        </view>
+        <view class="steps-list">
+          <view v-for="(step, index) in execStepsList"
+                :key="index"
+                class="exec-step-item">
+            <view class="delete-btn"
+                  @click="removeExecStep(index)">
+              <u-icon name="close"
+                      color="#fff"
+                      size="16" />
+            </view>
+            <view class="step-number">
+              {{ index + 1 }}
+            </view>
+            <view class="step-content">
+              <view class="step-row">
+                <text class="step-label">姝ラ鍚嶇О锛�</text>
+                <u-textarea v-model="step.step"
+                            placeholder="璇疯緭鍏ユ楠ゅ悕绉�"
+                            clearable
+                            border-bottom
+                            class="step-input" />
+              </view>
+              <view class="step-row">
+                <text class="step-label">澶勭疆鎺柦锛�</text>
+                <u-textarea v-model="step.description"
+                            placeholder="璇疯緭鍏ュ叿浣撶殑搴旀�ュ缃帾鏂�"
+                            type="textarea"
+                            clearable
+                            class="step-textarea" />
+              </view>
+            </view>
+          </view>
+        </view>
+        <u-button type="primary"
+                  @click="addExecStep"
+                  class="add-step-btn">
+          <text>娣诲姞姝ラ</text>
+        </u-button>
+      </view>
+    </u-form>
+    <!-- 鍙戝竷鐢熸晥鏃堕棿閫夋嫨鍣� -->
+    <up-datetime-picker :show="showTime"
+                        v-model="currentTime"
+                        @confirm="handleDateConfirm"
+                        @cancel="showTime = false"
+                        mode="date" />
+    <!--棰勬绫诲瀷閫夋嫨鍣� -->
+    <up-action-sheet :show="showPlanTypeActionSheet"
+                     :actions="emergencyPlanTypeOptions"
+                     @select="handlePlanTypeConfirm"
+                     title="閫夋嫨棰勬绫诲瀷" />
+    <!--鏍稿績璐d换浜洪�夋嫨鍣� -->
+    <up-action-sheet :show="showUserActionSheet"
+                     :actions="userList"
+                     @select="handleUserConfirm"
+                     title="閫夋嫨鏍稿績璐d换浜�" />
+  </view>
+  <!-- 搴曢儴鎸夐挳 -->
+  <view class="bottom-buttons">
+    <u-button type="default"
+              size="default"
+              @click="goBack"
+              class="bottom-btn">
+      鍙栨秷
+    </u-button>
+    <u-button type="primary"
+              size="default"
+              @click="submitForm"
+              class="bottom-btn">
+      淇濆瓨
+    </u-button>
+  </view>
+</template>
+
+<script setup>
+  import { ref, onMounted, computed } from "vue";
+  import { onShow } from "@dcloudio/uni-app";
+  import PageHeader from "@/components/PageHeader.vue";
+  import {
+    safeContingencyPlanAdd,
+    safeContingencyPlanUpdate,
+  } from "@/api/safeProduction/emergencyPlanReview";
+  import { userListNoPage } from "@/api/system/user";
+  import { useDict } from "@/utils/dict";
+  import dayjs from "dayjs";
+  // 鏇挎崲 toast 鏂规硶
+  defineOptions({ name: "emergency-plan-detail" });
+  const showToast = message => {
+    uni.showToast({
+      title: message,
+      icon: "none",
+    });
+  };
+
+  // 琛ㄥ崟寮曠敤
+  const formRef = ref();
+
+  // 琛ㄥ崟鏁版嵁
+  const form = ref({
+    id: "",
+    planCode: "",
+    planName: "",
+    publishTime: "",
+    planType: "",
+    coreResponsorUserId: "",
+    coreResponsorUserName: "",
+    remark: "",
+    applyScope: [],
+    execSteps: "",
+  });
+
+  // 搴旀�ュ缃楠ゅ垪琛�
+  const execStepsList = ref([]);
+
+  // 鏃ユ湡鑼冨洿
+  const minDate = new Date("2000-01-01");
+  const maxDate = new Date("2030-12-31");
+  const currentTime = ref(Date.now());
+  // 鐢ㄦ埛鍒楄〃
+  const userList = ref([]);
+
+  // 搴旀�ラ妗堢被鍨嬮�夐」
+  const { emergency_plan_type } = useDict("emergency_plan_type");
+  const emergencyPlanTypeOptions = computed(() => {
+    return (
+      emergency_plan_type?.value.map(item => ({
+        value: item.value,
+        name: item.label,
+      })) || []
+    );
+  });
+
+  // 搴旀�ラ妗堢被鍨嬫爣绛�
+  const emergencyPlanTypeLabel = ref("");
+
+  // 閫傜敤鑼冨洿閫夐」
+  const applyScopeOptions = [
+    { value: "all", label: "鍏ㄤ綋鍛樺伐" },
+    { value: "manager", label: "绠$悊灞�" },
+    { value: "hr", label: "浜轰簨閮ㄩ棬" },
+    { value: "finance", label: "璐㈠姟閮ㄩ棬" },
+    { value: "tech", label: "鎶�鏈儴闂�" },
+  ];
+
+  // 鏄惁涓虹紪杈戞ā寮�
+  const isEdit = ref(false);
+
+  // ActionSheet 鏄剧ず鐘舵��
+  const showPlanTypeActionSheet = ref(false);
+  const showUserActionSheet = ref(false);
+  const showTime = ref(false);
+
+  // 鍒濆鍖栨暟鎹�
+  const initData = () => {
+    const emergencyPlan = uni.getStorageSync("emergencyPlan") || {};
+    if (emergencyPlan.id) {
+      // 缂栬緫妯″紡
+      isEdit.value = true;
+      form.value = {
+        id: emergencyPlan.id,
+        planCode: emergencyPlan.planCode || "",
+        planName: emergencyPlan.planName || "",
+        publishTime: emergencyPlan.publishTime || "",
+        planType: emergencyPlan.planType || "",
+        coreResponsorUserId: emergencyPlan.coreResponsorUserId || "",
+        coreResponsorUserName: emergencyPlan.coreResponsorUserName || "",
+        remark: emergencyPlan.remark || "",
+        applyScope: emergencyPlan.applyScope
+          ? emergencyPlan.applyScope.split(",")
+          : [],
+        execSteps: emergencyPlan.execSteps || "",
+      };
+      currentTime.value = new Date(emergencyPlan.publishTime).getTime();
+      // 璁剧疆棰勬绫诲瀷鏍囩
+      const planTypeItem = emergencyPlanTypeOptions.value.find(
+        item => item.value === emergencyPlan.planType
+      );
+      emergencyPlanTypeLabel.value = planTypeItem ? planTypeItem.name : "";
+      console.log(form.value.applyScope, form.value.applyScope);
+      // 鍒濆鍖栧簲鎬ュ缃楠�
+      initExecSteps(emergencyPlan.execSteps);
+    } else {
+      // 鏂板妯″紡
+      isEdit.value = false;
+      form.value = {
+        planCode: "",
+        planName: "",
+        publishTime: new Date().toISOString().split("T")[0],
+        planType: "",
+        coreResponsorUserId: "",
+        coreResponsorUserName: "",
+        remark: "",
+        applyScope: [],
+        execSteps: "",
+      };
+      emergencyPlanTypeLabel.value = "";
+      execStepsList.value = [];
+      addExecStep();
+    }
+  };
+  const handleApplyScopeChange = e => {
+    // form.value.applyScope = e;
+    console.log(e, "e");
+    console.log(form.value.applyScope, "form.value.applyScope");
+  };
+
+  // 鍒濆鍖栧簲鎬ュ缃楠�
+  const initExecSteps = execSteps => {
+    if (execSteps) {
+      try {
+        execStepsList.value = JSON.parse(execSteps);
+      } catch (e) {
+        execStepsList.value = [];
+      }
+    } else {
+      execStepsList.value = [];
+    }
+    if (execStepsList.value.length === 0) {
+      addExecStep();
+    }
+  };
+
+  // 娣诲姞搴旀�ュ缃楠�
+  const addExecStep = () => {
+    const stepNumber = execStepsList.value.length + 1;
+    execStepsList.value.push({
+      step: `姝ラ${stepNumber}`,
+      description: "",
+    });
+  };
+
+  // 鍒犻櫎搴旀�ュ缃楠�
+  const removeExecStep = index => {
+    if (execStepsList.value.length > 1) {
+      execStepsList.value.splice(index, 1);
+    } else {
+      showToast("鑷冲皯淇濈暀涓�涓楠�");
+    }
+  };
+
+  // 鑾峰彇鐢ㄦ埛鍒楄〃
+  const getUserList = () => {
+    userListNoPage()
+      .then(res => {
+        userList.value = res.data.map(item => ({
+          value: item.userId,
+          name: item.nickName,
+        }));
+      })
+      .catch(() => {
+        showToast("鑾峰彇鐢ㄦ埛鍒楄〃澶辫触");
+      });
+  };
+
+  // 鏃ユ湡閫夋嫨纭
+  const handleDateConfirm = e => {
+    form.value.publishTime = dayjs(e.value).format("YYYY-MM-DD");
+    showTime.value = false;
+  };
+
+  // 棰勬绫诲瀷閫夋嫨纭
+  const handlePlanTypeConfirm = e => {
+    form.value.planType = e.value;
+    const selectedType = emergencyPlanTypeOptions.value.find(
+      item => item.value === e.value
+    );
+    if (selectedType) {
+      emergencyPlanTypeLabel.value = selectedType.name;
+    }
+    showPlanTypeActionSheet.value = false;
+  };
+
+  // 鐢ㄦ埛閫夋嫨纭
+  const handleUserConfirm = e => {
+    form.value.coreResponsorUserId = e.value;
+    const selectedUser = userList.value.find(user => user.value === e.value);
+    if (selectedUser) {
+      form.value.coreResponsorUserName = selectedUser.name;
+    }
+    showUserActionSheet.value = false;
+  };
+
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  // 琛ㄥ崟楠岃瘉瑙勫垯
+  const rules = {
+    planCode: [
+      {
+        required: true,
+        message: "璇疯緭鍏ュ簲鎬ラ妗堢紪鐮�",
+        trigger: ["submit", "blur"],
+      },
+    ],
+    planName: [
+      {
+        required: true,
+        message: "璇疯緭鍏ュ簲鎬ラ妗堝悕绉�",
+        trigger: ["submit", "blur"],
+      },
+    ],
+    publishTime: [
+      {
+        required: true,
+        message: "璇烽�夋嫨鍙戝竷鐢熸晥鏃堕棿",
+        trigger: ["submit", "change"],
+      },
+    ],
+    planType: [
+      {
+        required: true,
+        message: "璇烽�夋嫨棰勬绫诲瀷",
+        trigger: ["submit", "change"],
+      },
+    ],
+    coreResponsorUserId: [
+      {
+        required: true,
+        message: "璇烽�夋嫨鏍稿績璐d换浜�",
+        trigger: ["submit", "change"],
+      },
+    ],
+    applyScope: [
+      {
+        required: true,
+        message: "璇烽�夋嫨閫傜敤鑼冨洿",
+        trigger: ["submit", "change"],
+      },
+    ],
+  };
+
+  // 鎻愪氦琛ㄥ崟
+  const submitForm = async () => {
+    // 楠岃瘉琛ㄥ崟蹇呭~椤�
+    if (!formRef.value) return;
+
+    const valid = await formRef.value.validate();
+    if (!valid) {
+      return;
+    }
+
+    // 楠岃瘉搴旀�ュ缃楠�
+    for (let i = 0; i < execStepsList.value.length; i++) {
+      const step = execStepsList.value[i];
+      if (!step.step || !step.step.trim()) {
+        showToast(`绗�${i + 1}鏉℃楠ょ殑"姝ラ"涓嶈兘涓虹┖`);
+        return;
+      }
+      if (!step.description || !step.description.trim()) {
+        showToast(`绗�${i + 1}鏉℃楠ょ殑"鎺柦"涓嶈兘涓虹┖`);
+        return;
+      }
+    }
+
+    // 灏嗗簲鎬ュ缃楠よ浆鎹负JSON瀛楃涓�
+    form.value.execSteps = JSON.stringify(execStepsList.value);
+
+    // 澶勭悊閫傜敤鑼冨洿
+    form.value.applyScope = form.value.applyScope.join(",");
+
+    showLoadingToast("淇濆瓨涓�...");
+
+    try {
+      if (isEdit.value) {
+        // 缂栬緫妯″紡
+        const res = await safeContingencyPlanUpdate(form.value);
+        if (res.code === 200) {
+          showToast("鏇存柊鎴愬姛");
+          setTimeout(() => {
+            uni.navigateBack();
+          }, 1000);
+        } else {
+          showToast(res.msg || "鏇存柊澶辫触");
+        }
+      } else {
+        // 鏂板妯″紡
+        const res = await safeContingencyPlanAdd(form.value);
+        if (res.code === 200) {
+          showToast("娣诲姞鎴愬姛");
+          setTimeout(() => {
+            uni.navigateBack();
+          }, 1000);
+        } else {
+          showToast(res.msg || "娣诲姞澶辫触");
+        }
+      }
+    } catch (error) {
+      console.error("鎻愪氦澶辫触:", error);
+      showToast("鎻愪氦澶辫触锛岃閲嶈瘯");
+    } finally {
+      closeToast();
+    }
+  };
+
+  // 鏄剧ず鍔犺浇鎻愮ず
+  const showLoadingToast = message => {
+    uni.showLoading({
+      title: message,
+      mask: true,
+    });
+  };
+
+  // 鍏抽棴鎻愮ず
+  const closeToast = () => {
+    uni.hideLoading();
+  };
+
+  onMounted(() => {
+    initData();
+    getUserList();
+  });
+
+  onShow(() => {
+    initData();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+  .emergency-plan-detail {
+    min-height: 100vh;
+    background: #f8f9fa;
+    padding-bottom: 100px;
+  }
+
+  .form-section {
+  }
+
+  .checkbox-group {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16px;
+  }
+
+  .checkbox-item {
+    margin-right: 16px;
+  }
+
+  .select-container {
+    position: relative;
+    width: 100%;
+  }
+
+  .select-container .up-input {
+    width: 100%;
+    border: 1px solid #e4e7ed;
+    border-radius: 8px;
+    padding: 12px 16px;
+    background-color: #ffffff;
+  }
+
+  .exec-steps-container {
+    padding: 20px;
+    background-color: #fff;
+  }
+
+  .steps-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+    padding-bottom: 12px;
+    border-bottom: 1px solid #e4e7ed;
+  }
+
+  .steps-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .steps-count {
+    font-size: 14px;
+    color: #909399;
+  }
+
+  .steps-list {
+    margin-bottom: 20px;
+  }
+
+  .exec-step-item {
+    position: relative;
+    display: flex;
+    margin-bottom: 16px;
+    padding: 16px;
+    background-color: #ffffff;
+    border: 1px solid #e4e7ed;
+    border-radius: 8px;
+    transition: all 0.3s ease;
+    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
+  }
+
+  .exec-step-item:hover {
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+    border-color: #409eff;
+    transform: translateY(-1px);
+  }
+
+  .delete-btn {
+    position: absolute;
+    top: -25rpx;
+    right: -25rpx;
+    width: 50rpx;
+    height: 50rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: center;
+    font-size: 20px;
+    border-radius: 50%;
+    background-color: red;
+    border: none;
+    z-index: 10;
+  }
+
+  .delete-btn:hover {
+    transform: scale(1.1);
+    box-shadow: 0 3px 6px rgba(245, 108, 108, 0.4);
+  }
+
+  .step-number {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 32px;
+    height: 32px;
+    margin-right: 16px;
+    background-color: #ecf5ff;
+    color: #409eff;
+    font-size: 14px;
+    font-weight: 600;
+    border-radius: 50%;
+    flex-shrink: 0;
+  }
+
+  .step-content {
+    flex: 1;
+    min-width: 0;
+  }
+
+  .step-row {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 12px;
+  }
+
+  .step-row:last-child {
+    margin-bottom: 0;
+  }
+
+  .step-label {
+    display: inline-block;
+    width: 80px;
+    font-size: 14px;
+    color: #606266;
+    margin-right: 12px;
+    flex-shrink: 0;
+    line-height: 36px;
+  }
+
+  .step-input {
+    flex: 1;
+    min-width: 0;
+  }
+
+  .step-input input {
+    font-size: 14px;
+    color: #303133;
+  }
+
+  .step-textarea {
+    flex: 1;
+    min-width: 0;
+  }
+
+  .step-textarea textarea {
+    font-size: 14px;
+    color: #303133;
+    min-height: 80px;
+    line-height: 1.5;
+  }
+
+  .add-step-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 44px;
+    line-height: 44px;
+    font-size: 14px;
+    border-radius: 8px;
+    transition: all 0.3s ease;
+    gap: 8px;
+  }
+
+  .add-step-btn:hover {
+    transform: translateY(-1px);
+    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+  }
+
+  .add-step-btn text {
+    font-size: 14px;
+  }
+
+  .bottom-buttons {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    padding: 16px 20px;
+    background: #ffffff;
+    border-top: 1px solid #f0f0f0;
+    gap: 16px;
+  }
+
+  .bottom-btn {
+    flex: 1;
+  }
+</style>

--
Gitblit v1.9.3