From e449a5408265e4bd1f6c66f5be28a42efac444ee Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 20 九月 2026 15:22:46 +0800
Subject: [PATCH] 天津豹鸣app 1.需求修改

---
 src/pages/sales/receiptPaymentLedger/index.vue |  300 +++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 197 insertions(+), 103 deletions(-)

diff --git a/src/pages/sales/receiptPaymentLedger/index.vue b/src/pages/sales/receiptPaymentLedger/index.vue
index 7daa076..e038083 100644
--- a/src/pages/sales/receiptPaymentLedger/index.vue
+++ b/src/pages/sales/receiptPaymentLedger/index.vue
@@ -1,167 +1,261 @@
 <template>
   <view class="sales-account">
-    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
     <PageHeader title="瀹㈡埛寰�鏉�"
                 @back="goBack" />
+
+    <!-- 缁熻鏉★紙闇�姹備竷锛氬簲鏀舵憳瑕侊級 -->
+    <view class="summary-strip">
+      <view class="summary-cell">
+        <text class="summary-num">{{ summary.totalProjects || 0 }}</text>
+        <text class="summary-cap">椤圭洰</text>
+      </view>
+      <view class="summary-cell">
+        <text class="summary-num">{{ summary.totalCustomers || 0 }}</text>
+        <text class="summary-cap">瀹㈡埛</text>
+      </view>
+      <view class="summary-cell">
+        <text class="summary-num">{{ summary.totalContracts || 0 }}</text>
+        <text class="summary-cap">鍚堝悓</text>
+      </view>
+      <view class="summary-cell">
+        <text class="summary-num">{{ fmtMoney(summary.totalAmount) }}</text>
+        <text class="summary-cap">绛剧害鎬婚</text>
+      </view>
+      <view class="summary-cell overdue">
+        <text class="summary-num">{{ summary.totalOverdueCount || 0 }}</text>
+        <text class="summary-cap">瓒�30澶╂湭鍥炴</text>
+      </view>
+    </view>
+
     <!-- 鎼滅储鍖哄煙 -->
     <view class="search-section">
       <view class="search-bar">
         <view class="search-input">
-          <up-input class="search-text"
-                    placeholder="璇疯緭鍏ュ鎴峰悕绉�"
-                    v-model="searchForm.searchText"
-                    @change="searchChange"
-                    clearable />
+          <up-input v-model="query.projectName"
+                    class="search-text"
+                    placeholder="璇疯緭鍏ラ」鐩悕绉版悳绱�"
+                    clearable
+                    @change="getList" />
         </view>
-        <view class="search-button"
-              @click="handleQuery">
-          <up-icon name="search"
+        <view class="filter-button"
+              @click="showFilter = true">
+          <up-icon name="list"
                    size="24"
-                   color="#999"></up-icon>
+                   color="#999" />
         </view>
       </view>
     </view>
-    <!-- 瀹㈡埛鍒楄〃 -->
-    <view class="customer-list-container">
-      <view class="customer-list"
-            v-if="tableData.length > 0">
-        <view v-for="(item, index) in tableData"
-              :key="item.id"
-              class="customer-item"
-              @click="rowClickMethod(item)">
-          <view class="item-header">
-            <view class="item-left">
-              <view class="customer-icon">
-                <up-icon name="file-text"
-                         size="16"
-                         color="#ffffff"></up-icon>
-              </view>
-              <text class="customer-name">{{ item.customerName }}</text>
-            </view>
-            <view class="item-right">
-              <up-icon name="arrow-right"
+
+    <!-- 椤圭洰鍒楄〃 -->
+    <view v-if="projectList.length > 0"
+          class="ledger-list">
+      <view v-for="item in projectList"
+            :key="item.projectId"
+            class="ledger-item"
+            @click="goDetail(item)">
+        <view class="item-header">
+          <view class="item-left">
+            <view class="document-icon">
+              <up-icon name="file-text"
                        size="16"
-                       color="#999"></up-icon>
+                       color="#ffffff" />
             </view>
+            <text class="item-id">{{ item.projectName || "-" }}</text>
           </view>
