Huanyi 3 weeks ago
parent
commit
b139d8f87c
49 changed files with 801 additions and 478 deletions
  1. 13 3
      .idea/workspace.xml
  2. 20 0
      api/fulfiller.js
  3. 100 0
      api/fulfiller/log/index.js
  4. 30 0
      api/order/subOrder/index.js
  5. 0 20
      api/service.js
  6. 15 0
      api/service/list/index.js
  7. 31 0
      enums/fulfiller.json
  8. 5 5
      pages/home/index.vue
  9. 20 10
      pages/home/logic.js
  10. 52 22
      pages/home/work-status.vue
  11. 2 2
      pages/mine/index.vue
  12. 111 102
      pages/mine/level/index.vue
  13. 20 2
      pages/mine/logic.js
  14. 18 6
      pages/mine/order-stats.vue
  15. 4 3
      pages/orders/anomaly.vue
  16. 32 25
      pages/orders/detail-logic.js
  17. 2 10
      pages/orders/detail.vue
  18. 5 4
      pages/orders/logic.js
  19. 30 3
      pages/recruit/auth_logic.js
  20. 5 2
      pages/recruit/logic.js
  21. BIN
      unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-hdpi.png
  22. BIN
      unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xhdpi.png
  23. BIN
      unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xxhdpi.png
  24. BIN
      unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xxxhdpi.png
  25. 1 1
      unpackage/dist/dev/app-plus/app-config-service.js
  26. 246 204
      unpackage/dist/dev/app-plus/app-service.js
  27. 1 1
      unpackage/dist/dev/app-plus/manifest.json
  28. 3 4
      unpackage/dist/dev/app-plus/pages/home/work-status.css
  29. 29 44
      unpackage/dist/dev/app-plus/pages/mine/level/index.css
  30. 4 3
      unpackage/dist/dev/app-plus/pages/orders/anomaly.css
  31. 0 0
      unpackage/dist/dev/cache/.app-plus/tsc/app-android/.tsbuildInfo
  32. BIN
      unpackage/res/icons/1024x1024.png
  33. BIN
      unpackage/res/icons/120x120.png
  34. BIN
      unpackage/res/icons/144x144.png
  35. BIN
      unpackage/res/icons/152x152.png
  36. BIN
      unpackage/res/icons/167x167.png
  37. BIN
      unpackage/res/icons/180x180.png
  38. BIN
      unpackage/res/icons/192x192.png
  39. BIN
      unpackage/res/icons/20x20.png
  40. BIN
      unpackage/res/icons/29x29.png
  41. BIN
      unpackage/res/icons/40x40.png
  42. BIN
      unpackage/res/icons/58x58.png
  43. BIN
      unpackage/res/icons/60x60.png
  44. BIN
      unpackage/res/icons/72x72.png
  45. BIN
      unpackage/res/icons/76x76.png
  46. BIN
      unpackage/res/icons/80x80.png
  47. BIN
      unpackage/res/icons/87x87.png
  48. BIN
      unpackage/res/icons/96x96.png
  49. 2 2
      utils/config.js

+ 13 - 3
.idea/workspace.xml

@@ -4,7 +4,7 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="e5f5f697-2bd4-4205-922a-fb106cdbbdf5" name="Changes" comment="整改基本完成" />
+    <list default="true" id="e5f5f697-2bd4-4205-922a-fb106cdbbdf5" name="Changes" comment="改造登录;完善功能" />
     <list id="6ae23f6a-53fe-4817-a1d7-106bcf184c18" name="New changelist" comment="不想提交的文件" />
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -85,6 +85,7 @@
       <workItem from="1773252784481" duration="88000" />
       <workItem from="1773309863004" duration="21000" />
       <workItem from="1773334157405" duration="23000" />
+      <workItem from="1773772227895" duration="40000" />
     </task>
     <task id="LOCAL-00001" summary="1.完成app端履约者入驻相关功能开发&#10;2.完成app端履约者登录功能开发&#10;3.完成履约者个人中心功能开发">
       <option name="closed" value="true" />
@@ -150,7 +151,15 @@
       <option name="project" value="LOCAL" />
       <updated>1773334173000</updated>
     </task>
-    <option name="localTasksCounter" value="9" />
+    <task id="LOCAL-00009" summary="改造登录;完善功能">
+      <option name="closed" value="true" />
+      <created>1773772253104</created>
+      <option name="number" value="00009" />
+      <option name="presentableId" value="LOCAL-00009" />
+      <option name="project" value="LOCAL" />
+      <updated>1773772253104</updated>
+    </task>
+    <option name="localTasksCounter" value="10" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -167,6 +176,7 @@
     <MESSAGE value="1.完成app样式调整" />
     <MESSAGE value="接单成功,异常上报成功,UI初步调整,订单详情优化" />
     <MESSAGE value="整改基本完成" />
-    <option name="LAST_COMMIT_MESSAGE" value="整改基本完成" />
+    <MESSAGE value="改造登录;完善功能" />
+    <option name="LAST_COMMIT_MESSAGE" value="改造登录;完善功能" />
   </component>
 </project>

+ 20 - 0
api/fulfiller.js

@@ -385,3 +385,23 @@ export function submitNursingSummary(data) {
     data
   })
 }
+
+/**
+ * 获取所有等级配置列表
+ */
+export function listAllLevelConfigs() {
+  return request({
+    url: '/fulfiller/levelConfig/listAll',
+    method: 'GET'
+  })
+}
+
+/**
+ * 获取所有等级权益列表
+ */
+export function listAllLevelRights() {
+  return request({
+    url: '/fulfiller/levelRights/listAll',
+    method: 'GET'
+  })
+}

+ 100 - 0
api/fulfiller/log/index.js

@@ -0,0 +1,100 @@
+import request from '@/utils/request';
+
+/**
+ * 获取APP端余额及变动记录
+ * @returns {Promise}
+ */
+export function getBalanceOnApp() {
+    return request({
+        url: '/fulfiller/log/balanceOnApp',
+        method: 'GET'
+    });
+}
+
+/**
+ * 分页获取APP端变动记录列表
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function pageBalanceOnApp(data) {
+    return request({
+        url: '/fulfiller/log/pageBalanceOnApp',
+        method: 'GET',
+        data
+    });
+}
+
+/**
+ * 根据年月获取APP端变动记录列表
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function listBalanceOnApp(data) {
+    return request({
+        url: '/fulfiller/log/listBalanceOnApp',
+        method: 'GET',
+        data
+    });
+}
+
+/**
+ * 获取APP端当前积分
+ * @returns {Promise}
+ */
+export function pointsOnApp() {
+    return request({
+        url: '/fulfiller/log/pointsOnApp',
+        method: 'GET'
+    });
+}
+
+/**
+ * 分页获取APP端积分变动记录列表
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function pagePointsOnApp(data) {
+    return request({
+        url: '/fulfiller/log/pagePointsOnApp',
+        method: 'GET',
+        data
+    });
+}
+
+/**
+ * 根据年月获取APP端积分变动记录列表
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function listPointsOnApp(data) {
+    return request({
+        url: '/fulfiller/log/listPointsOnApp',
+        method: 'GET',
+        data
+    });
+}
+/**
+ * 获取APP端奖惩统计值
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function countOnAppReward(data) {
+    return request({
+        url: '/fulfiller/log/countOnAppReward',
+        method: 'GET',
+        data
+    });
+}
+
+/**
+ * 获取APP端奖惩列表数据
+ * @param {Object} data 
+ * @returns {Promise}
+ */
+export function listOnAppReward(data) {
+    return request({
+        url: '/fulfiller/log/listOnAppReward',
+        method: 'GET',
+        data
+    });
+}

