caiyuqin 2 månader sedan
förälder
incheckning
433f20042d

+ 0 - 13
src/api/income.ts

@@ -145,16 +145,3 @@ export function getWriteOffIncome(params = {}) {
 }
 
 
-//获取团队收益列表
-export function getTeamMembers(params = {}) {
-    return http.Get('/couponCenter/APP/mine/getTeamMembers', {
-        params,
-    })
-}
-
-//获取指定团员收益列表
-export function getMemberIncomeList(params = {}) {
-    return http.Get('/couponCenter/APP/mine/getMemberIncomeList', {
-        params,
-    })
-}

+ 14 - 0
src/api/my.ts

@@ -38,4 +38,18 @@ export function getTeamAmountStatistics(params:any) {
     return http.Get('/couponCenter/APP/mine/getTeamAmountStatistics', {
         params
     })
+}
+
+//获取团队收益列表
+export function getTeamMembers(params = {}) {
+    return http.Get('/couponCenter/APP/mine/getTeamMembers', {
+        params,
+    })
+}
+
+//获取指定团员收益列表
+export function getMemberIncomeList(params = {}) {
+    return http.Get('/couponCenter/APP/mine/getMemberIncomeList', {
+        params,
+    })
 }

+ 2 - 9
src/components/listScrollView/index.vue

@@ -14,19 +14,12 @@ import { ref, computed, onUnmounted } from "vue";
 import MescrollUni from "mescroll-uni/mescroll-uni.vue";
 
 interface Props {
-  // 数据接口
   api?: Function;
-  // 初始参数
   init?: Record<string, any>;
-  // 空状态配置
   empty?: Record<string, any>;
-  // mescroll 额外配置
   option?: Record<string, any>;
-  // 自定义list数据的字段
   keyName?: string;
-  // page相关
   noPage?: boolean;
-  // 每页大小
   pageSize?: number | string;
 }
 
@@ -86,12 +79,12 @@ const mescrollInit = (e: any) => {
   mescroll.value = e;
 };
 
-// 滚动中
+
 const onMove = (e: any) => {
   emit("move", e);
 };
 
-// 滚动事件(带防抖)
+// 滚动事件
 const onScroll = (e: any) => {
   isScrolling.value = true;
   emit("scroll", e);

+ 1 - 1
src/components/start/start.vue

@@ -14,7 +14,7 @@
 import { ref, computed } from 'vue'
 import { getImageUrl } from '@/utils/imageUtil'
 
-// 图片资源(需要在 static 目录下放置对应的图片)
+
 const startImg = getImageUrl('@img/index/start.png')
 const halfImg = getImageUrl('@img/index/start-half.png')
 

+ 29 - 28
src/pages-C/home/ranking.vue

@@ -1,8 +1,6 @@
 <script lang="ts" setup>
 import { ref, computed } from "vue";
 import { storeToRefs } from "pinia";
-import { useRequest } from "alova/client";
-import { useUserStore } from "@/store/user";
 import { useTokenStore } from "@/store/token";
 import { safeAreaInsets, menuButtonInfo } from "@/utils";
 import CustomNavigationBar from "@/components/CustomNavigationBar.vue";
@@ -11,6 +9,7 @@ import Classification from "./classification.vue";
 import Upopup from "@/components/popup/index.vue";
 import DateRangePicker from "@/components/dateRangePicker/index.vue";
 import FilterSelect from "@/components/filter/filter.vue";
+import LsvList from "@/components/listScrollView/index.vue";
 
 import { getCouponDistributionDetailsList } from "@/api/home";
 
@@ -21,16 +20,14 @@ definePage({
   },
 });
 
-const userStore = useUserStore();
 const tokenStore = useTokenStore();
 const { hasLogin } = storeToRefs(tokenStore);
 
-const { send: getRankingListRequest, data: rankingList } = useRequest(
-  getCouponDistributionDetailsList,
-  {
-    immediate: false,
-  }
-);
+const listRef = ref();
+
+const getCouponListApi = (params: any) => {
+  return getCouponDistributionDetailsList(params);
+};
 
 const filterRef = ref();
 
@@ -89,7 +86,7 @@ function selectValue(selected) {
     params.endTime = selected.dataFilter.endDate + " 23:59:59";
   }
 
-  getRankingListRequest(params);
+  listRef.value?.reloadList(params);
 }
 </script>
 
