From 04d2dcd5d484e5b1a702408ed9ecd095ed7cbba8 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 03 二月 2026 16:02:24 +0800
Subject: [PATCH] 危险物料管控模块开发

---
 src/pages/index.vue                                           |    9 
 src/pages/safeProduction/hazardSourceLedger/detail.vue        |    3 
 src/pages/safeProduction/hazardousMaterialsControl/index.vue  |  295 +++++++++++++++++++++
 src/pages.json                                                |   21 +
 src/api/safeProduction/hazardousMaterialsControl.js           |   33 ++
 src/pages/safeProduction/dangerInvestigation/detail.vue       |    3 
 src/pages/safeProduction/hazardousMaterialsControl/detail.vue |  444 +++++++++++++++++++++++++++++++
 src/pages/safeProduction/safeQualifications/detail.vue        |    1 
 8 files changed, 809 insertions(+), 0 deletions(-)

diff --git a/src/api/safeProduction/hazardousMaterialsControl.js b/src/api/safeProduction/hazardousMaterialsControl.js
new file mode 100644
index 0000000..0f5557f
--- /dev/null
+++ b/src/api/safeProduction/hazardousMaterialsControl.js
@@ -0,0 +1,33 @@
+import request from "@/utils/request";
+
+export function safeHazardRecordListPage(query) {
+  return request({
+    url: "/safeHazardRecord/page",
+    method: "get",
+    params: query,
+  });
+}
+
+export function safeHazardRecordDel(ids) {
+    return request({
+        url: '/safeHazardRecord/' + ids,
+        method: 'delete',
+        data: ids
+    })
+}
+// 鏂板鍗遍櫓婧愬彴璐�
+export function safeHazardRecordAdd(query) {
+    return request({
+        url: '/safeHazardRecord/borrow',
+        method: 'post',
+        data: query
+    })
+}
+
+export function safeHazardRecordUpdate(query) {
+    return request({
+        url: '/safeHazardRecord/return',
+        method: 'put',
+        data: query
+    })
+}
\ No newline at end of file
diff --git a/src/pages.json b/src/pages.json
index 9132df1..a2a1a59 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -759,6 +759,27 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/safeProduction/hazardousMaterialsControl/index",
+      "style": {
+        "navigationBarTitleText": "鍗遍櫓鐗╂枡",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/safeProduction/hazardousMaterialsControl/detail",
+      "style": {
+        "navigationBarTitleText": "鍗遍櫓鐗╂枡璇︽儏",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/safeProduction/hazardousMaterialsControl/view",
+      "style": {
+        "navigationBarTitleText": "鍗遍櫓鐗╂枡璇︽儏",
+        "navigationStyle": "custom"
+      }
+    },
   ],
   "subPackages": [
     {
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 10d6a58..22532f6 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -319,6 +319,10 @@
       icon: "/static/images/icon/guzhangfenxi@2x.png",
       label: "闅愭偅鎺掓煡",
     },
+    {
+      icon: "/static/images/icon/guzhangfenxi@2x.png",
+      label: "鍗遍櫓鐗╂枡",
+    },
   ]);
   // 鍗忓悓鍔炲叕鍔熻兘鏁版嵁
   const collaborationItems = reactive([
@@ -697,6 +701,11 @@
           url: "/pages/safeProduction/dangerInvestigation/index",
         });
         break;