+ 30 - 0
api/order/subOrder/index.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request';
+
+/**
+ * 取消订单
+ * @param {Object} data - 请求参数
+ * @param {number} data.orderId - 订单ID
+ * @author antigravity
+ */
+export function cancelOrderApi(data) {
+    return request({
+        url: '/order/subOrder/cancel',
+        method: 'PUT',
+        data
+    });
+}
+
+/**
+ * 拒绝接单
+ * @param {Object} data - 请求参数
+ * @param {number} data.orderId - 订单ID
+ * @param {string} data.rejectReason - 拒绝理由
+ * @author antigravity
+ */
+export function rejectOrderApi(data) {
+    return request({
+        url: '/order/subOrder/reject',
+        method: 'PUT',
+        data
+    });
+}

+ 0 - 20
api/service.js

@@ -4,23 +4,3 @@
  */
 import request from '@/utils/request'
 
-/**
- * 获取任务大厅服务类型列表
- */
-export function getServiceList() {
-  return request({
-    url: '/service/list/listOnTaskHall',
-    method: 'GET'
-  })
-}
-
-/**
- * 获取服务类型详情(含打卡备注)
- * @param {number} id 服务类型ID
- */
-export function getServiceDetail(id) {
-  return request({
-    url: `/service/list/${id}`,
-    method: 'GET'
-  })
-}

+ 15 - 0
api/service/list/index.js

@@ -0,0 +1,15 @@
+/**
+ * 服务列表相关的 API
+ */
+import request from '@/utils/request'
+
+/**
+ * 获取所有服务类型列表
+ * @returns {Promise} 响应数据
+ */
+export function listAllService() {
+    return request({
+        url: '/service/list/listAll',
+        method: 'GET'
+    })
+}

+ 31 - 0
enums/fulfiller.json

@@ -0,0 +1,31 @@
+{
+  "FlfBalanceBizType": {
+    "admin_reward": "后台奖励",
+    "admin_punish": "后台惩罚",
+    "admin_adjust": "后台调整",
+    "order_reward": "订单奖励",
+    "order_punish": "订单惩罚",
+    "order_finish": "订单完成",
+    "salary": "工资发放",
+    "withdraw": "提现"
+  },
+  "FlfPointsBizType": {
+    "admin_reward": "后台奖励",
+    "admin_punish": "后台惩罚",
+    "admin_adjust": "后台调整",
+    "order_reward": "订单奖励",
+    "order_punish": "订单惩罚",
+    "order_finish": "订单完成"
+  },
+  "FlfRewardBizType": {
+    "admin_reward": "后台奖励",
+    "admin_punish": "后台惩罚",
+    "order_reward": "订单奖励",
+    "order_punish": "订单惩罚",
+    "order_finish": "订单完成"
+  },
+  "FlfActionType": {
+    "add": "收入",
+    "reduce": "支出"
+  }
+}

+ 5 - 5
pages/home/index.vue

@@ -18,13 +18,13 @@
                 <view class="info-content">
                     <view class="top-row">
                         <text class="name">{{ profile?.name || '未登录' }}</text>
-                        <view class="status-pill" :class="{ 'resting': workStatus === 'resting' }"
+                        <view class="status-pill" :class="{ 'resting': workStatus !== 'busy' }"
                             @click="goToWorkStatus">
-                            <view class="status-dot-bg">
-                                <text class="check-mark" v-if="workStatus === 'working'">✔</text>
+                            <view class="status-dot-bg" :class="{ 'busy': workStatus === 'busy', 'disabled': workStatus === 'disabled' }">
+                                <text class="check-mark" v-if="workStatus === 'busy'">✔</text>
                                 <text class="check-mark" v-else style="font-size: 16rpx; line-height: 20rpx;">✕</text>
                             </view>
-                            <text class="status-text">{{ workStatus === 'working' ? '接单中' : '正在休息' }}</text>
+                            <text class="status-text">{{ workStatus === 'busy' ? '接单中' : (workStatus === 'resting' ? '正在休息' : '已禁用') }}</text>
                             <text class="arrow-down">▼</text>
                         </view>
                     </view>
@@ -126,7 +126,7 @@
         <view class="task-list-container">
             <!-- 任务列表 -->
             <view class="task-list">
-                <view class="task-card" v-for="(item, index) in taskList" :key="index" @click="goToDetail(item)">
+                <view class="task-card" v-for="item in taskList" :key="item.id" @click="goToDetail(item)">
                     <view class="card-header">
                         <view class="type-badge">
                             <image class="type-icon" :src="item.typeIcon"></image>

+ 20 - 10
pages/home/logic.js

@@ -1,6 +1,7 @@
 import { getMyProfile, getPendingOrders, acceptOrder, getOrderCount } from '@/api/fulfiller'
-import { getServiceList } from '@/api/service'
-import { rejectOrderApi } from '@/api/order/subOrder/index'
+import { listAllService } from '@/api/service/list/index'
+
+import { rejectOrderApi } from '@/api/order/subOrder/index.js'
 import { isLoggedIn } from '@/utils/auth'
 import customTabbar from '@/components/custom-tabbar/index.vue'
 
@@ -27,7 +28,7 @@ export default {
                 distance: '全部',
                 amount: '全部'
             },
-            workStatus: 'working', // working | resting
+            workStatus: 'resting', // resting | busy | disabled
             showConfirmModal: false,
             showPetModal: false,
             currentPetInfo: {},
