Răsfoiți Sursa

静态页面初始化完成

Huanyi 3 luni în urmă
părinte
comite
5c492cb7d1
100 a modificat fișierele cu 16137 adăugiri și 3 ștergeri
  1. 17 0
      App.vue
  2. 0 3
      README.md
  3. 128 0
      components/privacy-popup/privacy-popup.vue
  4. 53 0
      generate_icons.py
  5. 103 0
      implementation_plan.md
  6. 20 0
      index.html
  7. 22 0
      main.js
  8. 72 0
      manifest.json
  9. 264 0
      pages.json
  10. 371 0
      pages/home/index.vue
  11. 295 0
      pages/home/logic.js
  12. 1247 0
      pages/home/style.css
  13. 210 0
      pages/home/work-status.vue
  14. 89 0
      pages/login/logic.js
  15. 160 0
      pages/login/login.vue
  16. 110 0
      pages/login/reset-pwd-set.vue
  17. 138 0
      pages/login/reset-pwd-verify.vue
  18. 330 0
      pages/login/style.css
  19. 184 0
      pages/mine/index.vue
  20. 418 0
      pages/mine/level/index.vue
  21. 86 0
      pages/mine/logic.js
  22. 109 0
      pages/mine/message/detail.vue
  23. 183 0
      pages/mine/message/index.vue
  24. 168 0
      pages/mine/message/order.vue
  25. 186 0
      pages/mine/message/system.vue
  26. 330 0
      pages/mine/order-stats.vue
  27. 386 0
      pages/mine/points/detail.vue
  28. 378 0
      pages/mine/points/index.vue
  29. 216 0
      pages/mine/rewards-all.vue
  30. 421 0
      pages/mine/rewards.vue
  31. 160 0
      pages/mine/settings/about/index.vue
  32. 296 0
      pages/mine/settings/auth/index.vue
  33. 191 0
      pages/mine/settings/bank/index.vue
  34. 212 0
      pages/mine/settings/index.vue
  35. 113 0
      pages/mine/settings/notification/index.vue
  36. 137 0
      pages/mine/settings/profile/edit-name.vue
  37. 438 0
      pages/mine/settings/profile/index.vue
  38. 151 0
      pages/mine/settings/security/index.vue
  39. 607 0
      pages/mine/style.css
  40. 395 0
      pages/mine/wallet/bill.vue
  41. 458 0
      pages/mine/wallet/index.vue
  42. 396 0
      pages/orders/anomaly.vue
  43. 289 0
      pages/orders/detail-logic.js
  44. 1386 0
      pages/orders/detail-style.css
  45. 374 0
      pages/orders/detail.vue
  46. 316 0
      pages/orders/index.vue
  47. 322 0
      pages/orders/logic.js
  48. 1090 0
      pages/orders/style.css
  49. 152 0
      pages/recruit/auth.css
  50. 94 0
      pages/recruit/auth.vue
  51. 93 0
      pages/recruit/auth_logic.js
  52. 271 0
      pages/recruit/form.vue
  53. 180 0
      pages/recruit/landing.css
  54. 29 0
      pages/recruit/landing.js
  55. 67 0
      pages/recruit/landing.vue
  56. 232 0
      pages/recruit/logic.js
  57. 149 0
      pages/recruit/qualifications.css
  58. 46 0
      pages/recruit/qualifications.vue
  59. 73 0
      pages/recruit/qualifications_logic.js
  60. 446 0
      pages/recruit/style.css
  61. 91 0
      pages/recruit/success.css
  62. 40 0
      pages/recruit/success.vue
  63. 17 0
      pages/recruit/success_logic.js
  64. BIN
      static/dog.png
  65. BIN
      static/header.png
  66. 1 0
      static/icons/bell.png
  67. 1 0
      static/icons/bell.svg
  68. 5 0
      static/icons/bell_linear.svg
  69. 4 0
      static/icons/bell_outline.svg
  70. 6 0
      static/icons/calendar.svg
  71. 4 0
      static/icons/camera_grey.svg
  72. 0 0
      static/icons/car.png
  73. 1 0
      static/icons/car.svg
  74. 3 0
      static/icons/chevron_right.svg
  75. 3 0
      static/icons/chevron_right_dark.svg
  76. 3 0
      static/icons/chevron_right_gold.svg
  77. 4 0
      static/icons/clock.svg
  78. 4 0
      static/icons/close_gray.svg
  79. 3 0
      static/icons/crown.svg
  80. 4 0
      static/icons/diamond_white.svg
  81. 6 0
      static/icons/file.svg
  82. 5 0
      static/icons/headset_green.svg
  83. 4 0
      static/icons/headset_linear.svg
  84. 7 0
      static/icons/icon_order_msg.svg
  85. 4 0
      static/icons/icon_system_msg.svg
  86. 4 0
      static/icons/location.svg
  87. 7 0
      static/icons/money_linear.svg
  88. 4 0
      static/icons/motorbike.svg
  89. 0 0
      static/icons/nav.png
  90. 1 0
      static/icons/nav_arrow.png
  91. 1 0
      static/icons/nav_arrow.svg
  92. 7 0
      static/icons/order_no.svg
  93. 5 0
      static/icons/phone_green.svg
  94. 5 0
      static/icons/phone_orange.svg
  95. 4 0
      static/icons/power_white.svg
  96. 4 0
      static/icons/reward.svg
  97. 3 0
      static/icons/right_arrow_orange.svg
  98. 3 0
      static/icons/service.svg
  99. 4 0
      static/icons/settings.svg
  100. 8 0
      static/icons/star_decor.svg

+ 17 - 0
App.vue

@@ -0,0 +1,17 @@
+<script>
+	export default {
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+</style>

+ 0 - 3
README.md

@@ -1,3 +0,0 @@
-# pet-system-fulfiller-app
-
-宠物系统履约者APP

+ 128 - 0
components/privacy-popup/privacy-popup.vue

@@ -0,0 +1,128 @@
+<template>
+    <view class="popup-mask" v-if="visible" @click.stop>
+        <view class="popup-content">
+            <!-- 顶部: 标题 + 关闭按钮 -->
+            <view class="popup-header">
+                <text class="popup-title">{{ title }}</text>
+                <view class="close-icon" @click="close">×</view>
+            </view>
+            
+            <!-- 内容滚动区 -->
+            <scroll-view scroll-y class="popup-body">
+                <slot>
+                    <text class="default-text">{{ content }}</text>
+                </slot>
+            </scroll-view>
+            
+            <!-- 底部按钮 -->
+            <view class="popup-footer">
+                <button class="confirm-btn" @click="close">我知道了</button>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+    export default {
+        name: 'privacy-popup',
+        props: {
+            visible: {
+                type: Boolean,
+                default: false
+            },
+            title: {
+                type: String,
+                default: '协议标题'
+            },
+            content: {
+                type: String, // 备用,主要用 slot
+                default: ''
+            }
+        },
+        methods: {
+            close() {
+                this.$emit('close');
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .popup-mask {
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background-color: rgba(0, 0, 0, 0.4); /* 半透明遮罩 */
+        z-index: 999;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+
+    .popup-content {
+        width: 80%; /* 宽度大概屏幕 80% */
+        max-height: 70%;
+        background-color: #fff;
+        border-radius: 16rpx;
+        display: flex;
+        flex-direction: column;
+        overflow: hidden;
+    }
+
+    .popup-header {
+        height: 100rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        position: relative;
+        border-bottom: 2rpx solid #eee;
+    }
+
+    .popup-title {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #333;
+    }
+
+    .close-icon {
+        position: absolute;
+        right: 30rpx;
+        top: 50%;
+        transform: translateY(-50%);
+        font-size: 40rpx;
+        color: #999;
+        line-height: 1;
+        padding: 10rpx; /* 增加点击区域 */
+    }
+
+    .popup-body {
+        padding: 30rpx;
+        font-size: 28rpx;
+        color: #666;
+        line-height: 1.6;
+        max-height: 600rpx; /* 限制高度滚动 */
+        box-sizing: border-box;
+    }
+
+    .popup-footer {
+        padding: 30rpx;
+        border-top: 2rpx solid #eee;
+    }
+
+    .confirm-btn {
+        background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+        color: #fff;
+        font-size: 30rpx;
+        font-weight: bold;
+        height: 80rpx;
+        line-height: 80rpx;
+        border-radius: 8rpx;
+        box-shadow: 0 4rpx 10rpx rgba(255, 87, 34, 0.2);
+    }
+    
+    .confirm-btn::after {
+        border: none;
+    }
+</style>

+ 53 - 0
generate_icons.py

@@ -0,0 +1,53 @@
+import os
+from PIL import Image, ImageDraw, ImageFont
+
+def create_icon(name, color, text_symbol, filename):
+    size = (81, 81)
+    img = Image.new('RGBA', size, (255, 255, 255, 0))
+    draw = ImageDraw.Draw(img)
+    
+    # Draw a simple shape or text
+    # Since we don't have a guaranteed font, we'll draw shapes
+    
+    # Center
+    cx, cy = size[0] // 2, size[1] // 2
+    r = 30
+    
+    if 'home' in name:
+        # Draw a house
+        points = [(cx, cy-r), (cx-r, cy), (cx+r, cy)]
+        draw.polygon(points, fill=color)
+        draw.rectangle([cx-r+10, cy, cx+r-10, cy+r], fill=color)
+    elif 'order' in name:
+        # Draw a document
+        draw.rectangle([cx-20, cy-30, cx+20, cy+30], fill=color)
+        # Lines
+        draw.line([cx-10, cy-10, cx+10, cy-10], fill=(255,255,255,255), width=3)
+        draw.line([cx-10, cy+10, cx+10, cy+10], fill=(255,255,255,255), width=3)
+    elif 'mine' in name:
+        # Draw a person
+        draw.ellipse([cx-15, cy-35, cx+15, cy-5], fill=color)
+        draw.pieslice([cx-30, cy, cx+30, cy+60], 180, 360, fill=color)
+        
+    img.save(filename)
+    print(f"Generated {filename}")
+
+def main():
+    base_dir = r"C:\Users\admin\Desktop\宠物需求\宠物管理系统\performer_app\static\tabbar"
+    if not os.path.exists(base_dir):
+        os.makedirs(base_dir)
+        
+    gray = (153, 153, 153, 255) # #999999
+    orange = (255, 87, 34, 255) # #FF5722
+    
+    create_icon("home", gray, "H", os.path.join(base_dir, "home.png"))
+    create_icon("home-active", orange, "H", os.path.join(base_dir, "home-active.png"))
+    
+    create_icon("order", gray, "O", os.path.join(base_dir, "order.png"))
+    create_icon("order-active", orange, "O", os.path.join(base_dir, "order-active.png"))
+    
+    create_icon("mine", gray, "M", os.path.join(base_dir, "mine.png"))
+    create_icon("mine-active", orange, "M", os.path.join(base_dir, "mine-active.png"))
+
+if __name__ == "__main__":
+    main()

+ 103 - 0
implementation_plan.md

@@ -0,0 +1,103 @@
+# 履约者招募功能实施计划
+
+## 1. 登录页升级 (`src/pages/login/login.vue`)
+- **目标**: 完善 "密码登录" 模式 UI。
+- **变更**:
+    - 在 Tab 切换逻辑中,针对 Index 1 显示密码输入框。
+    - 添加密码输入框右侧 "眼睛" 图标 (切换 `password` 类型)。
+    - 添加 "忘记密码?" 文本链接。
+
+## 2. 招募流程页面开发
+
+### A. 招募落地页 (`src/pages/recruit/landing.vue`) **[已完成]**
+- **UI**: 全屏橙色背景 (`#FF9800`),头部文案居中。
+- **内容**:
+    - 顶部大标题 "加入宠宝履约者"。
+    - 白色悬浮卡片: 展示 3 点核心优势 (收入、灵活、自由),每点配图标 (青/蓝/橙配色)。
+- **交互**: 点击底部 "我要加入" -> 跳转 `src/pages/recruit/form`。
+- **导航**: 自定义导航栏,返回按钮逻辑优化 (支持 fallback)。
+
+### B. 资料填写页 (`src/pages/recruit/form.vue`) **[已完成]**
+- **UI**: 表单列表风格,采用 "Label + 灰色背景输入框" 布局。
+- **字段**:
+    - 手机号 (只读/输入)、验证码。
+    - 姓名 (Input)、性别 (Radio)、生日 (Custom Date Picker)、密码 (Input)。
+    - **服务类型**: 块状多选按钮组 (宠物接送、上门喂遛、上门洗护)。
+    - **工作城市**: Custom City Picker (省市区级联选择)。
+    - **服务站点**: Custom Station Picker (列表选择)。
+- **交互**: 底部勾选协议 + "下一步,实名认证" 按钮跳转至 `auth` 页。
+- **图标**: 线框风格密码图标 (同步登录页)。
+
+### C. 实名认证页 (`src/pages/recruit/auth.vue`)
+- **UI**: 上下分段表单。
+- **字段**:
+    - 证件类型 (固定 "居民身份证"), 真实姓名, 证件号码, 有效日期 (Picker)。
+- **上传**:
+    - 身份证人像面 (上传框示意图)。
+    - 身份证国徽面 (上传框示意图)。
+- **底部**: "下一步,完善资质" 按钮 -> 跳转 `src/pages/recruit/qualifications`。
+
+### D. 资质完善页 (`src/pages/recruit/qualifications.vue`)
+- **UI**:
+    - 顶部提示文案 "根据国家政策要求..."。
+    - **上传列表**: 根据 `form` 页选择的服务类型 (`serviceType` 数组) 动态渲染卡片。
+        - 宠物接送服务资质 / 上门喂遛服务资质 / 上门洗护服务资质。
+        - 每张卡片包含: 标题 + 图片上传框 (支持预览/删除)。
+        - 示例图: 蝴蝶图片 (Mock)。
+- **交互**: 底部 "立即提交" 按钮 -> 跳转 `src/pages/recruit/success`。
+
+### E. 注册成功页 (`src/pages/recruit/success.vue`)
+- **UI**:
+    - 大图标 (绿色对勾) + "报名成功" 标题。
+    - 红色提示文案 "请保持手机畅通..."。
+    - **信息卡片**:
+        - 服务站点: [Mock Data]
+        - 报名人: [Mock Name]
+        - 联系手机: [Mock Phone]
+- **交互**: "我知道了" 按钮 -> 返回首页或登录页。
+
+## 3. 路由配置 (`src/pages.json`)
+- 注册上述 3 个新页面。
+- 确保导航栏标题符合设计图 ("我要加入", "实名认证")。
+
+### [Shared Components]
+#### [NEW] [privacy-popup.vue](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/components/privacy-popup/privacy-popup.vue)
+-   **功能**: 通用协议弹窗
+-   **Props**: `visible`, `title`, `content` (or slot)
+-   **Events**: `close`
+
+### [Login Page]
+#### [MODIFY] [login.vue](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/login/login.vue)
+-   集成 `privacy-popup`,点击“隐私政策”时显示。
+-   **UI修复**: 修复 `+86` 箭头对齐和 `协议复选框` 对齐问题。
+
+### [Forgot Password Flow]
+#### [NEW] [reset-pwd-verify.vue](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/login/reset-pwd-verify.vue)
+-   **参考图2**: "重置密码" - 验证码步骤。
+-   **UI**: 顶部提示文本,验证码输入框 (带"获取验证码"按钮),橙色 "下一步" 按钮。
+
+#### [NEW] [reset-pwd-set.vue](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/login/reset-pwd-set.vue)
+-   **参考图3**: "设置新密码"。
+-   **UI**: 提示文本,两个密码输入框 (新密码 + 确认),橙色 "确定" 按钮。
+
+### [Performer Core Pages]
+#### [CONFIG] [pages.json](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages.json)
+-   配置 TabBar: 任务中心 (Home), 我的订单 (Orders), 我的 (Mine)。
+
+#### [NEW] [pages/home/](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/home/)
+-   **index.vue, logic.js, style.css**: 任务大厅。
+-   **UI**: 顶部统计卡片 (累计接单等),任务列表 (区分接送/喂遛等类型),接单/拒绝按钮。
+
+#### [NEW] [pages/orders/](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/orders/)
+-   **index.vue, logic.js, style.css**: 我的订单。
+-   **UI**: 顶部状态 Tab (待接送/服务中/已完成),订单列表 (带状态操作按钮: 一键拨号/到达打卡)。
+
+#### [NEW] [pages/mine/](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/mine/)
+-   **index.vue, logic.js, style.css**: 个人中心。
+-   **UI**: 用户头部详情(等级/城市),权益卡片(黑金),数据统计(钱包/订单),菜单列表。
+
+### [Recruit Form Page]
+#### [MODIFY] [form.vue](file:///C:/Users/admin/Desktop/宠物需求/宠物管理系统/performer_app/pages/recruit/form.vue)
+-   集成 `privacy-popup`,点击“宠宝履约者说明”时显示。
+
+## Verification Plan

+ 20 - 0
index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="UTF-8" />
+    <script>
+      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+        CSS.supports('top: constant(a)'))
+      document.write(
+        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+    </script>
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

+ 22 - 0
main.js

@@ -0,0 +1,22 @@
+import App from './App'
+
+// #ifndef VUE3
+import Vue from 'vue'
+import './uni.promisify.adaptor'
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+  ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif

+ 72 - 0
manifest.json

@@ -0,0 +1,72 @@
+{
+    "name" : "performer_app",
+    "appid" : "__UNI__F600891",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3"
+}

+ 264 - 0
pages.json

@@ -0,0 +1,264 @@
+{
+	"pages": [
+		{
+			"path": "pages/login/login",
+			"style": {
+				"navigationBarTitleText": "登录",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/recruit/landing",
+			"style": {
+				"navigationBarTitleText": "加入宠宝履约者",
+				"navigationBarBackgroundColor": "#FF9800",
+				"navigationBarTextStyle": "white",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/recruit/form",
+			"style": {
+				"navigationBarTitleText": "我要加入"
+			}
+		},
+		{
+			"path": "pages/recruit/auth",
+			"style": {
+				"navigationBarTitleText": "实名认证"
+			}
+		},
+		{
+			"path": "pages/recruit/qualifications",
+			"style": {
+				"navigationBarTitleText": "我的资质"
+			}
+		},
+		{
+			"path": "pages/recruit/success",
+			"style": {
+				"navigationBarTitleText": "提交成功"
+			}
+		},
+		{
+			"path": "pages/login/reset-pwd-verify",
+			"style": {
+				"navigationBarTitleText": "重置密码"
+			}
+		},
+		{
+			"path": "pages/login/reset-pwd-set",
+			"style": {
+				"navigationBarTitleText": "设置新密码"
+			}
+		},
+		{
+			"path": "pages/home/index",
+			"style": {
+				"navigationBarTitleText": "任务中心",
+				"navigationStyle": "custom",
+				"enablePullDownRefresh": true
+			}
+		},
+		{
+			"path": "pages/home/work-status",
+			"style": {
+				"navigationBarTitleText": "工作状态",
+				"navigationStyle": "default",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/orders/index",
+			"style": {
+				"navigationBarTitleText": "我的订单",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black",
+				"enablePullDownRefresh": true
+			}
+		},
+		{
+			"path": "pages/orders/detail",
+			"style": {
+				"navigationBarTitleText": "订单详情",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/orders/anomaly",
+			"style": {
+				"navigationBarTitleText": "异常上报",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/mine/order-stats",
+			"style": {
+				"navigationBarTitleText": "订单统计",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/mine/rewards",
+			"style": {
+				"navigationBarTitleText": "我的奖惩",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/mine/rewards-all",
+			"style": {
+				"navigationBarTitleText": "收款记录",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/mine/index",
+			"style": {
+				"navigationBarTitleText": "个人中心",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/profile/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/auth/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/bank/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/security/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/profile/edit-name",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/notification/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/settings/about/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/wallet/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/wallet/bill",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/level/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/message/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/message/order",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/message/system",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/message/detail",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/points/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/points/detail",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8"
+	},
+	"tabBar": {
+		"color": "#999999",
+		"selectedColor": "#FF5722",
+		"backgroundColor": "#ffffff",
+		"borderStyle": "black",
+		"list": [
+			{
+				"pagePath": "pages/home/index",
+				"text": "任务中心",
+				"iconPath": "static/tabbar/home.svg",
+				"selectedIconPath": "static/tabbar/home-active.svg"
+			},
+			{
+				"pagePath": "pages/orders/index",
+				"text": "我的订单",
+				"iconPath": "static/tabbar/order.svg",
+				"selectedIconPath": "static/tabbar/order-active.svg"
+			},
+			{
+				"pagePath": "pages/mine/index",
+				"text": "我的",
+				"iconPath": "static/tabbar/mine.svg",
+				"selectedIconPath": "static/tabbar/mine-active.svg"
+			}
+		]
+	},
+	"uniIdRouter": {}
+}

+ 371 - 0
pages/home/index.vue

@@ -0,0 +1,371 @@
+<template>
+	<view class="container">
+		<!-- 自定义导航栏标题 -->
+		<view class="custom-nav-bar" :style="{ backgroundColor: scrollTop > 20 ? '#fff' : 'transparent' }">
+			<text class="nav-title">任务中心</text>
+		</view>
+		<!-- 顶部自定义导航栏背景 -->
+		<!-- 顶部自定义导航栏背景 -->
+		<view class="nav-bg">
+            <view class="bg-circle-left"></view>
+            <view class="bg-circle-right"></view>
+        </view>
+		
+		<!-- 头部用户信息与统计 -->
+		<view class="header-section">
+			<view class="user-info">
+				<image class="avatar" src="/static/touxiang.png" mode="aspectFill"></image>
+				<view class="info-content">
+					<view class="top-row">
+						<text class="name">李海</text>
+						<view class="status-pill" :class="{ 'resting': workStatus === 'resting' }" @click="goToWorkStatus">
+                            <view class="status-dot-bg">
+                                <text class="check-mark" v-if="workStatus === 'working'">✔</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="arrow-down">▼</text>
+						</view>
+					</view>
+					<view class="bottom-row">
+						<text class="city-label">接单城市:武汉市</text>
+						<text class="city-arrow">></text>
+					</view>
+				</view>
+				<view class="notification-box">
+					<image class="bell-img" src="/static/icons/bell.svg"></image>
+					<view class="badge-count">2</view>
+				</view>
+			</view>
+			
+			<!-- 统计卡片 -->
+			<view class="stats-card">
+				<view class="stat-item">
+					<text class="num">2546</text>
+					<text class="label">累计接单</text>
+				</view>
+				<view class="divider"></view>
+				<view class="stat-item">
+					<text class="num">10</text>
+					<text class="label">拒接订单</text></view>
+				<view class="divider"></view>
+				<view class="stat-item">
+					<text class="num">10</text>
+					<text class="label">奖励订单</text>
+				</view>
+				<view class="divider"></view>
+				<view class="stat-item">
+					<text class="num">10</text>
+					<text class="label">惩罚订单</text>
+				</view>
+			</view>
+		</view>
+
+
+		<!-- 任务大厅标题栏 (Sticky Container) -->
+		<view class="task-header">
+            <!-- 标题栏内容 (Inner) -->
+            <view class="header-inner" :style="{ backgroundColor: (scrollTop > 300 || isFilterShow) ? '#fff' : 'transparent' }">
+                <view class="left-title">
+                    <view class="orange-bar"></view>
+                    <text class="title">任务大厅</text>
+                    <text class="count">- ({{ taskList.length }}单)</text>
+                </view>
+                <view class="filter-options">
+                    <view class="filter-item" :class="{ active: currentFilter === 'distance' }" @click="setFilter('distance')">
+                        距离
+                        <view class="sort-icon">
+                            <view class="up" :class="{ active: currentFilter === 'distance' && sortDistance === 'asc' }"></view>
+                            <view class="down" :class="{ active: currentFilter === 'distance' && sortDistance === 'desc' }"></view>
+                        </view>
+                    </view>
+                    <view class="filter-item" :class="{ active: currentFilter === 'time' }" @click="setFilter('time')">
+                        时间
+                        <view class="sort-icon">
+                            <view class="up" :class="{ active: currentFilter === 'time' && sortTime === 'asc' }"></view>
+                            <view class="down" :class="{ active: currentFilter === 'time' && sortTime === 'desc' }"></view>
+                        </view>
+                    </view>
+                    <view class="dropdown" @click="showFilterDropdown">
+                        <text>筛选条件</text>
+                        <text class="arrow-down">﹀</text>
+                    </view>
+                </view>
+            </view>
+
+            <!-- 筛选遮罩 (Absolute Child: Starts below header) -->
+            <view class="filter-mask" v-if="isFilterShow" @click="closeFilter"></view>
+
+            <!-- 筛选下拉面板 (Absolute Child) -->
+            <view class="filter-panel" :class="{ show: isFilterShow }">
+                <view class="filter-section">
+                    <text class="section-title">服务类型</text>
+                    <view class="options-grid">
+                        <view class="option-btn" :class="{ active: tempFilter.service === '全部' }" @click="selectService('全部')">全部</view>
+                        <view class="option-btn" :class="{ active: tempFilter.service === '接送' }" @click="selectService('接送')">接送</view>
+                        <view class="option-btn" :class="{ active: tempFilter.service === '喂遛' }" @click="selectService('喂遛')">喂遛</view>
+                        <view class="option-btn" :class="{ active: tempFilter.service === '洗护' }" @click="selectService('洗护')">洗护</view>
+                    </view>
+                </view>
+
+                <view class="filter-section">
+                    <text class="section-title">距离</text>
+                    <view class="options-grid">
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '全部' }" @click="selectDistance('全部')">全部</view>
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '2公里内' }" @click="selectDistance('2公里内')">2公里内</view>
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '5公里内' }" @click="selectDistance('5公里内')">5公里内</view>
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '10公里内' }" @click="selectDistance('10公里内')">10公里内</view>
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '20公里内' }" @click="selectDistance('20公里内')">20公里内</view>
+                        <view class="option-btn" :class="{ active: tempFilter.distance === '50公里内' }" @click="selectDistance('50公里内')">50公里内</view>
+                    </view>
+                </view>
+
+                <view class="filter-section">
+                    <text class="section-title">金额</text>
+                    <view class="options-grid">
+                        <view class="option-btn" :class="{ active: tempFilter.amount === '全部' }" @click="selectAmount('全部')">全部</view>
+                        <view class="option-btn" :class="{ active: tempFilter.amount === '100以下' }" @click="selectAmount('100以下')">100以下</view>
+                        <view class="option-btn" :class="{ active: tempFilter.amount === '100-200' }" @click="selectAmount('100-200')">100-200</view>
+                        <view class="option-btn" :class="{ active: tempFilter.amount === '200-500' }" @click="selectAmount('200-500')">200-500</view>
+                        <view class="option-btn" :class="{ active: tempFilter.amount === '500以上' }" @click="selectAmount('500以上')">500以上</view>
+                    </view>
+                </view>
+
+                <view class="filter-actions">
+                    <button class="action-btn reset" @click="resetFilter">重置</button>
+                    <button class="action-btn confirm" @click="confirmFilter">确认</button>
+                </view>
+            </view>
+        </view>
+
+        <!-- 列表容器 -->
+        <block v-if="workStatus === 'working'">
+            <!-- 任务列表 -->
+            <scroll-view scroll-y class="task-list">
+                <view class="task-card" v-for="(item, index) in taskList" :key="index" @click="goToDetail(item)">
+                    <view class="card-header">
+                        <view class="type-badge">
+                            <image class="type-icon" :src="item.typeIcon"></image>
+                            <text class="type-text">{{ item.typeText }}</text>
+                        </view>
+                        <text class="price">¥{{ item.price }}</text>
+                    </view>
+                    <view class="card-body">
+                        <view class="time-row">
+                            <text class="label">{{ item.timeLabel }}:</text>
+                            <text class="value">{{ item.time }}</text>
+                        </view>
+                        <view class="pet-card">
+                            <image class="pet-avatar" :src="item.petAvatar" mode="aspectFill"></image>
+                            <view class="pet-info">
+                                <text class="pet-name">{{ item.petName }}</text>
+                                <text class="pet-breed">品种: {{ item.petBreed }}</text>
+                            </view>
+                            <view class="pet-profile-btn" @click.stop="showPetProfile(item)">宠物档案</view>
+                        </view>
+                        
+                        <view class="route-info">
+                            <template v-if="item.type === 1">
+                                <view class="route-item" @click.stop="openNavigation(item, 'start')">
+                                    <view class="icon-circle start">取</view>
+                                    <view class="route-line-vertical"></view>
+                                    <view class="address-box">
+                                        <text class="addr-title">{{ item.startLocation }}</text>
+                                        <text class="addr-desc">{{ item.startAddress }}</text>
+                                    </view>
+                                    <view class="distance-tag">
+                                        <text>{{ item.startDistance }}</text>
+                                        <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                    </view>
+                                </view>
+
+                                <view class="route-item" @click.stop="openNavigation(item, 'end')">
+                                    <view class="icon-circle end">送</view>
+                                    <view class="address-box">
+                                        <text class="addr-title">{{ item.endLocation }}</text>
+                                        <text class="addr-desc">{{ item.endAddress }}</text>
+                                    </view>
+                                    <view class="distance-tag">
+                                        <text>{{ item.endDistance }}</text>
+                                        <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                    </view>
+                                </view>
+                            </template>
+                            <template v-else>
+                                <view class="route-item" @click.stop="openNavigation(item, 'end')">
+                                    <view class="icon-circle service">服</view>
+                                    <view class="address-box">
+                                        <text class="addr-title">{{ item.endLocation }}</text>
+                                        <text class="addr-desc">{{ item.endAddress }}</text>
+                                    </view>
+                                    <view class="distance-tag">
+                                        <text>{{ item.endDistance }}</text>
+                                        <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                    </view>
+                                </view>
+                                <view class="service-content" v-if="item.serviceContent">
+                                    <text class="content-label">服务内容:</text>
+                                    <text>{{ item.serviceContent }}</text>
+                                </view>
+                            </template>
+                        </view>
+
+                        <view class="remark-box" v-if="item.remark">
+                            <text>备注:{{ item.remark }}</text>
+                        </view>
+                    </view>
+                    <!-- action-btns class is in style.css but template used card-footer. style.css: .action-btns, index.vue: .card-footer -->
+                    <!-- Wait, style.css has .action-btns { display: flex; ... } and .btn.reject/accept -->
+                    <!-- I should use .action-btns instead of .card-footer -->
+                    <view class="action-btns">
+                        <button class="btn reject" @click.stop="openRejectModal(item)">拒绝</button>
+                        <button class="btn accept" @click.stop="openAcceptModal(item)">接单</button>
+                    </view>
+                </view>
+                <!-- Padding for safe area/tabbar -->
+                <view style="height: 120rpx;"></view>
+            </scroll-view>
+        </block>
+
+        <!-- 休息中空状态 -->
+        <view class="empty-state" v-else>
+            <image class="empty-icon" src="/static/empty-rest.png" mode="aspectFit"></image>
+            <text class="empty-text">当前处于休息中,暂时无法接单</text>
+            <button class="start-work-btn" @click="startWork">开工接单</button>
+        </view>
+        <!-- 自定义确认弹窗 -->
+        <view class="modal-mask" v-if="showConfirmModal">
+            <view class="custom-modal">
+                <text class="modal-title">提示</text>
+                <text class="modal-content">是否确定结束休息,开始接单?</text>
+                <view class="modal-btns">
+                    <button class="modal-btn cancel" @click="closeConfirmModal">取消</button>
+                    <button class="modal-btn confirm" @click="confirmStartWork">确定</button>
+                </view>
+            </view>
+        </view>
+        <!-- 宠物档案弹窗 -->
+        <view class="pet-modal-mask" v-if="showPetModal" @click="closePetProfile">
+            <view class="pet-modal-content" @click.stop>
+                <view class="pet-modal-header">
+                    <text class="pet-modal-title">宠物档案</text>
+                    <view class="close-icon-btn" @click="closePetProfile">×</view>
+                </view>
+                <scroll-view scroll-y class="pet-modal-scroll">
+                    <!-- Basic Info -->
+                    <view class="pet-base-info">
+                        <image class="pm-avatar" :src="currentPetInfo.petAvatar" mode="aspectFill"></image>
+                        <view class="pm-info-text">
+                            <view class="pm-name-row">
+                                <text class="pm-name">{{ currentPetInfo.petName }}</text>
+                                <!-- Gender badge -->
+                                <view class="pm-gender" v-if="currentPetInfo.petGender === 'M'">
+                                    <text class="gender-icon">♂</text>
+                                    <text>公</text>
+                                </view>
+                                <view class="pm-gender female" v-else-if="currentPetInfo.petGender === 'F'">
+                                    <text class="gender-icon">♀</text>
+                                    <text>母</text>
+                                </view>
+                            </view>
+                            <text class="pm-breed">品种:{{ currentPetInfo.petBreed }}</text>
+                        </view>
+                    </view>
+                    <!-- Details Grid -->
+                    <view class="pm-detail-grid">
+                        <view class="pm-grid-item half">
+                            <text class="pm-label">年龄</text>
+                            <text class="pm-val">{{ currentPetInfo.petAge || '未知' }}</text>
+                        </view>
+                        <view class="pm-grid-item half">
+                            <text class="pm-label">体重</text>
+                            <text class="pm-val">{{ currentPetInfo.petWeight || '未知' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">性格</text>
+                            <text class="pm-val">{{ currentPetInfo.petPersonality || '无' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">爱好</text>
+                            <text class="pm-val">{{ currentPetInfo.petHobby || '无' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">备注</text>
+                            <text class="pm-val">{{ currentPetInfo.petRemark || '无特殊过敏史' }}</text>
+                        </view>
+                    </view>
+                    <!-- Tags -->
+                    <view class="pm-tags" v-if="currentPetInfo.petTags && currentPetInfo.petTags.length > 0">
+                        <view class="pm-tag" v-for="(tag, index) in currentPetInfo.petTags" :key="index">{{ tag }}</view>
+                    </view>
+                    
+                    <!-- Log Section -->
+                    <view class="pm-section-title">
+                        <view class="orange-bar"></view>
+                        <text>备注日志</text>
+                    </view>
+                    <view class="pm-log-list">
+                        <view class="pm-log-item" v-for="(log, lIndex) in currentPetInfo.petLogs" :key="lIndex">
+                            <text class="pm-log-date">{{ log.date }}</text>
+                            <text class="pm-log-text">{{ log.content }}</text>
+                            <text class="pm-log-recorder">{{ log.recorder === '系统记录' ? '' : '记录人: '}}{{ log.recorder }}</text>
+                        </view>
+                    </view>
+                    <view style="height: 40rpx;"></view>
+                    <button class="pm-bottom-close" @click="closePetProfile">关闭</button>
+                    <view style="height: 20rpx;"></view>
+                </scroll-view>
+            </view>
+        </view>
+	</view>
+        
+        <!-- 拒绝接单弹窗 -->
+        <view class="modal-mask" v-if="showRejectModal">
+            <view class="custom-modal">
+                <text class="modal-title">拒绝接单</text>
+                <textarea class="reject-textarea" v-model="rejectReason" placeholder="请输入拒绝理由(必填)" maxlength="100"></textarea>
+                <view class="modal-btns mt-30">
+                    <button class="modal-btn cancel" @click="closeRejectModal">取消</button>
+                    <button class="modal-btn confirm" @click="confirmReject">提交</button>
+                </view>
+            </view>
+        </view>
+
+        <!-- 确认接单弹窗 -->
+        <view class="modal-mask" v-if="showAcceptConfirmModal">
+            <view class="custom-modal">
+                <text class="modal-title">接单确认</text>
+                <view class="modal-content-box">
+                    <text class="modal-content-main">请确认是否接收此订单?</text>
+                    <text class="modal-content-sub">接单后请尽快通过电话联系用户</text>
+                </view>
+                <view class="modal-btns mt-30">
+                    <button class="modal-btn cancel" @click="closeAcceptModal">再想想</button>
+                    <button class="modal-btn confirm" @click="confirmAccept">确认接单</button>
+                </view>
+            </view>
+        </view>
+
+        <!-- 选择地图导航弹窗 -->
+        <view class="nav-modal-mask" v-if="showNavModal" @click="closeNavModal">
+            <view class="nav-action-sheet" @click.stop>
+                <view class="nav-sheet-title">选择地图进行导航</view>
+                <view class="nav-sheet-item" @click="chooseMap('高德')">高德地图</view>
+                <view class="nav-sheet-item" @click="chooseMap('腾讯')">腾讯地图</view>
+                <view class="nav-sheet-item" @click="chooseMap('百度')">百度地图</view>
+                <view class="nav-sheet-gap"></view>
+                <view class="nav-sheet-item cancel" @click="closeNavModal">取消</view>
+            </view>
+        </view>
+</template>
+
+<script>
+import logic from './logic.js';
+export default {
+	...logic
+}
+</script>
+
+<style>
+@import './style.css';
+</style>

+ 295 - 0
pages/home/logic.js

@@ -0,0 +1,295 @@
+export default {
+    data() {
+        return {
+            taskList: [],
+            currentFilter: 'default', // default, distance, time
+            filterCondition: '筛选条件',
+            sortDistance: 'asc', // asc, desc
+            sortTime: 'asc',
+            scrollTop: 0, // Track scroll position
+            isFilterShow: false,
+            tempFilter: {
+                service: '全部',
+                distance: '全部',
+                amount: '全部'
+            },
+            activeFilter: {
+                service: '全部',
+                distance: '全部',
+                amount: '全部'
+            },
+            workStatus: 'working', // working | resting
+            showConfirmModal: false,
+            showPetModal: false,
+            currentPetInfo: {},
+            showRejectModal: false,
+            rejectReason: '',
+            currentOrder: null,
+            showAcceptConfirmModal: false,
+            showNavModal: false,
+            navTargetItem: null,
+            navTargetPointType: ''
+        }
+    },
+    onPageScroll(e) {
+        this.scrollTop = e.scrollTop;
+    },
+    onLoad() {
+        // Initial load
+        this.checkWorkStatus();
+        this.loadTaskList();
+    },
+    onShow() {
+        // Update status when returning from other pages
+        this.checkWorkStatus();
+    },
+    methods: {
+        checkWorkStatus() {
+            const status = uni.getStorageSync('workStatus');
+            if (status) {
+                this.workStatus = status;
+            } else {
+                // Default to working if not set
+                this.workStatus = 'working';
+                uni.setStorageSync('workStatus', 'working');
+            }
+        },
+        toggleFilter() {
+            if (this.workStatus === 'resting') return; // Disable filter when resting? Or keep it? User didn't specify, but usually disabled. Let's keep it enabled for now as they might look at filters before working.
+            this.isFilterShow = !this.isFilterShow;
+        },
+        goToWorkStatus() {
+            uni.navigateTo({
+                url: '/pages/home/work-status'
+            });
+        },
+        startWork() {
+            this.showConfirmModal = true;
+        },
+        confirmStartWork() {
+            this.workStatus = 'working';
+            uni.setStorageSync('workStatus', 'working');
+            this.loadTaskList();
+            this.showConfirmModal = false;
+            uni.showToast({ title: '已开始接单', icon: 'success' });
+        },
+        closeConfirmModal() {
+            this.showConfirmModal = false;
+        },
+        showPetProfile(item) {
+            this.currentPetInfo = item;
+            this.showPetModal = true;
+        },
+        closePetProfile() {
+            this.showPetModal = false;
+        },
+        openRejectModal(item) {
+            this.currentOrder = item;
+            this.rejectReason = '';
+            this.showRejectModal = true;
+        },
+        closeRejectModal() {
+            this.showRejectModal = false;
+            this.currentOrder = null;
+        },
+        confirmReject() {
+            if (!this.rejectReason.trim()) {
+                uni.showToast({ title: '请输入拒绝理由', icon: 'none' });
+                return;
+            }
+            // Add actual API call here
+            uni.showToast({ title: '已拒绝接单', icon: 'success' });
+            this.showRejectModal = false;
+        },
+        openAcceptModal(item) {
+            this.currentOrder = item;
+            this.showAcceptConfirmModal = true;
+        },
+        closeAcceptModal() {
+            this.showAcceptConfirmModal = false;
+            this.currentOrder = null;
+        },
+        confirmAccept() {
+            // Add actual API call here
+            uni.showToast({ title: '接单成功', icon: 'success' });
+            this.showAcceptConfirmModal = false;
+        },
+        openNavigation(item, pointType) {
+            this.navTargetItem = item;
+            this.navTargetPointType = pointType;
+            this.showNavModal = true;
+        },
+        closeNavModal() {
+            this.showNavModal = false;
+        },
+        chooseMap(mapType) {
+            let item = this.navTargetItem;
+            let pointType = this.navTargetPointType;
+            let name = pointType === 'start' ? item.startLocation : item.endLocation;
+            let address = pointType === 'start' ? item.startAddress : item.endAddress;
+
+            this.showNavModal = false;
+
+            uni.openLocation({
+                latitude: 30.52, // Mock lat
+                longitude: 114.31, // Mock lng
+                name: name || '目的地',
+                address: address || '默认地址',
+                success: function () {
+                    console.log('打开导航成功: ' + mapType);
+                }
+            });
+        },
+        selectService(type) {
+            this.tempFilter.service = type;
+        },
+        selectDistance(type) {
+            this.tempFilter.distance = type;
+        },
+        selectAmount(type) {
+            this.tempFilter.amount = type;
+        },
+        resetFilter() {
+            this.tempFilter = {
+                service: '全部',
+                distance: '全部',
+                amount: '全部'
+            };
+        },
+        confirmFilter() {
+            this.activeFilter = { ...this.tempFilter };
+            this.isFilterShow = false;
+            uni.showToast({ title: '筛选已生效', icon: 'none' });
+            // Add filtering logic here if needed
+        },
+        closeFilter() {
+            this.isFilterShow = false;
+        },
+        goToDetail(item) {
+            console.log('Go to detail', item);
+        },
+        loadTaskList() {
+            this.taskList = [
+                {
+                    type: 1, // 接送
+                    typeText: '接送',
+                    typeIcon: '/static/icons/car.svg', // Ensure this is the yellow car icon
+                    price: '20.00',
+                    timeLabel: '取货时间',
+                    time: '2026/02/10 10:00',
+                    petAvatar: '/static/dog.png',
+                    petName: '哈士奇宝宝',
+                    petBreed: '哈士奇',
+                    petGender: 'M',
+                    petAge: '2岁',
+                    petWeight: '12kg',
+                    petPersonality: '活泼好动,亲人',
+                    petHobby: '喜欢追球,爱吃鸡胸肉',
+                    petRemark: '无特殊过敏史',
+                    petTags: ['已免疫', '已绝育', '性格温顺'],
+                    petLogs: [
+                        { date: '2026/01/15', content: '左后腿有点敏感,剪指甲时要注意。', recorder: '李海' },
+                        { date: '2025/12/28', content: '今天便便正常,精神很好。', recorder: '张三' },
+                        { date: '2025/10/11', content: '模拟更多备注数据,测试吸顶滚动效果 1...', recorder: '系统记录' },
+                        { date: '2025/10/12', content: '模拟更多备注数据,测试吸顶滚动效果 2...', recorder: '系统记录' }
+                    ],
+                    startLocation: '武汉大学宠物店',
+                    startAddress: '武汉市洪山区珞喻路458号',
+                    startDistance: '0.5km',
+                    endLocation: '张** 189****8451',
+                    endAddress: '武汉市武昌区新区大道凤凰广场A座一楼25号',
+                    endDistance: '2.5km',
+                    remark: '这里是订单备注信息。'
+                },
+                {
+                    type: 2, // 喂遛
+                    typeText: '喂遛',
+                    typeIcon: '/static/icons/walk.svg', // Ensure this is the orange walk icon
+                    price: '35.00',
+                    timeLabel: '服务时间',
+                    time: '2026/02/11 14:00',
+                    petAvatar: '/static/dog.png',
+                    petName: '金毛',
+                    petBreed: '金毛寻回犬',
+                    petGender: 'F',
+                    petAge: '3岁',
+                    petWeight: '25kg',
+                    petPersonality: '温顺,听话',
+                    petHobby: '喜欢玩飞盘',
+                    petRemark: '暂无',
+                    petTags: ['已免疫', '未绝育'],
+                    petLogs: [],
+                    // Walking order typically has a service address (destination)
+                    endLocation: '王女士 138****1234',
+                    endAddress: '武汉市江汉区泛海国际居住区',
+                    endDistance: '1.2km',
+                    serviceContent: '需自带牵引绳,遛弯30分钟。',
+                    remark: '狗狗比较活泼,请注意安全。'
+                },
+                {
+                    type: 3, // 洗护
+                    typeText: '洗护',
+                    typeIcon: '/static/icons/wash.svg',
+                    price: '50.00',
+                    timeLabel: '服务时间',
+                    time: '2026/02/12 09:30',
+                    petAvatar: '/static/dog.png', // Or cat avatar if available
+                    petName: 'Mimi',
+                    petBreed: '布偶猫',
+                    petGender: 'F',
+                    petAge: '1.5岁',
+                    petWeight: '5kg',
+                    petPersonality: '胆小,怕生',
+                    petHobby: '喜欢梳毛',
+                    petRemark: '对水敏感',
+                    petTags: ['已免疫'],
+                    petLogs: [],
+                    endLocation: '赵先生 159****9876',
+                    endAddress: '武汉市汉阳区钟家村',
+                    endDistance: '3.0km',
+                    serviceContent: '上门洗澡,剪指甲。',
+                    remark: '猫咪有点怕生。'
+                },
+                {
+                    type: 1, // 接送 (Repeat for demo)
+                    typeText: '接送',
+                    typeIcon: '/static/icons/car.svg',
+                    price: '25.00',
+                    timeLabel: '取货时间',
+                    time: '2026/02/13 11:00',
+                    petAvatar: '/static/dog.png',
+                    petName: '柯基',
+                    petBreed: '柯基犬',
+                    petGender: 'M',
+                    petAge: '2岁',
+                    petWeight: '10kg',
+                    petPersonality: '活泼',
+                    petHobby: '散步',
+                    petRemark: '',
+                    petTags: [],
+                    petLogs: [],
+                    startLocation: '宠物医院',
+                    startAddress: '武汉市武昌区中南路',
+                    startDistance: '1.0km',
+                    endLocation: '李小姐 136****5678',
+                    endAddress: '武汉市武昌区积玉桥',
+                    endDistance: '4.5km',
+                    remark: '请带上笼子。'
+                }
+            ]
+        },
+        setFilter(type) {
+            this.currentFilter = type;
+            if (type === 'distance') {
+                this.sortDistance = this.sortDistance === 'asc' ? 'desc' : 'asc';
+                uni.showToast({ title: `按距离${this.sortDistance === 'asc' ? '升序' : '降序'}`, icon: 'none' });
+            } else if (type === 'time') {
+                this.sortTime = this.sortTime === 'asc' ? 'desc' : 'asc';
+                uni.showToast({ title: `按时间${this.sortTime === 'asc' ? '升序' : '降序'}`, icon: 'none' });
+            }
+        },
+        showFilterDropdown() {
+            this.toggleFilter();
+        }
+    }
+}

+ 1247 - 0
pages/home/style.css

@@ -0,0 +1,1247 @@
+/* Global Box Sizing Fix */
+view,
+text,
+image,
+scroll-view,
+button {
+    box-sizing: border-box;
+}
+
+/* 页面背景 */
+page {
+    background-color: #F8F8F8;
+}
+
+.container {
+    padding-bottom: 30rpx;
+}
+
+/* 顶部背景 */
+.nav-bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 310rpx;
+    /* Reduced by another 20rpx */
+    background: linear-gradient(180deg, #FFE0B2 0%, #FFF3E0 100%);
+    border-bottom-left-radius: 60rpx;
+    border-bottom-right-radius: 60rpx;
+    z-index: 1;
+    overflow: hidden;
+}
+
+/* Custom Navigation Bar */
+.custom-nav-bar {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    z-index: 100;
+    padding-top: var(--status-bar-height);
+    height: 88rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+/* 头部区域 */
+.header-section {
+    position: relative;
+    z-index: 2;
+    padding: 88rpx 30rpx 0;
+}
+
+/* 用户信息 */
+.user-info {
+    display: flex;
+    align-items: center;
+    margin-bottom: 40rpx;
+}
+
+.avatar {
+    width: 100rpx;
+    height: 100rpx;
+    border-radius: 50%;
+    margin-right: 24rpx;
+    border: 4rpx solid #fff;
+    box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.1);
+}
+
+.info-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.top-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8rpx;
+}
+
+.name {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 16rpx;
+}
+
+/* 状态胶囊 */
+.status-pill {
+    background-color: #4E4E4E;
+    border-radius: 24rpx;
+    display: flex;
+    align-items: center;
+    padding: 2rpx 20rpx 2rpx 6rpx;
+    /* Increased right/left padding to elongate */
+}
+
+.status-dot-bg {
+    width: 24rpx;
+    /* Smaller icon bg */
+    height: 24rpx;
+    background-color: #00E676;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 6rpx;
+}
+
+.check-mark {
+    color: #fff;
+    font-size: 14rpx;
+    /* Smaller check */
+    font-weight: bold;
+}
+
+.status-text {
+    color: #fff;
+    font-size: 22rpx;
+    /* Smaller font (11pt) */
+    margin-right: 6rpx;
+    font-weight: normal;
+}
+
+.status-pill .arrow-down {
+    color: #fff;
+    font-size: 10rpx;
+    /* Half size */
+}
+
+.bottom-row {
+    display: flex;
+    align-items: center;
+    font-size: 24rpx;
+    color: #333;
+}
+
+.city-label {
+    margin-right: 4rpx;
+}
+
+.city-arrow {
+    font-family: monospace;
+}
+
+/* 通知铃铛 */
+.notification-box {
+    position: relative;
+    width: 60rpx;
+    height: 60rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.bell-img {
+    width: 44rpx;
+    height: 44rpx;
+}
+
+.badge-count {
+    position: absolute;
+    top: -4rpx;
+    right: -4rpx;
+    background-color: #FF5252;
+    color: #fff;
+    font-size: 20rpx;
+    width: 32rpx;
+    height: 32rpx;
+    line-height: 32rpx;
+    text-align: center;
+    border-radius: 50%;
+    border: 2rpx solid #fff;
+}
+
+/* 统计卡片 - 悬浮样式 */
+.stats-card {
+    background-color: #fff;
+    border-radius: 30rpx;
+    padding: 30rpx 0;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
+    margin-bottom: 10rpx;
+    /* 10rpx spacing to task header */
+    margin-top: -10rpx;
+    position: relative;
+    width: 100%;
+}
+
+.stat-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    flex: 1;
+}
+
+.num {
+    font-size: 40rpx;
+    /* Increased font size */
+    font-weight: 800;
+    color: #333;
+    margin-bottom: 10rpx;
+    font-family: Arial, sans-serif;
+}
+
+.label {
+    font-size: 24rpx;
+    color: #888;
+}
+
+.divider {
+    width: 1px;
+    height: 40rpx;
+    background-color: #EEEEEE;
+}
+
+/* 任务大厅标题栏 - 吸顶容器 */
+.task-header {
+    position: sticky;
+    top: calc(88rpx + var(--status-bar-height));
+    z-index: 90;
+    margin-top: 0;
+    margin-bottom: 10rpx;
+    width: 100%;
+    /* Flex removed, padding removed, handled by inner */
+}
+
+/* 标题栏内部内容 */
+.header-inner {
+    position: relative;
+    z-index: 3;
+    /* Layer 3: Topmost */
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 94rpx;
+    padding: 0 30rpx;
+    background-color: transparent;
+    transition: background-color 0.2s;
+}
+
+.left-title {
+    display: flex;
+    align-items: center;
+}
+
+.orange-bar {
+    width: 8rpx;
+    height: 32rpx;
+    background-color: #FF5722;
+    border-radius: 4rpx;
+    margin-right: 15rpx;
+}
+
+.left-title .title {
+    font-size: 28rpx;
+    font-weight: 900;
+    color: #333;
+    font-style: italic;
+}
+
+.left-title .count {
+    font-size: 24rpx;
+    color: #999;
+    margin-left: 8rpx;
+    font-weight: normal;
+}
+
+.filter-options {
+    display: flex;
+    align-items: center;
+    font-size: 24rpx;
+    color: #666;
+}
+
+.filter-item {
+    margin-left: 30rpx;
+    transition: color 0.3s;
+    display: flex;
+    align-items: center;
+}
+
+.filter-item.active {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+/* Sort Icon Design: Up and Down arrows */
+.sort-icon {
+    display: flex;
+    flex-direction: column;
+    margin-left: 6rpx;
+    justify-content: center;
+    height: 20rpx;
+}
+
+.sort-icon .up {
+    width: 0;
+    height: 0;
+    border-left: 6rpx solid transparent;
+    border-right: 6rpx solid transparent;
+    border-bottom: 6rpx solid #ccc;
+    margin-bottom: 2rpx;
+}
+
+.sort-icon .down {
+    width: 0;
+    height: 0;
+    border-left: 6rpx solid transparent;
+    border-right: 6rpx solid transparent;
+    border-top: 6rpx solid #ccc;
+}
+
+.filter-item.active .sort-icon .up.active {
+    border-bottom-color: #FF5722;
+}
+
+.filter-item.active .sort-icon .down.active {
+    border-top-color: #FF5722;
+}
+
+.dropdown {
+    display: flex;
+    align-items: center;
+    margin-left: 30rpx;
+    background-color: transparent;
+    padding: 6rpx 20rpx;
+    border-radius: 30rpx;
+    border: none;
+    box-shadow: none;
+}
+
+.dropdown text {
+    margin-left: 0;
+    font-size: 24rpx;
+    color: #333;
+}
+
+.dropdown .arrow-down {
+    font-size: 18rpx;
+    margin-left: 6rpx;
+    color: #999;
+}
+
+/* 任务大厅列表 */
+.task-list {
+    padding: 0 30rpx;
+    width: 100%;
+}
+
+/* 任务卡片优化 */
+.task-card {
+    background-color: #fff;
+    border-radius: 24rpx;
+    padding: 20rpx 20rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.04);
+    width: 100%;
+}
+
+.card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 15rpx;
+}
+
+.type-badge {
+    display: flex;
+    align-items: center;
+}
+
+.type-icon {
+    width: 44rpx;
+    height: 44rpx;
+    margin-right: 15rpx;
+    background-color: #FFF3E0;
+    border-radius: 50%;
+    padding: 6rpx;
+    box-sizing: border-box;
+}
+
+.type-text {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.price {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #FF5252;
+}
+
+.time-row {
+    font-size: 26rpx;
+    color: #666;
+    margin-bottom: 20rpx;
+}
+
+.time-row .value {
+    color: #333;
+    margin-left: 10rpx;
+}
+
+/* 宠物卡片 */
+.pet-card {
+    background-color: #FFF8F0;
+    border-radius: 16rpx;
+    padding: 15rpx 20rpx;
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.pet-avatar {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+}
+
+.pet-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pet-name {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 5rpx;
+}
+
+.pet-breed {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.pet-profile-btn {
+    font-size: 24rpx;
+    color: #FF9800;
+    border: 1px solid #FF9800;
+    padding: 6rpx 20rpx;
+    border-radius: 50rpx;
+    background-color: #fff;
+}
+
+/* 路线信息 */
+.route-info {
+    margin-bottom: 20rpx;
+}
+
+.route-item {
+    display: flex;
+    align-items: flex-start;
+    padding-bottom: 12rpx;
+    /* Radically reduced for compactness */
+    position: relative;
+    width: 100%;
+}
+
+/* 路线项底部的间隔 */
+.route-item:not(:last-child) {
+    margin-bottom: 5rpx;
+    /* Radically reduced for compactness */
+}
+
+.route-item:last-child {
+    padding-bottom: 0;
+    margin-bottom: 0;
+}
+
+.route-line-vertical {
+    position: absolute;
+    left: 19rpx;
+    top: 46rpx;
+    bottom: -15rpx;
+    /* Adjusted to connect the now-closer nodes */
+    border-left: 2rpx dashed #E0E0E0;
+    width: 0;
+    z-index: 0;
+}
+
+.icon-circle {
+    width: 40rpx;
+    height: 40rpx;
+    border-radius: 50%;
+    color: #fff;
+    font-size: 22rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+    font-weight: bold;
+    margin-top: 6rpx;
+    position: relative;
+    z-index: 1;
+    /* Above line */
+}
+
+.icon-circle.start {
+    background-color: #FFB74D;
+}
+
+.icon-circle.end {
+    background-color: #81C784;
+}
+
+.icon-circle.service {
+    background-color: #81C784;
+}
+
+.address-box {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    padding-right: 20rpx;
+    width: 0;
+}
+
+.addr-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 6rpx;
+}
+
+.addr-desc {
+    font-size: 24rpx;
+    color: #999;
+    line-height: normal;
+}
+
+.distance-tag {
+    display: flex;
+    align-items: center;
+    background-color: #FFF3E0;
+    padding: 6rpx 6rpx 6rpx 12rpx;
+    border-radius: 30rpx;
+    flex-shrink: 0;
+}
+
+.distance-tag text {
+    font-size: 24rpx;
+    color: #FF5722;
+    margin-right: 5rpx;
+    font-weight: normal;
+}
+
+.nav-arrow {
+    width: 32rpx;
+    height: 32rpx;
+}
+
+.service-content {
+    margin-top: -10rpx;
+    /* Shifted up using negative margin for max compactness */
+    font-size: 24rpx;
+    /* 12pt */
+    color: #666;
+    padding-left: 60rpx;
+}
+
+.content-label {
+    color: #999;
+    margin-right: 10rpx;
+}
+
+/* 备注 */
+.remark-box {
+    background-color: #F8F8F8;
+    padding: 15rpx 20rpx;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+    color: #666;
+    margin-bottom: 20rpx;
+}
+
+/* 按钮组 */
+.action-btns {
+    display: flex;
+    justify-content: space-between;
+}
+
+.btn {
+    height: 64rpx;
+    /* Increased height */
+    line-height: 64rpx;
+    border-radius: 32rpx;
+    /* Matches height/2 */
+    font-size: 28rpx;
+    /* Slightly larger */
+    font-weight: normal;
+    width: 48%;
+}
+
+.btn::after {
+    border: none;
+}
+
+.btn.reject {
+    background-color: #F5F5F5;
+    color: #999;
+    box-shadow: none;
+}
+
+.btn.accept {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.3);
+}
+
+.bg-circle-right {
+    position: absolute;
+    top: -20rpx;
+    right: -20rpx;
+    width: 185rpx;
+    /* +20rpx */
+    height: 185rpx;
+    /* +20rpx */
+    border-radius: 50%;
+    background-color: rgba(255, 218, 185, 0.8);
+    /* 80% opacity */
+}
+
+/* 筛选面板 (Absolute Child) */
+.filter-panel {
+    position: absolute;
+    /* Relative to .task-header */
+    top: 94rpx;
+    /* Start right below header */
+    left: 0;
+    width: 100%;
+    background-color: #fff;
+    z-index: 2;
+    /* Layer 2: Below inner(3), Above mask(1) */
+    padding: 30rpx 30rpx 40rpx;
+    border-bottom-left-radius: 30rpx;
+    border-bottom-right-radius: 30rpx;
+    box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
+    transform: translateY(-20rpx);
+    /* Slightly tucked start */
+    opacity: 0;
+    transition: all 0.25s ease-out;
+    visibility: hidden;
+}
+
+.filter-panel.show {
+    transform: translateY(0);
+    opacity: 1;
+    visibility: visible;
+}
+
+/* 筛选遮罩 (Absolute Child) */
+.filter-mask {
+    position: absolute;
+    top: 94rpx;
+    /* Start below header */
+    left: 0;
+    right: 0;
+    height: 100vh;
+    /* Cover visible area below */
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 1;
+    /* Layer 1: Lowest in header */
+}
+
+.filter-section {
+    margin-bottom: 40rpx;
+}
+
+.section-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 20rpx;
+    display: block;
+}
+
+.options-grid {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+}
+
+.option-btn {
+    width: calc(33.33% - 14rpx);
+    /* 3 cols with gap */
+    height: 64rpx;
+    line-height: 64rpx;
+    text-align: center;
+    border-radius: 32rpx;
+    font-size: 26rpx;
+    color: #666;
+    background-color: #fff;
+    border: 2rpx solid #E0E0E0;
+    margin-bottom: 10rpx;
+}
+
+.option-btn.active {
+    color: #FF5722;
+    background-color: #FFF3E0;
+    border-color: #FF5722;
+    font-weight: bold;
+}
+
+.filter-actions {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 50rpx;
+}
+
+.action-btn {
+    width: 48%;
+    height: 64rpx;
+    /* Match .btn */
+    line-height: 64rpx;
+    border-radius: 32rpx;
+    /* Match .btn */
+    font-size: 28rpx;
+    /* Match .btn */
+    font-weight: normal;
+    /* Match .btn */
+}
+
+.action-btn::after {
+    border: none;
+}
+
+.action-btn.reset {
+    background-color: #F5F5F5;
+    color: #999;
+    /* Match light gray */
+}
+
+.action-btn.confirm {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.3);
+}
+
+/* 状态胶囊 */
+.status-pill {
+    display: flex;
+    align-items: center;
+    background-color: #333333;
+    /* Dark background */
+    border-radius: 20rpx;
+    padding: 4rpx 16rpx 4rpx 8rpx;
+    margin-left: 16rpx;
+    transition: background-color 0.3s;
+}
+
+.status-pill.resting {
+    background-color: #424242;
+    /* Slightly lighter dark */
+}
+
+.status-dot-bg {
+    width: 24rpx;
+    height: 24rpx;
+    background-color: #4CAF50;
+    border-radius: 50%;
+    margin-right: 6rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.check-mark {
+    color: #fff;
+    font-size: 14rpx;
+    font-weight: bold;
+}
+
+.status-pill.resting .status-dot-bg {
+    background-color: #FF5722;
+    /* Warning color for resting */
+}
+
+.status-icon {
+    width: 24rpx;
+    height: 24rpx;
+    margin-right: 6rpx;
+}
+
+.status-text {
+    font-size: 22rpx;
+    color: #fff;
+    margin-right: 6rpx;
+}
+
+.status-pill .arrow-down {
+    color: #fff;
+    font-size: 10rpx;
+    /* Reduced size */
+    margin-left: 4rpx;
+    /* Adjust spacing */
+}
+
+/* 空状态 - 休息中 */
+.empty-state {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding-top: 150rpx;
+}
+
+.empty-icon {
+    width: 200rpx;
+    height: 200rpx;
+    margin-bottom: 40rpx;
+    opacity: 0.5;
+}
+
+.empty-text {
+    font-size: 28rpx;
+    color: #666;
+    margin-bottom: 60rpx;
+}
+
+.start-work-btn {
+    width: 300rpx;
+    height: 80rpx;
+    line-height: 80rpx;
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    border-radius: 40rpx;
+    color: #fff;
+    font-size: 30rpx;
+    font-weight: bold;
+    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.3);
+}
+
+
+/* 自定义确认弹窗 */
+.modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.custom-modal {
+    width: 600rpx;
+    background-color: #fff;
+    border-radius: 24rpx;
+    padding: 40rpx 50rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.modal-title {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 30rpx;
+}
+
+.modal-content {
+    font-size: 30rpx;
+    color: #666;
+    margin-bottom: 50rpx;
+    text-align: center;
+}
+
+.modal-btns {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+}
+
+.modal-btn {
+    width: 45%;
+    height: 80rpx;
+    line-height: 80rpx;
+    border-radius: 40rpx;
+    font-size: 30rpx;
+    font-weight: bold;
+    margin: 0;
+}
+
+.modal-btn::after {
+    border: none;
+}
+
+.modal-btn.cancel {
+    background-color: #F5F5F5;
+    color: #999;
+}
+
+.modal-btn.confirm {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.3);
+}
+
+/* 宠物档案弹窗 */
+.pet-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.4);
+    z-index: 1000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.pet-modal-content {
+    width: 680rpx;
+    height: 85vh;
+    background-color: #fff;
+    border-radius: 20rpx;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+}
+
+.pet-modal-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 30rpx;
+    border-bottom: 1rpx solid #F0F0F0;
+}
+
+.pet-modal-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pet-modal-scroll {
+    flex: 1;
+    height: 0;
+    padding: 30rpx;
+    box-sizing: border-box;
+}
+
+.pet-base-info {
+    display: flex;
+    align-items: center;
+    margin-bottom: 40rpx;
+}
+
+.pm-avatar {
+    width: 120rpx;
+    height: 120rpx;
+    border-radius: 50%;
+    margin-right: 30rpx;
+    border: 2rpx solid #f5f5f5;
+}
+
+.pm-info-text {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-name-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15rpx;
+}
+
+.pm-name {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 20rpx;
+}
+
+.pm-gender {
+    display: flex;
+    align-items: center;
+    background-color: #E3F2FD;
+    padding: 4rpx 12rpx;
+    border-radius: 20rpx;
+}
+
+.pm-gender text {
+    font-size: 22rpx;
+    color: #1E88E5;
+}
+
+.pm-gender .gender-icon {
+    font-weight: bold;
+    margin-right: 4rpx;
+}
+
+.pm-gender.female {
+    background-color: #FCE4EC;
+}
+
+.pm-gender.female text {
+    color: #D81B60;
+}
+
+.pm-breed {
+    font-size: 26rpx;
+    color: #999;
+}
+
+.pm-detail-grid {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+}
+
+.pm-grid-item {
+    background-color: #F8F8F8;
+    border-radius: 16rpx;
+    padding: 24rpx;
+    margin-bottom: 20rpx;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-grid-item.half {
+    width: 48%;
+    box-sizing: border-box;
+}
+
+.pm-grid-item.full {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.pm-label {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 10rpx;
+}
+
+.pm-val {
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+
+.pm-tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+    margin-bottom: 40rpx;
+}
+
+.pm-tag {
+    background-color: #FFF8EB;
+    border: 2rpx solid #FFCC80;
+    color: #FF9800;
+    font-size: 22rpx;
+    padding: 8rpx 24rpx;
+    border-radius: 30rpx;
+}
+
+.pm-section-title {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+    padding-top: 30rpx;
+    border-top: 2rpx dashed #F0F0F0;
+}
+
+.pm-section-title .orange-bar {
+    width: 8rpx;
+    height: 32rpx;
+    background-color: #FF9800;
+    margin-right: 16rpx;
+    border-radius: 4rpx;
+}
+
+.pm-section-title text {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pm-log-list {
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-log-item {
+    display: flex;
+    flex-direction: column;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #F0F0F0;
+}
+
+.pm-log-item:last-child {
+    border-bottom: none;
+}
+
+.pm-log-date {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 16rpx;
+}
+
+.pm-log-text {
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.6;
+    margin-bottom: 20rpx;
+}
+
+.pm-log-recorder {
+    font-size: 24rpx;
+    color: #FF9800;
+    align-self: flex-end;
+}
+
+/* 拒绝接单弹窗输入框 */
+.reject-textarea {
+    width: 100%;
+    height: 200rpx;
+    background-color: #F8F8F8;
+    border-radius: 12rpx;
+    padding: 24rpx;
+    font-size: 28rpx;
+    line-height: 1.5;
+    box-sizing: border-box;
+    margin-bottom: 20rpx;
+}
+
+.mt-30 {
+    margin-top: 30rpx;
+}
+
+/* 宠物档案底部关闭按钮 */
+.pm-bottom-close {
+    width: 100%;
+    height: 80rpx;
+    line-height: 80rpx;
+    background-color: #F5F5F5;
+    color: #666;
+    border-radius: 40rpx;
+    font-size: 30rpx;
+    font-weight: bold;
+    margin: 0;
+}
+
+.pm-bottom-close::after {
+    border: none;
+}
+
+/* 宠物档案原生关闭图标 */
+.close-icon-btn {
+    font-size: 48rpx;
+    color: #999;
+    line-height: 1;
+    padding: 0 10rpx;
+}
+
+/* 确认接单弹窗内容 */
+.modal-content-box {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.modal-content-main {
+    font-size: 30rpx;
+    color: #333;
+    margin-bottom: 16rpx;
+}
+
+.modal-content-sub {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 地图导航 Action Sheet */
+.nav-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 1000;
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-end;
+}
+
+.nav-action-sheet {
+    background-color: #fff;
+    width: 100%;
+    border-top-left-radius: 24rpx;
+    border-top-right-radius: 24rpx;
+    overflow: hidden;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+
+.nav-sheet-title {
+    text-align: center;
+    padding: 30rpx 0;
+    font-size: 13px;
+    color: #999;
+    border-bottom: 1rpx solid #efefef;
+}
+
+.nav-sheet-item {
+    text-align: center;
+    padding: 30rpx 0;
+    font-size: 13px;
+    color: #333;
+    background-color: #fff;
+    border-bottom: 1rpx solid #efefef;
+}
+
+.nav-sheet-item.cancel {
+    border-bottom: none;
+    color: #666;
+}
+
+.nav-sheet-gap {
+    height: 16rpx;
+    background-color: #F8F8F8;
+}

+ 210 - 0
pages/home/work-status.vue

@@ -0,0 +1,210 @@
+<template>
+    <view class="container">
+        <!-- 挂牌看板区域 -->
+        <view class="signboard-container">
+            <view class="rope"></view>
+            <view class="nail"></view>
+            <view class="board" :class="{ 'resting': status === 'resting' }">
+                <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>
+                </view>
+            </view>
+        </view>
+
+        <!-- 状态描述 -->
+        <view class="status-desc">
+            <text>{{ status === 'working' ? '当前处于工作接单中,正常接收新订单' : '当前处于休息状态,暂停接收新订单' }}</text>
+        </view>
+
+        <!-- 操作按钮 -->
+        <view class="action-area">
+            <button class="action-btn" :class="{ 'stop': status === 'working', 'stopped': status === 'resting' }" @click="toggleStatus">
+                {{ status === 'working' ? '停止接单' : '已停止接单' }}
+            </button>
+            <view class="tips">
+                <text v-if="status === 'working'">当您希望长时间不再接收订单时,请点击上方按钮停止接单,开启后需手动恢复。</text>
+                <text v-else>点击上方按钮恢复接单,开始接收新的任务推送。</text>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            status: 'working' // working | resting
+        }
+    },
+    onShow() {
+        // 从本地存储获取状态
+        const savedStatus = uni.getStorageSync('workStatus');
+        if (savedStatus) {
+            this.status = savedStatus;
+        }
+    },
+    methods: {
+        toggleStatus() {
+            if (this.status === 'working') {
+                // 切换到休息
+                this.status = 'resting';
+                uni.setStorageSync('workStatus', 'resting');
+                // 图3显示依然有按钮只是置灰,或者变为"已停止接单"
+            } else {
+                // 切换回接单
+                this.status = 'working';
+                uni.setStorageSync('workStatus', 'working');
+            }
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #fff;
+}
+.container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding-top: 100rpx;
+}
+
+/* 挂牌动画区域 */
+.signboard-container {
+    position: relative;
+    width: 400rpx;
+    height: 300rpx;
+    display: flex;
+    justify-content: center;
+    margin-bottom: 60rpx;
+}
+
+.rope {
+    position: absolute;
+    top: 0;
+    width: 200rpx;
+    height: 100rpx;
+    border-top: 4rpx solid #FFC107; /* Yellow rope */
+    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
+    z-index: 1;
+}
+
+.nail {
+    position: absolute;
+    top: -10rpx;
+    width: 24rpx;
+    height: 24rpx;
+    background-color: #FFC107;
+    border-radius: 50%;
+    z-index: 2;
+    box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.2);
+}
+
+.board {
+    position: absolute;
+    top: 80rpx;
+    width: 360rpx;
+    height: 200rpx;
+    background-color: #FF7043; /* Orange for working */
+    border-radius: 20rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    box-shadow: 0 10rpx 0 #E64A19;
+    transition: all 0.3s;
+}
+
+.board.resting {
+    background-color: #BDBDBD; /* Gray for resting */
+    box-shadow: 0 10rpx 0 #9E9E9E;
+}
+
+.board-inner {
+    width: 280rpx;
+    height: 120rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    transform: rotate(-2deg); /* Slightly tilted inner paper */
+}
+
+.status-text {
+    font-size: 48rpx;
+    font-weight: bold;
+    color: #FF5722;
+}
+
+.board.resting .status-text {
+    color: #757575;
+}
+
+.screw {
+    position: absolute;
+    width: 16rpx;
+    height: 16rpx;
+    background-color: #fff;
+    border-radius: 50%;
+    opacity: 0.8;
+}
+
+.top-left { top: 20rpx; left: 20rpx; }
+.top-right { top: 20rpx; right: 20rpx; }
+.bottom-left { bottom: 20rpx; left: 20rpx; }
+.bottom-right { bottom: 20rpx; right: 20rpx; }
+
+/* 文本描述 */
+.status-desc {
+    margin-bottom: 100rpx;
+    color: #333;
+    font-size: 30rpx;
+    font-weight: 500;
+}
+
+/* 按钮区域 */
+.action-area {
+    width: 80%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.action-btn {
+    width: 100%;
+    height: 88rpx;
+    line-height: 88rpx;
+    border-radius: 44rpx;
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: bold;
+    margin-bottom: 30rpx;
+    border: none;
+}
+
+.action-btn::after { border: none; }
+
+.action-btn.stop {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    box-shadow: 0 10rpx 20rpx rgba(255, 87, 34, 0.3);
+}
+
+.action-btn.stopped {
+    background-color: #E0E0E0;
+    color: #999;
+    box-shadow: none;
+}
+
+.tips {
+    font-size: 24rpx;
+    color: #999;
+    text-align: center;
+    line-height: 1.5;
+}
+</style>

+ 89 - 0
pages/login/logic.js

@@ -0,0 +1,89 @@
+export default {
+    data() {
+        return {
+            currentTab: 0, // 0: 免密, 1: 密码
+            mobile: '',
+            code: '',
+            password: '',
+            showPassword: false,
+            isAgreed: false,
+            countDown: 0,
+            timer: null,
+            showAgreementModal: false,
+            agreementTitle: '',
+            agreementContent: ''
+        }
+    },
+    methods: {
+        showAgreement(type) {
+            this.agreementTitle = type === 1 ? '用户服务协议' : '隐私政策';
+
+            if (type === 1) {
+                this.agreementContent = '1. 服务条款\n欢迎使用宠宝平台。您在使用本服务时需遵守以下条款...\n\n2. 用户责任\n用户需对自己的行为负责...\n\n3. 账号管理\n请妥善保管您的账号密码...';
+            } else {
+                this.agreementContent = '1. 信息收集\n为了提供服务,我们需要收集您的手机号、地理位置、设备信息等必要数据。\n\n2. 信息使用\n您的位置信息将用于订单匹配和路径规划;您的联系方式将用于接单通知和客户沟通。\n\n3. 信息保护\n我们将采取严格的安全措施保护您的个人信息,未经授权不会向第三方披露。';
+            }
+
+            this.showAgreementModal = true;
+        },
+        getVerifyCode() {
+            if (this.currentTab === 1) return; // 密码登录不需要验证码
+            if (this.countDown > 0) return;
+            if (!this.mobile || this.mobile.length !== 11) {
+                uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
+                return;
+            }
+
+            this.countDown = 60;
+            this.timer = setInterval(() => {
+                this.countDown--;
+                if (this.countDown <= 0) {
+                    clearInterval(this.timer);
+                }
+            }, 1000);
+
+            uni.showToast({ title: '验证码已发送', icon: 'none' });
+        },
+        handleLogin() {
+            if (!this.isAgreed) {
+                uni.showToast({ title: '请先同意用户协议', icon: 'none' });
+                return;
+            }
+            if (!this.mobile) {
+                uni.showToast({ title: '请输入手机号', icon: 'none' });
+                return;
+            }
+
+            if (this.currentTab === 0) {
+                // 免密登录
+                if (!this.code) {
+                    uni.showToast({ title: '请输入验证码', icon: 'none' });
+                    return;
+                }
+            } else {
+                // 密码登录
+                if (!this.password) {
+                    uni.showToast({ title: '请输入密码', icon: 'none' });
+                    return;
+                }
+            }
+
+            uni.showToast({ title: '登录成功', icon: 'success' });
+            setTimeout(() => {
+                uni.switchTab({
+                    url: '/pages/home/index'
+                });
+            }, 1000);
+        },
+        goToRecruit() {
+            uni.navigateTo({
+                url: '/pages/recruit/landing'
+            });
+        },
+        goToForgotPwd() {
+            uni.navigateTo({
+                url: '/pages/login/reset-pwd-verify'
+            });
+        }
+    }
+}

+ 160 - 0
pages/login/login.vue

@@ -0,0 +1,160 @@
+<template>
+  <view class="container">
+    <!-- 顶部 Banner 区域 -->
+    <view class="banner-area">
+      <image class="banner-img" src="/static/header.png" mode="widthFix"></image>
+    </view>
+
+    <!-- 白色内容卡片 -->
+    <view class="content-card">
+      <!-- 悬浮 Logo -->
+      <view class="logo-wrapper">
+        <image class="logo-img" src="/static/logo.png" mode="widthFix"></image>
+      </view>
+
+      <!-- 登录 Tab 切换 -->
+      <view class="tabs">
+        <view 
+          class="tab-item" 
+          :class="{ active: currentTab === 0 }" 
+          @click="currentTab = 0"
+        >
+          <text class="tab-text">免密登录</text>
+          <view class="tab-indicator" v-if="currentTab === 0"></view>
+        </view>
+        <view class="divider"></view>
+        <view 
+          class="tab-item" 
+          :class="{ active: currentTab === 1 }" 
+          @click="currentTab = 1"
+        >
+          <text class="tab-text">密码登录</text>
+          <view class="tab-indicator" v-if="currentTab === 1"></view>
+        </view>
+      </view>
+
+      <!-- 表单区域 -->
+      <view class="form-area">
+        <!-- 手机号 (通用) -->
+        <view class="input-group">
+          <view class="area-code">
+            <text>+86</text>
+            <text class="arrow">﹀</text>
+          </view>
+          <input 
+            class="input" 
+            type="number" 
+            placeholder="手机号" 
+            placeholder-style="color: #ccc"
+            v-model="mobile"
+            maxlength="11"
+          />
+        </view>
+
+        <!-- 免密登录: 验证码 -->
+        <view class="input-group" v-if="currentTab === 0">
+          <input 
+            class="input" 
+            type="number" 
+            placeholder="验证码" 
+            placeholder-style="color: #ccc"
+            v-model="code"
+            maxlength="6"
+          />
+          <view class="get-code-btn" @click="getVerifyCode">
+            <text class="code-text">{{ countDown > 0 ? `${countDown}s后重试` : '获取验证码' }}</text>
+          </view>
+        </view>
+
+        <!-- 密码登录: 密码框 -->
+        <view class="input-group" v-if="currentTab === 1">
+          <input 
+            class="input" 
+            :password="!showPassword" 
+            type="text"
+            placeholder="请输入密码" 
+            placeholder-style="color: #ccc"
+            v-model="password"
+          />
+          <view class="eye-icon" @click="showPassword = !showPassword">
+            <template v-if="showPassword">
+              <!-- 睁眼线框图标 -->
+              <svg class="svg-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M12 4.5C7 4.5 2.73 7.61 1 12C2.73 16.39 7 19.5 12 19.5C17 19.5 21.27 16.39 23 12C21.27 7.61 17 4.5 12 4.5ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z" fill="#CCCCCC"/>
+              </svg>
+            </template>
+            <template v-else>
+               <!-- 闭眼线框图标 (带睫毛) -->
+               <svg class="svg-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M12 7C7 7 2.73 10.11 1 14.5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M23 14.5C21.27 10.11 17 7 12 7" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M12 7V4" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M16 8L18 5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M8 8L6 5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M20 10L22 8" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M4 10L2 8" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+              </svg>
+            </template>
+          </view>
+        </view>
+        
+        <!-- 忘记密码 -->
+        <view class="forgot-pwd" v-if="currentTab === 1">
+             <text @click="goToForgotPwd">忘记密码?</text>
+        </view>
+
+        <!-- 登录按钮 -->
+        <button class="login-btn" @click="handleLogin">登 录</button>
+
+        <!-- 协议 -->
+        <view class="agreement">
+          <view class="checkbox" :class="{ checked: isAgreed }" @click="isAgreed = !isAgreed">
+            <text v-if="isAgreed" class="check-mark">✓</text>
+          </view>
+          <text class="agree-text">
+            我已经阅读并同意 <text class="link" @click.stop="showAgreement(1)">《用户服务协议》</text> 和 <text class="link" @click.stop="showAgreement(2)">《隐私政策》</text>
+          </text>
+        </view>
+      </view>
+
+      <!-- 底部招募入口 (固定底部) -->
+      <view class="footer-recruit" @click="goToRecruit">
+        <view class="recruit-badge">
+          <!-- 旗帜线框图标 -->
+           <svg class="svg-icon flag-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="width:30rpx; height:30rpx;">
+            <path d="M4 14V4H18L17 9L18 14H4Z" stroke="#FF5722" stroke-width="2" stroke-linejoin="round"/>
+            <path d="M4 22V14" stroke="#FF5722" stroke-width="2" stroke-linecap="round"/>
+          </svg>
+          <text> 宠宝履约者招募</text>
+        </view>
+      </view>
+      
+      <!-- 协议弹窗 组件化 -->
+      <privacy-popup 
+        :visible="showAgreementModal" 
+        :title="agreementTitle" 
+        :content="agreementContent"
+        @close="showAgreementModal = false"
+      >
+      </privacy-popup>
+    </view>
+  </view>
+</template>
+
+<script>
+// 使用脚本文件
+import logic from './logic.js';
+import PrivacyPopup from '@/components/privacy-popup/privacy-popup.vue';
+
+export default {
+    ...logic,
+    components: {
+        PrivacyPopup
+    }
+}
+</script>
+
+<style>
+/* 引用样式文件 */
+@import './style.css';
+</style>

+ 110 - 0
pages/login/reset-pwd-set.vue

@@ -0,0 +1,110 @@
+<template>
+    <view class="reset-container">
+        <!-- 顶部导航栏 -->
+        <!-- 标题 "设置新密码" -->
+
+        <view class="content">
+            <view class="tip-text">请输入新密码,并重新登录验证</view>
+
+            <view class="input-form">
+                <view class="input-row">
+                    <input 
+                        class="pwd-input" 
+                        type="text" 
+                        password 
+                        placeholder="限12-20位字母和数字组合" 
+                        placeholder-style="color:#ccc"
+                        v-model="pwd1"
+                    />
+                </view>
+                 <view class="divider"></view>
+                <view class="input-row">
+                    <input 
+                        class="pwd-input" 
+                        type="text" 
+                        password 
+                        placeholder="限12-20位字母和数字组合" 
+                        placeholder-style="color:#ccc"
+                        v-model="pwd2"
+                    />
+                </view>
+                 <view class="divider"></view>
+            </view>
+            
+            <button class="confirm-btn" @click="confirmReset">确定</button>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            pwd1: '',
+            pwd2: ''
+        }
+    },
+    methods: {
+        confirmReset() {
+            if (!this.pwd1 || !this.pwd2) {
+                uni.showToast({ title: '请输入密码', icon: 'none' });
+                return;
+            }
+            if (this.pwd1 !== this.pwd2) {
+                uni.showToast({ title: '两次密码不一致', icon: 'none' });
+                return;
+            }
+            
+            uni.showToast({ title: '重置成功', icon: 'success' });
+            
+            // 延迟跳转回登录页
+            setTimeout(() => {
+                uni.navigateBack({
+                    delta: 2 // 返回到登录页
+                });
+            }, 1500);
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #fff;
+}
+.reset-container {
+    padding: 40rpx;
+}
+.tip-text {
+    font-size: 28rpx;
+    color: #666;
+    margin-bottom: 60rpx;
+}
+.input-form {
+    margin-bottom: 80rpx;
+}
+.input-row {
+    padding: 30rpx 0;
+}
+.pwd-input {
+    font-size: 30rpx;
+    width: 100%;
+    color: #333;
+}
+.divider {
+    height: 1px;
+    background-color: #eee;
+}
+.confirm-btn {
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: bold;
+    border-radius: 8rpx;
+    height: 88rpx;
+    line-height: 88rpx;
+}
+.confirm-btn::after {
+    border: none;
+}
+</style>

+ 138 - 0
pages/login/reset-pwd-verify.vue

@@ -0,0 +1,138 @@
+<template>
+    <view class="reset-container">
+        <!-- 顶部导航栏 (自定义或使用原生) -->
+        <!-- 这里假设使用原生导航栏,标题 "重置密码" -->
+
+        <view class="content">
+            <view class="tip-text">请输入 +86 {{ mobileMask }} 收到的短信验证码,进行验证~</view>
+
+            <view class="input-group">
+                <text class="label">验证码</text>
+                <view class="input-wrapper">
+                    <input 
+                        class="code-input" 
+                        type="number" 
+                        maxlength="6" 
+                        v-model="code"
+                    />
+                    <view class="get-code-btn" @click="getVerifyCode">
+                        <text class="btn-text">{{ countDown > 0 ? `${countDown}s` : '获取验证码' }}</text>
+                    </view>
+                </view>
+            </view>
+            
+            <button class="next-btn" @click="nextStep">下一步</button>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            mobile: '',
+            code: '',
+            countDown: 0,
+            timer: null
+        }
+    },
+    computed: {
+        mobileMask() {
+            if (!this.mobile) return '';
+            return this.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
+        }
+    },
+    onLoad(options) {
+        if (options.mobile) {
+            this.mobile = options.mobile;
+        } else {
+            // 测试用默认手机号
+            this.mobile = '13412346783';
+        }
+    },
+    methods: {
+        getVerifyCode() {
+            if (this.countDown > 0) return;
+            
+            this.countDown = 60;
+            this.timer = setInterval(() => {
+                this.countDown--;
+                if (this.countDown <= 0) {
+                    clearInterval(this.timer);
+                }
+            }, 1000);
+            
+            uni.showToast({ title: '验证码已发送', icon: 'none' });
+        },
+        nextStep() {
+            if (!this.code) {
+                uni.showToast({ title: '请输入验证码', icon: 'none' });
+                return;
+            }
+            // 跳转到设置密码页
+            uni.navigateTo({
+                url: '/pages/login/reset-pwd-set'
+            });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #fff;
+}
+.reset-container {
+    padding: 40rpx;
+}
+.tip-text {
+    font-size: 28rpx;
+    color: #666;
+    margin-bottom: 60rpx;
+    line-height: 1.5;
+}
+.input-group {
+    display: flex;
+    align-items: center;
+    border-bottom: 1px solid #f0f0f0;
+    padding-bottom: 20rpx;
+    margin-bottom: 60rpx;
+}
+.label {
+    font-size: 30rpx;
+    color: #333;
+    width: 120rpx;
+}
+.input-wrapper {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+.code-input {
+    flex: 1;
+    font-size: 30rpx;
+    color: #333;
+}
+.get-code-btn {
+    background-color: #F8F8F8;
+    padding: 10rpx 20rpx;
+    border-radius: 8rpx;
+}
+.btn-text {
+    font-size: 26rpx;
+    color: #FF5722;
+}
+.next-btn {
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: bold;
+    border-radius: 8rpx; /* 图2也是带圆角的矩形,和登录页一致 */
+    height: 88rpx;
+    line-height: 88rpx;
+}
+.next-btn::after {
+    border: none;
+}
+</style>

+ 330 - 0
pages/login/style.css

@@ -0,0 +1,330 @@
+/* 页面容器 */
+.container {
+  height: 100vh;
+  /* 强制全屏高度 */
+  overflow: hidden;
+  /* 禁止溢出滚动 */
+  background-color: #fff;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+}
+
+/* 顶部 Banner */
+.banner-area {
+  width: 100%;
+  position: relative;
+  /* 移除高度限制,依靠 content-card 的 margin-top 控制遮挡 */
+}
+
+.banner-img {
+  width: 100%;
+  display: block;
+  /* 消除图片底部空隙 */
+}
+
+/* 内容卡片 - 核心布局技巧 */
+.content-card {
+  flex: 1;
+  background-color: #fff;
+  margin-top: -80rpx;
+  /* 向上覆盖 banner,形成遮挡 */
+  /* 实现向上凸起的圆弧效果: 使用 border-radius 实现顶部椭圆 */
+  border-radius: 100% 100% 0 0 / 60rpx 60rpx 0 0;
+
+  position: relative;
+  z-index: 10;
+  padding: 0 50rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+/* 悬浮 Logo */
+.logo-wrapper {
+  margin-top: -70rpx;
+  /* Logo 向上悬浮 */
+  margin-bottom: 50rpx;
+  /* 添加白色光晕/阴影增强悬浮感 */
+  border-radius: 50%;
+  box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.1);
+  background-color: #fff;
+  padding: 8rpx;
+  /* 白色边框 */
+}
+
+.logo-img {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 50%;
+  display: block;
+}
+
+/* Tabs */
+.tabs {
+  display: flex;
+  align-items: center;
+  margin-bottom: 60rpx;
+}
+
+.tab-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 0 30rpx;
+}
+
+.tab-text {
+  font-size: 32rpx;
+  color: #999;
+  font-weight: 500;
+  margin-bottom: 10rpx;
+}
+
+.tab-item.active .tab-text {
+  color: #FF5722;
+  /* 主色调橙色 */
+  font-weight: bold;
+  font-size: 36rpx;
+}
+
+.tab-indicator {
+  width: 40rpx;
+  height: 6rpx;
+  background-color: #FF5722;
+  border-radius: 3rpx;
+}
+
+.divider {
+  width: 1px;
+  height: 30rpx;
+  background-color: #eee;
+  margin: 0 10rpx;
+}
+
+/* 表单 */
+.form-area {
+  width: 100%;
+}
+
+.input-group {
+  display: flex;
+  align-items: center;
+  border-bottom: 1px solid #f0f0f0;
+  padding: 30rpx 0;
+  margin-bottom: 20rpx;
+}
+
+.area-code {
+  display: flex;
+  align-items: center;
+  margin-right: 20rpx;
+  font-size: 32rpx;
+  color: #333;
+  height: 100%;
+  /* 确保高度撑满 */
+}
+
+.arrow {
+  font-size: 20rpx;
+  color: #999;
+  margin-left: 8rpx;
+  /* margin-top: 4rpx; 移除微调,依靠 flex 居中 */
+}
+
+.input {
+  flex: 1;
+  font-size: 30rpx;
+}
+
+.get-code-btn {
+  background-color: #FFF0E9;
+  /* 浅橙色背景 */
+  padding: 15rpx 30rpx;
+  /* 增大内边距 */
+  border-radius: 40rpx;
+  /* 稍微增大圆角 */
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.code-text {
+  color: #FF5722;
+  font-size: 28rpx;
+  /* 增大字体 */
+  line-height: 1;
+  /* 修正文字垂直居中 */
+}
+
+.eye-icon {
+  padding: 10rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.svg-icon {
+  width: 40rpx;
+  height: 40rpx;
+}
+
+.forgot-pwd {
+  width: 100%;
+  text-align: right;
+  padding-top: 20rpx;
+  font-size: 26rpx;
+  color: #666;
+}
+
+/* 按钮 */
+.login-btn {
+  /* 鲜亮的橙色渐变 */
+  background: linear-gradient(90deg, #FF9E60 0%, #FF5722 100%);
+  color: #fff;
+  border-radius: 50rpx;
+  margin-top: 60rpx;
+  margin-bottom: 40rpx;
+  font-size: 34rpx;
+  font-weight: bold;
+  box-shadow: 0 10rpx 30rpx rgba(255, 87, 34, 0.35);
+  /* 增强投影 */
+}
+
+.login-btn::after {
+  border: none;
+}
+
+/* 协议 */
+.agreement {
+  display: flex;
+  align-items: center;
+  /* 改为居中对齐,如果文字换行可能需要改为 flex-start 并调整 margin-top */
+  justify-content: center;
+}
+
+.checkbox {
+  width: 32rpx;
+  height: 32rpx;
+  border: 2rpx solid #ccc;
+  border-radius: 50%;
+  margin-right: 12rpx;
+  /* margin-top: 4rpx;  移除顶部 margin,由 align-items: center 控制 */
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.checkbox.checked {
+  border-color: #FF5722;
+  background-color: #FF5722;
+}
+
+.check-mark {
+  color: #fff;
+  font-size: 22rpx;
+  line-height: 1;
+  /* 确保勾选符号居中 */
+}
+
+.agree-text {
+  font-size: 24rpx;
+  color: #999;
+  line-height: 1.5;
+}
+
+.link {
+  color: #666;
+}
+
+/* 底部招募 */
+.footer-recruit {
+  margin-top: auto;
+  padding-bottom: 80rpx;
+  /* 增加底部距离 */
+  width: 100%;
+  display: flex;
+  justify-content: center;
+}
+
+.recruit-badge {
+  display: flex;
+  align-items: center;
+  padding: 20rpx 50rpx;
+  background-color: #fff;
+  /* 白色背景 */
+  border: 1px solid #FF5722;
+  /* 橙色边框 */
+  border-radius: 60rpx;
+  /* 胶囊圆角 */
+  color: #FF5722;
+  /* 橙色文字 */
+  font-size: 28rpx;
+  font-weight: bold;
+  box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.2);
+  /* 橙色阴影 */
+}
+
+.flag-icon {
+  margin-right: 15rpx;
+  font-size: 28rpx;
+  color: #FF5722;
+}
+
+/* 弹窗样式 */
+.modal-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+  z-index: 999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.modal-content {
+  width: 600rpx;
+  background-color: #fff;
+  border-radius: 20rpx;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  max-height: 70vh;
+}
+
+.modal-header {
+  padding: 30rpx;
+  text-align: center;
+  border-bottom: 1px solid #eee;
+}
+
+.modal-title {
+  font-size: 32rpx;
+  font-weight: bold;
+}
+
+.modal-body {
+  padding: 30rpx;
+  flex: 1;
+  overflow-y: auto;
+}
+
+.modal-text {
+  font-size: 28rpx;
+  color: #666;
+  line-height: 1.6;
+}
+
+.modal-footer {
+  padding: 20rpx 30rpx 30rpx;
+}
+
+.confirm-btn {
+  background-color: #FF5722;
+  color: #fff;
+  font-size: 30rpx;
+  border-radius: 40rpx;
+}

+ 184 - 0
pages/mine/index.vue

@@ -0,0 +1,184 @@
+<template>
+    <view class="container">
+        <!-- 顶部背景 -->
+        <view class="nav-bg">
+            <view class="bg-circle-1"></view>
+            <view class="bg-circle-2"></view>
+        </view>
+
+        <!-- 头部用户信息 -->
+        <view class="header-section">
+            <view class="title-bar">个人中心</view>
+            <view class="user-card" @click="navToProfile">
+                <image class="avatar" src="/static/touxiang.png" mode="aspectFill"></image>
+                <view class="info-content">
+                    <view class="name-row">
+                        <text class="name">张*哥</text>
+                        <view class="tags">
+                            <view class="tag green">接单中</view>
+                            <view class="tag blue">全职</view>
+                            <image class="bike-icon" src="/static/icons/motorbike.svg"></image>
+                        </view>
+                    </view>
+                    <view class="detail-row">
+                        <image class="small-icon" src="/static/icons/location.svg"></image>
+                        <text>深圳市龙华区民治街道第一站</text>
+                        <image class="arrow-icon-small" src="/static/icons/chevron_right_dark.svg"></image>
+                    </view>
+                    <view class="detail-row">
+                        <image class="small-icon" src="/static/icons/calendar.svg"></image>
+                        <text>已注册250天</text>
+                    </view>
+                </view>
+                <image class="settings-icon" src="/static/icons/settings.svg" @click.stop="navToSettings"></image>
+            </view>
+
+            <!-- 黑金权益卡 -->
+            <view class="vip-card">
+                <view class="vip-left">
+                    <image class="vip-icon" src="/static/icons/crown.svg"></image>
+                    <view class="vip-text">
+                        <text class="vip-title">L3 黄金履约者</text>
+                        <text class="vip-desc">再完成 298 单可升级为 L4 钻石履约者</text>
+                    </view>
+                </view>
+                <view class="vip-btn" @click="navToLevel">
+                    <text>查看权益</text>
+                    <image class="arrow-icon-small" src="/static/icons/chevron_right_gold.svg"></image>
+                </view>
+            </view>
+        </view>
+
+        <!-- 统计面板 -->
+        <view class="stats-panel">
+            <view class="stat-item" @click="navToWallet">
+                <view class="stat-header">
+                    <view class="red-bar"></view>
+                    <text class="label">我的钱包</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+                <view class="stat-value">
+                    <text class="num">2,575</text>
+                    <text class="unit">元</text>
+                </view>
+                <text class="sub-text">本月预计收入</text>
+            </view>
+            <view class="divider"></view> 
+            <view class="stat-item" @click="navToOrderStats">
+                <view class="stat-header">
+                    <view class="green-bar"></view>
+                    <text class="label">订单统计</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+                <view class="stat-value">
+                    <text class="num">702</text>
+                    <text class="unit">单</text>
+                </view>
+                <text class="sub-text">本月完成单量</text>
+            </view>
+            <view class="divider"></view>
+            <view class="stat-item" @click="navToPoints">
+                <view class="stat-header">
+                    <view class="orange-bar"></view>
+                    <text class="label">我的积分</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+                <view class="stat-value">
+                    <text class="num">1200</text>
+                    <text class="unit">分</text>
+                </view>
+                <text class="sub-text">可兑换权益</text>
+            </view>
+        </view>
+
+        <!-- 菜单列表 -->
+        <view class="menu-list">
+            <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 class="menu-item" @click="navToRewards">
+                <image class="menu-icon" src="/static/icons/money_linear.svg"></image>
+                <text class="menu-text">我的奖惩</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+            <view class="menu-item" @click="openServicePopup">
+                <image class="menu-icon" src="/static/icons/headset_linear.svg"></image>
+                <text class="menu-text">联系客服</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+        </view>
+
+        <!-- 退出登录 -->
+        <!-- 退出登录 -->
+        <view class="logout-btn" @click="logout">退出登录</view>
+
+        <!-- 联系客服弹窗 -->
+        <view class="service-popup-mask" v-if="showServicePopup" @click="closeServicePopup">
+            <view class="service-popup" @click.stop>
+                <view class="service-header">
+                    <text class="service-title">联系客服</text>
+                    <image class="close-icon" src="/static/icons/close_gray.svg" @click="closeServicePopup"></image>
+                </view>
+
+                <view class="qr-section">
+                    <text class="qr-title">客服二维码</text>
+                    <image class="qr-img" src="/static/logo.png" @click="previewQRCode"></image>
+                    <text class="qr-desc">点击查看大图</text>
+                </view>
+
+                <view class="service-list">
+                    <view class="service-row" @click="openOnlineService">
+                        <image class="service-row-icon" src="/static/icons/headset_green.svg"></image>
+                        <view class="service-info">
+                            <text class="service-name">在线客服</text>
+                            <text class="service-desc">企业微信专属客服在线解答</text>
+                        </view>
+                        <image class="arrow-icon-small" src="/static/icons/chevron_right.svg"></image>
+                    </view>
+
+                    <view class="service-row">
+                        <image class="service-row-icon" src="/static/icons/phone_orange.svg"></image>
+                        <view class="service-info">
+                            <text class="service-name">客服电话</text>
+                            <text class="service-desc">400-123-4567</text>
+                        </view>
+                        <view class="call-btn" @click="callServicePhone">
+                            <image class="phone-icon-small" src="/static/icons/phone_green.svg"></image>
+                            <text>拨打</text>
+                        </view>
+                    </view>
+                </view>
+            </view>
+        </view>
+
+
+        <!-- 退出登录弹窗 -->
+        <view class="logout-popup-mask" :class="{ 'show': showLogoutPopup }" @click="cancelLogout" @touchmove.stop.prevent>
+            <view class="popup-modal" @click.stop>
+
+                <text class="popup-title">退出登录</text>
+                <text class="popup-desc">确定要退出当前账号吗?\n退出后需要重新登录才能使用完整功能。</text>
+                <view class="popup-actions">
+                    <view class="popup-btn cancel" @click="cancelLogout">取消</view>
+                    <view class="popup-btn confirm" @click="confirmLogout">确定</view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import logic from './logic.js';
+export default {
+    ...logic
+}
+</script>
+
+<style>
+@import './style.css';
+</style>

+ 418 - 0
pages/mine/level/index.vue

@@ -0,0 +1,418 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">履约者等级权益</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <!-- 等级 Switcher -->
+        <view class="swiper-container">
+            <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)'}">
+                        <view class="card-content">
+                            <view class="card-header">
+                                <view class="level-badge">{{ level.id }}</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>
+                            <!-- Crown graphic overlay -->
+                            <image class="crown-overlay" src="/static/icons/crown.svg" mode="aspectFit"></image>
+                        </view>
+                    </view>
+                </swiper-item>
+            </swiper>
+            <!-- 自定义指示点 -->
+            <view class="swiper-dots">
+                <view 
+                    class="dot" 
+                    v-for="(item, index) in levels" 
+                    :key="index"
+                    :class="{ active: currentIndex === index }">
+                </view>
+            </view>
+        </view>
+
+        <!-- 权益标题 -->
+        <view class="benefits-title-row">
+            <text class="benefits-title">{{ currentLevel.id }} 专属权益</text>
+            <text class="benefits-count">({{ currentLevel.benefits.length }})</text>
+        </view>
+
+        <!-- 权益列表 -->
+        <view class="benefits-grid">
+            <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>
+                    <view class="benefit-icon-placeholder" v-else>{{ benefit.name[0] }}</view>
+                </view>
+                <text class="benefit-name">{{ benefit.name }}</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>
+                     <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>
+                <button class="popup-btn" @click="closePopup">我知道了</button>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+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: '' }
+                    ]
+                }
+            ],
+            isPopupShow: false,
+            currentBenefit: null
+        }
+    },
+    computed: {
+        currentLevel() {
+            return this.levels[this.currentIndex];
+        }
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        swiperChange(e) {
+            this.currentIndex = e.detail.current;
+        },
+        changeLevel(index) {
+            this.currentIndex = index;
+        },
+        showBenefitDetail(benefit) {
+            this.currentBenefit = benefit;
+            this.isPopupShow = true;
+        },
+        closePopup() {
+            this.isPopupShow = false;
+        }
+    }
+}
+</script>
+
+<style>
+/* ... Header styles keep same ... */
+page {
+    background-color: #fff;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.swiper-container {
+    position: relative;
+    padding-bottom: 30rpx;
+}
+.level-swiper {
+    height: 360rpx;
+    margin-top: 20rpx;
+}
+.level-card {
+    height: 320rpx; 
+    border-radius: 30rpx;
+    margin: 0 10rpx;
+    transition: transform 0.3s;
+    overflow: hidden;
+    position: relative;
+    box-shadow: 0 10rpx 20rpx 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%); }
+
+.card-content {
+    padding: 30rpx;
+    position: relative;
+    z-index: 2;
+    height: 100%;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+}
+.card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    margin-bottom: auto; /* Push content down */
+}
+.level-badge {
+    border: 1px solid rgba(255,255,255,0.6);
+    padding: 2rpx 12rpx;
+    border-radius: 10rpx;
+    font-size: 24rpx;
+    color: #fff;
+}
+.current-badge {
+    background-color: rgba(255,255,255,0.9);
+    color: #333;
+    font-size: 20rpx;
+    padding: 4rpx 12rpx;
+    border-radius: 20rpx;
+    font-weight: bold;
+}
+.level-name {
+    font-size: 44rpx;
+    font-weight: bold;
+    color: #fff;
+    margin-bottom: 10rpx;
+    text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
+}
+.level-score {
+    font-size: 24rpx;
+    color: rgba(255,255,255,0.8);
+    margin-bottom: 20rpx;
+}
+.crown-overlay {
+    position: absolute;
+    bottom: -30rpx;
+    right: -30rpx;
+    width: 260rpx;
+    height: 260rpx;
+    opacity: 0.1;
+    z-index: 1;
+}
+
+/* Dots */
+.swiper-dots {
+    display: flex;
+    justify-content: center;
+    margin-top: 10rpx;
+}
+.dot {
+    width: 12rpx;
+    height: 12rpx;
+    background-color: #E0E0E0;
+    border-radius: 50%;
+    margin: 0 6rpx;
+    transition: all 0.3s;
+}
+.dot.active {
+    width: 24rpx;
+    background-color: #333;
+    border-radius: 6rpx;
+}
+
+.benefits-title-row {
+    padding: 20rpx 30rpx;
+    display: flex;
+    align-items: baseline;
+}
+.benefits-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+.benefits-count {
+    font-size: 28rpx;
+    color: #999;
+    margin-left: 10rpx;
+}
+
+.benefits-grid {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 0 20rpx;
+}
+.benefit-item {
+    width: 25%; /* 4 items per row */
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin-bottom: 30rpx;
+}
+.benefit-icon-wrapper {
+    width: 88rpx;
+    height: 88rpx;
+    background-color: #F8F8F8; /* Or very light color based on current level? Keep simple for now */
+    border-radius: 24rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 12rpx;
+}
+.benefit-icon {
+    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 */
+    color: #666;
+    text-align: center;
+}
+
+/* Modal */
+.popup-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0,0,0,0.5); /* Semi-transparent black */
+    z-index: 999;
+    display: none; /* Hidden by default */
+    align-items: center;
+    justify-content: center;
+}
+.popup-mask.show {
+    display: flex; /* Show when active */
+}
+.popup-modal {
+    width: 480rpx; /* Narrower width */
+    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 */
+}
+.popup-icon-wrapper {
+    width: 120rpx;
+    height: 120rpx;
+    background-color: #FFF8E1; 
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 30rpx;
+}
+.benefit-icon-large {
+    width: 60rpx;
+    height: 60rpx;
+}
+.benefit-icon-placeholder-large {
+    font-size: 50rpx;
+    font-weight: bold;
+    color: #FFB300;
+}
+.popup-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 20rpx;
+}
+.popup-desc {
+    font-size: 26rpx;
+    color: #666;
+    text-align: center;
+    line-height: 1.5;
+    margin-bottom: 40rpx;
+}
+.popup-btn {
+    width: 80%;
+    height: 72rpx;
+    line-height: 72rpx;
+    background-color: #212121;
+    color: #fff;
+    font-size: 28rpx;
+    border-radius: 36rpx;
+}
+</style>

+ 86 - 0
pages/mine/logic.js

@@ -0,0 +1,86 @@
+export default {
+    data() {
+        return {
+            showServicePopup: false,
+            showLogoutPopup: false
+        }
+    },
+    methods: {
+        navToSettings() {
+            uni.navigateTo({
+                url: '/pages/mine/settings/index'
+            });
+        },
+        navToProfile() {
+            uni.navigateTo({
+                url: '/pages/mine/settings/profile/index'
+            });
+        },
+        navToLevel() {
+            uni.navigateTo({
+                url: '/pages/mine/level/index'
+            });
+        },
+        navToNotification() {
+            uni.navigateTo({
+                url: '/pages/mine/message/index'
+            });
+        },
+        navToWallet() {
+            uni.navigateTo({
+                url: '/pages/mine/wallet/index'
+            });
+        },
+        navToPoints() {
+            uni.navigateTo({
+                url: '/pages/mine/points/index'
+            });
+        },
+        navToOrderStats() {
+            uni.navigateTo({
+                url: '/pages/mine/order-stats'
+            });
+        },
+        navToRewards() {
+            uni.navigateTo({
+                url: '/pages/mine/rewards'
+            });
+        },
+        openServicePopup() {
+            this.showServicePopup = true;
+        },
+        closeServicePopup() {
+            this.showServicePopup = false;
+        },
+        previewQRCode() {
+            uni.previewImage({
+                urls: ['/static/logo.png']
+            });
+        },
+        openOnlineService() {
+            // 模拟跳转企业微信客服
+            uni.showToast({
+                title: '正在跳转企业微信客服...',
+                icon: 'none'
+            });
+        },
+        callServicePhone() {
+            uni.makePhoneCall({
+                phoneNumber: '400-123-4567'
+            });
+        },
+        logout() {
+            this.showLogoutPopup = true;
+        },
+        cancelLogout() {
+            this.showLogoutPopup = false;
+        },
+        confirmLogout() {
+            this.showLogoutPopup = false;
+            // 跳转到登录页,使用 reLaunch 关闭所有页面
+            uni.reLaunch({
+                url: '/pages/login/login'
+            });
+        }
+    }
+}

+ 109 - 0
pages/mine/message/detail.vue

@@ -0,0 +1,109 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="nav-title">消息详情</text>
+            <view class="nav-right"></view>
+        </view>
+        <view class="nav-placeholder"></view>
+
+        <view class="detail-content">
+            <text class="detail-title">账号审核通过</text>
+            <text class="detail-time">2023-11-01 10:00</text>
+            
+            <view class="detail-body">
+                <text>尊敬的用户,您的健康认证资料已通过平台审核。作为履约者,您现在可以正常接收并处理订单。请确保您熟读平台规则,遵守交通法规,安全配送。祝您工作愉快!</text>
+            </view>
+            
+            <view class="detail-footer">
+                <view class="divider"></view>
+                <text class="footer-text">如有疑问,请咨询在线客服。</text>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+export default {
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #fff;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.nav-bar {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+.nav-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+.nav-right { width: 40rpx; }
+
+.detail-content {
+    padding: 40rpx 30rpx;
+}
+.detail-title {
+    font-size: 40rpx;
+    font-weight: bold;
+    color: #333;
+    display: block;
+    margin-bottom: 20rpx;
+}
+.detail-time {
+    font-size: 24rpx;
+    color: #999;
+    display: block;
+    margin-bottom: 40rpx;
+}
+.detail-body {
+    font-size: 30rpx;
+    color: #333;
+    line-height: 1.8;
+}
+.detail-footer {
+    margin-top: 60rpx;
+    text-align: center;
+}
+.divider {
+    height: 1rpx;
+    background-color: #eee;
+    margin-bottom: 30rpx;
+}
+.footer-text {
+    font-size: 26rpx;
+    color: #ccc;
+}
+</style>

+ 183 - 0
pages/mine/message/index.vue

@@ -0,0 +1,183 @@
+<template>
+    <view class="container">
+        <!-- 自定义导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="nav-title">消息中心</text>
+            <view class="nav-right">
+                <view class="more-dots">
+                    <view class="dot"></view>
+                    <view class="dot"></view>
+                    <view class="dot"></view>
+                </view>
+            </view>
+        </view>
+        <view class="nav-placeholder"></view>
+
+        <!-- 消息分类列表 -->
+        <view class="message-list">
+            <!-- 订单消息 -->
+            <view class="message-item" @click="navToOrderMsg">
+                <view class="icon-wrapper">
+                    <image class="msg-icon" src="/static/icons/icon_order_msg.svg"></image>
+                    <view class="red-dot-badge"></view>
+                </view>
+                <view class="content-wrapper">
+                    <view class="top-row">
+                        <text class="msg-title">订单消息</text>
+                        <text class="msg-time">5分钟前</text>
+                    </view>
+                    <text class="msg-preview">你收到一个站长手动派单的新订单</text>
+                </view>
+            </view>
+
+            <!-- 系统消息 -->
+            <view class="message-item" @click="navToSystemMsg">
+                <view class="icon-wrapper">
+                    <image class="msg-icon" src="/static/icons/icon_system_msg.svg"></image>
+                </view>
+                <view class="content-wrapper">
+                    <view class="top-row">
+                        <text class="msg-title">系统消息</text>
+                        <text class="msg-time">7天前</text>
+                    </view>
+                    <text class="msg-preview">你的健康证明认证审核已通过。</text>
+                </view>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        navToOrderMsg() {
+            uni.navigateTo({
+                url: '/pages/mine/message/order'
+            });
+        },
+        navToSystemMsg() {
+            uni.navigateTo({
+                url: '/pages/mine/message/system'
+            });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #fff;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.nav-bar {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    padding-top: var(--status-bar-height); /* Ensure padding top includes status bar */
+    box-sizing: border-box;
+    z-index: 100;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+.nav-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+.nav-right {
+    width: 40rpx;
+    display: flex;
+    justify-content: flex-end;
+}
+.more-dots {
+    display: flex;
+    gap: 4rpx;
+}
+.dot {
+    width: 6rpx;
+    height: 6rpx;
+    background-color: #333;
+    border-radius: 50%;
+}
+
+.message-list {
+    padding: 0 30rpx;
+}
+.message-item {
+    display: flex;
+    align-items: center;
+    padding: 30rpx 0;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+.icon-wrapper {
+    position: relative;
+    margin-right: 30rpx;
+}
+.msg-icon {
+    width: 96rpx;
+    height: 96rpx;
+    border-radius: 50%;
+}
+.red-dot-badge {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 16rpx;
+    height: 16rpx;
+    background-color: #FF3B30;
+    border-radius: 50%;
+    border: 2rpx solid #fff;
+}
+.content-wrapper {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+.top-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 10rpx;
+}
+.msg-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.msg-time {
+    font-size: 24rpx;
+    color: #999;
+}
+.msg-preview {
+    font-size: 26rpx;
+    color: #666;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    width: 500rpx;
+}
+</style>

+ 168 - 0
pages/mine/message/order.vue

@@ -0,0 +1,168 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="nav-title">订单消息</text>
+            <view class="nav-right"></view>
+        </view>
+        <view class="nav-placeholder"></view>
+
+        <view class="msg-group">
+            <view class="date-label">2099-12-28</view>
+            
+            <!-- 消息卡片 1 -->
+            <view class="msg-card">
+                <view class="card-header">
+                    <text class="card-title">站长手动派单</text>
+                    <view class="red-dot"></view>
+                </view>
+                <view class="card-body">
+                    <text class="msg-text">你收到一个新订单,请及时查看并接单。</text>
+                </view>
+                <view class="card-footer">
+                    <text class="order-id">订单: 2099091503521</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+
+            <!-- 消息卡片 2 -->
+            <view class="msg-card">
+                <view class="card-header">
+                    <text class="card-title">系统自动派单</text>
+                </view>
+                <view class="card-body">
+                    <text class="msg-text">你收到一个新订单,请及时查看并接单。</text>
+                </view>
+                <view class="card-footer">
+                    <text class="order-id">订单: 2099091503523</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+        <view class="msg-group">
+            <view class="date-label">2099-12-27</view>
+            
+            <!-- 消息卡片 3 -->
+            <view class="msg-card">
+                <view class="card-header">
+                    <text class="card-title">系统取消派单</text>
+                </view>
+                <view class="card-body">
+                    <text class="msg-text">订单由于超时未接单已被系统取消。</text>
+                </view>
+                <view class="card-footer">
+                    <text class="order-id">订单: 2099091503111</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+export default {
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F5F6FA;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.nav-bar {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.nav-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+.nav-right { width: 40rpx; }
+
+.msg-group {
+    padding: 20rpx 30rpx;
+}
+.date-label {
+    text-align: center;
+    font-size: 24rpx;
+    color: #ccc;
+    margin: 20rpx 0;
+}
+.msg-card {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 4rpx 10rpx rgba(0,0,0,0.02);
+}
+.card-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+}
+.card-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.red-dot {
+    width: 12rpx;
+    height: 12rpx;
+    background-color: #FF3B30;
+    border-radius: 50%;
+    margin-left: 10rpx;
+}
+.card-body {
+    margin-bottom: 24rpx;
+    padding-bottom: 24rpx;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+.msg-text {
+    font-size: 26rpx;
+    color: #666;
+    line-height: 1.5;
+}
+.card-footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+.order-id {
+    font-size: 24rpx;
+    color: #999;
+}
+.arrow-icon {
+    width: 24rpx;
+    height: 24rpx;
+    opacity: 0.3;
+}
+</style>

+ 186 - 0
pages/mine/message/system.vue

@@ -0,0 +1,186 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="nav-title">系统消息</text>
+            <view class="nav-right"></view>
+        </view>
+        <view class="nav-placeholder"></view>
+
+        <view class="sys-msg-list">
+            <view class="date-label">2023-11-01</view>
+
+            <!-- 消息卡片 1 -->
+            <view class="sys-card" @click="navToDetail">
+                <view class="sys-header">
+                    <text class="sys-title">账号审核通过</text>
+                    <view class="red-dot"></view>
+                </view>
+                <view class="sys-content">
+                    <text class="sys-text">恭喜,您的健康证已通过审核,现在可以开始接单了。</text>
+                </view>
+                <view class="sys-footer">
+                    <text class="sys-time">10:00</text>
+                    <view class="check-more">
+                        <text>查看详情</text>
+                        <image class="arrow-icon-small" src="/static/icons/chevron_right.svg"></image>
+                    </view>
+                </view>
+            </view>
+
+             <!-- 消息卡片 2 -->
+             <view class="sys-card">
+                <view class="sys-header">
+                    <text class="sys-title">活动奖励到账</text>
+                </view>
+                <view class="sys-content">
+                    <text class="sys-text">您参与的“新手启航”活动奖励金 ¥50 已发放到您的账户。</text>
+                </view>
+                <view class="sys-footer">
+                    <text class="sys-time">09:15</text>
+                    <view class="check-more">
+                        <text>查看详情</text>
+                        <image class="arrow-icon-small" src="/static/icons/chevron_right.svg"></image>
+                    </view>
+                </view>
+            </view>
+
+            <view class="date-label">2023-10-30</view>
+
+            <!-- 消息卡片 3 -->
+            <view class="sys-card">
+                <view class="sys-header">
+                    <text class="sys-title">系统维护通知</text>
+                </view>
+                <view class="sys-content">
+                    <text class="sys-text">平台将于 11月5日 凌晨 02:00-04:00 进行系统维护,届时将无法接单。</text>
+                </view>
+                <view class="sys-footer">
+                    <text class="sys-time">18:30</text>
+                    <view class="check-more">
+                        <text>查看详情</text>
+                        <image class="arrow-icon-small" src="/static/icons/chevron_right.svg"></image>
+                    </view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        navToDetail() {
+            uni.navigateTo({
+                url: '/pages/mine/message/detail'
+            });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F5F6FA;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.nav-bar {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.nav-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+.nav-right { width: 40rpx; }
+
+.sys-msg-list {
+    padding: 20rpx 30rpx;
+}
+.date-label {
+    text-align: center;
+    font-size: 24rpx;
+    color: #ccc;
+    margin: 30rpx 0 20rpx; /* Increased top margin */
+}
+.sys-card {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.02);
+}
+.sys-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+}
+.sys-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.red-dot {
+    width: 10rpx;
+    height: 10rpx;
+    background-color: #FF3B30;
+    border-radius: 50%;
+    margin-left: 10rpx;
+}
+.sys-content {
+    margin-bottom: 24rpx;
+}
+.sys-text {
+    font-size: 26rpx;
+    color: #666;
+    line-height: 1.6;
+}
+.sys-footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    border-top: 1rpx solid #f5f5f5;
+    padding-top: 20rpx;
+}
+.sys-time {
+    font-size: 24rpx;
+    color: #999;
+}
+.check-more {
+    display: flex;
+    align-items: center;
+    font-size: 24rpx;
+    color: #999;
+}
+.arrow-icon-small {
+    width: 20rpx;
+    height: 20rpx;
+    margin-left: 4rpx;
+    opacity: 0.5;
+}
+</style>

+ 330 - 0
pages/mine/order-stats.vue

@@ -0,0 +1,330 @@
+<template>
+    <view class="container">
+        <!-- 统计banner:圆角浮动卡,左右30rpx边距 -->
+        <view class="stats-banner">
+            <view class="banner-item">
+                <text class="banner-num">2546</text>
+                <text class="banner-label">累计接单</text>
+            </view>
+            <view class="banner-item">
+                <text class="banner-num">10</text>
+                <text class="banner-label">累计拒单</text>
+            </view>
+            <view class="banner-item">
+                <text class="banner-num">10</text>
+                <text class="banner-label">奖励单量</text>
+            </view>
+            <view class="banner-item">
+                <text class="banner-num">10</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>
+
+        <!-- 标签页(全宽,无圆角,紧贴屏幕宽度) -->
+        <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>
+
+        <!-- 订单列表:每张卡片用margin左右各30rpx,与banner宽度对齐 -->
+        <scroll-view scroll-y class="order-scroll">
+            <view style="height: 16rpx;"></view>
+
+            <view
+                class="order-card"
+                v-for="(order, idx) in filteredOrders"
+                :key="idx"
+            >
+                <!-- 卡片头部:类型图标 + 类型名 | 状态 + 时间 -->
+                <view class="card-header">
+                    <view class="type-badge">
+                        <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>
+                </view>
+
+                <!-- 服务时间 -->
+                <text class="service-time">服务时间:{{ order.serviceTime }}</text>
+
+                <!-- 宠物信息卡(灰底)+ 右侧价格 -->
+                <view class="pet-card">
+                    <image class="pet-avatar" :src="order.petAvatar" mode="aspectFill"></image>
+                    <view class="pet-info">
+                        <text class="pet-name">{{ order.petName }}</text>
+                        <text class="pet-breed">品种: {{ order.petBreed }}</text>
+                    </view>
+                    <text class="pet-price">¥{{ order.price }}</text>
+                </view>
+
+                <!-- 路线信息 -->
+                <view class="route-info">
+                    <!-- 接送:取 → 送 -->
+                    <template v-if="order.orderType === 1">
+                        <view class="route-item">
+                            <view class="icon-circle pickup">取</view>
+                            <view class="route-connector"></view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ order.startName }}</text>
+                                <text class="addr-desc">{{ order.startAddr }}</text>
+                            </view>
+                        </view>
+                        <view class="route-item">
+                            <view class="icon-circle deliver">送</view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ order.endName }}</text>
+                                <text class="addr-desc">{{ order.endAddr }}</text>
+                            </view>
+                        </view>
+                    </template>
+                    <!-- 喂遛/洗护:服 -->
+                    <template v-else>
+                        <view class="route-item">
+                            <view class="icon-circle service">服</view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ order.endName }}</text>
+                                <text class="addr-desc">{{ order.endAddr }}</text>
+                            </view>
+                        </view>
+                        <view class="service-note-row" v-if="order.serviceNote">
+                            <text class="service-note-text">服务内容:{{ order.serviceNote }}</text>
+                        </view>
+                    </template>
+                </view>
+            </view>
+
+            <!-- 空状态 -->
+            <view class="empty-state" v-if="filteredOrders.length === 0">
+                <text class="empty-text">暂无相关订单</text>
+            </view>
+            <view style="height: 40rpx;"></view>
+        </scroll-view>
+    </view>
+</template>
+
+<script>
+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: '上门洗澡,剪指甲。'
+                }
+            ]
+        };
+    },
+    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 === '拒绝');
+        }
+    },
+    methods: {
+        switchTab(idx) { this.activeTab = idx; }
+    }
+};
+</script>
+
+<style>
+page { background-color: #F7F8FA; }
+.container { min-height: 100vh; background-color: #F7F8FA; padding: 20rpx 0 0; }
+
+/* ===== 统计banner:圆角浮动卡,左右30rpx边距 ===== */
+.stats-banner {
+    background: linear-gradient(135deg, #FF9800 0%, #FF5722 100%);
+    padding: 28rpx 16rpx;
+    display: flex;
+    justify-content: space-around;
+    margin: 0 30rpx 20rpx;
+    border-radius: 20rpx;
+    box-shadow: 0 6rpx 20rpx rgba(255, 87, 34, 0.25);
+}
+
+.banner-item { display: flex; flex-direction: column; align-items: center; }
+.banner-num { font-size: 34rpx; font-weight: bold; color: #fff; margin-bottom: 4rpx; }
+.banner-unit { font-size: 22rpx; font-weight: normal; }
+.banner-label { font-size: 20rpx; color: rgba(255,255,255,0.85); }
+
+/* ===== 标签页:全宽平铺,无圆角,无side margin ===== */
+.tab-bar {
+    background-color: #fff;
+    display: flex;
+    padding: 0 30rpx;
+    border-bottom: 1rpx solid #f0f0f0;
+    margin-bottom: 0;
+}
+
+.tab-item {
+    padding: 20rpx 24rpx;
+    font-size: 28rpx;
+    color: #999;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.tab-item.active { color: #FF9800; font-weight: bold; }
+
+.tab-line {
+    position: absolute;
+    bottom: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 36rpx;
+    height: 4rpx;
+    background-color: #FF9800;
+    border-radius: 2rpx;
+}
+
+/* ===== 订单列表:scroll-view 全宽,每张card用margin左右30rpx ===== */
+.order-scroll { 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 完全一致 */
+    box-sizing: border-box;
+}
+
+/* 卡片头部 */
+.card-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 10rpx;
+}
+
+.type-badge { display: flex; align-items: center; }
+
+/* 订单类型图标:与my-orders列表一致,直接使用带色彩的SVG图标 */
+.type-icon {
+    width: 44rpx;
+    height: 44rpx;
+    margin-right: 12rpx;
+}
+
+.type-text { font-size: 30rpx; font-weight: bold; color: #333; }
+
+.status-text { font-size: 24rpx; }
+.status-text.green { color: #4CAF50; }
+.status-text.red { color: #F44336; }
+
+/* 服务时间 */
+.service-time {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 16rpx;
+    display: block;
+}
+
+/* 宠物信息卡(灰底背景,右侧显示价格) */
+.pet-card {
+    background-color: #F7F8FA;
+    border-radius: 10rpx;
+    padding: 16rpx 20rpx;
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+}
+
+.pet-avatar { width: 70rpx; height: 70rpx; border-radius: 50%; margin-right: 16rpx; flex-shrink: 0; }
+
+.pet-info { flex: 1; display: flex; flex-direction: column; }
+.pet-name { font-size: 28rpx; font-weight: bold; color: #333; margin-bottom: 4rpx; }
+.pet-breed { font-size: 24rpx; color: #999; }
+
+/* 价格在宠物卡右侧 */
+.pet-price { font-size: 34rpx; font-weight: bold; color: #FF5722; flex-shrink: 0; }
+
+/* 路线信息 */
+.route-info { display: flex; flex-direction: column; }
+
+.route-item {
+    display: flex;
+    align-items: flex-start;
+    position: relative;
+    padding-bottom: 8rpx;
+}
+
+.icon-circle {
+    width: 44rpx;
+    height: 44rpx;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 22rpx;
+    font-weight: bold;
+    color: #fff;
+    flex-shrink: 0;
+    margin-right: 16rpx;
+    margin-top: 2rpx;
+}
+
+.icon-circle.pickup { background: linear-gradient(135deg, #FF9800, #FF6D00); }
+.icon-circle.deliver { background: linear-gradient(135deg, #4CAF50, #2E7D32); }
+.icon-circle.service { background: linear-gradient(135deg, #4CAF50, #1B5E20); }
+
+/* 取→送之间的虚线连接 */
+.route-connector {
+    position: absolute;
+    left: 21rpx;
+    top: 46rpx;
+    width: 2rpx;
+    height: 30rpx;
+    background-color: #e0e0e0;
+}
+
+.address-box { flex: 1; padding-bottom: 14rpx; }
+.addr-title { font-size: 26rpx; color: #333; display: block; margin-bottom: 4rpx; }
+.addr-desc { font-size: 24rpx; color: #999; display: block; }
+
+/* 服务内容说明(喂遛/洗护) */
+.service-note-row { padding: 4rpx 0 0 60rpx; }
+.service-note-text { font-size: 24rpx; color: #999; }
+
+/* 空状态 */
+.empty-state { text-align: center; padding: 80rpx 0; }
+.empty-text { font-size: 28rpx; color: #ccc; }
+</style>

+ 386 - 0
pages/mine/points/detail.vue

@@ -0,0 +1,386 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg"></image>
+            </view>
+            <text class="nav-title">积分明细</text>
+            <view class="nav-right"></view>
+        </view>
+
+        <!-- 内容区域 -->
+        <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>
+                </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>
+
+            <!-- 列表 -->
+            <scroll-view scroll-y class="bill-list">
+                <view v-for="(group, gIndex) in displayGroups" :key="gIndex" class="month-group">
+                    <!-- 月份头 -->
+                    <view class="group-header">
+                        <text class="month-title">{{ group.month }}</text>
+                        <text class="month-summary">获取 {{ group.income }} 扣减 {{ group.expense }}</text>
+                    </view>
+                    
+                    <!-- 列表项 -->
+                    <view class="list-item" v-for="(item, index) in group.items" :key="index">
+                        <!-- 图标 -->
+                        <view class="item-icon-box" :class="item.type">
+                            <text class="item-icon-symbol">{{ item.type === 'income' ? '+' : '-' }}</text>
+                        </view>
+                        
+                        <!-- 中间内容 -->
+                        <view class="item-center">
+                            <text class="item-title">{{ item.title }}</text>
+                            <text class="item-desc">{{ item.time }} {{ item.desc }}</text>
+                        </view>
+
+                        <!-- 右侧数据 -->
+                        <view class="item-right">
+                            <text class="item-amount" :class="{ income: item.type === 'income', expense: item.type === 'expense' }">
+                                {{ item.type === 'income' ? '+' : '' }}{{ item.amount }}
+                            </text>
+                            <view class="item-tag">
+                                <text>{{ item.tag }}</text>
+                            </view>
+                        </view>
+                    </view>
+                </view>
+                <view class="list-padding-bottom"></view>
+            </scroll-view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        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: '系统'
+                        }
+                    ]
+                }
+            ]
+        }
+    },
+    computed: {
+        displayGroups() {
+            if (this.currentTab === 0) return this.groups;
+            
+            return this.groups.map(group => {
+                const filteredItems = group.items.filter(item => {
+                    const type = this.currentTab === 1 ? 'income' : 'expense';
+                    return item.type === type;
+                });
+                return {
+                    ...group,
+                    items: filteredItems
+                };
+            }).filter(group => group.items.length > 0);
+        }
+    },
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        switchTab(index) {
+            this.currentTab = index;
+        }
+    }
+}
+</script>
+
+<style>
+/* 基础容器 */
+.container {
+    background-color: #F5F7FA;
+    min-height: 100vh;
+    display: flex;
+    flex-direction: column;
+}
+
+/* 导航栏 */
+.nav-bar {
+    background-color: #fff;
+    padding-top: var(--status-bar-height);
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    height: 88rpx; 
+    box-sizing: content-box;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+}
+
+.nav-left {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    width: 60rpx;
+}
+
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+    transform: rotate(180deg);
+}
+
+.nav-title {
+    font-size: 28rpx; /* 14pt (Strict) */
+    font-weight: bold;
+    color: #333;
+}
+
+.nav-right {
+    width: 60rpx;
+}
+
+/* 内容区域 */
+.content-area {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+/* Tabs */
+.tabs-row {
+    background-color: #fff;
+    display: flex;
+    justify-content: space-around;
+    padding-top: 20rpx;
+    padding-bottom: 2rpx;
+    margin-bottom: 20rpx;
+}
+
+.tab-item {
+    padding-bottom: 16rpx;
+    font-size: 28rpx;
+    color: #666;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    min-width: 100rpx;
+}
+
+.tab-item.active {
+    font-weight: bold;
+    color: #FF9800;
+}
+
+.tab-line {
+    width: 40rpx;
+    height: 4rpx;
+    background-color: #FF9800;
+    border-radius: 4rpx;
+    position: absolute;
+    bottom: 0;
+}
+
+/* 列表容器 */
+.bill-list {
+    flex: 1;
+    padding: 0 20rpx;
+    box-sizing: border-box;
+}
+
+/* 月份卡片 */
+.month-group {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 0 20rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.02);
+}
+
+.group-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 24rpx 10rpx;
+    border-bottom: 1rpx solid #f9f9f9; 
+}
+
+.month-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.month-summary {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 列表项 */
+.list-item {
+    display: flex;
+    align-items: center;
+    padding: 30rpx 10rpx;
+    border-bottom: 1rpx solid #f9f9f9;
+}
+
+.list-item:last-child {
+    border-bottom: none;
+}
+
+/* 左侧图标 */
+.item-icon-box {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.item-icon-box.income {
+    background-color: #FFF8E1; /* Light Yellow for Points */
+}
+
+.item-icon-box.expense {
+    background-color: #F5F5F5; /* Light Grey for Points */
+}
+
+.item-icon-symbol {
+    font-size: 40rpx;
+    font-weight: 300;
+    line-height: 1;
+    margin-top: -4rpx;
+}
+
+.item-icon-box.income .item-icon-symbol {
+    color: #FF9800; /* Orange */
+}
+
+.item-icon-box.expense .item-icon-symbol {
+    color: #333; /* Black */
+}
+
+/* 中间内容 */
+.item-center {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-around;
+    height: 80rpx;
+}
+
+.item-title {
+    font-size: 28rpx;
+    font-weight: 500;
+    color: #333;
+}
+
+.item-desc {
+    font-size: 22rpx;
+    color: #999;
+    margin-top: 8rpx;
+}
+
+/* 右侧数据 */
+.item-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    justify-content: space-around;
+    height: 80rpx;
+    margin-left: 10rpx;
+}
+
+.item-amount {
+    font-size: 30rpx;
+    font-weight: bold;
+}
+
+.item-amount.income {
+    color: #FF9800;
+}
+
+.item-amount.expense {
+    color: #333;
+}
+
+.item-tag {
+    display: inline-flex;
+    justify-content: flex-end;
+    margin-top: 6rpx;
+}
+
+.item-tag text {
+    background-color: #FFFFFF;
+    border: 1rpx solid #eee;
+    padding: 2rpx 8rpx;
+    border-radius: 6rpx;
+    font-size: 20rpx;
+    color: #999;
+}
+
+.list-padding-bottom {
+    height: 40rpx;
+}
+</style>

+ 378 - 0
pages/mine/points/index.vue

@@ -0,0 +1,378 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg"></image>
+            </view>
+            <text class="nav-title">我的积分</text>
+            <view class="nav-right"></view>
+        </view>
+
+        <!-- 顶部卡片 -->
+        <view class="points-card">
+            <view class="card-header">
+                <view class="equity-btn" @click="navToEquity">
+                    <image class="equity-icon" src="/static/icons/diamond_white.svg"></image>
+                    <text>积分权益</text>
+                </view>
+                <view class="detail-link" @click="navToDetail">
+                    <text>明细</text>
+                </view>
+            </view>
+            <view class="card-body">
+                <text class="label">当前积分</text>
+                <text class="value">1200</text>
+            </view>
+            <!-- 装饰背景 -->
+            <image class="bg-decor" src="/static/icons/star_decor.svg" mode="aspectFit"></image>
+        </view>
+
+        <!-- 最近变动 -->
+        <view class="record-container">
+            <view class="record-header">
+                <text class="header-title">最近积分变动</text>
+                <view class="header-more" @click="navToDetail">
+                    <text>查看全部</text>
+                    <image class="more-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+
+             <!-- 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="record-list">
+                <view class="list-item" v-for="(item, index) in displayList" :key="index">
+                    <view class="item-left">
+                        <text class="item-title">{{ item.title }}</text>
+                        <text class="item-desc">{{ item.desc }}</text>
+                        <text class="item-time">{{ item.time }}</text>
+                    </view>
+                    <view class="item-right">
+                        <text class="item-amount" :class="{ income: item.type === 'income', expense: item.type === 'expense' }">
+                            {{ item.type === 'income' ? '+' : '' }}{{ item.amount }}
+                        </text>
+                        <view class="item-tag">
+                            <text>{{ item.tag }}</text>
+                        </view>
+                    </view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            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: '惩罚'
+                }
+            ]
+        }
+    },
+    computed: {
+        displayList() {
+            if (this.currentTab === 0) return this.list;
+            const type = this.currentTab === 1 ? 'income' : 'expense';
+            return this.list.filter(item => item.type === type);
+        }
+    },
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        navToDetail() {
+            uni.navigateTo({
+                url: '/pages/mine/points/detail'
+            });
+        },
+        navToEquity() {
+            // TODO: 跳转权益页
+        },
+        switchTab(index) {
+            this.currentTab = index;
+        }
+    }
+}
+</script>
+
+<style>
+.container {
+    background-color: #F8F9FA;
+    min-height: 100vh;
+}
+
+.nav-bar {
+    background-color: #fff;
+    padding-top: var(--status-bar-height);
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    height: 88rpx;
+    box-sizing: content-box;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+}
+
+.nav-left {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    width: 60rpx;
+}
+
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+    transform: rotate(180deg);
+}
+
+.nav-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.nav-right {
+    width: 60rpx;
+}
+
+/* 积分卡片 */
+.points-card {
+    margin: 20rpx 30rpx;
+    height: 300rpx;
+    background: linear-gradient(135deg, #FFB74D 0%, #FF9800 100%);
+    border-radius: 20rpx;
+    position: relative;
+    padding: 30rpx;
+    box-sizing: border-box;
+    overflow: hidden;
+    color: #fff;
+    box-shadow: 0 4rpx 16rpx rgba(255, 152, 0, 0.2);
+}
+
+.bg-decor {
+    position: absolute;
+    right: -20rpx;
+    bottom: -20rpx;
+    width: 180rpx;
+    height: 180rpx;
+    opacity: 0.3;
+}
+
+.card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.equity-btn {
+    display: flex;
+    align-items: center;
+    font-size: 26rpx;
+}
+
+.equity-icon {
+    width: 32rpx; /* placeholder icon */
+    height: 32rpx;
+    margin-right: 8rpx;
+    border-radius: 50%;
+    background: rgba(255,255,255,0.3); /* circle bg for icon */
+}
+
+.detail-link {
+    font-size: 24rpx;
+    opacity: 0.9;
+}
+
+.card-body {
+    margin-top: 60rpx;
+}
+
+.label {
+    font-size: 26rpx;
+    opacity: 0.9;
+    display: block;
+    margin-bottom: 10rpx;
+}
+
+.value {
+    font-size: 64rpx;
+    font-weight: bold;
+}
+
+/* 记录区域 */
+.record-container {
+    background-color: #fff;
+    border-radius: 20rpx 20rpx 0 0;
+    padding: 30rpx;
+    min-height: 500rpx;
+}
+
+.record-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.header-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.header-more {
+    display: flex;
+    align-items: center;
+}
+
+.header-more text {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.more-icon {
+    width: 24rpx;
+    height: 24rpx;
+    margin-left: 4rpx;
+}
+
+/* Tabs */
+.tabs-row {
+    display: flex;
+    border-bottom: 1rpx solid #f5f5f5;
+    margin-bottom: 20rpx;
+}
+
+.tab-item {
+    margin-right: 40rpx;
+    padding-bottom: 12rpx;
+    font-size: 28rpx;
+    color: #666;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.tab-item.active {
+    font-weight: bold;
+    color: #333;
+}
+
+.tab-line {
+    width: 28rpx;
+    height: 4rpx;
+    background-color: #FF9800; /* Match card color */
+    border-radius: 4rpx;
+    position: absolute;
+    bottom: 0;
+}
+
+/* 列表 */
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #f9f9f9;
+}
+
+.item-left {
+    display: flex;
+    flex-direction: column;
+}
+
+.item-title {
+    font-size: 28rpx;
+    color: #333;
+    margin-bottom: 8rpx;
+    font-weight: 500;
+}
+
+.item-desc {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 6rpx;
+}
+
+.item-time {
+    font-size: 22rpx;
+    color: #ccc;
+}
+
+.item-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+}
+
+.item-amount {
+    font-size: 30rpx;
+    font-weight: bold;
+    margin-bottom: 8rpx;
+}
+
+.item-amount.income {
+    color: #FF9800; /* Orange for points income */
+}
+
+.item-amount.expense {
+    color: #333;
+}
+
+.item-tag {
+    display: inline-flex;
+    justify-content: flex-end;
+}
+
+.item-tag text {
+    background-color: #F5F5F5;
+    padding: 4rpx 12rpx;
+    border-radius: 6rpx;
+    font-size: 22rpx;
+    color: #999;
+}
+</style>

+ 216 - 0
pages/mine/rewards-all.vue

@@ -0,0 +1,216 @@
+<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>
+        </view>
+
+        <!-- 按月分组列表 -->
+        <scroll-view scroll-y class="main-scroll">
+            <view v-for="(group, gIdx) in filteredGroups" :key="gIdx" class="month-group">
+                <!-- 月份标题 -->
+                <view class="month-header">
+                    <text class="month-title">{{ group.month }}月</text>
+                    <view class="month-summary">
+                        <text class="month-sum-text">已入账¥{{ group.credited.toFixed(2) }}</text>
+                        <text class="month-sum-text"> 待入账¥{{ group.pending.toFixed(2) }}</text>
+                    </view>
+                </view>
+
+                <!-- 记录列 -->
+                <view class="record-item" v-for="(item, rIdx) in group.items" :key="rIdx">
+                    <view class="ri-icon" :class="item.amount > 0 ? 'ri-reward' : 'ri-penalty'">
+                        <text class="ri-icon-text">¥</text>
+                    </view>
+                    <view class="ri-content">
+                        <view class="ri-title-row">
+                            <text class="ri-date">{{ item.date }}</text>
+                            <text class="ri-title">{{ item.title }}</text>
+                        </view>
+                        <text class="ri-desc">{{ item.desc }}</text>
+                    </view>
+                    <view class="ri-right">
+                        <text class="ri-amount" :class="item.amount > 0 ? 'positive' : 'negative'">
+                            {{ item.amount > 0 ? '+' : '' }}{{ item.amount.toFixed(2) }}
+                        </text>
+                        <text class="ri-status" :class="item.statusClass">{{ item.status }}</text>
+                    </view>
+                </view>
+            </view>
+            <view style="height: 40rpx;"></view>
+        </scroll-view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        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' }
+                    ]
+                }
+            ]
+        };
+    },
+    computed: {
+        filteredGroups() {
+            if (this.activeTab === 0) return this.allGroups;
+            const typeKey = this.activeTab === 1 ? 'reward' : 'penalty';
+            return this.allGroups.map(g => ({
+                ...g,
+                items: g.items.filter(i => i.type === typeKey)
+            })).filter(g => g.items.length > 0);
+        }
+    },
+    methods: {
+        switchTab(idx) { this.activeTab = idx; }
+    }
+};
+</script>
+
+<style>
+page { background-color: #F7F8FA; }
+.container { min-height: 100vh; background-color: #F7F8FA; }
+
+.tab-bar {
+    display: flex;
+    background-color: #fff;
+    padding: 0 30rpx;
+}
+
+.tab-item {
+    padding: 18rpx 16rpx 0;
+    font-size: 28rpx;
+    color: #999;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.tab-item:first-child { padding-left: 0; }
+
+.tab-item.active { color: #FF9800; font-weight: bold; }
+
+/* 下划线正常流,自然居中 */
+.tab-line {
+    width: 32rpx;
+    height: 3rpx;
+    background-color: #FF9800;
+    border-radius: 2rpx;
+    margin-top: 8rpx;
+    align-self: center;
+}
+
+.main-scroll { flex: 1; padding: 16rpx 0; }
+
+.month-group {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 0 24rpx;
+    margin: 0 30rpx 16rpx;
+    overflow: hidden;
+}
+
+.month-header {
+    display: flex;
+    align-items: center;
+    padding: 20rpx 0;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+
+.month-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 12rpx;
+}
+
+.month-summary { display: flex; }
+
+.month-sum-text { font-size: 22rpx; color: #999; margin-right: 10rpx; }
+
+.record-item {
+    display: flex;
+    align-items: center;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #f9f9f9;
+}
+
+.ri-icon {
+    width: 72rpx;
+    height: 72rpx;
+    border-radius: 50%;
+    background-color: #FFF3E0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.ri-icon.ri-penalty { background-color: #FAFAFA; }
+
+.ri-icon-text {
+    font-size: 30rpx;
+    color: #FF9800;
+    font-weight: bold;
+}
+
+.ri-icon.ri-penalty .ri-icon-text { color: #ccc; }
+
+.ri-content { flex: 1; }
+
+.ri-title-row { display: flex; align-items: center; margin-bottom: 6rpx; }
+.ri-date { font-size: 26rpx; color: #333; font-weight: bold; margin-right: 10rpx; }
+.ri-title { font-size: 26rpx; color: #333; }
+.ri-desc { font-size: 24rpx; color: #999; }
+
+.ri-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    margin-left: 16rpx;
+}
+
+.ri-amount { font-size: 30rpx; font-weight: bold; margin-bottom: 4rpx; }
+.ri-amount.positive { color: #FF5722; }
+.ri-amount.negative { color: #333; }
+
+.ri-status { font-size: 22rpx; }
+.ri-status.pending { color: #FF9800; }
+.ri-status.credited { color: #999; }
+.ri-status.deducted { color: #999; }
+</style>

+ 421 - 0
pages/mine/rewards.vue

@@ -0,0 +1,421 @@
+<template>
+    <view class="container">
+        <!-- 顶部橙色统计卡 -->
+        <view class="top-banner">
+            <!-- 月份切换:箭头在背景框内紧跟文字 -->
+            <view class="month-btn" @click="openMonthPicker">
+                <text class="month-text">{{ selectedYear }}年{{ selectedMonth }}月 ▾</text>
+            </view>
+            <view class="stats-grid">
+                <view class="stats-cell">
+                    <text class="stats-label">奖励订单</text>
+                    <text class="stats-num">3<text class="stats-unit">单</text></text>
+                    <view class="stats-divider"></view>
+                    <text class="stats-sub">累计 1258单</text>
+                </view>
+                <view class="stats-cell">
+                    <text class="stats-label">惩罚订单</text>
+                    <text class="stats-num">1<text class="stats-unit">单</text></text>
+                    <view class="stats-divider"></view>
+                    <text class="stats-sub">累计 12单</text>
+                </view>
+                <view class="stats-cell">
+                    <text class="stats-label">奖励金额</text>
+                    <text class="stats-num reward-num">2910.00</text>
+                    <view class="stats-divider"></view>
+                    <text class="stats-sub">累计 45800.00</text>
+                </view>
+                <view class="stats-cell">
+                    <text class="stats-label">惩罚金额</text>
+                    <text class="stats-num penalty-num">-15.00</text>
+                    <view class="stats-divider"></view>
+                    <text class="stats-sub">累计 350.00</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- 标签 + 查看全部 -->
+        <view class="list-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="view-all-btn" @click="goToAll">
+                <text class="view-all-text">查看全部 ›</text>
+            </view>
+        </view>
+
+        <!-- 列表 -->
+        <view class="record-list">
+            <view class="record-item" v-for="(item, idx) in filteredList" :key="idx">
+                <!-- 左侧图标 -->
+                <view class="ri-icon" :class="item.amount > 0 ? 'ri-reward' : 'ri-penalty'">
+                    <text class="ri-icon-text">¥</text>
+                </view>
+                <!-- 内容 -->
+                <view class="ri-content">
+                    <view class="ri-title-row">
+                        <text class="ri-date">{{ item.date }}</text>
+                        <text class="ri-title">{{ item.title }}</text>
+                    </view>
+                    <text class="ri-desc">{{ item.desc }}</text>
+                </view>
+                <!-- 右侧金额 + 状态 -->
+                <view class="ri-right">
+                    <text class="ri-amount" :class="item.amount > 0 ? 'positive' : 'negative'">
+                        {{ item.amount > 0 ? '+' : '' }}{{ item.amount.toFixed(2) }}
+                    </text>
+                    <text class="ri-status" :class="item.statusClass">{{ item.status }}</text>
+                </view>
+            </view>
+
+            <!-- 底部提示 -->
+            <text class="more-hint">更多记录请点击上方的查看全部</text>
+        </view>
+
+        <!-- 月份选择器 -->
+        <view class="picker-mask" v-if="showMonthPicker" @click="closeMonthPicker">
+            <view class="picker-sheet" @click.stop>
+                <!-- 顶部操作 -->
+                <view class="picker-header">
+                    <text class="picker-cancel" @click="closeMonthPicker">取消</text>
+                    <text class="picker-title">选择时间</text>
+                    <text class="picker-confirm" @click="confirmMonthPicker">确定</text>
+                </view>
+                <!-- 年月两列 -->
+                <view class="picker-body">
+                    <!-- 年 -->
+                    <scroll-view scroll-y class="picker-column" :scroll-top="yearScrollTop" @scroll="onYearScroll">
+                        <view style="height: 80rpx;"></view>
+                        <view
+                            class="picker-col-item"
+                            v-for="year in years"
+                            :key="year"
+                            :class="{ 'picker-selected': pickerYear === year }"
+                            @click="pickerYear = year"
+                        >{{ year }}年</view>
+                        <view style="height: 80rpx;"></view>
+                    </scroll-view>
+                    <!-- 选中高亮条 -->
+                    <view class="picker-highlight"></view>
+                    <!-- 月 -->
+                    <scroll-view scroll-y class="picker-column" :scroll-top="monthScrollTop" @scroll="onMonthScroll">
+                        <view style="height: 80rpx;"></view>
+                        <view
+                            class="picker-col-item"
+                            v-for="month in months"
+                            :key="month"
+                            :class="{ 'picker-selected': pickerMonth === month }"
+                            @click="pickerMonth = month"
+                        >{{ month }}月</view>
+                        <view style="height: 80rpx;"></view>
+                    </scroll-view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            tabs: ['全部', '奖励', '惩罚'],
+            activeTab: 0,
+            selectedYear: 2026,
+            selectedMonth: 2,
+            // 月份选择器状态
+            showMonthPicker: false,
+            pickerYear: 2026,
+            pickerMonth: 2,
+            years: [2021, 2022, 2023, 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' }
+            ]
+        };
+    },
+    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');
+        }
+    },
+    methods: {
+        switchTab(idx) { this.activeTab = idx; },
+        openMonthPicker() {
+            this.pickerYear = this.selectedYear;
+            this.pickerMonth = this.selectedMonth;
+            this.showMonthPicker = true;
+        },
+        closeMonthPicker() { this.showMonthPicker = false; },
+        confirmMonthPicker() {
+            this.selectedYear = this.pickerYear;
+            this.selectedMonth = this.pickerMonth;
+            this.closeMonthPicker();
+        },
+        goToAll() {
+            uni.navigateTo({ url: '/pages/mine/rewards-all' });
+        }
+    }
+};
+</script>
+
+<style>
+page { background-color: #F7F8FA; }
+.container { min-height: 100vh; background-color: #F7F8FA; }
+
+/* 顶部橙色banner */
+.top-banner {
+    background: linear-gradient(135deg, #FF9800 0%, #FF5722 100%);
+    padding: 20rpx 30rpx 36rpx;
+    border-radius: 20rpx;
+    margin: 20rpx 30rpx 0;
+    box-shadow: 0 6rpx 20rpx rgba(255, 87, 34, 0.25);
+}
+
+.month-btn {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-bottom: 20rpx;
+}
+
+/* 年月文字和箭头在同一个圆角背景框内 */
+.month-text {
+    font-size: 24rpx;
+    color: rgba(255,255,255,0.95);
+    background-color: rgba(255,255,255,0.2);
+    padding: 6rpx 14rpx;
+    border-radius: 14rpx;
+}
+
+.stats-grid {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16rpx;
+}
+
+.stats-cell {
+    width: calc(50% - 8rpx);
+    background-color: rgba(255,255,255,0.15);
+    border-radius: 12rpx;
+    padding: 20rpx 24rpx;
+    display: flex;
+    flex-direction: column;
+    box-sizing: border-box;
+}
+
+.stats-num {
+    font-size: 38rpx;
+    font-weight: bold;
+    color: #fff;
+    margin-bottom: 8rpx;
+}
+
+.stats-unit { font-size: 20rpx; font-weight: normal; }
+
+.stats-num.reward-num { color: #fff; }
+.stats-num.penalty-num { color: #FFF176; }
+
+.stats-label {
+    font-size: 22rpx;
+    color: rgba(255,255,255,0.85);
+    margin-bottom: 8rpx;
+}
+
+/* 统计数字下方的分割线 */
+.stats-divider {
+    height: 1rpx;
+    background-color: rgba(255,255,255,0.3);
+    margin-bottom: 10rpx;
+}
+
+.stats-sub { font-size: 20rpx; color: rgba(255,255,255,0.65); }
+
+/* 列表头:tab栏无底部外框线 */
+.list-header {
+    display: flex;
+    align-items: center;
+    background-color: #fff;
+    padding: 0 16rpx 0 30rpx;
+    margin: 16rpx 30rpx 0;
+    border-radius: 16rpx 16rpx 0 0;
+}
+
+.tab-bar { display: flex; flex: 1; }
+
+.tab-item {
+    padding: 18rpx 16rpx 0;
+    font-size: 28rpx;
+    color: #999;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    position: relative;
+}
+
+.tab-item:first-child { padding-left: 0; }
+
+.tab-item.active { color: #FF9800; font-weight: bold; }
+
+/* 下划线用正常流,自然居中对齐文字 */
+.tab-line {
+    width: 32rpx;
+    height: 3rpx;
+    background-color: #FF9800;
+    border-radius: 2rpx;
+    margin-top: 8rpx;
+    align-self: center;
+}
+
+
+
+.view-all-btn { padding: 8rpx 0; margin-left: auto; }
+.view-all-text { font-size: 24rpx; color: #999; }
+
+/* 记录列表 */
+.record-list {
+    background-color: #fff;
+    padding: 0 30rpx;
+    margin: 0 30rpx;
+    border-radius: 0 0 16rpx 16rpx;
+}
+
+.record-item {
+    display: flex;
+    align-items: center;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+
+.ri-icon {
+    width: 72rpx;
+    height: 72rpx;
+    border-radius: 50%;
+    background-color: #FFF3E0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.ri-icon.ri-penalty { background-color: #FAFAFA; }
+
+.ri-icon-text {
+    font-size: 30rpx;
+    color: #FF9800;
+    font-weight: bold;
+}
+
+.ri-icon.ri-penalty .ri-icon-text { color: #ccc; }
+
+.ri-content { flex: 1; }
+
+.ri-title-row { display: flex; align-items: center; margin-bottom: 6rpx; }
+.ri-date { font-size: 26rpx; color: #333; font-weight: bold; margin-right: 10rpx; }
+.ri-title { font-size: 26rpx; color: #333; }
+.ri-desc { font-size: 24rpx; color: #999; }
+
+.ri-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    margin-left: 16rpx;
+}
+
+.ri-amount { font-size: 32rpx; font-weight: bold; margin-bottom: 4rpx; }
+.ri-amount.positive { color: #FF5722; }
+.ri-amount.negative { color: #333; }
+
+.ri-status { font-size: 22rpx; }
+.ri-status.pending { color: #FF9800; }
+.ri-status.credited { color: #999; }
+.ri-status.deducted { color: #999; }
+
+.more-hint { display: block; text-align: center; font-size: 24rpx; color: #ccc; padding: 30rpx 0; }
+
+/* 月份选择器 */
+.picker-mask {
+    position: fixed;
+    top: 0; left: 0;
+    width: 100%; height: 100%;
+    background-color: rgba(0,0,0,0.5);
+    z-index: 999;
+    display: flex;
+    align-items: flex-end;
+}
+
+.picker-sheet {
+    width: 100%;
+    background-color: #fff;
+    border-radius: 24rpx 24rpx 0 0;
+}
+
+.picker-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 24rpx 30rpx;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+
+.picker-cancel { font-size: 28rpx; color: #999; }
+.picker-title { font-size: 30rpx; font-weight: bold; color: #333; }
+.picker-confirm { font-size: 28rpx; color: #FF9800; font-weight: bold; }
+
+.picker-body {
+    display: flex;
+    height: 400rpx;
+    position: relative;
+    overflow: hidden;
+}
+
+.picker-column {
+    flex: 1;
+    height: 400rpx;
+}
+
+.picker-col-item {
+    height: 80rpx;
+    line-height: 80rpx;
+    text-align: center;
+    font-size: 28rpx;
+    color: #333;
+}
+
+.picker-col-item.picker-selected {
+    color: #FF9800;
+    font-weight: bold;
+    background-color: #FFF3E0;
+    border-radius: 8rpx;
+}
+
+.picker-highlight {
+    position: absolute;
+    top: 50%;
+    left: 0;
+    transform: translateY(-50%);
+    width: 100%;
+    height: 80rpx;
+    border-top: 1rpx solid #f0f0f0;
+    border-bottom: 1rpx solid #f0f0f0;
+    pointer-events: none;
+}
+</style>

+ 160 - 0
pages/mine/settings/about/index.vue

@@ -0,0 +1,160 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">关于我们</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <view class="logo-area">
+            <image class="app-logo" src="/static/logo.png" mode="aspectFit"></image>
+            <text class="app-name">履约者APP</text>
+            <text class="app-version">Version 2.0.6</text>
+        </view>
+
+        <view class="group-card">
+            <view class="list-item">
+                <text class="item-title">服务协议</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+            <view class="list-item">
+                <text class="item-title">隐私政策</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+            <view class="list-item no-border">
+                <text class="item-title">版本更新</text>
+                <view class="item-right">
+                    <view class="badge-yellow">1</view>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+        
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+}
+
+.logo-area {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 60rpx 0;
+}
+.app-logo {
+    width: 160rpx;
+    height: 160rpx;
+    border-radius: 30rpx;
+    margin-bottom: 20rpx;
+    /* gradient background is usually part of the logo image itself, assuming logo.png is complete */
+}
+.app-name {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 10rpx;
+}
+.app-version {
+    font-size: 28rpx;
+    color: #999;
+}
+
+.group-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+}
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: 1px solid #F5F5F5;
+}
+.list-item.no-border {
+    border-bottom: none;
+}
+.item-title {
+    font-size: 28rpx;
+    color: #333;
+}
+.item-right {
+    display: flex;
+    align-items: center;
+}
+.arrow-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.5;
+    margin-left: 10rpx;
+}
+.badge-yellow {
+    width: 36rpx;
+    height: 36rpx;
+    background-color: #FFC107;
+    color: #fff;
+    font-size: 24rpx;
+    line-height: 36rpx;
+    text-align: center;
+    border-radius: 6rpx;
+}
+</style>

+ 296 - 0
pages/mine/settings/auth/index.vue

@@ -0,0 +1,296 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">认证信息</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <!-- 身份认证 -->
+        <view class="card">
+            <view class="section-header">
+                <view class="orange-bar"></view>
+                <text class="section-title">身份认证</text>
+                <view class="tag-green">已认证</view>
+            </view>
+            <view class="info-row">
+                <text class="label">真实姓名</text>
+                <text class="value">张三哥</text>
+            </view>
+            <view class="info-row">
+                <text class="label">证件号码</text>
+                <text class="value">4403**********1234</text>
+            </view>
+            <view class="id-card-row">
+                <view class="id-card-box green-bg">
+                    <text class="id-text">ID Front</text>
+                    <view class="corner-tag">人像面</view>
+                </view>
+                <view class="id-card-box green-bg">
+                    <text class="id-text">ID Back</text>
+                    <view class="corner-tag">国徽面</view>
+                </view>
+            </view>
+        </view>
+
+        <!-- 服务类型 -->
+        <view class="card">
+            <view class="section-header">
+                <view class="orange-bar"></view>
+                <text class="section-title">服务类型</text>
+            </view>
+            <view class="tags-row">
+                <view class="service-tag">宠物接送</view>
+                <view class="service-tag">上门喂遛</view>
+            </view>
+        </view>
+
+        <!-- 资质证书 -->
+        <view class="card">
+            <view class="section-header">
+                <view class="orange-bar"></view>
+                <text class="section-title">资质证书</text>
+            </view>
+            
+            <text class="sub-title">宠物接送服务资质</text>
+            <view class="cert-row">
+                <view class="cert-box yellow-bg">
+                    <text class="cert-text orange">Cert 1</text>
+                </view>
+                <view class="cert-box yellow-bg">
+                    <text class="cert-text orange">Cert 2</text>
+                </view>
+            </view>
+
+            <text class="sub-title">上门喂遛服务资质</text>
+            <view class="cert-row">
+                <view class="cert-box blue-bg">
+                    <text class="cert-text blue">Cert 3</text>
+                </view>
+            </view>
+
+            <text class="sub-title">上门洗护服务资质</text>
+            <view class="cert-row">
+                <view class="cert-box green-light-bg">
+                    <text class="cert-text green">Cert 4</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- 修改按钮 -->
+        <view class="bottom-btn-area">
+            <button class="action-btn" @click="editAuth">修改认证信息</button>
+            <text class="tips">修改认证信息需要重新审核,审核期间无法接单</text>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        editAuth() {
+            uni.showToast({ title: '跳转修改认证页', icon: 'none' });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: content-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+    padding-bottom: 100rpx;
+}
+.card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 30rpx;
+    margin-bottom: 30rpx;
+}
+.section-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+}
+.orange-bar {
+    width: 8rpx;
+    height: 32rpx;
+    background-color: #FF5722;
+    border-radius: 4rpx;
+    margin-right: 16rpx;
+}
+.section-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    flex: 1;
+}
+.tag-green {
+    font-size: 24rpx;
+    color: #4CAF50;
+    background-color: #E8F5E9;
+    padding: 4rpx 12rpx;
+    border-radius: 8rpx;
+}
+
+.info-row {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 20rpx;
+}
+.label {
+    font-size: 28rpx;
+    color: #999;
+}
+.value {
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+
+.id-card-row {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 20rpx;
+}
+.id-card-box {
+    width: 48%;
+    height: 180rpx;
+    border-radius: 12rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+    overflow: hidden;
+}
+.green-bg {
+    background-color: #E8F5E9;
+}
+.id-text {
+    font-size: 36rpx;
+    color: #4CAF50;
+    font-weight: bold;
+}
+.corner-tag {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0,0,0,0.5);
+    color: #fff;
+    font-size: 20rpx;
+    padding: 4rpx 10rpx;
+    border-top-left-radius: 8rpx;
+}
+
+.tags-row {
+    display: flex;
+    flex-wrap: wrap;
+}
+.service-tag {
+    background-color: #FFF3E0;
+    color: #FF9800;
+    font-size: 26rpx;
+    padding: 10rpx 30rpx;
+    border-radius: 30rpx;
+    margin-right: 20rpx;
+    margin-bottom: 20rpx;
+}
+
+.sub-title {
+    font-size: 28rpx;
+    color: #666;
+    margin-top: 10rpx;
+    margin-bottom: 20rpx;
+    display: block;
+}
+.cert-row {
+    display: flex;
+    flex-wrap: wrap;
+    margin-bottom: 20rpx;
+}
+.cert-box {
+    width: 180rpx;
+    height: 180rpx;
+    border-radius: 12rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    margin-bottom: 20rpx;
+}
+.yellow-bg { background-color: #FFF8E1; }
+.blue-bg { background-color: #E3F2FD; }
+.green-light-bg { background-color: #F1F8E9; }
+
+.cert-text { font-size: 32rpx; font-weight: bold; }
+.cert-text.orange { color: #FFA000; }
+.cert-text.blue { color: #2196F3; }
+.cert-text.green { color: #8BC34A; }
+
+.bottom-btn-area {
+    margin-top: 40rpx;
+    text-align: center;
+}
+.action-btn {
+    background-color: #fff;
+    color: #FF5722;
+    border: 1px solid #FF5722;
+    font-size: 32rpx;
+    border-radius: 44rpx;
+    height: 88rpx;
+    line-height: 88rpx;
+}
+.tips {
+    display: block;
+    font-size: 24rpx;
+    color: #999;
+    margin-top: 20rpx;
+}
+</style>

+ 191 - 0
pages/mine/settings/bank/index.vue

@@ -0,0 +1,191 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">银行卡信息</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <!-- 银行卡卡片 -->
+        <view class="bank-card">
+            <view class="card-top">
+                <view class="bank-info">
+                    <view class="bank-icon-circle">
+                        <text class="bank-icon-text">招</text>
+                    </view>
+                    <text class="bank-name">招商银行</text>
+                </view>
+                <view class="card-type">储蓄卡</view>
+            </view>
+            <view class="card-number">622588******1234</view>
+            <view class="card-bg-circle"></view>
+        </view>
+
+        <!-- 修改按钮 -->
+        <button class="action-btn" @click="editBank">修改银行卡信息</button>
+
+        <!-- 底部提示 -->
+        <view class="security-tip">
+            <image class="shield-icon" src="/static/icons/shield.svg" v-if="hasShieldIcon"></image>
+            <text>信息已加密,仅用于收入发放</text>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            hasShieldIcon: false // 如果没有盾牌图标资源,暂时隐藏或用文字代替
+        }
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        editBank() {
+            uni.showToast({ title: '跳转修改银行卡页', icon: 'none' });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: content-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 30rpx;
+}
+
+.bank-card {
+    background: linear-gradient(135deg, #E53935, #C62828);
+    border-radius: 20rpx;
+    padding: 40rpx;
+    color: #fff;
+    margin-bottom: 60rpx;
+    position: relative;
+    overflow: hidden;
+    box-shadow: 0 10rpx 30rpx rgba(229, 57, 53, 0.3);
+}
+
+.card-top {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 60rpx;
+    position: relative;
+    z-index: 2;
+}
+.bank-info {
+    display: flex;
+    align-items: center;
+}
+.bank-icon-circle {
+    width: 60rpx;
+    height: 60rpx;
+    background-color: #fff;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+}
+.bank-icon-text {
+    color: #C62828;
+    font-weight: bold;
+    font-size: 32rpx;
+}
+.bank-name {
+    font-size: 32rpx;
+    font-weight: bold;
+}
+.card-type {
+    font-size: 24rpx;
+    border: 1px solid rgba(255,255,255,0.6);
+    padding: 4rpx 12rpx;
+    border-radius: 8rpx;
+}
+
+.card-number {
+    font-size: 48rpx;
+    font-family: monospace;
+    letter-spacing: 4rpx;
+    position: relative;
+    z-index: 2;
+    text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.2);
+}
+
+.card-bg-circle {
+    position: absolute;
+    top: -50rpx;
+    right: -50rpx;
+    width: 300rpx;
+    height: 300rpx;
+    background-color: rgba(255,255,255,0.1);
+    border-radius: 50%;
+    z-index: 1;
+}
+
+.action-btn {
+    background-color: #FF5722;
+    color: #fff;
+    font-size: 32rpx;
+    border-radius: 44rpx;
+    height: 88rpx;
+    line-height: 88rpx;
+    margin-bottom: 30rpx;
+}
+
+.security-tip {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 24rpx;
+    color: #999;
+}
+.shield-icon {
+    width: 24rpx;
+    height: 24rpx;
+    margin-right: 10rpx;
+}
+</style>

+ 212 - 0
pages/mine/settings/index.vue

@@ -0,0 +1,212 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">设置</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <!-- 个人信息组 -->
+        <view class="group-card">
+            <view class="list-item" @click="navTo('profile')">
+                <text class="item-title">个人资料</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+            <view class="list-item" @click="navTo('auth')">
+                <text class="item-title">认证信息</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+            <view class="list-item" @click="navTo('bank')">
+                <text class="item-title">银行卡信息</text>
+                <view class="item-right">
+                    <view class="tag-status">已完善</view>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item no-border" @click="navTo('security')">
+                <text class="item-title">账号与安全</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+        </view>
+
+        <!-- 应用设置组 -->
+        <view class="group-card">
+            <view class="list-item" @click="navTo('push')">
+                <text class="item-title">推送通知</text>
+                <view class="item-right">
+                    <text class="item-value">部分开启</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item">
+                <view class="item-row-left">
+                    <text class="item-title">位置上报</text>
+                    <text class="item-subtitle">每隔20分钟自动上报位置</text>
+                </view>
+                <switch checked color="#FF5722" style="transform:scale(0.8)"/>
+            </view>
+            <view class="list-item" @click="clearCache">
+                <text class="item-title">清理缓存</text>
+                <view class="item-right">
+                    <text class="item-value">105.14MB</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item no-border" @click="navTo('about')">
+                <text class="item-title">关于我们</text>
+                 <view class="item-right">
+                    <text class="item-value">v2.0.6</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        navTo(type) {
+            let url = '';
+            switch(type) {
+                case 'profile':
+                    url = '/pages/mine/settings/profile/index';
+                    break;
+                case 'auth':
+                    url = '/pages/mine/settings/auth/index';
+                    break;
+                case 'bank':
+                    url = '/pages/mine/settings/bank/index';
+                    break;
+                case 'security':
+                    url = '/pages/mine/settings/security/index';
+                    break;
+                case 'push':
+                    url = '/pages/mine/settings/notification/index';
+                    break;
+                case 'about':
+                    url = '/pages/mine/settings/about/index';
+                    break;
+                default:
+                    console.log('Navigate to:', type);
+                    return;
+            }
+            uni.navigateTo({ url });
+        },
+        clearCache() {
+            uni.showToast({ title: '缓存已清理', icon: 'none' });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: content-box; /* Exclude padding from height calculation if needed, or adjust */
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 28rpx; /* 14pt */
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+}
+.group-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+    margin-bottom: 30rpx;
+}
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: 1px solid #F5F5F5;
+}
+.list-item.no-border {
+    border-bottom: none;
+}
+.item-title {
+    font-size: 28rpx; /* 14pt */
+    color: #333;
+}
+.item-right {
+    display: flex;
+    align-items: center;
+}
+.arrow-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.5;
+    margin-left: 10rpx;
+}
+.tag-status {
+    font-size: 22rpx;
+    color: #4CAF50;
+    background-color: #F1F8E9;
+    padding: 4rpx 10rpx;
+    border-radius: 6rpx;
+    margin-right: 6rpx;
+}
+.item-value {
+    font-size: 28rpx; /* Changed to 14pt (28rpx) */
+    color: #999;
+}
+.item-column {
+    display: flex;
+    flex-direction: column;
+}
+.item-row-left {
+    display: flex;
+    align-items: center;
+}
+.item-subtitle {
+    font-size: 24rpx; /* Changed to 12pt (24rpx) for better legibility */
+    color: #999;
+    margin-left: 20rpx; /* Moved to right of title */
+    margin-top: 0;
+}
+</style>

+ 113 - 0
pages/mine/settings/notification/index.vue

@@ -0,0 +1,113 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">推送通知设置</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <view class="group-card">
+            <view class="list-item">
+                <text class="item-title">系统消息通知</text>
+                <switch checked color="#FF5722" style="transform:scale(0.8)"  @change="switchChange('system', $event)" />
+            </view>
+            <view class="list-item no-border">
+                <text class="item-title">订单消息通知</text>
+                <switch checked color="#FF5722" style="transform:scale(0.8)" @change="switchChange('order', $event)" />
+            </view>
+        </view>
+        
+        <text class="tips-text">关闭通知后将收不到消息通知推送</text>
+
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        switchChange(type, e) {
+            console.log('switch change', type, e.detail.value);
+            // 实际开发中需调用 API 更新设置
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 32rpx; /* 16pt based on design req, though previous pages used 14pt (28rpx). Sticking to consistency with previous pages might be better but user requested specifically for this task based on screenshot which looks a bit large. Let's stick to 32rpx for title as requested earlier for uniformity */
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+}
+.group-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+    margin-bottom: 20rpx;
+}
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: 1px solid #F5F5F5;
+}
+.list-item.no-border {
+    border-bottom: none;
+}
+.item-title {
+    font-size: 28rpx;
+    color: #333;
+}
+.tips-text {
+    font-size: 24rpx;
+    color: #999;
+    padding-left: 10rpx;
+}
+</style>

+ 137 - 0
pages/mine/settings/profile/edit-name.vue

@@ -0,0 +1,137 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">修改真实姓名</text>
+            <view class="header-right" @click="saveName">
+                <text class="save-btn">保存</text>
+            </view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <view class="input-card">
+            <input class="name-input" type="text" v-model="name" placeholder="请输入真实姓名" />
+            <view class="clear-icon" v-if="name.length > 0" @click="clearName">
+                <text class="clear-text">×</text>
+            </view>
+        </view>
+        <text class="input-tip">请确保填写真实有效的信息,方便管理员审核。</text>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            name: '张*哥'
+        }
+    },
+    onLoad(option) {
+        if(option.name) {
+            this.name = option.name;
+        }
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        clearName() {
+            this.name = '';
+        },
+        saveName() {
+            if(!this.name.trim()) {
+                uni.showToast({ title: '姓名不能为空', icon: 'none' });
+                return;
+            }
+            // 模拟保存并通知上一个页面更新
+            uni.$emit('updateName', this.name);
+            uni.navigateBack();
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: border-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 32rpx; /* 16pt based on design req */
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    /* width: 40rpx; removed fixed width to fit text */
+}
+.save-btn {
+    font-size: 28rpx;
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.container {
+    padding: 30rpx;
+}
+.input-card {
+    background-color: #fff;
+    border-radius: 12rpx;
+    padding: 20rpx 30rpx;
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+.name-input {
+    flex: 1;
+    font-size: 32rpx;
+    color: #333;
+    height: 60rpx;
+}
+.clear-icon {
+    width: 36rpx;
+    height: 36rpx;
+    background-color: #CCCCCC;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+.clear-text {
+    color: #fff;
+    font-size: 28rpx;
+    line-height: 28rpx;
+    margin-top: -2rpx; /* Visual adjustment */
+}
+.input-tip {
+    font-size: 24rpx;
+    color: #999;
+}
+</style>

+ 438 - 0
pages/mine/settings/profile/index.vue

@@ -0,0 +1,438 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">个人资料</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+
+        <view class="group-card">
+            <view class="list-item" @click="changeAvatar">
+                <text class="item-title">头像</text>
+                <view class="item-right">
+                    <image class="user-avatar" :src="userInfo.avatar" mode="aspectFill"></image>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item" @click="editName">
+                <text class="item-title">真实姓名</text>
+                <view class="item-right">
+                    <text class="item-value">{{ userInfo.name }}</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+        <view class="group-card">
+            <view class="list-item">
+                <text class="item-title">工作类型</text>
+                <view class="tag-blue-outline">{{ userInfo.workType }}</view>
+            </view>
+            <view class="list-item" @click="showStatusPicker">
+                <text class="item-title">工作状态</text>
+                <view class="item-right">
+                    <text class="item-value-black">{{ userInfo.workStatus }}</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+        <view class="group-card">
+            <view class="list-item" @click="showCityPicker">
+                <text class="item-title">工作城市</text>
+                <view class="item-right">
+                    <text class="item-value">{{ userInfo.city }}</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item no-border">
+                <text class="item-title">所属站点</text>
+                <view class="item-right">
+                    <text class="item-value">深圳市龙华区民治街道第一站</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- 工作状态选择弹窗 -->
+        <view class="popup-mask" v-if="isStatusPickerShow" @click="closeStatusPicker">
+            <view class="popup-content" @click.stop>
+                <view class="popup-title">选择工作状态</view>
+                <view class="popup-item" @click="selectStatus('接单中')">接单中</view>
+                <view class="popup-item" @click="selectStatus('休息中')">休息中</view>
+                <view class="popup-cancel" @click="closeStatusPicker">取消</view>
+            </view>
+        </view>
+
+        <!-- 城市选择弹窗 (模拟) -->
+        <view class="popup-mask" v-if="isCityPickerShow" @click="closeCityPicker">
+            <view class="popup-content" @click.stop>
+                <view class="popup-header-row">
+                    <text class="popup-btn-cancel" @click="closeCityPicker">取消</text>
+                    <text class="popup-title-text">请选择工作城市</text>
+                    <text class="popup-btn-confirm" @click="confirmCity">确定</text>
+                </view>
+                <view class="city-tabs">
+                    <view 
+                        class="city-tab-item" 
+                        :class="{ 'active': cityStep > 0, 'active-red': cityStep === 0 }"
+                        @click="changeCityStep(0)">
+                        {{ selectedProvince || '请选择' }}
+                    </view>
+                    <view 
+                        class="city-tab-item" 
+                        :class="{ 'active': cityStep > 1, 'active-red': cityStep === 1 }"
+                        v-if="selectedProvince"
+                        @click="changeCityStep(1)">
+                        {{ selectedCity || '请选择' }}
+                    </view>
+                     <view 
+                        class="city-tab-item" 
+                        :class="{ 'active-red': cityStep === 2 }"
+                        v-if="selectedCity"
+                        @click="changeCityStep(2)">
+                        {{ selectedDistrict || '请选择' }}
+                    </view>
+                </view>
+                <scroll-view scroll-y class="city-list">
+                    <view 
+                        class="city-item" 
+                        v-for="(item, index) in currentList" 
+                        :key="index"
+                        @click="selectItem(item)">
+                        {{ item }}
+                        <text v-if="isSelected(item)" style="float: right; color: #FF5722;">✓</text>
+                    </view>
+                </scroll-view>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            userInfo: {
+                name: '张*哥',
+                workType: '全职',
+                workStatus: '接单中',
+                city: '广东省 深圳市 龙华区',
+                avatar: '/static/touxiang.png'
+            },
+            isStatusPickerShow: false,
+            isCityPickerShow: false,
+            
+            // 城市选择相关
+            cityStep: 0, // 0: 省, 1: 市, 2: 区
+            selectedProvince: '',
+            selectedCity: '',
+            selectedDistrict: '',
+            
+            // 模拟数据
+            provinces: ['广东省', '湖南省', '江西省'],
+            cities: {
+                '广东省': ['深圳市', '广州市', '东莞市'],
+                '湖南省': ['长沙市', '株洲市'],
+                '江西省': ['南昌市', '九江市']
+            },
+            districts: {
+                '深圳市': ['龙华区', '南山区', '福田区', '宝安区'],
+                '广州市': ['天河区', '越秀区', '海珠区'],
+                '东莞市': ['南城区', '东城区'],
+                '长沙市': ['岳麓区', '芙蓉区'],
+                '南昌市': ['红谷滩区', '东湖区']
+            }
+        }
+    },
+    computed: {
+        currentList() {
+            if (this.cityStep === 0) {
+                return this.provinces;
+            } else if (this.cityStep === 1) {
+                return this.cities[this.selectedProvince] || [];
+            } else if (this.cityStep === 2) {
+                return this.districts[this.selectedCity] || [];
+            }
+            return [];
+        }
+    },
+    onLoad() {
+        // 监听姓名修改
+        uni.$on('updateName', (newName) => {
+            this.userInfo.name = newName;
+        });
+    },
+    onUnload() {
+        uni.$off('updateName');
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        changeAvatar() {
+            uni.chooseImage({
+                count: 1,
+                success: (res) => {
+                    console.log(res.tempFilePaths);
+                    this.userInfo.avatar = res.tempFilePaths[0];
+                }
+            });
+        },
+        editName() {
+            uni.navigateTo({
+                url: `/pages/mine/settings/profile/edit-name?name=${this.userInfo.name}`
+            });
+        },
+        toggleWorkType() {
+            // 简单模拟切换
+            this.userInfo.workType = this.userInfo.workType === '全职' ? '兼职' : '全职';
+        },
+        showStatusPicker() {
+            this.isStatusPickerShow = true;
+        },
+        closeStatusPicker() {
+            this.isStatusPickerShow = false;
+        },
+        selectStatus(status) {
+            this.userInfo.workStatus = status;
+            this.closeStatusPicker();
+        },
+        
+        // 城市选择逻辑
+        showCityPicker() {
+            this.isCityPickerShow = true;
+            // 初始化/重置
+            this.cityStep = 0;
+            this.selectedProvince = '';
+            this.selectedCity = '';
+            this.selectedDistrict = '';
+            
+            // 如果已有值,尝试回显 (这里简化处理,只重置)
+            // 实际开发可解析 this.userInfo.city 进行回显
+        },
+        closeCityPicker() {
+            this.isCityPickerShow = false;
+        },
+        changeCityStep(step) {
+            this.cityStep = step;
+        },
+        selectItem(item) {
+            if (this.cityStep === 0) {
+                this.selectedProvince = item;
+                this.cityStep = 1;
+                this.selectedCity = ''; // 重置下级
+                this.selectedDistrict = '';
+            } else if (this.cityStep === 1) {
+                this.selectedCity = item;
+                this.cityStep = 2;
+                this.selectedDistrict = '';
+            } else if (this.cityStep === 2) {
+                this.selectedDistrict = item;
+            }
+        },
+        isSelected(item) {
+            if (this.cityStep === 0) return this.selectedProvince === item;
+            if (this.cityStep === 1) return this.selectedCity === item;
+            if (this.cityStep === 2) return this.selectedDistrict === item;
+            return false;
+        },
+        confirmCity() {
+            if (this.selectedProvince && this.selectedCity && this.selectedDistrict) {
+                this.userInfo.city = `${this.selectedProvince} ${this.selectedCity} ${this.selectedDistrict}`;
+                this.closeCityPicker();
+            } else {
+                uni.showToast({
+                    title: '请选择完整的省市区',
+                    icon: 'none'
+                });
+            }
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: content-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 28rpx; /* 14pt */
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+}
+.group-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+    margin-bottom: 30rpx;
+}
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: 1px solid #F5F5F5;
+}
+.list-item.no-border {
+    border-bottom: none;
+}
+.item-title {
+    font-size: 28rpx;
+    color: #333;
+}
+.item-right {
+    display: flex;
+    align-items: center;
+}
+.arrow-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.5;
+    margin-left: 10rpx;
+}
+.user-avatar {
+    width: 64rpx; /* Smaller avatar */
+    height: 64rpx;
+    border-radius: 50%;
+}
+.item-value {
+    font-size: 28rpx;
+    color: #999;
+}
+.item-value-black {
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+.tag-blue-outline {
+    font-size: 24rpx;
+    color: #2979FF;
+    border: 1px solid #2979FF;
+    padding: 4rpx 20rpx;
+    border-radius: 30rpx;
+    background-color: #fff;
+}
+
+/* Popup Styles */
+.popup-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0,0,0,0.5);
+    z-index: 999;
+    display: flex;
+    align-items: flex-end;
+}
+.popup-content {
+    width: 100%;
+    background-color: #fff;
+    border-top-left-radius: 20rpx;
+    border-top-right-radius: 20rpx;
+    padding-bottom: 30rpx; /* Safe area */
+}
+.popup-title {
+    text-align: center;
+    font-size: 28rpx;
+    color: #999;
+    padding: 30rpx 0;
+    border-bottom: 1px solid #eee;
+}
+.popup-item {
+    text-align: center;
+    font-size: 32rpx;
+    color: #333;
+    padding: 30rpx 0;
+    border-bottom: 1px solid #eee;
+}
+.popup-cancel {
+    text-align: center;
+    font-size: 32rpx;
+    color: #333;
+    padding: 30rpx 0;
+    margin-top: 20rpx;
+    border-top: 10rpx solid #f5f5f5;
+}
+
+.popup-header-row {
+    display: flex;
+    justify-content: space-between;
+    padding: 30rpx;
+    border-bottom: 1px solid #eee;
+}
+.popup-btn-cancel { font-size: 28rpx; color: #666; }
+.popup-title-text { font-size: 32rpx; font-weight: bold; color: #333; }
+.popup-btn-confirm { font-size: 28rpx; color: #FF5722; font-weight: bold; }
+
+.city-tabs {
+    display: flex;
+    padding: 20rpx 30rpx;
+    border-bottom: 1px solid #eee;
+}
+.city-tab-item {
+    font-size: 28rpx;
+    margin-right: 40rpx;
+    position: relative;
+    padding-bottom: 10rpx;
+}
+.city-tab-item.active { color: #333; }
+.city-tab-item.active-red { color: #FF5722; font-weight: bold; }
+.city-tab-item.active-red::after {
+    content: '';
+    position: absolute;
+    bottom: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 40rpx;
+    height: 4rpx;
+    background-color: #FF5722;
+    border-radius: 2rpx;
+}
+.city-list {
+    height: 400rpx;
+}
+.city-item {
+    padding: 30rpx;
+    font-size: 28rpx;
+    color: #333;
+}
+</style>

+ 151 - 0
pages/mine/settings/security/index.vue

@@ -0,0 +1,151 @@
+<template>
+    <view class="container">
+        <!-- 自定义头部 -->
+        <view class="custom-header">
+            <view class="header-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg" style="transform: rotate(180deg);"></image>
+            </view>
+            <text class="header-title">账号与安全</text>
+            <view class="header-right"></view>
+        </view>
+        <view class="header-placeholder"></view>
+        <view class="section-title-security">安全设置</view>
+
+        <view class="group-card">
+            <view class="list-item" @click="changeMobile">
+                <text class="item-title">手机号</text>
+                <view class="item-right">
+                    <text class="item-value">136****5678</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+            <view class="list-item">
+                <text class="item-title">登录密码</text>
+                <view class="item-right">
+                    <text class="item-value">未设置</text>
+                    <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+                </view>
+            </view>
+        </view>
+
+        <view class="section-title-security">高级设置</view>
+        <view class="group-card">
+            <view class="list-item no-border" @click="deleteAccount">
+                <text class="item-title">注销账号</text>
+                <image class="arrow-icon" src="/static/icons/chevron_right.svg"></image>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {}
+    },
+    methods: {
+        navBack() {
+             uni.navigateBack({
+                delta: 1
+            });
+        },
+        changeMobile() {
+            // 跳转修改手机号
+        },
+        deleteAccount() {
+             uni.showModal({
+                title: '警示',
+                content: '注销账号后将无法恢复,确定要继续吗?',
+                success: function (res) {
+                    if (res.confirm) {
+                        uni.showToast({ title: '已提交注销申请', icon: 'none' });
+                    }
+                }
+            });
+        }
+    }
+}
+</script>
+
+<style>
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+.custom-header {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 88rpx;
+    padding-top: var(--status-bar-height);
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    box-sizing: content-box;
+    z-index: 100;
+}
+.header-placeholder {
+    height: calc(88rpx + var(--status-bar-height));
+}
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+.header-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+.header-right {
+    width: 40rpx;
+}
+
+.container {
+    padding: 20rpx 30rpx;
+}
+.section-title-security {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 20rpx;
+    margin-top: 20rpx;
+    padding-left: 10rpx;
+}
+.group-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+    margin-bottom: 30rpx;
+}
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: 1px solid #F5F5F5;
+}
+.list-item.no-border {
+    border-bottom: none;
+}
+.item-title {
+    font-size: 28rpx;
+    color: #333;
+}
+.item-right {
+    display: flex;
+    align-items: center;
+}
+.arrow-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.5;
+    margin-left: 10rpx;
+}
+.item-value {
+    font-size: 28rpx;
+    color: #999;
+}
+</style>

+ 607 - 0
pages/mine/style.css

@@ -0,0 +1,607 @@
+/* 页面背景 */
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+}
+
+.container {
+    padding-bottom: 30rpx;
+    position: relative;
+    overflow-x: hidden;
+}
+
+/* 顶部背景 */
+.nav-bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    /* 增加高度以覆盖顶部,确保上移后背景仍然充足 */
+    height: 550rpx;
+    /* 调整渐变色,使其更接近设计图的暖色调 */
+    background: linear-gradient(180deg, #FFE0B2 0%, #F8F8F8 100%);
+    z-index: 1;
+    overflow: hidden;
+    border-bottom-left-radius: 60rpx;
+    border-bottom-right-radius: 60rpx;
+}
+
+/* 装饰性圆球 - 加深颜色 */
+.bg-circle-1 {
+    position: absolute;
+    top: -60rpx;
+    right: -60rpx;
+    width: 320rpx;
+    height: 320rpx;
+    /* 加深颜色 */
+    background: radial-gradient(circle, rgba(255, 167, 38, 0.4) 0%, rgba(255, 167, 38, 0) 70%);
+    border-radius: 50%;
+}
+
+.bg-circle-2 {
+    position: absolute;
+    top: 80rpx;
+    left: -100rpx;
+    width: 420rpx;
+    height: 420rpx;
+    /* 加深颜色 */
+    background: radial-gradient(circle, rgba(255, 183, 77, 0.4) 0%, rgba(255, 183, 77, 0) 70%);
+    border-radius: 50%;
+}
+
+/* 头部区域 */
+.header-section {
+    position: relative;
+    z-index: 2;
+    padding: 60rpx 30rpx 0;
+}
+
+.title-bar {
+    text-align: center;
+    font-size: 32rpx;
+    /* 16pt = 32rpx, consistent with name */
+    font-weight: 500;
+    color: #333;
+    margin-bottom: 30rpx;
+}
+
+.user-card {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 30rpx;
+    position: relative;
+}
+
+.avatar {
+    width: 90rpx;
+    height: 90rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+    border: 3rpx solid #fff;
+    box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.05);
+}
+
+.info-content {
+    flex: 1;
+    padding-top: 5rpx;
+}
+
+.name-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12rpx;
+}
+
+.name {
+    /* 16号字体 = 32rpx */
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #1A1A1A;
+    margin-right: 12rpx;
+}
+
+.tags {
+    display: flex;
+    align-items: center;
+}
+
+.tag {
+    font-size: 18rpx;
+    padding: 2rpx 6rpx;
+    border-radius: 4rpx;
+    margin-right: 8rpx;
+    line-height: 1.2;
+}
+
+.tag.green {
+    color: #4CAF50;
+    background-color: #E8F5E9;
+    border: 1px solid #C8E6C9;
+}
+
+.tag.blue {
+    color: #2196F3;
+    background-color: #E3F2FD;
+    border: 1px solid #BBDEFB;
+}
+
+.bike-icon {
+    width: 28rpx;
+    height: 28rpx;
+    background-color: #FFF3E0;
+    border-radius: 4rpx;
+    padding: 2rpx;
+}
+
+.detail-row {
+    display: flex;
+    align-items: center;
+    /* 12号字体 = 24rpx */
+    font-size: 24rpx;
+    color: #666;
+    margin-bottom: 8rpx;
+}
+
+.small-icon {
+    width: 24rpx;
+    /* Slightly increase icon to match font */
+    height: 24rpx;
+    margin-right: 8rpx;
+}
+
+.settings-icon {
+    width: 36rpx;
+    height: 36rpx;
+    position: absolute;
+    top: 0;
+    right: 0;
+}
+
+/* VIP 卡片 - 独立卡片样式 */
+.vip-card {
+    border-radius: 20rpx;
+    padding: 20rpx 30rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    color: #FDD835;
+    background: linear-gradient(90deg, #1f1f1f 0%, #141414 100%);
+    box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.15);
+    margin-bottom: 30rpx;
+    position: relative;
+}
+
+.vip-left {
+    display: flex;
+    align-items: center;
+}
+
+.vip-icon {
+    width: 40rpx;
+    height: 40rpx;
+    margin-right: 16rpx;
+}
+
+.vip-text {
+    display: flex;
+    flex-direction: column;
+}
+
+.vip-title {
+    font-size: 26rpx;
+    font-weight: bold;
+    color: #FFE082;
+    margin-bottom: 4rpx;
+}
+
+.vip-desc {
+    font-size: 16rpx;
+    color: #9E9E9E;
+}
+
+.vip-btn {
+    font-size: 20rpx;
+    color: #FFE082;
+    display: flex;
+    /* Flex layout to align text and icon */
+    align-items: center;
+}
+
+/* 统计面板 */
+.stats-panel {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 30rpx 0;
+    margin: 0 30rpx 30rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.03);
+    position: relative;
+    z-index: 3;
+}
+
+.stat-item {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    padding-left: 30rpx;
+}
+
+.stat-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12rpx;
+    /* 12号字体 = 24rpx */
+    font-size: 24rpx;
+    color: #333;
+    font-weight: normal;
+}
+
+.arrow-icon {
+    width: 20rpx;
+    height: 20rpx;
+    margin-left: 6rpx;
+    opacity: 0.6;
+}
+
+.arrow-icon-small {
+    width: 18rpx;
+    height: 18rpx;
+    margin-left: 4rpx;
+    opacity: 0.8;
+}
+
+.red-bar,
+.green-bar,
+.orange-bar {
+    width: 6rpx;
+    height: 18rpx;
+    margin-right: 10rpx;
+    border-radius: 3rpx;
+}
+
+.red-bar {
+    background-color: #FF5252;
+}
+
+.green-bar {
+    background-color: #4CAF50;
+}
+
+.orange-bar {
+    background-color: #FF9800;
+}
+
+.stat-value {
+    margin-bottom: 6rpx;
+    display: flex;
+    align-items: baseline;
+}
+
+.num {
+    /* 16号字体 = 32rpx */
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 6rpx;
+    line-height: 1;
+}
+
+.unit {
+    font-size: 20rpx;
+    color: #666;
+}
+
+.sub-text {
+    font-size: 18rpx;
+    color: #999;
+}
+
+.divider {
+    width: 1px;
+    height: 50rpx;
+    background-color: #E0E0E0;
+}
+
+/* 菜单列表 */
+.menu-list {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 0 30rpx 30rpx;
+    padding: 0 30rpx;
+    box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.03);
+}
+
+.menu-item {
+    display: flex;
+    align-items: center;
+    padding: 32rpx 0;
+    border-bottom: 1px solid #F5F5F5;
+}
+
+.menu-item:last-child {
+    border-bottom: none;
+}
+
+.menu-icon {
+    width: 40rpx;
+    height: 40rpx;
+    margin-right: 20rpx;
+}
+
+.menu-text {
+    flex: 1;
+    /* 14号字体 = 28rpx */
+    font-size: 28rpx;
+    color: #333;
+}
+
+.menu-right {
+    display: flex;
+    align-items: center;
+}
+
+/* 加大菜单列表的箭头 */
+.menu-item .arrow-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.5;
+}
+
+.red-dot {
+    width: 10rpx;
+    height: 10rpx;
+    background-color: #FF5252;
+    border-radius: 50%;
+    margin-right: 12rpx;
+}
+
+/* 退出按钮 */
+.logout-btn {
+    background-color: #fff;
+    margin: 0 30rpx;
+    height: 88rpx;
+    line-height: 88rpx;
+    text-align: center;
+    border-radius: 20rpx;
+    color: #FF5252;
+    font-size: 28rpx;
+    font-weight: 500;
+    box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.03);
+}
+
+/* 联系客服弹窗样式 */
+.service-popup-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.service-popup {
+    width: 600rpx;
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 0;
+    box-sizing: border-box;
+    overflow: hidden;
+}
+
+.service-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 30rpx;
+    border-bottom: 1rpx solid #f5f5f5;
+}
+
+.service-title {
+    /* 14号字体 = 28rpx,不加粗 */
+    font-size: 28rpx;
+    font-weight: normal;
+    color: #333;
+}
+
+.close-icon {
+    width: 28rpx;
+    height: 28rpx;
+    opacity: 0.6;
+}
+
+.qr-section {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 40rpx 0;
+    background-color: #fff;
+}
+
+.qr-title {
+    font-size: 28rpx;
+    color: #333;
+    margin-bottom: 30rpx;
+    font-weight: 500;
+}
+
+.qr-img {
+    width: 200rpx;
+    height: 200rpx;
+    margin-bottom: 20rpx;
+    border-radius: 12rpx;
+    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+}
+
+.qr-desc {
+    /* 12号字体 = 24rpx */
+    font-size: 24rpx;
+    color: #999;
+}
+
+.service-list {
+    padding: 0 30rpx;
+    padding-bottom: 30rpx;
+}
+
+.service-row {
+    display: flex;
+    align-items: center;
+    padding: 30rpx 0;
+    border-top: 1rpx solid #f5f5f5;
+}
+
+.service-row:last-child {
+    border-bottom: none;
+}
+
+.service-row-icon {
+    width: 56rpx;
+    height: 56rpx;
+    margin-right: 24rpx;
+}
+
+.service-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.service-name {
+    /* 13号字体 = 26rpx */
+    font-size: 26rpx;
+    color: #333;
+    margin-bottom: 4rpx;
+    font-weight: 500;
+}
+
+.service-desc {
+    /* 12号字体 = 24rpx */
+    font-size: 24rpx;
+    color: #999;
+}
+
+.call-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #E8F5E9;
+    padding: 8rpx 24rpx;
+    border-radius: 30rpx;
+    height: 56rpx;
+    box-sizing: border-box;
+}
+
+.call-btn text {
+    font-size: 24rpx;
+    color: #4CAF50;
+    margin-left: 8rpx;
+    font-weight: 500;
+}
+
+.phone-icon-small {
+    width: 24rpx;
+    height: 24rpx;
+}
+
+/* 退出登录弹窗样式 */
+.logout-popup-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    opacity: 0;
+    pointer-events: none;
+    transition: opacity 0.3s;
+}
+
+.logout-popup-mask.show {
+    opacity: 1;
+    pointer-events: auto;
+}
+
+.popup-modal {
+    width: 520rpx;
+    background-color: #fff;
+    border-radius: 30rpx;
+    padding: 60rpx 40rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.2);
+    transform: scale(0.9);
+    transition: transform 0.3s;
+}
+
+.logout-popup-mask.show .popup-modal {
+    transform: scale(1);
+}
+
+.popup-icon-wrapper {
+    width: 120rpx;
+    height: 120rpx;
+    background-color: #FFF3E0;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 30rpx;
+}
+
+.popup-icon-large {
+    width: 60rpx;
+    height: 60rpx;
+}
+
+.popup-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 20rpx;
+}
+
+.popup-desc {
+    font-size: 28rpx;
+    color: #666;
+    text-align: center;
+    line-height: 1.5;
+    margin-bottom: 50rpx;
+}
+
+.popup-actions {
+    display: flex;
+    width: 100%;
+    justify-content: space-between;
+}
+
+.popup-btn {
+    flex: 1;
+    height: 80rpx;
+    line-height: 80rpx;
+    text-align: center;
+    font-size: 28rpx;
+    border-radius: 40rpx;
+    margin: 0 15rpx;
+}
+
+.popup-btn.cancel {
+    background-color: #F5F5F5;
+    color: #666;
+}
+
+.popup-btn.confirm {
+    background-color: #FF9800;
+    color: #fff;
+    box-shadow: 0 4rpx 12rpx rgba(255, 152, 0, 0.3);
+}

+ 395 - 0
pages/mine/wallet/bill.vue

@@ -0,0 +1,395 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg"></image>
+            </view>
+            <text class="nav-title">账单明细</text>
+            <view class="nav-right"></view>
+        </view>
+
+        <!-- 内容区域 -->
+        <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>
+                </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>
+
+            <!-- 账单列表 -->
+            <scroll-view scroll-y class="bill-list">
+                <view v-for="(group, gIndex) in displayGroups" :key="gIndex" class="month-group">
+                    <!-- 月份头 -->
+                    <view class="group-header">
+                        <text class="month-title">{{ group.month }}</text>
+                        <text class="month-summary">收入 ¥{{ group.income }} 支出 ¥{{ group.expense }}</text>
+                    </view>
+                    
+                    <!-- 列表项 -->
+                    <view class="list-item" v-for="(item, index) in group.items" :key="index">
+                        <!-- 图标 -->
+                        <view class="item-icon-box" :class="item.type">
+                            <text class="item-icon-symbol">{{ item.type === 'income' ? '+' : '-' }}</text>
+                        </view>
+                        
+                        <!-- 中间内容 -->
+                        <view class="item-center">
+                            <text class="item-title">{{ item.title }}</text>
+                            <text class="item-desc">{{ item.time }} {{ item.desc }}</text>
+                        </view>
+
+                        <!-- 右侧数据 -->
+                        <view class="item-right">
+                            <text class="item-amount" :class="{ income: item.type === 'income', expense: item.type === 'expense' }">
+                                {{ item.type === 'income' ? '+' : '' }}{{ item.amount }}
+                            </text>
+                            <view class="item-tag">
+                                <text>{{ item.tag }}</text>
+                            </view>
+                        </view>
+                    </view>
+                </view>
+                <view class="list-padding-bottom"></view>
+            </scroll-view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        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: '扣款'
+                        }
+                    ]
+                }
+            ]
+        }
+    },
+    computed: {
+        displayGroups() {
+            if (this.currentTab === 0) return this.groups;
+            
+            return this.groups.map(group => {
+                const filteredItems = group.items.filter(item => {
+                    const type = this.currentTab === 1 ? 'income' : 'expense';
+                    return item.type === type;
+                });
+                return {
+                    ...group,
+                    items: filteredItems
+                };
+            }).filter(group => group.items.length > 0);
+        }
+    },
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        switchTab(index) {
+            this.currentTab = index;
+        }
+    }
+}
+</script>
+
+<style>
+/* 基础容器 */
+.container {
+    background-color: #F5F7FA;
+    min-height: 100vh;
+    display: flex;
+    flex-direction: column;
+}
+
+/* 导航栏 */
+.nav-bar {
+    background-color: #fff;
+    padding-top: var(--status-bar-height);
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    height: 88rpx; 
+    box-sizing: content-box;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+}
+
+.nav-left {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    width: 60rpx;
+}
+
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+    transform: rotate(180deg);
+}
+
+.nav-title {
+    font-size: 28rpx; /* 14pt (Strictly enforced) */
+    font-weight: bold;
+    color: #333;
+}
+
+.nav-right {
+    width: 60rpx;
+}
+
+/* 内容区域 */
+.content-area {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+/* 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;
+}
+
+.tab-item {
+    padding-bottom: 16rpx;
+    font-size: 28rpx;
+    color: #666;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    min-width: 100rpx;
+}
+
+.tab-item.active {
+    font-weight: bold;
+    color: #FF6B00; /* Orange text for active */
+}
+
+.tab-line {
+    width: 40rpx; /* Little wider line */
+    height: 4rpx;
+    background-color: #FF6B00;
+    border-radius: 4rpx;
+    position: absolute;
+    bottom: 0;
+}
+
+/* 列表容器 */
+.bill-list {
+    flex: 1;
+    padding: 0 20rpx;
+    box-sizing: border-box;
+}
+
+/* 月份卡片 */
+.month-group {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 0 20rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.02);
+}
+
+.group-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 24rpx 10rpx;
+    /* No border bottom for header in card view usually, or light one */
+    border-bottom: 1rpx solid #f9f9f9; 
+}
+
+.month-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.month-summary {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 列表项 */
+.list-item {
+    display: flex;
+    align-items: center;
+    padding: 30rpx 10rpx;
+    border-bottom: 1rpx solid #f9f9f9;
+}
+
+.list-item:last-child {
+    border-bottom: none;
+}
+
+/* 左侧图标 */
+.item-icon-box {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.item-icon-box.income {
+    background-color: #EEF9F2; /* Light Green */
+}
+
+.item-icon-box.expense {
+    background-color: #FFF0F0; /* Light Red */
+}
+
+.item-icon-symbol {
+    font-size: 40rpx;
+    font-weight: 300;
+    line-height: 1;
+    margin-top: -4rpx; /* Visual center adjustment */
+}
+
+.item-icon-box.income .item-icon-symbol {
+    color: #4CAF50;
+}
+
+.item-icon-box.expense .item-icon-symbol {
+    color: #FF4D4F;
+}
+
+/* 中间内容 */
+.item-center {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-around;
+    height: 80rpx;
+}
+
+.item-title {
+    font-size: 28rpx;
+    font-weight: 500;
+    color: #333;
+}
+
+.item-desc {
+    font-size: 22rpx;
+    color: #999;
+    margin-top: 8rpx;
+}
+
+/* 右侧数据 */
+.item-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    justify-content: space-around;
+    height: 80rpx;
+    margin-left: 10rpx;
+}
+
+.item-amount {
+    font-size: 30rpx;
+    font-weight: bold;
+}
+
+.item-amount.income {
+    color: #4CAF50;
+}
+
+.item-amount.expense {
+    color: #333;
+}
+
+.item-tag {
+    display: inline-flex;
+    justify-content: flex-end;
+    margin-top: 6rpx;
+}
+
+.item-tag text {
+    background-color: #FFFFFF;
+    border: 1rpx solid #eee;
+    padding: 2rpx 8rpx;
+    border-radius: 6rpx;
+    font-size: 20rpx;
+    color: #999;
+}
+
+.list-padding-bottom {
+    height: 40rpx;
+}
+</style>

+ 458 - 0
pages/mine/wallet/index.vue

@@ -0,0 +1,458 @@
+<template>
+    <view class="container">
+        <!-- 导航栏 -->
+        <view class="nav-bar">
+            <view class="nav-left" @click="navBack">
+                <image class="back-icon" src="/static/icons/chevron_right_dark.svg"></image>
+            </view>
+            <text class="nav-title">我的钱包</text>
+            <view class="nav-right"></view>
+        </view>
+
+        <!-- 钱包卡片 -->
+        <view class="wallet-card">
+            <!-- 背景装饰圆 -->
+            <view class="bg-circle big"></view>
+            <view class="bg-circle small"></view>
+
+            <view class="card-content">
+                <view class="card-top">
+                    <view class="app-info">
+                        <image class="app-logo" src="/static/icons/wallet_white.svg" mode="aspectFit"></image>
+                        <text class="app-name">履约者APP</text>
+                    </view>
+                    <view class="bill-btn" @click="navToBill">
+                        <text>账单</text>
+                    </view>
+                </view>
+
+                <view class="balance-container">
+                    <view class="balance-main">
+                        <text class="balance-label">账户余额 (元)</text>
+                        <text class="balance-num">2575.00</text>
+                    </view>
+                    <view class="balance-pending">
+                        <text class="pending-label">待入账 (元)</text>
+                        <text class="pending-num">580.00</text>
+                    </view>
+                </view>
+            </view>
+        </view>
+
+        <!-- 最近记录区域 -->
+        <view class="record-container">
+            <view class="record-header">
+                <text class="header-title">最近账户余额变动记录</text>
+                <view class="header-more" @click="navToBill">
+                    <text>查看全部</text>
+                    <image class="more-icon" src="/static/icons/arrow_right_gray.svg"></image>
+                </view>
+            </view>
+
+            <!-- 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="record-list">
+                <view class="list-item" v-for="(item, index) in displayList" :key="index">
+                    <view class="item-left">
+                        <text class="item-title">{{ item.title }}</text>
+                        <text class="item-desc">{{ item.desc }}</text>
+                        <text class="item-time">{{ item.time }}</text>
+                    </view>
+                    <view class="item-right">
+                        <text class="item-amount" :class="{ income: item.type === 'income', expense: item.type === 'expense' }">
+                            {{ item.type === 'income' ? '+' : '' }}{{ item.amount }}
+                        </text>
+                        <view class="item-tag">
+                            <text>{{ item.tag }}</text>
+                        </view>
+                    </view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            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: '工资'
+                }
+            ]
+        }
+    },
+    computed: {
+        displayList() {
+            if (this.currentTab === 0) return this.list;
+            if (this.currentTab === 1) return this.list.filter(item => item.type === 'income');
+            if (this.currentTab === 2) return this.list.filter(item => item.type === 'expense');
+            return [];
+        }
+    },
+    methods: {
+        navBack() {
+            uni.navigateBack();
+        },
+        navToBill() {
+            uni.navigateTo({
+                url: '/pages/mine/wallet/bill'
+            });
+        },
+        switchTab(index) {
+            this.currentTab = index;
+        }
+    }
+}
+</script>
+
+<style>
+/* 基础容器 */
+.container {
+    background-color: #F8F9FA;
+    min-height: 100vh;
+    display: flex;
+    flex-direction: column;
+}
+
+/* 导航栏 */
+.nav-bar {
+    background-color: #fff;
+    padding-top: var(--status-bar-height);
+    padding-left: 30rpx;
+    padding-right: 30rpx;
+    height: 88rpx; 
+    box-sizing: content-box;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+}
+
+.nav-left {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    width: 60rpx; /* 增大点击区域 */
+}
+
+/* 复用通用图标并旋转 */
+.back-icon {
+    width: 40rpx;
+    height: 40rpx;
+    transform: rotate(180deg);
+}
+
+/* 导航标题 */
+.nav-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.nav-right {
+    width: 60rpx;
+}
+
+/* 钱包卡片 */
+.wallet-card {
+    margin: 20rpx 30rpx 0; 
+    /* 增加高度以优化内部间距 (原220rpx -> 300rpx) */
+    height: 300rpx; 
+    background: linear-gradient(135deg, #FF6B00 0%, #FF8F00 100%);
+    border-radius: 20rpx;
+    position: relative;
+    overflow: hidden;
+    color: #fff;
+    box-shadow: 0 4rpx 16rpx rgba(255, 107, 0, 0.15);
+}
+
+.bg-circle {
+    position: absolute;
+    border-radius: 50%;
+    background: rgba(255,255,255,0.08);
+}
+
+.bg-circle.big {
+    width: 400rpx;
+    height: 400rpx;
+    right: -100rpx;
+    bottom: -150rpx;
+}
+
+.bg-circle.small {
+    width: 200rpx;
+    height: 200rpx;
+    right: 80rpx;
+    bottom: 40rpx;
+}
+
+.card-content {
+    position: relative;
+    z-index: 1;
+    padding: 30rpx; /* 增加内边距 */
+    height: 100%;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+    /* justify-content: space-between; */
+}
+
+.card-top {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.app-info {
+    display: flex;
+    align-items: center;
+}
+
+.app-logo {
+    width: 28rpx; /* 图标调小 */
+    height: 28rpx;
+    background-color: transparent; /* SVG不需要背景色 */
+    margin-right: 10rpx;
+    border-radius: 0;
+}
+
+.app-name {
+    font-size: 26rpx; /* 调小:13pt */
+    font-weight: 500;
+}
+
+.bill-btn {
+    font-size: 26rpx; /* 13pt */
+    opacity: 0.9;
+}
+.bill-btn text {
+    font-size: 26rpx; /* 调小:13pt */
+    opacity: 0.95;
+}
+
+.balance-container {
+    margin-top: auto; /* Push to bottom */
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-end;
+    padding-bottom: 10rpx; /* Align with bottom padding visual */
+}
+
+.balance-main {
+    display: flex;
+    flex-direction: column;
+}
+
+.balance-label {
+    font-size: 24rpx; /* 12pt */
+    opacity: 0.9;
+    margin-bottom: 4rpx;
+}
+
+.balance-num {
+    font-size: 48rpx; /* 调整适中,不至于太小也不太大 */
+    font-weight: bold;
+    line-height: 1.1;
+}
+
+.balance-pending {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    margin-bottom: 10rpx;
+}
+
+.pending-label {
+    font-size: 24rpx; /* 12pt */
+    opacity: 0.9;
+    margin-bottom: 4rpx;
+}
+
+.pending-num {
+    font-size: 28rpx; /* 14pt */
+    font-weight: bold;
+}
+
+/* 记录区域 */
+.record-container {
+    flex: 1;
+    background-color: #fff;
+    margin: 24rpx 24rpx 0; /* 调整边距 */
+    border-radius: 20rpx 20rpx 0 0; 
+    padding: 30rpx 24rpx;
+}
+
+.record-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 24rpx;
+}
+
+.header-title {
+    font-size: 28rpx; /* 14pt */
+    font-weight: bold;
+    color: #333;
+}
+
+.header-more {
+    display: flex;
+    align-items: center;
+    font-size: 24rpx; /* 12pt */
+    color: #999;
+}
+
+.more-icon {
+    width: 24rpx;
+    height: 24rpx;
+    margin-left: 6rpx;
+    /* Ensure icon color is visible - svgs are usually static. display:block just in case */
+    display: block; 
+}
+
+/* Tabs */
+.tabs-row {
+    display: flex;
+    border-bottom: 1rpx solid #f5f5f5;
+    margin-bottom: 10rpx;
+}
+
+.tab-item {
+    margin-right: 40rpx;
+    padding-bottom: 12rpx;
+    font-size: 28rpx; /* 14pt */
+    color: #666;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.tab-item.active {
+    font-weight: bold;
+    color: #333;
+}
+
+.tab-line {
+    width: 28rpx;
+    height: 4rpx;
+    background-color: #FF6B00;
+    border-radius: 4rpx;
+    position: absolute;
+    bottom: 0;
+}
+
+/* 列表 */
+.list-item {
+    display: flex;
+    justify-content: space-between;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #f9f9f9;
+}
+
+.item-left {
+    display: flex;
+    flex-direction: column;
+}
+
+.item-title {
+    font-size: 28rpx; /* 14pt (Green Box) */
+    color: #333;
+    margin-bottom: 8rpx;
+    font-weight: 500;
+}
+
+.item-desc {
+    font-size: 26rpx; /* 13pt (Red Box) */
+    color: #999;
+    margin-bottom: 6rpx;
+}
+
+.item-time {
+    font-size: 24rpx; /* 12pt */
+    color: #ccc;
+}
+
+.item-right {
+    display: flex;
+    flex-direction: column;
+    /* align-items: flex-end; 保持右对齐 */
+    text-align: right;
+}
+
+.item-amount {
+    font-size: 28rpx; /* 14pt */
+    font-weight: bold;
+    margin-bottom: 8rpx;
+}
+
+.item-amount.income {
+    color: #4CAF50;
+}
+
+.item-amount.expense {
+    color: #333;
+}
+
+.item-tag {
+    display: inline-flex;
+    justify-content: flex-end;
+}
+
+.item-tag text {
+    background-color: #F5F5F5;
+    padding: 4rpx 12rpx;
+    border-radius: 6rpx;
+    font-size: 22rpx; /* 11pt */
+    color: #999;
+}
+</style>

+ 396 - 0
pages/orders/anomaly.vue

@@ -0,0 +1,396 @@
+<template>
+    <view class="anomaly-container">
+        <!-- 内容区域 -->
+        <scroll-view scroll-y class="anomaly-scroll">
+
+            <!-- 异常类型 -->
+            <view class="ano-card">
+                <view class="ano-section-title">
+                    <view class="ano-title-bar"></view>
+                    <text class="ano-title-text">异常类型</text>
+                </view>
+                <view class="ano-type-row" @click="openTypeSheet">
+                    <text class="ano-type-val" :class="{ 'placeholder': !selectedType }">
+                        {{ selectedType || '其他异常' }}
+                    </text>
+                    <image class="ano-right-arrow" src="/static/icons/right_arrow_orange.svg"></image>
+                </view>
+            </view>
+
+            <!-- 异常描述 -->
+            <view class="ano-card">
+                <view class="ano-section-title">
+                    <view class="ano-title-bar"></view>
+                    <text class="ano-title-text">异常描述</text>
+                </view>
+                <textarea
+                    class="ano-textarea"
+                    v-model="anomalyDesc"
+                    placeholder="请详细描述现场异常情况..."
+                    placeholder-style="color:#ccc; font-size:28rpx;"
+                    maxlength="500"
+                ></textarea>
+            </view>
+
+            <!-- 现场照片 -->
+            <view class="ano-card">
+                <view class="ano-section-title">
+                    <view class="ano-title-bar"></view>
+                    <text class="ano-title-text">现场照片 (必填,最多5张)</text>
+                </view>
+                <view class="ano-photo-grid">
+                    <!-- 已上传图片 -->
+                    <view class="ano-photo-item" v-for="(img, idx) in photoList" :key="idx">
+                        <image class="ano-photo-preview" :src="img" mode="aspectFill"></image>
+                        <view class="ano-photo-del" @click="removePhoto(idx)">×</view>
+                    </view>
+                    <!-- 添加按钮 -->
+                    <view class="ano-photo-add" @click="choosePhoto" v-if="photoList.length < 5">
+                        <image class="ano-add-icon" src="/static/icons/camera_grey.svg"></image>
+                        <text class="ano-add-text">上传</text>
+                    </view>
+                </view>
+            </view>
+
+            <!-- 底部留空供按钮 -->
+            <view style="height: 160rpx;"></view>
+        </scroll-view>
+
+        <!-- 底部提交按钮 -->
+        <view class="ano-footer">
+            <button class="ano-submit-btn" @click="submitAnomaly">提交上报</button>
+        </view>
+
+        <!-- 异常类型选择器 -->
+        <view class="ano-sheet-mask" v-if="showTypeSheet" @click="closeTypeSheet">
+            <view class="ano-sheet" @click.stop>
+                <text class="ano-sheet-title">选择异常类型</text>
+                <scroll-view scroll-y class="ano-sheet-list">
+                    <view
+                        class="ano-sheet-item"
+                        v-for="(type, idx) in anomalyTypes"
+                        :key="idx"
+                        @click="selectType(type)"
+                    >
+                        <text :class="['ano-sheet-item-text', { 'selected': selectedType === type }]">{{ type }}</text>
+                        <image
+                            v-if="selectedType === type"
+                            class="ano-check-icon"
+                            src="/static/icons/right_arrow_orange.svg"
+                        ></image>
+                    </view>
+                </scroll-view>
+                <view class="ano-sheet-cancel" @click="closeTypeSheet">取消</view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 已选异常类型
+            selectedType: '其他异常',
+            // 异常描述
+            anomalyDesc: '',
+            // 照片列表
+            photoList: [],
+            // 是否显示类型选择器
+            showTypeSheet: false,
+            // 异常类型列表
+            anomalyTypes: [
+                '无法联系用户',
+                '地址错误',
+                '宠物身体异常',
+                '设施损坏',
+                '用户拒收',
+                '其他异常'
+            ]
+        };
+    },
+    methods: {
+        // 打开类型选择器
+        openTypeSheet() {
+            this.showTypeSheet = true;
+        },
+        // 关闭类型选择器
+        closeTypeSheet() {
+            this.showTypeSheet = false;
+        },
+        // 选择异常类型
+        selectType(type) {
+            this.selectedType = type;
+            this.closeTypeSheet();
+        },
+        // 选择照片
+        choosePhoto() {
+            uni.chooseImage({
+                count: 5 - this.photoList.length,
+                sizeType: ['compressed'],
+                sourceType: ['album', 'camera'],
+                success: (res) => {
+                    this.photoList = [...this.photoList, ...res.tempFilePaths].slice(0, 5);
+                }
+            });
+        },
+        // 删除照片
+        removePhoto(idx) {
+            this.photoList.splice(idx, 1);
+        },
+        // 提交上报
+        submitAnomaly() {
+            if (!this.selectedType) {
+                uni.showToast({ title: '请选择异常类型', icon: 'none' });
+                return;
+            }
+            if (this.photoList.length === 0) {
+                uni.showToast({ title: '请上传现场照片', icon: 'none' });
+                return;
+            }
+            // 模拟提交
+            uni.showLoading({ title: '提交中...' });
+            setTimeout(() => {
+                uni.hideLoading();
+                uni.showToast({ title: '上报成功', icon: 'success' });
+                setTimeout(() => {
+                    uni.navigateBack();
+                }, 1500);
+            }, 1000);
+        }
+    }
+};
+</script>
+
+<style>
+/* 页面背景 */
+.anomaly-container {
+    min-height: 100vh;
+    background-color: #F7F8FA;
+    display: flex;
+    flex-direction: column;
+}
+
+.anomaly-scroll {
+    flex: 1;
+    padding: 20rpx 30rpx 0;
+    box-sizing: border-box;
+}
+
+/* 内容卡片 */
+.ano-card {
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+}
+
+/* 节标题 */
+.ano-section-title {
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.ano-title-bar {
+    width: 6rpx;
+    height: 30rpx;
+    background-color: #FF9800;
+    border-radius: 3rpx;
+    margin-right: 12rpx;
+}
+
+.ano-title-text {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+/* 异常类型行 */
+.ano-type-row {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10rpx 0;
+}
+
+.ano-type-val {
+    font-size: 28rpx;
+    color: #333;
+    flex: 1;
+}
+
+.ano-type-val.placeholder {
+    color: #ccc;
+}
+
+.ano-right-arrow {
+    width: 20rpx;
+    height: 20rpx;
+}
+
+/* 描述文本框 */
+.ano-textarea {
+    width: 100%;
+    min-height: 200rpx;
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.6;
+    background-color: #FAFAFA;
+    border-radius: 10rpx;
+    padding: 20rpx;
+    box-sizing: border-box;
+}
+
+/* 照片网格 */
+.ano-photo-grid {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16rpx;
+}
+
+.ano-photo-item {
+    width: 150rpx;
+    height: 150rpx;
+    border-radius: 12rpx;
+    position: relative;
+    overflow: hidden;
+}
+
+.ano-photo-preview {
+    width: 100%;
+    height: 100%;
+}
+
+.ano-photo-del {
+    position: absolute;
+    top: 4rpx;
+    right: 4rpx;
+    width: 36rpx;
+    height: 36rpx;
+    line-height: 32rpx;
+    text-align: center;
+    background-color: rgba(0, 0, 0, 0.5);
+    color: #fff;
+    border-radius: 50%;
+    font-size: 28rpx;
+}
+
+.ano-photo-add {
+    width: 150rpx;
+    height: 150rpx;
+    border: 2rpx dashed #E0E0E0;
+    border-radius: 12rpx;
+    background-color: #FAFAFA;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+}
+
+.ano-add-icon {
+    width: 50rpx;
+    height: 50rpx;
+    margin-bottom: 10rpx;
+    opacity: 0.5;
+}
+
+.ano-add-text {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 底部提交 */
+.ano-footer {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    background-color: #FF9800;
+    padding: 20rpx 40rpx;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+    box-sizing: border-box;
+}
+
+.ano-submit-btn {
+    width: 100%;
+    height: 90rpx;
+    line-height: 90rpx;
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: bold;
+    border-radius: 45rpx;
+    border: none;
+}
+
+.ano-submit-btn::after {
+    border: none;
+}
+
+/* 异常类型选择器 */
+.ano-sheet-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    align-items: flex-end;
+}
+
+.ano-sheet {
+    width: 100%;
+    background-color: #fff;
+    border-radius: 24rpx 24rpx 0 0;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+
+.ano-sheet-title {
+    display: block;
+    text-align: center;
+    font-size: 28rpx;
+    color: #999;
+    padding: 30rpx 0 20rpx;
+    border-bottom: 1px solid #f5f5f5;
+}
+
+.ano-sheet-list {
+    max-height: 60vh;
+}
+
+.ano-sheet-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 30rpx 40rpx;
+    border-bottom: 1px solid #f9f9f9;
+}
+
+.ano-sheet-item-text {
+    font-size: 32rpx;
+    color: #333;
+}
+
+.ano-sheet-item-text.selected {
+    color: #FF9800;
+    font-weight: bold;
+}
+
+.ano-check-icon {
+    width: 20rpx;
+    height: 20rpx;
+}
+
+.ano-sheet-cancel {
+    text-align: center;
+    font-size: 32rpx;
+    color: #999;
+    padding: 30rpx 0;
+    border-top: 16rpx solid #F7F8FA;
+}
+</style>

+ 289 - 0
pages/orders/detail-logic.js

@@ -0,0 +1,289 @@
+export default {
+    data() {
+        return {
+            orderType: 1, // 1:接送, 2:喂遛, 3:洗护
+
+            // Define steps dynamically based on type
+            stepsPickup: ['接单', '到达', '出发', '送达', '完成'],
+            stepsWalkWash: ['接单', '到达', '开始', '结束', '完成'],
+
+            currentStep: 1, // 0-indexed (1 means 到达)
+
+            // Mock Data
+            orderDetail: {
+                type: 1,
+                price: '20.00',
+                timeLabel: '取货时间',
+                time: '2026/02/10 10:00',
+                petAvatar: '/static/dog.png',
+                petName: '哈士奇宝宝',
+                petBreed: '哈士奇',
+                serviceTag: '宠物接送',
+                startLocation: '武汉大学宠物店',
+                startAddress: '武汉市洪山区珞喻路458号',
+                endLocation: '张** 189****8451',
+                endAddress: '武汉市武昌区新区大道凤凰广场A座一楼25号',
+                serviceContent: '这里是订单服务内容。',
+                remark: '这里是订单备注信息。',
+                orderNo: 'T1001',
+                createTime: '2026/02/10 09:30',
+                progressLogs: [
+                    { status: '您已接单', time: '2026-02-10 10:00' }
+                ]
+            },
+
+            // Modal states
+            showPetModal: false,
+            currentPetInfo: {},
+            showNavModal: false,
+            navTargetPointType: '',
+
+            // Upload Modal State
+            showUploadModal: false,
+            modalMediaList: [],
+            modalRemark: '',
+
+            // 宠护小结弹窗状态
+            showSumModal: false,
+            sumContent: '',
+            sumDate: '',
+            sumSigner: '张*哥',
+
+            // 宠物备注弹窗状态
+            showPetRemarkInput: false,
+            petRemarkText: ''
+        }
+    },
+    computed: {
+        steps() {
+            return this.orderType === 1 ? this.stepsPickup : this.stepsWalkWash;
+        },
+        displayStatusText() {
+            let status = this.steps[this.currentStep];
+            if (status === '已完成' || status === '完成') return '已完成';
+            if (status === '已拒绝') return '已拒绝';
+            if (status === '接单') {
+                return this.orderType === 1 ? '待接送' : '待服务';
+            }
+            // For other active states (出发, 到达, 送达, 开始, 结束)
+            return this.orderType === 1 ? '配送中' : '服务中';
+        },
+        currentStatusText() {
+            return this.steps[this.currentStep];
+        },
+        currentTaskTitle() {
+            let action = this.steps[this.currentStep];
+            if (action === '到达') return '到达打卡';
+            if (action === '开始') return '开始服务';
+            if (action === '出发') return '确认出发';
+            if (action === '送达' || action === '结束') return '服务完成';
+            return action;
+        },
+        currentTaskDesc() {
+            let action = this.steps[this.currentStep];
+            if (action === '到达') {
+                return '打卡穿着工装消毒站门口的照片或视频';
+            }
+            if (this.orderType === 1) { // 送货
+                if (action === '出发') return '拍摄宠物上车/出发时的状态照片或视频';
+                if (action === '送达') return '打卡确认送达的照片或视频';
+            } else if (this.orderType === 2) { // 喂遛
+                if (action === '开始') return '开始服务并拍摄照片或视频';
+                if (action === '结束') return '服务完成拍摄照片或视频';
+            } else if (this.orderType === 3) { // 洗护
+                if (action === '开始') return '开始服务并拍摄照片或视频';
+                if (action === '结束') return '服务完成拍摄照片或视频';
+            }
+            return '请按要求提交照片或视频及备注';
+        }
+    },
+    onLoad(options) {
+        if (options.type) {
+            this.orderType = parseInt(options.type);
+            this.orderDetail.type = this.orderType;
+            if (this.orderType === 2 || this.orderType === 3) {
+                this.orderDetail.serviceTag = this.orderType === 2 ? '上门喂遛' : '上门洗护';
+                this.orderDetail.orderNo = this.orderType === 2 ? 'W1002' : 'X1003';
+                this.currentStep = 1;
+            }
+        }
+    },
+    methods: {
+        showPetProfile() {
+            // Use orderDetail basic info and mock the rest
+            this.currentPetInfo = {
+                ...this.orderDetail,
+                petGender: 'M',
+                petAge: '2岁',
+                petWeight: '15kg',
+                petPersonality: '活泼亲人,精力旺盛',
+                petHobby: '喜欢追飞盘,爱吃肉干',
+                petRemark: '肠胃较弱,不能乱喂零食;出门易爆冲,请拉紧牵引绳。',
+                petTags: ['拉响警报', '不能吃鸡肉', '精力旺盛'],
+                petLogs: [
+                    { date: '2026-02-09 14:00', content: '今天遛弯拉了两次粑粑,精神状态很好。', recorder: '王阿姨' },
+                    { date: '2026-02-08 10:30', content: '有些挑食,剩了小半碗狗粮。', recorder: '李师傅' },
+                    { date: '2026-02-05 09:00', content: '建档。', recorder: '系统记录' }
+                ]
+            };
+            this.showPetModal = true;
+        },
+        closePetProfile() {
+            this.showPetModal = false;
+        },
+        openPetRemarkInput() {
+            this.petRemarkText = '';
+            this.showPetRemarkInput = true;
+        },
+        closePetRemarkInput() {
+            this.showPetRemarkInput = false;
+        },
+        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 = [];
+            }
+            this.currentPetInfo.petLogs.unshift({
+                date: date,
+                content: this.petRemarkText,
+                recorder: '张*哥'
+            });
+            this.closePetRemarkInput();
+            uni.showToast({ title: '备注已添加', icon: 'success' });
+        },
+        goToAnomaly() {
+            uni.navigateTo({
+                url: '/pages/orders/anomaly?orderId=' + (this.orderDetail.orderNo || '')
+            });
+        },
+        callPhone() {
+            uni.makePhoneCall({ phoneNumber: '18900008451' });
+        },
+        openNavigation(type) {
+            this.navTargetPointType = type;
+            this.showNavModal = true;
+        },
+        closeNavModal() {
+            this.showNavModal = false;
+        },
+        chooseMap(mapType) {
+            let pointType = this.navTargetPointType;
+            let name = pointType === 'start' ? this.orderDetail.startLocation : this.orderDetail.endLocation;
+            let address = pointType === 'start' ? this.orderDetail.startAddress : this.orderDetail.endAddress;
+
+            this.showNavModal = false;
+
+            uni.openLocation({
+                latitude: 30.52, // Mock lat
+                longitude: 114.31, // Mock lng
+                name: name || '目的地',
+                address: address || '默认地址',
+                success: function () {
+                    console.log('打开导航成功: ' + mapType);
+                }
+            });
+        },
+        openUploadModal() {
+            this.modalMediaList = [];
+            this.modalRemark = '';
+            this.showUploadModal = true;
+        },
+        closeUploadModal() {
+            this.showUploadModal = false;
+        },
+        chooseModalMedia() {
+            uni.chooseImage({
+                count: 5 - this.modalMediaList.length,
+                success: (res) => {
+                    this.modalMediaList = this.modalMediaList.concat(res.tempFilePaths);
+                    uni.showToast({ title: '添加成功', icon: 'none' });
+                }
+            });
+        },
+        removeModalMedia(index) {
+            this.modalMediaList.splice(index, 1);
+        },
+        getCurrentTime() {
+            const now = new Date();
+            const y = now.getFullYear();
+            const m = String(now.getMonth() + 1).padStart(2, '0');
+            const d = String(now.getDate()).padStart(2, '0');
+            const h = String(now.getHours()).padStart(2, '0');
+            const min = String(now.getMinutes()).padStart(2, '0');
+            return `${y}/${m}/${d} ${h}:${min}`;
+        },
+        confirmUploadModal() {
+            if (this.modalMediaList.length === 0) {
+                uni.showToast({ title: '请上传至少一张图片或视频', icon: 'none' });
+                return;
+            }
+
+            // Append to timeline
+            this.orderDetail.progressLogs.unshift({
+                status: this.currentTaskTitle,
+                time: this.getCurrentTime(),
+                medias: [...this.modalMediaList],
+                remark: this.modalRemark
+            });
+
+            // Advance step
+            if (this.currentStep < this.steps.length - 1) {
+                this.currentStep++;
+            }
+
+            this.closeUploadModal();
+            uni.showToast({ title: '打卡成功', icon: 'success' });
+
+            // Check if it's finished now
+            if (this.currentStep === this.steps.length - 1) {
+                setTimeout(() => {
+                    uni.showToast({ title: '订单已完成', icon: 'none' });
+                }, 1500);
+            }
+        },
+        copyOrderNo() {
+            uni.setClipboardData({
+                data: this.orderDetail.orderNo,
+                success: () => {
+                    uni.showToast({ title: '复制成功', icon: 'none' });
+                }
+            });
+        },
+        openSumModal() {
+            // 初始化日期
+            const now = new Date();
+            const y = now.getFullYear();
+            const m = String(now.getMonth() + 1).padStart(2, '0');
+            const d = String(now.getDate()).padStart(2, '0');
+            this.sumDate = `${y}/${m}/${d}`;
+
+            // 预设服务内容模板
+            if (!this.sumContent) {
+                this.sumContent =
+                    '1. 精神/身体状态:\n' +
+                    '2. 进食/饮水:\n' +
+                    '3. 排泤情况:\n' +
+                    '4. 卫生情况:\n' +
+                    '5. 互动情况:\n' +
+                    '6. 特殊情况/备注:';
+            }
+            this.showSumModal = true;
+        },
+        closeSumModal() {
+            this.showSumModal = false;
+        },
+        submitSumModal() {
+            if (!this.sumContent.trim()) {
+                uni.showToast({ title: '请填写服务内容', icon: 'none' });
+                return;
+            }
+            this.closeSumModal();
+            uni.showToast({ title: '小结已提交', icon: 'success' });
+        }
+    }
+}

+ 1386 - 0
pages/orders/detail-style.css

@@ -0,0 +1,1386 @@
+/* 页面背景 */
+page {
+    background-color: #F8F8F8;
+}
+
+.detail-container {
+    padding-bottom: 200rpx;
+}
+
+/* 顶部动态状态区 */
+.detail-header {
+    background: linear-gradient(135deg, #FF9800 0%, #FF5722 100%);
+    padding: 40rpx 40rpx 50rpx 40rpx;
+    color: #fff;
+    border-radius: 20rpx;
+    margin: 30rpx 30rpx 25rpx 30rpx;
+    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.2);
+}
+
+.status-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 40rpx;
+}
+
+.status-title {
+    font-size: 28rpx;
+    font-weight: bold;
+}
+
+.status-price {
+    font-size: 40rpx;
+    font-weight: bold;
+}
+
+/* 进度条 */
+.progress-bar {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    padding: 0 10rpx;
+}
+
+.step-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    flex: 1;
+    position: relative;
+    opacity: 0.6;
+}
+
+.step-item.active {
+    opacity: 1;
+}
+
+.step-circle-wrapper {
+    position: relative;
+    width: 100%;
+    display: flex;
+    justify-content: center;
+    margin-bottom: 10rpx;
+}
+
+.step-circle {
+    width: 40rpx;
+    height: 40rpx;
+    border-radius: 50%;
+    background-color: rgba(255, 255, 255, 0.3);
+    color: #fff;
+    font-size: 20rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    position: relative;
+    z-index: 2;
+}
+
+.step-item.active .step-circle {
+    background-color: #fff;
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.step-line {
+    position: absolute;
+    top: 50%;
+    right: calc(50% + 20rpx);
+    width: calc(100% - 40rpx);
+    height: 2rpx;
+    background-color: rgba(255, 255, 255, 0.3);
+    z-index: 1;
+    transform: translateY(-50%);
+}
+
+.step-line.active-line {
+    background-color: #fff;
+}
+
+.step-text {
+    font-size: 24rpx;
+}
+
+/* 内容区通用卡片 */
+.detail-content {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0 30rpx;
+    position: relative;
+    z-index: 10;
+}
+
+.white-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 30rpx;
+    margin-bottom: 25rpx;
+    box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.03);
+}
+
+/* 宠物信息条 */
+.pet-bar {
+    display: flex;
+    align-items: center;
+}
+
+.pb-avatar {
+    width: 100rpx;
+    height: 100rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+}
+
+.pb-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pb-name-row {
+    margin-bottom: 10rpx;
+}
+
+.pb-name {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 15rpx;
+}
+
+.pb-breed {
+    font-size: 26rpx;
+    color: #999;
+}
+
+.pb-tags {
+    display: flex;
+}
+
+.pb-tag {
+    background-color: #FFF3E0;
+    color: #FF9800;
+    font-size: 22rpx;
+    padding: 4rpx 16rpx;
+    border-radius: 8rpx;
+}
+
+.pb-actions {
+    display: flex;
+    align-items: center;
+}
+
+.pb-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.profile-btn {
+    border: 2rpx solid #FF9800;
+    color: #FF9800;
+    font-size: 24rpx;
+    padding: 8rpx 20rpx;
+    border-radius: 30rpx;
+    margin-right: 20rpx;
+}
+
+.phone-btn {
+    width: 60rpx;
+    height: 60rpx;
+    border-radius: 50%;
+    background-color: #FFF3E0;
+}
+
+.phone-icon {
+    width: 32rpx;
+    height: 32rpx;
+}
+
+/* 服务及路线信息 */
+.si-row {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 30rpx;
+}
+
+.si-row:last-child {
+    margin-bottom: 0;
+}
+
+.si-icon {
+    width: 36rpx;
+    height: 36rpx;
+    margin-right: 20rpx;
+    margin-top: 4rpx;
+}
+
+.si-icon-uni {
+    margin-right: 20rpx;
+    margin-top: 4rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.si-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.si-label {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 6rpx;
+}
+
+.icon-bg {
+    width: 44rpx;
+    height: 44rpx;
+    border-radius: 8rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-right: 20rpx;
+    margin-top: 4rpx;
+    flex-shrink: 0;
+}
+
+.icon-bg.grey-bg {
+    background-color: #F8F8F8;
+}
+
+.custom-icon {
+    width: 28rpx;
+    height: 28rpx;
+}
+
+.custom-icon-file {
+    width: 36rpx;
+    height: 36rpx;
+}
+
+.si-val {
+    font-size: 28rpx;
+    color: #333;
+}
+
+.record-btn {
+    font-size: 24rpx;
+    color: #FF5722;
+    display: flex;
+    align-items: center;
+}
+
+.record-arrow {
+    width: 24rpx;
+    height: 24rpx;
+    margin-left: 6rpx;
+}
+
+/* 地址展现复用图标逻辑 */
+.addr-row {
+    position: relative;
+    align-items: stretch;
+}
+
+.icon-circle {
+    width: 40rpx;
+    height: 40rpx;
+    border-radius: 50%;
+    color: #fff;
+    font-size: 22rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+    font-weight: bold;
+    margin-top: 6rpx;
+    position: relative;
+    z-index: 1;
+}
+
+.icon-circle.start {
+    background-color: #FFB74D;
+}
+
+.icon-circle.end {
+    background-color: #81C784;
+}
+
+.icon-circle.service {
+    background-color: #81C784;
+}
+
+.route-line-vertical {
+    position: absolute;
+    left: 19rpx;
+    top: 46rpx;
+    bottom: -6rpx;
+    border-left: 2rpx dashed #E0E0E0;
+    width: 0;
+    z-index: 0;
+}
+
+.si-addr-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 6rpx;
+}
+
+.si-addr-desc {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.nav-btn-circle {
+    width: 50rpx;
+    height: 50rpx;
+    background-color: #FFF3E0;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-top: 6rpx;
+}
+
+.nav-arrow {
+    width: 28rpx;
+    height: 28rpx;
+}
+
+/* 打卡任务区 */
+.task-card {
+    display: flex;
+    flex-direction: column;
+}
+
+.tc-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 15rpx;
+}
+
+.tc-desc {
+    font-size: 22rpx;
+    color: #666;
+    margin-bottom: 12rpx;
+}
+
+.media-grid {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+    margin-bottom: 20rpx;
+}
+
+.media-item {
+    width: 160rpx;
+    height: 160rpx;
+    position: relative;
+    border-radius: 12rpx;
+}
+
+.media-preview {
+    width: 100%;
+    height: 100%;
+    border-radius: 12rpx;
+}
+
+.media-del {
+    position: absolute;
+    top: -10rpx;
+    right: -10rpx;
+    width: 36rpx;
+    height: 36rpx;
+    background-color: rgba(0, 0, 0, 0.5);
+    color: #fff;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 24rpx;
+    z-index: 2;
+}
+
+.media-add {
+    width: 160rpx;
+    height: 160rpx;
+    border: 2rpx dashed #ccc;
+    border-radius: 12rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    background-color: #FAFAFA;
+    box-sizing: border-box;
+}
+
+.upload-icon-small {
+    width: 40rpx;
+    height: 40rpx;
+    margin-bottom: 10rpx;
+}
+
+.upload-text-small {
+    font-size: 22rpx;
+    color: #999;
+}
+
+.full-media-add {
+    width: 100%;
+    height: 140rpx;
+    background-color: #FAFAFA;
+    border: 2rpx dashed #E0E0E0;
+    border-radius: 12rpx;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    margin-top: 10rpx;
+}
+
+.upload-icon-large {
+    width: 50rpx;
+    height: 50rpx;
+    margin-bottom: 10rpx;
+    opacity: 0.5;
+}
+
+.upload-text-large {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 基础信息区 */
+.bi-row {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 25rpx;
+}
+
+.bi-row:last-child {
+    margin-bottom: 0;
+}
+
+.bi-icon {
+    width: 32rpx;
+    height: 32rpx;
+    margin-right: 20rpx;
+    margin-top: 4rpx;
+}
+
+.bi-icon-uni {
+    margin-right: 20rpx;
+    margin-top: 4rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.bi-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.bi-label {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 6rpx;
+}
+
+.bi-val-row {
+    display: flex;
+    align-items: center;
+}
+
+.bi-val {
+    font-size: 28rpx;
+    color: #333;
+}
+
+.bi-copy {
+    background-color: #F0F0F0;
+    color: #666;
+    font-size: 20rpx;
+    padding: 2rpx 10rpx;
+    border-radius: 6rpx;
+    margin-left: 15rpx;
+}
+
+/* 订单进度 */
+.tl-title-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+}
+
+.orange-bar {
+    width: 8rpx;
+    height: 32rpx;
+    background-color: #FF9800;
+    margin-right: 16rpx;
+    border-radius: 4rpx;
+}
+
+.tl-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.tl-list {
+    display: flex;
+    flex-direction: column;
+    padding-left: 10rpx;
+}
+
+.tl-item {
+    display: flex;
+    position: relative;
+    padding-bottom: 40rpx;
+}
+
+.tl-item:last-child {
+    padding-bottom: 0;
+}
+
+.tl-marker {
+    width: 16rpx;
+    height: 16rpx;
+    border-radius: 50%;
+    background-color: #E0E0E0;
+    position: absolute;
+    left: 0;
+    top: 6rpx;
+    z-index: 2;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.tl-marker.active {
+    background-color: #fff;
+    border: 3rpx solid #FF9800;
+    width: 18rpx;
+    height: 18rpx;
+    left: -1rpx;
+    /* offset for border width */
+}
+
+.tl-dot-inner {
+    width: 10rpx;
+    height: 10rpx;
+    border-radius: 50%;
+    background-color: #FF9800;
+}
+
+.tl-item:not(:last-child)::after {
+    content: '';
+    position: absolute;
+    left: 7rpx;
+    top: 24rpx;
+    bottom: -6rpx;
+    width: 2rpx;
+    background-color: #FFE0B2;
+    z-index: 1;
+}
+
+.tl-content-row {
+    margin-left: 40rpx;
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+}
+
+.tl-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    width: 100%;
+    margin-bottom: 10rpx;
+}
+
+.tl-status {
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+
+.tl-time {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.tl-medias {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15rpx;
+    margin-bottom: 15rpx;
+}
+
+.tl-img {
+    width: 140rpx;
+    height: 140rpx;
+    border-radius: 8rpx;
+}
+
+.tl-remark {
+    font-size: 24rpx;
+    color: #666;
+    background-color: #F9F9F9;
+    padding: 15rpx;
+    border-radius: 8rpx;
+    line-height: 1.5;
+}
+
+
+/* 底部操作栏 */
+.bottom-action-bar {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 120rpx;
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    box-shadow: 0 -5rpx 20rpx rgba(0, 0, 0, 0.05);
+    box-sizing: border-box;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+    z-index: 100;
+}
+
+.action-left,
+.action-right {
+    display: flex;
+    align-items: center;
+}
+
+.action-btn {
+    height: 64rpx;
+    line-height: 64rpx;
+    border-radius: 32rpx;
+    font-size: 26rpx;
+    padding: 0 35rpx;
+    margin: 0;
+}
+
+.action-left .action-btn:first-child {
+    margin-right: 20rpx;
+}
+
+.action-btn.grey-outline {
+    background-color: #fff;
+    color: #666;
+    border: 1px solid #E0E0E0;
+}
+
+.action-btn.orange-outline {
+    background-color: #FFF8F0;
+    color: #FF9800;
+    border: 1px solid #FF9800;
+}
+
+.action-btn.primary {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 4rpx 12rpx rgba(255, 87, 34, 0.2);
+    border: none;
+}
+
+.action-btn.grey-bg {
+    background: #E0E0E0;
+    color: #999;
+    box-shadow: none;
+    border: none;
+}
+
+.action-btn::after {
+    border: none;
+}
+
+/* 上传图片视频弹窗 */
+.upload-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.4);
+    z-index: 999;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.upload-modal-content {
+    width: 600rpx;
+    background-color: #ffffff;
+    border-radius: 20rpx;
+    padding: 40rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+}
+
+.um-header {
+    text-align: center;
+    margin-bottom: 40rpx;
+}
+
+.um-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.um-grid {
+    display: flex;
+    flex-wrap: wrap;
+    margin-bottom: 30rpx;
+}
+
+.um-item {
+    width: 130rpx;
+    height: 130rpx;
+    border-radius: 8rpx;
+    margin-right: 20rpx;
+    margin-bottom: 20rpx;
+    position: relative;
+    background-color: #f5f5f5;
+    overflow: hidden;
+}
+
+.um-item:nth-child(4n) {
+    margin-right: 0;
+}
+
+.um-preview {
+    width: 100%;
+    height: 100%;
+}
+
+.um-del {
+    position: absolute;
+    top: 4rpx;
+    right: 4rpx;
+    width: 36rpx;
+    height: 36rpx;
+    line-height: 32rpx;
+    text-align: center;
+    background-color: rgba(0, 0, 0, 0.5);
+    color: #fff;
+    border-radius: 50%;
+    font-size: 28rpx;
+}
+
+.um-add {
+    width: 130rpx;
+    height: 130rpx;
+    border-radius: 8rpx;
+    border: 1px dashed #e5e5e5;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    box-sizing: border-box;
+    margin-bottom: 20rpx;
+}
+
+.um-add-icon {
+    width: 44rpx;
+    height: 44rpx;
+    margin-bottom: 10rpx;
+    opacity: 0.4;
+}
+
+.um-add-text {
+    font-size: 24rpx;
+    color: #ccc;
+}
+
+.um-textarea {
+    width: 100%;
+    height: 160rpx;
+    background-color: #ffffff;
+    border-radius: 12rpx;
+    padding: 24rpx;
+    font-size: 28rpx;
+    color: #333;
+    box-sizing: border-box;
+    border: 1px solid #f0f0f0;
+}
+
+.um-footer {
+    margin-top: 40rpx;
+    display: flex;
+    justify-content: center;
+}
+
+.um-submit-btn {
+    width: 100%;
+    height: 88rpx;
+    line-height: 88rpx;
+    border-radius: 44rpx;
+    font-size: 32rpx;
+    background-color: #E0E0E0;
+    color: #fff;
+    border: none;
+}
+
+.um-submit-btn.active {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 4rpx 10rpx rgba(255, 87, 34, 0.3);
+}
+
+.um-submit-btn::after {
+    border: none;
+}
+
+/* 宠物档案弹窗 */
+.pet-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.pet-modal-content {
+    width: 680rpx;
+    max-height: 85vh;
+    background-color: #fff;
+    border-radius: 20rpx;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
+}
+
+.pet-modal-header {
+    display: flex;
+    align-items: center;
+    padding: 28rpx 30rpx 20rpx;
+    border-bottom: 1px solid #f5f5f5;
+    flex-shrink: 0;
+}
+
+.pet-modal-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.close-icon-btn {
+    width: 52rpx;
+    height: 52rpx;
+    line-height: 52rpx;
+    text-align: center;
+    font-size: 36rpx;
+    color: #999;
+    border-radius: 50%;
+    background-color: #f5f5f5;
+    flex-shrink: 0;
+}
+
+.pm-remark-btn {
+    height: 52rpx;
+    line-height: 52rpx;
+    padding: 0 24rpx;
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 26rpx;
+    border-radius: 26rpx;
+    margin-right: 16rpx;
+    font-weight: bold;
+    flex-shrink: 0;
+}
+
+.pet-modal-scroll {
+    flex: 1;
+    height: 65vh;
+    overflow: auto;
+}
+
+.pet-base-info {
+    display: flex;
+    align-items: center;
+    padding: 24rpx 30rpx;
+    border-bottom: 1px solid #f9f9f9;
+}
+
+.pm-avatar {
+    width: 100rpx;
+    height: 100rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.pm-info-text {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-name-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8rpx;
+}
+
+.pm-name {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 12rpx;
+}
+
+.pm-gender {
+    display: flex;
+    align-items: center;
+    background-color: #E3F2FD;
+    color: #1976D2;
+    font-size: 22rpx;
+    padding: 2rpx 10rpx;
+    border-radius: 10rpx;
+}
+
+.pm-gender.female {
+    background-color: #FCE4EC;
+    color: #C2185B;
+}
+
+.gender-icon {
+    font-size: 22rpx;
+    margin-right: 4rpx;
+}
+
+.pm-breed {
+    font-size: 26rpx;
+    color: #999;
+}
+
+.pm-detail-grid {
+    padding: 20rpx 30rpx;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16rpx;
+    border-bottom: 1px solid #f9f9f9;
+}
+
+.pm-grid-item {
+    background-color: #FAFAFA;
+    border-radius: 12rpx;
+    padding: 16rpx 20rpx;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-grid-item.half {
+    width: calc(50% - 8rpx);
+}
+
+.pm-grid-item.full {
+    width: 100%;
+}
+
+.pm-label {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 8rpx;
+}
+
+.pm-val {
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.5;
+}
+
+.pm-tags-row {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 16rpx 30rpx;
+    gap: 16rpx;
+    border-bottom: 1px solid #f9f9f9;
+}
+
+.pm-tag-chip {
+    background-color: #FFF3E0;
+    border: 1px solid #FFB74D;
+    border-radius: 20rpx;
+    padding: 6rpx 20rpx;
+}
+
+.pm-tag-chip-text {
+    font-size: 24rpx;
+    color: #FF9800;
+}
+
+.pm-log-section {
+    padding: 20rpx 30rpx;
+}
+
+.pm-log-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.pm-log-section-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pm-log-item {
+    padding: 18rpx 0;
+    border-bottom: 1rpx solid #f5f5f5;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-log-date {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 8rpx;
+}
+
+.pm-log-text {
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.6;
+    margin-bottom: 6rpx;
+}
+
+.pm-log-recorder {
+    font-size: 22rpx;
+    color: #FF9800;
+    text-align: right;
+}
+
+.pm-log-recorder.system {
+    color: #999;
+}
+
+.pm-bottom-close {
+    margin: 16rpx 30rpx;
+    height: 72rpx;
+    line-height: 72rpx;
+    border-radius: 36rpx;
+    font-size: 28rpx;
+    background-color: #f5f5f5;
+    color: #666;
+    border: none;
+}
+
+.pm-bottom-close::after {
+    border: none;
+}
+
+/* 宠护小结底部弹窗 */
+
+.sum-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.50);
+    z-index: 999;
+    display: flex;
+    align-items: flex-end;
+}
+
+.sum-modal-sheet {
+    width: 100%;
+    max-height: 90vh;
+    background-color: #fff;
+    border-radius: 24rpx 24rpx 0 0;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+}
+
+.sum-modal-scroll {
+    flex: 1;
+    overflow: hidden;
+}
+
+.sum-modal-inner {
+    padding: 32rpx 36rpx 0;
+}
+
+.sum-modal-title {
+    display: block;
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+    text-align: center;
+    margin-bottom: 30rpx;
+}
+
+.sum-meta-row {
+    display: flex;
+    margin-bottom: 16rpx;
+    align-items: flex-start;
+}
+
+.sum-meta-label {
+    font-size: 26rpx;
+    color: #999;
+    flex-shrink: 0;
+    width: 140rpx;
+}
+
+.sum-meta-val {
+    font-size: 24rpx;
+    color: #333;
+    flex: 1;
+}
+
+.sum-section-title {
+    font-size: 26rpx;
+    font-weight: bold;
+    color: #333;
+    padding-left: 12rpx;
+    border-left: 6rpx solid #FF9800;
+    margin-top: 24rpx;
+    margin-bottom: 16rpx;
+}
+
+.sum-pet-card {
+    background-color: #FAFAFA;
+    border-radius: 12rpx;
+    padding: 20rpx;
+    display: flex;
+    align-items: center;
+}
+
+.sum-pet-avatar {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+.sum-pet-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.sum-pet-name-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8rpx;
+}
+
+.sum-pet-name {
+    font-size: 26rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 12rpx;
+}
+
+.sum-pet-breed {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.sum-pet-remark {
+    font-size: 24rpx;
+    color: #666;
+    line-height: 1.5;
+}
+
+.sum-textarea {
+    width: 100%;
+    min-height: 220rpx;
+    background-color: #fff;
+    border: 1px solid #eeeeee;
+    border-radius: 12rpx;
+    padding: 18rpx;
+    font-size: 26rpx;
+    color: #333;
+    box-sizing: border-box;
+    line-height: 1.8;
+}
+
+.sum-sign-row {
+    display: flex;
+    align-items: center;
+    margin-top: 30rpx;
+    padding: 16rpx 0;
+    border-top: 1px solid #f5f5f5;
+}
+
+.sum-sign-label {
+    font-size: 26rpx;
+    color: #999;
+    margin-right: 10rpx;
+}
+
+.sum-sign-val {
+    font-size: 26rpx;
+    color: #333;
+}
+
+.sum-footer {
+    padding: 20rpx 36rpx 36rpx;
+    padding-bottom: max(36rpx, constant(safe-area-inset-bottom));
+    padding-bottom: max(36rpx, env(safe-area-inset-bottom));
+    background-color: #fff;
+}
+
+.sum-submit-btn {
+    width: 100%;
+    height: 84rpx;
+    line-height: 84rpx;
+    border-radius: 42rpx;
+    font-size: 30rpx;
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    border: none;
+    box-shadow: 0 4rpx 16rpx rgba(255, 87, 34, 0.25);
+}
+
+.sum-submit-btn::after {
+    border: none;
+}
+
+/* 宠护小结 - 居中白卡样式 */
+.sum-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 999;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.sum-modal-card {
+    width: 660rpx;
+    max-height: 80vh;
+    background-color: #fff;
+    border-radius: 20rpx;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
+}
+
+.sum-modal-scroll {
+    flex: 1;
+    overflow: hidden;
+}
+
+/* 宠物档案 - 备注按钮 */
+.pet-modal-header {
+    display: flex;
+    align-items: center;
+    padding: 30rpx 30rpx 20rpx;
+    border-bottom: 1px solid #f5f5f5;
+}
+
+.pm-remark-btn {
+    height: 52rpx;
+    line-height: 52rpx;
+    padding: 0 24rpx;
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 26rpx;
+    border-radius: 26rpx;
+    margin-right: 16rpx;
+    font-weight: bold;
+}
+
+/* 标签芯片 */
+.pm-tags-row {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 0 24rpx 20rpx;
+    gap: 16rpx;
+}
+
+.pm-tag-chip {
+    background-color: #FFF3E0;
+    border: 1px solid #FFB74D;
+    border-radius: 20rpx;
+    padding: 6rpx 20rpx;
+}
+
+.pm-tag-chip-text {
+    font-size: 24rpx;
+    color: #FF9800;
+}
+
+/* 备注日志 */
+.pm-log-section {
+    padding: 20rpx 24rpx;
+    border-top: 1px solid #f5f5f5;
+    margin-top: 10rpx;
+}
+
+.pm-log-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.pm-log-section-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pm-log-item {
+    padding: 16rpx 0;
+    border-bottom: 1px solid #f9f9f9;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-log-date {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 8rpx;
+}
+
+.pm-log-text {
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.6;
+    margin-bottom: 6rpx;
+}
+
+.pm-log-recorder {
+    font-size: 22rpx;
+    color: #FF9800;
+    text-align: right;
+}
+
+.pm-log-recorder.system {
+    color: #999;
+}

+ 374 - 0
pages/orders/detail.vue

@@ -0,0 +1,374 @@
+<template>
+    <view class="detail-container">
+        <!-- 顶部动态状态区 -->
+        <view class="detail-header">
+            <view class="status-row">
+                <text class="status-title">{{ displayStatusText }}</text>
+                <text class="status-price">¥{{ orderDetail.price }}</text>
+            </view>
+            <!-- 进度条区域 -->
+            <view class="progress-bar">
+                <view class="step-item" v-for="(step, index) in steps" :key="index" :class="{ 'active': index <= currentStep }">
+                    <view class="step-circle-wrapper">
+                        <!-- Connecting Line before circle, except first item -->
+                        <view class="step-line" v-if="index !== 0" :class="{ 'active-line': index <= currentStep }"></view>
+                        <view class="step-circle">{{ index + 1 }}</view>
+                    </view>
+                    <text class="step-text">{{ step }}</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- 内容区域 -->
+        <scroll-view scroll-y class="detail-content">
+            <!-- 宠物信息 -->
+            <view class="white-card pet-bar">
+                <image class="pb-avatar" :src="orderDetail.petAvatar" mode="aspectFill"></image>
+                <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>
+                    </view>
+                </view>
+                <view class="pb-actions">
+                    <view class="pb-btn profile-btn" @click="showPetProfile">宠物档案</view>
+                    <view class="pb-btn phone-btn" @click="callPhone">
+                        <image class="phone-icon" src="/static/icons/phone_orange.svg"></image>
+                    </view>
+                </view>
+            </view>
+
+            <!-- 路线及服务信息 -->
+            <view class="white-card service-info-card">
+                <view class="si-row time-row">
+                    <image class="si-icon outline" src="/static/icons/clock.svg"></image>
+                    <view class="si-content">
+                        <text class="si-label">服务时间</text>
+                        <text class="si-val">{{ orderDetail.time }}</text>
+                    </view>
+                    <view class="si-action record-btn">
+                        <text>异常记录</text>
+                        <image class="record-arrow" src="/static/icons/right_arrow_orange.svg"></image>
+                    </view>
+                </view>
+
+                <!-- 接送类型的地址展现 -->
+                <template v-if="orderDetail.type === 1">
+                    <view class="si-row addr-row start-addr">
+                        <view class="icon-circle start">取</view>
+                        <view class="route-line-vertical"></view>
+                        <view class="si-content">
+                            <text class="si-addr-title">{{ orderDetail.startLocation }}</text>
+                            <text class="si-addr-desc">{{ orderDetail.startAddress }}</text>
+                        </view>
+                        <view class="nav-btn-circle" @click="openNavigation('start')">
+                            <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                        </view>
+                    </view>
+
+                    <view class="si-row addr-row end-addr">
+                        <view class="icon-circle end">送</view>
+                        <view class="si-content">
+                            <text class="si-addr-title">{{ orderDetail.endLocation }}</text>
+                            <text class="si-addr-desc">{{ orderDetail.endAddress }}</text>
+                        </view>
+                        <view class="nav-btn-circle" @click="openNavigation('end')">
+                            <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                        </view>
+                    </view>
+                </template>
+                <!-- 喂遛/洗护类型的地址展现 -->
+                <template v-else>
+                    <view class="si-row addr-row end-addr">
+                        <view class="icon-circle service">服</view>
+                        <view class="si-content">
+                            <text class="si-addr-title">{{ orderDetail.endLocation }}</text>
+                            <text class="si-addr-desc">{{ orderDetail.endAddress }}</text>
+                        </view>
+                        <view class="nav-btn-circle" @click="openNavigation('end')">
+                            <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">
+                        <text class="si-label">备注</text>
+                        <text class="si-val">{{ orderDetail.remark || '无' }}</text>
+                    </view>
+                </view>
+            </view>
+
+            <!-- 打卡任务 -->
+            <view class="white-card task-card" v-if="currentStep < steps.length - 1">
+                <text class="tc-title">当前任务:{{ currentTaskTitle }}</text>
+                <text class="tc-desc">{{ currentTaskDesc }}</text>
+                
+                <!-- 单个巨大点击区触发弹窗 -->
+                <view class="full-media-add" @click="openUploadModal">
+                    <image class="upload-icon-large" src="/static/icons/camera_grey.svg"></image>
+                    <text class="upload-text-large">上传图或视频</text>
+                </view>
+            </view>
+
+            <!-- 订单属性 -->
+            <view class="white-card base-info-card">
+                <view class="bi-row">
+                    <image class="si-icon outline" src="/static/icons/order_no.svg"></image>
+                    <view class="bi-content">
+                        <text class="bi-label">订单编号</text>
+                        <view class="bi-val-row">
+                            <text class="bi-val">{{ orderDetail.orderNo }}</text>
+                            <text class="bi-copy" @click="copyOrderNo">复制</text>
+                        </view>
+                    </view>
+                </view>
+                <view class="bi-row">
+                    <image class="si-icon outline" src="/static/icons/clock.svg"></image>
+                    <view class="bi-content">
+                        <text class="bi-label">下单时间</text>
+                        <text class="bi-val">{{ orderDetail.createTime }}</text>
+                    </view>
+                </view>
+            </view>
+
+            <!-- 订单进度 -->
+            <view class="white-card timeline-card">
+                <view class="tl-title-row">
+                    <view class="orange-bar"></view>
+                    <text class="tl-title">订单进度</text>
+                </view>
+                <view class="tl-list">
+                    <view class="tl-item" v-for="(log, idx) in orderDetail.progressLogs" :key="idx">
+                        <view class="tl-marker active">
+                            <view class="tl-dot-inner"></view>
+                        </view>
+                        <view class="tl-content-row">
+                            <view class="tl-header">
+                                <text class="tl-status">{{ log.status }}</text>
+                                <text class="tl-time">{{ log.time }}</text>
+                            </view>
+                            <!-- 图片展示 -->
+                            <view class="tl-medias" v-if="log.medias && log.medias.length > 0">
+                                <image class="tl-img" v-for="(img, midx) in log.medias" :key="midx" :src="img" mode="aspectFill"></image>
+                            </view>
+                            <!-- 备注展示 -->
+                            <view class="tl-remark" v-if="log.remark">
+                                <text>{{ log.remark }}</text>
+                            </view>
+                        </view>
+                    </view>
+                </view>
+            </view>
+
+            <view style="height: 140rpx;"></view>
+        </scroll-view>
+
+        <!-- 底部操作栏 -->
+        <view class="bottom-action-bar">
+            <view class="action-left">
+                <button class="action-btn outline grey-outline" @click="goToAnomaly">异常上报</button>
+                <button class="action-btn outline orange-outline" @click="openSumModal">宠护小结</button>
+            </view>
+            <view class="action-right">
+                <button class="action-btn primary" @click="openUploadModal" v-if="currentStep < steps.length - 1">{{ currentTaskTitle }}</button>
+                <button class="action-btn primary grey-bg" v-else>已完成</button>
+            </view>
+        </view>
+        
+        <!-- 宠物档案弹窗 -->
+        <view class="pet-modal-mask" v-if="showPetModal" @click="closePetProfile">
+            <view class="pet-modal-content" @click.stop>
+                <!-- 头部 -->
+                <view class="pet-modal-header">
+                    <text class="pet-modal-title">宠物档案</text>
+                    <view style="flex:1"></view>
+                    <view class="pm-remark-btn" @click="openPetRemarkInput">备注</view>
+                    <view class="close-icon-btn" @click="closePetProfile">×</view>
+                </view>
+                <scroll-view scroll-y class="pet-modal-scroll">
+                    <!-- 宠物基础信息 -->
+                    <view class="pet-base-info">
+                        <image class="pm-avatar" :src="currentPetInfo.petAvatar" mode="aspectFill"></image>
+                        <view class="pm-info-text">
+                            <view class="pm-name-row">
+                                <text class="pm-name">{{ currentPetInfo.petName }}</text>
+                                <view class="pm-gender" v-if="currentPetInfo.petGender === 'M'">
+                                    <text class="gender-icon">♂</text>
+                                    <text>公</text>
+                                </view>
+                                <view class="pm-gender female" v-else-if="currentPetInfo.petGender === 'F'">
+                                    <text class="gender-icon">♀</text>
+                                    <text>母</text>
+                                </view>
+                            </view>
+                            <text class="pm-breed">品种:{{ currentPetInfo.petBreed }}</text>
+                        </view>
+                    </view>
+                    <!-- 属性网格 -->
+                    <view class="pm-detail-grid">
+                        <view class="pm-grid-item half">
+                            <text class="pm-label">年龄</text>
+                            <text class="pm-val">{{ currentPetInfo.petAge || '未知' }}</text>
+                        </view>
+                        <view class="pm-grid-item half">
+                            <text class="pm-label">体重</text>
+                            <text class="pm-val">{{ currentPetInfo.petWeight || '未知' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">性格</text>
+                            <text class="pm-val">{{ currentPetInfo.petPersonality || '无' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">爱好</text>
+                            <text class="pm-val">{{ currentPetInfo.petHobby || '无' }}</text>
+                        </view>
+                        <view class="pm-grid-item full">
+                            <text class="pm-label">备注</text>
+                            <text class="pm-val">{{ currentPetInfo.petRemark || '无特殊过敏史' }}</text>
+                        </view>
+                    </view>
+                    <!-- 标签 -->
+                    <view class="pm-tags-row" v-if="currentPetInfo.petTags && currentPetInfo.petTags.length > 0">
+                        <view class="pm-tag-chip" v-for="(tag, ti) in currentPetInfo.petTags" :key="ti">
+                            <text class="pm-tag-chip-text">{{ tag }}</text>
+                        </view>
+                    </view>
+                    <!-- 备注日志 -->
+                    <view class="pm-log-section">
+                        <view class="pm-log-header">
+                            <view style="width:6rpx; height:28rpx; background:#FF9800; border-radius:3rpx; margin-right:12rpx;"></view>
+                            <text class="pm-log-section-title">备注日志</text>
+                        </view>
+                        <view class="pm-log-item" v-for="(log, lIndex) in currentPetInfo.petLogs" :key="lIndex">
+                            <text class="pm-log-date">{{ log.date }}</text>
+                            <text class="pm-log-text">{{ log.content }}</text>
+                            <text class="pm-log-recorder" v-if="log.recorder !== '系统记录'">记录人:{{ log.recorder }}</text>
+                            <text class="pm-log-recorder system" v-else>系统记录</text>
+                        </view>
+                    </view>
+                    <view style="height: 30rpx;"></view>
+                </scroll-view>
+            </view>
+        </view>
+        <!-- 宠物备注输入弹窗 -->
+        <view class="upload-modal-mask" v-if="showPetRemarkInput" @click="closePetRemarkInput">
+            <view class="upload-modal-content" @click.stop>
+                <view class="um-header">
+                    <text class="um-title">添加备注</text>
+                </view>
+                <view class="um-body">
+                    <textarea class="um-textarea" v-model="petRemarkText" auto-height placeholder="请输入宠物备注内容..."
+                        placeholder-style="color:#ccc; font-size:26rpx;"></textarea>
+                </view>
+                <view class="um-footer">
+                    <button class="um-submit-btn active" @click="submitPetRemark">确认提交</button>
+                </view>
+            </view>
+        </view>
+
+        <!-- 选择地图导航弹窗 (复用) -->
+        <view class="nav-modal-mask" v-if="showNavModal" @click="closeNavModal">
+            <view class="nav-action-sheet" @click.stop>
+                <view class="nav-sheet-title">选择地图进行导航</view>
+                <view class="nav-sheet-item" @click="chooseMap('高德')">高德地图</view>
+                <view class="nav-sheet-item" @click="chooseMap('腾讯')">腾讯地图</view>
+                <view class="nav-sheet-item" @click="chooseMap('百度')">百度地图</view>
+                <view class="nav-sheet-gap"></view>
+                <view class="nav-sheet-item cancel" @click="closeNavModal">取消</view>
+            </view>
+        </view>
+
+        <!-- 上传图视频弹窗 (新增) -->
+        <view class="upload-modal-mask" v-if="showUploadModal" @click="closeUploadModal">
+            <view class="upload-modal-content" @click.stop>
+                <view class="um-header">
+                    <text class="um-title">上传图或视频 ({{ modalMediaList.length }}/5)</text>
+                </view>
+                <view class="um-body">
+                    <view class="um-grid">
+                        <view class="um-item" v-for="(img, idx) in modalMediaList" :key="idx">
+                            <image class="um-preview" :src="img" mode="aspectFill"></image>
+                            <view class="um-del" @click="removeModalMedia(idx)">×</view>
+                        </view>
+                        <view class="um-add" @click="chooseModalMedia" v-if="modalMediaList.length < 5">
+                            <image class="um-add-icon" src="/static/icons/camera_grey.svg"></image>
+                            <text class="um-add-text">拍摄/上传</text>
+                        </view>
+                    </view>
+                    <textarea class="um-textarea" v-model="modalRemark" placeholder="在此输入备注信息..." placeholder-style="color:#ccc; font-size:26rpx;"></textarea>
+                </view>
+                <view class="um-footer">
+                    <button class="um-submit-btn" :class="{'active': modalMediaList.length > 0}" @click="confirmUploadModal">确认提交</button>
+                </view>
+            </view>
+        </view>
+        <!-- 宠护小结弹窗 -->
+        <view class="sum-modal-mask" v-if="showSumModal" @click="closeSumModal">
+            <view class="sum-modal-card" @click.stop>
+                <scroll-view scroll-y class="sum-modal-scroll">
+                    <view class="sum-modal-inner">
+                        <text class="sum-modal-title">宠物护理工作小结</text>
+                        <view class="sum-meta-row">
+                            <text class="sum-meta-label">日期:</text>
+                            <text class="sum-meta-val">{{ sumDate }}</text>
+                        </view>
+                        <view class="sum-meta-row">
+                            <text class="sum-meta-label">客户住址:</text>
+                            <text class="sum-meta-val">{{ orderDetail.endAddress }}</text>
+                        </view>
+                        <view class="sum-meta-row">
+                            <text class="sum-meta-label">宠主姓名:</text>
+                            <text class="sum-meta-val">{{ orderDetail.ownerName || '张**' }}</text>
+                        </view>
+                        <view class="sum-section-title">宠物信息</view>
+                        <view class="sum-pet-card">
+                            <image class="sum-pet-avatar" :src="orderDetail.petAvatar" mode="aspectFill"></image>
+                            <view class="sum-pet-info">
+                                <view class="sum-pet-name-row">
+                                    <text class="sum-pet-name">{{ orderDetail.petName }}</text>
+                                    <text class="sum-pet-breed">品种: {{ orderDetail.petBreed }}</text>
+                                </view>
+                                <text class="sum-pet-remark">{{ orderDetail.petNotes || '喜欢坐车,有点晗车,请注意通风。' }}</text>
+                            </view>
+                        </view>
+                        <view class="sum-section-title">服务内容记录</view>
+                        <textarea class="sum-textarea" v-model="sumContent" auto-height placeholder="请填写服务内容..." placeholder-style="color:#ccc"></textarea>
+                        <view class="sum-sign-row">
+                            <text class="sum-sign-label">护宠师签名:</text>
+                            <text class="sum-sign-val">{{ sumSigner }}</text>
+                        </view>
+                        <view style="height: 20rpx;"></view>
+                    </view>
+                </scroll-view>
+                <view class="sum-footer">
+                    <button class="sum-submit-btn" @click="submitSumModal">提交小结</button>
+                </view>
+            </view>
+        </view>
+
+    </view>
+</template>
+
+<script>
+import logic from './detail-logic.js';
+export default {
+    ...logic
+}
+</script>
+
+<style>
+@import './detail-style.css';
+</style>

+ 316 - 0
pages/orders/index.vue

@@ -0,0 +1,316 @@
+<template>
+    <view class="container">
+        <!-- 吸顶固定层:状态tab + 搜索 + 筛选 -->
+        <view class="sticky-header">
+            <!-- 顶部 Tab (待接送/服务中...) -->
+            <view class="status-tabs">
+                <view 
+                    class="tab-item" 
+                    v-for="(tab, index) in tabs" 
+                    :key="index"
+                    :class="{ active: currentTab === index }"
+                    @click="currentTab = index"
+                >
+                    <text>{{ tab }}</text>
+                    <view class="indicator" v-if="currentTab === index"></view>
+                </view>
+            </view>
+
+            <!-- 搜索栏 -->
+            <view class="search-bar">
+                <view class="search-input-box">
+                    <input class="search-input" placeholder="搜索地址/电话/姓名" placeholder-class="ph-style" />
+                </view>
+            </view>
+
+            <!-- 筛选栏 (支持自定义下拉) -->
+            <view class="filter-wrapper">
+            <view class="filter-bar">
+                <!-- 订单类型下拉视图 -->
+                <view class="filter-item" :class="{ 'active': activeDropdown === 1 }" @click="toggleDropdown(1)">
+                    <text :class="{ 'active-text': activeDropdown === 1 || currentTypeFilterIdx > 0 }">
+                        {{ currentTypeFilterIdx > 0 ? typeFilterOptions[currentTypeFilterIdx] : '全部类型' }}
+                    </text>
+                    <view class="triangle" :class="activeDropdown === 1 ? 'up' : 'down'"></view>
+                </view>
+                
+                <!-- 服务时间下拉视图 -->
+                <view class="filter-item" :class="{ 'active': activeDropdown === 2 }" @click="toggleDropdown(2)">
+                    <text :class="{ 'active-text': activeDropdown === 2 || hasTimeFilter }">服务时间</text>
+                    <view class="triangle" :class="activeDropdown === 2 ? 'up' : 'down'"></view>
+                </view>
+            </view>
+            
+            <!-- 下拉内容面板与遮罩 -->
+            <view class="dropdown-mask" v-if="activeDropdown !== 0" @click="closeDropdown"></view>
+            <view class="dropdown-panel" v-if="activeDropdown === 1">
+                <view 
+                    class="type-option" 
+                    v-for="(item, index) in typeFilterOptions" 
+                    :key="index"
+                    :class="{ 'selected': currentTypeFilterIdx === index }"
+                    @click="selectType(index)"
+                >
+                    <text>{{ item }}</text>
+                </view>
+            </view>
+            <view class="dropdown-panel calendar-panel" v-if="activeDropdown === 2">
+                <view class="custom-calendar-container">
+                    <!-- 头部 -->
+                    <view class="cal-header">
+                        <uni-icons type="left" size="18" color="#666" @click="prevMonth"></uni-icons>
+                        <text class="cal-title">{{ currentMonth }}</text>
+                        <uni-icons type="right" size="18" color="#666" @click="nextMonth"></uni-icons>
+                    </view>
+                    <!-- 星期条 -->
+                    <view class="cal-weekdays">
+                        <text v-for="(wk, idx) in weekDays" :key="idx" class="wk-item">{{ wk }}</text>
+                    </view>
+                    <!-- 日期网格 -->
+                    <view class="cal-body">
+                        <!-- Feb 2026 starts on Sunday (index 0), so no empty padding needed for first row -->
+                        <view 
+                            v-for="(day, idx) in calendarDays" 
+                            :key="idx"
+                            class="cal-day-box"
+                            :class="getDateClass(day)"
+                            @click="selectDateItem(day)"
+                        >
+                            <view class="cal-day-text">{{ day }}</view>
+                        </view>
+                    </view>
+                </view>
+                <view class="calendar-actions">
+                    <button class="cal-btn reset" @click="resetTimeFilter">重置</button>
+                    <button class="cal-btn confirm" @click="confirmTimeFilter">确定</button>
+                </view>
+            </view>
+        </view><!-- end filter-wrapper -->
+        </view><!-- end sticky-header -->
+
+        <!-- 订单列表 -->
+        <scroll-view scroll-y class="order-list">
+            <view class="order-card" v-for="(item, index) in orderList" :key="index" @click="goToDetail(item)">
+                <view class="card-header">
+                    <view class="type-badge">
+                        <image class="type-icon" :src="item.typeIcon"></image>
+                        <text class="type-text">{{ item.typeText }}</text>
+                    </view>
+                    <text class="status-badge" :class="getStatusClass(item)">{{ getDisplayStatus(item) }}</text>
+                </view>
+
+                <view class="card-body">
+                    <view class="time-row">
+                        <view class="time-col">
+                            <text class="label">{{ item.timeLabel }}:</text>
+                            <text class="value">{{ item.time }}</text>
+                        </view>
+                        <text class="price">¥{{ item.price }}</text>
+                    </view>
+
+                    <!-- 宠物信息 -->
+                    <view class="pet-card">
+                        <image class="pet-avatar" :src="item.petAvatar" mode="aspectFill"></image>
+                        <view class="pet-info">
+                            <text class="pet-name">{{ item.petName }}</text>
+                            <text class="pet-breed">品种: {{ item.petBreed }}</text>
+                        </view>
+                        <view class="pet-profile-btn" @click.stop="showPetProfile(item)">宠物档案</view>
+                    </view>
+
+                <!-- 路线信息 (完全复用 Home 样式) -->
+                <view class="route-info">
+                    <template v-if="item.type === 1">
+                        <view class="route-item" @click.stop="openNavigation(item, 'start')">
+                            <view class="icon-circle start">取</view>
+                            <view class="route-line-vertical"></view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ item.startLocation }}</text>
+                                <text class="addr-desc">{{ item.startAddress }}</text>
+                            </view>
+                            <view class="distance-tag">
+                                <text class="distance-text">{{ item.startDistance }}</text>
+                                <view class="nav-icon-circle">
+                                    <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                </view>
+                            </view>
+                        </view>
+
+                        <view class="route-item" @click.stop="openNavigation(item, 'end')">
+                            <view class="icon-circle end">送</view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ item.endLocation }}</text>
+                                <text class="addr-desc">{{ item.endAddress }}</text>
+                            </view>
+                            <view class="distance-tag">
+                                <text class="distance-text">{{ item.endDistance }}</text>
+                                <view class="nav-icon-circle">
+                                    <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                </view>
+                            </view>
+                        </view>
+                    </template>
+                    <template v-else>
+                        <view class="route-item" @click.stop="openNavigation(item, 'end')">
+                            <view class="icon-circle service">服</view>
+                            <view class="address-box">
+                                <text class="addr-title">{{ item.endLocation }}</text>
+                                <text class="addr-desc">{{ item.endAddress }}</text>
+                            </view>
+                            <view class="distance-tag">
+                                <text class="distance-text">{{ item.endDistance }}</text>
+                                <view class="nav-icon-circle">
+                                    <image class="nav-arrow" src="/static/icons/nav_arrow.svg"></image>
+                                </view>
+                            </view>
+                        </view>
+                        <view class="service-content" v-if="item.serviceContent">
+                            <text class="content-label">服务内容:</text>
+                            <text>{{ item.serviceContent }}</text>
+                        </view>
+                    </template>
+                </view>
+
+                <!-- 备注 -->
+                <view class="remark-box" v-if="item.remark">
+                    <text>备注:{{ item.remark }}</text>
+                </view>
+                </view><!-- End of card-body -->
+
+                <!-- 按钮组 -->
+                <view class="action-btns" v-if="['接单', '到达', '出发', '开始', '送达', '结束'].includes(item.statusText)">
+                    <view class="action-left">
+                        <button class="btn normal" @click.stop="toggleCallMenu(item)">一键拨号</button>
+                        <view class="call-popover" v-if="activeCallItem === item" @click.stop>
+                            <view class="call-pop-item" @click="doCall('merchant')">联系商家</view>
+                            <view class="call-pop-item" @click="doCall('customer')">联系客户</view>
+                        </view>
+                    </view>
+                    <view class="action-right">
+                        <button class="btn normal" @click.stop="reportAbnormal(item)">异常上报</button>
+                        <button class="btn primary" @click.stop="mainAction(item)">{{ getMainActionText(item) }}</button>
+                    </view>
+                </view>
+            </view>
+            <!-- 已加载完提示文字 -->
+            <view class="loading-text">已加载完</view>
+            <view style="height: 160rpx;"></view>
+        </scroll-view>
+        <view class="call-mask" v-if="activeCallItem" @click="closeCallMenu"></view>
+    </view>
+
+    <!-- 宠物档案弹窗 (复用Home) -->
+    <view class="pet-modal-mask" v-if="showPetModal" @click="closePetProfile">
+        <view class="pet-modal-content" @click.stop>
+            <view class="pet-modal-header">
+                <text class="pet-modal-title">宠物档案</text>
+                <view class="pm-header-actions">
+                    <view class="pm-remark-btn" @click="openRemarkInput">备注</view>
+                    <view class="close-icon-btn" @click="closePetProfile">×</view>
+                </view>
+            </view>
+            <scroll-view scroll-y class="pet-modal-scroll">
+                <!-- Basic Info -->
+                <view class="pet-base-info">
+                    <image class="pm-avatar" :src="currentPetInfo.petAvatar" mode="aspectFill"></image>
+                    <view class="pm-info-text">
+                        <view class="pm-name-row">
+                            <text class="pm-name">{{ currentPetInfo.petName }}</text>
+                            <view class="pm-gender" v-if="currentPetInfo.petGender === 'M'">
+                                <text class="gender-icon">♂</text>
+                                <text>公</text>
+                            </view>
+                            <view class="pm-gender female" v-else-if="currentPetInfo.petGender === 'F'">
+                                <text class="gender-icon">♀</text>
+                                <text>母</text>
+                            </view>
+                        </view>
+                        <text class="pm-breed">品种:{{ currentPetInfo.petBreed }}</text>
+                    </view>
+                </view>
+                <!-- Details Grid -->
+                <view class="pm-detail-grid">
+                    <view class="pm-grid-item half">
+                        <text class="pm-label">年龄</text>
+                        <text class="pm-val">{{ currentPetInfo.petAge || '未知' }}</text>
+                    </view>
+                    <view class="pm-grid-item half">
+                        <text class="pm-label">体重</text>
+                        <text class="pm-val">{{ currentPetInfo.petWeight || '未知' }}</text>
+                    </view>
+                    <view class="pm-grid-item full">
+                        <text class="pm-label">性格</text>
+                        <text class="pm-val">{{ currentPetInfo.petPersonality || '无' }}</text>
+                    </view>
+                    <view class="pm-grid-item full">
+                        <text class="pm-label">爱好</text>
+                        <text class="pm-val">{{ currentPetInfo.petHobby || '无' }}</text>
+                    </view>
+                    <view class="pm-grid-item full">
+                        <text class="pm-label">备注</text>
+                        <text class="pm-val">{{ currentPetInfo.petRemark || '无特殊过敏史' }}</text>
+                    </view>
+                </view>
+                <!-- Tags -->
+                <view class="pm-tags" v-if="currentPetInfo.petTags && currentPetInfo.petTags.length > 0">
+                    <view class="pm-tag" v-for="(tag, index) in currentPetInfo.petTags" :key="index">{{ tag }}</view>
+                </view>
+                <!-- Log Section -->
+                <view class="pm-section-title">
+                    <view class="orange-bar"></view>
+                    <text>备注日志</text>
+                </view>
+                <view class="pm-log-list">
+                    <view class="pm-log-item" v-for="(log, lIndex) in currentPetInfo.petLogs" :key="lIndex">
+                        <text class="pm-log-date">{{ log.date }}</text>
+                        <text class="pm-log-text">{{ log.content }}</text>
+                        <text class="pm-log-recorder">{{ log.recorder === '系统记录' ? '' : '记录人: '}}{{ log.recorder }}</text>
+                    </view>
+                </view>
+                <view style="height: 30rpx;"></view>
+            </scroll-view>
+        </view>
+    </view>
+
+    <!-- 备注输入弹窗 -->
+    <view class="remark-mask" v-if="showRemarkInput" @click="closeRemarkInput">
+        <view class="remark-sheet" @click.stop>
+            <view class="remark-sheet-header">
+                <text class="remark-sheet-title">添加备注</text>
+                <view class="close-icon-btn" @click="closeRemarkInput">×</view>
+            </view>
+            <textarea
+                class="remark-textarea"
+                v-model="remarkText"
+                placeholder="请输入备注内容..."
+                maxlength="500"
+                auto-height
+            />
+            <view class="remark-submit-btn" @click="submitRemark">提交备注</view>
+        </view>
+    </view>
+
+    <!-- 选择地图导航弹窗 (复用Home) -->
+    <view class="nav-modal-mask" v-if="showNavModal" @click="closeNavModal">
+        <view class="nav-action-sheet" @click.stop>
+            <view class="nav-sheet-title">选择地图进行导航</view>
+            <view class="nav-sheet-item" @click="chooseMap('高德')">高德地图</view>
+            <view class="nav-sheet-item" @click="chooseMap('腾讯')">腾讯地图</view>
+            <view class="nav-sheet-item" @click="chooseMap('百度')">百度地图</view>
+            <view class="nav-sheet-gap"></view>
+            <view class="nav-sheet-item cancel" @click="closeNavModal">取消</view>
+        </view>
+    </view>
+
+</template>
+
+<script>
+import logic from './logic.js';
+export default {
+    ...logic
+}
+</script>
+
+<style>
+@import './style.css';
+</style>

+ 322 - 0
pages/orders/logic.js

@@ -0,0 +1,322 @@
+export default {
+    data() {
+        return {
+            currentTab: 0,
+            tabs: ['待接送/服务', '配送/服务中', '已完成', '已拒绝'],
+            // Filter dropdown states
+            typeFilterOptions: ['全部类型', '接送', '喂遛', '洗护'],
+            currentTypeFilterIdx: 0,
+            activeDropdown: 0, // 0 = none, 1 = type filter, 2 = time filter
+            hasTimeFilter: false,
+
+            // Custom Calendar State (Mock Feb 2026)
+            currentMonth: '2026年2月',
+            weekDays: ['日', '一', '二', '三', '四', '五', '六'],
+            calendarDays: [], // Generated in onLoad or created
+            selectedDateRange: [], // stores [start, end]
+
+            allOrderList: [
+                // === Tab 1: 待接送/服务 (Status: 接单) ===
+                { type: 1, typeText: '接送', typeIcon: '/static/icons/car.svg', statusText: '接单', price: '20.00', timeLabel: '取货时间', time: '2026/02/10 10:00', petAvatar: '/static/dog.png', petName: '哈士奇宝宝', petBreed: '哈士奇', startLocation: '武汉大学宠物店', startAddress: '武汉市洪山区珞喻路458号', startDistance: '0.5km', endLocation: '张** 189****8451', endAddress: '武汉市武昌区新区大道凤凰广场25号', endDistance: '2.5km', remark: '尽快接单。' },
+                { type: 2, typeText: '喂遛', typeIcon: '/static/icons/walk.svg', statusText: '接单', price: '30.00', timeLabel: '服务时间', time: '2026/02/10 14:00', petAvatar: '/static/dog.png', petName: '边牧', petBreed: '边境牧羊犬', endLocation: '李** 138****0001', endAddress: '武汉市洪山区保利花园', endDistance: '1.5km', serviceContent: '需自带牵引绳。', remark: '狗狗很活泼。' },
+                { type: 3, typeText: '洗护', typeIcon: '/static/icons/wash.svg', statusText: '接单', price: '60.00', timeLabel: '服务时间', time: '2026/02/10 16:00', petAvatar: '/static/dog.png', petName: '布偶', petBreed: '布偶猫', endLocation: '王** 139****0002', endAddress: '武汉市汉阳区钟家村', endDistance: '3.5km', serviceContent: '上门洗护、全身检查', remark: '猫咪怕水。' },
+
+                // === Tab 2: 配送/服务中 (Status: 出发/开始/到达等) ===
+                { type: 1, typeText: '接送', typeIcon: '/static/icons/car.svg', statusText: '出发', price: '25.00', timeLabel: '取货时间', time: '2026/02/11 09:00', petAvatar: '/static/dog.png', petName: '柯基', petBreed: '柯基犬', startLocation: '南湖宠物店', startAddress: '武汉市洪山区南湖大道', startDistance: '1.0km', endLocation: '陈** 158****0003', endAddress: '武汉市江夏区藏龙岛', endDistance: '6.5km', remark: '已接到狗狗,送往目的地。' },
+                { type: 2, typeText: '喂遛', typeIcon: '/static/icons/walk.svg', statusText: '开始', price: '35.00', timeLabel: '服务时间', time: '2026/02/11 15:00', petAvatar: '/static/dog.png', petName: '金毛', petBreed: '金毛寻回犬', endLocation: '赵** 159****0004', endAddress: '武汉市江汉区泛海国际', endDistance: '4.5km', serviceContent: '遛弯一小时', remark: '注意避开大型犬。' },
+                { type: 3, typeText: '洗护', typeIcon: '/static/icons/wash.svg', statusText: '开始', price: '80.00', timeLabel: '服务时间', time: '2026/02/11 18:00', petAvatar: '/static/dog.png', petName: '英短', petBreed: '英国短毛猫', endLocation: '钱** 177****0005', endAddress: '武汉市武昌区楚河汉街', endDistance: '2.0km', serviceContent: '深度去污、洗护', remark: '客户要求修剪指甲。' },
+
+                // === Tab 3: 已完成 (Status: 已完成) ===
+                { type: 1, typeText: '接送', typeIcon: '/static/icons/car.svg', statusText: '已完成', price: '40.00', timeLabel: '取货时间', time: '2026/02/12 10:00', petAvatar: '/static/dog.png', petName: '柴犬', petBreed: '柴犬', startLocation: '汉口宠物医院', startAddress: '武汉市江岸区解放大道', startDistance: '2.0km', endLocation: '孙** 186****0006', endAddress: '武汉市东西湖区金银湖', endDistance: '10.5km', remark: '安全抵达。' },
+                { type: 2, typeText: '喂遛', typeIcon: '/static/icons/walk.svg', statusText: '已完成', price: '28.00', timeLabel: '服务时间', time: '2026/02/12 16:00', petAvatar: '/static/dog.png', petName: '萨摩耶', petBreed: '萨摩耶犬', endLocation: '周** 188****0007', endAddress: '武汉市洪山区软件园', endDistance: '0.8km', serviceContent: '遛狗', remark: '遛得很开心。' },
+                { type: 3, typeText: '洗护', typeIcon: '/static/icons/wash.svg', statusText: '已完成', price: '120.00', timeLabel: '服务时间', time: '2026/02/12 19:00', petAvatar: '/static/dog.png', petName: '加菲', petBreed: '加菲猫', endLocation: '吴** 189****0008', endAddress: '武汉市青山区别区', endDistance: '5.0km', serviceContent: '全套美容洗护', remark: '客户非常满意。' },
+
+                // === Tab 4: 已拒绝 (Status: 已拒绝) ===
+                { type: 1, typeText: '接送', typeIcon: '/static/icons/car.svg', statusText: '已拒绝', price: '15.00', timeLabel: '取货时间', time: '2026/02/13 09:00', petAvatar: '/static/dog.png', petName: '吉娃娃', petBreed: '吉娃娃', startLocation: '宠物乐园', startAddress: '武汉市黄陂区盘龙城', startDistance: '3.0km', endLocation: '郑** 133****0009', endAddress: '武汉市汉南区', endDistance: '20.5km', remark: '路程太远。' },
+                { type: 2, typeText: '喂遛', typeIcon: '/static/icons/walk.svg', statusText: '已拒绝', price: '22.00', timeLabel: '服务时间', time: '2026/02/13 14:00', petAvatar: '/static/dog.png', petName: '博美', petBreed: '博美犬', endLocation: '刘** 134****0010', endAddress: '武汉市蔡甸区', endDistance: '15.0km', serviceContent: '公园遛弯', remark: '天气原因取消。' },
+                { type: 3, typeText: '洗护', typeIcon: '/static/icons/wash.svg', statusText: '已拒绝', price: '45.00', timeLabel: '服务时间', time: '2026/02/13 17:00', petAvatar: '/static/dog.png', petName: '暹罗', petBreed: '暹罗猫', endLocation: '张** 135****0011', endAddress: '武汉市新洲区', endDistance: '18.0km', serviceContent: '洗澡', remark: '时间冲突。' }
+            ],
+            showPetModal: false,
+            currentPetInfo: {},
+            showNavModal: false,
+            navTargetItem: null,
+            navTargetPointType: '',
+
+            // Popover control
+            activeCallItem: null,
+            // 备注输入弹窗
+            showRemarkInput: false,
+            remarkText: ''
+        }
+    },
+    created() {
+        this.initCalendar();
+    },
+    computed: {
+        orderList() {
+            return this.allOrderList.filter(item => {
+                // 1. Tab Status Filter
+                // 待接送/服务: [接送]的接单, [喂遛/洗护]的接单
+                // 配送/服务中: [接送]的到达、出发、送达; [喂遛/洗护]的到达、开始、结束
+                // 已完成: 完成
+                let matchTab = false;
+                if (this.currentTab === 0) {
+                    matchTab = item.statusText === '接单';
+                } else if (this.currentTab === 1) {
+                    let pickingTypes = ['到达', '出发', '送达'];
+                    let serviceTypes = ['到达', '开始', '结束'];
+                    if (item.type === 1) {
+                        matchTab = pickingTypes.includes(item.statusText);
+                    } else {
+                        matchTab = serviceTypes.includes(item.statusText);
+                    }
+                } else if (this.currentTab === 2) {
+                    matchTab = item.statusText === '已完成';
+                } else if (this.currentTab === 3) {
+                    matchTab = item.statusText === '已拒绝';
+                }
+
+                // 2. Type Filter
+                let matchType = true;
+                if (this.currentTypeFilterIdx > 0) {
+                    matchType = item.type === parseInt(this.currentTypeFilterIdx);
+                }
+
+                // 3. Time Filter (Mocked)
+                let matchTime = true; // For now treat all equally unless parsed
+
+                return matchTab && matchType && matchTime;
+            });
+        }
+    },
+    methods: {
+        getDisplayStatus(item) {
+            if (item.statusText === '已完成') return '已完成';
+            if (item.statusText === '已拒绝') return '已拒绝';
+            if (item.statusText === '接单') {
+                return item.type === 1 ? '待接送' : '待服务';
+            }
+            // For other active states (出发, 到达, 送达, 开始, 结束)
+            return item.type === 1 ? '配送中' : '服务中';
+        },
+        getStatusClass(item) {
+            let display = this.getDisplayStatus(item);
+            if (display === '已完成') return 'finish';
+            if (display === '已拒绝') return 'reject';
+            if (display === '配送中' || display === '服务中') return 'processing';
+            return 'highlight';
+        },
+        goToDetail(item) {
+            // 将在 detail 页面实现
+            uni.navigateTo({
+                url: `/pages/orders/detail?type=${item.type}`
+            });
+        },
+        showPetProfile(item) {
+            // 补全 mock 数据
+            this.currentPetInfo = {
+                ...item,
+                petGender: 'M',
+                petAge: '2岁',
+                petWeight: '15kg',
+                petPersonality: '活泼亲人,精力旺盛',
+                petHobby: '喜欢追飞盘,爱吃肉干',
+                petRemark: '肠胃较弱,不能乱喂零食;出门易爆冲,请拉紧牵引绳。',
+                petTags: ['拉响警报', '不能吃鸡肉', '精力旺盛'],
+                petLogs: [
+                    { date: '2026-02-09 14:00', content: '今天遛弯拉了两次粑粑,精神状态很好。', recorder: '王阿姨' },
+                    { date: '2026-02-08 10:30', content: '有些挑食,剩了小半碗狗粮。', recorder: '李师傅' },
+                    { date: '2026-02-05 09:00', content: '建档。', recorder: '系统记录' }
+                ]
+            };
+            this.showPetModal = true;
+        },
+        closePetProfile() {
+            this.showPetModal = false;
+        },
+        openNavigation(item, pointType) {
+            this.navTargetItem = item;
+            this.navTargetPointType = pointType;
+            this.showNavModal = true;
+        },
+        closeNavModal() {
+            this.showNavModal = false;
+        },
+        chooseMap(mapType) {
+            let item = this.navTargetItem;
+            let pointType = this.navTargetPointType;
+            let name = pointType === 'start' ? item.startLocation : item.endLocation;
+            let address = pointType === 'start' ? item.startAddress : item.endAddress;
+
+            this.showNavModal = false;
+
+            uni.openLocation({
+                latitude: 30.52, // Mock lat
+                longitude: 114.31, // Mock lng
+                name: name || '目的地',
+                address: address || '默认地址',
+                success: function () {
+                    console.log('打开导航成功: ' + mapType);
+                }
+            });
+        },
+        toggleCallMenu(item) {
+            if (this.activeCallItem === item) {
+                this.activeCallItem = null;
+            } else {
+                this.activeCallItem = item;
+            }
+        },
+        closeCallMenu() {
+            this.activeCallItem = null;
+        },
+        doCall(type) {
+            let phoneNum = ''
+            if (type === 'merchant') {
+                phoneNum = '18900008451' // Mock merchant
+            } else if (type === 'customer') {
+                phoneNum = '13800000001' // Mock customer
+            }
+            if (phoneNum) {
+                uni.makePhoneCall({ phoneNumber: phoneNum })
+            }
+            this.activeCallItem = null;
+        },
+        reportAbnormal(item) {
+            uni.showToast({ title: '上报功能待开发', icon: 'none' });
+        },
+        toggleDropdown(idx) {
+            // If clicking the currently open one, close it
+            if (this.activeDropdown === idx) {
+                this.activeDropdown = 0;
+            } else {
+                this.activeDropdown = idx;
+            }
+        },
+        closeDropdown() {
+            this.activeDropdown = 0;
+        },
+        selectType(index) {
+            this.currentTypeFilterIdx = index;
+            this.closeDropdown();
+        },
+        initCalendar() {
+            // Mock Feb 2026 (1 is Sunday, 28 is Saturday)
+            let days = [];
+            for (let i = 1; i <= 28; i++) {
+                days.push(i);
+            }
+            this.calendarDays = days;
+            // Pre-select 2, 3, 4 for the demo in Figure 2
+            this.selectedDateRange = [2, 4];
+        },
+        prevMonth() { uni.showToast({ title: '上个月', icon: 'none' }); },
+        nextMonth() { uni.showToast({ title: '下个月', icon: 'none' }); },
+        selectDateItem(day) {
+            // Simple range toggle logic
+            if (this.selectedDateRange.length === 2) {
+                this.selectedDateRange = [day]; // Reset to new start
+            } else if (this.selectedDateRange.length === 1) {
+                let start = this.selectedDateRange[0];
+                if (day > start) {
+                    this.selectedDateRange = [start, day];
+                } else if (day < start) {
+                    this.selectedDateRange = [day, start];
+                } else {
+                    this.selectedDateRange = []; // clear if same clicked
+                }
+            } else {
+                this.selectedDateRange = [day];
+            }
+        },
+        getDateClass(day) {
+            if (this.selectedDateRange.length === 0) return '';
+            if (this.selectedDateRange.length === 1) {
+                return day === this.selectedDateRange[0] ? 'is-start' : '';
+            }
+            let start = this.selectedDateRange[0];
+            let end = this.selectedDateRange[1];
+            if (day === start) return 'is-start';
+            if (day === end) return 'is-end';
+            if (day > start && day < end) return 'is-between';
+            return '';
+        },
+        resetTimeFilter() {
+            this.hasTimeFilter = false;
+            this.selectedDateRange = [];
+            uni.showToast({ title: '已重置服务时间', icon: 'none' });
+            this.closeDropdown();
+        },
+        confirmTimeFilter() {
+            if (this.selectedDateRange.length === 0) {
+                uni.showToast({ title: '请先选择日期', icon: 'none' });
+                return;
+            }
+            let text = this.selectedDateRange.length === 2 ?
+                `${this.selectedDateRange[0]}日-${this.selectedDateRange[1]}日` :
+                `${this.selectedDateRange[0]}日`;
+            uni.showToast({ title: '已应用: ' + text, icon: 'none' });
+            this.hasTimeFilter = true;
+            this.closeDropdown();
+        },
+        getMainActionText(item) {
+            if (item.statusText === '接单') {
+                return '到达打卡'; // Next step
+            } else if (item.statusText === '到达' && item.type === 1) {
+                return '确认出发';
+            } else if (item.statusText === '到达' && item.type !== 1) {
+                return '开始服务';
+            } else if (item.statusText === '出发') {
+                return '送达打卡';
+            } else if (item.statusText === '开始') {
+                return '结束服务';
+            } else if (item.statusText === '送达' || item.statusText === '结束') {
+                return '服务完成';
+            }
+            return '查看详情';
+        },
+        mainAction(item) {
+            // Simply navigate to detail page, where the real action button lives
+            uni.navigateTo({
+                url: `/pages/orders/detail?type=${item.type}`
+            });
+        },
+        reportAbnormal(item) {
+            uni.navigateTo({
+                url: '/pages/orders/anomaly?orderId=' + (item.orderNo || '')
+            });
+        },
+        // 打开备注输入弹窗
+        openRemarkInput() {
+            this.remarkText = '';
+            this.showRemarkInput = true;
+        },
+        // 关闭备注输入弹窗
+        closeRemarkInput() {
+            this.showRemarkInput = false;
+            this.remarkText = '';
+        },
+        // 提交备注,追加到宠物档案日志列表
+        submitRemark() {
+            const text = this.remarkText.trim();
+            if (!text) {
+                uni.showToast({ title: '备注内容不能为空', icon: 'none' });
+                return;
+            }
+            // 获取当前时间
+            const now = new Date();
+            const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
+            // 追加到当前宠物的日志列表头部
+            if (!this.currentPetInfo.petLogs) {
+                this.$set(this.currentPetInfo, 'petLogs', []);
+            }
+            this.currentPetInfo.petLogs.unshift({
+                date: dateStr,
+                content: text,
+                recorder: '我'
+            });
+            uni.showToast({ title: '备注已添加', icon: 'success' });
+            this.closeRemarkInput();
+        }
+    }
+}

+ 1090 - 0
pages/orders/style.css

@@ -0,0 +1,1090 @@
+page {
+    background-color: #F8F8F8;
+}
+
+/* 自定义导航标题栏(因navigationStyle:custom) */
+.custom-nav-bar {
+    padding: 80rpx 30rpx 20rpx;
+    background-color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.nav-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+/* 吸顶容器:状态tab + 搜索 + 筛选 */
+.sticky-header {
+    position: sticky;
+    top: 0;
+    z-index: 999;
+    background-color: #F8F8F8;
+}
+
+.container {
+    background-color: #F8F8F8;
+    display: flex;
+    flex-direction: column;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+/* 状态 Tabs */
+.status-tabs {
+    display: flex;
+    background-color: #fff;
+    padding: 0 30rpx;
+    justify-content: space-between;
+}
+
+.tab-item {
+    position: relative;
+    padding: 20rpx 0;
+    font-size: 26rpx;
+    color: #666;
+    font-weight: 500;
+}
+
+.tab-item.active {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.indicator {
+    position: absolute;
+    bottom: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 40rpx;
+    height: 6rpx;
+    background-color: #FF5722;
+    border-radius: 3rpx;
+}
+
+/* 搜索栏 */
+.search-bar {
+    padding: 10rpx 30rpx;
+    background-color: #fff;
+}
+
+.search-input-box {
+    display: flex;
+    align-items: center;
+    background-color: #F8F8F8;
+    height: 64rpx;
+    border-radius: 32rpx;
+    padding: 0 30rpx;
+}
+
+.search-input {
+    flex: 1;
+    font-size: 26rpx;
+    color: #333;
+    padding-left: 20rpx;
+    /* Give some left padding since icon is gone */
+}
+
+.ph-style {
+    font-size: 26rpx;
+    color: #999;
+}
+
+/* 筛选栏 (改用 wrapper 进行相对定位) */
+.filter-wrapper {
+    position: relative;
+    z-index: 998;
+}
+
+.filter-bar {
+    display: flex;
+    background-color: #fff;
+    padding: 5rpx 30rpx 10rpx 30rpx;
+    justify-content: space-between;
+    position: relative;
+    z-index: 998;
+}
+
+.filter-item {
+    width: 48%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 26rpx;
+    color: #666;
+    background-color: #F8F8F8;
+    height: 56rpx;
+    border-radius: 12rpx;
+    transition: all 0.2s;
+}
+
+.filter-item.active {
+    background-color: #FFF3E0;
+}
+
+.active-text {
+    color: #FF5722;
+    /* Matches red triangle */
+    font-weight: 500;
+}
+
+.triangle {
+    width: 0;
+    height: 0;
+    border-left: 8rpx solid transparent;
+    border-right: 8rpx solid transparent;
+    margin-left: 10rpx;
+    transition: all 0.2s;
+}
+
+.triangle.down {
+    border-top: 10rpx solid #dcdcdc;
+}
+
+.filter-item.active .triangle.down,
+.active-text+.triangle.down {
+    border-top-color: #FF5722;
+}
+
+.triangle.up {
+    border-bottom: 10rpx solid #FF5722;
+}
+
+/* 下拉面板 */
+.dropdown-mask {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    height: 100vh;
+    background-color: rgba(0, 0, 0, 0.4);
+    z-index: 80;
+}
+
+.dropdown-panel {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    background-color: #fff;
+    z-index: 90;
+    border-radius: 0 0 20rpx 20rpx;
+    box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.05);
+    overflow: hidden;
+}
+
+.type-option {
+    padding: 30rpx 40rpx;
+    font-size: 28rpx;
+    color: #333;
+    border-bottom: 1px solid #f5f5f5;
+}
+
+.type-option:last-child {
+    border-bottom: none;
+}
+
+.type-option.selected text {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.calendar-panel {
+    padding-bottom: 30rpx;
+}
+
+/* Custom Calendar Styles */
+.custom-calendar-container {
+    padding: 20rpx 30rpx 0;
+}
+
+.cal-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx 0;
+}
+
+.cal-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.cal-weekdays {
+    display: flex;
+    justify-content: space-around;
+    padding: 20rpx 0;
+    border-bottom: 1px solid #f5f5f5;
+}
+
+.wk-item {
+    font-size: 24rpx;
+    color: #999;
+    width: 14.28%;
+    text-align: center;
+}
+
+.cal-body {
+    display: flex;
+    flex-wrap: wrap;
+    padding-top: 20rpx;
+}
+
+.cal-day-box {
+    width: 14.28%;
+    height: 80rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 10rpx;
+    position: relative;
+}
+
+.cal-day-text {
+    width: 64rpx;
+    height: 64rpx;
+    line-height: 64rpx;
+    text-align: center;
+    font-size: 28rpx;
+    color: #333;
+    border-radius: 8rpx;
+    position: relative;
+    z-index: 2;
+}
+
+/* Range styles matching Figure 2 */
+.cal-day-box.is-start .cal-day-text,
+.cal-day-box.is-end .cal-day-text {
+    background-color: #FF5722;
+    color: #fff;
+    font-weight: bold;
+}
+
+.cal-day-box.is-start::after {
+    content: '';
+    position: absolute;
+    right: 0;
+    top: 8rpx;
+    bottom: 8rpx;
+    width: 50%;
+    background-color: #FFF3E0;
+    z-index: 1;
+}
+
+.cal-day-box.is-end::after {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 8rpx;
+    bottom: 8rpx;
+    width: 50%;
+    background-color: #FFF3E0;
+    z-index: 1;
+}
+
+.cal-day-box.is-start.is-end::after {
+    display: none;
+    /* No range background if same day */
+}
+
+.cal-day-box.is-between {
+    background-color: #FFF3E0;
+    /* reduce height slightly to match design */
+    margin-top: 8rpx;
+    height: 64rpx;
+    margin-bottom: 18rpx;
+}
+
+.cal-day-box.is-between .cal-day-text {
+    color: #FF5722;
+}
+
+.calendar-actions {
+    display: flex;
+    justify-content: space-between;
+    padding: 0 30rpx;
+    margin-top: 20rpx;
+}
+
+.cal-btn {
+    width: 48%;
+    height: 70rpx;
+    line-height: 70rpx;
+    text-align: center;
+    border-radius: 10rpx;
+    font-size: 28rpx;
+    margin: 0;
+}
+
+.cal-btn.reset {
+    background-color: #f5f5f5;
+    color: #666;
+}
+
+.cal-btn.confirm {
+    background-color: #FF5722;
+    color: #fff;
+}
+
+/* 订单列表 */
+.order-list {
+    padding: 0 30rpx;
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.order-card {
+    background-color: #fff;
+    border-radius: 24rpx;
+    padding: 20rpx 20rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
+}
+
+.order-card:first-child {
+    margin-top: 20rpx;
+}
+
+.card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 15rpx;
+}
+
+.type-badge {
+    display: flex;
+    align-items: center;
+}
+
+.type-icon {
+    width: 44rpx;
+    height: 44rpx;
+    margin-right: 15rpx;
+    background-color: #FFF3E0;
+    border-radius: 50%;
+    padding: 6rpx;
+    box-sizing: border-box;
+}
+
+.type-text {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.status-badge {
+    font-size: 28rpx;
+}
+
+.status-badge.highlight {
+    color: #FF5722;
+}
+
+.status-badge.processing {
+    color: #2196F3;
+}
+
+.status-badge.finish {
+    color: #4CAF50;
+}
+
+.status-badge.reject {
+    color: #9E9E9E;
+}
+
+.time-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 25rpx;
+}
+
+.time-row .time-col {
+    display: flex;
+    align-items: center;
+    font-size: 26rpx;
+    color: #333;
+}
+
+.time-row .label {
+    color: #666;
+    margin-right: 10rpx;
+}
+
+.price {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #FF5722;
+}
+
+/* 宠物卡片 */
+.pet-card {
+    background-color: #FFF8F0;
+    border-radius: 16rpx;
+    padding: 15rpx 20rpx;
+    display: flex;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.pet-avatar {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+}
+
+.pet-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pet-name {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 5rpx;
+}
+
+.pet-breed {
+    font-size: 24rpx;
+    color: #999;
+}
+
+.pet-profile-btn {
+    font-size: 24rpx;
+    color: #FF9800;
+    border: 1px solid #FF9800;
+    padding: 6rpx 20rpx;
+    border-radius: 50rpx;
+    background-color: #fff;
+}
+
+/* 路线信息 (复用) */
+.route-info {
+    margin-bottom: 25rpx;
+}
+
+.route-item {
+    display: flex;
+    align-items: flex-start;
+    padding-bottom: 12rpx;
+    /* Radically reduced for compactness */
+    position: relative;
+    width: 100%;
+}
+
+/* 路线项底部的间隔 */
+.route-item:not(:last-child) {
+    margin-bottom: 5rpx;
+    /* Radically reduced for compactness */
+}
+
+.route-item:last-child {
+    padding-bottom: 0;
+    margin-bottom: 0;
+}
+
+.route-line-vertical {
+    position: absolute;
+    left: 19rpx;
+    top: 46rpx;
+    bottom: -15rpx;
+    /* Adjusted to connect the now-closer nodes */
+    border-left: 2rpx dashed #E0E0E0;
+    width: 0;
+    z-index: 0;
+}
+
+.icon-circle {
+    width: 40rpx;
+    height: 40rpx;
+    border-radius: 50%;
+    color: #fff;
+    font-size: 22rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+    font-weight: bold;
+    margin-top: 6rpx;
+    position: relative;
+    z-index: 1;
+}
+
+.icon-circle.service {
+    background-color: #81C784;
+}
+
+.icon-circle.start {
+    background-color: #FFB74D;
+}
+
+.icon-circle.end {
+    background-color: #81C784;
+}
+
+.address-box {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    margin-right: 20rpx;
+}
+
+.addr-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 4rpx;
+}
+
+.addr-desc {
+    font-size: 24rpx;
+    color: #999;
+    line-height: 1.4;
+}
+
+.distance-tag {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    flex-shrink: 0;
+    min-width: 80rpx;
+}
+
+.distance-text {
+    font-size: 24rpx;
+    color: #FF5722;
+    margin-right: 15rpx;
+    font-weight: 500;
+}
+
+.nav-icon-circle {
+    width: 48rpx;
+    height: 48rpx;
+    background-color: #FFF3E0;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.nav-arrow {
+    width: 24rpx;
+    height: 24rpx;
+}
+
+.service-content {
+    margin-top: -10rpx;
+    /* Shifted up using negative margin for max compactness */
+    font-size: 24rpx;
+    color: #666;
+    padding-left: 60rpx;
+}
+
+.content-label {
+    color: #999;
+    margin-right: 10rpx;
+}
+
+/* 备注 */
+.remark-box {
+    background-color: #F8F8F8;
+    padding: 15rpx 20rpx;
+    border-radius: 8rpx;
+    font-size: 26rpx;
+    color: #666;
+    margin-bottom: 30rpx;
+}
+
+/* 底部按钮 */
+.action-btns {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 15rpx;
+}
+
+.action-left {
+    display: flex;
+}
+
+.action-right {
+    display: flex;
+}
+
+.btn {
+    height: 60rpx;
+    line-height: 60rpx;
+    border-radius: 30rpx;
+    font-size: 26rpx;
+    padding: 0 30rpx;
+    margin: 0;
+}
+
+.action-right .btn:not(:last-child) {
+    margin-right: 20rpx;
+}
+
+.btn::after {
+    border: none;
+}
+
+.btn.normal {
+    background-color: #F8F8F8;
+    color: #666;
+    border: none;
+}
+
+.btn.primary {
+    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
+    color: #fff;
+    box-shadow: 0 4rpx 12rpx rgba(255, 87, 34, 0.2);
+    border: none;
+}
+
+/* 宠物档案弹窗 */
+.pet-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.4);
+    z-index: 1000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.pet-modal-content {
+    width: 680rpx;
+    height: 85vh;
+    background-color: #fff;
+    border-radius: 20rpx;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+}
+
+.pet-modal-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 30rpx;
+    border-bottom: 1rpx solid #F0F0F0;
+}
+
+.pet-modal-title {
+    font-size: 34rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pet-modal-scroll {
+    flex: 1;
+    height: 0;
+    padding: 30rpx;
+    box-sizing: border-box;
+}
+
+.pet-base-info {
+    display: flex;
+    align-items: center;
+    margin-bottom: 40rpx;
+}
+
+.pm-avatar {
+    width: 120rpx;
+    height: 120rpx;
+    border-radius: 50%;
+    margin-right: 30rpx;
+    border: 2rpx solid #f5f5f5;
+}
+
+.pm-info-text {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-name-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15rpx;
+}
+
+.pm-name {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 20rpx;
+}
+
+.pm-gender {
+    display: flex;
+    align-items: center;
+    background-color: #E3F2FD;
+    padding: 4rpx 12rpx;
+    border-radius: 20rpx;
+}
+
+.pm-gender text {
+    font-size: 22rpx;
+    color: #1E88E5;
+}
+
+.pm-gender .gender-icon {
+    font-weight: bold;
+    margin-right: 4rpx;
+}
+
+.pm-gender.female {
+    background-color: #FCE4EC;
+}
+
+.pm-gender.female text {
+    color: #D81B60;
+}
+
+.pm-breed {
+    font-size: 26rpx;
+    color: #999;
+}
+
+.pm-detail-grid {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+}
+
+.pm-grid-item {
+    background-color: #F8F8F8;
+    border-radius: 16rpx;
+    padding: 24rpx;
+    margin-bottom: 20rpx;
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-grid-item.half {
+    width: 48%;
+    box-sizing: border-box;
+}
+
+.pm-grid-item.full {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.pm-label {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 10rpx;
+}
+
+.pm-val {
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+
+.pm-tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+    margin-bottom: 40rpx;
+}
+
+.pm-tag {
+    background-color: #FFF8EB;
+    border: 2rpx solid #FFCC80;
+    color: #FF9800;
+    font-size: 22rpx;
+    padding: 8rpx 24rpx;
+    border-radius: 30rpx;
+}
+
+.pm-section-title {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+    padding-top: 30rpx;
+    border-top: 2rpx dashed #F0F0F0;
+}
+
+.pm-section-title .orange-bar {
+    width: 8rpx;
+    height: 32rpx;
+    background-color: #FF9800;
+    margin-right: 16rpx;
+    border-radius: 4rpx;
+}
+
+.pm-section-title text {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.pm-log-list {
+    display: flex;
+    flex-direction: column;
+}
+
+.pm-log-item {
+    display: flex;
+    flex-direction: column;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #F0F0F0;
+}
+
+.pm-log-item:last-child {
+    border-bottom: none;
+}
+
+.pm-log-date {
+    font-size: 24rpx;
+    color: #999;
+    margin-bottom: 16rpx;
+}
+
+.pm-log-text {
+    font-size: 28rpx;
+    color: #333;
+    line-height: 1.6;
+    margin-bottom: 20rpx;
+}
+
+.pm-log-recorder {
+    font-size: 24rpx;
+    color: #FF9800;
+    align-self: flex-end;
+}
+
+.pm-bottom-close {
+    width: 100%;
+    height: 80rpx;
+    line-height: 80rpx;
+    background-color: #F5F5F5;
+    color: #666;
+    border-radius: 40rpx;
+    font-size: 30rpx;
+    font-weight: bold;
+    margin: 0;
+}
+
+.pm-bottom-close::after {
+    border: none;
+}
+
+.close-icon-btn {
+    font-size: 48rpx;
+    color: #999;
+    line-height: 1;
+    padding: 0 10rpx;
+}
+
+/* 地图导航 Action Sheet */
+.nav-modal-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 1000;
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-end;
+}
+
+.nav-action-sheet {
+    background-color: #fff;
+    width: 100%;
+    border-top-left-radius: 24rpx;
+    border-top-right-radius: 24rpx;
+    overflow: hidden;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+
+.nav-sheet-title {
+    text-align: center;
+    padding: 30rpx 0;
+    font-size: 13px;
+    color: #999;
+    border-bottom: 1rpx solid #efefef;
+}
+
+.nav-sheet-item {
+    text-align: center;
+    padding: 30rpx 0;
+    font-size: 13px;
+    color: #333;
+    background-color: #fff;
+    border-bottom: 1rpx solid #efefef;
+}
+
+.nav-sheet-item.cancel {
+    border-bottom: none;
+    color: #666;
+}
+
+.nav-sheet-gap {
+    height: 16rpx;
+    background-color: #F8F8F8;
+}
+
+/* 订单列表:填满剩余高度,实现只有列表内容滚动 */
+.order-list {
+    flex: 1;
+    overflow-y: auto;
+    width: 100%;
+    padding: 0 30rpx;
+    box-sizing: border-box;
+}
+
+.loading-text {
+    text-align: center;
+    font-size: 24rpx;
+    color: #999;
+    padding: 30rpx 0;
+}
+
+/* 宠物档案弹窗头部操作区(备注按钮 + 关闭) */
+.pm-header-actions {
+    display: flex;
+    align-items: center;
+    gap: 16rpx;
+}
+
+.pm-remark-btn {
+    font-size: 24rpx;
+    color: #fff;
+    background-color: #FF9800;
+    padding: 6rpx 18rpx;
+    border-radius: 20rpx;
+}
+
+/* 备注输入遮罩与弹窗(图2居中样式) */
+.remark-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 3000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.remark-sheet {
+    width: 600rpx;
+    background-color: #fff;
+    border-radius: 24rpx;
+    padding: 40rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.remark-sheet-header {
+    width: 100%;
+    text-align: center;
+    margin-bottom: 30rpx;
+    position: relative;
+}
+
+.remark-sheet-header .close-icon-btn {
+    position: absolute;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+.remark-sheet-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+.remark-textarea {
+    width: 100%;
+    height: 160rpx;
+    border: 1rpx solid #eee;
+    border-radius: 12rpx;
+    padding: 20rpx;
+    font-size: 28rpx;
+    color: #333;
+    box-sizing: border-box;
+    margin-bottom: 40rpx;
+}
+
+.remark-submit-btn {
+    width: 100%;
+    background-color: #FF5722;
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: bold;
+    text-align: center;
+    padding: 24rpx 0;
+    border-radius: 16rpx;
+}
+
+/* 一键拨号下拉面板 */
+.action-left {
+    position: relative;
+    z-index: 10;
+}
+
+.action-left .btn.normal {
+    font-size: 26rpx;
+}
+
+.call-popover {
+    position: absolute;
+    top: calc(100% + 10rpx);
+    left: 0;
+    background-color: #fff;
+    border-radius: 12rpx;
+    box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+    z-index: 999;
+    display: flex;
+    flex-direction: column;
+    width: 200rpx;
+}
+
+.call-pop-item {
+    font-size: 26rpx;
+    color: #333;
+    text-align: center;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #eee;
+}
+
+.call-pop-item:last-child {
+    border-bottom: none;
+}
+
+.call-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 900;
+    background: transparent;
+}

+ 152 - 0
pages/recruit/auth.css

@@ -0,0 +1,152 @@
+/* 页面背景 */
+page {
+    background-color: #F8F8F8;
+    font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
+}
+
+.auth-container {
+    padding: 20rpx;
+    padding-bottom: 200rpx;
+}
+
+/* 顶部提示 */
+.top-tip {
+    font-size: 24rpx;
+    color: #666;
+    margin-bottom: 20rpx;
+    padding: 0 10rpx;
+}
+
+/* 表单卡片 */
+.form-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 0 30rpx;
+    margin-bottom: 20rpx;
+}
+
+.form-item {
+    display: flex;
+    align-items: center;
+    height: 100rpx;
+    border-bottom: none;
+}
+
+.label {
+    width: 160rpx;
+    font-size: 26rpx;
+    /* 13号字体 */
+    font-weight: bold;
+    color: #333;
+}
+
+.input-area {
+    flex: 1;
+    font-size: 26rpx;
+    /* 13号字体 */
+    color: #333;
+}
+
+.input-placeholder {
+    color: #ccc;
+    font-size: 26rpx;
+    /* 13号字体 */
+}
+
+.read-only-text {
+    color: #333;
+    font-size: 26rpx;
+    /* 13号字体 */
+}
+
+/* ... existing code ... */
+
+.card-label {
+    font-size: 26rpx;
+    /* 13号字体 */
+    color: #333;
+    font-weight: bold;
+}
+
+/* ... existing code ... */
+
+.next-btn {
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 28rpx;
+    /* 14号字体 */
+    font-weight: bold;
+    height: 90rpx;
+    line-height: 90rpx;
+    border-radius: 45rpx;
+    box-shadow: 0 10rpx 20rpx rgba(255, 87, 34, 0.2);
+}
+
+/* 灰色背景输入框 (复刻图1样式,实际上图1是白色背景+灰色块? 不,图1看起来是整行白色,输入框区域是浅灰块) */
+/* 修正: 图1中输入框是浅灰色的矩形块 */
+.gray-input-box {
+    flex: 1;
+    height: 70rpx;
+    background-color: #F8F8F8;
+    border-radius: 8rpx;
+    display: flex;
+    align-items: center;
+    padding: 0 20rpx;
+}
+
+.arrow-right {
+    width: 24rpx;
+    height: 24rpx;
+    margin-left: auto;
+}
+
+/* 上传卡片 */
+.upload-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 40rpx 0;
+    margin-bottom: 20rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+}
+
+.upload-box {
+    width: 600rpx;
+    height: 360rpx;
+    /* 身份证比例 roughly 1.6 */
+    background-color: #F8F8F8;
+    border: 2rpx dashed #eee;
+    border-radius: 12rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 20rpx;
+    position: relative;
+    overflow: hidden;
+}
+
+.camera-icon {
+    width: 64rpx;
+    height: 64rpx;
+    margin-bottom: 15rpx;
+    /* 使用SVG或图片 */
+}
+
+.upload-text {
+    font-size: 26rpx;
+    color: #ccc;
+}
+
+.preview-img {
+    width: 100%;
+    height: 100%;
+}
+
+/* 底部按钮 */
+.footer-btn-area {
+    margin-top: 60rpx;
+    padding: 0 20rpx;
+}

+ 94 - 0
pages/recruit/auth.vue

@@ -0,0 +1,94 @@
+<template>
+  <view class="auth-container">
+    <!-- 顶部提示 -->
+    <view class="top-tip">请确保身份信息的准确,以免影响后续履约费用结算。</view>
+
+    <!-- 表单信息 -->
+    <view class="form-card">
+      <!-- 证件类型 -->
+      <view class="form-item">
+        <text class="label">证件类型</text>
+        <view class="read-only-text">居民身份证</view>
+      </view>
+
+      <!-- 真实姓名 -->
+      <view class="form-item">
+        <text class="label">真实姓名</text>
+        <view class="gray-input-box">
+          <input class="input-area" type="text" v-model="formData.name" placeholder="证件姓名" placeholder-class="input-placeholder" />
+        </view>
+      </view>
+
+      <!-- 证件号码 -->
+      <view class="form-item">
+        <text class="label">证件号码</text>
+        <view class="gray-input-box">
+          <input class="input-area" type="idcard" v-model="formData.idNumber" placeholder="身份证号" placeholder-class="input-placeholder" />
+        </view>
+      </view>
+
+      <!-- 有效日期 -->
+      <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>
+          <!-- 箭头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>
+           </svg>
+        </view>
+      </view>
+    </view>
+
+    <!-- 身份证正面 -->
+    <view class="upload-card">
+      <view class="upload-box" @click="chooseImage('front')">
+        <image v-if="idCardFront" :src="idCardFront" class="preview-img" mode="aspectFill"></image>
+        <template v-else>
+           <!-- 相机图标SVG -->
+           <svg class="camera-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M12 12C14.7614 12 17 9.76142 17 7C17 4.23858 14.7614 2 12 2C9.23858 2 7 4.23858 7 7C7 9.76142 9.23858 12 12 12Z" fill="#E0E0E0"/>
+              <circle cx="12" cy="12" r="3" stroke="#CCCCCC" stroke-width="2"/>
+              <path d="M20 6H17.82L16.4 4.47C15.96 4 15.34 3.73 14.68 3.73H9.32C8.66 3.73 8.04 4 7.6 4.47L6.18 6H4C2.9 6 2 6.9 2 8V18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V8C22 6.9 21.1 6 20 6ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17Z" fill="#CCCCCC"/>
+           </svg>
+           <text class="upload-text">点击上传</text>
+        </template>
+      </view>
+      <text class="card-label">证件带照片面</text>
+    </view>
+
+    <!-- 身份证反面 -->
+    <view class="upload-card">
+      <view class="upload-box" @click="chooseImage('back')">
+         <image v-if="idCardBack" :src="idCardBack" class="preview-img" mode="aspectFill"></image>
+         <template v-else>
+            <!-- 相机图标SVG -->
+           <svg class="camera-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M20 6H17.82L16.4 4.47C15.96 4 15.34 3.73 14.68 3.73H9.32C8.66 3.73 8.04 4 7.6 4.47L6.18 6H4C2.9 6 2 6.9 2 8V18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V8C22 6.9 21.1 6 20 6ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17Z" fill="#CCCCCC"/>
+           </svg>
+           <text class="upload-text">点击上传</text>
+         </template>
+      </view>
+      <text class="card-label">证件国徽面</text>
+    </view>
+
+    <!-- 底部按钮 -->
+    <view class="footer-btn-area">
+      <button class="next-btn" @click="goToQualifications">下一步,完善资质</button>
+    </view>
+
+  </view>
+</template>
+
+<script>
+import logic from './auth_logic.js'; // 注意文件名可能需要对应
+export default logic;
+</script>
+
+<style>
+@import './auth.css';
+</style>

+ 93 - 0
pages/recruit/auth_logic.js

@@ -0,0 +1,93 @@
+export default {
+    data() {
+        return {
+            formData: {
+                idType: '居民身份证',
+                name: '',
+                idNumber: '',
+                expiryDate: ''
+            },
+            idCardFront: '', // 身份证正面路径
+            idCardBack: '',  // 身份证反面路径
+            showDatePicker: false,
+            pickerValue: [0, 0, 0], // YYYY-MM-DD
+            years: [],
+            months: [],
+            days: [],
+            serviceType: [] // 接收上一页的服务类型
+        }
+    },
+    onLoad(options) {
+        if (options.services) {
+            try {
+                this.serviceType = JSON.parse(options.services);
+            } catch (e) {
+                console.error('Parse services failed', e);
+            }
+        }
+        this.initDateData();
+    },
+    methods: {
+        // --- 日期选择器逻辑 (简化版, 仅示意) ---
+        initDateData() {
+            const date = new Date();
+            const year = date.getFullYear();
+            for (let i = year; i <= year + 20; i++) {
+                this.years.push(i);
+            }
+            for (let i = 1; i <= 12; i++) {
+                this.months.push(i);
+            }
+            for (let i = 1; i <= 31; i++) {
+                this.days.push(i);
+            }
+        },
+        openDatePicker() {
+            // this.showDatePicker = true; 
+            // 简单起见,这里可以用 uni.chooseImage 逻辑,但日期通常用 picker
+            // 为了完全还原UI的自定义picker,这里先用原生 picker 简化,或者复用 form 的逻辑
+            // 鉴于图1是普通的列表选择样式,这里暂时使用普通 picker 或者 input禁用+点击事件
+        },
+        onDateChange(e) {
+            this.formData.expiryDate = e.detail.value;
+        },
+
+        // --- 图片上传 ---
+        chooseImage(side) {
+            uni.chooseImage({
+                count: 1,
+                sizeType: ['compressed'],
+                sourceType: ['album', 'camera'],
+                success: (res) => {
+                    if (side === 'front') {
+                        this.idCardFront = res.tempFilePaths[0];
+                    } else {
+                        this.idCardBack = res.tempFilePaths[0];
+                    }
+                }
+            });
+        },
+
+        // --- 提交 ---
+        goToQualifications() {
+            // 简单校验
+            // 简单校验
+            /*
+            if (!this.formData.name || !this.formData.idNumber) {
+                uni.showToast({ title: '请完善信息', icon: 'none' });
+                return;
+            }
+            if (!this.idCardFront || !this.idCardBack) {
+                uni.showToast({ title: '请上传证件照', icon: 'none' });
+                return;
+            }
+            */
+
+            // 传递数据
+            const services = JSON.stringify(this.serviceType);
+            uni.navigateTo({
+                url: `/pages/recruit/qualifications?services=${services}`
+            });
+        }
+    }
+}

+ 271 - 0
pages/recruit/form.vue

@@ -0,0 +1,271 @@
+<template>
+  <view class="container">
+    <!-- 个人信息卡片 -->
+    <view class="card">
+      <!-- 手机号 -->
+      <view class="form-item">
+        <text class="label">手机号</text>
+        <view class="input-box">
+           <view class="prefix-area">
+             <text class="prefix">+86</text>
+             <text class="arrow-down">﹀</text>
+           </view>
+           <input class="input" type="number" v-model="formData.mobile" />
+        </view>
+      </view>
+
+      <!-- 验证码 -->
+      <view class="form-item">
+        <text class="label">验证码</text>
+        <view class="input-box">
+          <input class="input" type="number" v-model="formData.code" placeholder="验证码" />
+          <text class="get-code-text">获取验证码</text>
+        </view>
+      </view>
+
+      <!-- 姓名 -->
+      <view class="form-item">
+        <text class="label">姓名</text>
+        <view class="input-box">
+          <input class="input" type="text" v-model="formData.name" />
+        </view>
+      </view>
+
+      <!-- 性别 -->
+      <view class="form-item">
+        <text class="label">性别</text>
+        <view class="gender-group">
+          <view class="radio-item" @click="formData.gender = 1">
+            <text class="radio-icon" :class="{active: formData.gender === 1}">{{ formData.gender === 1 ? '♂' : '○' }}</text>
+            <text class="radio-label" :class="{active: formData.gender === 1}"> 男</text>
+          </view>
+          <view class="radio-item" @click="formData.gender = 2">
+            <text class="radio-icon" :class="{active: formData.gender === 2}">{{ formData.gender === 2 ? '♀' : '○' }}</text>
+            <text class="radio-label" :class="{active: formData.gender === 2}"> 女</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 生日 -->
+      <view class="form-item">
+        <text class="label">生日</text>
+        <view class="input-box" @click="openPicker">
+            <text>{{ formData.birthday || '请选择生日' }}</text>
+            <!-- 灰色箭头 SVG -->
+            <svg class="arrow-right" style="width:24rpx; height:24rpx; margin-left: auto;" 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>
+            </svg>
+        </view>
+      </view>
+
+      <!-- 密码 -->
+      <view class="form-item">
+        <text class="label">密码</text>
+        <view class="input-box">
+          <input class="input" :password="!showPwd" v-model="formData.password" placeholder="设置登录密码" />
+          <view class="monkey-icon" @click="showPwd = !showPwd">
+             <template v-if="showPwd">
+              <!-- 睁眼线框图标 -->
+              <svg class="svg-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M12 4.5C7 4.5 2.73 7.61 1 12C2.73 16.39 7 19.5 12 19.5C17 19.5 21.27 16.39 23 12C21.27 7.61 17 4.5 12 4.5ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z" fill="#CCCCCC"/>
+              </svg>
+            </template>
+            <template v-else>
+              <!-- 闭眼线框图标 (带睫毛) -->
+              <svg class="svg-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M12 7C7 7 2.73 10.11 1 14.5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M23 14.5C21.27 10.11 17 7 12 7" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M12 7V4" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M16 8L18 5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M8 8L6 5" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M20 10L22 8" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+                <path d="M4 10L2 8" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round"/>
+              </svg>
+            </template>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 服务类型卡片 -->
+    <view class="card">
+      <view class="section-title">服务类型</view>
+      <view class="service-types">
+        <view 
+          class="type-btn" 
+          v-for="(item, index) in serviceTypes" 
+          :key="index"
+          :class="{selected: formData.serviceType.includes(item)}"
+          @click="toggleService(item)"
+        >
+          {{ item }}
+        </view>
+      </view>
+
+      <!-- 工作城市 -->
+      <view class="form-item">
+        <text class="label">工作城市</text>
+        <view class="input-box" @click="openCityPicker">
+            <text>{{ formData.city || '广东省 深圳市 龙华区' }}</text>
+            <!-- 灰色箭头 SVG -->
+            <svg class="arrow-right" style="width:24rpx; height:24rpx; margin-left: auto;" 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>
+            </svg>
+        </view>
+      </view>
+
+      <!-- 服务站点 -->
+      <view class="form-item">
+        <text class="label">服务站点</text>
+        <view class="input-box" @click="openStationPicker">
+            <text :style="{color: formData.station ? '#333' : '#ccc'}">{{ formData.station || '请选择服务站点' }}</text>
+            <!-- 灰色箭头 SVG -->
+            <svg class="arrow-right" style="width:24rpx; height:24rpx; margin-left: auto;" 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>
+            </svg>
+        </view>
+      </view>
+    </view>
+
+    <!-- ... (Bottom content) ... -->
+    
+    <!-- 自定义日期选择器 (已存在) --> 
+    <!-- ... (Picker content) ... -->
+
+    <!-- 自定义城市选择器 (级联版) -->
+    <view class="picker-mask" :class="{show: showCityPicker}" @click="closeCityPicker">
+        <view class="picker-content" @click.stop>
+            <view class="picker-header">
+                <text class="picker-btn-cancel" @click="closeCityPicker">取消</text>
+                <text class="picker-title">请选择工作城市</text>
+                <text class="picker-btn-confirm" @click="confirmCity">确定</text>
+            </view>
+            <view class="picker-body">
+                <!-- 左侧:垂直路径 -->
+                <view class="timeline-area">
+                    <!-- 已选节点 -->
+                    <view 
+                        class="timeline-item" 
+                        v-for="(item, index) in selectedPathway" 
+                        :key="index"
+                        @click="jumpToStep(index)"
+                    >
+                        <view class="timeline-dot"></view>
+                        <text>{{ item.name }}</text>
+                    </view>
+                    <!-- 当前正在选的提示 (如果还没选完) -->
+                    <view 
+                        class="timeline-item active" 
+                        v-if="selectStep === selectedPathway.length"
+                    >
+                        <view class="timeline-dot"></view>
+                        <text>请选择</text>
+                    </view>
+                </view>
+
+                <!-- 右侧:待选项列表 -->
+                <scroll-view scroll-y class="list-area">
+                    <view 
+                        class="list-item" 
+                        v-for="(item, index) in currentList" 
+                        :key="item.id"
+                        @click="selectCityItem(item)"
+                    >
+                        {{ item.name }}
+                    </view>
+                    <view v-if="currentList.length === 0" style="padding:20rpx;color:#999">
+                        无数据
+                    </view>
+                </scroll-view>
+            </view>
+        </view>
+    </view>
+
+    <!-- 自定义站点选择器 -->
+    <view class="picker-mask" :class="{show: showStationPicker}" @click="closeStationPicker">
+        <view class="picker-content" @click.stop>
+            <view class="picker-header" style="justify-content: center; position: relative;">
+                <text class="picker-btn-cancel" style="position: absolute; left: 30rpx;" @click="closeStationPicker">取消</text>
+                <text class="picker-title">选择服务站点</text>
+            </view>
+            <scroll-view scroll-y class="picker-list">
+                <view 
+                    class="station-item" 
+                    v-for="(item, index) in stationList" 
+                    :key="index"
+                    @click="selectStation(item)"
+                >
+                    {{ item }}
+                </view>
+            </scroll-view>
+        </view>
+    </view>
+
+    <!-- 底部协议与按钮 -->
+    <view class="footer-actions">
+        <view class="agreement-row">
+          <view class="checkbox" :class="{checked: isAgreed}" @click="isAgreed = !isAgreed">
+             <text v-if="isAgreed" class="check-mark">✓</text>
+          </view>
+          <text class="agree-text">我已阅读并同意 <text style="color:#2979ff" @click.stop="openPrivacy">《宠宝履约者说明》</text></text>
+        </view>
+
+        <view class="footer-btn-area">
+          <button class="submit-btn" @click="goToAuth">下一步,实名认证</button>
+        </view>
+    </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>
+
+    <!-- 协议弹窗 -->
+    <privacy-popup 
+        :visible="showPrivacy" 
+        :title="privacyTitle" 
+        :content="privacyContent"
+        @close="showPrivacy = false"
+    >
+    </privacy-popup>
+
+  </view>
+</template>
+
+<script>
+import logic from './logic.js';
+import PrivacyPopup from '@/components/privacy-popup/privacy-popup.vue';
+
+export default {
+    ...logic,
+    components: {
+        PrivacyPopup
+    }
+}
+</script>
+
+<style>
+@import './style.css';
+</style>

+ 180 - 0
pages/recruit/landing.css

@@ -0,0 +1,180 @@
+/* 页面整体背景 - 橙色 */
+page {
+    background-color: #FF9800;
+}
+
+.container {
+    min-height: 100vh;
+    display: flex;
+    flex-direction: column;
+    position: relative;
+}
+
+/* 自定义导航栏 */
+.nav-bar {
+    height: 88rpx;
+    /* 标准导航栏高度 */
+    display: flex;
+    align-items: center;
+    padding: 0 30rpx;
+    /* 适配状态栏高度在 vue 中通过 padding-top 实现,这里仅控制栏本身 */
+}
+
+.back-icon {
+    font-size: 60rpx;
+    color: #fff;
+    font-weight: bold;
+    /* 增大点击区域 */
+    width: 60rpx;
+    height: 60rpx;
+    line-height: 56rpx;
+    text-align: center;
+    display: block;
+}
+
+/* 头部文案 */
+.header-area {
+    padding: 40rpx 40rpx 20rpx;
+    color: #fff;
+    text-align: center;
+}
+
+.main-title {
+    font-size: 48rpx;
+    font-weight: bold;
+    display: block;
+    margin-bottom: 20rpx;
+}
+
+.sub-title {
+    font-size: 32rpx;
+    opacity: 0.9;
+    display: block;
+}
+
+/* 内容卡片 */
+.content-card {
+    background-color: #fff;
+    border-radius: 30rpx;
+    /* 四周圆角 */
+    margin: 40rpx 30rpx;
+    /* 上下40 左右30 */
+    padding: 60rpx 40rpx;
+    display: flex;
+    flex-direction: column;
+    box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
+}
+
+.benefit-item {
+    display: flex;
+    align-items: center;
+    /* 垂直居中对齐 */
+    margin-bottom: 60rpx;
+}
+
+.icon-circle {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 30rpx;
+    flex-shrink: 0;
+    color: #fff;
+    /* 图标文字白色 */
+    font-weight: bold;
+}
+
+/* 图1 配色复刻 */
+.icon-money {
+    background-color: #26A69A;
+    /* 青色/绿色 */
+}
+
+.icon-loc {
+    background-color: #2979FF;
+    /* 蓝色 */
+}
+
+.icon-clock {
+    background-color: #FF7043;
+    /* 橙色 */
+}
+
+.icon-text {
+    font-size: 40rpx;
+}
+
+.info {
+    flex: 1;
+}
+
+.item-title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 8rpx;
+    /* 减小间距 */
+    display: block;
+}
+
+.item-desc {
+    font-size: 26rpx;
+    color: #666;
+    line-height: 1.6;
+    display: block;
+}
+
+/* 底部区域 */
+.footer-area {
+    margin-top: auto;
+    /* 推到最底部 */
+    padding: 20rpx 40rpx 80rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    /* 移除白色背景,呈现底色橙色 */
+}
+
+.join-btn {
+    width: 100%;
+    height: 90rpx;
+    line-height: 90rpx;
+    background: #fff;
+    /* 白色按钮 */
+    color: #FF5722;
+    /* 橙色文字 */
+    font-size: 34rpx;
+    font-weight: bold;
+    border-radius: 45rpx;
+    box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
+}
+
+.join-btn::after {
+    border: none;
+}
+
+.faq {
+    margin-top: 30rpx;
+    color: #fff;
+    /* 白色文字 */
+    font-size: 26rpx;
+    display: flex;
+    align-items: center;
+}
+
+.help-icon {
+    width: 30rpx;
+    height: 30rpx;
+    border: 1px solid #fff;
+    /* 白色边框 */
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 20rpx;
+    margin-right: 10rpx;
+    color: #fff;
+    /* 白色问号 */
+}

+ 29 - 0
pages/recruit/landing.js

@@ -0,0 +1,29 @@
+export default {
+    data() {
+        return {
+            statusBarHeight: 20, // 默认状态栏高度
+        }
+    },
+    onLoad() {
+        // 获取系统信息适配刘海屏/状态栏
+        const sysInfo = uni.getSystemInfoSync();
+        this.statusBarHeight = sysInfo.statusBarHeight || 20;
+    },
+    methods: {
+        goBack() {
+            const pages = getCurrentPages();
+            if (pages.length > 1) {
+                uni.navigateBack();
+            } else {
+                uni.reLaunch({
+                    url: '/pages/login/login'
+                });
+            }
+        },
+        goToForm() {
+            uni.navigateTo({
+                url: '/pages/recruit/form'
+            });
+        }
+    }
+}

+ 67 - 0
pages/recruit/landing.vue

@@ -0,0 +1,67 @@
+<template>
+  <view class="container">
+    <!-- 状态栏占位 -->
+    <view :style="{ height: statusBarHeight + 'px' }"></view>
+    
+    <!-- 自定义导航栏 (返回按钮) -->
+    <view class="nav-bar">
+      <view class="back-icon" @click="goBack">‹</view>
+    </view>
+    
+    <!-- 标题区域 -->
+    <view class="header-area">
+      <text class="main-title">加入宠宝履约者</text>
+      <text class="sub-title">月薪最高可达1.5万元</text>
+    </view>
+
+    <!-- 白色内容卡片 -->
+    <view class="content-card">
+      <view class="benefit-item">
+        <view class="icon-circle icon-money">
+          <text class="icon-text">¥</text>
+        </view>
+        <view class="info">
+          <text class="item-title">1、收入可观</text>
+          <text class="item-desc">小默配送为您提供一种全新的赚钱选择,利用空闲时间,获得更多收入。</text>
+        </view>
+      </view>
+
+      <view class="benefit-item">
+        <view class="icon-circle icon-loc">
+          <text class="icon-text">📍</text>
+        </view>
+        <view class="info">
+          <text class="item-title">2、地点灵活</text>
+          <text class="item-desc">小默配送覆盖国内各城市与港澳台等地,您可随时就近使用。</text>
+        </view>
+      </view>
+
+      <view class="benefit-item">
+        <view class="icon-circle icon-clock">
+          <text class="icon-text">🕒</text>
+        </view>
+        <view class="info">
+          <text class="item-title">3、时间自由</text>
+          <text class="item-desc">不必再受繁琐事务约束,加入小默配送,自由分配个人时间,为自己工作。</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 底部按钮 -->
+    <view class="footer-area">
+      <button class="join-btn" @click="goToForm">我要加入</button>
+      <view class="faq">
+        <text class="help-icon">?</text> 常见问题
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import logic from './landing.js';
+export default logic;
+</script>
+
+<style>
+@import './landing.css';
+</style>

+ 232 - 0
pages/recruit/logic.js

@@ -0,0 +1,232 @@
+export default {
+    data() {
+        return {
+            formData: {
+                mobile: '13612345678',
+                code: '',
+                name: '张三哥',
+                gender: 1, // 1男 2女
+                birthday: '2026-02-13',
+                password: '',
+                serviceType: ['宠物接送'],
+                city: '',
+                station: ''
+            },
+            showPwd: false,
+            isAgreed: false,
+            serviceTypes: ['宠物接送', '上门喂遛', '上门洗护'],
+
+            // 日期选择器相关
+            showPicker: false,
+            years: [],
+            months: [],
+            days: [],
+            pickerValue: [0, 0, 0], // 选中项索引
+            tempYear: 0,
+            tempMonth: 0,
+            tempDay: 0,
+
+            // 城市选择器相关
+            showCityPicker: false,
+            // 模拟级联数据
+            cityData: [
+                {
+                    id: 11, name: '北京市', children: [
+                        {
+                            id: 1101, name: '北京市', children: [
+                                { id: 110101, name: '东城区' },
+                                { id: 110105, name: '朝阳区' },
+                                { id: 110108, name: '海淀区' }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    id: 44, name: '广东省', children: [
+                        {
+                            id: 4401, name: '广州市', children: [
+                                { id: 440106, name: '天河区' },
+                                { id: 440104, name: '越秀区' }
+                            ]
+                        },
+                        {
+                            id: 4403, name: '深圳市', children: [
+                                { id: 440304, name: '福田区' },
+                                { id: 440305, name: '南山区' },
+                                { id: 440306, name: '宝安区' },
+                                { id: 440309, name: '龙华区' }
+                            ]
+                        }
+                    ]
+                }
+            ],
+            selectStep: 0, // 0:省, 1:市, 2:区
+            selectedPathway: [], // 已选节点 [{id, name}, ...]
+            currentList: [], // 当前可选列表
+
+
+            // 站点选择器相关
+            showStationPicker: false,
+            stationList: ['民治街道第一站', '民治街道第二站', '龙华中心站', '福田区分站'],
+
+            // 协议弹窗
+            showPrivacy: false,
+            privacyTitle: '',
+            privacyContent: ''
+        }
+    },
+    created() {
+        this.initDateData();
+    },
+    methods: {
+        initDateData() {
+            const now = new Date();
+            const currentYear = now.getFullYear();
+
+            // 初始化年份 (1980 - 2030)
+            for (let i = 1980; i <= currentYear + 5; i++) {
+                this.years.push(i);
+            }
+            // 初始化月份
+            for (let i = 1; i <= 12; i++) {
+                this.months.push(i);
+            }
+            // 初始化日期 (默认31天, 实际应动态计算, 这里简化处理或在change中联动)
+            for (let i = 1; i <= 31; i++) {
+                this.days.push(i);
+            }
+        },
+
+        // 打开选择器
+        openPicker() {
+            // 解析当前选中日期或默认日期
+            const dateStr = this.formData.birthday || '2000-01-01';
+            const [y, m, d] = dateStr.split('-').map(Number);
+
+            // 查找索引
+            const yIndex = this.years.indexOf(y);
+            const mIndex = this.months.indexOf(m);
+            const 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]];
+        },
+
+        confirmPicker() {
+            // 格式化日期
+            const mStr = this.tempMonth < 10 ? '0' + this.tempMonth : this.tempMonth;
+            const dStr = this.tempDay < 10 ? '0' + this.tempDay : this.tempDay;
+            this.formData.birthday = `${this.tempYear}-${mStr}-${dStr}`;
+            this.closePicker();
+        },
+
+        toggleService(item) {
+            const idx = this.formData.serviceType.indexOf(item);
+            if (idx > -1) {
+                this.formData.serviceType.splice(idx, 1);
+            } else {
+                this.formData.serviceType.push(item);
+            }
+        },
+
+        // 城市选择器 logic
+        openCityPicker() {
+            this.showCityPicker = true;
+            // 如果未选择过,初始化第一级
+            if (this.selectedPathway.length === 0) {
+                this.resetCityPicker();
+            }
+        },
+        resetCityPicker() {
+            this.selectStep = 0;
+            this.selectedPathway = [];
+            this.currentList = this.cityData;
+        },
+        closeCityPicker() {
+            this.showCityPicker = false;
+        },
+        // 点击列表项
+        selectCityItem(item) {
+            // 记录当前选择
+            this.selectedPathway[this.selectStep] = item;
+
+            // 尝试获取下一级
+            if (item.children && item.children.length > 0) {
+                this.selectStep++;
+                this.currentList = item.children;
+                // 清理后续旧数据(如果是重新选择的情况)
+                this.selectedPathway = this.selectedPathway.slice(0, this.selectStep);
+            } else {
+                // 没有下一级了,自动确认
+                this.confirmCity();
+            }
+        },
+        // 点击“已选路径”回溯
+        jumpToStep(step) {
+            this.selectStep = step;
+            // 重新计算该级的列表
+            if (step === 0) {
+                this.currentList = this.cityData;
+            } else {
+                // 列表是上一级选择的 item 的 children
+                const parent = this.selectedPathway[step - 1];
+                this.currentList = parent ? parent.children : [];
+            }
+        },
+        confirmCity() {
+            // 拼接完整名称
+            const fullPath = this.selectedPathway.map(i => i.name).join(' ');
+            this.formData.city = fullPath;
+            this.closeCityPicker();
+        },
+
+        // 站点选择器
+        openStationPicker() {
+            this.showStationPicker = true;
+        },
+        closeStationPicker() {
+            this.showStationPicker = false;
+        },
+        selectStation(item) {
+            this.formData.station = item;
+            this.closeStationPicker();
+        },
+
+        openPrivacy() {
+            this.privacyTitle = '宠宝履约者说明';
+            this.privacyContent = '1. 履约职责\n作为宠宝履约者,您需要按照平台标准完成宠物接送、喂遛或洗护服务,确保宠物安全与健康。\n\n2. 结算方式\n服务费用将根据订单类型和距离计算,定期结算至您的账户。具体结算周期请查看钱包说明。\n\n3. 行为规范\n请在这个过程中保持专业,穿着整洁,礼貌待人。严禁虐待宠物,违反者将承担法律责任。';
+            this.showPrivacy = true;
+        },
+
+        goToAuth() {
+            if (!this.isAgreed) {
+                uni.showToast({ title: '请勾选协议', icon: 'none' });
+                return;
+            }
+            const services = JSON.stringify(this.formData.serviceType);
+            uni.navigateTo({
+                url: `/pages/recruit/auth?services=${services}`
+            });
+        }
+    }
+}

+ 149 - 0
pages/recruit/qualifications.css

@@ -0,0 +1,149 @@
+/* 页面背景 */
+page {
+    background-color: #F8F8F8;
+    padding-bottom: 200rpx;
+    /* 底部留白 */
+    font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
+}
+
+.qual-container {
+    padding: 20rpx;
+}
+
+/* 顶部提示 */
+.top-tip {
+    font-size: 24rpx;
+    color: #666;
+    margin-bottom: 20rpx;
+    padding: 0 10rpx;
+    line-height: 1.5;
+}
+
+/* 空状态 */
+.empty-state {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding-top: 100rpx;
+    padding-bottom: 60rpx;
+}
+
+.empty-tip {
+    font-size: 30rpx;
+    color: #999;
+    margin-bottom: 40rpx;
+}
+
+.back-btn {
+    width: 300rpx;
+    height: 80rpx;
+    line-height: 80rpx;
+    border: 2rpx solid #FF5722;
+    color: #FF5722;
+    background-color: #fff;
+    border-radius: 40rpx;
+    font-size: 30rpx;
+}
+
+/* 资质卡片 */
+.qual-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+}
+
+.card-title {
+    font-size: 28rpx;
+    /* 14号字体 */
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 30rpx;
+}
+
+/* 上传容器 */
+.upload-wrapper {
+    display: flex;
+    flex-wrap: wrap;
+}
+
+.img-item {
+    width: 200rpx;
+    height: 200rpx;
+    position: relative;
+    margin-right: 20rpx;
+    margin-bottom: 20rpx;
+}
+
+.upload-box {
+    width: 200rpx;
+    height: 200rpx;
+    background-color: #F8F8F8;
+    /* 虚线框背景 */
+    border: 2rpx dashed #eee;
+    border-radius: 12rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 20rpx;
+}
+
+.plus-icon {
+    font-size: 60rpx;
+    color: #ccc;
+    font-weight: 300;
+    margin-bottom: 10rpx;
+}
+
+.upload-text {
+    font-size: 24rpx;
+    color: #999;
+}
+
+/* 图片预览 */
+.preview-img {
+    width: 100%;
+    height: 100%;
+    border-radius: 12rpx;
+}
+
+/* 删除按钮 */
+.delete-btn {
+    position: absolute;
+    top: -10rpx;
+    right: -10rpx;
+    width: 36rpx;
+    height: 36rpx;
+    background-color: #FF5722;
+    border-radius: 50%;
+    color: #fff;
+    font-size: 24rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    z-index: 10;
+    border: 2rpx solid #fff;
+}
+
+/* 底部操作区 */
+.footer-actions {
+    margin-top: 60rpx;
+    padding: 0 20rpx;
+}
+
+.submit-btn {
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 28rpx;
+    /* 14号字体 */
+    font-weight: bold;
+    height: 90rpx;
+    line-height: 90rpx;
+    border-radius: 45rpx;
+    box-shadow: 0 10rpx 20rpx rgba(255, 87, 34, 0.2);
+}
+
+.submit-btn::after {
+    border: none;
+}

+ 46 - 0
pages/recruit/qualifications.vue

@@ -0,0 +1,46 @@
+<template>
+  <view class="qual-container">
+    <!-- 顶部提示 -->
+    <view class="top-tip">根据国家政策要求,请尽快完成实名认证与健康认证,否则无法开展配送业务。我们承诺将严格保管好您的个人信息。</view>
+
+    <!-- 如果没有选择服务类型 -->
+    <view class="empty-state" v-if="serviceTypes.length === 0">
+        <text class="empty-tip">请返回第一步选择服务类型</text>
+        <button class="back-btn" @click="goBackToForm">返回选择</button>
+    </view>
+
+    <!-- 动态渲染资质卡片 -->
+    <view class="qual-card" v-for="(type, index) in serviceTypes" :key="index">
+      <view class="card-title">{{ type }}服务资质</view>
+      
+      <view class="upload-wrapper">
+         <!-- 已有图片列表 -->
+         <view class="img-item" v-for="(img, imgIndex) in qualifications[type]" :key="imgIndex">
+             <image :src="img" class="preview-img" mode="aspectFill" @click="previewImage(type, imgIndex)"></image>
+             <view class="delete-btn" @click.stop="deleteImage(type, imgIndex)">×</view>
+         </view>
+         
+         <!-- 上传/添加按钮 -->
+         <view class="upload-box" @click="chooseImage(type)">
+             <text class="plus-icon">+</text>
+             <text class="upload-text">上传</text>
+         </view>
+      </view>
+    </view>
+    
+    <!-- 底部按钮 -->
+    <view class="footer-actions">
+      <button class="submit-btn" @click="submit">立即提交</button>
+    </view>
+
+  </view>
+</template>
+
+<script>
+import logic from './qualifications_logic.js';
+export default logic;
+</script>
+
+<style>
+@import './qualifications.css';
+</style>

+ 73 - 0
pages/recruit/qualifications_logic.js

@@ -0,0 +1,73 @@
+export default {
+    data() {
+        return {
+            serviceTypes: [], // 从上一页传递过来的服务类型列表
+            qualifications: {}, // 存储图片路径 { '宠物接送': 'path/to/img', ... }
+        }
+    },
+    onLoad(options) {
+        if (options.services) {
+            try {
+                this.serviceTypes = JSON.parse(options.services);
+                // 初始化 qualifications 对象
+                this.serviceTypes.forEach(type => {
+                    // 使用 Vue.set 或直接赋值 
+                    this.qualifications[type] = [];
+                });
+            } catch (e) {
+                console.error('Parse services failed', e);
+            }
+        }
+    },
+    methods: {
+        chooseImage(serviceName) {
+            uni.chooseImage({
+                count: 9,
+                sizeType: ['compressed'],
+                sourceType: ['album', 'camera'],
+                success: (res) => {
+                    if (!this.qualifications[serviceName]) {
+                        this.qualifications[serviceName] = [];
+                    }
+                    this.qualifications[serviceName] = this.qualifications[serviceName].concat(res.tempFilePaths);
+                    this.$forceUpdate();
+                }
+            });
+        },
+        deleteImage(serviceName, index) {
+            this.qualifications[serviceName].splice(index, 1);
+            this.$forceUpdate();
+        },
+        goBackToForm() {
+            // 尝试返回填写页
+            const pages = getCurrentPages();
+            if (pages.length > 2) {
+                uni.navigateBack({
+                    delta: 2
+                });
+            } else {
+                // 如果页面栈不够(比如直接进入该页),则重定向
+                uni.reLaunch({
+                    url: '/pages/recruit/form'
+                });
+            }
+        },
+        submit() {
+            // 校验是否所有资质都已上传
+            // const missing = this.serviceTypes.find(type => !this.qualifications[type]);
+            // if (missing) {
+            //     uni.showToast({ title: `请上传${missing}服务资质`, icon: 'none' });
+            //     return;
+            // }
+
+            // 实际可能允许部分上传或者有后台逻辑,这里假设全部必填
+            // 为了演示方便,暂时不强制校验,或者校验全部
+
+            // 提交成功,跳转到成功页
+            // 提交成功,跳转到成功页
+            uni.reLaunch({
+                url: '/pages/recruit/success'
+            });
+        }
+    }
+}

+ 446 - 0
pages/recruit/style.css

@@ -0,0 +1,446 @@
+/* 页面背景 */
+page {
+    background-color: #F5F6F8;
+}
+
+.container {
+    padding: 20rpx;
+    /* 底部留白给按钮 */
+}
+
+/* 卡片通用样式 */
+.card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+}
+
+/* 表单行 */
+.form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+}
+
+.form-item:last-child {
+    margin-bottom: 0;
+}
+
+/* 标签宽度固定 */
+.label {
+    width: 120rpx;
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+}
+
+/* 灰色输入框容器 */
+.input-box {
+    flex: 1;
+    height: 80rpx;
+    background-color: #F8F8F8;
+    /* 灰色背景 */
+    border-radius: 8rpx;
+    display: flex;
+    align-items: center;
+    padding: 0 20rpx;
+    font-size: 28rpx;
+    color: #333;
+}
+
+.input {
+    flex: 1;
+    height: 100%;
+    font-size: 28rpx;
+}
+
+/* 特殊样式: 手机号前缀 */
+.prefix-area {
+    display: flex;
+    align-items: center;
+    margin-right: 20rpx;
+    height: 100%;
+    /* 确保高度撑满 */
+}
+
+.prefix {
+    color: #333;
+    margin-right: 5rpx;
+}
+
+.arrow-down {
+    font-size: 20rpx;
+    color: #999;
+    line-height: 1;
+    /* 消除行高影响 */
+}
+
+/* 特殊样式: 获取验证码 */
+.get-code-text {
+    color: #FF5722;
+    font-size: 28rpx;
+    font-weight: bold;
+    margin-left: 20rpx;
+}
+
+/* 特殊样式: 性别单选 */
+.gender-group {
+    display: flex;
+    align-items: center;
+}
+
+.radio-item {
+    display: flex;
+    align-items: center;
+    margin-right: 40rpx;
+    font-size: 30rpx;
+    color: #333;
+}
+
+.radio-icon {
+    margin-right: 10rpx;
+    font-size: 32rpx;
+    color: #ccc;
+    /* 默认灰色 */
+}
+
+.radio-icon.active {
+    color: #FF5722;
+    /* 选中橙色 */
+}
+
+.radio-label.active {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+/* 特殊样式: 箭头与图标 */
+.arrow-right {
+    color: #ccc;
+    font-size: 24rpx;
+    margin-left: auto;
+    /* 推到最右 */
+}
+
+.eye-icon {
+    padding: 10rpx;
+    color: #ccc;
+}
+
+/* 服务类型区域 */
+.section-title {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 20rpx;
+}
+
+.service-types {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 30rpx;
+}
+
+.type-btn {
+    width: 30%;
+    /* 三等分 */
+    height: 80rpx;
+    background-color: #F8F8F8;
+    border-radius: 8rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 28rpx;
+    color: #333;
+    font-weight: 500;
+}
+
+.type-btn.selected {
+    background-color: #FFF3E0;
+    /* 浅橙背景 */
+    color: #FF5722;
+    font-weight: bold;
+}
+
+/* 底部操作区 (非固定) */
+.footer-actions {
+    margin-top: 40rpx;
+    padding: 0 10rpx;
+    padding-bottom: 60rpx;
+    /* 底部留白 */
+}
+
+/* 底部协议 */
+.agreement-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30rpx;
+    /* 增加间距 */
+}
+
+.checkbox {
+    width: 32rpx;
+    height: 32rpx;
+    border: 2rpx solid #ccc;
+    border-radius: 4rpx;
+    margin-right: 15rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.checkbox.checked {
+    border-color: #FF5722;
+    background-color: #FF5722;
+}
+
+.check-mark {
+    color: #fff;
+    font-size: 22rpx;
+}
+
+.agree-text {
+    font-size: 26rpx;
+    color: #999;
+}
+
+/* 底部按钮 */
+.footer-btn-area {
+    width: 100%;
+    margin-top: 40rpx;
+    /* 增加上间距 */
+}
+
+.submit-btn {
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 28rpx;
+    /* 14号字体 */
+    font-weight: bold;
+    height: 90rpx;
+    line-height: 90rpx;
+    border-radius: 45rpx;
+    box-shadow: 0 10rpx 20rpx rgba(255, 87, 34, 0.2);
+}
+
+.submit-btn::after {
+    border: none;
+}
+
+/* 自定义日期选择器弹窗 */
+.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;
+}
+
+/* 猴子图标样式 (复用 eye-icon 容器) */
+.monkey-icon {
+    padding: 10rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.svg-icon {
+    width: 40rpx;
+    height: 40rpx;
+}
+
+/* 弹窗通用列表 (覆盖) */
+.picker-content {
+    height: 800rpx;
+    /* 增加高度以容纳层级 */
+    display: flex;
+    flex-direction: column;
+}
+
+.picker-body {
+    flex: 1;
+    display: flex;
+    overflow: hidden;
+    padding: 0 30rpx 30rpx;
+}
+
+/* 左侧:已选路径垂直时间轴 */
+.timeline-area {
+    width: 200rpx;
+    border-right: 1px solid #f5f5f5;
+    padding-right: 20rpx;
+    display: flex;
+    flex-direction: column;
+}
+
+.timeline-item {
+    position: relative;
+    padding-bottom: 40rpx;
+    padding-left: 30rpx;
+    color: #333;
+    font-size: 28rpx;
+}
+
+.timeline-item:last-child {
+    padding-bottom: 0;
+}
+
+.timeline-dot {
+    position: absolute;
+    left: 0;
+    top: 12rpx;
+    width: 14rpx;
+    height: 14rpx;
+    border-radius: 50%;
+    background-color: #eee;
+}
+
+.timeline-item.active .timeline-dot {
+    background-color: #FF5722;
+    box-shadow: 0 0 0 4rpx rgba(255, 87, 34, 0.2);
+}
+
+.timeline-item.active {
+    font-weight: bold;
+    color: #FF5722;
+}
+
+/* 虚线连接 (除最后一个外的点都有线) */
+.timeline-item:not(:last-child)::after {
+    content: '';
+    position: absolute;
+    left: 6rpx;
+    top: 30rpx;
+    bottom: -10rpx;
+    width: 2rpx;
+    background-color: #f0f0f0;
+}
+
+/* 右侧:待选列表 */
+.list-area {
+    flex: 1;
+    padding-left: 30rpx;
+    overflow-y: auto;
+}
+
+.list-item {
+    padding: 24rpx 0;
+    border-bottom: 1px solid #f9f9f9;
+    font-size: 28rpx;
+    color: #666;
+}
+
+.list-item:active {
+    background-color: #f5f5f5;
+}
+
+/* 弹窗通用列表 */
+.picker-list {
+    max-height: 600rpx;
+    overflow-y: auto;
+    padding: 20rpx 0;
+}
+
+/* 城市选择项 (仿图1) */
+.city-item {
+    display: flex;
+    align-items: center;
+    padding: 24rpx 40rpx;
+    font-size: 30rpx;
+    color: #333;
+}
+
+.city-item.active {
+    color: #FF5722;
+    font-weight: bold;
+}
+
+.dot-radio {
+    width: 16rpx;
+    height: 16rpx;
+    border-radius: 50%;
+    background-color: #eee;
+    margin-right: 20rpx;
+    position: relative;
+}
+
+.city-item.active .dot-radio {
+    background-color: #FF5722;
+    box-shadow: 0 0 0 6rpx rgba(255, 87, 34, 0.2);
+}
+
+/* 站点选择项 (仿图2) */
+.station-item {
+    padding: 30rpx 40rpx;
+    font-size: 30rpx;
+    color: #333;
+    border-bottom: 1px solid #f9f9f9;
+}
+
+.station-item:last-child {
+    border-bottom: none;
+}

+ 91 - 0
pages/recruit/success.css

@@ -0,0 +1,91 @@
+/* 页面背景 */
+page {
+    background-color: #fff;
+    /* 图3看起来是白色背景,或者非常淡的灰 */
+    font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
+}
+
+.success-container {
+    padding: 60rpx 40rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+/* 成功图标区域 */
+.icon-area {
+    margin-top: 60rpx;
+    margin-bottom: 30rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.success-icon {
+    width: 120rpx;
+    height: 120rpx;
+    margin-bottom: 20rpx;
+}
+
+.main-title {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+}
+
+/* 红色提示 */
+.sub-tip {
+    font-size: 26rpx;
+    color: #FF5722;
+    /* 红色/橙红色 */
+    margin-bottom: 60rpx;
+    text-align: center;
+}
+
+/* 信息卡片 */
+.info-card {
+    width: 100%;
+    background-color: #fff;
+    border: 2rpx dashed #eee;
+    /* 虚线边框 */
+    border-radius: 12rpx;
+    padding: 40rpx;
+    box-sizing: border-box;
+    margin-bottom: 100rpx;
+}
+
+.info-item {
+    display: flex;
+    margin-bottom: 25rpx;
+    font-size: 28rpx;
+}
+
+.info-item:last-child {
+    margin-bottom: 0;
+}
+
+.label {
+    min-width: 160rpx;
+    /* 对齐 */
+    color: #999;
+}
+
+.value {
+    color: #333;
+    font-weight: bold;
+}
+
+/* 底部按钮 */
+.footer-btn {
+    width: 240rpx;
+    height: 80rpx;
+    line-height: 80rpx;
+    background: linear-gradient(90deg, #FF6F00 0%, #FF5722 100%);
+    color: #fff;
+    font-size: 28rpx;
+    font-weight: bold;
+    border-radius: 8rpx;
+    /* 方角带一点圆 */
+    text-align: center;
+    margin-top: auto;
+}

+ 40 - 0
pages/recruit/success.vue

@@ -0,0 +1,40 @@
+<template>
+  <view class="success-container">
+    <view class="icon-area">
+      <!-- 绿色对勾图标 (SVG) -->
+      <svg class="success-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
+          <path d="M512 0C229.23 0 0 229.23 0 512s229.23 512 512 512 512-229.23 512-512S794.77 0 512 0z m0 960C264.58 960 64 759.42 64 512S264.58 64 512 64s448 200.58 448 448-200.58 448-448 448z" fill="#64D01D" />
+          <path d="M743.08 335.78c-12.23-12.24-32.07-12.24-44.3 0L426.6 607.96 325.22 506.58c-12.24-12.24-32.07-12.24-44.3 0-12.24 12.24-12.24 32.07 0 44.3l124.58 124.58c6.12 6.12 14.14 9.17 22.15 9.17s16.03-3.05 22.15-9.17L743.08 380.08c12.24-12.24 12.24-32.07 0-44.3z" fill="#64D01D" />
+      </svg>
+      <text class="main-title">提交成功</text>
+    </view>
+
+    <text class="sub-tip">请保持手机畅通,等待平台工作人员与您联系</text>
+
+    <view class="info-card">
+      <view class="info-item">
+        <text class="label">服务站点:</text>
+        <text class="value">{{ station }}</text>
+      </view>
+      <view class="info-item">
+        <text class="label">报 名 人  :</text>
+        <text class="value">{{ name }}</text>
+      </view>
+      <view class="info-item">
+        <text class="label">联系手机:</text>
+        <text class="value">{{ phone }}</text>
+      </view>
+    </view>
+
+    <view class="footer-btn" @click="goHome">我知道了</view>
+  </view>
+</template>
+
+<script>
+import logic from './success_logic.js';
+export default logic;
+</script>
+
+<style>
+@import './success.css';
+</style>

+ 17 - 0
pages/recruit/success_logic.js

@@ -0,0 +1,17 @@
+export default {
+    data() {
+        return {
+            station: '民治街道第一站',
+            name: '张三哥',
+            phone: '+8613612345678'
+        }
+    },
+    methods: {
+        goHome() {
+            // 返回首页或登录页
+            uni.reLaunch({
+                url: '/pages/login/login'
+            });
+        }
+    }
+}

BIN
static/dog.png


BIN
static/header.png


+ 1 - 0
static/icons/bell.png

@@ -0,0 +1 @@
+x

+ 1 - 0
static/icons/bell.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8a6 6 0 0 0-6-6 6 6 0 0 0-6 6c0 7-3 9-3 9h18s-3-2-3-9"></path><path d="M13.73 21a2 2 0 0 1-3.46 0"></path></svg>

+ 5 - 0
static/icons/bell_linear.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 21.5C12.8284 21.5 13.5 20.8284 13.5 20H10.5C10.5 20.8284 11.1716 21.5 12 21.5Z" stroke="#333333" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M18 16V10.5C18 7.46243 15.3137 5 12 5C8.6863 5 6 7.46243 6 10.5V16L4 18V19H20V18L18 16Z" stroke="#333333" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 5V3" stroke="#333333" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 4 - 0
static/icons/bell_outline.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#555555" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
+    <path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
+</svg>

+ 6 - 0
static/icons/calendar.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
+    <line x1="16" y1="2" x2="16" y2="6"></line>
+    <line x1="8" y1="2" x2="8" y2="6"></line>
+    <line x1="3" y1="10" x2="21" y2="10"></line>
+</svg>

+ 4 - 0
static/icons/camera_grey.svg

@@ -0,0 +1,4 @@
+<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.5 4H9.5L8 7H4C3.46957 7 2.96086 7.21071 2.58579 7.58579C2.21071 7.96086 2 8.46957 2 9V19C2 19.5304 2.21071 20.0391 2.58579 20.4142C2.96086 20.7893 3.46957 21 4 21H20C20.5304 21 21.0391 20.7893 21.4142 20.4142C21.7893 20.0391 22 19.5304 22 19V9C22 8.46957 21.7893 7.96086 21.4142 7.58579C21.0391 7.21071 20.5304 7 20 7H16L14.5 4Z" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 18C14.2091 18 16 16.2091 16 14C16 11.7909 14.2091 10 12 10C9.79086 10 8 11.7909 8 14C8 16.2091 9.79086 18 12 18Z" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 0 - 0
static/icons/car.png


+ 1 - 0
static/icons/car.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="orange" stroke="white" stroke-width="1"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/></svg>

+ 3 - 0
static/icons/chevron_right.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <polyline points="9 18 15 12 9 6"></polyline>
+</svg>

+ 3 - 0
static/icons/chevron_right_dark.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <polyline points="9 18 15 12 9 6"></polyline>
+</svg>

+ 3 - 0
static/icons/chevron_right_gold.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FFE082" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <polyline points="9 18 15 12 9 6"></polyline>
+</svg>

+ 4 - 0
static/icons/clock.svg

@@ -0,0 +1,4 @@
+<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 7V12L15 15" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 4 - 0
static/icons/close_gray.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18 6L6 18" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M6 6L18 18" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 3 - 0
static/icons/crown.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FDD835" stroke="#FFA000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <path d="M2 4l3 12h14l3-12-6 7-4-7-4 7-6-7zm3 16h14"></path>
+</svg>

+ 4 - 0
static/icons/diamond_white.svg

@@ -0,0 +1,4 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="16" cy="16" r="16" fill="white" fill-opacity="0.2"/>
+<path d="M16 8L19 16L16 24L13 16L16 8Z" fill="white"/>
+</svg>

+ 6 - 0
static/icons/file.svg

@@ -0,0 +1,6 @@
+<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M14 2V8H20" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 13H16" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 17H16" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
static/icons/headset_green.svg

@@ -0,0 +1,5 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <path d="M42 24C42 14.0589 33.9411 6 24 6C14.0589 6 6 14.0589 6 24V29C6 31.2091 7.79086 33 10 33H12C14.2091 33 16 31.2091 16 29V24C16 21.7909 14.2091 20 12 20H10C10.0342 16.3683 12.918 10 24 10C35.082 10 37.9658 16.3683 38 20H36C33.7909 20 32 21.7909 32 24V29C32 31.2091 33.7909 33 36 33H38C38.0009 33 38.0018 32.9999 38.0026 32.9998C37.8973 35.8083 35.8926 38.3845 31.9091 39.5L34 43.1232C40.0915 41.2292 41.9705 36.9038 41.9993 33.0253C42 33.0169 42 33.0084 42 33V24Z" fill="#7CB342"/>
+  <rect x="34" y="22" width="6" height="8" rx="2" fill="#7CB342"/>
+  <rect x="8" y="22" width="6" height="8" rx="2" fill="#7CB342"/>
+</svg>

+ 4 - 0
static/icons/headset_linear.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19 14V17C19 18.66 17.66 20 16 20H15.5C15.22 20 15 19.78 15 19.5V14.5C15 14.22 15.22 14 15.5 14H19ZM5 14H8.5C8.78 14 9 14.22 9 14.5V19.5C9 19.78 8.78 20 8.5 20H8C6.34 20 5 18.66 5 17V14Z" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19 14V10C19 6.13 15.87 3 12 3C8.13 3 5 6.13 5 10V14" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 7 - 0
static/icons/icon_order_msg.svg

@@ -0,0 +1,7 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="24" cy="24" r="24" fill="#FF6B6B"/>
+<rect x="15" y="13" width="18" height="22" rx="2" fill="white"/>
+<path d="M19 18H29" stroke="#FF6B6B" stroke-width="2" stroke-linecap="round"/>
+<path d="M19 23H29" stroke="#FF6B6B" stroke-width="2" stroke-linecap="round"/>
+<path d="M19 28H25" stroke="#FF6B6B" stroke-width="2" stroke-linecap="round"/>
+</svg>

+ 4 - 0
static/icons/icon_system_msg.svg

@@ -0,0 +1,4 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="24" cy="24" r="24" fill="#4285F4"/>
+<path d="M24 35C25.65 35 27 33.66 27 32H21C21 33.66 22.34 35 24 35ZM30 28V22C30 18.23 27.67 15.11 24 14.15V13C24 11.9 23.1 11 22 11C20.9 11 20 11.9 20 13V14.15C16.33 15.11 14 18.23 14 22V28L12 30V31H36V30L34 28Z" fill="white"/>
+</svg>

+ 4 - 0
static/icons/location.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
+    <circle cx="12" cy="10" r="3"></circle>
+</svg>

+ 7 - 0
static/icons/money_linear.svg

@@ -0,0 +1,7 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="2" y="2" width="20" height="20" rx="10" stroke="#333333" stroke-width="2"/>
+<path d="M9 8L11 11H13L15 8" stroke="#333333" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 11V16" stroke="#333333" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M10 13H14" stroke="#333333" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M10 15H14" stroke="#333333" stroke-width="1.5" stroke-linecap="round"/>
+</svg>

+ 4 - 0
static/icons/motorbike.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FF9800" stroke="none">
+    <rect x="0" y="0" width="24" height="24" rx="4" fill="transparent"/>
+    <path d="M2.6,20.4l1.3-4.2c0.3-0.9,1.1-1.6,2.1-1.6h0.5c0.3-1.6,1.4-2.9,3-3.4l1.3-0.4l-0.8-2.6C9.8,7.9,10,7.5,10.3,7.2 l2.4-1.9C12.8,5.2,13,5.3,12.9,5.4L12.7,6l1.2,0.4l2-1.6c0.4-0.3,1-0.2,1.3,0.2l0,0c0.3,0.4,0.2,1-0.2,1.3l-1.6,1.2l0.4,1.3l2.8,0.9 c1.2,0.4,2.2,1.3,2.6,2.5l1.6,5.3H2.6z M16.5,13.5c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S17.6,13.5,16.5,13.5z M7.5,13.5 c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S8.6,13.5,7.5,13.5z" fill="#FF9800"/>
+</svg>

+ 0 - 0
static/icons/nav.png


+ 1 - 0
static/icons/nav_arrow.png

@@ -0,0 +1 @@
+x

+ 1 - 0
static/icons/nav_arrow.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#FF5722"><path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"/></svg>

+ 7 - 0
static/icons/order_no.svg

@@ -0,0 +1,7 @@
+<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M14 2V8H20" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 13H16" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 17H16" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 9H10" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
static/icons/phone_green.svg

@@ -0,0 +1,5 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M39 33.0001C39 31.8955 38.1046 31.0001 37 31.0001H33C31.8954 31.0001 31 31.8955 31 33.0001C31 36.3138 28.3137 39.0001 25 39.0001C24.4477 39.0001 24 38.5524 24 38.0001V24.0001H21V19.0001C21 16.2387 23.2386 14.0001 26 14.0001H31C32.1046 14.0001 33 13.1047 33 12.0001V8.00012C33 6.89555 32.1046 6.00012 31 6.00012H26C18.8203 6.00012 13 11.8204 13 19.0001V38.0001C13 39.6569 14.3431 41.0001 16 41.0001H36C37.6569 41.0001 39 39.6569 39 38.0001V33.0001Z" fill="#7CB342" fill-opacity="0.01"/>
+<path d="M15.1782 11.3965L11.5816 11.6962C10.5989 11.7781 9.77123 12.4871 9.54483 13.4429C8.62916 17.3082 8.79093 23.9572 13.5658 30.8267C18.4357 37.8384 24.3794 40.5471 28.3243 40.7963C29.2996 40.8579 30.1736 40.1793 30.4309 39.2312L31.3725 35.7617C31.6661 34.6802 31.0116 33.5674 29.9576 33.2201L26.3475 32.0305C25.4673 31.7405 24.4947 32.0468 23.9743 32.8123L22.6571 34.7497C22.6571 34.7497 20.3719 33.6749 18.2505 31.5535C16.129 29.432 15.0543 27.1468 15.0543 27.1468L16.9917 25.8296C17.7571 25.3092 18.0635 24.3366 17.7735 23.4564L16.5838 19.8463C16.2366 18.7923 15.1238 18.1378 14.0423 18.4314L15.1782 11.3965Z" fill="#7CB342"/>
+<path d="M15.1782 11.3965L11.5816 11.6962C10.5989 11.7781 9.77123 12.4871 9.54483 13.4429C8.62916 17.3082 8.79093 23.9572 13.5658 30.8267C18.4357 37.8384 24.3794 40.5471 28.3243 40.7963C29.2996 40.8579 30.1736 40.1793 30.4309 39.2312L31.3725 35.7617C31.6661 34.6802 31.0116 33.5674 29.9576 33.2201L26.3475 32.0305C25.4673 31.7405 24.4947 32.0468 23.9743 32.8123L22.6571 34.7497C22.6571 34.7497 20.3719 33.6749 18.2505 31.5535C16.129 29.432 15.0543 27.1468 15.0543 27.1468L16.9917 25.8296C17.7571 25.3092 18.0635 24.3366 17.7735 23.4564L16.5838 19.8463C16.2366 18.7923 15.1238 18.1378 14.0423 18.4314L15.1782 11.3965Z" stroke="#7CB342" stroke-width="3" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
static/icons/phone_orange.svg

@@ -0,0 +1,5 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M39 33.0001C39 31.8955 38.1046 31.0001 37 31.0001H33C31.8954 31.0001 31 31.8955 31 33.0001C31 36.3138 28.3137 39.0001 25 39.0001C24.4477 39.0001 24 38.5524 24 38.0001V24.0001H21V19.0001C21 16.2387 23.2386 14.0001 26 14.0001H31C32.1046 14.0001 33 13.1047 33 12.0001V8.00012C33 6.89555 32.1046 6.00012 31 6.00012H26C18.8203 6.00012 13 11.8204 13 19.0001V38.0001C13 39.6569 14.3431 41.0001 16 41.0001H36C37.6569 41.0001 39 39.6569 39 38.0001V33.0001Z" fill="#FF9800" fill-opacity="0.01"/>
+<path d="M15.1782 11.3965L11.5816 11.6962C10.5989 11.7781 9.77123 12.4871 9.54483 13.4429C8.62916 17.3082 8.79093 23.9572 13.5658 30.8267C18.4357 37.8384 24.3794 40.5471 28.3243 40.7963C29.2996 40.8579 30.1736 40.1793 30.4309 39.2312L31.3725 35.7617C31.6661 34.6802 31.0116 33.5674 29.9576 33.2201L26.3475 32.0305C25.4673 31.7405 24.4947 32.0468 23.9743 32.8123L22.6571 34.7497C22.6571 34.7497 20.3719 33.6749 18.2505 31.5535C16.129 29.432 15.0543 27.1468 15.0543 27.1468L16.9917 25.8296C17.7571 25.3092 18.0635 24.3366 17.7735 23.4564L16.5838 19.8463C16.2366 18.7923 15.1238 18.1378 14.0423 18.4314L15.1782 11.3965Z" fill="#FF9800"/>
+<path d="M15.1782 11.3965L11.5816 11.6962C10.5989 11.7781 9.77123 12.4871 9.54483 13.4429C8.62916 17.3082 8.79093 23.9572 13.5658 30.8267C18.4357 37.8384 24.3794 40.5471 28.3243 40.7963C29.2996 40.8579 30.1736 40.1793 30.4309 39.2312L31.3725 35.7617C31.6661 34.6802 31.0116 33.5674 29.9576 33.2201L26.3475 32.0305C25.4673 31.7405 24.4947 32.0468 23.9743 32.8123L22.6571 34.7497C22.6571 34.7497 20.3719 33.6749 18.2505 31.5535C16.129 29.432 15.0543 27.1468 15.0543 27.1468L16.9917 25.8296C17.7571 25.3092 18.0635 24.3366 17.7735 23.4564L16.5838 19.8463C16.2366 18.7923 15.1238 18.1378 14.0423 18.4314L15.1782 11.3965Z" stroke="#FF9800" stroke-width="3" stroke-linejoin="round"/>
+</svg>

+ 4 - 0
static/icons/power_white.svg

@@ -0,0 +1,4 @@
+<svg width="64" height="64" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 3V12" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M5.63604 5.63604C2.12132 9.15076 2.12132 14.8492 5.63604 18.364C9.15076 21.8787 14.8492 21.8787 18.364 18.364C21.8787 14.8492 21.8787 9.15076 18.364 5.63604" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 4 - 0
static/icons/reward.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <circle cx="12" cy="8" r="7"></circle>
+    <polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"></polyline>
+</svg>

+ 3 - 0
static/icons/right_arrow_orange.svg

@@ -0,0 +1,3 @@
+<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9 5L16 12L9 19" stroke="#FF5722" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 3 - 0
static/icons/service.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <path d="M15.05 5A5 5 0 0 1 19 8.95M15.05 1A9 9 0 0 1 23 8.94m-1 7.98v3a2 2 0 0 1-2.17 2.03c-2.44-.28-4.8-1.52-6.66-3.38C10.51 15.9 8.44 13.84 7.21 11.4c-.87-1.74-1.22-3.7-1.12-5.41A2 2 0 0 1 8 4.09 2 2 0 0 1 10 2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-1c-.5 0-1 .5-1.15.65-.67 1.51-.06 3.19 1.15 4.4 1.21 1.21 2.89 1.82 4.4 1.15.15-.15.65-.65.65-1.15v-1a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2z"></path>
+</svg>

+ 4 - 0
static/icons/settings.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+    <circle cx="12" cy="12" r="3"></circle>
+    <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
+</svg>

+ 8 - 0
static/icons/star_decor.svg

@@ -0,0 +1,8 @@
+<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
+<!-- Ribbons -->
+<path d="M70 20H130V60L100 40L70 60V20Z" fill="white" fill-opacity="0.1"/>
+<!-- Medal Circle -->
+<circle cx="100" cy="110" r="70" fill="white" fill-opacity="0.15"/>
+<!-- Star -->
+<path d="M100 65L110 95H140L115 115L125 145L100 125L75 145L85 115L60 95H90L100 65Z" fill="white" fill-opacity="0.2"/>
+</svg>

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff