From 263b4a60670671cef5445b102e670c40ba34a162 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 30 六月 2026 15:11:11 +0800
Subject: [PATCH] 特种设备管理模块开发

---
 src/api/safeProduction/specialEquipmentManagement.js                      |  106 ++++
 src/pages/safeProduction/specialEquipmentManagement/ledgerEdit.vue        |  145 ++++++
 src/pages.json                                                            |   30 +
 src/pages/safeProduction/specialEquipmentManagement/recordEdit.vue        |  275 +++++++++++
 src/pages/works.vue                                                       |    9 
 src/pages/safeProduction/specialEquipmentManagement/index.vue             |  516 +++++++++++++++++++++
 src/pages/safeProduction/specialEquipmentManagement/rectificationEdit.vue |  310 ++++++++++++
 7 files changed, 1,390 insertions(+), 1 deletions(-)

diff --git a/src/api/safeProduction/specialEquipmentManagement.js b/src/api/safeProduction/specialEquipmentManagement.js
new file mode 100644
index 0000000..2bb5437
--- /dev/null
+++ b/src/api/safeProduction/specialEquipmentManagement.js
@@ -0,0 +1,106 @@
+import request from "@/utils/request";
+
+export function specialEquipmentLedgerListPage(query) {
+  return request({
+    url: "/safe/specialEquipment/ledger/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+export function specialEquipmentLedgerList(query) {
+  return request({
+    url: "/safe/specialEquipment/ledger/list",
+    method: "get",
+    params: query,
+  });
+}
+
+export function specialEquipmentLedgerAdd(data) {
+  return request({
+    url: "/safe/specialEquipment/ledger/add",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentLedgerUpdate(data) {
+  return request({
+    url: "/safe/specialEquipment/ledger/update",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentLedgerDel(ids) {
+  return request({
+    url: "/safe/specialEquipment/ledger/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+export function specialEquipmentRecordListPage(query) {
+  return request({
+    url: "/safe/specialEquipment/record/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+export function specialEquipmentRecordAdd(data) {
+  return request({
+    url: "/safe/specialEquipment/record/add",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentRecordUpdate(data) {
+  return request({
+    url: "/safe/specialEquipment/record/update",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentRecordDel(ids) {
+  return request({
+    url: "/safe/specialEquipment/record/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+export function specialEquipmentRectificationListPage(query) {
+  return request({
+    url: "/safe/specialEquipment/rectification/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+export function specialEquipmentRectificationAdd(data) {
+  return request({
+    url: "/safe/specialEquipment/rectification/add",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentRectificationClose(data) {
+  return request({
+    url: "/safe/specialEquipment/rectification/close",
+    method: "post",
+    data,
+  });
+}
+
+export function specialEquipmentRectificationDel(ids) {
+  return request({
+    url: "/safe/specialEquipment/rectification/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
diff --git a/src/pages.json b/src/pages.json
index 7f0820a..a8b9e69 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -1020,6 +1020,34 @@
       }
     },
     {
+      "path": "pages/safeProduction/specialEquipmentManagement/index",
+      "style": {
+        "navigationBarTitleText": "鐗圭璁惧绠$悊",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/safeProduction/specialEquipmentManagement/ledgerEdit",
+      "style": {
+        "navigationBarTitleText": "鍙拌处",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/safeProduction/specialEquipmentManagement/recordEdit",
+      "style": {
+        "navigationBarTitleText": "妫�楠岀淮淇�",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/safeProduction/specialEquipmentManagement/rectificationEdit",
+      "style": {
+        "navigationBarTitleText": "闅愭偅鏁存敼",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/safeProduction/accidentReportingRecord/index",
       "style": {
         "navigationBarTitleText": "浜嬫晠鎶ュ憡璁板綍",
@@ -1596,4 +1624,4 @@
     "navigationBarTitleText": "RuoYi",
     "navigationBarBackgroundColor": "#FFFFFF"
   }
-}
+}
\ No newline at end of file
diff --git a/src/pages/safeProduction/specialEquipmentManagement/index.vue b/src/pages/safeProduction/specialEquipmentManagement/index.vue
new file mode 100644
index 0000000..1c39385
--- /dev/null
+++ b/src/pages/safeProduction/specialEquipmentManagement/index.vue
@@ -0,0 +1,516 @@
+<template>
+  <view class="special-equipment">
+    <PageHeader title="鐗圭璁惧绠$悊"
+                @back="goBack">
+    </PageHeader>
+    <view class="tabs-section">
+      <up-tabs v-model="activeTabIndex"
+               :list="tabList"
+               itemStyle="width: 33.33%;height: 80rpx;"
+               @change="onTabChange" />
+    </view>
+    <scroll-view scroll-y
+                 class="list-scroll"
+                 @scrolltolower="loadMore"
+                 v-if="list.length > 0">
+      <up-checkbox-group v-if="selectMode"
+                         v-model="selectedIds"
+                         placement="column">
+        <view v-for="row in list"
+              :key="row.id"
+              class="card"
+              @click="toggleSelect(row)">
+          <view class="card-header">
+            <text class="title">{{ getCardTitle(row) }}</text>
+            <view class="right">
+              <up-checkbox :name="String(row.id)"
+                           :label="''"
+                           @click.stop></up-checkbox>
+            </view>
+          </view>
+          <up-divider></up-divider>
+          <view class="card-body">
+            <template v-if="activeTab === 'ledger'">
+              <view class="row"><text class="label">璁惧缂栧彿</text><text class="value">{{ row.equipmentNo || '-' }}</text></view>
+              <view class="row"><text class="label">璁惧绫诲埆</text><text class="value">{{ row.equipmentType || '-' }}</text></view>
+              <view class="row"><text class="label">瀹夎浣嶇疆</text><text class="value">{{ row.installLocation || '-' }}</text></view>
+              <view class="row"><text class="label">璐熻矗浜�</text><text class="value">{{ row.managerName || '-' }}</text></view>
+            </template>
+            <template v-else-if="activeTab === 'record'">
+              <view class="row"><text class="label">璁板綍绫诲瀷</text><text class="value">{{ recordTypeLabel(row.recordType) }}</text></view>
+              <view class="row"><text class="label">璁板綍鏃ユ湡</text><text class="value">{{ row.recordDate || '-' }}</text></view>
+              <view class="row"><text class="label">鎵ц浜�</text><text class="value">{{ row.executorName || '-' }}</text></view>
+              <view class="row"><text class="label">涓嬫鍒版湡鏃ユ湡</text><text class="value">{{ row.nextDueDate || '-' }}</text></view>
+            </template>
+            <template v-else>
+              <view class="row"><text class="label">椋庨櫓绛夌骇</text><text class="value">{{ row.riskLevel || '-' }}</text></view>
+              <view class="row"><text class="label">鍙戠幇鏃ユ湡</text><text class="value">{{ row.discoveredDate || '-' }}</text></view>
+              <view class="row"><text class="label">璐d换浜�</text><text class="value">{{ row.responsibleUserName || '-' }}</text></view>
+              <view class="row"><text class="label">鏁存敼鐘舵��</text><text class="value">{{ rectStatusLabel(row.rectificationStatus) }}</text></view>
+            </template>
+          </view>
+        </view>
+      </up-checkbox-group>
+      <view v-else>
+        <view v-for="row in list"
+              :key="row.id"
+              class="card">
+          <view class="card-header">
+            <text class="title">{{ getCardTitle(row) }}</text>
+            <up-tag v-if="activeTab === 'record'"
+                    :text="recordTypeLabel(row.recordType)"
+                    type="primary"
+                    size="mini" />
+            <up-tag v-else-if="activeTab === 'rectification'"
+                    :text="rectStatusLabel(row.rectificationStatus)"
+                    type="info"
+                    size="mini" />
+          </view>
+          <up-divider></up-divider>
+          <view class="card-body">
+            <template v-if="activeTab === 'ledger'">
+              <view class="row"><text class="label">璁惧缂栧彿</text><text class="value">{{ row.equipmentNo || '-' }}</text></view>
+              <view class="row"><text class="label">璁惧绫诲埆</text><text class="value">{{ row.equipmentType || '-' }}</text></view>
+              <view class="row"><text class="label">瀹夎浣嶇疆</text><text class="value">{{ row.installLocation || '-' }}</text></view>
+              <view class="row"><text class="label">璐熻矗浜�</text><text class="value">{{ row.managerName || '-' }}</text></view>
+            </template>
+            <template v-else-if="activeTab === 'record'">
+              <view class="row"><text class="label">鍏宠仈璁惧</text><text class="value">{{ row.equipmentName || '-' }}</text></view>
+              <view class="row"><text class="label">璁板綍鏃ユ湡</text><text class="value">{{ row.recordDate || '-' }}</text></view>
+              <view class="row"><text class="label">鎵ц浜�</text><text class="value">{{ row.executorName || '-' }}</text></view>
+              <view class="row"><text class="label">涓嬫鍒版湡鏃ユ湡</text><text class="value">{{ row.nextDueDate || '-' }}</text></view>
+            </template>
+            <template v-else>
+              <view class="row"><text class="label">闅愭偅鎻忚堪</text><text class="value">{{ row.hazardDescription || '-' }}</text></view>
+              <view class="row"><text class="label">椋庨櫓绛夌骇</text><text class="value">{{ row.riskLevel || '-' }}</text></view>
+              <view class="row"><text class="label">鏁存敼鏈熼檺</text><text class="value">{{ row.rectificationDeadline || '-' }}</text></view>
+              <view class="row"><text class="label">璐d换浜�</text><text class="value">{{ row.responsibleUserName || '-' }}</text></view>
+            </template>
+          </view>
+          <view class="actions">
+            <u-button v-if="activeTab !== 'rectification'"
+                      size="small"
+                      class="action-btn"
+                      @click.stop="goEdit(row)">缂栬緫</u-button>
+            <u-button size="small"
+                      class="action-btn"
+                      type="error"
+                      @click.stop="deleteSingle(row)">鍒犻櫎</u-button>
+          </view>
+        </view>
+        <up-loadmore :status="loadStatus" />
+      </view>
+    </scroll-view>
+    <view v-else
+          class="no-data">
+      <up-empty mode="data"
+                text="鏆傛棤鏁版嵁"></up-empty>
+    </view>
+    <FooterButtons v-if="selectMode"
+                   cancelText="鍙栨秷"
+                   confirmText="鍒犻櫎"
+                   :confirmDisabled="selectedIds.length === 0"
+                   @cancel="exitSelectMode"
+                   @confirm="deleteSelected" />
+    <view class="fab-button"
+          @click="goAdd">
+      <up-icon name="plus"
+               size="24"
+               color="#ffffff"></up-icon>
+    </view>
+    <up-action-sheet :show="showRecordTypeSheet"
+                     title="閫夋嫨璁板綍绫诲瀷"
+                     :actions="recordTypeActions"
+                     @select="onSelectRecordType"
+                     @close="showRecordTypeSheet = false" />
+    <up-action-sheet :show="showRectStatusSheet"
+                     title="閫夋嫨鏁存敼鐘舵��"
+                     :actions="rectStatusActions"
+                     @select="onSelectRectStatus"
+                     @close="showRectStatusSheet = false" />
+  </view>
+</template>
+
+<script setup>
+  import { computed, onMounted, reactive, ref } from "vue";
+  import { onShow } from "@dcloudio/uni-app";
+  import PageHeader from "@/components/PageHeader.vue";
+  import FooterButtons from "@/components/FooterButtons.vue";
+  import {
+    specialEquipmentLedgerDel,
+    specialEquipmentLedgerListPage,
+    specialEquipmentRecordDel,
+    specialEquipmentRecordListPage,
+    specialEquipmentRectificationDel,
+    specialEquipmentRectificationListPage,
+  } from "@/api/safeProduction/specialEquipmentManagement";
+
+  const tabList = reactive([
+    { name: "鐢靛瓙鍙拌处", value: "ledger" },
+    { name: "妫�楠岀淮淇�", value: "record" },
+    { name: "闅愭偅鏁存敼", value: "rectification" },
+  ]);
+  const activeTabIndex = ref(0);
+  const activeTab = computed(
+    () => tabList[activeTabIndex.value]?.value || "ledger"
+  );
+
+  const ledgerSearch = reactive({ equipmentName: "" });
+  const recordSearch = reactive({ recordType: "" });
+  const rectSearch = reactive({ rectificationStatus: "" });
+
+  const page = reactive({ current: 1, size: 10, total: 0 });
+  const list = ref([]);
+  const loadStatus = ref("loadmore");
+  const loading = ref(false);
+
+  const selectMode = ref(false);
+  const selectedIds = ref([]);
+
+  const showRecordTypeSheet = ref(false);
+  const showRectStatusSheet = ref(false);
+
+  const recordTypeActions = [
+    { name: "妫�楠�", value: 1 },
+    { name: "缁翠繚", value: 2 },
+  ];
+  const rectStatusActions = [
+    { name: "寰呮暣鏀�", value: 1 },
+    { name: "鏁存敼涓�", value: 2 },
+    { name: "寰呭鏍�", value: 3 },
+    { name: "宸查棴鐜�", value: 4 },
+  ];
+
+  const recordTypeText = computed(() => {
+    const v = recordSearch.recordType;
+    if (!v) return "";
+    return v === 1 ? "妫�楠�" : "缁翠繚";
+  });
+  const rectStatusText = computed(() =>
+    rectStatusLabel(rectSearch.rectificationStatus)
+  );
+
+  const recordTypeLabel = v => {
+    if (String(v) === "1") return "妫�楠�";
+    if (String(v) === "2") return "缁翠繚";
+    return "-";
+  };
+  const rectStatusLabel = v => {
+    const map = { 1: "寰呮暣鏀�", 2: "鏁存敼涓�", 3: "寰呭鏍�", 4: "宸查棴鐜�" };
+    return map[Number(v)] || "";
+  };
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const getCardTitle = row => {
+    if (activeTab.value === "ledger") return row.equipmentName || "-";
+    if (activeTab.value === "record") return row.recordNo || "-";
+    return row.hazardDescription || "-";
+  };
+
+  const resetAndQuery = () => {
+    page.current = 1;
+    page.total = 0;
+    list.value = [];
+    loadStatus.value = "loadmore";
+    exitSelectMode();
+    fetchList();
+  };
+
+  const fetchList = () => {
+    if (loading.value) return;
+    loading.value = true;
+    loadStatus.value = "loading";
+
+    const reqPage = { current: page.current, size: page.size };
+    let req;
+    if (activeTab.value === "ledger") {
+      req = specialEquipmentLedgerListPage({ ...ledgerSearch, ...reqPage });
+    } else if (activeTab.value === "record") {
+      req = specialEquipmentRecordListPage({ ...recordSearch, ...reqPage });
+    } else {
+      req = specialEquipmentRectificationListPage({ ...rectSearch, ...reqPage });
+    }
+
+    req
+      .then(res => {
+        const records = res?.data?.records || res?.data?.rows || [];
+        const total = Number(res?.data?.total || 0);
+        page.total = total;
+        list.value = page.current === 1 ? records : [...list.value, ...records];
+        loadStatus.value =
+          list.value.length >= page.total ? "nomore" : "loadmore";
+      })
+      .catch(() => {
+        loadStatus.value = "loadmore";
+        uni.showToast({ title: "鍔犺浇澶辫触", icon: "none" });
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+  };
+
+  const handleSearch = () => {
+    resetAndQuery();
+  };
+
+  const loadMore = () => {
+    if (loadStatus.value !== "loadmore") return;
+    page.current++;
+    fetchList();
+  };
+
+  const onTabChange = val => {
+    activeTabIndex.value = val.index;
+    resetAndQuery();
+  };
+
+  const ledgerQuery = () => {
+    resetAndQuery();
+  };
+
+  const enterSelectMode = () => {
+    selectMode.value = true;
+    selectedIds.value = [];
+  };
+
+  const exitSelectMode = () => {
+    selectMode.value = false;
+    selectedIds.value = [];
+  };
+
+  const toggleSelect = row => {
+    if (!row?.id) return;
+    const id = String(row.id);
+    const idx = selectedIds.value.indexOf(id);
+    if (idx >= 0) selectedIds.value.splice(idx, 1);
+    else selectedIds.value.push(id);
+  };
+
+  const deleteApi = ids => {
+    if (activeTab.value === "ledger") return specialEquipmentLedgerDel(ids);
+    if (activeTab.value === "record") return specialEquipmentRecordDel(ids);
+    return specialEquipmentRectificationDel(ids);
+  };
+
+  const deleteSelected = () => {
+    const ids = selectedIds.value.map(i => Number(i));
+    if (!ids.length) {
+      uni.showToast({ title: "璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁", icon: "none" });
+      return;
+    }
+    uni.showModal({
+      title: "鍒犻櫎纭",
+      content: "纭鍒犻櫎鎵�閫夋暟鎹悧锛�",
+      success: res => {
+        if (!res.confirm) return;
+        uni.showLoading({ title: "鍒犻櫎涓�...", mask: true });
+        deleteApi(ids)
+          .then(() => {
+            uni.showToast({ title: "鍒犻櫎鎴愬姛", icon: "success" });
+            exitSelectMode();
+            resetAndQuery();
+          })
+          .catch(() => {
+            uni.showToast({ title: "鍒犻櫎澶辫触", icon: "none" });
+          })
+          .finally(() => {
+            uni.hideLoading();
+          });
+      },
+    });
+  };
+
+  const deleteSingle = row => {
+    if (!row?.id) return;
+    uni.showModal({
+      title: "鍒犻櫎纭",
+      content: "纭鍒犻櫎璇ユ潯鏁版嵁鍚楋紵",
+      success: res => {
+        if (!res.confirm) return;
+        uni.showLoading({ title: "鍒犻櫎涓�...", mask: true });
+        deleteApi([row.id])
+          .then(() => {
+            uni.showToast({ title: "鍒犻櫎鎴愬姛", icon: "success" });
+            resetAndQuery();
+          })
+          .catch(() => {
+            uni.showToast({ title: "鍒犻櫎澶辫触", icon: "none" });
+          })
+          .finally(() => {
+            uni.hideLoading();
+          });
+      },
+    });
+  };
+
+  const goAdd = () => {
+    if (activeTab.value === "ledger") {
+      uni.navigateTo({
+        url: "/pages/safeProduction/specialEquipmentManagement/ledgerEdit",
+      });
+      return;
+    }
+    if (activeTab.value === "record") {
+      uni.navigateTo({
+        url: "/pages/safeProduction/specialEquipmentManagement/recordEdit",
+      });
+      return;
+    }
+    uni.navigateTo({
+      url: "/pages/safeProduction/specialEquipmentManagement/rectificationEdit",
+    });
+  };
+
+  const goEdit = row => {
+    if (!row?.id) return;
+    const data = encodeURIComponent(JSON.stringify(row));
+    if (activeTab.value === "ledger") {
+      uni.navigateTo({
+        url: `/pages/safeProduction/specialEquipmentManagement/ledgerEdit?data=${data}`,
+      });
+      return;
+    }
+    if (activeTab.value === "record") {
+      uni.navigateTo({
+        url: `/pages/safeProduction/specialEquipmentManagement/recordEdit?data=${data}`,
+      });
+      return;
+    }
+  };
+
+  const onSelectRecordType = action => {
+    recordSearch.recordType = action.value;
+    showRecordTypeSheet.value = false;
+    resetAndQuery();
+  };
+
+  const onSelectRectStatus = action => {
+    rectSearch.rectificationStatus = action.value;
+    showRectStatusSheet.value = false;
+    resetAndQuery();
+  };
+
+  onMounted(() => {
+    resetAndQuery();
+  });
+
+  onShow(() => {
+    resetAndQuery();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "../../../styles/sales-common.scss";
+
+  .special-equipment {
+    min-height: 100vh;
+    background: #f8f9fa;
+    position: relative;
+    padding-bottom: 140rpx;
+  }
+
+  .tabs-section {
+    background: #fff;
+    padding: 0 12px 8px 12px;
+  }
+
+  .header-right {
+    display: flex;
+    align-items: center;
+    padding-right: 12rpx;
+  }
+
+  .list-scroll {
+    flex: 1;
+    min-height: 0;
+    padding: 0 0 20rpx 0;
+  }
+
+  .card {
+    background: #fff;
+    border-radius: 16rpx;
+    padding: 24rpx;
+    margin: 20rpx;
+    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+  }
+
+  .card-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 12rpx;
+  }
+
+  .title {
+    font-size: 28rpx;
+    font-weight: 600;
+    color: #333;
+    flex: 1;
+    min-width: 0;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .card-body {
+    padding: 10rpx 0;
+  }
+
+  .row {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 12rpx;
+  }
+
+  .label {
+    font-size: 26rpx;
+    color: #999;
+  }
+
+  .value {
+    font-size: 26rpx;
+    color: #333;
+    text-align: right;
+    max-width: 70%;
+    word-break: break-all;
+  }
+
+  .actions {
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    gap: 16rpx;
+    padding-top: 16rpx;
+    border-top: 1rpx solid #f0f0f0;
+  }
+
+  .fab-button {
+    position: fixed;
+    right: 30rpx;
+    bottom: 140rpx;
+    width: 96rpx;
+    height: 96rpx;
+    background: #3c9cff;
+    border-radius: 48rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0 8rpx 24rpx rgba(60, 156, 255, 0.3);
+    z-index: 1001;
+  }
+
+  .no-data {
+    padding-top: 200rpx;
+  }
+
+  .card-header .right :deep(.up-checkbox__label) {
+    display: none;
+  }
+  .u-border,
+  .up-border {
+    border: none !important;
+  }
+</style>
diff --git a/src/pages/safeProduction/specialEquipmentManagement/ledgerEdit.vue b/src/pages/safeProduction/specialEquipmentManagement/ledgerEdit.vue
new file mode 100644
index 0000000..45a9548
--- /dev/null
+++ b/src/pages/safeProduction/specialEquipmentManagement/ledgerEdit.vue
@@ -0,0 +1,145 @@
+<template>
+  <view class="account-detail">
+    <PageHeader :title="pageTitle" @back="goBack" />
+    <up-form ref="formRef" :model="form" label-width="110">
+      <up-form-item label="璁惧缂栧彿" required>
+        <up-input v-model="form.equipmentNo" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="璁惧鍚嶇О" required>
+        <up-input v-model="form.equipmentName" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="璁惧绫诲埆">
+        <up-input v-model="form.equipmentType" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="瑙勬牸鍨嬪彿">
+        <up-input v-model="form.modelSpec" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="瀹夎浣嶇疆">
+        <up-input v-model="form.installLocation" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="浣跨敤鍗曚綅">
+        <up-input v-model="form.useUnit" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="璐熻矗浜�">
+        <up-input v-model="managerName" placeholder="璇烽�夋嫨" readonly @click="showManagerSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showManagerSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+    </up-form>
+
+    <FooterButtons :loading="loading" confirmText="淇濆瓨" @cancel="goBack" @confirm="handleSubmit" />
+
+    <up-action-sheet
+      :show="showManagerSheet"
+      title="閫夋嫨璐熻矗浜�"
+      :actions="managerActions"
+      @select="onSelectManager"
+      @close="showManagerSheet = false"
+    />
+  </view>
+</template>
+
+<script setup>
+  import { computed, onMounted, ref } from "vue";
+  import { onLoad } from "@dcloudio/uni-app";
+  import FooterButtons from "@/components/FooterButtons.vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import { userListNoPageByTenantId } from "@/api/system/user";
+  import {
+    specialEquipmentLedgerAdd,
+    specialEquipmentLedgerUpdate,
+  } from "@/api/safeProduction/specialEquipmentManagement";
+
+  const formRef = ref();
+  const loading = ref(false);
+  const showManagerSheet = ref(false);
+  const managerActions = ref([]);
+  const managerName = ref("");
+
+  const form = ref({
+    id: "",
+    equipmentNo: "",
+    equipmentName: "",
+    equipmentType: "",
+    modelSpec: "",
+    installLocation: "",
+    useUnit: "",
+    managerId: "",
+    managerName: "",
+  });
+
+  const pageTitle = computed(() => (form.value.id ? "缂栬緫鍙拌处" : "鏂板鍙拌处"));
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const loadUsers = () => {
+    userListNoPageByTenantId()
+      .then(res => {
+        const rows = Array.isArray(res?.data) ? res.data : [];
+        managerActions.value = rows.map(u => ({
+          name: u.nickName || u.userName || "",
+          value: u.userId,
+        }));
+      })
+      .catch(() => {
+        managerActions.value = [];
+      });
+  };
+
+  const onSelectManager = action => {
+    form.value.managerId = action.value;
+    form.value.managerName = action.name;
+    managerName.value = action.name;
+    showManagerSheet.value = false;
+  };
+
+  const handleSubmit = async () => {
+    const equipmentNo = String(form.value.equipmentNo || "").trim();
+    if (!equipmentNo) {
+      uni.showToast({ title: "璇疯緭鍏ヨ澶囩紪鍙�", icon: "none" });
+      return;
+    }
+    const equipmentName = String(form.value.equipmentName || "").trim();
+    if (!equipmentName) {
+      uni.showToast({ title: "璇疯緭鍏ヨ澶囧悕绉�", icon: "none" });
+      return;
+    }
+
+    loading.value = true;
+    const api = form.value.id ? specialEquipmentLedgerUpdate : specialEquipmentLedgerAdd;
+    api({ ...form.value, equipmentNo, equipmentName })
+      .then(() => {
+        uni.showToast({ title: "淇濆瓨鎴愬姛", icon: "success" });
+        uni.$emit("specialEquipmentManagement:refresh");
+        goBack();
+      })
+      .catch(() => {
+        uni.showToast({ title: "淇濆瓨澶辫触", icon: "none" });
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+  };
+
+  onLoad(options => {
+    if (!options?.data) return;
+    try {
+      const row = JSON.parse(decodeURIComponent(options.data));
+      form.value = { ...form.value, ...(row || {}) };
+      managerName.value = form.value.managerName || "";
+    } catch {
+      uni.showToast({ title: "鏁版嵁鍔犺浇澶辫触", icon: "none" });
+    }
+  });
+
+  onMounted(() => {
+    loadUsers();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+</style>
diff --git a/src/pages/safeProduction/specialEquipmentManagement/recordEdit.vue b/src/pages/safeProduction/specialEquipmentManagement/recordEdit.vue
new file mode 100644
index 0000000..4c81a55
--- /dev/null
+++ b/src/pages/safeProduction/specialEquipmentManagement/recordEdit.vue
@@ -0,0 +1,275 @@
+<template>
+  <view class="account-detail">
+    <PageHeader :title="pageTitle" @back="goBack" />
+    <up-form ref="formRef" :model="form" label-width="110">
+      <up-form-item label="鍏宠仈璁惧" required>
+        <up-input v-model="equipmentText" placeholder="璇烽�夋嫨" readonly @click="showEquipmentSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showEquipmentSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="璁板綍绫诲瀷" required>
+        <up-input v-model="recordTypeText" placeholder="璇烽�夋嫨" readonly @click="showRecordTypeSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showRecordTypeSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="璁板綍缂栧彿" required>
+        <up-input v-model="form.recordNo" placeholder="璇疯緭鍏�" clearable />
+      </up-form-item>
+      <up-form-item label="璁板綍鏃ユ湡" required>
+        <up-input v-model="form.recordDate" placeholder="璇烽�夋嫨" readonly @click="showRecordDatePicker = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showRecordDatePicker = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鎵ц浜�" required>
+        <up-input v-model="executorText" placeholder="璇烽�夋嫨" readonly @click="showExecutorSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showExecutorSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="涓嬫鍒版湡鏃ユ湡">
+        <up-input v-model="form.nextDueDate" placeholder="璇烽�夋嫨" readonly @click="showNextDueDatePicker = true" />
+        <template #right>
+          <up-icon name="arrow-right" @click="showNextDueDatePicker = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鎵ц缁撴灉">
+        <up-textarea v-model="form.executeResult" placeholder="璇疯緭鍏�" auto-height />
+      </up-form-item>
+      <up-form-item label="闂鎻忚堪">
+        <up-textarea v-model="form.problemDescription" placeholder="璇疯緭鍏�" auto-height />
+      </up-form-item>
+      <up-form-item label="澶勭悊鎺柦">
+        <up-textarea v-model="form.disposeMeasure" placeholder="璇疯緭鍏�" auto-height />
+      </up-form-item>
+      <up-form-item label="闄勪欢璇存槑">
+        <up-textarea v-model="form.attachmentRemark" placeholder="璇疯緭鍏�" auto-height />
+      </up-form-item>
+    </up-form>
+
+    <FooterButtons :loading="loading" confirmText="淇濆瓨" @cancel="goBack" @confirm="handleSubmit" />
+
+    <up-action-sheet
+      :show="showEquipmentSheet"
+      title="閫夋嫨璁惧"
+      :actions="equipmentActions"
+      @select="onSelectEquipment"
+      @close="showEquipmentSheet = false"
+    />
+    <up-action-sheet
+      :show="showRecordTypeSheet"
+      title="閫夋嫨璁板綍绫诲瀷"
+      :actions="recordTypeActions"
+      @select="onSelectRecordType"
+      @close="showRecordTypeSheet = false"
+    />
+    <up-action-sheet
+      :show="showExecutorSheet"
+      title="閫夋嫨鎵ц浜�"
+      :actions="executorActions"
+      @select="onSelectExecutor"
+      @close="showExecutorSheet = false"
+    />
+
+    <up-datetime-picker
+      :show="showRecordDatePicker"
+      v-model="recordDateValue"
+      mode="date"
+      @confirm="onRecordDateConfirm"
+      @cancel="showRecordDatePicker = false"
+    />
+    <up-datetime-picker
+      :show="showNextDueDatePicker"
+      v-model="nextDueDateValue"
+      mode="date"
+      @confirm="onNextDueDateConfirm"
+      @cancel="showNextDueDatePicker = false"
+    />
+  </view>
+</template>
+
+<script setup>
+  import { computed, onMounted, ref } from "vue";
+  import { onLoad } from "@dcloudio/uni-app";
+  import FooterButtons from "@/components/FooterButtons.vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import { formatDateToYMD } from "@/utils/ruoyi";
+  import { userListNoPageByTenantId } from "@/api/system/user";
+  import {
+    specialEquipmentLedgerList,
+    specialEquipmentRecordAdd,
+    specialEquipmentRecordUpdate,
+  } from "@/api/safeProduction/specialEquipmentManagement";
+
+  const formRef = ref();
+  const loading = ref(false);
+
+  const showEquipmentSheet = ref(false);
+  const showRecordTypeSheet = ref(false);
+  const showExecutorSheet = ref(false);
+  const equipmentActions = ref([]);
+  const executorActions = ref([]);
+
+  const showRecordDatePicker = ref(false);
+  const showNextDueDatePicker = ref(false);
+  const recordDateValue = ref(Date.now());
+  const nextDueDateValue = ref(Date.now());
+
+  const equipmentText = ref("");
+  const recordTypeText = ref("");
+  const executorText = ref("");
+
+  const recordTypeActions = [
+    { name: "妫�楠�", value: 1 },
+    { name: "缁翠繚", value: 2 },
+  ];
+
+  const form = ref({
+    id: "",
+    equipmentId: "",
+    recordType: "",
+    recordNo: "",
+    recordDate: "",
+    executeResult: "",
+    problemDescription: "",
+    disposeMeasure: "",
+    executorId: "",
+    executorName: "",
+    nextDueDate: "",
+    attachmentRemark: "",
+  });
+
+  const pageTitle = computed(() => (form.value.id ? "缂栬緫璁板綍" : "鏂板璁板綍"));
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const loadEquipmentOptions = () => {
+    specialEquipmentLedgerList({})
+      .then(res => {
+        const rows = Array.isArray(res?.data) ? res.data : [];
+        equipmentActions.value = rows.map(r => ({
+          name: r.equipmentName || "",
+          value: r.id,
+          equipmentNo: r.equipmentNo,
+        }));
+      })
+      .catch(() => {
+        equipmentActions.value = [];
+      });
+  };
+
+  const loadUsers = () => {
+    userListNoPageByTenantId()
+      .then(res => {
+        const rows = Array.isArray(res?.data) ? res.data : [];
+        executorActions.value = rows.map(u => ({
+          name: u.nickName || u.userName || "",
+          value: u.userId,
+        }));
+      })
+      .catch(() => {
+        executorActions.value = [];
+      });
+  };
+
+  const onSelectEquipment = action => {
+    form.value.equipmentId = action.value;
+    equipmentText.value = action.equipmentNo ? `${action.name}(${action.equipmentNo})` : action.name;
+    showEquipmentSheet.value = false;
+  };
+
+  const onSelectRecordType = action => {
+    form.value.recordType = action.value;
+    recordTypeText.value = action.name;
+    showRecordTypeSheet.value = false;
+  };
+
+  const onSelectExecutor = action => {
+    form.value.executorId = action.value;
+    form.value.executorName = action.name;
+    executorText.value = action.name;
+    showExecutorSheet.value = false;
+  };
+
+  const onRecordDateConfirm = e => {
+    const value = e?.value ?? recordDateValue.value;
+    form.value.recordDate = formatDateToYMD(value);
+    showRecordDatePicker.value = false;
+  };
+
+  const onNextDueDateConfirm = e => {
+    const value = e?.value ?? nextDueDateValue.value;
+    form.value.nextDueDate = formatDateToYMD(value);
+    showNextDueDatePicker.value = false;
+  };
+
+  const normalizeTexts = () => {
+    if (form.value.recordType) {
+      recordTypeText.value = String(form.value.recordType) === "1" ? "妫�楠�" : "缁翠繚";
+    }
+    executorText.value = form.value.executorName || "";
+  };
+
+  const handleSubmit = async () => {
+    if (!form.value.equipmentId) {
+      uni.showToast({ title: "璇烽�夋嫨鍏宠仈璁惧", icon: "none" });
+      return;
+    }
+    if (!form.value.recordType) {
+      uni.showToast({ title: "璇烽�夋嫨璁板綍绫诲瀷", icon: "none" });
+      return;
+    }
+    const recordNo = String(form.value.recordNo || "").trim();
+    if (!recordNo) {
+      uni.showToast({ title: "璇疯緭鍏ヨ褰曠紪鍙�", icon: "none" });
+      return;
+    }
+    if (!form.value.recordDate) {
+      uni.showToast({ title: "璇烽�夋嫨璁板綍鏃ユ湡", icon: "none" });
+      return;
+    }
+    if (!form.value.executorId) {
+      uni.showToast({ title: "璇烽�夋嫨鎵ц浜�", icon: "none" });
+      return;
+    }
+
+    loading.value = true;
+    const api = form.value.id ? specialEquipmentRecordUpdate : specialEquipmentRecordAdd;
+    api({ ...form.value, recordNo })
+      .then(() => {
+        uni.showToast({ title: "淇濆瓨鎴愬姛", icon: "success" });
+        uni.$emit("specialEquipmentManagement:refresh");
+        goBack();
+      })
+      .catch(() => {
+        uni.showToast({ title: "淇濆瓨澶辫触", icon: "none" });
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+  };
+
+  onLoad(options => {
+    if (!options?.data) return;
+    try {
+      const row = JSON.parse(decodeURIComponent(options.data));
+      form.value = { ...form.value, ...(row || {}) };
+      normalizeTexts();
+    } catch {
+      uni.showToast({ title: "鏁版嵁鍔犺浇澶辫触", icon: "none" });
+    }
+  });
+
+  onMounted(() => {
+    loadEquipmentOptions();
+    loadUsers();
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+</style>
diff --git a/src/pages/safeProduction/specialEquipmentManagement/rectificationEdit.vue b/src/pages/safeProduction/specialEquipmentManagement/rectificationEdit.vue
new file mode 100644
index 0000000..0550151
--- /dev/null
+++ b/src/pages/safeProduction/specialEquipmentManagement/rectificationEdit.vue
@@ -0,0 +1,310 @@
+<template>
+  <view class="account-detail">
+    <PageHeader title="鏂板鏁存敼"
+                @back="goBack" />
+    <up-form ref="formRef"
+             :model="form"
+             label-width="110">
+      <up-form-item label="鍏宠仈璁惧"
+                    required>
+        <up-input v-model="equipmentText"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showEquipmentSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showEquipmentSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="椋庨櫓绛夌骇"
+                    required>
+        <up-input v-model="riskLevelText"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showRiskLevelSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showRiskLevelSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鍙戠幇鏃ユ湡"
+                    required>
+        <up-input v-model="form.discoveredDate"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showDiscoveredDatePicker = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showDiscoveredDatePicker = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鏁存敼鏈熼檺"
+                    required>
+        <up-input v-model="form.rectificationDeadline"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showDeadlinePicker = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showDeadlinePicker = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鏁存敼璐d换浜�">
+        <up-input v-model="responsibleUserText"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showResponsibleUserSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showResponsibleUserSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="鏁存敼鐘舵��">
+        <up-input v-model="rectStatusText"
+                  placeholder="璇烽�夋嫨"
+                  readonly
+                  @click="showRectStatusSheet = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showRectStatusSheet = true"></up-icon>
+        </template>
+      </up-form-item>
+      <up-form-item label="闅愭偅鎻忚堪"
+                    required>
+        <up-textarea v-model="form.hazardDescription"
+                     placeholder="璇疯緭鍏�"
+                     auto-height />
+      </up-form-item>
+      <up-form-item label="鏁存敼鎺柦">
+        <up-textarea v-model="form.rectificationMeasures"
+                     placeholder="璇疯緭鍏�"
+                     auto-height />
+      </up-form-item>
+      <up-form-item label="鏁存敼缁撴灉">
+        <up-textarea v-model="form.rectificationResult"
+                     placeholder="璇疯緭鍏�"
+                     auto-height />
+      </up-form-item>
+      <up-form-item label="澶囨敞">
+        <up-textarea v-model="form.remarks"
+                     placeholder="璇疯緭鍏�"
+                     auto-height />
+      </up-form-item>
+    </up-form>
+    <FooterButtons :loading="loading"
+                   confirmText="淇濆瓨"
+                   @cancel="goBack"
+                   @confirm="handleSubmit" />
+    <up-action-sheet :show="showEquipmentSheet"
+                     title="閫夋嫨璁惧"
+                     :actions="equipmentActions"
+                     @select="onSelectEquipment"
+                     @close="showEquipmentSheet = false" />
+    <up-action-sheet :show="showRiskLevelSheet"
+                     title="閫夋嫨椋庨櫓绛夌骇"
+                     :actions="riskLevelActions"
+                     @select="onSelectRiskLevel"
+                     @close="showRiskLevelSheet = false" />
+    <up-action-sheet :show="showResponsibleUserSheet"
+                     title="閫夋嫨鏁存敼璐d换浜�"
+                     :actions="responsibleUserActions"
+                     @select="onSelectResponsibleUser"
+                     @close="showResponsibleUserSheet = false" />
+    <up-action-sheet :show="showRectStatusSheet"
+                     title="閫夋嫨鏁存敼鐘舵��"
+                     :actions="rectStatusActions"
+                     @select="onSelectRectStatus"
+                     @close="showRectStatusSheet = false" />
+    <up-datetime-picker :show="showDiscoveredDatePicker"
+                        v-model="discoveredDateValue"
+                        mode="date"
+                        @confirm="onDiscoveredDateConfirm"
+                        @cancel="showDiscoveredDatePicker = false" />
+    <up-datetime-picker :show="showDeadlinePicker"
+                        v-model="deadlineValue"
+                        mode="date"
+                        @confirm="onDeadlineConfirm"
+                        @cancel="showDeadlinePicker = false" />
+  </view>
+</template>
+
+<script setup>
+  import { onMounted, ref } from "vue";
+  import FooterButtons from "@/components/FooterButtons.vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import { formatDateToYMD } from "@/utils/ruoyi";
+  import { userListNoPageByTenantId } from "@/api/system/user";
+  import {
+    specialEquipmentLedgerList,
+    specialEquipmentRectificationAdd,
+  } from "@/api/safeProduction/specialEquipmentManagement";
+
+  const formRef = ref();
+  const loading = ref(false);
+
+  const equipmentActions = ref([]);
+  const responsibleUserActions = ref([]);
+
+  const showEquipmentSheet = ref(false);
+  const showRiskLevelSheet = ref(false);
+  const showResponsibleUserSheet = ref(false);
+  const showRectStatusSheet = ref(false);
+
+  const showDiscoveredDatePicker = ref(false);
+  const showDeadlinePicker = ref(false);
+  const discoveredDateValue = ref(Date.now());
+  const deadlineValue = ref(Date.now());
+
+  const equipmentText = ref("");
+  const riskLevelText = ref("");
+  const responsibleUserText = ref("");
+  const rectStatusText = ref("寰呮暣鏀�");
+
+  const riskLevelActions = [
+    { name: "浣�", value: "浣�" },
+    { name: "涓�", value: "涓�" },
+    { name: "楂�", value: "楂�" },
+  ];
+  const rectStatusActions = [
+    { name: "寰呮暣鏀�", value: 1 },
+    { name: "鏁存敼涓�", value: 2 },
+    { name: "寰呭鏍�", value: 3 },
+    { name: "宸查棴鐜�", value: 4 },
+  ];
+
+  const form = ref({
+    id: "",
+    equipmentId: "",
+    hazardDescription: "",
+    riskLevel: "",
+    discoveredDate: "",
+    responsibleUserId: "",
+    responsibleUserName: "",
+    rectificationDeadline: "",
+    rectificationStatus: 1,
+    rectificationMeasures: "",
+    rectificationResult: "",
+    remarks: "",
+  });
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const loadEquipmentOptions = () => {
+    specialEquipmentLedgerList({})
+      .then(res => {
+        const rows = Array.isArray(res?.data) ? res.data : [];
+        equipmentActions.value = rows.map(r => ({
+          name: r.equipmentName || "",
+          value: r.id,
+          equipmentNo: r.equipmentNo,
+        }));
+      })
+      .catch(() => {
+        equipmentActions.value = [];
+      });
+  };
+
+  const loadUsers = () => {
+    userListNoPageByTenantId()
+      .then(res => {
+        const rows = Array.isArray(res?.data) ? res.data : [];
+        responsibleUserActions.value = rows.map(u => ({
+          name: u.nickName || u.userName || "",
+          value: u.userId,
+        }));
+      })
+      .catch(() => {
+        responsibleUserActions.value = [];
+      });
+  };
+
+  const onSelectEquipment = action => {
+    form.value.equipmentId = action.value;
+    equipmentText.value = action.equipmentNo
+      ? `${action.name}(${action.equipmentNo})`
+      : action.name;
+    showEquipmentSheet.value = false;
+  };
+
+  const onSelectRiskLevel = action => {
+    form.value.riskLevel = action.value;
+    riskLevelText.value = action.name;
+    showRiskLevelSheet.value = false;
+  };
+
+  const onSelectResponsibleUser = action => {
+    form.value.responsibleUserId = action.value;
+    form.value.responsibleUserName = action.name;
+    responsibleUserText.value = action.name;
+    showResponsibleUserSheet.value = false;
+  };
+
+  const onSelectRectStatus = action => {
+    form.value.rectificationStatus = action.value;
+    rectStatusText.value = action.name;
+    showRectStatusSheet.value = false;
+  };
+
+  const onDiscoveredDateConfirm = e => {
+    const value = e?.value ?? discoveredDateValue.value;
+    form.value.discoveredDate = formatDateToYMD(value);
+    showDiscoveredDatePicker.value = false;
+  };
+
+  const onDeadlineConfirm = e => {
+    const value = e?.value ?? deadlineValue.value;
+    form.value.rectificationDeadline = formatDateToYMD(value);
+    showDeadlinePicker.value = false;
+  };
+
+  const handleSubmit = async () => {
+    if (!form.value.equipmentId) {
+      uni.showToast({ title: "璇烽�夋嫨鍏宠仈璁惧", icon: "none" });
+      return;
+    }
+    if (!form.value.riskLevel) {
+      uni.showToast({ title: "璇烽�夋嫨椋庨櫓绛夌骇", icon: "none" });
+      return;
+    }
+    if (!form.value.discoveredDate) {
+      uni.showToast({ title: "璇烽�夋嫨鍙戠幇鏃ユ湡", icon: "none" });
+      return;
+    }
+    if (!form.value.rectificationDeadline) {
+      uni.showToast({ title: "璇烽�夋嫨鏁存敼鏈熼檺", icon: "none" });
+      return;
+    }
+    const hazardDescription = String(form.value.hazardDescription || "").trim();
+    if (!hazardDescription) {
+      uni.showToast({ title: "璇疯緭鍏ラ殣鎮f弿杩�", icon: "none" });
+      return;
+    }
+
+    loading.value = true;
+    specialEquipmentRectificationAdd({ ...form.value, hazardDescription })
+      .then(() => {
+        uni.showToast({ title: "淇濆瓨鎴愬姛", icon: "success" });
+        uni.$emit("specialEquipmentManagement:refresh");
+        goBack();
+      })
+      .catch(() => {
+        uni.showToast({ title: "淇濆瓨澶辫触", icon: "none" });
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+  };
+
+  onMounted(() => {
+    loadEquipmentOptions();
+    loadUsers();
+    rectStatusText.value = "寰呮暣鏀�";
+    form.value.rectificationStatus = 1;
+  });
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+</style>
diff --git a/src/pages/works.vue b/src/pages/works.vue
index fc7eed5..c484e70 100644
--- a/src/pages/works.vue
+++ b/src/pages/works.vue
@@ -507,6 +507,10 @@
       label: "瑙勭▼涓庤祫璐�",
     },
     {
+      icon: "/static/images/icon/yunxingguanli.svg",
+      label: "鐗圭璁惧绠$悊",
+    },
+    {
       icon: "/static/images/icon/weixianyuan.svg",
       label: "鍗遍櫓婧愬彴璐�",
     },
@@ -935,6 +939,11 @@
           url: "/pages/safeProduction/safeQualifications/index",
         });
         break;
+      case "鐗圭璁惧绠$悊":
+        uni.navigateTo({
+          url: "/pages/safeProduction/specialEquipmentManagement/index",
+        });
+        break;
       case "鍗遍櫓婧愬彴璐�":
         uni.navigateTo({
           url: "/pages/safeProduction/hazardSourceLedger/index",

--
Gitblit v1.9.3