From 1e6748fbf03f44ff06967bc887076dea1f1c6e33 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 22 十二月 2025 18:57:48 +0800
Subject: [PATCH] 海川开心添加通知公告模块

---
 src/pages/index.vue                                    |   11 
 src/pages/cooperativeOffice/noticeManagement/index.vue |  813 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pages.json                                         |   11 
 src/api/collaborativeApproval/noticeManagement.js      |   35 -
 4 files changed, 841 insertions(+), 29 deletions(-)

diff --git a/src/api/collaborativeApproval/noticeManagement.js b/src/api/collaborativeApproval/noticeManagement.js
index fa1caec..a1a2a2c 100644
--- a/src/api/collaborativeApproval/noticeManagement.js
+++ b/src/api/collaborativeApproval/noticeManagement.js
@@ -3,7 +3,7 @@
 // 鏌ヨ鍏憡鍒楄〃
 export function listNotice(query) {
   return request({
-    url: '/collaborativeApproval/notice/list',
+    url: '/collaborativeApproval/notice/page',
     method: 'get',
     params: query
   })
@@ -20,7 +20,7 @@
 // 鏂板鍏憡
 export function addNotice(data) {
   return request({
-    url: '/collaborativeApproval/notice',
+    url: '/collaborativeApproval/notice/add',
     method: 'post',
     data: data
   })
@@ -29,41 +29,24 @@
 // 淇敼鍏憡
 export function updateNotice(data) {
   return request({
-    url: '/collaborativeApproval/notice',
+    url: '/collaborativeApproval/notice/update',
     method: 'put',
     data: data
   })
 }
 
 // 鍒犻櫎鍏憡
-export function delNotice(noticeId) {
+export function delNotice(ids) {
   return request({
-    url: '/collaborativeApproval/notice/' + noticeId,
-    method: 'delete'
-  })
-}
-
-// 鎵归噺鍒犻櫎鍏憡
-export function delNoticeBatch(noticeIds) {
-  return request({
-    url: '/collaborativeApproval/notice/batch',
+    url: '/collaborativeApproval/notice/' + ids,
     method: 'delete',
-    data: noticeIds
   })
 }
 
-// 鍙戝竷鍏憡
-export function publishNotice(noticeId) {
+// 鑾峰彇鍏憡鏁伴噺
+export function getCount() {
   return request({
-    url: '/collaborativeApproval/notice/publish/' + noticeId,
-    method: 'put'
-  })
-}
-
-// 涓嬬嚎鍏憡
-export function offlineNotice(noticeId) {
-  return request({
-    url: '/collaborativeApproval/notice/offline/' + noticeId,
-    method: 'put'
+    url: '/collaborativeApproval/notice/count',
+    method: 'get',
   })
 }
diff --git a/src/pages.json b/src/pages.json
index 7df8341..56ad7b3 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -317,6 +317,13 @@
       }
     },
     {
+      "path": "pages/cooperativeOffice/noticeManagement/index",
+      "style": {
+        "navigationBarTitleText": "閫氱煡鍏憡",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/equipmentManagement/ledger/index",
       "style": {
         "navigationBarTitleText": "璁惧鍙拌处",
@@ -412,8 +419,8 @@
       "style": {
         "navigationBarTitleText": "宸℃涓婁紶",
         "navigationStyle": "custom",
-				"enablePullDownRefresh": true, // 寮�鍚笅鎷夊埛鏂�
-				"backgroundColor": "#f8f8f8" // 涓嬫媺鍒锋柊鏃剁殑鑳屾櫙鑹�
+				"enablePullDownRefresh": true,
+				"backgroundColor": "#f8f8f8"
       }
     },
     {
diff --git a/src/pages/cooperativeOffice/noticeManagement/index.vue b/src/pages/cooperativeOffice/noticeManagement/index.vue
new file mode 100644
index 0000000..b08a739
--- /dev/null
+++ b/src/pages/cooperativeOffice/noticeManagement/index.vue
@@ -0,0 +1,813 @@
+<template>
+  <view class="notice-page">
+    <PageHeader title="閫氱煡鍏憡" @back="goBack" />
+    <!-- 鎼滅储琛ㄥ崟 -->
+    <!-- <view class="search_form">
+      <up-button type="primary" size="small" @click="openForm('add')">鏂板鍏憡</up-button>
+        <up-button type="error" size="small" plain @click="handleDeleteBatch" :disabled="!selectedIds.length">
+          鍒犻櫎
+        </up-button>
+    </view> -->
+
+    <!-- 閫氱煡鍏憡鏉� -->
+    <view class="notice-board">
+      <!-- 缁熶竴閫氱煡鍖哄煙 -->
+      <view class="notice-section" v-if="totalNoticeCount > 0">
+        <view class="section-header">
+          <h3>锟� 閫氱煡鍏憡</h3>
+          <text class="section-count">{{ totalNoticeCount }}鏉�</text>
+        </view>
+        <view class="notice-cards">
+          <!-- 鏀惧亣閫氱煡 -->
+          <view
+              v-for="notice in holidayNotices"
+              :key="'holiday-' + notice.id"
+              class="notice-card holiday-card"
+              :class="{ 'urgent': notice.priority === '3' }"
+          >
+            <view class="card-header">
+              <view class="card-title">
+                <view class="holiday-icon">
+                  <up-icon name="calendar" size="18" color="#67c23a" />
+                </view>
+                <text>{{ notice.title }}</text>
+              </view>
+<!--              <view class="card-actions">-->
+<!--                <up-button-->
+<!--                  text-->
+<!--                  type="primary"-->
+<!--                  size="mini"-->
+<!--                  @click="handleEdit(notice)"-->
+<!--                  :disabled="isNoticeExpired(notice)"-->
+<!--                >-->
+<!--                  缂栬緫-->
+<!--                </up-button>-->
+<!--                <up-button-->
+<!--                  text-->
+<!--                  type="error"-->
+<!--                  size="mini"-->
+<!--                  @click="handleDelete(notice.id)"-->
+<!--                >-->
+<!--                  鍒犻櫎-->
+<!--                </up-button>-->
+<!--              </view>-->
+            </view>
+            <view class="card-content">
+              <text>{{ notice.content }}</text>
+            </view>
+            <view class="card-footer">
+              <view class="card-meta">
+                <text class="type" :class="'type-' + notice.type">
+                  {{ notice.type }}
+                </text>
+                <text class="priority" :class="'priority-' + notice.priority">
+                  {{ getPriorityText(notice.priority) }}
+                </text>
+                <text class="status" :class="'status-' + getNoticeStatus(notice)">
+                  {{ getStatusText(getNoticeStatus(notice)) }}
+                </text>
+              </view>
+              <view class="card-info">
+                <text class="creator">{{ notice.createUserName }}</text>
+                <text class="expiration" v-if="notice.expirationDate">鎴鏃ユ湡锛歿{ notice.expirationDate }}</text>
+              </view>
+            </view>
+            <view class="card-remark" v-if="notice.remark">
+              <up-icon name="info-circle" size="16" color="#409eff" />
+              <text>{{ notice.remark }}</text>
+            </view>
+          </view>
+          
+          <!-- 璁惧缁翠慨閫氱煡 -->
+          <view
+              v-for="notice in maintenanceNotices"
+              :key="'maintenance-' + notice.id"
+              class="notice-card maintenance-card"
+              :class="{ 'urgent': notice.priority === '3' }"
+          >
+            <view class="card-header">
+              <view class="card-title">
+                <view class="maintenance-icon">
+                  <up-icon name="wrench" size="18" color="#e6a23c" />
+                </view>
+                <text>{{ notice.title }}</text>
+              </view>
+              <view class="card-actions">
+                <up-button
+                  text
+                  type="primary"
+                  size="mini"
+                  @click="handleEdit(notice)"
+                  :disabled="isNoticeExpired(notice)"
+                >
+                  缂栬緫
+                </up-button>
+                <up-button
+                  text
+                  type="error"
+                  size="mini"
+                  @click="handleDelete(notice.id)"
+                >
+                  鍒犻櫎
+                </up-button>
+              </view>
+            </view>
+            <view class="card-content">
+              <text>{{ notice.content }}</text>
+            </view>
+            <view class="card-footer">
+              <view class="card-meta">
+                <text class="priority" :class="'priority-' + notice.priority">
+                  {{ getPriorityText(notice.priority) }}
+                </text>
+                <text class="status" :class="'status-' + getNoticeStatus(notice)">
+                  {{ getStatusText(getNoticeStatus(notice)) }}
+                </text>
+              </view>
+              <view class="card-info">
+                <text class="creator">{{ notice.createUserName }}</text>
+                <text class="expiration" v-if="notice.expirationDate">鎴鏃ユ湡锛歿{ notice.expirationDate }}</text>
+              </view>
+            </view>
+            <view class="card-remark" v-if="notice.remark">
+              <up-icon name="info-circle" size="16" color="#409eff" />
+              <text>{{ notice.remark }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <!-- 绌虹姸鎬� -->
+      <view class="empty-state" v-if="holidayNotices.length === 0 && maintenanceNotices.length === 0">
+        <text>鏆傛棤閫氱煡鍏憡</text>
+      </view>
+    </view>
+
+    <!-- 鏂板/缂栬緫寮圭獥 -->
+    <up-popup
+      v-model:show="dialogVisible"
+      mode="bottom"
+      :round="18"
+      :safeAreaInsetBottom="true"
+      @close="resetForm"
+    >
+      <view class="dialog-container">
+        <view class="dialog-header">
+          <text class="dialog-title">{{ dialogTitle }}</text>
+        </view>
+        <view class="dialog-body">
+          <up-form
+            ref="formRef"
+            :model="form"
+            :rules="rules"
+            labelWidth="80"
+          >
+            <up-form-item label="鍏憡鏍囬" prop="title">
+              <up-input v-model="form.title" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" />
+            </up-form-item>
+            <up-form-item label="鍏憡绫诲瀷" prop="type">
+              <up-input v-model="form.type" placeholder="璇疯緭鍏ュ叕鍛婄被鍨�" />
+            </up-form-item>
+            <up-form-item label="鐘舵��">
+              <up-radio-group v-model="form.status">
+                <up-radio :name="0">鑽夌</up-radio>
+                <up-radio :name="1">姝e紡鍙戝竷</up-radio>
+              </up-radio-group>
+            </up-form-item>
+            <up-form-item label="浼樺厛绾�" prop="priority">
+              <up-select
+                v-model="form.priority"
+                :options="priorityOptions"
+                placeholder="璇烽�夋嫨浼樺厛绾�"
+              />
+            </up-form-item>
+            <up-form-item label="杩囨湡鏃堕棿" prop="expirationDate">
+              <up-datetime-picker
+                v-model="form.expirationDate"
+                mode="date"
+                @confirm="onExpireConfirm"
+              >
+                <up-input
+                  :value="form.expirationDate"
+                  placeholder="璇烽�夋嫨鏃ユ湡"
+                  readonly
+                />
+              </up-datetime-picker>
+            </up-form-item>
+            <up-form-item label="鍏憡鍐呭" prop="content">
+              <up-textarea
+                v-model="form.content"
+                placeholder="璇疯緭鍏ュ叕鍛婂唴瀹�"
+                :maxlength="500"
+                count
+              />
+            </up-form-item>
+            <up-form-item label="澶囨敞">
+              <up-textarea
+                v-model="form.remark"
+                placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+                :maxlength="200"
+                count
+              />
+            </up-form-item>
+          </up-form>
+        </view>
+        <view class="dialog-footer">
+          <up-button
+            text="鍙栨秷"
+            type="info"
+            plain
+            @click="dialogVisible = false"
+            :customStyle="{ marginRight: '10px', flex: 1 }"
+          />
+          <up-button
+            text="纭畾"
+            type="primary"
+            @click="submitForm"
+            :customStyle="{ flex: 1 }"
+          />
+        </view>
+      </view>
+    </up-popup>
+  </view>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive, toRefs } from "vue";
+import { onReachBottom } from "@dcloudio/uni-app";
+import PageHeader from "@/components/PageHeader.vue";
+import useUserStore from "@/store/modules/user";
+import {
+  addNotice,
+  delNotice,
+  getCount,
+  listNotice,
+  updateNotice
+} from "@/api/collaborativeApproval/noticeManagement.js";
+
+const userStore = useUserStore();
+
+// 鍝嶅簲寮忔暟鎹�
+const data = reactive({
+  searchForm: {
+    title: "",
+    type: undefined,
+    status: undefined,
+  },
+  form: {
+    id: undefined,
+    title: "",
+    type: null,
+    content: "",
+    status: 0,
+    priority: 1,
+    remark: "",
+		expirationDate: "",
+  },
+  rules: {
+    title: [
+      {required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur"}
+    ],
+    type: [
+      {required: true, message: "璇烽�夋嫨鍏憡绫诲瀷", trigger: "change"}
+    ],
+    content: [
+      {required: true, message: "鍏憡鍐呭涓嶈兘涓虹┖", trigger: "blur"}
+    ],
+		expirationDate: [
+      {required: true, message: "璇烽�夋嫨鏃ユ湡", trigger: "change"}
+    ]
+  }
+});
+
+const {searchForm, form, rules} = toRefs(data);
+
+// 椤甸潰鐘舵��
+const dialogVisible = ref(false);
+const dialogTitle = ref("");
+const selectedIds = ref([]);
+const formRef = ref();
+
+const priorityOptions = [
+  { label: "鏅��", value: 1 },
+  { label: "閲嶈", value: 2 },
+  { label: "绱ф��", value: 3 },
+];
+
+const goBack = () => {
+  uni.navigateBack();
+};
+
+const onExpireConfirm = (e) => {
+  if (!e) return;
+  // uview-plus datetime-picker confirm 浜嬩欢杩斿洖鐨� value
+  const value = e.value || e;
+  form.value.expirationDate = value;
+};
+
+
+const getPriorityText = (priority) => {
+  const priorityMap = {"1": "鏅��", "2": "閲嶈", "3": "绱ф��"};
+  return priorityMap[priority] || "鏅��";
+};
+
+const getStatusText = (status) => {
+  const statusMap = {"0": "鑽夌", "1": "宸插彂甯�", "2": "宸茶繃鏈�"};
+  return statusMap[status] || "鏈煡";
+};
+
+const isNoticeExpired = (notice) => {
+  if (!notice || !notice.expirationDate) {
+    return false;
+  }
+
+  const expiration = new Date(notice.expirationDate);
+
+  if (Number.isNaN(expiration.getTime())) {
+    return false;
+  }
+
+  expiration.setHours(23, 59, 59, 999);
+
+  return new Date() > expiration;
+};
+
+const getNoticeStatus = (notice) => {
+  const normalizedStatus = notice && notice.status !== undefined && notice.status !== null
+      ? String(notice.status)
+      : "0";
+
+  return isNoticeExpired(notice) ? "2" : normalizedStatus;
+};
+
+const openForm = (type) => {
+  if (type === 'add') {
+    dialogTitle.value = "鏂板鍏憡";
+    form.value = {
+      id: undefined,
+      title: "",
+      type: undefined,
+      content: "",
+      status: 0,
+      priority: 1,
+      remark: "",
+      expirationDate: "",
+    };
+  }
+  dialogVisible.value = true;
+};
+
+const handleEdit = (row) => {
+  if (isNoticeExpired(row)) {
+    uni.showToast({
+      title: "宸茶繃鏈熺殑鍏憡涓嶅彲缂栬緫",
+      icon: "none"
+    });
+    return;
+  }
+  dialogTitle.value = "缂栬緫鍏憡";
+  form.value = {...row};
+  dialogVisible.value = true;
+};
+
+const handleDelete = (id) => {
+  if (!id) return;
+  uni.showModal({
+    title: "鎻愮ず",
+    content: "纭鍒犻櫎杩欐潯鍏憡鍚楋紵",
+    success: (res) => {
+      if (res.confirm) {
+        delNotice(id).then(() => {
+          uni.showToast({
+            title: "鍒犻櫎鎴愬姛",
+            icon: "success"
+          });
+          resetTable();
+        });
+      }
+    }
+  });
+};
+
+// 棰勭暀鎵归噺鍒犻櫎锛堢洰鍓嶆湭瀹炵幇閫変腑閫昏緫锛屼粎鍗犱綅锛�
+const handleDeleteBatch = () => {
+  if (!selectedIds.value.length) return;
+  uni.showModal({
+    title: "鎻愮ず",
+    content: "纭鍒犻櫎閫変腑鐨勫叕鍛婂悧锛�",
+    success: (res) => {
+      if (res.confirm) {
+        // 鏍规嵁selectedIds鎵ц鎵归噺鍒犻櫎閫昏緫锛堝彲鎸夐渶鎵╁睍锛�
+      }
+    }
+  });
+};
+
+const submitForm = () => {
+  formRef.value.validate((valid) => {
+    if (valid) {
+      if (form.value.id) {
+        // 缂栬緫妯″紡
+        updateNotice(form.value).then(res => {
+          uni.showToast({
+            title: "淇敼鎴愬姛",
+            icon: "success"
+          });
+          resetTable();
+        })
+      } else {
+        // 鏂板妯″紡
+        addNotice(form.value).then(res => {
+          uni.showToast({
+            title: "鏂板鎴愬姛",
+            icon: "success"
+          });
+          resetTable();
+        })
+      }
+      dialogVisible.value = false;
+    }
+  });
+};
+
+const totalNoticeCount = ref(0)
+const fetchCount = () => {
+  getCount().then(res => {
+    totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0);
+  });
+}
+
+const holidayNotices = ref([])
+const maintenanceNotices = ref([])
+const holidayNoticePage = ref({
+  total: 0,
+  current: 1,
+  size: 9
+})
+
+const maintenanceNoticePage = ref({
+  total: 0,
+  current: 1,
+  size: 9
+})
+
+const isLoadingMore = ref(false)
+
+const fetchHolidayNotices = (append = false) => {
+  listNotice({...holidayNoticePage.value}).then(res => {
+    const records = res?.data?.records || []
+    holidayNoticePage.value.total = res?.data?.total || 0
+    if (append && holidayNotices.value.length) {
+      holidayNotices.value = [...holidayNotices.value, ...records]
+    } else {
+      holidayNotices.value = records
+    }
+  });
+};
+
+const fetchMaintenanceNotices = (append = false) => {
+  listNotice({...holidayNoticePage.value, type: 2}).then(res => {
+    const records = res?.data?.records || []
+    maintenanceNoticePage.value.total = res?.data?.total || 0
+    if (append && maintenanceNotices.value.length) {
+      maintenanceNotices.value = [...maintenanceNotices.value, ...records]
+    } else {
+      maintenanceNotices.value = records
+    }
+  });
+};
+
+const handleCurrentChange = (val) => {
+  holidayNoticePage.value.size = val.limit
+  holidayNoticePage.value.current = val.page
+  maintenanceNoticePage.value.size = val.limit
+  maintenanceNoticePage.value.current = val.page
+  fetchHolidayNotices()
+  fetchMaintenanceNotices()
+};
+
+const resetTable = () => {
+  holidayNoticePage.value.current = 1
+  holidayNoticePage.value.size = 9
+  maintenanceNoticePage.value.current = 1
+  maintenanceNoticePage.value.size = 9
+  fetchHolidayNotices()
+  fetchMaintenanceNotices()
+  fetchCount()
+};
+
+const resetForm = () => {
+  formRef.value?.resetFields();
+};
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  fetchCount()
+  fetchHolidayNotices()
+  fetchMaintenanceNotices()
+});
+
+// 涓婂垝鍔犺浇鏇村
+onReachBottom(() => {
+  if (isLoadingMore.value) return;
+  isLoadingMore.value = true;
+
+  holidayNoticePage.value.current += 1;
+  maintenanceNoticePage.value.current += 1;
+
+  Promise.all([
+    new Promise((resolve) => {
+      fetchHolidayNotices(true);
+      resolve();
+    }),
+    new Promise((resolve) => {
+      fetchMaintenanceNotices(true);
+      resolve();
+    })
+  ]).finally(() => {
+    isLoadingMore.value = false;
+  });
+});
+</script>
+
+<style scoped>
+.notice-page {
+  min-height: 100vh;
+  background: #f5f7fa;
+  padding-bottom: 16px;
+  display: flex;
+  flex-direction: column;
+}
+
+.search_form {
+  background: #ffffff;
+  padding: 12px 16px;
+  margin: 8px 12px 12px;
+  border-radius: 10px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.search_title {
+  font-weight: 500;
+  color: #333;
+  margin-right: 8px;
+}
+
+.ml10 {
+  margin-left: 10px;
+}
+
+.notice-board {
+  padding: 0 12px 16px;
+}
+
+.notice-section {
+  margin-bottom: 16px;
+}
+
+.section-header {
+  display: flex;
+  align-items: center;
+  margin: 4px 4px 12px;
+}
+
+.section-header h3 {
+  margin: 0;
+  color: #303133;
+  font-size: 16px;
+  font-weight: 600;
+}
+
+.section-count {
+  margin-left: 10px;
+  background: #409eff;
+  color: white;
+  padding: 2px 8px;
+  border-radius: 12px;
+  font-size: 12px;
+}
+
+.notice-cards {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+}
+
+.notice-card {
+  background: white;
+  border-radius: 12px;
+  padding: 14px 14px 10px;
+  box-shadow: 0 4px 10px rgba(15, 23, 42, 0.06);
+  transition: all 0.3s ease;
+  border-left: 4px solid transparent;
+}
+
+.notice-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+}
+
+.holiday-card {
+  border-left-color: #67c23a;
+}
+
+.maintenance-card {
+  border-left-color: #e6a23c;
+}
+
+.urgent {
+  border-left-color: #f56c6c;
+  background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%);
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  margin-bottom: 10px;
+}
+
+.card-title {
+  display: flex;
+  align-items: center;
+  font-size: 15px;
+  font-weight: 600;
+  color: #303133;
+  flex: 1;
+}
+
+.holiday-icon {
+  color: #67c23a;
+  margin-right: 8px;
+  font-size: 18px;
+}
+
+.maintenance-icon {
+  color: #e6a23c;
+  margin-right: 8px;
+  font-size: 18px;
+}
+
+.card-actions {
+  display: flex;
+  gap: 8px;
+}
+
+.card-content {
+  margin-bottom: 10px;
+}
+
+.card-content text {
+  color: #606266;
+  line-height: 1.6;
+  font-size: 13px;
+}
+
+.card-footer {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.card-meta {
+  display: flex;
+  gap: 8px;
+}
+
+.type, .priority, .status {
+  padding: 2px 8px;
+  border-radius: 12px;
+  font-size: 12px;
+  font-weight: 500;
+}
+
+.type-1 {
+  background: #f0f9ff;
+  color: #0369a1;
+}
+
+.type-2 {
+  background: #fef3c7;
+  color: #d97706;
+}
+
+.priority-1 {
+  background: #f0f9ff;
+  color: #0369a1;
+}
+
+.priority-2 {
+  background: #fef3c7;
+  color: #d97706;
+}
+
+.priority-3 {
+  background: #fef2f2;
+  color: #dc2626;
+}
+
+.status-0 {
+  background: #f3f4f6;
+  color: #6b7280;
+}
+
+.status-1 {
+  background: #d1fae5;
+  color: #059669;
+}
+
+.status-2 {
+  background: #fef3c7;
+  color: #d97706;
+}
+
+.card-info {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+  font-size: 12px;
+  color: #909399;
+}
+
+.creator {
+  font-weight: 500;
+  margin-bottom: 2px;
+}
+
+.expiration {
+  margin-top: 2px;
+}
+
+.card-remark {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 12px;
+  background: #f8f9fa;
+  border-radius: 6px;
+  font-size: 12px;
+  color: #606266;
+  border-left: 3px solid #409eff;
+}
+
+.empty-state {
+  text-align: center;
+  padding: 48px 16px;
+  color: #999;
+  font-size: 13px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+/* 绉诲姩绔脊绐楁牱寮� */
+.dialog-container {
+  background: #ffffff;
+  border-radius: 18px 18px 0 0;
+  max-height: 80vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.dialog-header {
+  padding: 16px 20px 8px 20px;
+}
+
+.dialog-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.dialog-body {
+  flex: 1;
+  padding: 0 16px 12px 16px;
+  overflow-y: auto;
+}
+
+.dialog-footer {
+  display: flex;
+  padding: 12px 16px 16px 16px;
+  border-top: 1px solid #f0f0f0;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .search_form {
+    flex-direction: column;
+    gap: 15px;
+    align-items: flex-start;
+  }
+
+  .search_form > div {
+    width: 100%;
+    display: flex;
+    gap: 10px;
+  }
+}
+</style>
diff --git a/src/pages/index.vue b/src/pages/index.vue
index e5f9c59..462b20e 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -261,7 +261,11 @@
 		{
 			icon: '/static/images/icon/kehubaifang@2x.png',
 			label: '瀹㈡埛鎷滆',
-		}
+		},
+		{
+			icon: '/static/images/icon/qingjiaguanli@2x.png',
+			label: '閫氱煡鍏憡',
+		},
 	]);
 	// 鍗忓悓鍔炲叕鍔熻兘鏁版嵁inventoryManagement/receiptManagement
 	const inventoryManagement = reactive([{
@@ -430,6 +434,11 @@
 					url: '/pages/cooperativeOffice/clientVisit/index'
 				});
 				break;
+			case '閫氱煡鍏憡':
+				uni.navigateTo({
+					url: '/pages/cooperativeOffice/noticeManagement/index'
+				});
+				break;
 			case '鑷畾涔夊叆搴�':
 				uni.navigateTo({
 					url: '/pages/inventoryManagement/receiptManagement/index'

--
Gitblit v1.9.3