-          <up-divider></up-divider>
-          <view class="item-details">
-            <view class="detail-row">
-              <text class="detail-label">寮�绁ㄩ噾棰�(鍏�)</text>
-              <text class="detail-value">{{ formattedNumber(item.invoiceTotal) }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">鍥炴閲戦(鍏�)</text>
-              <text class="detail-value">{{ formattedNumber(item.receiptPaymentAmount) }}</text>
-            </view>
-            <view class="detail-row">
-              <text class="detail-label">搴旀敹閲戦(鍏�)</text>
-              <text class="detail-value highlight danger">{{ formattedNumber(item.unReceiptPaymentAmount) }}</text>
-            </view>
+          <up-tag :text="overdueText(item.overdueCount)"
+                  :type="item.overdueCount > 0 ? 'error' : 'success'"
+                  size="mini"
+                  shape="circle" />
+        </view>
+        <up-divider></up-divider>
+        <view class="item-details">
+          <view class="detail-row">
+            <text class="detail-label">椤圭洰缂栧彿</text>
+            <text class="detail-value">{{ item.projectCode || "-" }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">绛剧害鎬婚</text>
+            <text class="detail-value highlight">{{ fmtMoney(item.contractAmounts) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">寮�绁ㄩ噾棰�</text>
+            <text class="detail-value">{{ fmtMoney(item.invoiceAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍥炴閲戦</text>
+            <text class="detail-value highlight">{{ fmtMoney(item.receiptPaymentAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">搴旀敹閲戦</text>
+            <text class="detail-value danger">{{ fmtMoney(item.receiptableAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">閫�璐ч噾棰�</text>
+            <text class="detail-value">{{ fmtMoney(item.returnAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍥炴杩涘害</text>
+            <text class="detail-value"
+                  :class="{ danger: item.overdueCount > 0 }">
+              {{ calcRate(item.receiptPaymentAmount, item.contractAmounts) }}%
+            </text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">瀹㈡埛 / 鍚堝悓</text>
+            <text class="detail-value">{{ item.customerCount || 0 }} 瀹� / {{ item.contractCount || 0 }} 浠�</text>
           </view>
         </view>
-      </view>
-      <view v-else
-            class="no-data">
-        <text>鏆傛棤瀹㈡埛鏁版嵁</text>
+        <view class="action-buttons">
+          <up-button class="action-btn"
+                     size="small"
+                     type="primary"
+                     @click.stop="goDetail(item)">鏌ョ湅瀹㈡埛寰�鏉�</up-button>
+        </view>
       </view>
     </view>
+    <view v-else
+          class="no-data">
+      <text>鏆傛棤椤圭洰寰�鏉ユ暟鎹�</text>
+    </view>
+
+    <FilterPanel v-model:show="showFilter"
+                 :model-value="query"
+                 title="瀹㈡埛寰�鏉ョ瓫閫�"
+                 :fields="filterFields"
+                 @search="onFilterSearch"
+                 @reset="onFilterSearch" />
   </view>
 </template>
 
 <script setup>
-  import { onMounted, ref, reactive, toRefs } from "vue";
+  import { reactive, ref, onMounted } from "vue";
   import { onShow } from "@dcloudio/uni-app";
-  import { invoiceLedgerSalesAccount } from "@/api/salesManagement/invoiceLedger";
+  import PageHeader from "@/components/PageHeader.vue";
+  import FilterPanel from "@/components/FilterPanel.vue";
+  import {
+    projectTransactions,
+    transactionsSummary,
+  } from "@/api/salesManagement/indicatorStats";
+  import { unwrapList } from "@/utils/list";
 
-  const tableData = ref([]);
+  const projectList = ref([]);
+  const summary = ref({});
+  const showFilter = ref(false);
 
-  const page = reactive({
-    current: -1,
-    size: -1,
+  const query = reactive({
+    projectName: "",
+    customerName: "",
+    contractName: "",
   });
 
-  const data = reactive({
-    searchForm: {
-      searchText: "",
-      invoiceDate: "",
-    },
-  });
+  const filterFields = [
+    { prop: "customerName", label: "瀹㈡埛鍚嶇О", type: "input", placeholder: "璇疯緭鍏ュ鎴峰悕绉�" },
+    { prop: "contractName", label: "鍚堝悓鍚嶇О", type: "input", placeholder: "璇疯緭鍏ュ悎鍚屽悕绉�" },
+  ];
 
-  const { searchForm } = toRefs(data);
-
-  // 杩斿洖涓婁竴椤�
   const goBack = () => {
     uni.navigateBack();
   };
-  // 鎼滅储妗嗗彉鍖栨椂瑙﹀彂
-  const searchChange = val => {
-    searchForm.value.searchText = val;
-    getList();
-  };
-  // 鏌ヨ鍒楄〃
-  const handleQuery = () => {
-    getList();
-  };
 
   const getList = () => {
-    showLoadingToast("鍔犺浇涓�...");
-    invoiceLedgerSalesAccount({ ...searchForm.value, ...page })
+    uni.showLoading({ title: "鍔犺浇涓�...", mask: true });
+    const params = { ...query, current: -1, size: -1 };
+    projectTransactions(params)
       .then(res => {
-        tableData.value = res.data.records;
-        closeToast();
+        projectList.value = unwrapList(res);
+        uni.hideLoading();
       })
       .catch(() => {
-        closeToast();
-        uni.showToast({
-          title: "鏌ヨ澶辫触",
-          icon: "error",
-        });
+        uni.hideLoading();
+        uni.showToast({ title: "鏌ヨ澶辫触", icon: "none" });
       });
   };
 
-  const formattedNumber = value => {
-    return parseFloat(value || 0).toFixed(2);
+  const getSummary = () => {
+    transactionsSummary()
+      .then(res => {
+        summary.value = res.data || {};
+      })
+      .catch(() => {});
   };
 
-  // 鏄剧ず鍔犺浇鎻愮ず
-  const showLoadingToast = message => {
-    uni.showLoading({
-      title: message,
-      mask: true,
-    });
+  const onFilterSearch = values => {
+    Object.assign(query, values || {});
+    getList();
   };
 
-  // 鍏抽棴鎻愮ず
-  const closeToast = () => {
-    uni.hideLoading();
-  };
-
-  const rowClickMethod = row => {
-    // 浣跨敤 uni.setStorageSync 瀛樺偍瀹㈡埛淇℃伅
-    uni.setStorageSync("customerId", row.id);
-    // 璺宠浆鍒板洖娆捐褰曟槑缁嗛〉闈�
+  const goDetail = item => {
+    if (!item?.projectId) return;
     uni.navigateTo({
-      url: "/pages/sales/receiptPaymentLedger/detail",
+      url: `/pages/sales/receiptPaymentLedger/detail?projectId=${item.projectId}`
+        + `&projectName=${encodeURIComponent(item.projectName || "")}`,
     });
+  };
+
+  const overdueText = count => (count > 0 ? `${count} 浠借秴鏈焋 : "姝e父灞ョ害");
+
+  const fmtMoney = value => {
+    const num = Number(value);
+    if (!Number.isFinite(num)) return "楼 0.00";
+    return "楼 " + num.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+  };
+
+  const calcRate = (paid, amount) => {
+    const total = Number(amount);
+    if (!Number.isFinite(total) || total === 0) return "0.0";
+    return (((Number(paid) || 0) / total) * 100).toFixed(1);
   };
 
   onShow(() => {
-    // 椤甸潰鏄剧ず鏃跺埛鏂板垪琛�
     getList();
+    getSummary();
   });
 
   onMounted(() => {
     getList();
+    getSummary();
   });
 </script>
 
 <style scoped lang="scss">
   @import "@/styles/sales-common.scss";
 
-  // 瀹㈡埛寰�鏉ョ壒鏈夋牱寮�
+  .summary-strip {
+    display: flex;
+    flex-wrap: wrap;
+    background: #ffffff;
+    margin: 12px 12px 0;
+    border-radius: 12px;
+    padding: 12px 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  }
+
+  .summary-cell {
+    flex: 1 0 33%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 6px 0;
+  }
+
+  .summary-num {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+  }
+
+  .summary-cap {
+    font-size: 11px;
+    color: #909399;
+    margin-top: 2px;
+  }
+
+  .summary-cell.overdue .summary-num {
+    color: #ff4757;
+  }
+
   .detail-value.danger {
-    color: #ff4757; // 涓庡叕鍏辨牱寮忎腑鐨� #ee0a24 涓嶅悓
+    color: #ff4757;
     font-weight: 500;
   }
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.9.3