Ver código fonte

改造登录;完善功能

Huanyi 4 semanas atrás
pai
commit
d9344cb06b
55 arquivos alterados com 1990 adições e 714 exclusões
  1. 10 1
      .idea/workspace.xml
  2. 13 0
      api/archieves/changeLog/index.js
  3. 11 0
      api/archieves/pet/index.js
  4. 5 3
      api/auth.js
  5. 22 0
      api/fulfiller.js
  6. 3 1
      manifest.json
  7. 2 2
      pages/home/index.vue
  8. 2 2
      pages/mine/index.vue
  9. 125 45
      pages/mine/order-stats.vue
  10. 139 64
      pages/mine/points/detail.vue
  11. 75 27
      pages/mine/points/index.vue
  12. 133 38
      pages/mine/rewards-all.vue
  13. 95 20
      pages/mine/rewards.vue
  14. 140 72
      pages/mine/wallet/bill.vue
  15. 83 36
      pages/mine/wallet/index.vue
  16. 44 13
      pages/orders/detail-logic.js
  17. 70 0
      pages/recruit/auth.css
  18. 31 6
      pages/recruit/auth.vue
  19. 40 10
      pages/recruit/auth_logic.js
  20. BIN
      unpackage/cache/apk/__UNI__76F5C47_cm.apk
  21. 1 1
      unpackage/cache/apk/apkurl
  22. 0 0
      unpackage/cache/apk/cmManifestCache.json
  23. 1 1
      unpackage/cache/wgt/__UNI__76F5C47/app-config-service.js
  24. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/app-service.js
  25. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/app.css
  26. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/manifest.json
  27. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/pages/home/index.css
  28. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/pages/mine/index.css
  29. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/pages/orders/detail.css
  30. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/pages/orders/index.css
  31. 0 0
      unpackage/cache/wgt/__UNI__76F5C47/uni-app-view.umd.js
  32. 1 1
      unpackage/dist/build/app-plus/app-config-service.js
  33. 0 0
      unpackage/dist/build/app-plus/app-service.js
  34. 0 0
      unpackage/dist/build/app-plus/app.css
  35. 34 1
      unpackage/dist/build/app-plus/manifest.json
  36. 0 0
      unpackage/dist/build/app-plus/pages/home/index.css
  37. 0 0
      unpackage/dist/build/app-plus/pages/mine/index.css
  38. 0 0
      unpackage/dist/build/app-plus/pages/orders/detail.css
  39. 0 0
      unpackage/dist/build/app-plus/pages/orders/index.css
  40. 0 0
      unpackage/dist/build/app-plus/uni-app-view.umd.js
  41. 1 1
      unpackage/dist/dev/app-plus/app-config-service.js
  42. 732 341
      unpackage/dist/dev/app-plus/app-service.js
  43. 0 0
      unpackage/dist/dev/app-plus/app.css
  44. 2 1
      unpackage/dist/dev/app-plus/manifest.json
  45. 7 7
      unpackage/dist/dev/app-plus/pages/mine/order-stats.css
  46. 33 3
      unpackage/dist/dev/app-plus/pages/mine/points/detail.css
  47. 28 1
      unpackage/dist/dev/app-plus/pages/mine/rewards-all.css
  48. 33 3
      unpackage/dist/dev/app-plus/pages/mine/wallet/bill.css
  49. 60 0
      unpackage/dist/dev/app-plus/pages/recruit/auth.css
  50. 0 0
      unpackage/dist/dev/app-plus/uni-app-view.umd.js
  51. 0 0
      unpackage/dist/dev/cache/.app-plus/tsc/app-android/.tsbuildInfo
  52. BIN
      unpackage/release/apk/__UNI__76F5C47__20260316202839.apk
  53. BIN
      unpackage/release/apk/__UNI__76F5C47__20260317093308.apk
  54. 5 4
      utils/config.js
  55. 9 9
      utils/request.js

+ 10 - 1
.idea/workspace.xml

@@ -84,6 +84,7 @@
       <workItem from="1773142765254" duration="647000" />
       <workItem from="1773252784481" duration="88000" />
       <workItem from="1773309863004" duration="21000" />
+      <workItem from="1773334157405" duration="23000" />
     </task>
     <task id="LOCAL-00001" summary="1.完成app端履约者入驻相关功能开发&#10;2.完成app端履约者登录功能开发&#10;3.完成履约者个人中心功能开发">
       <option name="closed" value="true" />
@@ -141,7 +142,15 @@
       <option name="project" value="LOCAL" />
       <updated>1773309878846</updated>
     </task>
-    <option name="localTasksCounter" value="8" />
+    <task id="LOCAL-00008" summary="整改基本完成">
+      <option name="closed" value="true" />
+      <created>1773334173000</created>
+      <option name="number" value="00008" />
+      <option name="presentableId" value="LOCAL-00008" />
+      <option name="project" value="LOCAL" />
+      <updated>1773334173000</updated>
+    </task>
+    <option name="localTasksCounter" value="9" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">

+ 13 - 0
api/archieves/changeLog/index.js

@@ -0,0 +1,13 @@
+import request from '@/utils/request'
+
+/**
+ * 获取变更日志列表(备注日志)
+ * @param {Object} params - { targetId, targetType }
+ */
+export function listChangeLog(params) {
+  return request({
+    url: '/archieves/changeLog/listAll',
+    method: 'GET',
+    data: params
+  })
+}

+ 11 - 0
api/archieves/pet/index.js

@@ -14,3 +14,14 @@ export function getPetDetail(id) {
         method: 'GET'
     })
 }
+/**
+ * 提交宠物备注
+ * @param {Object} data - { petId, content }
+ */
+export function submitPetRemark(data) {
+    return request({
+        url: '/archieves/pet/remark',
+        method: 'POST',
+        data
+    })
+}

+ 5 - 3
api/auth.js

@@ -16,12 +16,14 @@ export function loginByPassword(username, password) {
     method: 'POST',
     needToken: false,
     data: {
-      tenantId: TENANT_ID,
-      platformId: PLATFORM_ID,
+      // tenantId: TENANT_ID,
+      // platformId: PLATFORM_ID,
+      userSource: 1,
       username,
       password,
       clientId: CLIENT_ID,
-      grantType: 'fulfiller_password' // 使用履约者专用认证策略
+      grantType: 'password',
+      source: 1
     }
   })
 }

+ 22 - 0
api/fulfiller.js

@@ -284,6 +284,28 @@ export function getOrderCount() {
   })
 }
 
+/**
+ * 获取订单统计数据(含奖励、惩罚、拒单等合计)
+ */
+export function getOrderStats() {
+  return request({
+    url: '/order/subOrderLog/count',
+    method: 'GET'
+  })
+}
+
+/**
+ * 分页获取统计页面的订单列表
+ * @param {Object} params - { status, pageNum, pageSize }
+ */
+export function getStatisticOrders(params) {
+  return request({
+    url: '/order/subOrder/listOnStatistic',
+    method: 'GET',
+    data: params
+  })
+}
+
 /**
  * 获取我的订单列表
  * @param {Object} params - { status, content, service, startServiceTime, endServiceTime }

+ 3 - 1
manifest.json

@@ -17,7 +17,9 @@
             "delay" : 0
         },
         /* 模块配置 */
