From 3a0f25f9d38c08e1b78afedb2f67b7bb73f8c84f Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 01 七月 2026 17:15:45 +0800
Subject: [PATCH] 会议审批列表查不出,会议申请参会人列表查不出问题修改

---
 src/pages/oa/ApproveManage/approve-list/index.vue |  313 ++++++++++++++++++++++-----------------------------
 1 files changed, 136 insertions(+), 177 deletions(-)

diff --git a/src/pages/oa/ApproveManage/approve-list/index.vue b/src/pages/oa/ApproveManage/approve-list/index.vue
index fd5e142..40f9468 100644
--- a/src/pages/oa/ApproveManage/approve-list/index.vue
+++ b/src/pages/oa/ApproveManage/approve-list/index.vue
@@ -1,109 +1,94 @@
 <!--
   OA / 瀹℃壒绠$悊 / 瀹℃壒鍒楄〃
-  璺敱锛�/pages/oa/ApproveManage/approve-list/index
 -->
 <template>
-  <view class="approve-list-page sales-account">
+  <view class="oa-approval-page">
     <PageHeader title="瀹℃壒鍒楄〃"
                 @back="goBack" />
-    <view class="search-section">
-      <view class="search-bar">
-        <view class="search-input">
-          <up-input v-model="queryParams.keyword"
-                    class="search-text"
-                    placeholder="瀹℃壒鏍囬 / 瀹℃壒缂栧彿"
-                    clearable
-                    @confirm="handleSearch" />
-        </view>
-        <view class="filter-button"
-              @click="handleSearch">
-          <up-icon name="search"
-                   size="24"
-                   color="#999" />
-        </view>
+
+    <view class="oa-toolbar">
+      <view class="oa-filter-chip active-search">
+        <up-icon name="search"
+                 size="18"
+                 color="#666" />
+        <up-input v-model="queryParams.keyword"
+                  class="chip-input"
+                  placeholder="瀹℃壒鏍囬 / 瀹℃壒缂栧彿"
+                  clearable
+                  border="none"
+                  @confirm="handleSearch" />
+      </view>
+      <view class="oa-icon-btn"
+            @click="handleSearch">
+        <up-icon name="search"
+                 size="20"
+                 color="#2979ff" />
       </view>
     </view>
 
-    <scroll-view class="list-scroll"
+    <scroll-view class="oa-list-scroll"
                  scroll-y
                  :show-scrollbar="false"
+                 :style="{ height: listScrollHeight + 'px' }"
                  @scrolltolower="loadMore">
       <view v-if="list.length"
-            class="ledger-list">
+            class="oa-card-list">
         <view v-for="item in list"
               :key="item.id"
-              class="ledger-item">
-          <view class="item-header">
-            <view class="item-left">
-              <view class="document-icon">
-                <up-icon name="file-text"
-                         size="16"
-                         color="#ffffff" />
+              class="oa-card"
+              @click="openDetail(item)">
+          <view class="oa-card-head">
+            <view class="oa-card-title-wrap">
+              <text class="oa-card-title">{{ item.title || item.instanceNo || "-" }}</text>
+              <text v-if="item.templateName"
+                    class="oa-card-sub">{{ item.templateName }}</text>
+            </view>
+            <text :class="['oa-status', businessStatusClass(item.status)]">
+              {{ statusText(item.status) }}
+            </text>
+          </view>
+
+          <view class="oa-card-body">
+            <view class="oa-info-grid">
+              <view class="oa-info-row">
+                <text class="oa-info-label">瀹℃壒缂栧彿</text>
+                <text class="oa-info-value">{{ item.instanceNo || "-" }}</text>
               </view>