@@ -62,8 +63,11 @@ export default {
         uni.hideTabBar()
         this.checkWorkStatus();
         if (isLoggedIn()) {
+            // 每次进入页面强制刷新所有展示数据
             this.loadProfile()
             this.loadOrderStats()
+            this.loadTaskList()
+            this.loadServiceList() // 确保服务配置也是最新的
         }
     },
     async onPullDownRefresh() {
@@ -95,7 +99,13 @@ export default {
             this.profileLoading = true
             try {
                 const res = await getMyProfile()
-                this.profile = res.data || null
+                const data = res.data || null
+                this.profile = data
+                // 以服务器返回的状态为准进行更新
+                if (data && data.status) {
+                    this.workStatus = data.status;
+                    uni.setStorageSync('workStatus', data.status);
+                }
             } catch (err) {
                 console.error('获取个人信息失败:', err)
             } finally {
@@ -104,7 +114,7 @@ export default {
         },
         async loadServiceList() {
             try {
-                const res = await getServiceList()
+                const res = await listAllService()
                 this.serviceList = res.data || []
             } catch (err) {
                 console.error('获取服务类型失败:', err)
@@ -123,9 +133,9 @@ export default {
             if (status) {
                 this.workStatus = status;
             } else {
-                // Default to working if not set
-                this.workStatus = 'working';
-                uni.setStorageSync('workStatus', 'working');
+                // 默认状态为休息
+                this.workStatus = 'resting';
+                uni.setStorageSync('workStatus', 'resting');
             }
         },
         toggleFilter() {
@@ -141,8 +151,8 @@ export default {
             this.showConfirmModal = true;
         },
         confirmStartWork() {
-            this.workStatus = 'working';
-            uni.setStorageSync('workStatus', 'working');
+            this.workStatus = 'busy';
+            uni.setStorageSync('workStatus', 'busy');
             this.loadTaskList();
             this.showConfirmModal = false;
             uni.showToast({ title: '已开始接单', icon: 'success' });

+ 52 - 22
pages/home/work-status.vue

@@ -4,29 +4,29 @@
         <view class="signboard-container">
             <view class="rope"></view>
             <view class="nail"></view>
-            <view class="board" :class="{ 'resting': status === 'resting' }">
+            <view class="board" :class="{ 'resting': status !== 'busy' }">
                 <view class="screw top-left"></view>
                 <view class="screw top-right"></view>
                 <view class="screw bottom-left"></view>
                 <view class="screw bottom-right"></view>
                 <view class="board-inner">
-                    <text class="status-text">{{ status === 'working' ? '接单中' : '休息中' }}</text>
+                    <text class="status-text">{{ status === 'busy' ? '接单中' : '休息中' }}</text>
                 </view>
             </view>
         </view>
 
         <!-- 状态描述 -->
         <view class="status-desc">
-            <text>{{ status === 'working' ? '当前处于工作接单中,正常接收新订单' : '当前处于休息状态,暂停接收新订单' }}</text>
+            <text>{{ status === 'busy' ? '当前处于工作接单中,正常接收新订单' : '当前处于休息状态,暂停接收新订单' }}</text>
         </view>
 
         <!-- 操作按钮 -->
         <view class="action-area">
-            <button class="action-btn" :class="{ 'stop': status === 'working', 'stopped': status === 'resting' }" @click="toggleStatus">
-                {{ status === 'working' ? '停止接单' : '已停止接单' }}
+            <button class="action-btn" :class="{ 'stop': status === 'busy', 'start': status !== 'busy' }" @click="toggleStatus">
+                {{ status === 'busy' ? '停止接单' : '开始接单' }}
             </button>
             <view class="tips">
-                <text v-if="status === 'working'">当您希望长时间不再接收订单时,请点击上方按钮停止接单,开启后需手动恢复。</text>
+                <text v-if="status === 'busy'">当您希望长时间不再接收订单时,请点击上方按钮停止接单,开启后需手动恢复。</text>
                 <text v-else>点击上方按钮恢复接单,开始接收新的任务推送。</text>
             </view>
         </view>
@@ -34,30 +34,61 @@
 </template>
 
 <script>
+import { updateStatus, getMyProfile } from '@/api/fulfiller'
+
 export default {
     data() {
         return {
-            status: 'working' // working | resting
+            status: 'resting', // resting | busy | disabled
+            loading: false
         }
     },
     onShow() {
-        // 从本地存储获取状态
+        // 优先从本地缓存读取,保证视觉即时性
         const savedStatus = uni.getStorageSync('workStatus');
         if (savedStatus) {
             this.status = savedStatus;
         }
+        // 同时拉取最新 profile 确保同步
+        this.fetchLatestProfile();
     },
     methods: {
-        toggleStatus() {
-            if (this.status === 'working') {
-                // 切换到休息
-                this.status = 'resting';
-                uni.setStorageSync('workStatus', 'resting');
-                // 图3显示依然有按钮只是置灰,或者变为"已停止接单"
-            } else {
-                // 切换回接单
-                this.status = 'working';
-                uni.setStorageSync('workStatus', 'working');
+        async fetchLatestProfile() {
+            try {
+                const res = await getMyProfile();
+                if (res.data && res.data.status) {
+                    this.status = res.data.status;
+                    uni.setStorageSync('workStatus', this.status);
+                }
+            } catch (err) {
+                console.error('获取状态失败:', err);
+            }
+        },
+        async toggleStatus() {
+            if (this.loading) return;
+            
+            // 确定目标状态
+            const targetStatus = this.status === 'busy' ? 'resting' : 'busy';
+            const actionText = targetStatus === 'busy' ? '恢复接单' : '停止接单';
+            
+            try {
+                uni.showLoading({ title: '处理中...', mask: true });
+                this.loading = true;
+                
+                // 向后端发送请求
+                await updateStatus(targetStatus);
+                
+                // 成功后重新获取用户信息以更新本地状态
+                await this.fetchLatestProfile();
+                
+                uni.hideLoading();
+                uni.showToast({ title: actionText + '成功', icon: 'success' });
+            } catch (err) {
+                uni.hideLoading();
+                console.error('切换状态失败:', err);
+                uni.showToast({ title: '操作失败,请重试', icon: 'none' });
+            } finally {
+                this.loading = false;
             }
         }
     }
@@ -195,10 +226,9 @@ page {
     box-shadow: 0 10rpx 20rpx rgba(255, 87, 34, 0.3);
 }
 
-.action-btn.stopped {
-    background-color: #E0E0E0;
-    color: #999;
-    box-shadow: none;
+.action-btn.start {
+    background: linear-gradient(90deg, #4CAF50 0%, #2E7D32 100%);
+    box-shadow: 0 10rpx 20rpx rgba(76, 175, 80, 0.3);
 }
 
 .tips {

+ 2 - 2
pages/mine/index.vue

@@ -40,8 +40,8 @@
                 <view class="vip-left">
                     <image class="vip-icon" src="/static/icons/crown.svg"></image>
                     <view class="vip-text">
-                        <text class="vip-title">{{ profile?.levelName || '普通履约者' }}</text>
-                        <text class="vip-desc">{{ profile?.levelDesc || '完成更多订单即可升级' }}</text>
+                        <text class="vip-title">{{ displayLevelName }}</text>
+                        <text class="vip-desc">完成更多订单即可升级</text>
                     </view>
                 </view>
                 <view class="vip-btn" @click="navToLevel">

+ 111 - 102
pages/mine/level/index.vue

@@ -10,23 +10,28 @@
         </view>
         <view class="header-placeholder"></view>
 
-        <!-- 等级 Switcher -->
-        <view class="swiper-container">
+        <!-- 等级 Swiper -->
+        <view class="swiper-container" v-if="!pageLoading">
             <swiper 
                 class="level-swiper" 
                 previous-margin="80rpx" 
                 next-margin="80rpx" 
                 :current="currentIndex"
                 @change="swiperChange">
-                <swiper-item v-for="(level, index) in levels" :key="index" @click="changeLevel(index)">
-                    <view class="level-card" :class="'level-card-' + (index + 1)" :style="{transform: currentIndex === index ? 'scale(1)' : 'scale(0.9)'}">
+                <swiper-item v-for="(level, index) in processedLevels" :key="index" @click="changeLevel(index)">
+                    <view class="level-card" :style="{ 
+                        transform: currentIndex === index ? 'scale(1)' : 'scale(0.9)',
+                        backgroundImage: 'url(' + level.backgroundUrl + ')',
+                        backgroundSize: 'cover',
+                        backgroundPosition: 'center'
+                    }">
                         <view class="card-content">
                             <view class="card-header">
-                                <view class="level-badge">{{ level.id }}</view>
+                                <view class="level-badge">L{{ index + 1 }}</view>
                                 <view class="current-badge" v-if="level.isCurrent">当前等级</view>
                             </view>
                             <text class="level-name">{{ level.name }}</text>
-                            <text class="level-score">{{ level.score }}</text>
+                            <text class="level-score">所需积分: {{ level.upgradePoints || 0 }}</text>
                             <!-- Crown graphic overlay -->
                             <image class="crown-overlay" src="/static/icons/crown.svg" mode="aspectFit"></image>
                         </view>
@@ -37,7 +42,7 @@
             <view class="swiper-dots">
                 <view 
                     class="dot" 
-                    v-for="(item, index) in levels" 
+                    v-for="(item, index) in processedLevels" 
                     :key="index"
                     :class="{ active: currentIndex === index }">
                 </view>
@@ -45,35 +50,38 @@
         </view>
 
         <!-- 权益标题 -->
-        <view class="benefits-title-row">
-            <text class="benefits-title">{{ currentLevel.id }} 专属权益</text>
-            <text class="benefits-count">({{ currentLevel.benefits.length }})</text>
+        <view class="benefits-title-row" v-if="!pageLoading && currentLevel">
+            <text class="benefits-title">专属权益</text>
+            <text class="benefits-count">({{ currentLevel.benefits ? currentLevel.benefits.length : 0 }})</text>
         </view>
 
         <!-- 权益列表 -->
-        <view class="benefits-grid">
+        <view class="benefits-grid" v-if="!pageLoading && currentLevel">
             <view 
                 class="benefit-item" 
                 v-for="(benefit, index) in currentLevel.benefits" 
                 :key="index"
                 @click="showBenefitDetail(benefit)">
                 <view class="benefit-icon-wrapper">
-                    <image class="benefit-icon" :src="benefit.icon" mode="aspectFit" v-if="benefit.icon"></image>
+                    <image class="benefit-icon" :src="benefit.iconUrl" mode="aspectFit" v-if="benefit.iconUrl"></image>
                     <view class="benefit-icon-placeholder" v-else>{{ benefit.name[0] }}</view>
                 </view>
                 <text class="benefit-name">{{ benefit.name }}</text>
             </view>
+            <view class="empty-benefits" v-if="!currentLevel.benefits || currentLevel.benefits.length === 0">
+                <text>该等级暂无特殊权益</text>
+            </view>
         </view>
 
         <!-- 权益详情弹窗 -->
         <view class="popup-mask" :class="{ 'show': isPopupShow }" @click="closePopup" @touchmove.stop.prevent>
             <view class="popup-modal" @click.stop>
                 <view class="popup-icon-wrapper">
-                     <image class="benefit-icon-large" :src="currentBenefit.icon" mode="aspectFit" v-if="currentBenefit && currentBenefit.icon"></image>
+                     <image class="benefit-icon-large" :src="currentBenefit.iconUrl" mode="aspectFit" v-if="currentBenefit && currentBenefit.iconUrl"></image>
                      <view class="benefit-icon-placeholder-large" v-else>{{ currentBenefit ? currentBenefit.name[0] : '' }}</view>
                 </view>
                 <text class="popup-title">{{ currentBenefit ? currentBenefit.name : '' }}</text>
-                <text class="popup-desc">{{ currentBenefit ? currentBenefit.desc : '' }}</text>
+                <text class="popup-desc">{{ currentBenefit ? currentBenefit.statement : '' }}</text>
                 <button class="popup-btn" @click="closePopup">我知道了</button>
             </view>
         </view>
@@ -82,68 +90,77 @@
 </template>
 
 <script>
+import { getMyProfile, listAllLevelConfigs, listAllLevelRights } from '@/api/fulfiller'
+
 export default {
     data() {
         return {
-            currentIndex: 2, // 默认选中 L3
-            levels: [
-                { 
-                    id: 'L1', 
-                    name: '青铜履约者', 
-                    score: '需成长值 0', 
-                    isCurrent: false,
-                    benefits: [
-                        { name: '新手任务', desc: '完成新手任务可获得额外奖励', icon: '/static/icons/reward.svg' }
-                    ]
-                },
-                { 
-                    id: 'L2', 
-                    name: '白银履约者', 
-                    score: '需成长值 200', 
-                    isCurrent: false,
-                    benefits: [
-                         { name: '新手任务', desc: '完成新手任务可获得额外奖励', icon: '/static/icons/reward.svg' },
-                        { name: '优先派单', desc: '系统将优先为您派送附近的优质订单', icon: '' }
-                    ]
-                },
-                { 
-                    id: 'L3', 
-                    name: '黄金履约者', 
-                    score: '需成长值 500', 
-                    isCurrent: true,
-                    benefits: [
-                        { name: '极速提现', desc: '提现申请 2 小时内极速到账,无需等待。', icon: '' },
-                        { name: '晋升奖励', desc: '晋升等级可获得现金红包奖励。', icon: '/static/icons/reward.svg' },
-                        { name: '优先派单', desc: '系统将优先为您派送附近的优质订单。', icon: '' }
-                    ]
-                },
-                { 
-                    id: 'L4', 
-                    name: '钻石履约者', 
-                    score: '需成长值 2000', 
-                    isCurrent: false,
-                    benefits: [
-                        { name: '专属客服', desc: '享受 7x24 小时专属客服通道。', icon: '/static/icons/service.svg' },
-                        { name: '生日礼包', desc: '生日当天获赠专属礼包。', icon: '/static/icons/reward.svg' },
-                        { name: '装备免费换', desc: '每年可免费更换一套履约装备。', icon: '' },
-                        { name: '医疗互助', desc: '享受平台提供的医疗互助保障。', icon: '' }
-                    ]
-                }
-            ],
+            currentIndex: 0,
+            profile: null,
+            levels: [], // 从后端获取的等级配置
+            rightsList: [], // 从后端获取的所有权益列表
             isPopupShow: false,
-            currentBenefit: null
+            currentBenefit: null,
+            pageLoading: true
         }
     },
     computed: {
         currentLevel() {
-            return this.levels[this.currentIndex];
+            return this.processedLevels[this.currentIndex];
+        },
+        // 合并等级与对应的权益详细信息
+        processedLevels() {
+            if (!this.levels.length) return [];
+            return this.levels.map(lvl => {
+                // 筛选出属于该等级的权益
+                const benefits = (lvl.rights || []).map(rightId => {
+                    return this.rightsList.find(r => r.id === rightId)
+                }).filter(Boolean); // 过滤掉未找到的
+
+                return {
+                    ...lvl,
+                    isCurrent: this.profile && this.profile.level === lvl.lvNo,
+                    benefits: benefits
+                }
+            }).sort((a,b) => a.lvNo - b.lvNo); // 确保按级别排序
         }
     },
+    async onLoad() {
+        await this.initData();
+    },
     methods: {
+        async initData() {
+            this.pageLoading = true;
+            uni.showLoading({ title: '加载中...' });
+            try {
+                // 并行加载个人信息、等级配置、权益列表
+                const [profileRes, levelsRes, rightsRes] = await Promise.all([
+                    getMyProfile(),
+                    listAllLevelConfigs(),
+                    listAllLevelRights()
+                ]);
+
+                this.profile = profileRes.data;
+                this.levels = levelsRes.data || [];
+                this.rightsList = rightsRes.data || [];
+
+                // 默认定位到用户当前等级
+                if (this.profile) {
+                    const idx = this.processedLevels.findIndex(lvl => lvl.lvNo === this.profile.level);
+                    if (idx !== -1) {
+                        this.currentIndex = idx;
+                    }
+                }
+            } catch (err) {
+                console.error('初始化等级页面失败:', err);
+                uni.showToast({ title: '数据加载失败', icon: 'none' });
+            } finally {
+                this.pageLoading = false;
+                uni.hideLoading();
+            }
+        },
         navBack() {
-             uni.navigateBack({
-                delta: 1
-            });
+             uni.navigateBack();
         },
         swiperChange(e) {
             this.currentIndex = e.detail.current;
@@ -163,7 +180,6 @@ export default {
 </script>
 
 <style>
-/* ... Header styles keep same ... */
 page {
     background-color: #fff;
     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
@@ -216,12 +232,8 @@ page {
     overflow: hidden;
     position: relative;
     box-shadow: 0 10rpx 20rpx rgba(0,0,0,0.1);
+    background-color: #eee;
 }
-/* Gradients */
-.level-card-1 { background: linear-gradient(135deg, #E0E0E0 0%, #BDBDBD 100%); }
-.level-card-2 { background: linear-gradient(135deg, #CFD8DC 0%, #B0BEC5 100%); }
-.level-card-3 { background: linear-gradient(135deg, #FFC107 0%, #FF9800 100%); }
-.level-card-4 { background: linear-gradient(135deg, #4FC3F7 0%, #039BE5 100%); }
 
 .card-content {
     padding: 30rpx;
@@ -236,9 +248,10 @@ page {
     display: flex;
     justify-content: space-between;
     align-items: flex-start;
-    margin-bottom: auto; /* Push content down */
+    margin-bottom: auto;
 }
 .level-badge {
+    background: rgba(255,255,255,0.2);
     border: 1px solid rgba(255,255,255,0.6);
     padding: 2rpx 12rpx;
     border-radius: 10rpx;
@@ -258,11 +271,11 @@ page {
     font-weight: bold;
     color: #fff;
     margin-bottom: 10rpx;
-    text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
+    text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.2);
 }
 .level-score {
     font-size: 24rpx;
-    color: rgba(255,255,255,0.8);
+    color: rgba(255,255,255,0.9);
     margin-bottom: 20rpx;
 }
 .crown-overlay {
@@ -271,11 +284,10 @@ page {
     right: -30rpx;
     width: 260rpx;
     height: 260rpx;
-    opacity: 0.1;
+    opacity: 0.15;
     z-index: 1;
 }
 
-/* Dots */
 .swiper-dots {
     display: flex;
     justify-content: center;
@@ -317,7 +329,7 @@ page {
     padding: 0 20rpx;
 }
 .benefit-item {
-    width: 25%; /* 4 items per row */
+    width: 25%;
     display: flex;
     flex-direction: column;
     align-items: center;
@@ -326,7 +338,7 @@ page {
 .benefit-icon-wrapper {
     width: 88rpx;
     height: 88rpx;
-    background-color: #F8F8F8; /* Or very light color based on current level? Keep simple for now */
+    background-color: #F8F8F8;
     border-radius: 24rpx;
     display: flex;
     align-items: center;
@@ -337,42 +349,44 @@ page {
     width: 44rpx;
     height: 44rpx;
 }
-.benefit-icon-placeholder {
-    font-size: 36rpx;
-    font-weight: bold;
-    color: #FFB300;
-} 
 .benefit-name {
-    font-size: 22rpx; /* Smaller font as requested matching image roughly */
+    font-size: 22rpx;
     color: #666;
     text-align: center;
 }
 
-/* Modal */
+.empty-benefits {
+    width: 100%;
+    padding: 60rpx 0;
+    text-align: center;
+    color: #ccc;
+    font-size: 26rpx;
+}
+
 .popup-mask {
     position: fixed;
     top: 0;
     left: 0;
     right: 0;
     bottom: 0;
-    background-color: rgba(0,0,0,0.5); /* Semi-transparent black */
+    background-color: rgba(0,0,0,0.5);
     z-index: 999;
-    display: none; /* Hidden by default */
+    display: none;
     align-items: center;
     justify-content: center;
 }
 .popup-mask.show {
-    display: flex; /* Show when active */
+    display: flex;
 }
 .popup-modal {
-    width: 480rpx; /* Narrower width */
+    width: 520rpx;
     background-color: #fff;
     border-radius: 30rpx;
     padding: 50rpx 40rpx;
     display: flex;
     flex-direction: column;
     align-items: center;
-    box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.2); /* Drop shadow */
+    box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.2);
 }
 .popup-icon-wrapper {
     width: 120rpx;
@@ -388,31 +402,26 @@ page {
     width: 60rpx;
     height: 60rpx;
 }
-.benefit-icon-placeholder-large {
-    font-size: 50rpx;
-    font-weight: bold;
-    color: #FFB300;
-}
 .popup-title {
-    font-size: 32rpx;
+    font-size: 34rpx;
     font-weight: bold;
     color: #333;
     margin-bottom: 20rpx;
 }
 .popup-desc {
-    font-size: 26rpx;
+    font-size: 28rpx;
     color: #666;
     text-align: center;
-    line-height: 1.5;
+    line-height: 1.6;
     margin-bottom: 40rpx;
 }
 .popup-btn {
-    width: 80%;
-    height: 72rpx;
-    line-height: 72rpx;
-    background-color: #212121;
+    width: 90%;
+    height: 80rpx;
+    line-height: 80rpx;
+    background: linear-gradient(90deg, #333 0%, #111 100%);
     color: #fff;
     font-size: 28rpx;
-    border-radius: 36rpx;
+    border-radius: 40rpx;
 }
 </style>

+ 20 - 2
pages/mine/logic.js

@@ -1,5 +1,5 @@
 import { logout as logoutApi } from '@/api/auth'
-import { getMyProfile } from '@/api/fulfiller'
+import { getMyProfile, listAllLevelConfigs } from '@/api/fulfiller'
 import { clearAuth, isLoggedIn } from '@/utils/auth'
 import customTabbar from '@/components/custom-tabbar/index.vue'
 
@@ -12,13 +12,23 @@ export default {
             showServicePopup: false,
             showLogoutPopup: false,
             profile: null,
-            profileLoading: false
+            profileLoading: false,
+            levelConfigs: [] // 等级配置列表
+        }
+    },
+    computed: {
+        // 根据 profile.level 匹配对应的等级名称
+        displayLevelName() {
+            if (!this.profile || !this.levelConfigs.length) return '普通履约者'
+            const config = this.levelConfigs.find(c => c.lvNo === this.profile.level)
+            return config ? config.name : (this.profile.levelName || '普通履约者')
         }
     },
     onShow() {
         uni.hideTabBar()
         if (isLoggedIn()) {
             this.loadProfile()
+            this.loadLevelConfigs()
         }
     },
     methods: {
@@ -34,6 +44,14 @@ export default {
                 this.profileLoading = false
             }
         },
+        async loadLevelConfigs() {
+            try {
+                const res = await listAllLevelConfigs()
+                this.levelConfigs = res.data || []
+            } catch (err) {
+                console.error('加载等级配置失败:', err)
+            }
+        },
         navToSettings() {
             uni.navigateTo({
                 url: '/pages/mine/settings/index'

+ 18 - 6
pages/mine/order-stats.vue

@@ -49,8 +49,8 @@
                         <image class="type-icon" :src="order.typeIcon"></image>
                         <text class="type-text">{{ order.typeName }}</text>
                     </view>
-                    <text class="status-text" :class="order.status === '完成' ? 'green' : 'red'">
-                        {{ order.status === '完成' ? '完成:' : '拒绝:' }}{{ order.finishTime }}
+                    <text class="status-text" :style="{ color: order.statusColor }">
+                        {{ order.statusLabel }}
                     </text>
                 </view>
 
@@ -119,7 +119,8 @@
 
 <script>
 import { getOrderStats, getStatisticOrders } from '@/api/fulfiller';
-import { getServiceList } from '@/api/service';
+import { listAllService } from '@/api/service/list/index';
+
 
 export default {
     data() {
@@ -153,7 +154,7 @@ export default {
     methods: {
         async loadServiceList() {
             try {
-                const res = await getServiceList();
+                const res = await listAllService();
                 this.serviceList = res.data || [];
             } catch (err) {
                 console.error('获取服务类型失败:', err);
@@ -206,14 +207,25 @@ export default {
             const service = this.serviceList.find(s => s.id === order.service);
             const mode = service?.mode || 0;
             const isRoundTrip = mode === 1;
-            const isSuccess = order.status === 4;
+            
+            // 状态枚举映射
+            const statusMap = {
+                0: { label: '待派单', color: '#f56c6c' },
+                1: { label: '待接单', color: '#e6a23c' },
+                2: { label: '待服务', color: '#49a3ff' },
+                3: { label: '服务中', color: '#49a3ff' },
+                4: { label: '已完成', color: '#67c23a' },
+                5: { label: '已取消', color: '#909399' }
+            };
+            const statusInfo = statusMap[order.status] || { label: '未知', color: '#999' };
 
             return {
                 id: order.id,
                 orderType: isRoundTrip ? 1 : 2,
                 typeName: service?.name || '未知',
                 typeIcon: service?.iconUrl || '',
-                status: isSuccess ? '完成' : '拒绝',
+                statusLabel: statusInfo.label,
+                statusColor: statusInfo.color,
                 finishTime: order.serviceTime || '',
                 serviceTime: order.serviceTime || '',
                 petName: order.petName || '未知',

+ 4 - 3
pages/orders/anomaly.vue

@@ -363,11 +363,12 @@ export default {
     bottom: 0;
     left: 0;
     width: 100%;
-    background-color: #FF9800;
+    background-color: #fff;
     padding: 20rpx 40rpx;
-    padding-bottom: constant(safe-area-inset-bottom);
-    padding-bottom: env(safe-area-inset-bottom);
+    padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
     box-sizing: border-box;
+    box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
+    z-index: 10;
 }
 
 .ano-submit-btn {

+ 32 - 25
pages/orders/detail-logic.js

@@ -1,5 +1,9 @@
 import { getOrderInfo, getOrderLogs, uploadFile, clockIn, getAnomalyList, submitNursingSummary } from '@/api/fulfiller'
-import { getServiceList, getServiceDetail } from '@/api/service'
+import { listAllService } from '@/api/service/list/index'
+
+
+
+
 import { getDictDataByType } from '@/api/system/dict/index'
 import { getPetDetail, submitPetRemark as apiSubmitPetRemark } from '@/api/archieves/pet/index'
 import { listChangeLog } from '@/api/archieves/changeLog/index'
@@ -42,6 +46,7 @@ export default {
                 remark: '',
                 orderNo: '',
                 createTime: '',
+                serviceName: '', // 服务类型名称
                 progressLogs: [],
                 nursingSummary: '' // 宠护小结
             },
@@ -129,8 +134,11 @@ export default {
         try {
             // 先加载字典
             await this.loadAnomalyTypeDict()
-            // 获取订单详情(内部会拿到 serviceId,然后加载服务详情获取 clockInRemark)
+            // 先加载所有服务列表
+            await this.loadServiceList()
+            // 获取订单详情
             await this.loadOrderDetail()
+
         } finally {
             this.pageLoading = false
         }
@@ -138,7 +146,7 @@ export default {
     methods: {
         async loadServiceList() {
             try {
-                const res = await getServiceList()
+                const res = await listAllService()
                 this.serviceList = res.data || []
             } catch (err) {
                 console.error('获取服务类型失败:', err)
@@ -147,29 +155,28 @@ export default {
         /**
          * 根据服务类型ID获取服务详情,解析 clockInRemark 为打卡步骤
          */
-        async loadServiceDetail(serviceId) {
-            console.log('开始加载服务详情, ID:', serviceId)
-            try {
-                const res = await getServiceDetail(serviceId)
-                const serviceInfo = res.data
-                console.log('服务详情响应结果:', serviceInfo)
-                if (serviceInfo) {
-                    this.serviceMode = serviceInfo.mode
-                    console.log('当前服务模式(mode):', this.serviceMode)
-                    if (serviceInfo.clockInRemark) {
-                        try {
-                            const parsed = JSON.parse(serviceInfo.clockInRemark)
-                            if (Array.isArray(parsed) && parsed.length > 0) {
-                                this.clockInSteps = parsed
-                                console.log('解析打卡步骤:', this.clockInSteps)
-                            }
-                        } catch (parseErr) {
-                            console.error('解析 clockInRemark 失败:', parseErr)
+        /**
+         * 基于已加载的 serviceList 进行前端匹配,解析 clockInRemark 为打卡步骤
+         */
+        loadServiceDetail(serviceId) {
+            console.log('前端匹配服务详情, ID:', serviceId)
+            const serviceInfo = (this.serviceList || []).find(s => s.id === serviceId)
+            console.log('匹配到的服务信息:', serviceInfo)
+            if (serviceInfo) {
+                this.serviceMode = serviceInfo.mode
+                this.orderDetail.serviceName = serviceInfo.name
+                console.log('当前服务模式(mode):', this.serviceMode)
+                if (serviceInfo.clockInRemark) {
+                    try {
+                        const parsed = JSON.parse(serviceInfo.clockInRemark)
+                        if (Array.isArray(parsed) && parsed.length > 0) {
+                            this.clockInSteps = parsed
+                            console.log('解析打卡步骤:', this.clockInSteps)
                         }
+                    } catch (parseErr) {
+                        console.error('解析 clockInRemark 失败:', parseErr)
                     }
                 }
-            } catch (err) {
-                console.error('获取服务类型详情失败:', err)
             }
         },
         async loadOrderDetail() {
@@ -196,7 +203,7 @@ export default {
 
                 // 根据订单的服务类型ID获取服务详情(含 clockInRemark)
                 if (this.serviceId) {
-                    await this.loadServiceDetail(this.serviceId)
+                    this.loadServiceDetail(this.serviceId)
                 } else {
                     console.warn('订单中未找到 service 字段,无法加载服务步骤')
                 }
@@ -487,7 +494,7 @@ export default {
         },
         goToAnomaly() {
             uni.navigateTo({
-                url: '/pages/orders/anomaly?orderId=' + (this.orderDetail.orderNo || '')
+                url: '/pages/orders/anomaly?orderId=' + (this.orderId || '')
             });
         },
         callPhone() {

+ 2 - 10
pages/orders/detail.vue

@@ -48,10 +48,9 @@
                 <view class="pb-info">
                     <view class="pb-name-row">
                         <text class="pb-name">{{ orderDetail.petName }}</text>
-                        <text class="pb-breed">品种: {{ orderDetail.petBreed }}</text>
                     </view>
                     <view class="pb-tags">
-                        <text class="pb-tag">{{ orderDetail.serviceTag }}</text>
+                        <text class="pb-tag">{{ orderDetail.serviceName }}</text>
                     </view>
                 </view>
                 <view class="pb-actions">
@@ -113,16 +112,9 @@
                             <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
                         </view>
                     </view>
-
-                    <view class="si-row">
-                        <image class="si-icon outline" src="/static/icons/heart.svg"></image>
-                        <view class="si-content">
-                            <text class="si-label">服务内容</text>
-                            <text class="si-val">{{ orderDetail.serviceContent }}</text>
-                        </view>
-                    </view>
                 </template>
 
+
                 <view class="si-row">
                     <image class="si-icon outline custom-icon-file" src="/static/icons/file.svg"></image>
                     <view class="si-content">

+ 5 - 4
pages/orders/logic.js

@@ -1,6 +1,7 @@
 import { getMyOrders } from '@/api/fulfiller'
-import { getServiceList } from '@/api/service'
-import { cancelOrderApi } from '@/api/order/subOrder/index'
+import { listAllService } from '@/api/service/list/index'
+
+import { cancelOrderApi } from '@/api/order/subOrder/index.js'
 import customTabbar from '@/components/custom-tabbar/index.vue'
 
 export default {
@@ -10,7 +11,7 @@ export default {
     data() {
         return {
             currentTab: 0,
-            tabs: ['待接送/服务', '配送/服务中', '已完成', '已拒绝'],
+            tabs: ['待接送/服务', '配送/服务中', '已完成', '已取消'],
             typeFilterOptions: ['全部类型'],
             currentTypeFilterIdx: 0,
             activeDropdown: 0,
@@ -75,7 +76,7 @@ export default {
     methods: {
         async loadServiceList() {
             try {
-                const res = await getServiceList()
+                const res = await listAllService()
                 this.serviceList = res.data || []
                 this.typeFilterOptions = ['全部类型', ...this.serviceList.map(s => s.name)]
             } catch (err) {

+ 30 - 3
pages/recruit/auth_logic.js

@@ -21,7 +21,8 @@ export default {
             tempYear: 0,
             tempMonth: 0,
             tempDay: 0,
-            serviceType: [] // 接收上一页的服务类型
+            serviceType: [], // 接收上一页的服务类型
+            isChoosingImage: false // 标志位:是否正在选择图片中,防止 onShow 重置数据
         }
     },
     onLoad(options) {
@@ -33,8 +34,16 @@ export default {
             }
         }
         this.initDateData();
-        // 从本地缓存恢复实名认证数据(返回上一级再进来时不丢失)
-        this.restoreAuthData();
+        // 移除原有的 restoreAuthData 调用,因为用户要求进入页面即清空
+    },
+    onShow() {
+        // 如果是从选择图片页面返回,不重置数据
+        if (this.isChoosingImage) {
+            this.isChoosingImage = false;
+            return;
+        }
+        // 正常进入页面时清空所有信息
+        this.resetFormData();
     },
     methods: {
         // --- 日期选择器逻辑 ---
@@ -121,9 +130,27 @@ export default {
                 console.error('保存认证数据失败', e);
             }
         },
+        // --- 重置表单数据 ---
+        resetFormData() {
+            // 清空本地组件数据
+            this.formData.name = '';
+            this.formData.idNumber = '';
+            this.formData.expiryDate = '';
+            this.idCardFront = '';
+            this.idCardBack = '';
+            this.idCardFrontOssId = '';
+            this.idCardBackOssId = '';
+            // 清除本地缓存
+            try {
+                uni.removeStorageSync('recruit_auth_data');
+            } catch (e) {
+                console.error('清除缓存失败', e);
+            }
+        },
 
         // --- 图片上传(选择后自动上传到OSS) ---
         chooseImage(side) {
+            this.isChoosingImage = true;
             uni.chooseImage({
                 count: 1,
                 sizeType: ['compressed'],

+ 5 - 2
pages/recruit/logic.js

@@ -1,5 +1,8 @@
 import { sendSmsCode } from '@/api/auth'
-import { getAreaChildren, getServiceTypes } from '@/api/fulfiller'
+import { getAreaChildren } from '@/api/fulfiller'
+import { listAllService } from '@/api/service/list/index'
+
+
 
 export default {
     data() {
@@ -122,7 +125,7 @@ export default {
 
         async loadServiceTypes() {
             try {
-                const res = await getServiceTypes();
+                const res = await listAllService();
                 this.serviceTypes = (res.data || []).map(item => ({
                     id: item.id,
                     name: item.name

BIN
unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-hdpi.png


BIN
unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xhdpi.png


BIN
unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xxhdpi.png


BIN
unpackage/cache/wgt/__UNI__76F5C47/.manifest/icon-android-xxxhdpi.png


File diff suppressed because it is too large
+ 1 - 1
unpackage/dist/dev/app-plus/app-config-service.js


File diff suppressed because it is too large
+ 246 - 204
unpackage/dist/dev/app-plus/app-service.js


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

@@ -122,7 +122,7 @@
     "uni-app": {
       "control": "uni-v3",
       "vueVersion": "3",
-      "compilerVersion": "5.03",
+      "compilerVersion": "5.04",
       "nvueCompiler": "uni-app",
       "renderer": "auto",
       "nvue": {

+ 3 - 4
unpackage/dist/dev/app-plus/pages/home/work-status.css

@@ -121,10 +121,9 @@ body {
     background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
     box-shadow: 0 0.3125rem 0.625rem rgba(255, 87, 34, 0.3);
 }
-.action-btn.stopped {
-    background-color: #E0E0E0;
-    color: #999;
-    box-shadow: none;
+.action-btn.start {
+    background: linear-gradient(90deg, #4CAF50 0%, #2E7D32 100%);
+    box-shadow: 0 0.3125rem 0.625rem rgba(76, 175, 80, 0.3);
 }
 .tips {
     font-size: 0.75rem;

+ 29 - 44
unpackage/dist/dev/app-plus/pages/mine/level/index.css

@@ -1,5 +1,4 @@
 
-/* ... Header styles keep same ... */
 body {
     background-color: #fff;
     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
@@ -51,15 +50,7 @@ body {
     overflow: hidden;
     position: relative;
     box-shadow: 0 0.3125rem 0.625rem rgba(0,0,0,0.1);
-}
-/* Gradients */
-.level-card-1 { background: linear-gradient(135deg, #E0E0E0 0%, #BDBDBD 100%);
-}
-.level-card-2 { background: linear-gradient(135deg, #CFD8DC 0%, #B0BEC5 100%);
-}
-.level-card-3 { background: linear-gradient(135deg, #FFC107 0%, #FF9800 100%);
-}
-.level-card-4 { background: linear-gradient(135deg, #4FC3F7 0%, #039BE5 100%);
+    background-color: #eee;
 }
 .card-content {
     padding: 0.9375rem;
@@ -74,9 +65,10 @@ body {
     display: flex;
     justify-content: space-between;
     align-items: flex-start;
-    margin-bottom: auto; /* Push content down */
+    margin-bottom: auto;
 }
 .level-badge {
+    background: rgba(255,255,255,0.2);
     border: 1px solid rgba(255,255,255,0.6);
     padding: 0.0625rem 0.375rem;
     border-radius: 0.3125rem;
@@ -96,11 +88,11 @@ body {
     font-weight: bold;
     color: #fff;
     margin-bottom: 0.3125rem;
-    text-shadow: 0 0.0625rem 0.125rem rgba(0,0,0,0.1);
+    text-shadow: 0 0.0625rem 0.125rem rgba(0,0,0,0.2);
 }
 .level-score {
     font-size: 0.75rem;
-    color: rgba(255,255,255,0.8);
+    color: rgba(255,255,255,0.9);
     margin-bottom: 0.625rem;
 }
 .crown-overlay {
@@ -109,11 +101,9 @@ body {
     right: -0.9375rem;
     width: 8.125rem;
     height: 8.125rem;
-    opacity: 0.1;
+    opacity: 0.15;
     z-index: 1;
 }
-
-/* Dots */
 .swiper-dots {
     display: flex;
     justify-content: center;
@@ -153,7 +143,7 @@ body {
     padding: 0 0.625rem;
 }
 .benefit-item {
-    width: 25%; /* 4 items per row */
+    width: 25%;
     display: flex;
     flex-direction: column;
     align-items: center;
@@ -162,7 +152,7 @@ body {
 .benefit-icon-wrapper {
     width: 2.75rem;
     height: 2.75rem;
-    background-color: #F8F8F8; /* Or very light color based on current level? Keep simple for now */
+    background-color: #F8F8F8;
     border-radius: 0.75rem;
     display: flex;
     align-items: center;
@@ -173,42 +163,42 @@ body {
     width: 1.375rem;
     height: 1.375rem;
 }
-.benefit-icon-placeholder {
-    font-size: 1.125rem;
-    font-weight: bold;
-    color: #FFB300;
-}
 .benefit-name {
-    font-size: 0.6875rem; /* Smaller font as requested matching image roughly */
+    font-size: 0.6875rem;
     color: #666;
     text-align: center;
 }
-
-/* Modal */
+.empty-benefits {
+    width: 100%;
+    padding: 1.875rem 0;
+    text-align: center;
+    color: #ccc;
+    font-size: 0.8125rem;
+}
 .popup-mask {
     position: fixed;
     top: 0;
     left: 0;
     right: 0;
     bottom: 0;
-    background-color: rgba(0,0,0,0.5); /* Semi-transparent black */
+    background-color: rgba(0,0,0,0.5);
     z-index: 999;
-    display: none; /* Hidden by default */
+    display: none;
     align-items: center;
     justify-content: center;
 }
 .popup-mask.show {
-    display: flex; /* Show when active */
+    display: flex;
 }
 .popup-modal {
-    width: 15rem; /* Narrower width */
+    width: 16.25rem;
     background-color: #fff;
     border-radius: 0.9375rem;
     padding: 1.5625rem 1.25rem;
     display: flex;
     flex-direction: column;
     align-items: center;
-    box-shadow: 0 0.3125rem 1.25rem rgba(0,0,0,0.2); /* Drop shadow */
+    box-shadow: 0 0.3125rem 1.25rem rgba(0,0,0,0.2);
 }
 .popup-icon-wrapper {
     width: 3.75rem;
@@ -224,30 +214,25 @@ body {
     width: 1.875rem;
     height: 1.875rem;
 }
-.benefit-icon-placeholder-large {
-    font-size: 1.5625rem;
-    font-weight: bold;
-    color: #FFB300;
-}
 .popup-title {
-    font-size: 1rem;
+    font-size: 1.0625rem;
     font-weight: bold;
     color: #333;
     margin-bottom: 0.625rem;
 }
 .popup-desc {
-    font-size: 0.8125rem;
+    font-size: 0.875rem;
     color: #666;
     text-align: center;
-    line-height: 1.5;
+    line-height: 1.6;
     margin-bottom: 1.25rem;
 }
 .popup-btn {
-    width: 80%;
-    height: 2.25rem;
-    line-height: 2.25rem;
-    background-color: #212121;
+    width: 90%;
+    height: 2.5rem;
+    line-height: 2.5rem;
+    background: linear-gradient(90deg, #333 0%, #111 100%);
     color: #fff;
     font-size: 0.875rem;
-    border-radius: 1.125rem;
+    border-radius: 1.25rem;
 }

+ 4 - 3
unpackage/dist/dev/app-plus/pages/orders/anomaly.css

@@ -130,11 +130,12 @@
     bottom: 0;
     left: 0;
     width: 100%;
-    background-color: #FF9800;
+    background-color: #fff;
     padding: 0.625rem 1.25rem;
-    padding-bottom: constant(safe-area-inset-bottom);
-    padding-bottom: env(safe-area-inset-bottom);
+    padding-bottom: calc(0.625rem + env(safe-area-inset-bottom));
     box-sizing: border-box;
+    box-shadow: 0 -0.125rem 0.625rem rgba(0, 0, 0, 0.05);
+    z-index: 10;
 }
 .ano-submit-btn {
     width: 100%;

File diff suppressed because it is too large
+ 0 - 0
unpackage/dist/dev/cache/.app-plus/tsc/app-android/.tsbuildInfo


BIN
unpackage/res/icons/1024x1024.png


BIN
unpackage/res/icons/120x120.png


BIN
unpackage/res/icons/144x144.png


BIN
unpackage/res/icons/152x152.png


BIN
unpackage/res/icons/167x167.png


BIN
unpackage/res/icons/180x180.png


BIN
unpackage/res/icons/192x192.png


BIN
unpackage/res/icons/20x20.png


BIN
unpackage/res/icons/29x29.png


BIN
unpackage/res/icons/40x40.png


BIN
unpackage/res/icons/58x58.png


BIN
unpackage/res/icons/60x60.png


BIN
unpackage/res/icons/72x72.png


BIN
unpackage/res/icons/76x76.png


BIN
unpackage/res/icons/80x80.png


BIN
unpackage/res/icons/87x87.png


BIN
unpackage/res/icons/96x96.png


+ 2 - 2
utils/config.js

@@ -4,9 +4,9 @@
  */
 
 // API 基础地址(开发环境)
-// export const BASE_URL = 'http://192.168.1.118:8080'
+export const BASE_URL = 'http://192.168.1.118:8080'
 // export const BASE_URL = 'http://8.136.194.143/api'
-export const BASE_URL = 'http://192.168.0.105:8080'
+// export const BASE_URL = 'http://192.168.0.103:8080'
 
 // 履约者App客户端ID(需要在 sys_client 表中配置)
 export const CLIENT_ID = 'fe63fea7be31b0200b496d08bc6b517d'

Some files were not shown because too many files changed in this diff