@@ -136,24 +133,28 @@ function selectValue(selected) {
             height="44rpx">
           </u--image>
           <view class="ranking-list">
-            <view class="ranking-item" v-for="(item, index) in (rankingList || [])" :key="item.templateId || index">
-              <u--image v-if="item.serialNumber == 1" class='selected-icon' :src="getImageUrl('@img/me/rank1.png')"
-                mode="aspectFit" width="48rpx" height="48rpx">
-              </u--image>
-              <u--image v-else-if="item.serialNumber == 2" class='selected-icon'
-                :src="getImageUrl('@img/me/rank2.png')" mode="aspectFit" width="48rpx" height="48rpx">
-              </u--image>
-              <u--image v-else-if="item.serialNumber == 3" class='selected-icon'
-                :src="getImageUrl('@img/me/rank3.png')" mode="aspectFit" width="48rpx" height="48rpx">
-              </u--image>
-              <text v-else class="ranking-value rank-num">{{ item.serialNumber }}</text>
-              <text class="ranking-value">{{ item.templateName }}</text>
-              <text class="ranking-value">{{ item.classification }}</text>
-              <text class="ranking-value">{{ item.browseNum }}</text>
-              <text class="ranking-value">{{ item.receivedNum }}</text>
-              <text class="ranking-value">{{ item.writeOffAmount }}</text>
-              <text class="ranking-value">{{ item.writeOffRate }}%</text>
-            </view>
+            <LsvList ref="listRef" :api="getCouponListApi" :noPage="true">
+              <template #list="{ data }">
+                <view class="ranking-item" v-for="(item, index) in data" :key="index">
+                  <u--image v-if="item.serialNumber == 1" class='selected-icon' :src="getImageUrl('@img/me/rank1.png')"
+                    mode="aspectFit" width="48rpx" height="48rpx">
+                  </u--image>
+                  <u--image v-else-if="item.serialNumber == 2" class='selected-icon' :src="getImageUrl('@img/me/rank2.png')"
+                    mode="aspectFit" width="48rpx" height="48rpx">
+                  </u--image>
+                  <u--image v-else-if="item.serialNumber == 3" class='selected-icon' :src="getImageUrl('@img/me/rank3.png')"
+                    mode="aspectFit" width="48rpx" height="48rpx">
+                  </u--image>
+                  <text v-else class="ranking-value rank-num">{{ item.serialNumber }}</text>
+                  <text class="ranking-value">{{ item.templateName }}</text>
+                  <text class="ranking-value">{{ item.classification }}</text>
+                  <text class="ranking-value">{{ item.browseNum }}</text>
+                  <text class="ranking-value">{{ item.receivedNum }}</text>
+                  <text class="ranking-value">{{ item.writeOffAmount }}</text>
+                  <text class="ranking-value">{{ item.writeOffRate }}%</text>
+                </view>
+              </template>
+            </LsvList>
           </view>
         </view>
       </view>

+ 85 - 92
src/pages-C/income/incomeMoney.vue

@@ -1,7 +1,9 @@
 <script setup lang="ts">
 import { ref } from "vue";
-import { getImageUrl } from "@/utils/imageUtil";
 import DateRangePicker from "@/components/dateRangePicker/index.vue";
+import LsvList from "@/components/listScrollView/index.vue";
+import { pageMap } from "@/api/income";
+
 definePage({
   style: {
     navigationBarTitleText: "累计提现",
@@ -9,70 +11,61 @@ definePage({
   },
 });
 
-const moneyData = ref([
-  {
-    id: 1,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 2,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 3,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 4,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 5,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 6,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 7,
-    type: "提现到银行卡",
-    amount: "37.92",
-    bankName: "招商银行",
-    date: "2026-05-18 19:00:00",
-  },
-]);
-
+const totalAmount = ref<string>();
 const showPicker = ref(false);
-const defaultStart = "";
-const defaultEnd = "";
+const defaultStart = ref("");
+const defaultEnd = ref("");
+const listRef = ref();
+
+const getCouponListApi = (params: any) => {
+  return pageMap({
+    pageNo: params.pageNo,
+    pageSize: params.pageSize,
+    startDate: params.startDate,
+    endDate: params.endDate,
+    status: 2,
+  });
+};
+
+const afterFetch = (result: any) => {
+  totalAmount.value = result.totalAmount;
+};
 
 const handleConfirm = (value: { startDate: string; endDate: string }) => {
-  console.log("选中的日期范围:", value);
-  // 处理业务逻辑
+  defaultStart.value = value.startDate;
+  defaultEnd.value = value.endDate;
+  reloadListRef();
+};
+
+const reloadListRef = () => {
+  listRef.value?.reloadList({
+    startDate: defaultStart.value,
+    endDate: defaultEnd.value,
+    status: 2,
+  });
 };
 
 const handleCancel = () => {
   console.log("取消选择");
 };
+
+const getIncomeDisplay = (data) => {
+  if ([5, 6, 7].includes(data.commissionType)) {
+    if (data.commissionType == 5) return "拉新奖励";
+    if (data.commissionType == 6) return "分享奖励";
+    if (data.commissionType == 7) return `提现到银行卡`;
+  }
+
+  if (data.receiveUserName) {
+    return data.receiveUserName;
+  }
+
+  let result = data.couponName || "";
+  if (data.status === 2) {
+    result += " (退款)";
+  }
+  return result;
+};
 </script>
 
 <template>
@@ -82,39 +75,43 @@ const handleCancel = () => {
 
     <view class='income-select'>
       <view class='income-time' @click='showPicker=true'>
-        <view class='income-time-name'>2026 05.10-2026 05.12 </view>
+        <view class='income-time-name'>{{ defaultStart && defaultEnd ? `${defaultStart} - ${defaultEnd}` : '日期筛选' }}
+        </view>
         <view class="caret" />
       </view>
       <view class="total-amount">
         <text class="total-label">合计</text>
-        <text class="total-value">340</text>
+        <text class="total-value">{{ totalAmount || 0}}</text>
         <text class="total-unit">元</text>
       </view>
     </view>
 
     <view class="money-content">
       <view class="money-card">
-        <view class="money-list">
-          <view class="money-item" v-for="item in moneyData" :key="item.id">
-            <view class="item-header">
-              <text class="item-type">{{ item.type }}</text>
-              <view class="item-amount">
-                <text class="amount-symbol">¥</text>
-                <text class="amount-value">{{ item.amount }}</text>
+        <LsvList ref="listRef" :api="getCouponListApi" key-name="result" @afterFetch="afterFetch">
+          <template #list="{ data }">
+
+            <view class="money-item" v-for="item in data" :key="item.id">
+              <view class="item-header">
+                <text class="item-type">{{ getIncomeDisplay(item) }}</text>
+
+                <view class="item-amount">
+                  <text class="amount-symbol">¥</text>
+                  <text class="amount-value">{{ item.changeAmount }}</text>
+                </view>
               </view>
+              <view class="item-info">
+                <text class="info-label">{{ item.bankName }}</text>
+                <text class="info-value">{{ item.createTime }}</text>
+              </view>
+              <view class="divider" v-if="item.id !== moneyData.length"></view>
             </view>
-            <view class="item-info">
-              <text class="info-label">{{ item.bankName }}</text>
-              <text class="info-value">{{ item.date }}</text>
-            </view>
-            <view class="divider" v-if="item.id !== moneyData.length"></view>
-          </view>
-        </view>
+          </template>
+        </LsvList>
       </view>
     </view>
   </view>
 
-  <!-- 日期 -->
   <DateRangePicker v-model:show="showPicker" :startDate="defaultStart" :endDate="defaultEnd" @confirm="handleConfirm"
     @cancel="handleCancel" />
 </template>
@@ -123,10 +120,16 @@ const handleCancel = () => {
 .income-money-container {
   min-height: 100vh;
   background: #f8f8fa;
+  display: flex;
+  flex-direction: column;
 
   .money-content {
+    flex: 1;
     padding: 32rpx;
+    box-sizing: border-box;
+    overflow: auto;
   }
+
   .income-select {
     padding: 32rpx;
     box-sizing: border-box;
@@ -134,17 +137,18 @@ const handleCancel = () => {
     align-items: center;
     justify-content: space-between;
     background: #fff;
+    flex: 0 0 auto;
+
     .income-time-name {
       font-size: 28rpx;
       color: #333;
     }
+
     .income-time {
       display: flex;
+      align-items: center;
     }
-    .income-down {
-      margin-top: -8rpx;
-      margin-left: 8rpx;
-    }
+
     .total-amount {
       display: flex;
       align-items: baseline;
@@ -168,14 +172,7 @@ const handleCancel = () => {
         color: #ff5365;
       }
     }
-    .income-time {
-      display: flex;
-      align-items: center;
-      color: #333333;
-      font-size: 28rpx;
-      line-height: 28rpx;
-      white-space: nowrap;
-    }
+
     .caret {
       width: 0;
       height: 0;
@@ -185,17 +182,13 @@ const handleCancel = () => {
       border-top: 9rpx solid #333333;
     }
   }
+
   .money-card {
     background: #ffffff;
     border-radius: 32rpx;
     padding: 30rpx 32rpx 0 32rpx;
     box-sizing: border-box;
 
-    .money-list {
-      display: flex;
-      flex-direction: column;
-    }
-
     .money-item {
       .item-header {
         display: flex;
@@ -261,4 +254,4 @@ const handleCancel = () => {
     }
   }
 }
-</style>
+</style>

+ 182 - 163
src/pages-C/my/myGroup.vue

@@ -1,14 +1,12 @@
-
-
 <script setup lang="ts">
 import { computed, ref } from "vue";
-import { getImageUrl } from "@/utils/imageUtil";
-import { getTeamStatistics, getTeamAmountStatistics,getTeamMembers } from "@/api/my";
 import {
-  usePagination,
-  useRequest,
-  actionDelegationMiddleware,
-} from "alova/client";
+  getTeamStatistics,
+  getTeamAmountStatistics,
+  getTeamMembers,
+} from "@/api/my";
+import LsvList from "@/components/listScrollView/index.vue";
+import { useRequest } from "alova/client";
 
 definePage({
   style: {
@@ -17,9 +15,14 @@ definePage({
   },
 });
 
-const activePanel = ref("list");
+const activePanel = ref(1);
 const activePeriod = ref("1");
-const activeTabs = ref("all");
+const activeTabs = ref("");
+
+const panelTabs = [
+  { label: "团队列表", value: 1 },
+  { label: "团队收益", value: 2 },
+];
 
 const periodTabs = [
   { label: "今天", value: "1" },
@@ -27,9 +30,9 @@ const periodTabs = [
 ];
 
 const incomeFilterTabs = [
-  { label: "全部", value: "all" },
-  { label: "一级收益", value: "level1" },
-  { label: "二级收益", value: "level2" },
+  { label: "全部", value: "" },
+  { label: "一级收益", value: "1" },
+  { label: "二级收益", value: "2" },
 ];
 
 const listSummary = computed(() => {
@@ -60,67 +63,59 @@ const { send: sendAmountStatistics, data: statisticsData } = useRequest(
   { immediate: false }
 );
 
-const memberList = [
-  {
-    id: 1,
-    name: "吴枕书",
-    level: "二级团员",
-    orders: "5单 | 创收27.84元",
-    phone: "15721118536",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 2,
-    name: "吴枕书",
-    level: "二级团员",
-    orders: "5单 | 创收27.84元",
-    phone: "15721118536",
-    date: "2026-05-18 19:00:00",
-  },
-  {
-    id: 3,
-    name: "吴枕书",
-    level: "二级团员",
-    orders: "5单 | 创收27.84元",
-    phone: "15721118536",
-    date: "2026-05-18 19:00:00",
-  },
-];
-
 const summaryItems = computed(() =>
-  activePanel.value === "list" ? listSummary.value : incomeSummary.value
+  activePanel.value === 1 ? listSummary.value : incomeSummary.value
 );
 
 const showPicker = ref(false);
 const defaultStart = ref();
 const defaultEnd = ref();
 const listRef = ref();
+
 const handleConfirm = (value: { startDate: string; endDate: string }) => {
   defaultStart.value = value.startDate;
   defaultEnd.value = value.endDate;
-  //   reloadListRef();
   sendIncomeData({
     timeType: activePeriod.value,
     startTime: defaultStart.value ? defaultStart.value + " 00:00:00" : "",
     endTime: defaultEnd.value ? defaultEnd.value + " 23:59:59" : "",
   });
+  reloadListRef();
 };
+
 const reloadListRef = () => {
-  listRef.value.reloadList({
-    startTime: defaultStart.value ? defaultStart.value + " 00:00:00" : "",
-    endTime: defaultEnd.value ? defaultEnd.value + " 23:59:59" : "",
-    timeType: activePeriod.value,
-  });
+  if (activePanel.value == 1) {
+    listRef.value?.reloadList({
+      startTime: defaultStart.value ? defaultStart.value + " 00:00:00" : "",
+      endTime: defaultEnd.value ? defaultEnd.value + " 23:59:59" : "",
+      timeType: activePeriod.value,
+    });
+  } else {
+    listRef.value?.reloadList({
+      inviteType: activeTabs.value,
+    });
+  }
 };
 
-onShow(async () => {
-  await sendIncomeData({
-    timeType: 1,
+const getCouponListApi = (params: any) => {
+  return getTeamMembers({
+    pageNo: params.pageNo,
+    pageSize: params.pageSize,
+    timeType: activePanel.value == 1 ? params.timeType || 1 : "",
+    startTime: params.startTime || "",
+    endTime: params.endTime || "",
+    inviteType: params.inviteType,
   });
+};
 
-  await sendAmountStatistics({
-    timeType: 1,
-  });
+const inviteTypeMap: Record<string, string> = {
+  "1": "一级团员",
+  "2": "二级团员",
+};
+
+onShow(async () => {
+  await sendIncomeData({ timeType: 1 });
+  await sendAmountStatistics();
 });
 
 const dateRangeText = computed(() => {
@@ -129,27 +124,42 @@ const dateRangeText = computed(() => {
   }
   return "日期筛选";
 });
+
 const handleCancel = () => {
   console.log("取消选择");
 };
 
-function goDetails(item) {
+function goDetails(item: any) {
   uni.navigateTo({
-    url: `/pages-C/my/myGroupDetails`,
+    url: `/pages-C/my/myGroupDetails?memberId=${item.userId}&inviteType=${item.inviteType}`,
   });
 }
 
-const tabClick = (item) => {
+const tabClick = (item: { label: string; value: string }) => {
   activePeriod.value = item.value;
   sendIncomeData({
     timeType: activePeriod.value,
     startTime: defaultStart.value ? defaultStart.value + " 00:00:00" : "",
     endTime: defaultEnd.value ? defaultEnd.value + " 23:59:59" : "",
   });
+  reloadListRef();
 };
 
-const leaveClick = (item) => {
+const activePanelClick = (item: { label: string; value: number }) => {
+  activePanel.value = item.value;
+  reloadListRef();
+  if (item.value === 1) {
+    sendAmountStatistics({
+      timeType: activePeriod.value,
+      startTime: defaultStart.value ? defaultStart.value + " 00:00:00" : "",
+      endTime: defaultEnd.value ? defaultEnd.value + " 23:59:59" : "",
+    });
+  }
+};
+
+const leaveClick = (item: { label: string; value: string }) => {
   activeTabs.value = item.value;
+  reloadListRef();
 };
 </script>
 
@@ -160,19 +170,15 @@ const leaveClick = (item) => {
     <view class="team-income-page">
 
       <view class="panel-tabs">
-        <view class="panel-tab" @tap="activePanel = 'list'">
-          <text :class="{ active: activePanel === 'list' }">团队列表</text>
-          <view v-if="activePanel === 'list'" class="tab-underline" />
-        </view>
-        <view class="panel-divider" />
-        <view class="panel-tab" @tap="activePanel = 'income'">
-          <text :class="{ active: activePanel === 'income' }">团队收益</text>
-          <view v-if="activePanel === 'income'" class="tab-underline" />
+        <view v-for="(tab, index) in panelTabs" :key="index" class="panel-tab" @tap="activePanelClick(tab)">
+          <text :class="{ active: activePanel === tab.value }">{{ tab.label }}</text>
+          <view v-if="activePanel === tab.value" class="tab-underline" />
         </view>
+        <view v-if="panelTabs.length === 2" class="panel-divider" />
       </view>
 
-      <view class="filter-box">
-        <view v-if="activePanel === 'list'" class="list-filter">
+      <view v-if="activePanel === 1" class="filter-box">
+        <view class="list-filter">
           <view class="period-tabs">
             <view v-for="item in periodTabs" :key="item.value" class="period-tab"
               :class="{ active: activePeriod === item.value }" @tap="tabClick(item)">
@@ -185,16 +191,18 @@ const leaveClick = (item) => {
             <view class="caret" />
           </view>
         </view>
+      </view>
 
-        <view v-else class="income-filter">
+      <view v-else class="filter-box">
+        <view class="income-filter">
           <view v-for="item in incomeFilterTabs" :key="item.value" class="period-tab"
-            :class="{ active: activeTabs==item.value  }" @tap="leaveClick(item)">
+            :class="{ active: activeTabs==item.value }" @tap="leaveClick(item)">
             <text>{{ item.label }}</text>
           </view>
         </view>
       </view>
 
-      <view class="summary-section" :class="activePanel === 'list' ? 'list-summary' : 'income-summary'">
+      <view class="summary-section" :class="activePanel === 1 ? 'list-summary' : 'income-summary'">
         <view v-for="(item, index) in summaryItems" :key="item.label" class="summary-item">
           <text class="summary-label">{{ item.label }}</text>
           <text class="summary-value">{{ item.value }}</text>
@@ -203,29 +211,34 @@ const leaveClick = (item) => {
       </view>
 
       <view class="member-list">
-        <view v-for="item in memberList" :key="item.id" class="member-card" @click='goDetails'>
-          <view class="member-header">
-            <text class="member-name">{{ item.name }}</text>
-            <view class="level-tag">
-              <text>{{ item.level }}</text>
-            </view>
-          </view>
-          <view class="card-line" />
-          <view class="info-list">
-            <view class="info-row">
-              <text class="info-label">完成单数</text>
-              <text class="info-value income">{{ item.orders }}</text>
-            </view>
-            <view class="info-row">
-              <text class="info-label">联系方式</text>
-              <text class="info-value">{{ item.phone }}</text>
-            </view>
-            <view class="info-row">
-              <text class="info-label">邀请日期</text>
-              <text class="info-value">{{ item.date }}</text>
+        <LsvList ref="listRef" :api="getCouponListApi" key-name="result">
+          <template #list="{ data }">
+            <view v-for="item in data" :key="item.userId || item.userName" class="member-card" @click='goDetails(item)'>
+              <view class="member-header">
+                <text class="member-name">{{ item.userName || '--' }}</text>
+                <view class="level-tag">
+                  <text>{{ inviteTypeMap[String(item.inviteType)] || '团员' }}</text>
+                </view>
+              </view>
+              <view class="card-line" />
+              <view class="info-list">
+                <view class="info-row">
+                  <text class="info-label">完成单数</text>
+                  <text class="info-value income">{{ item.completeOrderCount || 0 }}单 |
+                    ¥{{ item.revenueGenerationAmount || 0 }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">联系方式</text>
+                  <text class="info-value">{{ item.phone || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">绑定时间</text>
+                  <text class="info-value">{{ item.bindTime || '--' }}</text>
+                </view>
+              </view>
             </view>
-          </view>
-        </view>
+          </template>
+        </LsvList>
       </view>
     </view>
   </view>
@@ -239,11 +252,15 @@ const leaveClick = (item) => {
 .group-info-container {
   min-height: 100vh;
   background: #f8f8fa;
+  display: flex;
+  flex-direction: column;
 }
 
 .team-income-page {
   display: flex;
   flex-direction: column;
+  flex: 1;
+  min-height: 0;
   width: 100%;
   color: #1d2129;
 
@@ -311,6 +328,7 @@ const leaveClick = (item) => {
     box-sizing: border-box;
     flex: 0 0 auto;
     border-bottom: 1rpx solid #d9d9d9;
+
     .list-filter,
     .income-filter {
       display: flex;
@@ -353,6 +371,7 @@ const leaveClick = (item) => {
       background: #d9d9d9;
       flex: 0 0 auto;
     }
+
     .caret {
       width: 0;
       height: 0;
@@ -419,7 +438,6 @@ const leaveClick = (item) => {
       }
     }
 
-    // 团队列表模式下的统计项宽度
     &.list-summary {
       .summary-item {
         &:nth-child(1) {
@@ -438,7 +456,6 @@ const leaveClick = (item) => {
       }
     }
 
-    // 团队收益模式下的统计项宽度
     &.income-summary {
       .summary-item {
         &:nth-child(1),
@@ -461,96 +478,98 @@ const leaveClick = (item) => {
   // 成员列表
   .member-list {
     display: flex;
-    flex: 1 0 auto;
+    flex: 1 1 auto;
+    min-height: 0;
     flex-direction: column;
     gap: 32rpx;
     width: 100%;
     padding: 32rpx 32rpx 21rpx;
     box-sizing: border-box;
+    overflow: auto;
+  }
+
+  .member-card {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    min-height: 311rpx;
+    padding: 32rpx;
+    border-radius: 32rpx;
+    background: #ffffff;
+    box-sizing: border-box;
 
-    .member-card {
+    .member-header {
       display: flex;
-      flex-direction: column;
-      width: 100%;
-      min-height: 311rpx;
-      padding: 32rpx;
-      border-radius: 32rpx;
-      background: #ffffff;
-      box-sizing: border-box;
+      align-items: center;
+      gap: 14rpx;
 
-      .member-header {
+      .member-name {
+        color: #2c2c2c;
+        font-size: 32rpx;
+        font-weight: 700;
+        line-height: 32rpx;
+        white-space: nowrap;
+      }
+
+      .level-tag {
         display: flex;
         align-items: center;
-        gap: 14rpx;
-
-        .member-name {
-          color: #2c2c2c;
-          font-size: 32rpx;
-          font-weight: 700;
-          line-height: 32rpx;
+        justify-content: center;
+        height: 40rpx;
+        padding: 0 16rpx;
+        border-radius: 2rpx;
+        background: #e8f7ff;
+        box-sizing: border-box;
+
+        text {
+          color: #3491fa;
+          font-size: 24rpx;
+          font-weight: 500;
+          line-height: 40rpx;
           white-space: nowrap;
         }
-
-        .level-tag {
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          height: 40rpx;
-          padding: 0 16rpx;
-          border-radius: 2rpx;
-          background: #e8f7ff;
-          box-sizing: border-box;
-
-          text {
-            color: #3491fa;
-            font-size: 24rpx;
-            font-weight: 500;
-            line-height: 40rpx;
-            white-space: nowrap;
-          }
-        }
       }
+    }
 
-      .card-line {
-        width: 100%;
-        height: 1rpx;
-        margin-top: 24rpx;
-        background: #eaeaea;
-      }
+    .card-line {
+      width: 100%;
+      height: 1rpx;
+      margin-top: 24rpx;
+      background: #eaeaea;
+    }
 
-      .info-list {
+    .info-list {
+      display: flex;
+      flex-direction: column;
+      gap: 30rpx;
+      margin-top: 31rpx;
+
+      .info-row {
         display: flex;
-        flex-direction: column;
-        gap: 30rpx;
-        margin-top: 31rpx;
-
-        .info-row {
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-          min-height: 30rpx;
-
-          .info-label {
-            color: #86909c;
-            font-size: 30rpx;
-            line-height: 30rpx;
-            white-space: nowrap;
-          }
+        align-items: center;
+        justify-content: space-between;
+        min-height: 30rpx;
 
-          .info-value {
-            color: #333333;
-            font-size: 30rpx;
-            line-height: 30rpx;
-            text-align: right;
-            white-space: nowrap;
+        .info-label {
+          color: #86909c;
+          font-size: 30rpx;
+          line-height: 30rpx;
+          white-space: nowrap;
+        }
+
+        .info-value {
+          color: #333333;
+          font-size: 30rpx;
+          line-height: 30rpx;
+          text-align: right;
+          white-space: nowrap;
 
-            &.income {
-              color: #ff5365;
-            }
+          &.income {
+            color: #ff5365;
           }
         }
       }
     }
   }
 }
-</style>
+</style>

+ 139 - 169
src/pages-C/my/myGroupDetails.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
 import { ref } from "vue";
-import { safeAreaInsets, menuButtonInfo } from "@/utils";
-import CustomNavigationBar from "@/components/CustomNavigationBar.vue";
 import { getImageUrl } from "@/utils/imageUtil";
+import LsvList from "@/components/listScrollView/index.vue";
+import { getMemberIncomeList } from "@/api/my";
 
 definePage({
   style: {
@@ -11,45 +11,37 @@ definePage({
   },
 });
 
-const totalIncome = ref("38.00");
+const totalIncome = ref<number>();
 
-const shareList = ref([
-  {
-    id: 1,
-    couponName: "某某某某某优惠券",
-    income: "2.00",
-    receiveTime: "2026-05-18 19:00:00",
-    receiver: "林雨欣",
-  },
-  {
-    id: 2,
-    couponName: "某某某某某优惠券",
-    income: "17.00",
-    receiveTime: "2026-05-18 19:00:00",
-    receiver: "吴雨桐",
-  },
-  {
-    id: 3,
-    couponName: "某某某某某优惠券",
-    income: "18.00",
-    receiveTime: "2026-05-18 19:00:00",
-    receiver: "周昭宁",
-  },
-  {
-    id: 4,
-    couponName: "某某某某某优惠券",
-    income: "8.00",
-    receiveTime: "2026-05-18 19:00:00",
-    receiver: "周宇轩",
-  },
-]);
+const pageParams = ref<{ memberId: string; inviteType: string }>({
+  memberId: "",
+  inviteType: "",
+});
+
+const listRef = ref();
 
-function handleViewDetail(item) {
-  uni.showToast({
-    title: `查看 ${item.couponName} 详情`,
-    icon: "none",
+const memberLevelMap: Record<string, string> = {
+  "1": "一级团员",
+  "2": "二级团员",
+};
+
+const getCouponListApi = (params: any) => {
+  return getMemberIncomeList({
+    pageNo: params.pageNo,
+    pageSize: params.pageSize,
+    memberId: pageParams.value.memberId,
+    inviteType: pageParams.value.inviteType,
   });
-}
+};
+
+const afterFetch = (result: any) => {
+  totalIncome.value = result.totalAmount;
+};
+
+onLoad((options: any) => {
+  pageParams.value.memberId = options.memberId || "";
+  pageParams.value.inviteType = options.inviteType || "";
+});
 </script>
 
 <template>
@@ -65,7 +57,7 @@ function handleViewDetail(item) {
                     backgroundPosition: 'center'
                 }">
         <text class="income-label">累计总收益(元)</text>
-        <text class="income-amount">3859.00</text>
+        <text class="income-amount">{{ totalIncome || 0}}</text>
       </view>
 
       <view class="share-card">
@@ -78,84 +70,82 @@ function handleViewDetail(item) {
             <text class="total-label">总收益</text>
             <view>
               <text class="total-symbol">¥</text>
-              <text class="total-amount">{{ totalIncome }}</text>
+              <text class="total-amount">{{ totalIncome || 0}}</text>
             </view>
           </view>
         </view>
 
-        <view class="records-list">
-          <view v-for="(item, index) in shareList" :key="item.id" class="record-item">
-
-            <view class="record-bottom">
-              <view class="info-row">
-                <text class="info-label">团员层级</text>
-                <text class="info-value">¥{{ item.income }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">优惠券名称</text>
-                <text class="info-value">{{ item.receiver }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">核销时间</text>
-                <text class="info-value">{{ item.receiver }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">发券团员</text>
-                <view class="income-person">
-                  <u--image class='income-phone' :src="getImageUrl('@img/me/head.png')" width="42rpx" height="42rpx"
-                    shape="circle">
-                  </u--image>
-                  <view>林雨欣</view>
+        <LsvList ref="listRef" :api="getCouponListApi" key-name="result" @afterFetch="afterFetch">
+          <template #list="{ data }">
+            <view v-for="(item, index) in data" :key="item.writeOffTime + index" class="record-item">
+              <view class="record-bottom">
+                <view class="info-row">
+                  <text class="info-label">团员层级</text>
+                  <text class="info-value">{{ memberLevelMap[String(item.memberLevel)] || '--' }}</text>
                 </view>
-              </view>
-              <view class="info-row">
-                <text class="info-label">团员联系方式</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">核销用户</text>
-                <view class="income-person">
-                  <u--image class='income-phone' :src="getImageUrl('@img/me/head.png')" width="42rpx" height="42rpx"
-                    shape="circle">
-                  </u--image>
-                  <view>林雨欣</view>
+                <view class="info-row">
+                  <text class="info-label">优惠券名称</text>
+                  <text class="info-value">{{ item.couponName || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">核销时间</text>
+                  <text class="info-value">{{ item.writeOffTime || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">发券团员</text>
+                  <view class="income-person">
+                    <u--image class='income-phone'
+                      :src="item.membersReceiveCouponsUrl || getImageUrl('@img/me/head.png')" width="42rpx"
+                      height="42rpx" shape="circle">
+                    </u--image>
+                    <view>{{ item.membersReceiveCouponsNickName || '--' }}</view>
+                  </view>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">团员联系方式</text>
+                  <text class="info-value">{{ item.membersReceiveCouponsPhone || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">核销用户</text>
+                  <view class="income-person">
+                    <u--image class='income-phone' :src="item.writeOffUserUrl || getImageUrl('@img/me/head.png')"
+                      width="42rpx" height="42rpx" shape="circle">
+                    </u--image>
+                    <view>{{ item.writeOffUserNickName || '--' }}</view>
+                  </view>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">用户联系方式</text>
+                  <text class="info-value">{{ item.writeOffUserPhone || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">核销类型</text>
+                  <text class="info-value">{{ item.commodityCategory || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">商品名称</text>
+                  <text class="info-value">{{ item.productName || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">核销商家</text>
+                  <text class="info-value">{{ item.writeOffMerchant || '--' }}</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">实付金额</text>
+                  <text class="info-value">{{ item.actualPaymentAmount ?? '--' }}元</text>
+                </view>
+                <view class="info-row">
+                  <text class="info-label">获得佣金</text>
+                  <text class="income-value">{{ item.commission ?? '--' }}</text>
                 </view>
               </view>
-              <view class="info-row">
-                <text class="info-label">用户联系方式</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">核销类型</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">商品名称</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">核销商家</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">实付金额</text>
-                <text class="info-value">{{ item.receiveTime }}</text>
-              </view>
-              <view class="info-row">
-                <text class="info-label">获得佣金</text>
-                <text class="income-value">{{ item.receiveTime }}</text>
-              </view>
-            </view>
 
-            <view v-if="index < shareList.length - 1" class="record-divider"></view>
-          </view>
-        </view>
+              <view v-if="index < data.length - 1" class="record-divider"></view>
+            </view>
+          </template>
+        </LsvList>
       </view>
     </view>
-
-    <!-- 日期 -->
-    <DateRangePicker v-model:show="showPicker" :startDate="defaultStart" :endDate="defaultEnd" @confirm="handleConfirm"
-      @cancel="handleCancel" />
   </view>
 </template>
 
@@ -163,8 +153,11 @@ function handleViewDetail(item) {
 .share-info-container {
   min-height: 100vh;
   background: #f8f8fa;
+  display: flex;
+  flex-direction: column;
 
   .share-info-content {
+    flex: 1;
     margin: 32rpx;
     box-sizing: border-box;
     overflow: auto;
@@ -252,86 +245,63 @@ function handleViewDetail(item) {
       }
     }
 
-    .records-list {
-      .record-item {
-        padding: 32rpx 0;
+    .record-item {
+      padding: 32rpx 0;
 
-        .record-top {
+      .record-bottom {
+        .info-row {
           display: flex;
           justify-content: space-between;
+          margin-bottom: 30rpx;
           align-items: center;
-          margin-bottom: 40rpx;
+          min-height: 30rpx;
+          line-height: 30rpx;
+
+          .info-label {
+            font-weight: 400;
+            font-size: 30rpx;
+            color: #86909c;
+            white-space: nowrap;
+          }
 
-          .coupon-name {
+          .info-value {
+            font-weight: 400;
+            font-size: 30rpx;
+            color: #333333;
+            text-align: right;
+            white-space: nowrap;
+          }
+
+          .income-value {
             font-weight: 500;
-            font-size: 28rpx;
-            color: #2c2c2c;
-            line-height: 28rpx;
+            font-size: 30rpx;
+            color: #ff5365;
           }
 
-          .income-amount {
+          .income-person {
             display: flex;
             align-items: center;
-            gap: 12rpx;
-
-            .income-label {
-              font-weight: 400;
-              font-size: 30rpx;
-              color: #333333;
-              line-height: 30rpx;
-            }
           }
-        }
 
-        .record-bottom {
-          .info-row {
-            display: flex;
-            justify-content: space-between;
-            margin-bottom: 30rpx;
-            align-items: center;
-            height: 30rpx;
-            line-height: 30rpx;
-
-            .info-label {
-              font-weight: 400;
-              font-size: 30rpx;
-              color: #86909c;
-            }
-
-            .info-value {
-              font-weight: 400;
-              font-size: 30rpx;
-              color: #333333;
-            }
-            .income-value {
-              font-weight: 500;
-              font-size: 30rpx;
-              color: #ff5365;
-            }
-            .income-person {
-              display: flex;
-              align-items: center;
-            }
-            .income-phone {
-              margin-right: 12rpx;
-            }
+          .income-phone {
+            margin-right: 12rpx;
           }
         }
+      }
 
-        .record-divider {
-          width: 100%;
-          height: 1rpx;
-          background: #eaeaea;
-          margin-top: 32rpx;
-        }
+      .record-divider {
+        width: 100%;
+        height: 1rpx;
+        background: #eaeaea;
+        margin-top: 32rpx;
       }
+    }
 
-      .record-item:last-child {
-        .info-row:last-child {
-          margin-bottom: 0;
-        }
+    .record-item:last-child {
+      .info-row:last-child {
+        margin-bottom: 0;
       }
     }
   }
 }
-</style>
+</style>