فهرست منبع

二期基本完成

Huanyi 3 ساعت پیش
والد
کامیت
315e663dd1

+ 3 - 3
manifest.json

@@ -1,9 +1,9 @@
 {
 {
     "name" : "履约守护",
     "name" : "履约守护",
     "appid" : "__UNI__76F5C47",
     "appid" : "__UNI__76F5C47",
-    "description" : "履约守护",
-    "versionName" : "1.2.3",
-    "versionCode" : 23,
+    "description" : "履约",
+    "versionName" : "2.0.0",
+    "versionCode" : 20000,
     "transformPx" : false,
     "transformPx" : false,
     /* 5+App特有相关 */
     /* 5+App特有相关 */
     "app-plus" : {
     "app-plus" : {

+ 8 - 0
pages.json

@@ -69,6 +69,14 @@
 				"navigationBarTextStyle": "black"
 				"navigationBarTextStyle": "black"
 			}
 			}
 		},
 		},
+		{
+			"path": "pages/home/orderDetail/index",
+			"style": {
+				"navigationBarTitleText": "订单大厅详情",
+				"navigationBarBackgroundColor": "#ffffff",
+				"navigationBarTextStyle": "black"
+			}
+		},
 		{
 		{
 			"path": "pages/orders/index",
 			"path": "pages/orders/index",
 			"style": {
 			"style": {

+ 37 - 2
pages/home/index.vue

@@ -134,7 +134,13 @@
                             <image class="type-icon" :src="item.typeIcon"></image>
                             <image class="type-icon" :src="item.typeIcon"></image>
                             <text class="type-text">{{ item.typeText }}</text>
                             <text class="type-text">{{ item.typeText }}</text>
                         </view>
                         </view>
-                        <text class="price">¥{{ item.price }}</text>
+                        <view class="header-right">
+                          <text class="price">¥{{ item.price }}</text>
+                          <view class="detail-link">
+                            <text>详情</text>
+                            <text class="arrow">></text>
+                          </view>
+                        </view>
                     </view>
                     </view>
                     <view class="card-body">
                     <view class="card-body">
                         <view class="time-row">
                         <view class="time-row">
@@ -733,7 +739,9 @@ export default {
             this.isFilterShow = false;
             this.isFilterShow = false;
         },
         },
         goToDetail(item) {
         goToDetail(item) {
-            console.log('Go to detail', item);
+            uni.navigateTo({
+                url: `/pages/home/orderDetail/index?id=${item.id}`
+            });
         },
         },
         async loadTaskList() {
         async loadTaskList() {
             try {
             try {
@@ -2128,4 +2136,31 @@ page {
     height: 16rpx;
     height: 16rpx;
     background-color: #F8F8F8;
     background-color: #F8F8F8;
 }
 }
+
+/* 详情跳转指引样式 @Author: Antigravity */
+.task-card:active {
+    opacity: 0.8;
+    transform: scale(0.99);
+}
+
+.header-right {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+}
+
+.detail-link {
+    display: flex;
+    align-items: center;
+    font-size: 24rpx;
+    color: #FF9800;
+    margin-top: 6rpx;
+    opacity: 0.9;
+}
+
+.detail-link .arrow {
+    margin-left: 4rpx;
+    font-size: 20rpx;
+    font-weight: bold;
+}
 </style>
 </style>

+ 500 - 0
pages/home/orderDetail/index.vue

@@ -0,0 +1,500 @@
+<template>
+  <view class="detail-container">
+    <!-- 加载动画 -->
+    <view class="loading-container" v-if="pageLoading">
+      <view class="skeleton-header">
+        <view class="skeleton-line skeleton-ani" style="width: 30%; height: 36rpx;"></view>
+        <view class="skeleton-line skeleton-ani" style="width: 20%; height: 36rpx;"></view>
+      </view>
+      <view class="skeleton-card" v-for="j in 3" :key="'c' + j">
+        <view class="skeleton-line skeleton-ani" style="width: 60%; height: 28rpx; margin-bottom: 20rpx;"></view>
+        <view class="skeleton-line skeleton-ani" style="width: 90%; height: 24rpx; margin-bottom: 14rpx;"></view>
+        <view class="skeleton-line skeleton-ani" style="width: 75%; height: 24rpx;"></view>
+      </view>
+    </view>
+
+    <template v-else>
+      <!-- 顶部状态区 -->
+      <view class="detail-header pre-accept">
+        <view class="status-row">
+          <text class="status-title">待接单</text>
+          <text class="status-price">¥{{ orderDetail.fulfillmentCommission }}</text>
+        </view>
+        <view class="status-desc">待接单订单,接单后可查看完整联系方式</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.serviceName }}</text>
+            </view>
+          </view>
+          <view class="pb-actions">
+            <view class="view-profile-btn" @click="showPetProfile">
+              <text>宠物档案</text>
+              <text class="arrow">></text>
+            </view>
+          </view>
+        </view>
+
+        <!-- 用户档案卡片 -->
+        <view class="white-card user-profile-card">
+          <view class="tl-title-row">
+            <view class="orange-bar"></view>
+            <text class="tl-title">用户档案</text>
+          </view>
+          <view class="bi-row">
+            <image class="bi-icon" src="/static/icons/user.svg"></image>
+            <view class="bi-content">
+              <text class="bi-label">联系人</text>
+              <text class="bi-val">{{ orderDetail.ownerName || '匿名用户' }}</text>
+            </view>
+          </view>
+          <view class="bi-row">
+            <image class="bi-icon" src="/static/icons/phone.svg"></image>
+            <view class="bi-content">
+              <text class="bi-label">联系电话</text>
+              <text class="bi-val">{{ orderDetail.ownerPhone || '接单后可见' }}</text>
+            </view>
+          </view>
+          <view class="bi-row no-border">
+            <image class="bi-icon" src="/static/icons/location.svg"></image>
+            <view class="bi-content">
+              <text class="bi-label">详细地址</text>
+              <text class="bi-val">{{ orderDetail.endAddress || '暂无详细地址' }}</text>
+            </view>
+          </view>
+        </view>
+
+        <!-- 路线及服务信息 -->
+        <view class="white-card service-info-card">
+           <view class="tl-title-row">
+            <view class="orange-bar"></view>
+            <text class="tl-title">服务详情</text>
+          </view>
+          <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>
+
+          <!-- 接送类型的地址展现 -->
+          <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>
+          </template>
+
+          <view class="si-row no-border">
+            <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 logs-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, index) in orderLogs" :key="index">
+              <view class="tl-marker" :class="{ 'active': index === 0 }">
+                <view class="tl-dot-inner" v-if="index === 0"></view>
+              </view>
+              <view class="tl-content-row">
+                <view class="tl-header">
+                  <text class="tl-status">{{ log.title || '系统记录' }}</text>
+                  <text class="tl-time">{{ log.time }}</text>
+                </view>
+                <text class="tl-remark" v-if="log.content">{{ log.content }}</text>
+              </view>
+            </view>
+          </view>
+        </view>
+
+        <view style="height: 60rpx;"></view>
+      </scroll-view>
+    </template>
+
+    <!-- 宠物档案弹窗 (引用首页逻辑) -->
+    <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">
+          <view class="pet-base-info">
+            <image class="pm-avatar" :src="orderDetail.petAvatar" mode="aspectFill"></image>
+            <view class="pm-info-text">
+              <view class="pm-name-row">
+                <text class="pm-name">{{ orderDetail.petName }}</text>
+                <view class="pm-gender" v-if="orderDetail.petGender === 'M'">
+                  <text class="gender-icon">♂</text><text>公</text>
+                </view>
+                <view class="pm-gender female" v-else-if="orderDetail.petGender === 'F'">
+                  <text class="gender-icon">♀</text><text>母</text>
+                </view>
+              </view>
+              <text class="pm-breed">品种:{{ orderDetail.petBreed }}</text>
+            </view>
+          </view>
+          <view class="pm-detail-grid">
+            <view class="pm-grid-item half">
+              <text class="pm-label">年龄</text>
+              <text class="pm-val">{{ orderDetail.petAge || '未知' }}</text>
+            </view>
+            <view class="pm-grid-item half">
+              <text class="pm-label">体重</text>
+              <text class="pm-val">{{ orderDetail.petWeight || '未知' }}</text>
+            </view>
+            <view class="pm-grid-item full">
+              <text class="pm-label">性格</text>
+              <text class="pm-val">{{ orderDetail.petPersonality || '暂无' }}</text>
+            </view>
+            <view class="pm-grid-item full">
+               <text class="pm-label">备注/禁忌</text>
+               <text class="pm-val">{{ orderDetail.petNotes || '暂无说明' }}</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 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>
+</template>
+
+<script>
+import { getOrderInfo } from '@/api/order/subOrder'
+import { getOrderLogs } from '@/api/order/subOrderLog'
+import { listAllService } from '@/api/service/list'
+import { getPetDetail } from '@/api/archieves/pet'
+import { reportGps } from '@/utils/gps'
+
+/**
+ * 订单大厅详情页 (数据修正版)
+ * @Author: Antigravity
+ */
+export default {
+    data() {
+        return {
+            orderId: null,
+            pageLoading: true,
+            orderDetail: {
+                type: 1, fulfillmentCommission: '0.00', time: '',
+                petAvatar: '/static/dog.png', petName: '', petBreed: '',
+                serviceName: '', startLocation: '', startAddress: '', endLocation: '', endAddress: '',
+                remark: '', orderNo: '', createTime: '', fromLat: null, fromLng: null, toLat: null, toLng: null,
+                ownerName: '', ownerPhone: '', petAge: '', petWeight: '', petGender: 'M', petPersonality: '', petNotes: ''
+            },
+            orderLogs: [],
+            serviceList: [],
+            showNavModal: false,
+            navTargetPointType: '',
+            showPetModal: false
+        }
+    },
+    async onLoad(options) {
+        if (options.id) this.orderId = options.id
+        this.pageLoading = true
+        try {
+            await this.loadServiceList()
+            await this.loadOrderDetail()
+        } finally {
+            this.pageLoading = false
+        }
+    },
+    methods: {
+        async loadServiceList() {
+            try {
+                const res = await listAllService()
+                this.serviceList = res.data || []
+            } catch (err) { console.error('获取服务类型失败:', err) }
+        },
+        async loadOrderDetail() {
+            if (!this.orderId) return
+            try {
+                const res = await getOrderInfo(this.orderId)
+                const order = res.data
+                if (!order) return
+                
+                const serviceInfo = this.serviceList.find(s => s.id === order.service)
+                const mode = serviceInfo?.mode || 0
+                this.orderDetail = {
+                    id: order.id,
+                    type: mode === 1 ? 1 : 2,
+                    fulfillmentCommission: (order.fulfillmentCommission / 100).toFixed(2),
+                    time: order.serviceTime || '',
+                    petAvatar: order.petAvatar || '/static/dog.png',
+                    petName: order.petName || '宠物',
+                    petBreed: order.breed || '未知品种',
+                    serviceName: serviceInfo?.name || '未知服务',
+                    startLocation: order.fromAddress || '暂无起点',
+                    startAddress: order.fromAddress || '',
+                    fromLat: order.fromLat, fromLng: order.fromLng,
+                    endLocation: order.toAddress || '查看详情可见',
+                    endAddress: order.toAddress || '',
+                    toLat: order.toLat, toLng: order.toLng,
+                    remark: order.remark || '',
+                    orderNo: order.code || 'T' + order.id,
+                    createTime: order.createDateTime || order.serviceTime,
+                    ownerName: order.contact || '匿名用户',
+                    ownerPhone: order.contactPhoneNumber || ''
+                }
+                
+                // 1. 加载宠物详情
+                if (order.usrPet) {
+                  this.loadPetInfo(order.usrPet)
+                }
+                // 2. 加载时间轴日志
+                this.loadLogs()
+            } catch (err) { console.error('获取详情失败:', err) }
+        },
+        async loadPetInfo(petId) {
+          try {
+            const res = await getPetDetail(petId)
+            const pet = res.data
+            if (pet) {
+              this.orderDetail.petAge = pet.age || '未知'
+              this.orderDetail.petWeight = pet.weight || '未知'
+              this.orderDetail.petGender = pet.sex || 'M'
+              this.orderDetail.petPersonality = pet.personality || '暂无标签'
+              this.orderDetail.petNotes = pet.remark || '暂无说明'
+            }
+          } catch (err) { console.error('获取宠物详情失败:', err) }
+        },
+        async loadLogs() {
+          try {
+            const res = await getOrderLogs(this.orderId)
+            const list = Array.isArray(res.data) ? res.data : (res.rows || [])
+            this.orderLogs = list.map(item => ({
+              title: item.title || '状态更新',
+              time: item.createTime || '',
+              content: item.content || ''
+            }))
+          } catch (err) { console.error('获取日志失败:', err) }
+        },
+        showPetProfile() { this.showPetModal = true },
+        closePetProfile() { this.showPetModal = false },
+        openNavigation(type) { this.navTargetPointType = type; this.showNavModal = true },
+        closeNavModal() { this.showNavModal = false },
+        chooseMap(mapType) {
+            let pointType = this.navTargetPointType;
+            let name = pointType === 'start' ? (this.orderDetail.startAddress || '起点') : (this.orderDetail.endAddress || '终点');
+            let address = name;
+            let latitude = pointType === 'start' ? Number(this.orderDetail.fromLat) : Number(this.orderDetail.toLat);
+            let longitude = pointType === 'start' ? Number(this.orderDetail.fromLng) : Number(this.orderDetail.toLng);
+            this.showNavModal = false;
+            
+            const navigateTo = (lat, lng) => {
+                uni.openLocation({ latitude: lat, longitude: lng, name: name, address: address });
+            };
+            if (latitude && longitude && !isNaN(latitude)) {
+                navigateTo(latitude, longitude);
+            } else {
+                uni.showLoading({ title: '定位中...' });
+                reportGps(true).then(res => {
+                    uni.hideLoading(); navigateTo(res.latitude, res.longitude);
+                }).catch(() => uni.hideLoading());
+            }
+        }
+    }
+}
+</script>
+
+<style lang="scss">
+.detail-container {
+  min-height: 100vh;
+  background-color: #f8f8f8;
+  display: flex;
+  flex-direction: column;
+}
+
+.detail-header {
+  padding: 40rpx 40rpx 80rpx;
+  background: linear-gradient(135deg, #FF9800 0%, #FFB74D 100%);
+  color: #fff;
+  .status-row {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 20rpx;
+      .status-title { font-size: 44rpx; font-weight: bold; }
+      .status-price { font-size: 40rpx; font-weight: bold; }
+  }
+  .status-desc { font-size: 26rpx; opacity: 0.9; }
+}
+
+.detail-content {
+  flex: 1;
+  padding: 20rpx;
+  margin-top: -40rpx;
+}
+
+.white-card {
+  background: #fff;
+  border-radius: 24rpx;
+  padding: 30rpx;
+  margin-bottom: 24rpx;
+  box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
+}
+
+/* 宠物栏 */
+.pet-bar {
+  display: flex;
+  align-items: center;
+  .pb-avatar { width: 110rpx; height: 110rpx; border-radius: 50%; margin-right: 24rpx; background: #f0f0f0; border: 4rpx solid #fff; box-shadow: 0 4rpx 10rpx rgba(0,0,0,0.05); }
+  .pb-info {
+      flex: 1;
+      .pb-name { font-size: 34rpx; font-weight: bold; color: #333; margin-right: 12rpx; }
+      .pb-breed { font-size: 24rpx; color: #999; }
+      .pb-tags { margin-top: 10rpx; .pb-tag { font-size: 22rpx; color: #FF9800; background: rgba(255,152,0,0.1); padding: 4rpx 16rpx; border-radius: 6rpx; } }
+  }
+  .view-profile-btn {
+      display: flex; align-items: center; background: #FFF3E0; padding: 10rpx 20rpx; border-radius: 30rpx;
+      text { font-size: 24rpx; color: #FF9800; font-weight: bold; }
+      .arrow { margin-left: 6rpx; font-size: 20rpx; }
+  }
+}
+
+/* 用户档案 */
+.user-profile-card {
+    .bi-row {
+        display: flex; align-items: flex-start; padding: 20rpx 0; border-bottom: 1rpx solid #f5f5f5;
+        &.no-border { border-bottom: none; }
+        .bi-icon { width: 32rpx; height: 32rpx; margin-right: 20rpx; margin-top: 6rpx; opacity: 0.6; }
+        .bi-content {
+            flex: 1;
+            .bi-label { font-size: 24rpx; color: #999; margin-bottom: 4rpx; display: block; }
+            .bi-val { font-size: 28rpx; color: #333; font-weight: 500; }
+        }
+    }
+}
+
+/* 服务详情 */
+.service-info-card {
+  .si-row {
+      display: flex; padding: 24rpx 0; border-bottom: 1rpx solid #f5f5f5;
+      &.no-border { border-bottom: none; }
+      .si-icon { width: 36rpx; height: 36rpx; margin-right: 20rpx; margin-top: 4rpx; }
+      .si-content {
+          flex: 1;
+          .si-label { font-size: 24rpx; color: #999; display: block; margin-bottom: 6rpx; }
+          .si-val { font-size: 28rpx; color: #333; }
+          .si-addr-title { font-size: 30rpx; font-weight: bold; color: #333; display: block; margin-bottom: 8rpx; }
+          .si-addr-desc { font-size: 24rpx; color: #666; }
+      }
+  }
+}
+
+.addr-row {
+    position: relative;
+    .icon-circle {
+        width: 44rpx; height: 44rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center;
+        font-size: 22rpx; color: #fff; margin-right: 20rpx; flex-shrink: 0; margin-top: 6rpx;
+        &.start { background: #FF9800; }
+        &.end { background: #4CAF50; }
+        &.service { background: #2196F3; }
+    }
+    .route-line-vertical { position: absolute; left: 22rpx; top: 56rpx; bottom: -10rpx; width: 2rpx; border-left: 2rpx dashed #ddd; }
+}
+
+.nav-btn-circle { width: 56rpx; height: 56rpx; border-radius: 50%; background: #FFF3E0; display: flex; align-items: center; justify-content: center; margin-left: 20rpx; .nav-arrow { width: 28rpx; height: 28rpx; } }
+
+/* 日志板块 */
+.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 { 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: 12rpx; 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; }
+.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: 32rpx; bottom: -10rpx; width: 2rpx; background-color: #FFE0B2; z-index: 1; }
+.tl-content-row { margin-left: 44rpx; display: flex; flex-direction: column; width: 100%; }
+.tl-header { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-bottom: 12rpx; }
+.tl-status { font-size: 28rpx; color: #333; font-weight: bold; }
+.tl-time { font-size: 24rpx; color: #999; }
+.tl-remark { font-size: 24rpx; color: #666; background-color: #F9F9F9; padding: 16rpx; border-radius: 12rpx; line-height: 1.5; }
+
+/* 弹窗通用 */
+.pet-modal-mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 999; display: flex; align-items: center; justify-content: center; }
+.pet-modal-content { width: 680rpx; background: #fff; border-radius: 24rpx; overflow: hidden; }
+.pet-modal-header { padding: 30rpx; display: flex; justify-content: space-between; align-items: center; border-bottom: 1rpx solid #f5f5f5; .pet-modal-title { font-size: 34rpx; font-weight: bold; } .close-icon-btn { font-size: 40rpx; color: #999; } }
+.pet-modal-scroll { padding: 30rpx; height: 75vh; 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; } }
+.pm-name-row { display: flex; align-items: center; margin-bottom: 12rpx; .pm-name { font-size: 36rpx; font-weight: bold; margin-right: 20rpx; } .pm-gender { background: #E3F2FD; padding: 4rpx 16rpx; border-radius: 20rpx; text { font-size: 22rpx; color: #1E88E5; } &.female { background: #FCE4EC; text { color: #D81B60; } } } }
+.pm-breed { font-size: 26rpx; color: #999; }
+.pm-detail-grid { display: flex; flex-wrap: wrap; gap: 20rpx; .pm-grid-item { background: #f8f8f8; padding: 24rpx; border-radius: 16rpx; display: flex; flex-direction: column; &.half { width: calc(50% - 10rpx); box-sizing: border-box; } &.full { width: 100%; box-sizing: border-box; } .pm-label { font-size: 24rpx; color: #999; margin-bottom: 8rpx; } .pm-val { font-size: 28rpx; color: #333; font-weight: 500; } } }
+.pm-bottom-close { margin-top: 40rpx; background: #f5f5f5; color: #666; border-radius: 40rpx; font-size: 30rpx; }
+
+.nav-modal-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.4); z-index: 1000; }
+.nav-action-sheet { position: absolute; bottom: 0; left: 0; right: 0; background: #fff; border-radius: 24rpx 24rpx 0 0; padding-bottom: env(safe-area-inset-bottom);
+    .nav-sheet-title { padding: 30rpx; text-align: center; font-size: 28rpx; color: #999; border-bottom: 1rpx solid #eee; }
+    .nav-sheet-item { padding: 30rpx; text-align: center; font-size: 32rpx; color: #333; border-bottom: 1rpx solid #eee; &.cancel { color: #f26d6d; border-bottom: none; } }
+    .nav-sheet-gap { height: 12rpx; background: #f5f5f5; }
+}
+
+.loading-container { padding: 100rpx 40rpx; .skeleton-header { display: flex; justify-content: space-between; margin-bottom: 60rpx; } .skeleton-card { background: #fff; border-radius: 20rpx; padding: 30rpx; margin-bottom: 30rpx; } .skeleton-line { background: #f0f0f0; border-radius: 4rpx; } .skeleton-ani { animation: skeleton-loading 1.4s ease infinite; } }
+@keyframes skeleton-loading { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }
+</style>

+ 3 - 3
pages/orders/anomaly/index.vue

@@ -36,7 +36,7 @@
             <view class="ano-card">
             <view class="ano-card">
                 <view class="ano-section-title">
                 <view class="ano-section-title">
                     <view class="ano-title-bar"></view>
                     <view class="ano-title-bar"></view>
-                    <text class="ano-title-text">现场照片 (必填,最多5张)</text>
+                    <text class="ano-title-text">现场照片 (必填,最多6张)</text>
                 </view>
                 </view>
                 <view class="ano-photo-grid">
                 <view class="ano-photo-grid">
                     <!-- 已上传图片 -->
                     <!-- 已上传图片 -->
@@ -45,7 +45,7 @@
                         <view class="ano-photo-del" @click="removePhoto(idx)">×</view>
                         <view class="ano-photo-del" @click="removePhoto(idx)">×</view>
                     </view>
                     </view>
                     <!-- 添加按钮 -->
                     <!-- 添加按钮 -->
-                    <view class="ano-photo-add" @click="choosePhoto" v-if="photoList.length < 5">
+                    <view class="ano-photo-add" @click="choosePhoto" v-if="photoList.length < 6">
                         <image class="ano-add-icon" src="/static/icons/camera_grey.svg"></image>
                         <image class="ano-add-icon" src="/static/icons/camera_grey.svg"></image>
                         <text class="ano-add-text">上传</text>
                         <text class="ano-add-text">上传</text>
                     </view>
                     </view>
@@ -158,7 +158,7 @@ export default {
         // 选择照片并上传
         // 选择照片并上传
         choosePhoto() {
         choosePhoto() {
             uni.chooseImage({
             uni.chooseImage({
-                count: 5 - this.photoList.length,
+                count: 6 - this.photoList.length,
                 sizeType: ['compressed'],
                 sizeType: ['compressed'],
                 sourceType: ['album', 'camera'],
                 sourceType: ['album', 'camera'],
                 success: async (res) => {
                 success: async (res) => {

+ 3 - 3
pages/orders/appeal/index.vue

@@ -57,14 +57,14 @@
         <view class="section-label">
         <view class="section-label">
           <text class="label-text">图片凭证</text>
           <text class="label-text">图片凭证</text>
           <text class="required">*</text>
           <text class="required">*</text>
-          <text class="label-sub">(最多9张)</text>
+          <text class="label-sub">(最多6张)</text>
         </view>
         </view>
         <view class="upload-grid">
         <view class="upload-grid">
           <view class="upload-item" v-for="(img, index) in imageList" :key="index" @click="previewImage(index)">
           <view class="upload-item" v-for="(img, index) in imageList" :key="index" @click="previewImage(index)">
             <image :src="img" class="uploaded-img" mode="aspectFill"></image>
             <image :src="img" class="uploaded-img" mode="aspectFill"></image>
             <view class="delete-btn" @click.stop="deleteImage(index)">×</view>
             <view class="delete-btn" @click.stop="deleteImage(index)">×</view>
           </view>
           </view>
-          <view class="upload-btn" v-if="imageList.length < 9" @click="chooseImage">
+          <view class="upload-btn" v-if="imageList.length < 6" @click="chooseImage">
             <text class="plus">+</text>
             <text class="plus">+</text>
             <text class="upload-text">上传凭证</text>
             <text class="upload-text">上传凭证</text>
           </view>
           </view>
@@ -162,7 +162,7 @@ export default {
     },
     },
     chooseImage() {
     chooseImage() {
       uni.chooseImage({
       uni.chooseImage({
-        count: 9 - this.imageList.length,
+        count: 6 - this.imageList.length,
         sizeType: ['compressed'],
         sizeType: ['compressed'],
         sourceType: ['album', 'camera'],
         sourceType: ['album', 'camera'],
         success: async (res) => {
         success: async (res) => {

+ 3 - 3
pages/orders/detail/index.vue

@@ -333,7 +333,7 @@
             <view class="upload-modal-mask" v-if="showUploadModal" @click="closeUploadModal">
             <view class="upload-modal-mask" v-if="showUploadModal" @click="closeUploadModal">
                 <view class="upload-modal-content" @click.stop>
                 <view class="upload-modal-content" @click.stop>
                     <view class="um-header">
                     <view class="um-header">
-                        <text class="um-title">上传图或视频 ({{ modalMediaList.length }}/5)</text>
+                        <text class="um-title">上传图或视频 ({{ modalMediaList.length }}/6)</text>
                         <text class="um-remark-hint">{{ currentTaskDesc }}</text>
                         <text class="um-remark-hint">{{ currentTaskDesc }}</text>
                     </view>
                     </view>
                     <view class="um-body">
                     <view class="um-body">
@@ -347,7 +347,7 @@
                                 </view>
                                 </view>
                                 <view class="um-del" @click="removeModalMedia(idx)">×</view>
                                 <view class="um-del" @click="removeModalMedia(idx)">×</view>
                             </view>
                             </view>
-                            <view class="um-add" @click="chooseModalMedia" v-if="modalMediaList.length < 5">
+                            <view class="um-add" @click="chooseModalMedia" v-if="modalMediaList.length < 6">
                                 <image class="um-add-icon" src="/static/icons/camera_grey.svg"></image>
                                 <image class="um-add-icon" src="/static/icons/camera_grey.svg"></image>
                                 <text class="um-add-text">拍摄/上传</text>
                                 <text class="um-add-text">拍摄/上传</text>
                             </view>
                             </view>
@@ -787,7 +787,7 @@ export default {
                 success: (asRes) => {
                 success: (asRes) => {
                     if (asRes.tapIndex === 0) {
                     if (asRes.tapIndex === 0) {
                         uni.chooseImage({
                         uni.chooseImage({
-                            count: 5 - this.modalMediaList.length,
+                            count: 6 - this.modalMediaList.length,
                             sizeType: ['compressed'],
                             sizeType: ['compressed'],
                             sourceType: ['album', 'camera'],
                             sourceType: ['album', 'camera'],
                             success: async (res) => {
                             success: async (res) => {

+ 1 - 1
pages/recruit/qualifications/index.vue

@@ -72,7 +72,7 @@ export default {
     },
     },
     chooseImage(serviceName) {
     chooseImage(serviceName) {
       uni.chooseImage({
       uni.chooseImage({
-        count: 9, sizeType: ['compressed'], sourceType: ['album', 'camera'],
+        count: 6, sizeType: ['compressed'], sourceType: ['album', 'camera'],
         success: async (res) => {
         success: async (res) => {
           if (!this.qualifications[serviceName]) { this.qualifications[serviceName] = []; this.qualOssIds[serviceName] = []; }
           if (!this.qualifications[serviceName]) { this.qualifications[serviceName] = []; this.qualOssIds[serviceName] = []; }
           for (const tempPath of res.tempFilePaths) {
           for (const tempPath of res.tempFilePaths) {

BIN
unpackage/cache/apk/__UNI__76F5C47_cm.apk


+ 1 - 1
unpackage/cache/apk/apkurl

@@ -1 +1 @@
-https://app.liuyingyong.cn/build/download/83f35700-2e70-11f1-8ab7-6ffc0f58920c
+https://app.liuyingyong.cn/build/download/99ef12e0-380d-11f1-8b46-818db5eefbd6

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/apk/cmManifestCache.json


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
unpackage/cache/wgt/__UNI__76F5C47/app-config-service.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/app-service.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/manifest.json


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/home/index.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/home/orderDetail/index.css


+ 0 - 1
unpackage/cache/wgt/__UNI__76F5C47/pages/mine/settings/about/agreement-detail/index.css

@@ -1 +0,0 @@
-body{background-color:#fff}.container{display:flex;flex-direction:column;height:100vh}.custom-header{position:fixed;top:0;left:0;width:100%;height:2.75rem;padding-top:var(--status-bar-height);background-color:#fff;display:flex;align-items:center;justify-content:space-between;padding-left:.9375rem;padding-right:.9375rem;box-sizing:content-box;z-index:100;border-bottom:.03125rem solid #f5f5f5}.header-placeholder{height:calc(2.75rem + var(--status-bar-height));flex-shrink:0}.back-icon{width:1.25rem;height:1.25rem}.header-title{font-size:1rem;font-weight:700;color:#333}.header-right{width:1.25rem}.content-scroll{flex:1;overflow:hidden}.content-card{padding:.9375rem 1.25rem;line-height:1.6}.rich-text{font-size:.875rem;color:#333}.safe-area-inset-bottom{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/orders/appeal/index.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/orders/detail/index.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/cache/wgt/__UNI__76F5C47/pages/orders/index.css


BIN
unpackage/release/apk/__UNI__76F5C47__20260407145031.apk → unpackage/release/apk/__UNI__76F5C47__20260414222409.apk


+ 2 - 2
utils/config.js

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

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است