-              <text class="item-id">{{ item.title || item.instanceNo || "-" }}</text>
-            </view>
-            <u-tag :type="statusTagType(item.status)"
-                   :text="statusText(item.status)" />
-          </view>
-          <up-divider />
-          <view class="item-details">
-            <view class="detail-row">
-              <text class="detail-label">瀹℃壒缂栧彿</text>
-              <text class="detail-value">{{ item.instanceNo || "-" }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">妯℃澘鍚嶇О</text>
-              <text class="detail-value">{{ item.templateName || "-" }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">涓氬姟鍚嶇О</text>
-              <text class="detail-value">{{ item.businessName || "-" }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">鐢宠浜�</text>
-              <text class="detail-value">{{ item.applicantName || "-" }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">褰撳墠绾у埆</text>
-              <text class="detail-value">{{ formatLevel(item.currentLevel) }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">褰撳墠瀹℃壒浜�</text>
-              <text class="detail-value">{{ currentApproverName(item) }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">鐢宠鏃堕棿</text>
-              <text class="detail-value">{{ formatDateTime(item.applyTime) }}</text>
-            </view>
-            <view v-if="item.finishTime"
-                  class="detail-row">
-              <text class="detail-label">瀹屾垚鏃堕棿</text>
-              <text class="detail-value">{{ formatDateTime(item.finishTime) }}</text>
+              <view v-if="item.businessName"
+                    class="oa-info-row">
+                <text class="oa-info-label">涓氬姟鍚嶇О</text>
+                <text class="oa-info-value">{{ item.businessName }}</text>
+              </view>
+              <view class="oa-info-row">
+                <text class="oa-info-label">鐢宠浜�</text>
+                <text class="oa-info-value">{{ item.applicantName || "-" }}</text>
+              </view>
+              <view class="oa-info-row">
+                <text class="oa-info-label">褰撳墠瀹℃壒浜�</text>
+                <text class="oa-info-value">{{ currentApproverName(item) }}</text>
+              </view>
+              <view class="oa-info-row">
+                <text class="oa-info-label">鐢宠鏃堕棿</text>
+                <text class="oa-info-value">{{ formatDateTime(item.applyTime) }}</text>
+              </view>
             </view>
           </view>
+
           <view v-if="canModify(item) || item.isApprove"
-                class="action-buttons">
-            <up-button v-if="canModify(item)"
-                       class="action-btn"
-                       size="small"
-                       type="warning"
-                       plain
-                       @click.stop="goModify(item)">
-              缂栬緫
-            </up-button>
-            <up-button v-if="item.isApprove"
-                       class="action-btn"
-                       size="small"
-                       type="primary"
-                       @click.stop="handleApprove(item)">
-              瀹℃壒
-            </up-button>
+                class="oa-card-foot"
+                @click.stop>
+            <text v-if="canModify(item)"
+                  class="oa-foot-btn btn-edit"
+                  @click="goModify(item)">缂栬緫</text>
+            <text v-if="item.isApprove"
+                  class="oa-foot-btn btn-approve"
+                  @click="handleApprove(item)">瀹℃壒</text>
           </view>
         </view>
         <up-loadmore :status="pageStatus" />
       </view>
       <view v-else
-            class="empty-wrap">
+            class="oa-empty">
         <up-empty mode="list"
                   text="鏆傛棤瀹℃壒鏁版嵁" />
       </view>
@@ -119,71 +104,52 @@
 </template>
 
 <script setup>
-  import { reactive, ref } from "vue";
+  import { onMounted, reactive, ref } from "vue";
   import { onShow } from "@dcloudio/uni-app";
   import PageHeader from "@/components/PageHeader.vue";
   import { listApprovalInstancePage } from "@/api/oa/approvalInstance.js";
   import { OA_NAV } from "@/config/oaPaths.js";
   import useUserStore from "@/store/modules/user";
   import { parseTime } from "@/utils/ruoyi";
+  import {
+    businessStatusClass,
+    businessStatusText,
+    canModifyInstance,
+    stashInstanceRow,
+  } from "../../_utils/approveListUtils.js";
+  import {
+    inferReimburseModuleKeyFromInstance,
+    resolveFinReimbursementIdFromInstance,
+    stashReimburseEditFromApprove,
+  } from "../../_utils/reimburseApproveBridge.js";
 
-  const EDIT_STORAGE_KEY = "oa_approve_instance_edit_row";
   const userStore = useUserStore();
-
-  const queryParams = reactive({
-    keyword: "",
-  });
-
+  const queryParams = reactive({ keyword: "" });
   const list = ref([]);
   const pageStatus = ref("loadmore");
+  const page = reactive({ current: 1, size: 10, total: 0 });
+  const listScrollHeight = ref(400);
 
-  const page = reactive({
-    current: 1,
-    size: 10,
-    total: 0,
-  });
+  function calcListScrollHeight() {
+    const sys = uni.getSystemInfoSync();
+    const statusBar = sys.statusBarHeight || 0;
+    const navBar = 44;
+    const toolbar = 56;
+    const fabGap = 16;
+    listScrollHeight.value = Math.max(
+      200,
+      sys.windowHeight - statusBar - navBar - toolbar - fabGap
+    );
+  }
 
-  const STATUS_TEXT = {
-    PENDING: "杩涜涓�",
-    APPROVED: "宸查�氳繃",
-    REJECTED: "宸查┏鍥�",
-  };
-
-  const STATUS_TAG = {
-    PENDING: "warning",
-    APPROVED: "success",
-    REJECTED: "error",
-  };
-
-  const statusText = status => STATUS_TEXT[status] || status || "-";
-
-  const statusTagType = status => STATUS_TAG[status] || "info";
-
-  const formatLevel = level => {
-    if (level == null || level === "") return "-";
-    return `绗� ${level} 绾;
-  };
+  const statusText = status => businessStatusText(status);
 
   const formatDateTime = val => {
     if (!val) return "-";
     return parseTime(val, "{y}-{m}-{d} {h}:{i}:{s}") || String(val);
   };
 
-  /** 鏄惁鏈汉鍙戣捣鐨勫鎵癸紙鍏煎鍒楄〃鏈繑鍥� applicantId锛� */
-  const isOwnApplication = item => {
-    const uid = userStore.id;
-    if (item?.applicantId != null && uid != null && uid !== "") {
-      return String(item.applicantId) === String(uid);
-    }
-    const loginName = userStore.nickName || userStore.name;
-    if (loginName && item?.applicantName) {
-      return String(item.applicantName).trim() === String(loginName).trim();
-    }
-    return false;
-  };
-
-  /** 浠呫�岃繘琛屼腑銆嶄笖鏈汉鍙戣捣鏃跺彲缂栬緫锛堝凡閫氳繃/宸查┏鍥炰笉鏄剧ず缂栬緫锛� */
-  const canModify = item => item?.status === "PENDING" && isOwnApplication(item);
+  const canModify = item => canModifyInstance(item, userStore);
 
   const currentApproverName = item => {
     const tasks = item?.tasks;
@@ -204,31 +170,22 @@
         dto.instanceNo = keyword;
       }
     }
-    return {
-      page: {
-        current: page.current,
-        size: page.size,
-      },
-      approvalInstanceDto: dto,
-    };
+    return { current: page.current, size: page.size, ...dto };
   };
 
   const getList = () => {
     if (pageStatus.value === "loading" || pageStatus.value === "nomore") return;
-
     pageStatus.value = "loading";
     listApprovalInstancePage(buildListParams())
       .then(res => {
         const pageData = res?.data || {};
         const records = pageData.records || [];
         const total = pageData.total ?? 0;
-
         if (page.current === 1) {
           list.value = records;
         } else {
           list.value = [...list.value, ...records];
         }
-
         page.total = total;
         if (list.value.length >= total || records.length < page.size) {
           pageStatus.value = "nomore";
@@ -238,9 +195,7 @@
         }
       })
       .catch(() => {
-        if (page.current === 1) {
-          list.value = [];
-        }
+        if (page.current === 1) list.value = [];
         pageStatus.value = "loadmore";
         uni.showToast({ title: "鏌ヨ澶辫触", icon: "none" });
       });
@@ -254,17 +209,16 @@
   };
 
   const loadMore = () => {
-    if (pageStatus.value === "loadmore") {
-      getList();
-    }
+    if (pageStatus.value === "loadmore") getList();
   };
 
-  const goBack = () => {
-    uni.navigateBack();
-  };
+  const goBack = () => uni.navigateBack();
+  const goAdd = () => uni.navigateTo({ url: OA_NAV.approveListTemplateSelect });
 
-  const goAdd = () => {
-    uni.navigateTo({ url: OA_NAV.approveListTemplateSelect });
+  const openDetail = item => {
+    if (!item?.id) return;
+    stashInstanceRow(item);
+    uni.navigateTo({ url: `${OA_NAV.approveListDetail}?id=${item.id}` });
   };
 
   const goModify = item => {
@@ -272,52 +226,57 @@
       uni.showToast({ title: "浠呰繘琛屼腑鐨勬湰浜虹敵璇峰彲缂栬緫", icon: "none" });
       return;
     }
+    const mk = inferReimburseModuleKeyFromInstance(item);
+    if (mk) {
+      const rid = resolveFinReimbursementIdFromInstance(item);
+      if (rid == null) {
+        uni.showToast({ title: "鏃犳硶淇敼锛氱己灏戞姤閿�鍗� ID", icon: "none" });
+        return;
+      }
+      stashReimburseEditFromApprove(mk, rid);
+      uni.navigateTo({
+        url: `${OA_NAV.reimburseForm}?moduleKey=${mk}&mode=edit&reimbursementId=${rid}`,
+      });
+      return;
+    }
     if (!item?.id) return;
-    uni.setStorageSync(EDIT_STORAGE_KEY, item);
-    uni.navigateTo({
-      url: `${OA_NAV.approveListApply}?id=${item.id}`,
-    });
+    stashInstanceRow(item);
+    uni.navigateTo({ url: `${OA_NAV.approveListApply}?id=${item.id}` });
   };
 
   const handleApprove = item => {
     if (!item?.id) return;
-    uni.showToast({ title: "瀹℃壒璇︽儏椤靛緟瀵规帴", icon: "none" });
+    if (!item.isApprove) {
+      uni.showToast({ title: "褰撳墠瀹℃壒鏃犻渶鎮ㄥ鐞�", icon: "none" });
+      return;
+    }
+    stashInstanceRow(item);
+    uni.navigateTo({ url: `${OA_NAV.approveListApprove}?id=${item.id}` });
   };
 
+  onMounted(() => calcListScrollHeight());
+
   onShow(() => {
+    calcListScrollHeight();
     handleSearch();
   });
 </script>
 
 <style scoped lang="scss">
   @import "@/styles/sales-common.scss";
+  @import "../../_styles/oa-approval-list.scss";
 
-  .approve-list-page {
-    display: flex;
-    flex-direction: column;
-    min-height: 100vh;
+  .active-search {
+    padding-right: 4px;
   }
 
-  .list-scroll {
+  .chip-input {
     flex: 1;
-    height: 0;
-    padding-bottom: calc(80px + env(safe-area-inset-bottom));
+    font-size: 14px;
   }
 
-  .empty-wrap {
-    padding: 48px 20px;
-  }
-
-  .action-buttons {
-    display: flex;
-    justify-content: flex-end;
-    gap: 10px;
-    margin-top: 12px;
-    padding-top: 12px;
-    border-top: 1px solid #f0f0f0;
-  }
-
-  .action-btn {
-    min-width: 72px;
+  :deep(.chip-input .u-input__content) {
+    background: transparent !important;
+    padding: 0 !important;
   }
 </style>

--
Gitblit v1.9.3