+      case "鍗遍櫓鐗╂枡":
+        uni.navigateTo({
+          url: "/pages/safeProduction/hazardousMaterialsControl/index",
+        });
+        break;
       default:
         uni.showToast({
           title: `鐐瑰嚮浜�${item.label}`,
diff --git a/src/pages/safeProduction/dangerInvestigation/detail.vue b/src/pages/safeProduction/dangerInvestigation/detail.vue
index 1bff840..1e0c8c4 100644
--- a/src/pages/safeProduction/dangerInvestigation/detail.vue
+++ b/src/pages/safeProduction/dangerInvestigation/detail.vue
@@ -117,16 +117,19 @@
     <up-action-sheet :show="hiddenTypeSheetVisible"
                      :actions="hiddenTypeOptions"
                      @select="handleHiddenTypeSelect"
+                     @close="hiddenTypeSheetVisible = false"
                      title="閫夋嫨闅愭偅绫诲瀷" />
     <!-- 椋庨櫓绛夌骇閫夋嫨鍣� -->
     <up-action-sheet :show="riskLevelSheetVisible"
                      :actions="riskLevelOptions"
                      @select="handleRiskLevelSelect"
+                     @close="riskLevelSheetVisible = false"
                      title="閫夋嫨椋庨櫓绛夌骇" />
     <!-- 鏁存敼璐d换浜洪�夋嫨鍣� -->
     <up-action-sheet :show="principalSheetVisible"
                      :actions="principalOptions"
                      @select="handlePrincipalSelect"
+                     @close="principalSheetVisible = false"
                      title="閫夋嫨鏁存敼璐d换浜�" />
   </view>
 </template>
diff --git a/src/pages/safeProduction/hazardSourceLedger/detail.vue b/src/pages/safeProduction/hazardSourceLedger/detail.vue
index d9ffde2..104bfaf 100644
--- a/src/pages/safeProduction/hazardSourceLedger/detail.vue
+++ b/src/pages/safeProduction/hazardSourceLedger/detail.vue
@@ -117,16 +117,19 @@
     <up-action-sheet :show="typeSheetVisible"
                      :actions="typeOptions"
                      @select="handleTypeSelect"
+                     @close="typeSheetVisible = false"
                      title="閫夋嫨鍗遍櫓婧愮被鍨�" />
     <!-- 椋庨櫓绛夌骇閫夋嫨鍣� -->
     <up-action-sheet :show="riskLevelSheetVisible"
                      :actions="riskLevelOptions"
                      @select="handleRiskLevelSelect"
+                     @close="riskLevelSheetVisible = false"
                      title="閫夋嫨椋庨櫓绛夌骇" />
     <!-- 绠℃帶璐d换浜洪�夋嫨鍣� -->
     <up-action-sheet :show="principalSheetVisible"
                      :actions="principalOptions"
                      @select="handlePrincipalSelect"
+                     @close="principalSheetVisible = false"
                      title="閫夋嫨绠℃帶璐d换浜�" />
   </view>
 </template>
diff --git a/src/pages/safeProduction/hazardousMaterialsControl/detail.vue b/src/pages/safeProduction/hazardousMaterialsControl/detail.vue
new file mode 100644
index 0000000..2177e1c
--- /dev/null
+++ b/src/pages/safeProduction/hazardousMaterialsControl/detail.vue
@@ -0,0 +1,444 @@
+<template>
+  <view class="hazard-source-detail">
+    <PageHeader :title="isEdit ? '褰掕繕' : '棰嗙敤鍗遍櫓婧�'"
+                @back="goBack" />
+    <u-form @submit="handleSubmit"
+            ref="formRef"
+            label-width="110">
+      <!-- 鍗遍櫓婧愪俊鎭� -->
+      <u-cell-group v-if="!isEdit"
+                    title="鍗遍櫓婧愪俊鎭�">
+        <u-form-item v-if="!isEdit"
+                     label="鍗遍櫓婧愬悕绉�"
+                     prop="name"
+                     required
+                     border-bottom>
+          <u-input v-model="form.name"
+                   placeholder="璇烽�夋嫨鍗遍櫓婧�"
+                   @click="showHazardSourceSheet"
+                   readonly />
+          <template #right>
+            <up-icon name="arrow-right"
+                     @click="showHazardSourceSheet"></up-icon>
+          </template>
+        </u-form-item>
+        <u-form-item label="鍗遍櫓婧愮紪鐮�"
+                     prop="code"
+                     border-bottom>
+          <u-input v-model="form.code"
+                   disabled
+                   placeholder="鑷姩甯﹀嚭"
+                   readonly />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="鍗遍櫓婧愮被鍨�"
+                     prop="type"
+                     border-bottom>
+          <u-input v-model="form.type"
+                   disabled
+                   placeholder="鑷姩甯﹀嚭"
+                   readonly />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="椋庨櫓绛夌骇"
+                     prop="riskLevel"
+                     border-bottom>
+          <u-input v-model="form.riskLevel"
+                   disabled
+                   placeholder="鑷姩甯﹀嚭"
+                   readonly />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="鎵�鍦ㄤ綅缃�"
+                     prop="location"
+                     border-bottom>
+          <u-input v-model="form.location"
+                   disabled
+                   placeholder="鑷姩甯﹀嚭"
+                   readonly />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="棰嗙敤鏃堕棿"
+                     prop="applyTime"
+                     border-bottom>
+          <u-input v-model="form.applyTime"
+                   disabled />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="棰嗙敤浜�"
+                     prop="applyUserName"
+                     border-bottom>
+          <u-input v-model="form.applyUserName"
+                   disabled />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="棰嗙敤鐢ㄩ��"
+                     prop="applyPurpose"
+                     required
+                     border-bottom>
+          <u-input v-model="form.applyPurpose"
+                   placeholder="璇疯緭鍏ラ鐢ㄧ敤閫�" />
+        </u-form-item>
+        <u-form-item v-if="!isEdit"
+                     label="棰嗙敤鏁伴噺"
+                     prop="applyQty"
+                     required
+                     border-bottom>
+          <u-input v-model="form.applyQty"
+                   type="number"
+                   @blur="validateApplyQty"
+                   min="1"
+                   placeholder="璇疯緭鍏ラ鐢ㄦ暟閲�" />
+        </u-form-item>
+      </u-cell-group>
+      <u-cell-group v-if="isEdit"
+                    title="褰掕繕淇℃伅">
+        <u-form-item label="褰掕繕浜�"
+                     prop="returnUserName"
+                     border-bottom>
+          <u-input v-model="form.returnUserName"
+                   disabled />
+        </u-form-item>
+        <u-form-item label="褰掕繕鏃堕棿"
+                     prop="returnTime"
+                     border-bottom>
+          <u-input v-model="form.returnTime"
+                   disabled />
+        </u-form-item>
+        <u-form-item label="褰掕繕鎯呭喌璇存槑"
+                     prop="returnRemark"
+                     required
+                     border-bottom>
+          <u-textarea v-model="form.returnRemark"
+                      placeholder="璇疯緭鍏ュ綊杩樻儏鍐佃鏄�"
+                      :maxlength="200"
+                      count
+                      :autoHeight="true" />
+        </u-form-item>
+      </u-cell-group>
+      <!-- 鎻愪氦鎸夐挳 -->
+      <view class="footer-btns">
+        <u-button class="cancel-btn"
+                  @click="goBack">鍙栨秷</u-button>
+        <u-button class="sign-btn"
+                  type="primary"
+                  @click="handleSubmit"
+                  :loading="loading">{{ isEdit ? '褰掕繕' : '棰嗙敤' }}</u-button>
+      </view>
+    </u-form>
+    <!-- 鍗遍櫓婧愰�夋嫨鍣� -->
+    <up-action-sheet :show="hazardSourceSheetVisible"
+                     :actions="hazardSourceOptions"
+                     @select="handleHazardSourceSelect"
+                     @close="hazardSourceSheetVisible = false"
+                     title="閫夋嫨鍗遍櫓婧�" />
+    <!-- 鏃堕棿閫夋嫨鍣� -->
+    <up-datetime-picker :show="applyTimeVisible"
+                        v-model="applyTime"
+                        @confirm="onApplyTimeConfirm"
+                        @cancel="applyTimeVisible = false"
+                        mode="datetime" />
+    <up-datetime-picker :show="returnTimeVisible"
+                        v-model="returnTime"
+                        @confirm="onReturnTimeConfirm"
+                        @cancel="returnTimeVisible = false"
+                        mode="date" />
+  </view>
+</template>
+
+<script setup>
+  // 鏇挎崲 toast 鏂规硶
+  defineOptions({ name: "hazard-source-detail" });
+  const showToast = message => {
+    uni.showToast({
+      title: message,
+      icon: "none",
+    });
+  };
+
+  import { ref, onMounted } from "vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import {
+    safeHazardRecordAdd,
+    safeHazardRecordUpdate,
+  } from "@/api/safeProduction/hazardousMaterialsControl";
+  import { safeHazardListPage } from "@/api/safeProduction/hazardSourceLedger";
+  import useUserStore from "@/store/modules/user";
+  import dayjs from "dayjs";
+  import { onLoad } from "@dcloudio/uni-app";
+
+  const userStore = useUserStore();
+
+  // 琛ㄥ崟鏁版嵁
+  const form = ref({
+    name: "",
+    code: "",
+    type: "",
+    riskLevel: "",
+    location: "",
+    applyPurpose: "",
+    applyTime: "",
+    applyQty: "",
+    returnTime: "",
+    returnRemark: "",
+    safeHazardId: "",
+  });
+
+  // 椤甸潰鐘舵��
+  const loading = ref(false);
+  const formRef = ref(null);
+  const isEdit = ref(false);
+
+  // 鍗遍櫓婧愰�夋嫨鍣�
+  const hazardSourceSheetVisible = ref(false);
+  const hazardSourceOptions = ref([]);
+  const hazardSourceList = ref([]);
+  const showHazardSourceSheet = () => {
+    if (hazardSourceOptions.value.length === 0) {
+      getHazardSourceList();
+    } else {
+      hazardSourceSheetVisible.value = true;
+    }
+  };
+  const stockQty = ref(0);
+  const handleHazardSourceSelect = item => {
+    const hazardSource = hazardSourceList.value.find(h => h.id === item.value);
+    if (hazardSource) {
+      form.value.name = hazardSource.name;
+      form.value.code = hazardSource.code;
+      form.value.type = hazardSource.type;
+      form.value.riskLevel = hazardSource.riskLevel;
+      form.value.location = hazardSource.location;
+      form.value.safeHazardId = hazardSource.id;
+      stockQty.value = hazardSource.stockQty || 0;
+    }
+    hazardSourceSheetVisible.value = false;
+  };
+  const validateApplyQty = () => {
+    if (!form.value.applyQty) {
+      showToast("璇疯緭鍏ラ鐢ㄦ暟閲�");
+      return false;
+    }
+    if (isNaN(form.value.applyQty)) {
+      showToast("棰嗙敤鏁伴噺蹇呴』鏄暟瀛�");
+      form.value.applyQty = 0;
+      return false;
+    }
+    if (form.value.applyQty < 0) {
+      showToast("棰嗙敤鏁伴噺蹇呴』澶т簬绛変簬1");
+      form.value.applyQty = 0;
+      return false;
+    }
+    if (form.value.applyQty > stockQty.value) {
+      showToast("棰嗙敤鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
+      form.value.applyQty = 0;
+      return false;
+    }
+    return true;
+  };
+
+  // 鑾峰彇鍗遍櫓婧愬垪琛�
+  const getHazardSourceList = () => {
+    const params = {
+      current: -1,
+      size: -1,
+    };
+    safeHazardListPage(params).then(res => {
+      if (res.code === 200) {
+        hazardSourceList.value = res.records || res.data?.records || [];
+        // 杩囨护鎺夊簱瀛樻暟閲忓皬浜庣瓑浜�0鐨勯�夐」
+        const validHazardSources = hazardSourceList.value.filter(
+          item => item.stockQty > 0
+        );
+        hazardSourceOptions.value = validHazardSources.map(item => ({
+          value: item.id,
+          name: item.name,
+          subname: `搴撳瓨: ${item.stockQty}`,
+        }));
+        hazardSourceSheetVisible.value = true;
+      }
+    });
+  };
+
+  // 鏃堕棿閫夋嫨鍣�
+  const applyTimeVisible = ref(false);
+  const applyTime = ref(Date.now());
+  const showApplyTimePicker = () => {
+    applyTimeVisible.value = true;
+  };
+  const onApplyTimeConfirm = e => {
+    form.value.applyTime = dayjs(e.value).format("YYYY-MM-DD HH:mm:ss");
+    applyTime.value = e.value;
+    applyTimeVisible.value = false;
+  };
+
+  const returnTimeVisible = ref(false);
+  const returnTime = ref(Date.now());
+  const showReturnTimePicker = () => {
+    returnTimeVisible.value = true;
+  };
+  const onReturnTimeConfirm = e => {
+    form.value.returnTime = dayjs(e.value).format("YYYY-MM-DD");
+    returnTime.value = e.value;
+    returnTimeVisible.value = false;
+  };
+
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    // 杩斿洖鏃舵竻闄ゆ湰鍦板瓨鍌ㄧ殑鏁版嵁
+    uni.removeStorageSync("hazardousMaterialsControl");
+    uni.navigateBack();
+  };
+
+  // 鎻愪氦琛ㄥ崟
+  const handleSubmit = async () => {
+    if (!form.value.safeHazardId) {
+      showToast("璇烽�夋嫨鍗遍櫓婧�");
+      return;
+    }
+
+    if (!form.value.applyPurpose) {
+      showToast("璇疯緭鍏ラ鐢ㄧ敤閫�");
+      return;
+    }
+
+    if (!form.value.applyQty) {
+      showToast("璇疯緭鍏ラ鐢ㄦ暟閲�");
+      return;
+    }
+
+    if (isEdit.value) {
+      if (!form.value.returnTime) {
+        showToast("璇烽�夋嫨褰掕繕鏃堕棿");
+        return;
+      }
+
+      if (!form.value.returnRemark) {
+        showToast("璇疯緭鍏ュ綊杩樻儏鍐佃鏄�");
+        return;
+      }
+    }
+
+    try {
+      loading.value = true;
+
+      // 浣跨敤瀹夊叏娴呮嫹璐濓紝閬垮厤瀵硅薄灞曞紑鍦ㄦ煇浜涜繍琛屾椂鎶涢敊
+      const source =
+        form.value && typeof form.value === "object" ? form.value : {};
+      const submitData = {};
+      Object.keys(source).forEach(k => {
+        submitData[k] = source[k];
+      });
+      console.log("submitData", submitData);
+      if (isEdit.value) {
+        const { code } = await safeHazardRecordUpdate(submitData);
+        if (code === 200) {
+          showToast("褰掕繕鎴愬姛");
+          setTimeout(() => {
+            goBack();
+          }, 500);
+        } else {
+          loading.value = false;
+          showToast("褰掕繕澶辫触锛岃閲嶈瘯");
+        }
+      } else {
+        const { code } = await safeHazardRecordAdd(submitData);
+        if (code === 200) {
+          showToast("棰嗙敤鎴愬姛");
+          setTimeout(() => {
+            goBack();
+          }, 500);
+        } else {
+          loading.value = false;
+          showToast("棰嗙敤澶辫触锛岃閲嶈瘯");
+        }
+      }
+    } catch (e) {
+      loading.value = false;
+      console.error("鎻愪氦澶辫触:", e);
+      showToast("鎻愪氦澶辫触锛岃閲嶈瘯");
+    }
+  };
+
+  onLoad(() => {
+    // 缂栬緫鍗遍櫓婧愭椂锛屼粠鏈湴瀛樺偍鑾峰彇鏁版嵁
+    const hazardousMaterials = uni.getStorageSync("hazardousMaterialsControl");
+    console.log("hazardousMaterials", hazardousMaterials);
+    if (hazardousMaterials.id) {
+      form.value = hazardousMaterials;
+      isEdit.value = true;
+      userStore.getInfo().then(res => {
+        form.value.returnUserId = res.user.userId;
+        form.value.returnUserName = res.user.nickName;
+      });
+      console.log("form.value", form.value);
+    } else {
+      userStore.getInfo().then(res => {
+        form.value.applyUserId = res.user.userId;
+        form.value.applyUserName = res.user.nickName;
+      });
+      isEdit.value = false;
+    }
+  });
+
+  onMounted(() => {
+    // 璁剧疆榛樿鏃堕棿
+    if (!isEdit.value) {
+      form.value.applyTime = dayjs().format("YYYY-MM-DD");
+      applyTime.value = Date.now();
+    } else {
+      form.value.returnTime = dayjs().format("YYYY-MM-DD");
+      returnTime.value = Date.now();
+    }
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+  .client-visit {
+    min-height: 100vh;
+    background: #f8f9fa;
+    padding-bottom: 5rem;
+  }
+
+  .footer-btns {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: #fff;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    padding: 0.75rem 0;
+    box-shadow: 0 -0.125rem 0.5rem rgba(0, 0, 0, 0.05);
+    z-index: 1000;
+  }
+
+  .cancel-btn {
+    font-weight: 400;
+    font-size: 1rem;
+    color: #666;
+    background: #f5f5f5;
+    border: 1px solid #ddd;
+    width: 45%;
+    height: 2.5rem;
+    border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+  }
+
+  .sign-btn {
+    font-weight: 500;
+    font-size: 1rem;
+    color: #fff;
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    border: none;
+    width: 45%;
+    height: 2.5rem;
+    border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+  }
+
+  .location-icon {
+    color: #1989fa;
+    font-size: 1.2rem;
+  }
+</style>
\ No newline at end of file
diff --git a/src/pages/safeProduction/hazardousMaterialsControl/index.vue b/src/pages/safeProduction/hazardousMaterialsControl/index.vue
new file mode 100644
index 0000000..0cf3ba1
--- /dev/null
+++ b/src/pages/safeProduction/hazardousMaterialsControl/index.vue
@@ -0,0 +1,295 @@
+<template>
+  <view class="sales-accoun">
+    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+    <PageHeader title="鍗遍櫓鐗╂枡绠℃帶"
+                @back="goBack" />
+    <!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+    <view class="search-section">
+      <view class="search-bar">
+        <view class="search-input">
+          <up-input class="search-text"
+                    placeholder="璇疯緭鍏ュ嵄闄╂簮鍚嶇О"
+                    v-model="customerName"
+                    @blur="getList"
+                    clearable />
+        </view>
+        <view class="filter-button"
+              @click="getList">
+          <u-icon name="search"
+                  size="24"
+                  color="#999"></u-icon>
+        </view>
+      </view>
+    </view>
+    <!-- 鎷滆璁板綍鍒楄〃 -->
+    <view class="ledger-list"
+          v-if="visitList.length > 0">
+      <view v-for="(item, index) in visitList"
+            :key="index">
+        <view class="ledger-item">
+          <view class="item-header">
+            <view class="item-left">
+              <view class="document-icon">
+                <up-icon name="file-text"
+                         size="16"
+                         color="#ffffff"></up-icon>
+              </view>
+              <text class="item-id">棰嗙敤鍗曞彿锛歿{ item.materialRecordCode }}</text>
+            </view>
+          </view>
+          <up-divider></up-divider>
+          <view class="item-details">
+            <view class="detail-row">
+              <text class="detail-label">鍗遍櫓婧愬悕绉�</text>
+              <text class="detail-value">{{ item.name || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鍗遍櫓婧愮紪鐮�</text>
+              <text class="detail-value">{{ item.code || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鍗遍櫓婧愮被鍨�</text>
+              <text class="detail-value">{{ hazard_source_type.find(i => i.value === item.type)?.label || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">椋庨櫓绛夌骇</text>
+              <u-tag :type="getRiskLevelType(item.riskLevel)">
+                {{ item.riskLevel || '-' }}
+              </u-tag>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鎵�鍦ㄤ綅缃�</text>
+              <text class="detail-value">{{ item.location || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">棰嗙敤鐢ㄩ��</text>
+              <text class="detail-value">{{ item.applyPurpose || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">棰嗙敤鏃堕棿</text>
+              <text class="detail-value">{{ item.applyTime || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">棰嗙敤鏁伴噺</text>
+              <text class="detail-value">{{ item.applyQty || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">褰掕繕鏃堕棿</text>
+              <text class="detail-value">{{ item.returnTime || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">褰掕繕浜�</text>
+              <text class="detail-value">{{ item.returnUserName || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">褰掕繕鎯呭喌璇存槑</text>
+              <text class="detail-value">{{ item.returnRemark || '-' }}</text>
+            </view>
+          </view>
+          <!-- 鎸夐挳鍖哄煙 -->
+          <view class="action-buttons">
+            <!-- <u-button type="info"
+                      size="small"
+                      class="action-btn"
+                      @click="viewDetail(item)">
+              鏌ョ湅璇︽儏
+            </u-button> -->
+            <u-button type="primary"
+                      size="small"
+                      class="action-btn"
+                      :disabled="item.returnUserId"
+                      @click="editVisit(item)">
+              褰掕繕
+            </u-button>
+            <u-button type="error"
+                      size="small"
+                      class="action-btn"
+                      @click="deleteVisit(item)">
+              鍒犻櫎
+            </u-button>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view v-else
+          class="no-data">
+      <text>鏆傛棤鎷滆璁板綍</text>
+    </view>
+    <!-- 娴姩鏂板鎸夐挳 -->
+    <view class="fab-button"
+          @click="addVisit">
+      <up-icon name="plus"
+               size="24"
+               color="#ffffff"></up-icon>
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { ref, onMounted } from "vue";
+
+  import { onShow } from "@dcloudio/uni-app";
+  import PageHeader from "@/components/PageHeader.vue";
+  import {
+    safeHazardRecordListPage,
+    safeHazardRecordDel,
+  } from "@/api/safeProduction/hazardousMaterialsControl";
+  import useUserStore from "@/store/modules/user";
+  import { useDict } from "@/utils/dict";
+  // 鏇挎崲 toast 鏂规硶
+  defineOptions({ name: "client-visit-index" });
+  const showToast = message => {
+    uni.showToast({
+      title: message,
+      icon: "none",
+    });
+  };
+  const getRiskLevelType = riskLevel => {
+    const typeMap = {
+      浣庨闄�: "info",
+      涓�鑸闄�: "info",
+      杈冨ぇ椋庨櫓: "warning",
+      閲嶅ぇ椋庨櫓: "error",
+    };
+    return typeMap[riskLevel] || "info";
+  };
+
+  import dayjs from "dayjs";
+
+  const userStore = useUserStore();
+
+  // 鎼滅储鍏抽敭璇�
+  const customerName = ref("");
+
+  // 鎷滆璁板綍鏁版嵁
+  const visitList = ref([]);
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  // 鏌ヨ鍒楄〃
+  const getList = () => {
+    showLoadingToast("鍔犺浇涓�...");
+    const params = {
+      current: -1,
+      size: -1,
+      name: customerName.value,
+    };
+    safeHazardRecordListPage(params)
+      .then(res => {
+        visitList.value = res.records || res.data?.records || [];
+        closeToast();
+      })
+      .catch(() => {
+        closeToast();
+        showToast("鑾峰彇鏁版嵁澶辫触");
+      });
+  };
+
+  // 鏄剧ず鍔犺浇鎻愮ず
+  const showLoadingToast = message => {
+    uni.showLoading({
+      title: message,
+      mask: true,
+    });
+  };
+
+  // 鍏抽棴鎻愮ず
+  const closeToast = () => {
+    uni.hideLoading();
+  };
+
+  // 鏂板鍗遍櫓婧�
+  const addVisit = () => {
+    uni.setStorageSync("hazardousMaterialsControl", {});
+    uni.navigateTo({
+      url: "/pages/safeProduction/hazardousMaterialsControl/detail",
+    });
+  };
+  // 缂栬緫鍗遍櫓婧�
+  const editVisit = item => {
+    uni.setStorageSync("hazardousMaterialsControl", item);
+    uni.navigateTo({
+      url: "/pages/safeProduction/hazardousMaterialsControl/detail",
+    });
+  };
+  // 鍒犻櫎鍗遍櫓婧�
+  const deleteVisit = item => {
+    uni.showModal({
+      title: "鍒犻櫎纭",
+      content: `纭畾瑕佸垹闄よ鍗遍櫓婧愬悧锛焋,
+      success: res => {
+        if (res.confirm) {
+          deleteClientVisit(item.id);
+        }
+      },
+    });
+  };
+  const { hazard_source_type } = useDict("hazard_source_type");
+  const { risk_level } = useDict("risk_level");
+
+  // 鍒犻櫎鍗遍櫓婧愯褰�
+  const deleteClientVisit = id => {
+    showLoadingToast("鍒犻櫎涓�...");
+    safeHazardRecordDel([id])
+      .then(() => {
+        closeToast();
+        showToast("鍒犻櫎鎴愬姛");
+        getList();
+      })
+      .catch(() => {
+        closeToast();
+        showToast("鍒犻櫎澶辫触");
+      });
+  };
+  // 鏌ョ湅璇︽儏
+  const viewDetail = item => {
+    uni.setStorageSync("hazardSourceLedger", item);
+    uni.navigateTo({
+      url: "/pages/safeProduction/hazardSourceLedger/view",
+    });
+  };
+
+  onMounted(() => {
+    getList();
+  });
+
+  onShow(() => {
+    getList();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "../../../styles/sales-common.scss";
+
+  // 椤甸潰鐗瑰畾鐨勬牱寮忚鐩�
+  .sales-accoun {
+    min-height: 100vh;
+    background: #f8f9fa;
+    position: relative;
+    padding-bottom: 80px;
+  }
+
+  // 鐗瑰畾鐨勫浘鏍囨牱寮�
+  .document-icon {
+    background: #667eea; // 淇濇寔椤甸潰鐗规湁鐨勮儗鏅壊
+  }
+
+  // 鐗规湁鏍峰紡
+  .visit-status {
+    display: flex;
+    align-items: center;
+  }
+
+  .detail-value {
+    word-break: break-all; // 淇濈暀椤甸潰鐗规湁鐨勬枃鏈崲琛屾牱寮�
+  }
+
+  // 鐗瑰畾鐨勬诞鍔ㄦ寜閽牱寮�
+  .fab-button {
+    background: #667eea; // 淇濇寔椤甸潰鐗规湁鐨勮儗鏅壊
+    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // 淇濇寔椤甸潰鐗规湁鐨勯槾褰辨晥鏋�
+  }
+</style>
+
diff --git a/src/pages/safeProduction/safeQualifications/detail.vue b/src/pages/safeProduction/safeQualifications/detail.vue
index affa43e..0d0648b 100644
--- a/src/pages/safeProduction/safeQualifications/detail.vue
+++ b/src/pages/safeProduction/safeQualifications/detail.vue
@@ -83,6 +83,7 @@
     <up-action-sheet :show="typeSheetVisible"
                      :actions="typeOptions"
                      @select="handleTypeSelect"
+                     @close="typeSheetVisible = false"
                      title="閫夋嫨瑙勭▼璧勮川绫诲瀷" />
   </view>
 </template>

--
Gitblit v1.9.3