-        "modules" : {},
+        "modules" : {
+            "Camera" : {}
+        },
         /* 应用发布信息 */
         "distribute" : {
             /* android打包配置 */

+ 2 - 2
pages/home/index.vue

@@ -33,10 +33,10 @@
                         <text class="city-arrow">></text>
                     </view>
                 </view>
-                <view class="notification-box">
+               <!-- <view class="notification-box">
                     <image class="bell-img" src="/static/icons/bell.svg"></image>
                     <view class="badge-count">2</view>
-                </view>
+                </view> -->
             </view>
 
             <!-- 统计卡片 -->

+ 2 - 2
pages/mine/index.vue

@@ -95,14 +95,14 @@
 
         <!-- 菜单列表 -->
         <view class="menu-list">
-            <view class="menu-item" @click="navToNotification">
+           <!-- <view class="menu-item" @click="navToNotification">
                 <image class="menu-icon" src="/static/icons/bell_linear.svg"></image>
                 <text class="menu-text">消息中心</text>
                 <view class="menu-right">
                     <view class="red-dot"></view>
                     <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
                 </view>
-            </view>
+            </view> -->
             <view class="menu-item" @click="navToRewards">
                 <image class="menu-icon" src="/static/icons/money_linear.svg"></image>
                 <text class="menu-text">我的奖惩</text>

+ 125 - 45
pages/mine/order-stats.vue

@@ -3,25 +3,21 @@
         <!-- 统计banner:圆角浮动卡,左右30rpx边距 -->
         <view class="stats-banner">
             <view class="banner-item">
-                <text class="banner-num">2546</text>
+                <text class="banner-num">{{ stats.total }}</text>
                 <text class="banner-label">累计接单</text>
             </view>
             <view class="banner-item">
-                <text class="banner-num">10</text>
+                <text class="banner-num">{{ stats.reject }}</text>
                 <text class="banner-label">累计拒单</text>
             </view>
             <view class="banner-item">
-                <text class="banner-num">10</text>
+                <text class="banner-num">{{ stats.reward }}</text>
                 <text class="banner-label">奖励单量</text>
             </view>
             <view class="banner-item">
-                <text class="banner-num">10</text>
+                <text class="banner-num">{{ stats.punish }}</text>
                 <text class="banner-label">惩罚单量</text>
             </view>
-            <view class="banner-item">
-                <text class="banner-num">158<text class="banner-unit">天</text></text>
-                <text class="banner-label">服务时长</text>
-            </view>
         </view>
 
         <!-- 标签页(全宽,无圆角,紧贴屏幕宽度) -->
@@ -39,7 +35,7 @@
         </view>
 
         <!-- 订单列表:每张卡片用margin左右各30rpx,与banner宽度对齐 -->
-        <scroll-view scroll-y class="order-scroll">
+        <scroll-view scroll-y class="order-scroll" @scrolltolower="onReachBottom">
             <view style="height: 16rpx;"></view>
 
             <view
@@ -108,64 +104,146 @@
             </view>
 
             <!-- 空状态 -->
-            <view class="empty-state" v-if="filteredOrders.length === 0">
+            <view class="empty-state" v-if="filteredOrders.length === 0 && !loading">
                 <text class="empty-text">暂无相关订单</text>
             </view>
+            
+            <view class="loading-more" v-if="loading">
+                <text>加载中...</text>
+            </view>
+
             <view style="height: 40rpx;"></view>
         </scroll-view>
     </view>
 </template>
 
 <script>
+import { getOrderStats, getStatisticOrders } from '@/api/fulfiller';
+import { getServiceList } from '@/api/service';
+
 export default {
     data() {
         return {
             tabs: ['全部', '已完成', '已拒绝'],
             activeTab: 0,
-            orders: [
-                {
-                    orderType: 1,
-                    typeName: '接送', typeIcon: '/static/icons/car.svg',
-                    status: '完成', finishTime: '2026/02/03 14:30', serviceTime: '2026/02/10 10:00',
-                    petName: '哈士奇宝宝', petBreed: '哈士奇', petAvatar: '/static/dog.png', price: '20.00',
-                    startName: '武汉大学宠物店', startAddr: '武汉市洪山区珞喻路458号',
-                    endName: '张** 189****8451', endAddr: '武汉市武昌区新区大道凤凰广场A座', serviceNote: ''
-                },
-                {
-                    orderType: 2,
-                    typeName: '喂遛', typeIcon: '/static/icons/walk.svg',
-                    status: '完成', finishTime: '2026/02/03 15:00', serviceTime: '2026/02/11 14:00',
-                    petName: '金毛', petBreed: '金毛寻回犬', petAvatar: '/static/dog.png', price: '35.00',
-                    startName: '', startAddr: '',
-                    endName: '王女士 138****1234', endAddr: '武汉市江汉区泛海国际居住区', serviceNote: '需自带牵引绳,遛弯30分钟。'
-                },
-                {
-                    orderType: 3,
-                    typeName: '洗护', typeIcon: '/static/icons/wash.svg',
-                    status: '拒绝', finishTime: '2026/02/03 09:30', serviceTime: '2026/02/12 09:30',
-                    petName: 'Mimi', petBreed: '布偶猫', petAvatar: '/static/dog.png', price: '50.00',
-                    startName: '', startAddr: '',
-                    endName: '赵先生 159****9876', endAddr: '武汉市汉阳区钟家村', serviceNote: '上门洗澡,剪指甲。'
-                }
-            ]
+            stats: {
+                total: 0,
+                reject: 0,
+                reward: 0,
+                punish: 0
+            },
+            orders: [],
+            serviceList: [],
+            pageNum: 1,
+            pageSize: 10,
+            total: 0,
+            loading: false
         };
     },
     computed: {
         filteredOrders() {
-            if (this.activeTab === 0) return this.orders;
-            if (this.activeTab === 1) return this.orders.filter(o => o.status === '完成');
-            return this.orders.filter(o => o.status === '拒绝');
+            return this.orders;
         }
     },
+    async onLoad() {
+        await this.loadServiceList();
+        this.fetchStats();
+        this.fetchOrders(true);
+    },
     methods: {
-        switchTab(idx) { this.activeTab = idx; }
+        async loadServiceList() {
+            try {
+                const res = await getServiceList();
+                this.serviceList = res.data || [];
+            } catch (err) {
+                console.error('获取服务类型失败:', err);
+            }
+        },
+        async fetchStats() {
+            try {
+                const res = await getOrderStats();
+                if (res.code === 200 && res.data) {
+                    this.stats = {
+                        ...this.stats,
+                        ...res.data
+                    };
+                }
+            } catch (err) {
+                console.error('获取统计值失败:', err);
+            }
+        },
+        async fetchOrders(reset = false) {
+            if (reset) {
+                this.pageNum = 1;
+                this.orders = [];
+            }
+            if (this.loading) return;
+            if (!reset && this.orders.length >= this.total && this.total !== 0) return;
+
+            this.loading = true;
+            try {
+                const statusMap = { 0: undefined, 1: 4, 2: 5 };
+                const params = {
+                    status: statusMap[this.activeTab],
+                    pageNum: this.pageNum,
+                    pageSize: this.pageSize
+                };
+                const res = await getStatisticOrders(params);
+                if (res.code === 200) {
+                    this.total = res.total || 0;
+                    const rows = res.rows || [];
+                    const mapped = rows.map(item => this.transformOrder(item));
+                    this.orders = this.orders.concat(mapped);
+                    this.pageNum++;
+                }
+            } catch (err) {
+                console.error('获取订单列表失败:', err);
+            } finally {
+                this.loading = false;
+            }
+        },
+        transformOrder(order) {
+            const service = this.serviceList.find(s => s.id === order.service);
+            const mode = service?.mode || 0;
+            const isRoundTrip = mode === 1;
+            const isSuccess = order.status === 4;
+
+            return {
+                id: order.id,
+                orderType: isRoundTrip ? 1 : 2,
+                typeName: service?.name || '未知',
+                typeIcon: service?.iconUrl || '',
+                status: isSuccess ? '完成' : '拒绝',
+                finishTime: order.serviceTime || '',
+                serviceTime: order.serviceTime || '',
+                petName: order.petName || '未知',
+                petBreed: order.breed || '未知',
+                petAvatar: order.petAvatarUrl || '/static/dog.png',
+                price: (order.price / 100).toFixed(2),
+                startName: order.fromAddress || '',
+                startAddr: order.fromAddress || '',
+                endName: (order.customerName || '') + ' ' + (order.customerPhone || ''),
+                endAddr: order.toAddress || '',
+                serviceNote: order.remark || ''
+            };
+        },
+        switchTab(idx) {
+            this.activeTab = idx;
+            this.fetchOrders(true);
+        },
+        onReachBottom() {
+            this.fetchOrders();
+        },
+        navBack() {
+            uni.navigateBack();
+        }
     }
 };
 </script>
 
 <style>
 page { background-color: #F7F8FA; }
-.container { min-height: 100vh; background-color: #F7F8FA; padding: 20rpx 0 0; }
+.container { min-height: 100vh; background-color: #F7F8FA; padding: 20rpx 0 0; display: flex; flex-direction: column; }
 
 /* ===== 统计banner:圆角浮动卡,左右30rpx边距 ===== */
 .stats-banner {
@@ -176,6 +254,7 @@ page { background-color: #F7F8FA; }
     margin: 0 30rpx 20rpx;
     border-radius: 20rpx;
     box-shadow: 0 6rpx 20rpx rgba(255, 87, 34, 0.25);
+    flex-shrink: 0;
 }
 
 .banner-item { display: flex; flex-direction: column; align-items: center; }
@@ -190,6 +269,7 @@ page { background-color: #F7F8FA; }
     padding: 0 30rpx;
     border-bottom: 1rpx solid #f0f0f0;
     margin-bottom: 0;
+    flex-shrink: 0;
 }
 
 .tab-item {
@@ -216,14 +296,13 @@ page { background-color: #F7F8FA; }
 }
 
 /* ===== 订单列表:scroll-view 全宽,每张card用margin左右30rpx ===== */
-.order-scroll { width: 100%; }
+.order-scroll { flex: 1; height: 0; width: 100%; }
 
-/* 关键:order-card 用 margin: 0 30rpx 实现与banner对齐 */
 .order-card {
     background-color: #fff;
     border-radius: 16rpx;
     padding: 24rpx;
-    margin: 0 30rpx 16rpx;   /* ← 与banner的 margin: 0 30rpx 完全一致 */
+    margin: 0 30rpx 16rpx;
     box-sizing: border-box;
 }
 
@@ -237,7 +316,6 @@ page { background-color: #F7F8FA; }
 
 .type-badge { display: flex; align-items: center; }
 
-/* 订单类型图标:与my-orders列表一致,直接使用带色彩的SVG图标 */
 .type-icon {
     width: 44rpx;
     height: 44rpx;
@@ -327,4 +405,6 @@ page { background-color: #F7F8FA; }
 /* 空状态 */
 .empty-state { text-align: center; padding: 80rpx 0; }
 .empty-text { font-size: 28rpx; color: #ccc; }
+
+.loading-more { text-align: center; padding: 20rpx; font-size: 24rpx; color: #999; }
 </style>

+ 139 - 64
pages/mine/points/detail.vue

@@ -11,19 +11,32 @@
 
         <!-- 内容区域 -->
         <view class="content-area">
-            <!-- Tabs -->
-            <view class="tabs-row">
-                <view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
-                    <text>全部</text>
-                    <view class="tab-line" v-if="currentTab === 0"></view>
-                </view>
-                <view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
-                    <text>获取</text>
-                    <view class="tab-line" v-if="currentTab === 1"></view>
+            <!-- 筛选行: Tabs + 日期选择器 -->
+            <view class="filter-area">
+                <!-- Tabs -->
+                <view class="tabs-row">
+                    <view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
+                        <text>全部</text>
+                        <view class="tab-line" v-if="currentTab === 0"></view>
+                    </view>
+                    <view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
+                        <text>获取</text>
+                        <view class="tab-line" v-if="currentTab === 1"></view>
+                    </view>
+                    <view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">
+                        <text>扣减</text>
+                        <view class="tab-line" v-if="currentTab === 2"></view>
+                    </view>
                 </view>
-                <view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">
-                    <text>扣减</text>
-                    <view class="tab-line" v-if="currentTab === 2"></view>
+
+                <!-- 日期选择器 -->
+                <view class="date-picker-wrap">
+                    <picker mode="date" fields="month" :value="currentDate" @change="onDateChange">
+                        <view class="date-picker">
+                            <text class="date-text">{{ year }}年{{ `${month}`.padStart(2, '0') }}月</text>
+                            <text class="arrow-down">﹀</text>
+                        </view>
+                    </picker>
                 </view>
             </view>
 
@@ -67,62 +80,26 @@
 </template>
 
 <script>
+import { listPointsOnApp } from '@/api/fulfiller/log/index.js';
+
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfPointsBizType;
+
 export default {
     data() {
+        const d = new Date();
         return {
             currentTab: 0,
-            // 模拟数据结构
-            groups: [
-                {
-                    month: '2月 2026',
-                    income: '15',
-                    expense: '10',
-                    items: [
-                        {
-                            title: '订单完成奖励',
-                            desc: '订单完成',
-                            time: '02-05 18:42',
-                            amount: '10',
-                            type: 'income',
-                            tag: '订单'
-                        },
-                        {
-                            title: '好评奖励',
-                            desc: '五星好评',
-                            time: '02-05 19:00',
-                            amount: '5',
-                            type: 'income',
-                            tag: '奖励'
-                        },
-                        {
-                            title: '超时扣分',
-                            desc: '订单超时',
-                            time: '02-04 10:20',
-                            amount: '-10',
-                            type: 'expense',
-                            tag: '惩罚'
-                        }
-                    ]
-                },
-                {
-                    month: '1月 2026',
-                    income: '100',
-                    expense: '0',
-                    items: [
-                        {
-                            title: '新用户奖励',
-                            desc: '注册赠送',
-                            time: '01-10 09:00',
-                            amount: '100',
-                            type: 'income',
-                            tag: '系统'
-                        }
-                    ]
-                }
-            ]
+            year: d.getFullYear(),
+            month: d.getMonth() + 1,
+            groups: []
         }
     },
     computed: {
+        currentDate() {
+            return `${this.year}-${String(this.month).padStart(2, '0')}`;
+        },
         displayGroups() {
             if (this.currentTab === 0) return this.groups;
             
@@ -138,7 +115,72 @@ export default {
             }).filter(group => group.items.length > 0);
         }
     },
+    onShow() {
+        this.fetchData();
+    },
     methods: {
+        async fetchData() {
+            try {
+                const res = await listPointsOnApp({
+                    year: this.year,
+                    month: this.month
+                });
+                if (res.code === 200) {
+                    const list = res.data || [];
+                    let incomeTotal = 0;
+                    let expenseTotal = 0;
+
+                    const items = list.map(item => {
+                        const isAdd = item.type === 'add';
+                        const uiType = isAdd ? 'income' : 'expense';
+                        const title = bizTypeMap[item.bizType] || item.bizType || '其他';
+                        let amountVal = Math.abs(item.amount);
+                        
+                        if (isAdd) {
+                            incomeTotal += amountVal;
+                        } else {
+                            expenseTotal += amountVal;
+                        }
+
+                        let amountStr = String(amountVal);
+                        if (!isAdd) amountStr = '-' + amountStr;
+
+                        let timeStr = item.createTime || '';
+                        if (timeStr.length >= 16) {
+                            timeStr = timeStr.substring(5, 16); 
+                        }
+
+                        return {
+                            ...item,
+                            title: title,
+                            desc: item.reason || '',
+                            time: timeStr,
+                            amount: amountStr,
+                            type: uiType,
+                            tag: title
+                        };
+                    });
+
+                    this.groups = [
+                        {
+                            month: `${this.month}月 ${this.year}`,
+                            income: String(incomeTotal),
+                            expense: String(expenseTotal),
+                            items: items
+                        }
+                    ];
+                }
+            } catch (error) {
+                console.error('获取积分明细记录失败', error);
+            }
+        },
+        onDateChange(e) {
+            const val = e.detail.value;
+            const [y, m] = val.split('-');
+            this.year = parseInt(y, 10);
+            this.month = parseInt(m, 10);
+            this.fetchData();
+        },
         navBack() {
             uni.navigateBack();
         },
@@ -204,14 +246,22 @@ export default {
     flex-direction: column;
 }
 
+/* 筛选区域 */
+.filter-area {
+    background-color: #fff;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 30rpx;
+    margin-bottom: 20rpx;
+}
+
 /* Tabs */
 .tabs-row {
-    background-color: #fff;
     display: flex;
-    justify-content: space-around;
     padding-top: 20rpx;
     padding-bottom: 2rpx;
-    margin-bottom: 20rpx;
+    gap: 40rpx;
 }
 
 .tab-item {
@@ -239,6 +289,31 @@ export default {
     bottom: 0;
 }
 
+/* 日期选择器 */
+.date-picker-wrap {
+    display: flex;
+    align-items: center;
+}
+
+.date-picker {
+    background-color: #F5F7FA;
+    padding: 8rpx 20rpx;
+    border-radius: 30rpx;
+    display: flex;
+    align-items: center;
+}
+
+.date-text {
+    font-size: 26rpx;
+    color: #333;
+    margin-right: 8rpx;
+}
+
+.arrow-down {
+    font-size: 24rpx;
+    color: #999;
+}
+
 /* 列表容器 */
 .bill-list {
     flex: 1;

+ 75 - 27
pages/mine/points/index.vue

@@ -22,7 +22,7 @@
             </view>
             <view class="card-body">
                 <text class="label">当前积分</text>
-                <text class="value">1200</text>
+                <text class="value">{{ points }}</text>
             </view>
             <!-- 装饰背景 -->
             <image class="bg-decor" src="/static/icons/star_decor.svg" mode="aspectFit"></image>
@@ -77,36 +77,22 @@
 </template>
 
 <script>
+import { pointsOnApp, pagePointsOnApp } from '@/api/fulfiller/log/index.js';
+
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfPointsBizType;
+
 export default {
     data() {
         return {
+            points: 0,
             currentTab: 0,
-            list: [
-                {
-                    title: '订单完成奖励',
-                    desc: '订单 T1002839 完成',
-                    time: '2026-02-05 18:42',
-                    amount: '10',
-                    type: 'income',
-                    tag: '订单'
-                },
-                {
-                    title: '好评奖励',
-                    desc: '获得五星好评',
-                    time: '2026-02-05 19:00',
-                    amount: '5',
-                    type: 'income',
-                    tag: '奖励'
-                },
-                {
-                    title: '超时扣分',
-                    desc: '订单 T1002830 超时送达',
-                    time: '2026-02-04 10:20',
-                    amount: '-10',
-                    type: 'expense',
-                    tag: '惩罚'
-                }
-            ]
+            list: [],
+            pageNum: 1,
+            pageSize: 10,
+            total: 0,
+            loading: false
         }
     },
     computed: {
@@ -116,7 +102,69 @@ export default {
             return this.list.filter(item => item.type === type);
         }
     },
+    onShow() {
+        this.fetchPoints();
+        this.fetchList(true);
+    },
+    onReachBottom() {
+        this.fetchList();
+    },
     methods: {
+        async fetchPoints() {
+            try {
+                const res = await pointsOnApp();
+                if (res.code === 200) {
+                    this.points = res.data || 0;
+                }
+            } catch (error) {
+                console.error('获取当前积分失败', error);
+            }
+        },
+        async fetchList(reset = false) {
+            if (reset) {
+                this.pageNum = 1;
+                this.list = [];
+                this.total = 0;
+            }
+            if (this.loading) return;
+            if (!reset && this.list.length >= this.total && this.total !== 0) return;
+
+            this.loading = true;
+            try {
+                const res = await pagePointsOnApp({
+                    pageNum: this.pageNum,
+                    pageSize: this.pageSize
+                });
+                if (res.code === 200) {
+                    this.total = res.total || 0;
+                    const rows = res.rows || [];
+                    const mappedRows = rows.map(item => {
+                        const isAdd = item.type === 'add';
+                        const uiType = isAdd ? 'income' : 'expense';
+                        const title = bizTypeMap[item.bizType] || item.bizType || '其他';
+                        let amountStr = Math.abs(item.amount);
+                        if (!isAdd) {
+                            amountStr = '-' + amountStr;
+                        }
+                        return {
+                            ...item,
+                            title: title,
+                            desc: item.reason || '',
+                            time: item.createTime || '',
+                            amount: amountStr,
+                            type: uiType,
+                            tag: title
+                        };
+                    });
+                    this.list = this.list.concat(mappedRows);
+                    this.pageNum++;
+                }
+            } catch (error) {
+                console.error('获取积分明细失败', error);
+            } finally {
+                this.loading = false;
+            }
+        },
         navBack() {
             uni.navigateBack();
         },

+ 133 - 38
pages/mine/rewards-all.vue

@@ -1,16 +1,26 @@
 <template>
     <view class="container">
-        <!-- 类型标签 -->
-        <view class="tab-bar">
-            <view
-                class="tab-item"
-                v-for="(tab, idx) in tabs"
-                :key="idx"
-                :class="{ active: activeTab === idx }"
-                @click="switchTab(idx)"
-            >
-                <text>{{ tab }}</text>
-                <view class="tab-line" v-if="activeTab === idx"></view>
+        <!-- 顶部筛选:类型标签 + 日期选择 -->
+        <view class="filter-header">
+            <view class="tab-bar">
+                <view
+                    class="tab-item"
+                    v-for="(tab, idx) in tabs"
+                    :key="idx"
+                    :class="{ active: activeTab === idx }"
+                    @click="switchTab(idx)"
+                >
+                    <text>{{ tab }}</text>
+                    <view class="tab-line" v-if="activeTab === idx"></view>
+                </view>
+            </view>
+            <view class="date-filter">
+                <picker mode="date" fields="month" :value="currentPickerDate" @change="onDateChange">
+                    <view class="picker-trigger">
+                        <text>{{ selectedYear }}年{{ String(selectedMonth).padStart(2, '0') }}月</text>
+                        <text class="arrow-icon">▼</text>
+                    </view>
+                </picker>
             </view>
         </view>
 
@@ -52,40 +62,28 @@
 </template>
 
 <script>
+import { listOnAppReward } from '@/api/fulfiller/log/index.js';
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfRewardBizType;
+
 export default {
     data() {
+        const now = new Date();
         return {
             tabs: ['全部', '奖励', '惩罚'],
             activeTab: 0,
-            // 所有完整记录(按月分组)
-            allGroups: [
-                {
-                    month: 9,
-                    credited: 30, pending: 0,
-                    items: [
-                        { date: '09-24', title: '高温补贴', desc: '9月份高温天气补贴', amount: 30, status: '已入账', statusClass: 'credited', type: 'reward' }
-                    ]
-                },
-                {
-                    month: 8,
-                    credited: 2610, pending: 0,
-                    items: [
-                        { date: '08-01', title: '单量奖励', desc: '超140单', amount: 560, status: '已入账', statusClass: 'credited', type: 'reward' },
-                        { date: '07-01', title: '单量奖励', desc: '超470单', amount: 2050, status: '已入账', statusClass: 'credited', type: 'reward' }
-                    ]
-                },
-                {
-                    month: 7,
-                    credited: 0, pending: 0,
-                    items: [
-                        { date: '07-15', title: '超时扣款', desc: '订单#T98211 超时30分钟', amount: -15, status: '已扣款', statusClass: 'deducted', type: 'penalty' },
-                        { date: '07-20', title: '客诉扣款', desc: '订单#T98222 餐品遗漏', amount: -50, status: '已扣款', statusClass: 'deducted', type: 'penalty' }
-                    ]
-                }
-            ]
+            selectedYear: now.getFullYear(),
+            selectedMonth: now.getMonth() + 1,
+            // 原始分组数据
+            allGroups: [],
+            loading: false
         };
     },
     computed: {
+        currentPickerDate() {
+            return `${this.selectedYear}-${String(this.selectedMonth).padStart(2, '0')}`;
+        },
         filteredGroups() {
             if (this.activeTab === 0) return this.allGroups;
             const typeKey = this.activeTab === 1 ? 'reward' : 'penalty';
@@ -95,7 +93,73 @@ export default {
             })).filter(g => g.items.length > 0);
         }
     },
+    onShow() {
+        this.fetchMonthData();
+    },
     methods: {
+        async fetchMonthData() {
+            if (this.loading) return;
+            this.loading = true;
+            try {
+                const params = {
+                    year: this.selectedYear,
+                    month: this.selectedMonth
+                };
+                const res = await listOnAppReward(params);
+                const data = res.data || [];
+
+                if (data.length === 0) {
+                    this.allGroups = [];
+                    return;
+                }
+
+                let credited = 0;
+                const items = data.map(item => {
+                    const isAdd = item.type === 'add';
+                    const amountVal = Math.abs(item.amount) / 100;
+                    if (isAdd) credited += amountVal;
+
+                    let dateStr = '';
+                    if (item.createTime) {
+                        const datePart = item.createTime.split(' ')[0];
+                        const parts = datePart.split('-');
+                        if (parts.length >= 3) {
+                            dateStr = `${parts[1]}-${parts[2]}`;
+                        }
+                    }
+
+                    return {
+                        ...item,
+                        date: dateStr,
+                        title: bizTypeMap[item.bizType] || item.bizType || '其他',
+                        desc: item.reason || '',
+                        amount: isAdd ? amountVal : -amountVal,
+                        type: isAdd ? 'reward' : 'penalty',
+                        status: isAdd ? '已入账' : '已扣款',
+                        statusClass: isAdd ? 'credited' : 'deducted'
+                    };
+                });
+
+                this.allGroups = [{
+                    month: this.selectedMonth,
+                    year: this.selectedYear,
+                    credited: credited,
+                    pending: 0,
+                    items: items
+                }];
+            } catch (err) {
+                console.error('获取奖惩明细失败:', err);
+            } finally {
+                this.loading = false;
+            }
+        },
+        onDateChange(e) {
+            const val = e.detail.value;
+            const parts = val.split('-');
+            this.selectedYear = parseInt(parts[0]);
+            this.selectedMonth = parseInt(parts[1]);
+            this.fetchMonthData();
+        },
         switchTab(idx) { this.activeTab = idx; }
     }
 };
@@ -105,10 +169,41 @@ export default {
 page { background-color: #F7F8FA; }
 .container { min-height: 100vh; background-color: #F7F8FA; }
 
-.tab-bar {
+/* 筛选头部:标签 + 日期 */
+.filter-header {
     display: flex;
+    align-items: center;
+    justify-content: space-between;
     background-color: #fff;
     padding: 0 30rpx;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+
+.tab-bar {
+    display: flex;
+}
+
+.date-filter {
+    padding: 8rpx 0;
+}
+
+.picker-trigger {
+    background-color: #f7f8fa;
+    padding: 8rpx 20rpx;
+    border-radius: 30rpx;
+    display: flex;
+    align-items: center;
+}
+
+.picker-trigger text {
+    font-size: 24rpx;
+    color: #333;
+}
+
+.arrow-icon {
+    font-size: 18rpx;
+    color: #999;
+    margin-left: 8rpx;
 }
 
 .tab-item {

+ 95 - 20
pages/mine/rewards.vue

@@ -9,27 +9,27 @@
             <view class="stats-grid">
                 <view class="stats-cell">
                     <text class="stats-label">奖励订单</text>
-                    <text class="stats-num">3<text class="stats-unit">单</text></text>
+                    <text class="stats-num">{{ stats.rewardCount }}<text class="stats-unit">单</text></text>
                     <view class="stats-divider"></view>
-                    <text class="stats-sub">累计 1258单</text>
+                    <text class="stats-sub">月度统计</text>
                 </view>
                 <view class="stats-cell">
                     <text class="stats-label">惩罚订单</text>
-                    <text class="stats-num">1<text class="stats-unit">单</text></text>
+                    <text class="stats-num">{{ stats.punishCount }}<text class="stats-unit">单</text></text>
                     <view class="stats-divider"></view>
-                    <text class="stats-sub">累计 12单</text>
+                    <text class="stats-sub">月度统计</text>
                 </view>
                 <view class="stats-cell">
                     <text class="stats-label">奖励金额</text>
-                    <text class="stats-num reward-num">2910.00</text>
+                    <text class="stats-num reward-num">{{ (stats.rewardBalance / 100).toFixed(2) }}</text>
                     <view class="stats-divider"></view>
-                    <text class="stats-sub">累计 45800.00</text>
+                    <text class="stats-sub">月度统计</text>
                 </view>
                 <view class="stats-cell">
                     <text class="stats-label">惩罚金额</text>
-                    <text class="stats-num penalty-num">-15.00</text>
+                    <text class="stats-num penalty-num">{{ (stats.punishBalance / 100).toFixed(2) }}</text>
                     <view class="stats-divider"></view>
-                    <text class="stats-sub">累计 350.00</text>
+                    <text class="stats-sub">月度统计</text>
                 </view>
             </view>
         </view>
@@ -125,38 +125,112 @@
 </template>
 
 <script>
+import { countOnAppReward, listOnAppReward } from '@/api/fulfiller/log/index.js';
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfRewardBizType;
+
 export default {
     data() {
+        const now = new Date();
         return {
             tabs: ['全部', '奖励', '惩罚'],
             activeTab: 0,
-            selectedYear: 2026,
-            selectedMonth: 2,
+            selectedYear: now.getFullYear(),
+            selectedMonth: now.getFullYear() === 2026 && now.getMonth() < 2 ? 3 : now.getMonth() + 1, // 默认当前月,处理一下测试数据时间
+            // 统计数据
+            stats: {
+                rewardCount: 0,
+                punishCount: 0,
+                rewardBalance: 0,
+                punishBalance: 0
+            },
             // 月份选择器状态
             showMonthPicker: false,
             pickerYear: 2026,
-            pickerMonth: 2,
-            years: [2021, 2022, 2023, 2024, 2025, 2026],
+            pickerMonth: 3,
+            years: [2024, 2025, 2026],
             months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
             yearScrollTop: 0,
             monthScrollTop: 0,
             // 奖惩记录列表
-            records: [
-                { date: '09-01', title: '单量奖励', desc: '超140单', amount: 560, status: '待入账', statusClass: 'pending', type: 'reward' },
-                { date: '08-01', title: '单量奖励', desc: '超470单', amount: 2050, status: '已入账', statusClass: 'credited', type: 'reward' },
-                { date: '09-02', title: '超时扣款', desc: '订单#T982 超时30分钟', amount: -15, status: '已扣款', statusClass: 'deducted', type: 'penalty' },
-                { date: '09-05', title: '高温补贴', desc: '8月份高温天气补贴', amount: 300, status: '已入账', statusClass: 'credited', type: 'reward' }
-            ]
+            records: []
         };
     },
     computed: {
         filteredList() {
             if (this.activeTab === 0) return this.records;
-            if (this.activeTab === 1) return this.records.filter(r => r.type === 'reward');
-            return this.records.filter(r => r.type === 'penalty');
+            const targetType = this.activeTab === 1 ? 'reward' : 'penalty';
+            return this.records.filter(r => r.type === targetType);
+        }
+    },
+    onShow() {
+        // 设置默认选中的年月
+        const now = new Date();
+        if (this.selectedYear === 2026 && this.selectedMonth === 2) {
+             // 保持默认或根据实际需求
         }
+        this.fetchData();
     },
     methods: {
+        async fetchData() {
+            const params = {
+                year: this.selectedYear,
+                month: this.selectedMonth
+            };
+            this.fetchStats(params);
+            this.fetchList(params);
+        },
+        async fetchStats(params) {
+            try {
+                const res = await countOnAppReward(params);
+                if (res.code === 200) {
+                    this.stats = res.data || {
+                        rewardCount: 0,
+                        punishCount: 0,
+                        rewardBalance: 0,
+                        punishBalance: 0
+                    };
+                }
+            } catch (err) {
+                console.error('获取奖惩统计失败:', err);
+            }
+        },
+        async fetchList(params) {
+            try {
+                const res = await listOnAppReward(params);
+                if (res.code === 200) {
+                    const list = res.data || [];
+                    this.records = list.map(item => {
+                        const isAdd = item.type === 'add';
+                        const amountVal = Math.abs(item.amount) / 100;
+                        
+                        // 格式化日期 MM-DD
+                        let dateStr = '';
+                        if (item.createTime) {
+                            const datePart = item.createTime.split(' ')[0];
+                            const parts = datePart.split('-');
+                            if (parts.length >= 3) {
+                                dateStr = `${parts[1]}-${parts[2]}`;
+                            }
+                        }
+
+                        return {
+                            ...item,
+                            date: dateStr,
+                            title: bizTypeMap[item.bizType] || item.bizType || '其他',
+                            desc: item.reason || '',
+                            amount: isAdd ? amountVal : -amountVal,
+                            type: isAdd ? 'reward' : 'penalty',
+                            status: isAdd ? '已入账' : '已扣款', // 简化处理状态
+                            statusClass: isAdd ? 'credited' : 'deducted'
+                        };
+                    });
+                }
+            } catch (err) {
+                console.error('获取奖惩列表失败:', err);
+            }
+        },
         switchTab(idx) { this.activeTab = idx; },
         openMonthPicker() {
             this.pickerYear = this.selectedYear;
@@ -168,6 +242,7 @@ export default {
             this.selectedYear = this.pickerYear;
             this.selectedMonth = this.pickerMonth;
             this.closeMonthPicker();
+            this.fetchData();
         },
         goToAll() {
             uni.navigateTo({ url: '/pages/mine/rewards-all' });

+ 140 - 72
pages/mine/wallet/bill.vue

@@ -11,19 +11,32 @@
 
         <!-- 内容区域 -->
         <view class="content-area">
-            <!-- Tabs -->
-            <view class="tabs-row">
-                <view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
-                    <text>全部</text>
-                    <view class="tab-line" v-if="currentTab === 0"></view>
-                </view>
-                <view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
-                    <text>收入</text>
-                    <view class="tab-line" v-if="currentTab === 1"></view>
+            <!-- 筛选行: Tabs + 日期选择器 -->
+            <view class="filter-area">
+                <!-- Tabs -->
+                <view class="tabs-row">
+                    <view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
+                        <text>全部</text>
+                        <view class="tab-line" v-if="currentTab === 0"></view>
+                    </view>
+                    <view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
+                        <text>收入</text>
+                        <view class="tab-line" v-if="currentTab === 1"></view>
+                    </view>
+                    <view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">
+                        <text>支出</text>
+                        <view class="tab-line" v-if="currentTab === 2"></view>
+                    </view>
                 </view>
-                <view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">
-                    <text>支出</text>
-                    <view class="tab-line" v-if="currentTab === 2"></view>
+
+                <!-- 日期选择器 -->
+                <view class="date-picker-wrap">
+                    <picker mode="date" fields="month" :value="currentDate" @change="onDateChange">
+                        <view class="date-picker">
+                            <text class="date-text">{{ year }}年{{ `${month}`.padStart(2, '0') }}月</text>
+                            <text class="arrow-down">﹀</text>
+                        </view>
+                    </picker>
                 </view>
             </view>
 
@@ -67,70 +80,26 @@
 </template>
 
 <script>
+import { listBalanceOnApp } from '@/api/fulfiller/log/index.js';
+
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfBalanceBizType;
+
 export default {
     data() {
+        const d = new Date();
         return {
             currentTab: 0,
-            // 模拟数据结构
-            groups: [
-                {
-                    month: '2月 2026',
-                    income: '35.00',
-                    expense: '10.00',
-                    items: [
-                        {
-                            title: '订单服务费用',
-                            desc: '订单完成',
-                            time: '02-03 14:30',
-                            amount: '20.00',
-                            type: 'income',
-                            tag: '订单'
-                        },
-                        {
-                            title: '奖励费用',
-                            desc: '早高峰奖励', // shortened to match ui better
-                            time: '02-03 10:00',
-                            amount: '15.00',
-                            type: 'income',
-                            tag: '奖励'
-                        },
-                        {
-                            title: '惩罚金额',
-                            desc: '超时送达',
-                            time: '02-02 18:20',
-                            amount: '-10.00',
-                            type: 'expense',
-                            tag: '惩罚'
-                        }
-                    ]
-                },
-                {
-                    month: '1月 2026',
-                    income: '3500.00',
-                    expense: '100.00',
-                    items: [
-                        {
-                            title: '后台转账',
-                            desc: '1月工资发放',
-                            time: '01-31 09:00',
-                            amount: '3500.00',
-                            type: 'income',
-                            tag: '工资'
-                        },
-                        {
-                            title: '装备扣款',
-                            desc: '装备费用',
-                            time: '01-15 10:00',
-                            amount: '-100.00',
-                            type: 'expense',
-                            tag: '扣款'
-                        }
-                    ]
-                }
-            ]
+            year: d.getFullYear(),
+            month: d.getMonth() + 1,
+            groups: []
         }
     },
     computed: {
+        currentDate() {
+            return `${this.year}-${String(this.month).padStart(2, '0')}`;
+        },
         displayGroups() {
             if (this.currentTab === 0) return this.groups;
             
@@ -146,7 +115,73 @@ export default {
             }).filter(group => group.items.length > 0);
         }
     },
+    onShow() {
+        this.fetchData();
+    },
     methods: {
+        async fetchData() {
+            try {
+                const res = await listBalanceOnApp({
+                    year: this.year,
+                    month: this.month
+                });
+                if (res.code === 200) {
+                    const list = res.data || [];
+                    let incomeTotal = 0;
+                    let expenseTotal = 0;
+
+                    const items = list.map(item => {
+                        const isAdd = item.type === 'add';
+                        const uiType = isAdd ? 'income' : 'expense';
+                        const title = bizTypeMap[item.bizType] || item.bizType || '其他';
+                        let amountVal = Math.abs(item.amount) / 100;
+                        
+                        if (isAdd) {
+                            incomeTotal += amountVal;
+                        } else {
+                            expenseTotal += amountVal;
+                        }
+
+                        let amountStr = amountVal.toFixed(2);
+                        if (!isAdd) amountStr = '-' + amountStr;
+
+                        // 取时间 HH:mm
+                        let timeStr = item.createTime || '';
+                        if (timeStr.length >= 16) {
+                            timeStr = timeStr.substring(5, 16); 
+                        }
+
+                        return {
+                            ...item,
+                            title: title,
+                            desc: item.reason || '',
+                            time: timeStr,
+                            amount: amountStr,
+                            type: uiType,
+                            tag: title
+                        };
+                    });
+
+                    this.groups = [
+                        {
+                            month: `${this.month}月 ${this.year}`,
+                            income: incomeTotal.toFixed(2),
+                            expense: expenseTotal.toFixed(2),
+                            items: items
+                        }
+                    ];
+                }
+            } catch (error) {
+                console.error('获取账单记录失败', error);
+            }
+        },
+        onDateChange(e) {
+            const val = e.detail.value; // "YYYY-MM"
+            const [y, m] = val.split('-');
+            this.year = parseInt(y, 10);
+            this.month = parseInt(m, 10);
+            this.fetchData();
+        },
         navBack() {
             uni.navigateBack();
         },
@@ -212,14 +247,22 @@ export default {
     flex-direction: column;
 }
 
+/* 筛选区域 */
+.filter-area {
+    background-color: #fff;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 30rpx;
+    margin-bottom: 20rpx;
+}
+
 /* Tabs */
 .tabs-row {
-    background-color: #fff;
     display: flex;
-    justify-content: space-around; /* Match Figure 1 spacing */
     padding-top: 20rpx;
     padding-bottom: 2rpx;
-    margin-bottom: 20rpx;
+    gap: 40rpx;
 }
 
 .tab-item {
@@ -247,6 +290,31 @@ export default {
     bottom: 0;
 }
 
+/* 日期选择器 */
+.date-picker-wrap {
+    display: flex;
+    align-items: center;
+}
+
+.date-picker {
+    background-color: #F5F7FA;
+    padding: 8rpx 20rpx;
+    border-radius: 30rpx;
+    display: flex;
+    align-items: center;
+}
+
+.date-text {
+    font-size: 26rpx;
+    color: #333;
+    margin-right: 8rpx;
+}
+
+.arrow-down {
+    font-size: 24rpx;
+    color: #999;
+}
+
 /* 列表容器 */
 .bill-list {
     flex: 1;

+ 83 - 36
pages/mine/wallet/index.vue

@@ -29,11 +29,11 @@
                 <view class="balance-container">
                     <view class="balance-main">
                         <text class="balance-label">账户余额 (元)</text>
-                        <text class="balance-num">2575.00</text>
+                        <text class="balance-num">{{ balance }}</text>
                     </view>
                     <view class="balance-pending">
                         <text class="pending-label">待入账 (元)</text>
-                        <text class="pending-num">580.00</text>
+                        <text class="pending-num">{{ pendingBalance }}</text>
                     </view>
                 </view>
             </view>
@@ -88,44 +88,24 @@
 </template>
 
 <script>
+import { getBalanceOnApp, pageBalanceOnApp } from '@/api/fulfiller/log/index.js';
+
+import fulfillerEnum from '@/enums/fulfiller.json';
+
+const bizTypeMap = fulfillerEnum.FlfBalanceBizType;
+const actionTypeMap = fulfillerEnum.FlfActionType;
+
 export default {
     data() {
         return {
+            balance: '0.00',
+            pendingBalance: '0.00',
             currentTab: 0,
-            list: [
-                {
-                    title: '订单服务费用',
-                    desc: '订单 T1002839 完成结算',
-                    time: '2026-02-03 14:30',
-                    amount: '20.00',
-                    type: 'income',
-                    tag: '订单'
-                },
-                {
-                    title: '奖励费用',
-                    desc: '早高峰冲单奖励',
-                    time: '2026-02-03 10:00',
-                    amount: '15.00',
-                    type: 'income',
-                    tag: '奖励'
-                },
-                {
-                    title: '惩罚金额',
-                    desc: '超时送达扣款',
-                    time: '2026-02-02 18:20',
-                    amount: '-10.00',
-                    type: 'expense',
-                    tag: '惩罚'
-                },
-                {
-                    title: '后台转账',
-                    desc: '2026年1月工资发放',
-                    time: '2026-02-01 09:00',
-                    amount: '3500.00',
-                    type: 'income',
-                    tag: '工资'
-                }
-            ]
+            list: [],
+            pageNum: 1,
+            pageSize: 10,
+            total: 0,
+            loading: false
         }
     },
     computed: {
@@ -136,7 +116,74 @@ export default {
             return [];
         }
     },
+    onShow() {
+        this.fetchData();
+        this.fetchList(true);
+    },
+    onReachBottom() {
+        this.fetchList();
+    },
     methods: {
+        async fetchData() {
+            try {
+                const res = await getBalanceOnApp();
+                if (res.code === 200 && res.data) {
+                    this.balance = (res.data.balance / 100).toFixed(2);
+                    this.pendingBalance = (res.data.pendingBalance / 100).toFixed(2);
+                }
+            } catch (error) {
+                console.error('获取余额数据失败', error);
+            }
+        },
+        async fetchList(reset = false) {
+            if (reset) {
+                this.pageNum = 1;
+                this.list = [];
+                this.total = 0;
+            }
+            if (this.loading) return;
+            if (!reset && this.list.length >= this.total && this.total !== 0) return;
+
+            this.loading = true;
+            try {
+                const res = await pageBalanceOnApp({
+                    pageNum: this.pageNum,
+                    pageSize: this.pageSize
+                });
+                if (res.code === 200) {
+                    this.total = res.total || 0;
+                    const rows = res.rows || [];
+                    const mappedRows = rows.map(item => {
+                        // type 枚举:add 增加, reduce 减少
+                        const isAdd = item.type === 'add';
+                        const uiType = isAdd ? 'income' : 'expense';
+                        const title = bizTypeMap[item.bizType] || item.bizType || '其他';
+                        
+                        // 金额处理:分转元
+                        let amountStr = (Math.abs(item.amount) / 100).toFixed(2);
+                        if (!isAdd) {
+                            amountStr = '-' + amountStr;
+                        }
+                        
+                        return {
+                            ...item,
+                            title: title,
+                            desc: item.reason || '',
+                            time: item.createTime || '',
+                            amount: amountStr,
+                            type: uiType, // 'income' or 'expense' for template class
+                            tag: title
+                        };
+                    });
+                    this.list = this.list.concat(mappedRows);
+                    this.pageNum++;
+                }
+            } catch (error) {
+                console.error('获取列表数据失败', error);
+            } finally {
+                this.loading = false;
+            }
+        },
         navBack() {
             uni.navigateBack();
         },

+ 44 - 13
pages/orders/detail-logic.js

@@ -1,7 +1,8 @@
 import { getOrderInfo, getOrderLogs, uploadFile, clockIn, getAnomalyList, submitNursingSummary } from '@/api/fulfiller'
 import { getServiceList, getServiceDetail } from '@/api/service'
 import { getDictDataByType } from '@/api/system/dict/index'
-import { getPetDetail } from '@/api/archieves/pet/index'
+import { getPetDetail, submitPetRemark as apiSubmitPetRemark } from '@/api/archieves/pet/index'
+import { listChangeLog } from '@/api/archieves/changeLog/index'
 
 export default {
     data() {
@@ -410,6 +411,8 @@ export default {
                     ownerName: pet.ownerName || '',
                     ownerPhone: pet.ownerPhone || ''
                 }
+                // 同步加载备注日志
+                this.loadPetChangeLogs(pet.id)
             } else {
                 // 兜底:如果宠物档案未加载成功,使用订单中的基本信息
                 this.currentPetInfo = {
@@ -426,6 +429,23 @@ export default {
             }
             this.showPetModal = true
         },
+        async loadPetChangeLogs(petId) {
+            if (!petId) return
+            try {
+                const res = await listChangeLog({
+                    targetId: petId,
+                    targetType: 'pet'
+                })
+                const logs = res.data || []
+                this.currentPetInfo.petLogs = logs.map(item => ({
+                    date: item.createTime || '',
+                    content: item.content || '',
+                    recorder: item.operatorName || '未知'
+                }))
+            } catch (err) {
+                console.error('获取宠物备注列表失败:', err)
+            }
+        },
         closePetProfile() {
             this.showPetModal = false;
         },
@@ -436,23 +456,34 @@ export default {
         closePetRemarkInput() {
             this.showPetRemarkInput = false;
         },
-        submitPetRemark() {
+        async submitPetRemark() {
             if (!this.petRemarkText.trim()) {
                 uni.showToast({ title: '备注内容不能为空', icon: 'none' });
                 return;
             }
-            const now = new Date();
-            const date = `${now.getFullYear()}/${String(now.getMonth() + 1).padStart(2, '0')}/${String(now.getDate()).padStart(2, '0')}`;
-            if (!this.currentPetInfo.petLogs) {
-                this.currentPetInfo.petLogs = [];
+            if (!this.petId) {
+                uni.showToast({ title: '宠物信息缺失', icon: 'none' });
+                return;
+            }
+
+            uni.showLoading({ title: '提交中...', mask: true });
+            try {
+                await apiSubmitPetRemark({
+                    petId: this.petId,
+                    content: this.petRemarkText
+                });
+                
+                uni.hideLoading();
+                uni.showToast({ title: '备注已添加', icon: 'success' });
+                this.closePetRemarkInput();
+                
+                // 提交成功后,重新加载最新的备注日志列表
+                this.loadPetChangeLogs(this.petId);
+            } catch (err) {
+                uni.hideLoading();
+                console.error('提交宠物备注失败:', err);
+                // 具体的错误提示已由 request.js 处理
             }
-            this.currentPetInfo.petLogs.unshift({
-                date: date,
-                content: this.petRemarkText,
-                recorder: this.orderDetail.fulfillerName || '未知'
-            });
-            this.closePetRemarkInput();
-            uni.showToast({ title: '备注已添加', icon: 'success' });
         },
         goToAnomaly() {
             uni.navigateTo({

+ 70 - 0
pages/recruit/auth.css

@@ -149,4 +149,74 @@ page {
 .footer-btn-area {
     margin-top: 60rpx;
     padding: 0 20rpx;
+}
+
+/* 自定义日期选择器弹窗 */
+.picker-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    visibility: hidden;
+    opacity: 0;
+    transition: all 0.3s;
+}
+
+.picker-mask.show {
+    visibility: visible;
+    opacity: 1;
+}
+
+.picker-content {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    background-color: #fff;
+    border-radius: 20rpx 20rpx 0 0;
+    transform: translateY(100%);
+    transition: all 0.3s;
+}
+
+.picker-mask.show .picker-content {
+    transform: translateY(0);
+}
+
+.picker-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 30rpx;
+    border-bottom: 1px solid #eee;
+    font-size: 32rpx;
+}
+
+.picker-btn-cancel {
+    color: #999;
+}
+
+.picker-title {
+    font-weight: bold;
+    color: #333;
+}
+
+.picker-btn-confirm {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.picker-view {
+    width: 100%;
+    height: 400rpx;
+}
+
+.picker-item {
+    line-height: 50px;
+    /* picker-view-column 默认高度需要配合 */
+    text-align: center;
+    font-size: 32rpx;
+    color: #333;
 }

+ 31 - 6
pages/recruit/auth.vue

@@ -30,12 +30,10 @@
       <!-- 有效日期 -->
       <view class="form-item">
         <text class="label">有效日期</text>
-        <view class="gray-input-box">
-          <picker mode="date" @change="onDateChange" style="width: 100%;">
-             <view class="input-area" :class="{'input-placeholder': !formData.expiryDate}">
-               {{ formData.expiryDate || '选择有效结束期限' }}
-             </view>
-          </picker>
+        <view class="gray-input-box" @click="openPicker">
+          <text class="input-area" :class="{'input-placeholder': !formData.expiryDate}">
+            {{ formData.expiryDate || '选择有效结束期限' }}
+          </text>
           <!-- 箭头SVG -->
            <svg class="arrow-right" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
                 <path d="M340.864 149.312a30.592 30.592 0 0 0 0 42.752L652.736 512 340.864 831.872a30.592 30.592 0 0 0 0 42.752 29.12 29.12 0 0 0 41.728 0L714.24 534.336a32 32 0 0 0 0-45.056L382.592 149.312a29.12 29.12 0 0 0-41.728 0z" fill="#CCCCCC"></path>
@@ -81,6 +79,33 @@
       <button class="next-btn" @click="goToQualifications">下一步,完善资质</button>
     </view>
 
+    <!-- 自定义日期选择器 -->
+    <view class="picker-mask" :class="{show: showPicker}" @click="closePicker">
+        <view class="picker-content" @click.stop>
+            <view class="picker-header">
+                <text class="picker-btn-cancel" @click="closePicker">取消</text>
+                <text class="picker-title">选择有效结束期限</text>
+                <text class="picker-btn-confirm" @click="confirmPicker">确定</text>
+            </view>
+            <picker-view 
+                class="picker-view" 
+                indicator-style="height: 50px;" 
+                :value="pickerValue" 
+                @change="onPickerChange"
+            >
+                <picker-view-column>
+                    <view class="picker-item" v-for="(item,index) in years" :key="index">{{item}}年</view>
+                </picker-view-column>
+                <picker-view-column>
+                    <view class="picker-item" v-for="(item,index) in months" :key="index">{{item}}月</view>
+                </picker-view-column>
+                <picker-view-column>
+                    <view class="picker-item" v-for="(item,index) in days" :key="index">{{item}}日</view>
+                </picker-view-column>
+            </picker-view>
+        </view>
+    </view>
+
   </view>
 </template>
 

+ 40 - 10
pages/recruit/auth_logic.js

@@ -13,11 +13,14 @@ export default {
             idCardBack: '',       // 身份证反面本地预览路径
             idCardFrontOssId: '', // 身份证正面 OSS ID
             idCardBackOssId: '',  // 身份证反面 OSS ID
-            showDatePicker: false,
+            showPicker: false,
             pickerValue: [0, 0, 0], // YYYY-MM-DD
             years: [],
             months: [],
             days: [],
+            tempYear: 0,
+            tempMonth: 0,
+            tempDay: 0,
             serviceType: [] // 接收上一页的服务类型
         }
     },
@@ -34,11 +37,11 @@ export default {
         this.restoreAuthData();
     },
     methods: {
-        // --- 日期选择器逻辑 (简化版, 仅示意) ---
+        // --- 日期选择器逻辑 ---
         initDateData() {
             const date = new Date();
             const year = date.getFullYear();
-            for (let i = year; i <= year + 20; i++) {
+            for (let i = year; i <= year + 50; i++) {
                 this.years.push(i);
             }
             for (let i = 1; i <= 12; i++) {
@@ -48,14 +51,41 @@ export default {
                 this.days.push(i);
             }
         },
-        openDatePicker() {
-            // this.showDatePicker = true; 
-            // 简单起见,这里可以用 uni.chooseImage 逻辑,但日期通常用 picker
-            // 为了完全还原UI的自定义picker,这里先用原生 picker 简化,或者复用 form 的逻辑
-            // 鉴于图1是普通的列表选择样式,这里暂时使用普通 picker 或者 input禁用+点击事件
+        openPicker() {
+            const date = new Date();
+            const dateStr = this.formData.expiryDate || `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
+            const [y, m, d] = dateStr.split('-').map(Number);
+
+            let yIndex = this.years.indexOf(y);
+            let mIndex = this.months.indexOf(m);
+            let dIndex = this.days.indexOf(d);
+
+            this.pickerValue = [
+                yIndex > -1 ? yIndex : 0,
+                mIndex > -1 ? mIndex : 0,
+                dIndex > -1 ? dIndex : 0
+            ];
+
+            this.tempYear = this.years[this.pickerValue[0]];
+            this.tempMonth = this.months[this.pickerValue[1]];
+            this.tempDay = this.days[this.pickerValue[2]];
+
+            this.showPicker = true;
+        },
+        closePicker() {
+            this.showPicker = false;
+        },
+        onPickerChange(e) {
+            const val = e.detail.value;
+            this.tempYear = this.years[val[0]];
+            this.tempMonth = this.months[val[1]];
+            this.tempDay = this.days[val[2]];
         },
-        onDateChange(e) {
-            this.formData.expiryDate = e.detail.value;
+        confirmPicker() {
+            const mStr = this.tempMonth < 10 ? '0' + this.tempMonth : this.tempMonth;
+            const dStr = this.tempDay < 10 ? '0' + this.tempDay : this.tempDay;
+            this.formData.expiryDate = `${this.tempYear}-${mStr}-${dStr}`;
+            this.closePicker();
         },
 
         // --- 数据持久化(防止返回上一级丢失) ---

BIN
unpackage/cache/apk/__UNI__76F5C47_cm.apk


+ 1 - 1
unpackage/cache/apk/apkurl

@@ -1 +1 @@
-https://app.liuyingyong.cn/build/download/a6788ca0-1ddf-11f1-a284-c712c017342c
+https://app.liuyingyong.cn/build/download/40be4780-21a1-11f1-92e9-1f84edcba3f1

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/apk/cmManifestCache.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
unpackage/cache/wgt/__UNI__76F5C47/app-config-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/app-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/app.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/manifest.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/home/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/mine/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/orders/detail.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/orders/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/uni-app-view.umd.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
unpackage/dist/build/app-plus/app-config-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/app-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/app.css


+ 34 - 1
unpackage/dist/build/app-plus/manifest.json

@@ -17,6 +17,7 @@
     "url": ""
   },
   "permissions": {
+    "Camera": {},
     "UniNView": {
       "description": "UniNView原生渲染"
     }
@@ -41,6 +42,38 @@
     "nvueStyleCompiler": "uni-app",
     "compilerVersion": 3,
     "distribute": {
+      "icons": {
+        "android": {
+          "hdpi": "unpackage/res/icons/72x72.png",
+          "xhdpi": "unpackage/res/icons/96x96.png",
+          "xxhdpi": "unpackage/res/icons/144x144.png",
+          "xxxhdpi": "unpackage/res/icons/192x192.png"
+        },
+        "ios": {
+          "appstore": "unpackage/res/icons/1024x1024.png",
+          "ipad": {
+            "app": "unpackage/res/icons/76x76.png",
+            "app@2x": "unpackage/res/icons/152x152.png",
+            "notification": "unpackage/res/icons/20x20.png",
+            "notification@2x": "unpackage/res/icons/40x40.png",
+            "proapp@2x": "unpackage/res/icons/167x167.png",
+            "settings": "unpackage/res/icons/29x29.png",
+            "settings@2x": "unpackage/res/icons/58x58.png",
+            "spotlight": "unpackage/res/icons/40x40.png",
+            "spotlight@2x": "unpackage/res/icons/80x80.png"
+          },
+          "iphone": {
+            "app@2x": "unpackage/res/icons/120x120.png",
+            "app@3x": "unpackage/res/icons/180x180.png",
+            "notification@2x": "unpackage/res/icons/40x40.png",
+            "notification@3x": "unpackage/res/icons/60x60.png",
+            "settings@2x": "unpackage/res/icons/58x58.png",
+            "settings@3x": "unpackage/res/icons/87x87.png",
+            "spotlight@2x": "unpackage/res/icons/80x80.png",
+            "spotlight@3x": "unpackage/res/icons/120x120.png"
+          }
+        }
+      },
       "google": {
         "permissions": [
           "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
@@ -89,7 +122,7 @@
     "uni-app": {
       "control": "uni-v3",
       "vueVersion": "3",
-      "compilerVersion": "4.87",
+      "compilerVersion": "5.03",
       "nvueCompiler": "uni-app",
       "renderer": "auto",
       "nvue": {

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/pages/home/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/pages/mine/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/pages/orders/detail.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/pages/orders/index.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/build/app-plus/uni-app-view.umd.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
unpackage/dist/dev/app-plus/app-config-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 732 - 341
unpackage/dist/dev/app-plus/app-service.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/dev/app-plus/app.css


+ 2 - 1
unpackage/dist/dev/app-plus/manifest.json

@@ -17,6 +17,7 @@
     "url": ""
   },
   "permissions": {
+    "Camera": {},
     "UniNView": {
       "description": "UniNView原生渲染"
     }
@@ -121,7 +122,7 @@
     "uni-app": {
       "control": "uni-v3",
       "vueVersion": "3",
-      "compilerVersion": "4.87",
+      "compilerVersion": "5.03",
       "nvueCompiler": "uni-app",
       "renderer": "auto",
       "nvue": {

+ 7 - 7
unpackage/dist/dev/app-plus/pages/mine/order-stats.css

@@ -1,7 +1,7 @@
 
 body { background-color: #F7F8FA;
 }
-.container { min-height: 100vh; background-color: #F7F8FA; padding: 0.625rem 0 0;
+.container { min-height: 100vh; background-color: #F7F8FA; padding: 0.625rem 0 0; display: flex; flex-direction: column;
 }
 
 /* ===== 统计banner:圆角浮动卡,左右30rpx边距 ===== */
@@ -13,6 +13,7 @@ body { background-color: #F7F8FA;
     margin: 0 0.9375rem 0.625rem;
     border-radius: 0.625rem;
     box-shadow: 0 0.1875rem 0.625rem rgba(255, 87, 34, 0.25);
+    flex-shrink: 0;
 }
 .banner-item { display: flex; flex-direction: column; align-items: center;
 }
@@ -30,6 +31,7 @@ body { background-color: #F7F8FA;
     padding: 0 0.9375rem;
     border-bottom: 0.03125rem solid #f0f0f0;
     margin-bottom: 0;
+    flex-shrink: 0;
 }
 .tab-item {
     padding: 0.625rem 0.75rem;
@@ -54,15 +56,13 @@ body { background-color: #F7F8FA;
 }
 
 /* ===== 订单列表:scroll-view 全宽,每张card用margin左右30rpx ===== */
-.order-scroll { width: 100%;
+.order-scroll { flex: 1; height: 0; width: 100%;
 }
-
-/* 关键:order-card 用 margin: 0 30rpx 实现与banner对齐 */
 .order-card {
     background-color: #fff;
     border-radius: 0.5rem;
     padding: 0.75rem;
-    margin: 0 0.9375rem 0.5rem;   /* ← 与banner的 margin: 0 30rpx 完全一致 */
+    margin: 0 0.9375rem 0.5rem;
     box-sizing: border-box;
 }
 
@@ -75,8 +75,6 @@ body { background-color: #F7F8FA;
 }
 .type-badge { display: flex; align-items: center;
 }
-
-/* 订单类型图标:与my-orders列表一致,直接使用带色彩的SVG图标 */
 .type-icon {
     width: 1.375rem;
     height: 1.375rem;
@@ -178,3 +176,5 @@ body { background-color: #F7F8FA;
 }
 .empty-text { font-size: 0.875rem; color: #ccc;
 }
+.loading-more { text-align: center; padding: 0.625rem; font-size: 0.75rem; color: #999;
+}

+ 33 - 3
unpackage/dist/dev/app-plus/pages/mine/points/detail.css

@@ -50,14 +50,22 @@
     flex-direction: column;
 }
 
+/* 筛选区域 */
+.filter-area {
+    background-color: #fff;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 0.9375rem;
+    margin-bottom: 0.625rem;
+}
+
 /* Tabs */
 .tabs-row {
-    background-color: #fff;
     display: flex;
-    justify-content: space-around;
     padding-top: 0.625rem;
     padding-bottom: 0.0625rem;
-    margin-bottom: 0.625rem;
+    gap: 1.25rem;
 }
 .tab-item {
     padding-bottom: 0.5rem;
@@ -82,6 +90,28 @@
     bottom: 0;
 }
 
+/* 日期选择器 */
+.date-picker-wrap {
+    display: flex;
+    align-items: center;
+}
+.date-picker {
+    background-color: #F5F7FA;
+    padding: 0.25rem 0.625rem;
+    border-radius: 0.9375rem;
+    display: flex;
+    align-items: center;
+}
+.date-text {
+    font-size: 0.8125rem;
+    color: #333;
+    margin-right: 0.25rem;
+}
+.arrow-down {
+    font-size: 0.75rem;
+    color: #999;
+}
+
 /* 列表容器 */
 .bill-list {
     flex: 1;

+ 28 - 1
unpackage/dist/dev/app-plus/pages/mine/rewards-all.css

@@ -3,10 +3,37 @@ body { background-color: #F7F8FA;
 }
 .container { min-height: 100vh; background-color: #F7F8FA;
 }
-.tab-bar {
+
+/* 筛选头部:标签 + 日期 */
+.filter-header {
     display: flex;
+    align-items: center;
+    justify-content: space-between;
     background-color: #fff;
     padding: 0 0.9375rem;
+    border-bottom: 0.03125rem solid #f5f5f5;
+}
+.tab-bar {
+    display: flex;
+}
+.date-filter {
+    padding: 0.25rem 0;
+}
+.picker-trigger {
+    background-color: #f7f8fa;
+    padding: 0.25rem 0.625rem;
+    border-radius: 0.9375rem;
+    display: flex;
+    align-items: center;
+}
+.picker-trigger uni-text {
+    font-size: 0.75rem;
+    color: #333;
+}
+.arrow-icon {
+    font-size: 0.5625rem;
+    color: #999;
+    margin-left: 0.25rem;
 }
 .tab-item {
     padding: 0.5625rem 0.5rem 0;

+ 33 - 3
unpackage/dist/dev/app-plus/pages/mine/wallet/bill.css

@@ -50,14 +50,22 @@
     flex-direction: column;
 }
 
+/* 筛选区域 */
+.filter-area {
+    background-color: #fff;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 0.9375rem;
+    margin-bottom: 0.625rem;
+}
+
 /* Tabs */
 .tabs-row {
-    background-color: #fff;
     display: flex;
-    justify-content: space-around; /* Match Figure 1 spacing */
     padding-top: 0.625rem;
     padding-bottom: 0.0625rem;
-    margin-bottom: 0.625rem;
+    gap: 1.25rem;
 }
 .tab-item {
     padding-bottom: 0.5rem;
@@ -82,6 +90,28 @@
     bottom: 0;
 }
 
+/* 日期选择器 */
+.date-picker-wrap {
+    display: flex;
+    align-items: center;
+}
+.date-picker {
+    background-color: #F5F7FA;
+    padding: 0.25rem 0.625rem;
+    border-radius: 0.9375rem;
+    display: flex;
+    align-items: center;
+}
+.date-text {
+    font-size: 0.8125rem;
+    color: #333;
+    margin-right: 0.25rem;
+}
+.arrow-down {
+    font-size: 0.75rem;
+    color: #999;
+}
+
 /* 列表容器 */
 .bill-list {
     flex: 1;

+ 60 - 0
unpackage/dist/dev/app-plus/pages/recruit/auth.css

@@ -130,3 +130,63 @@ body {
     margin-top: 1.875rem;
     padding: 0 0.625rem;
 }
+/* 自定义日期选择器弹窗 */
+.picker-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    visibility: hidden;
+    opacity: 0;
+    transition: all 0.3s;
+}
+.picker-mask.show {
+    visibility: visible;
+    opacity: 1;
+}
+.picker-content {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    background-color: #fff;
+    border-radius: 0.625rem 0.625rem 0 0;
+    transform: translateY(100%);
+    transition: all 0.3s;
+}
+.picker-mask.show .picker-content {
+    transform: translateY(0);
+}
+.picker-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0.9375rem;
+    border-bottom: 1px solid #eee;
+    font-size: 1rem;
+}
+.picker-btn-cancel {
+    color: #999;
+}
+.picker-title {
+    font-weight: bold;
+    color: #333;
+}
+.picker-btn-confirm {
+    color: #FF5722;
+    font-weight: bold;
+}
+.picker-view {
+    width: 100%;
+    height: 12.5rem;
+}
+.picker-item {
+    line-height: 50px;
+    /* picker-view-column 默认高度需要配合 */
+    text-align: center;
+    font-size: 1rem;
+    color: #333;
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/dev/app-plus/uni-app-view.umd.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
unpackage/dist/dev/cache/.app-plus/tsc/app-android/.tsbuildInfo


BIN
unpackage/release/apk/__UNI__76F5C47__20260312144943.apk → unpackage/release/apk/__UNI__76F5C47__20260316202839.apk


BIN
unpackage/release/apk/__UNI__76F5C47__20260317093308.apk


+ 5 - 4
utils/config.js

@@ -5,16 +5,17 @@
 
 // API 基础地址(开发环境)
 // export const BASE_URL = 'http://192.168.1.118:8080'
-export const BASE_URL = 'http://192.168.0.104:8080'
+// export const BASE_URL = 'http://8.136.194.143/api'
+export const BASE_URL = 'http://192.168.0.105:8080'
 
 // 履约者App客户端ID(需要在 sys_client 表中配置)
-export const CLIENT_ID = '3'
-
+export const CLIENT_ID = 'fe63fea7be31b0200b496d08bc6b517d'
+ 
 // 履约者App平台码
 export const PLATFORM_CODE = 'FlfAppPlatformCodeX9kR7mT3wQ5vZ8nB1jY6pD4sL0hC2gA'
 
 // 履约者平台ID(对应 Platform.FULFILLER.id = 2)
-export const PLATFORM_ID = 2
+export const PLATFORM_ID = 3
 
 // 租户ID(默认)
 export const TENANT_ID = '000000'

+ 9 - 9
utils/request.js

@@ -65,9 +65,9 @@ export default function request(options = {}) {
         // }
 
         if (statusCode !== 200) {
-          const msg = msg || `请求失败(${statusCode})`
-          uni.showToast({ title: msg, icon: 'none' })
-          return reject(new Error(msg))
+          const errorMsg = msg || `请求失败(${statusCode})`
+          uni.showToast({ title: errorMsg, icon: 'none' })
+          return reject(new Error(errorMsg))
         }
 
         if (code === 401) {
@@ -80,12 +80,12 @@ export default function request(options = {}) {
           return reject(new Error('未授权'))
         }
 
-        // // 业务状态码
-        // if (result.code !== undefined && result.code !== 200) {
-        //   const msg = result.msg || '操作失败'
-        //   uni.showToast({ title: msg, icon: 'none' })
-        //   return reject(new Error(msg))
-        // }
+        // 业务状态码
+        if (code !== undefined && code !== 200) {
+          const errorMsg = msg || '操作失败'
+          uni.showToast({ title: errorMsg, icon: 'none' })
+          return reject(new Error(errorMsg))
+        }
 
         resolve(res.data)
       },

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff