Răsfoiți Sursa

护理小结已添加

Huanyi 1 lună în urmă
părinte
comite
047f4826e9

+ 16 - 0
src/api/order/subOrder/index.ts

@@ -46,3 +46,19 @@ export const remarkSubOrder = (data: { orderId: string | number; remark: string;
         data
         data
     });
     });
 };
 };
+
+export const confirmSubOrder = (data: { id: string | number; }) => {
+    return request({
+        url: '/order/subOrder/confirm',
+        method: 'put',
+        data
+    });
+};
+
+export const nursingSummarySubOrder = (data: { orderId: string | number; content: string; }) => {
+    return request({
+        url: '/order/subOrder/nursingSummary',
+        method: 'put',
+        data
+    });
+};

+ 2 - 0
src/api/order/subOrder/types.ts

@@ -34,4 +34,6 @@ export interface SubOrderVO {
     detail?: any;
     detail?: any;
     serviceTime?: string;
     serviceTime?: string;
     remark?: string;
     remark?: string;
+    nursingSummary?: string;
+    nursingSummaryTime?: string;
 }
 }

+ 59 - 20
src/views/order/dispatch/components/DispatchDialog.vue

@@ -22,7 +22,9 @@
               <div class="row-addr" :title="order.address"><span class="tag home">址</span> {{ order.address }}</div>
               <div class="row-addr" :title="order.address"><span class="tag home">址</span> {{ order.address }}</div>
             </template>
             </template>
             <div class="row-time" style="margin-top: 4px">
             <div class="row-time" style="margin-top: 4px">
-              <el-icon><Clock /></el-icon> {{ order.time }}
+              <el-icon>
+                <Clock />
+              </el-icon> {{ order.time }}
               <span class="days-tag" v-if="order.daysLater">{{ order.daysLater }}</span>
               <span class="days-tag" v-if="order.daysLater">{{ order.daysLater }}</span>
             </div>
             </div>
           </div>
           </div>
@@ -34,7 +36,8 @@
         <div class="select-header" style="margin-bottom: 8px">
         <div class="select-header" style="margin-bottom: 8px">
           <span class="tit">当前派单履约者</span>
           <span class="tit">当前派单履约者</span>
         </div>
         </div>
-        <div class="list-card rider-card" style="margin-bottom: 20px; border: 1px solid #e4e7ed; background: #fafafa; cursor: default">
+        <div class="list-card rider-card"
+          style="margin-bottom: 20px; border: 1px solid #e4e7ed; background: #fafafa; cursor: default">
           <div class="card-left relative">
           <div class="card-left relative">
             <el-avatar :src="currentRider.avatar" :size="40" />
             <el-avatar :src="currentRider.avatar" :size="40" />
             <div class="dot" :class="currentRider.status"></div>
             <div class="dot" :class="currentRider.status"></div>
@@ -46,18 +49,21 @@
                 <span class="r-phone">{{ currentRider.maskPhone }}</span>
                 <span class="r-phone">{{ currentRider.maskPhone }}</span>
               </div>
               </div>
               <div class="status-right">
               <div class="status-right">
-                <span class="status-badge" :class="currentRider.status">{{ getRiderStatusText(currentRider.status) }}</span>
+                <span class="status-badge" :class="currentRider.status">{{ getRiderStatusText(currentRider.status)
+                  }}</span>
               </div>
               </div>
             </div>
             </div>
 
 
             <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
             <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
-              <span v-for="cat in currentRider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{ cat }}</span>
+              <span v-for="cat in currentRider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{
+                cat
+                }}</span>
             </div>
             </div>
 
 
             <div class="row-3 time-row" style="margin-top: 4px">
             <div class="row-3 time-row" style="margin-top: 4px">
-              <span class="last-time"
-                >下一单: {{ currentRider.status === 'offline' || currentRider.status === 'disabled' ? '--' : currentRider.lastServiceTime }}</span
-              >
+              <span class="last-time">下一单: {{ currentRider.status === 'offline' || currentRider.status === 'disabled' ?
+                '--' :
+                currentRider.lastServiceTime }}</span>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
@@ -67,19 +73,15 @@
       <div class="dispatch-rider-select">
       <div class="dispatch-rider-select">
         <div class="select-header">
         <div class="select-header">
           <span class="tit">选择履约者 (下一单时间由近及远排序)</span>
           <span class="tit">选择履约者 (下一单时间由近及远排序)</span>
-          <el-input v-model="searchQuery" placeholder="搜索履约者姓名/手机号" prefix-icon="Search" clearable style="width: 240px" />
+          <el-input v-model="searchQuery" placeholder="搜索履约者姓名/手机号" prefix-icon="Search" clearable
+            style="width: 240px" />
         </div>
         </div>
 
 
         <div class="rider-grid-wrapper">
         <div class="rider-grid-wrapper">
           <el-scrollbar height="400px">
           <el-scrollbar height="400px">
             <div class="rider-grid">
             <div class="rider-grid">
-              <div
-                v-for="rider in filteredRiders"
-                :key="rider.id"
-                class="list-card rider-card select-card"
-                :class="{ active: selectedId === rider.id }"
-                @click="selectedId = rider.id"
-              >
+              <div v-for="rider in filteredRiders" :key="rider.id" class="list-card rider-card select-card"
+                :class="{ active: selectedId === rider.id }" @click="selectedId = rider.id">
                 <div class="card-left relative">
                 <div class="card-left relative">
                   <el-avatar :src="rider.avatar" :size="40" />
                   <el-avatar :src="rider.avatar" :size="40" />
                   <div class="dot" :class="rider.status"></div>
                   <div class="dot" :class="rider.status"></div>
@@ -96,19 +98,22 @@
                   </div>
                   </div>
 
 
                   <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
                   <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
-                    <span v-for="cat in rider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{ cat }}</span>
+                    <span v-for="cat in rider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{
+                      cat
+                      }}</span>
                   </div>
                   </div>
 
 
                   <div class="row-3 time-row" style="margin-top: 4px">
                   <div class="row-3 time-row" style="margin-top: 4px">
-                    <span class="last-time"
-                      >下一单: {{ rider.status === 'offline' || rider.status === 'disabled' ? '--' : rider.lastServiceTime }}</span
-                    >
+                    <span class="last-time">下一单: {{ rider.status === 'offline' || rider.status === 'disabled' ? '--' :
+                      rider.lastServiceTime }}</span>
                   </div>
                   </div>
                 </div>
                 </div>
 
 
                 <!-- Selected Check -->
                 <!-- Selected Check -->
                 <div class="selected-mark" v-if="selectedId === rider.id">
                 <div class="selected-mark" v-if="selectedId === rider.id">
-                  <el-icon><Check /></el-icon>
+                  <el-icon>
+                    <Check />
+                  </el-icon>
                 </div>
                 </div>
               </div>
               </div>
 
 
@@ -225,6 +230,7 @@ const getCategoryClass = (cat) => {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
+
 .order-card .type-tag {
 .order-card .type-tag {
   width: 40px;
   width: 40px;
   height: 40px;
   height: 40px;
@@ -236,12 +242,15 @@ const getCategoryClass = (cat) => {
   font-size: 12px;
   font-size: 12px;
   font-weight: bold;
   font-weight: bold;
 }
 }
+
 .type-tag.transport {
 .type-tag.transport {
   background: #e6a23c;
   background: #e6a23c;
 }
 }
+
 .type-tag.feeding {
 .type-tag.feeding {
   background: #67c23a;
   background: #67c23a;
 }
 }
+
 .type-tag.washing {
 .type-tag.washing {
   background: #409eff;
   background: #409eff;
 }
 }
@@ -254,15 +263,18 @@ const getCategoryClass = (cat) => {
   justify-content: flex-start;
   justify-content: flex-start;
   gap: 4px;
   gap: 4px;
 }
 }
+
 .row-1 {
 .row-1 {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
+
 .o-type {
 .o-type {
   font-weight: bold;
   font-weight: bold;
   font-size: 14px;
   font-size: 14px;
   color: #303133;
   color: #303133;
 }
 }
+
 .row-2 {
 .row-2 {
   font-size: 12px;
   font-size: 12px;
   color: #606266;
   color: #606266;
@@ -270,6 +282,7 @@ const getCategoryClass = (cat) => {
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
 }
 }
+
 .row-3 {
 .row-3 {
   font-size: 12px;
   font-size: 12px;
   color: #909399;
   color: #909399;
@@ -287,6 +300,7 @@ const getCategoryClass = (cat) => {
   margin-left: 8px;
   margin-left: 8px;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
+
 .card-right .actions {
 .card-right .actions {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
@@ -302,12 +316,15 @@ const getCategoryClass = (cat) => {
   border-radius: 50%;
   border-radius: 50%;
   border: 2px solid #fff;
   border: 2px solid #fff;
 }
 }
+
 .dot.online {
 .dot.online {
   background: #67c23a;
   background: #67c23a;
 }
 }
+
 .dot.busy {
 .dot.busy {
   background: #409eff;
   background: #409eff;
 }
 }
+
 .dot.offline {
 .dot.offline {
   background: #909399;
   background: #909399;
 }
 }
@@ -317,6 +334,7 @@ const getCategoryClass = (cat) => {
   font-weight: bold;
   font-weight: bold;
   color: #303133;
   color: #303133;
 }
 }
+
 .r-phone {
 .r-phone {
   font-size: 12px;
   font-size: 12px;
   color: #909399;
   color: #909399;
@@ -329,16 +347,19 @@ const getCategoryClass = (cat) => {
   padding: 1px 4px;
   padding: 1px 4px;
   border-radius: 2px;
   border-radius: 2px;
 }
 }
+
 .cat-tag.cat-transport {
 .cat-tag.cat-transport {
   background: #e6f7ff;
   background: #e6f7ff;
   color: #1890ff;
   color: #1890ff;
   border: 1px solid #91d5ff;
   border: 1px solid #91d5ff;
 }
 }
+
 .cat-tag.cat-feeding {
 .cat-tag.cat-feeding {
   background: #f6ffed;
   background: #f6ffed;
   color: #52c41a;
   color: #52c41a;
   border: 1px solid #b7eb8f;
   border: 1px solid #b7eb8f;
 }
 }
+
 .cat-tag.cat-washing {
 .cat-tag.cat-washing {
   background: #fff0f6;
   background: #fff0f6;
   color: #eb2f96;
   color: #eb2f96;
@@ -352,18 +373,22 @@ const getCategoryClass = (cat) => {
   display: inline-block;
   display: inline-block;
   font-weight: bold;
   font-weight: bold;
 }
 }
+
 .status-badge.online {
 .status-badge.online {
   background: #f0f9eb;
   background: #f0f9eb;
   color: #67c23a;
   color: #67c23a;
 }
 }
+
 .status-badge.busy {
 .status-badge.busy {
   background: #ecf5ff;
   background: #ecf5ff;
   color: #409eff;
   color: #409eff;
 }
 }
+
 .status-badge.offline {
 .status-badge.offline {
   background: #f4f4f5;
   background: #f4f4f5;
   color: #909399;
   color: #909399;
 }
 }
+
 .status-badge.disabled {
 .status-badge.disabled {
   background: #fef0f0;
   background: #fef0f0;
   color: #f56c6c;
   color: #f56c6c;
@@ -381,12 +406,14 @@ const getCategoryClass = (cat) => {
   margin-bottom: 20px;
   margin-bottom: 20px;
   border: 1px solid #e4e7ed;
   border: 1px solid #e4e7ed;
 }
 }
+
 .dispatch-rider-select .select-header {
 .dispatch-rider-select .select-header {
   display: flex;
   display: flex;
   justify-content: space-between;
   justify-content: space-between;
   align-items: center;
   align-items: center;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
+
 .dispatch-rider-select .tit {
 .dispatch-rider-select .tit {
   font-weight: bold;
   font-weight: bold;
   font-size: 14px;
   font-size: 14px;
@@ -398,6 +425,7 @@ const getCategoryClass = (cat) => {
   gap: 12px;
   gap: 12px;
   padding-right: 10px;
   padding-right: 10px;
 }
 }
+
 .rider-card.select-card {
 .rider-card.select-card {
   cursor: pointer;
   cursor: pointer;
   border: 1px solid #dcdfe6;
   border: 1px solid #dcdfe6;
@@ -405,13 +433,16 @@ const getCategoryClass = (cat) => {
   transition: all 0.2s;
   transition: all 0.2s;
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
+
 .rider-card.select-card:hover {
 .rider-card.select-card:hover {
   border-color: #409eff;
   border-color: #409eff;
 }
 }
+
 .rider-card.select-card.active {
 .rider-card.select-card.active {
   border-color: #409eff;
   border-color: #409eff;
   background-color: #ecf5ff;
   background-color: #ecf5ff;
 }
 }
+
 .selected-mark {
 .selected-mark {
   position: absolute;
   position: absolute;
   top: 0;
   top: 0;
@@ -435,12 +466,14 @@ const getCategoryClass = (cat) => {
   justify-content: space-between;
   justify-content: space-between;
   align-items: center;
   align-items: center;
 }
 }
+
 .dispatch-footer .fee-input {
 .dispatch-footer .fee-input {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   gap: 8px;
   gap: 8px;
   font-size: 14px;
   font-size: 14px;
 }
 }
+
 .empty-text {
 .empty-text {
   text-align: center;
   text-align: center;
   color: #909399;
   color: #909399;
@@ -461,6 +494,7 @@ const getCategoryClass = (cat) => {
   text-overflow: ellipsis;
   text-overflow: ellipsis;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
+
 .row-addr .tag {
 .row-addr .tag {
   font-size: 11px;
   font-size: 11px;
   color: #fff;
   color: #fff;
@@ -469,15 +503,19 @@ const getCategoryClass = (cat) => {
   flex-shrink: 0;
   flex-shrink: 0;
   transform: scale(0.9);
   transform: scale(0.9);
 }
 }
+
 .tag.pick {
 .tag.pick {
   background: #409eff;
   background: #409eff;
 }
 }
+
 .tag.drop {
 .tag.drop {
   background: #e6a23c;
   background: #e6a23c;
 }
 }
+
 .tag.home {
 .tag.home {
   background: #67c23a;
   background: #67c23a;
 }
 }
+
 .row-time {
 .row-time {
   font-size: 12px;
   font-size: 12px;
   color: #909399;
   color: #909399;
@@ -485,6 +523,7 @@ const getCategoryClass = (cat) => {
   align-items: center;
   align-items: center;
   gap: 4px;
   gap: 4px;
 }
 }
+
 .days-tag {
 .days-tag {
   color: #f56c6c;
   color: #f56c6c;
   background: #fef0f0;
   background: #fef0f0;

+ 3 - 3
src/views/order/dispatch/index.vue

@@ -130,12 +130,12 @@ const getAreaStationList = async () => {
     const areaData = areaStationList.value.filter(item => Number(item.type) === 0 || Number(item.type) === 1)
     const areaData = areaStationList.value.filter(item => Number(item.type) === 0 || Number(item.type) === 1)
     areaOptions.value = buildTree(areaData, 0)
     areaOptions.value = buildTree(areaData, 0)
     siteOptions.value = []
     siteOptions.value = []
-    
+
     const allStations = areaStationList.value.filter(item => Number(item.type) === 2)
     const allStations = areaStationList.value.filter(item => Number(item.type) === 2)
     if (allStations.length > 0) {
     if (allStations.length > 0) {
       const randomStation = allStations[Math.floor(Math.random() * allStations.length)]
       const randomStation = allStations[Math.floor(Math.random() * allStations.length)]
       const areaId = randomStation.parentId
       const areaId = randomStation.parentId
-      
+
       const path = []
       const path = []
       let currentId = areaId
       let currentId = areaId
       while (currentId && String(currentId) !== '0') {
       while (currentId && String(currentId) !== '0') {
@@ -147,7 +147,7 @@ const getAreaStationList = async () => {
           break
           break
         }
         }
       }
       }
-      
+
       regionValue.value = path
       regionValue.value = path
       siteOptions.value = areaStationList.value
       siteOptions.value = areaStationList.value
         .filter(item => Number(item.type) === 2 && String(item.parentId) === String(areaId))
         .filter(item => Number(item.type) === 2 && String(item.parentId) === String(areaId))

+ 350 - 188
src/views/order/orderList/components/CareSummaryDrawer.vue

@@ -1,143 +1,144 @@
 <template>
 <template>
-    <el-drawer
-        v-model="drawerVisible"
-        title="宠物护理工作小结"
-        direction="rtl"
-        size="750px"
-        destroy-on-close
-        class="care-summary-drawer"
-    >
+    <el-drawer v-model="drawerVisible" title="宠物护理工作小结" direction="rtl" size="750px" destroy-on-close
+        class="care-summary-drawer">
         <div class="care-summary-container" v-if="order">
         <div class="care-summary-container" v-if="order">
-             <!-- Pet Header -->
-             <div class="summary-header">
-                  <div class="avatar-wrapper">
-                      <el-avatar :size="80" :src="order.petAvatar" shape="circle" class="pet-summary-avatar">{{ order.petName?.charAt(0) }}</el-avatar>
-                  </div>
-                  <div class="pet-summary-info">
-                       <div class="summary-name-row">
-                           <span class="name">{{ order.petName }}</span>
-                           <div class="tags-group">
-                               <el-tag :type="order.petGender==='male'?'':'danger'" effect="light" round>
-                                   <el-icon><component :is="order.petGender==='male'?'Male':'Female'" /></el-icon>
-                                   {{ order.petAge }}
-                               </el-tag>
-                               <el-tag v-for="tag in (order.petTags||[])" :key="tag" type="warning" effect="plain" round>{{ tag }}</el-tag>
-                           </div>
-                       </div>
-                       <div class="summary-sub-row">
-                           <div class="info-item">
-                               <span class="lbl">品种</span>
-                               <span class="val">{{ order.petBreed || '未知' }}</span>
-                           </div>
-                           <div class="divider-v"></div>
-                           <div class="info-item">
-                               <span class="lbl">体重</span>
-                               <span class="val">{{ order.petWeight }}</span>
-                           </div>
-                           <div class="divider-v"></div>
-                           <div class="info-item">
-                               <span class="lbl">主人</span>
-                               <span class="val">{{ order.userName || '未知' }}</span>
-                           </div>
-                       </div>
-                  </div>
-             </div>
-
-             <!-- Info Groups -->
-             <div class="summary-section">
-                  <div class="sec-title">
-                      <span class="icon-box"><el-icon><List /></el-icon></span> 
-                      基本信息
-                  </div>
-                  <el-descriptions :column="2" border class="spacious-desc">
-                      <el-descriptions-item label="性格关键词">{{ order.petPersonality }}</el-descriptions-item>
-                      <el-descriptions-item label="健康状况">
-                          <el-tag :type="order.healthStatus==='健康'?'success':'danger'" effect="light" size="small">{{ order.healthStatus }}</el-tag>
-                      </el-descriptions-item>
-                      <el-descriptions-item label="疫苗情况">
-                          <div class="flex-align">
-                              <span style="color:#67c23a; margin-right:8px;" v-if="order.vaccineImg"><el-icon><CircleCheckFilled /></el-icon> 已接种</span>
-                              <span v-else style="color:#909399;">未接种</span>
-                              <el-image 
-                                v-if="order.vaccineImg"
+            <!-- Pet Header -->
+            <div class="summary-header">
+                <div class="avatar-wrapper">
+                    <el-avatar :size="80" :src="order.petAvatar" shape="circle" class="pet-summary-avatar">{{
+                        order.petName?.charAt(0) }}</el-avatar>
+                </div>
+                <div class="pet-summary-info">
+                    <div class="summary-name-row">
+                        <span class="name">{{ order.petName }}</span>
+                        <div class="tags-group">
+                            <dict-tag :options="sys_pet_gender" :value="order.petGender" />
+                            <el-tag type="info" effect="light" round>
+                                {{ order.petAge }}
+                            </el-tag>
+                            <el-tag v-for="tag in (order.petTags || [])" :key="tag" type="warning" effect="plain"
+                                round>{{ tag }}</el-tag>
+                        </div>
+                    </div>
+                    <div class="summary-sub-row">
+                        <div class="info-item">
+                            <span class="lbl">品种</span>
+                            <span class="val">{{ order.petBreed || '未知' }}</span>
+                        </div>
+                        <div class="divider-v"></div>
+                        <div class="info-item">
+                            <span class="lbl">体重</span>
+                            <span class="val">{{ order.petWeight }}</span>
+                        </div>
+                        <div class="divider-v"></div>
+                        <div class="info-item">
+                            <span class="lbl">主人</span>
+                            <span class="val">{{ order.userName || '未知' }}</span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- Info Groups -->
+            <div class="summary-section">
+                <div class="sec-title">
+                    <span class="icon-box"><el-icon>
+                            <List />
+                        </el-icon></span>
+                    基本信息
+                </div>
+                <el-descriptions :column="2" border class="spacious-desc">
+                    <el-descriptions-item label="性格关键词">{{ order.petPersonality }}</el-descriptions-item>
+                    <el-descriptions-item label="健康状况">
+                        <el-tag :type="order.healthStatus === '健康' ? 'success' : 'danger'" effect="light"
+                            size="small">{{ order.healthStatus }}</el-tag>
+                    </el-descriptions-item>
+                    <el-descriptions-item label="疫苗情况">
+                        <div class="flex-align">
+                            <span style="color:#67c23a; margin-right:8px;" v-if="order.vaccineImg"><el-icon>
+                                    <CircleCheckFilled />
+                                </el-icon> 已接种</span>
+                            <span v-else style="color:#909399;">未接种</span>
+                            <el-image v-if="order.vaccineImg"
                                 style="width: 24px; height: 24px; border-radius:4px; vertical-align:middle; cursor:zoom-in;"
                                 style="width: 24px; height: 24px; border-radius:4px; vertical-align:middle; cursor:zoom-in;"
-                                :src="order.vaccineImg"
-                                :preview-src-list="[order.vaccineImg]"
-                                :preview-teleported="true"
-                              />
-                          </div>
-                      </el-descriptions-item>
-                      <el-descriptions-item label="过敏史">
-                          <span :style="{color: order.allergy ? '#f56c6c' : 'inherit'}">{{ order.allergy || '无' }}</span>
-                      </el-descriptions-item>
-                  </el-descriptions>
-             </div>
-
-             <div class="summary-section">
-                  <div class="sec-title">
-                      <span class="icon-box text-blue"><el-icon><HomeFilled /></el-icon></span>
-                      服务环境
-                  </div>
-                   <el-descriptions :column="2" border class="spacious-desc">
-                      <el-descriptions-item label="到家时间">{{ order.homeTime }}</el-descriptions-item>
-                      <el-descriptions-item label="房屋类型">{{ order.houseType }}</el-descriptions-item>
-                      <el-descriptions-item label="入户方式" :span="2">
-                          <span style="font-weight:bold;">{{ order.entryMethod }}</span> 
-                          <span style="margin-left:8px; color:#909399;">({{ order.entryDetail }})</span>
-                      </el-descriptions-item>
-                  </el-descriptions>
-             </div>
-
-             <!-- Service Log -->
-             <div class="summary-section main-log">
-                  <div class="sec-title" style="border:none; padding-left:0; margin-bottom:16px;">
-                      <div class="left">
-                          <span class="icon-box text-orange"><el-icon><Notebook /></el-icon></span>
-                          服务内容记录
-                      </div>
-                      <el-button v-if="!isEditingSummary" type="primary" link icon="Edit" @click="isEditingSummary = true">编辑</el-button>
-                  </div>
-                  
-                  <div v-if="isEditingSummary" class="edit-area">
-                      <el-input 
-                        v-model="careSummaryText" 
-                        type="textarea" 
-                        :rows="12" 
-                        placeholder="请输入详细的护理服务小结..."
-                        resize="none"
-                      />
-                      <div class="edit-actions">
-                          <el-button @click="isEditingSummary = false">取消</el-button>
-                          <el-button type="primary" @click="saveCareSummary">保存内容</el-button>
-                      </div>
-                  </div>
-                  <div v-else class="log-content-box">
-                      <pre class="log-text">{{ careSummaryText }}</pre>
-                  </div>
-             </div>
-             
-             <!-- Footer Info -->
-             <div class="summary-footer">
-                 <div class="footer-info">
-                     <div class="f-row">
-                         <span class="lbl">护宠师</span>
-                         <span class="val user-active">{{ order.fulfillerName || '当前履约者' }}</span>
-                     </div>
-                     <div class="f-row">
-                         <span class="lbl">提交时间</span>
-                         <span class="val">{{ order.summaryTime || '2024-02-04 17:00' }}</span>
-                     </div>
-                 </div>
-                 <div class="footer-action">
-                     <el-button size="large" @click="drawerVisible = false">关闭</el-button>
-                 </div>
-             </div>
+                                :src="order.vaccineImg" :preview-src-list="[order.vaccineImg]"
+                                :preview-teleported="true" />
+                        </div>
+                    </el-descriptions-item>
+                    <el-descriptions-item label="过敏史">
+                        <span :style="{ color: order.allergy ? '#f56c6c' : 'inherit' }">{{ order.allergy || '无'
+                        }}</span>
+                    </el-descriptions-item>
+                </el-descriptions>
+            </div>
+
+            <div class="summary-section">
+                <div class="sec-title">
+                    <span class="icon-box text-blue"><el-icon>
+                            <HomeFilled />
+                        </el-icon></span>
+                    服务环境
+                </div>
+                <el-descriptions :column="2" border class="spacious-desc">
+                    <el-descriptions-item label="到家时间">{{ order.homeTime }}</el-descriptions-item>
+                    <el-descriptions-item label="房屋类型">
+                        <dict-tag :options="sys_house_type" :value="order.houseType" />
+                    </el-descriptions-item>
+                    <el-descriptions-item label="入户方式" :span="2">
+                        <dict-tag :options="sys_entry_method" :value="order.entryMethod" />
+                        <span style="margin-left:8px; color:#909399;">({{ order.entryDetail }})</span>
+                    </el-descriptions-item>
+                </el-descriptions>
+            </div>
+
+            <!-- Service Log -->
+            <div class="summary-section main-log">
+                <div class="sec-title" style="border:none; padding-left:0; margin-bottom:16px;">
+                    <div class="left">
+                        <span class="icon-box text-orange"><el-icon>
+                                <Notebook />
+                            </el-icon></span>
+                        服务内容记录
+                    </div>
+                    <el-button v-if="!isEditingSummary" type="primary" link icon="Edit"
+                        @click="isEditingSummary = true">编辑</el-button>
+                </div>
+
+                <div v-if="isEditingSummary" class="edit-area">
+                    <el-input v-model="careSummaryText" type="textarea" :rows="12" placeholder="请输入详细的护理服务小结..."
+                        resize="none" />
+                    <div class="edit-actions">
+                        <el-button @click="isEditingSummary = false">取消</el-button>
+                        <el-button type="primary" @click="saveCareSummary">保存内容</el-button>
+                    </div>
+                </div>
+                <div v-else class="log-content-box">
+                    <pre class="log-text">{{ careSummaryText }}</pre>
+                </div>
+            </div>
+
+            <!-- Footer Info -->
+            <div class="summary-footer">
+                <div class="footer-info">
+                    <div class="f-row">
+                        <span class="lbl">护宠师</span>
+                        <span class="val user-active">{{ order.fulfillerName || '当前履约者' }}</span>
+                    </div>
+                    <div class="f-row">
+                        <span class="lbl">提交时间</span>
+                        <span class="val">{{ order.summaryTime || '2024-02-04 17:00' }}</span>
+                    </div>
+                </div>
+                <div class="footer-action">
+                    <el-button size="large" @click="drawerVisible = false">关闭</el-button>
+                </div>
+            </div>
         </div>
         </div>
     </el-drawer>
     </el-drawer>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, computed, watch } from 'vue'
+import { ref, computed, watch, getCurrentInstance, toRefs } from 'vue'
 
 
 const props = defineProps({
 const props = defineProps({
     visible: Boolean,
     visible: Boolean,
@@ -145,6 +146,11 @@ const props = defineProps({
 })
 })
 const emit = defineEmits(['update:visible', 'submit'])
 const emit = defineEmits(['update:visible', 'submit'])
 
 
+const { proxy } = getCurrentInstance()
+const { sys_pet_gender, sys_house_type, sys_entry_method } = toRefs(
+    proxy?.useDict('sys_pet_gender', 'sys_house_type', 'sys_entry_method')
+)
+
 const drawerVisible = computed({
 const drawerVisible = computed({
     get: () => props.visible,
     get: () => props.visible,
     set: (val) => emit('update:visible', val)
     set: (val) => emit('update:visible', val)
@@ -156,16 +162,7 @@ const isEditingSummary = ref(false)
 watch(() => props.visible, (val) => {
 watch(() => props.visible, (val) => {
     if (val && props.order) {
     if (val && props.order) {
         isEditingSummary.value = false
         isEditingSummary.value = false
-        if (!props.order.careSummary) {
-            careSummaryText.value = `1. 精神/身体状态:${props.order.petName}精神状态良好,愿意互动。
-2. 进食/饮水:食欲正常,饮水适当,已清洗碗具。
-3. 排泄情况:排便正常,颜色形状正常,已清理。
-4. 卫生情况:猫砂盆/地面已清理干净,无异味。
-5. 互动情况:陪玩了20分钟,${props.order.petName}很开心。
-6. 特殊情况/备注:无特殊异常。`
-        } else {
-            careSummaryText.value = props.order.careSummary
-        }
+        careSummaryText.value = props.order.careSummary || ''
     }
     }
 })
 })
 
 
@@ -177,71 +174,236 @@ const saveCareSummary = () => {
 
 
 <style scoped>
 <style scoped>
 /* Enhanced Care Summary Styles */
 /* Enhanced Care Summary Styles */
-.care-summary-drawer :deep(.el-drawer__header) { margin-bottom: 0; padding: 20px 24px; border-bottom: 1px solid #f0f0f0; }
-.care-summary-drawer :deep(.el-drawer__body) { padding: 0; overflow-y: auto; background: #fff; }
+.care-summary-drawer :deep(.el-drawer__header) {
+    margin-bottom: 0;
+    padding: 20px 24px;
+    border-bottom: 1px solid #f0f0f0;
+}
+
+.care-summary-drawer :deep(.el-drawer__body) {
+    padding: 0;
+    overflow-y: auto;
+    background: #fff;
+}
 
 
-.care-summary-container { padding: 32px 40px; }
+.care-summary-container {
+    padding: 32px 40px;
+}
 
 
 /* 1. Header */
 /* 1. Header */
-.summary-header { display: flex; gap: 24px; align-items: flex-start; margin-bottom: 32px; padding-bottom: 24px; border-bottom: 1px dashed #e4e7ed; }
-.avatar-wrapper { border: 4px solid #f2f6fc; border-radius: 50%; }
-.pet-summary-info { flex: 1; display:flex; flex-direction:column; gap:12px; padding-top: 4px; }
+.summary-header {
+    display: flex;
+    gap: 24px;
+    align-items: flex-start;
+    margin-bottom: 32px;
+    padding-bottom: 24px;
+    border-bottom: 1px dashed #e4e7ed;
+}
+
+.avatar-wrapper {
+    border: 4px solid #f2f6fc;
+    border-radius: 50%;
+}
 
 
-.summary-name-row { display: flex; align-items: center; gap: 16px; margin-bottom: 4px; }
-.summary-name-row .name { font-size: 24px; font-weight: 800; color: #303133; letter-spacing: 0.5px; }
-.tags-group { display: flex; gap: 8px; align-items: center; }
+.pet-summary-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 12px;
+    padding-top: 4px;
+}
 
 
-.summary-sub-row { display: flex; align-items: center; background: #f9fafe; padding: 10px 16px; border-radius: 8px; align-self: flex-start; }
-.info-item { display: flex; flex-direction: column; gap: 2px; }
-.info-item .lbl { font-size: 11px; color: #909399; text-transform: uppercase; }
-.info-item .val { font-size: 14px; font-weight: bold; color: #606266; }
-.divider-v { width: 1px; height: 24px; background: #ebeef5; margin: 0 16px; }
+.summary-name-row {
+    display: flex;
+    align-items: center;
+    gap: 16px;
+    margin-bottom: 4px;
+}
+
+.summary-name-row .name {
+    font-size: 24px;
+    font-weight: 800;
+    color: #303133;
+    letter-spacing: 0.5px;
+}
+
+.tags-group {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+}
+
+.summary-sub-row {
+    display: flex;
+    align-items: center;
+    background: #f9fafe;
+    padding: 10px 16px;
+    border-radius: 8px;
+    align-self: flex-start;
+}
+
+.info-item {
+    display: flex;
+    flex-direction: column;
+    gap: 2px;
+}
+
+.info-item .lbl {
+    font-size: 11px;
+    color: #909399;
+    text-transform: uppercase;
+}
+
+.info-item .val {
+    font-size: 14px;
+    font-weight: bold;
+    color: #606266;
+}
+
+.divider-v {
+    width: 1px;
+    height: 24px;
+    background: #ebeef5;
+    margin: 0 16px;
+}
 
 
 /* 2. Sections */
 /* 2. Sections */
-.summary-section { margin-bottom: 40px; }
-.sec-title { 
-    font-size: 16px; font-weight: 700; color: #303133; margin-bottom: 16px; 
-    display:flex; align-items:center; gap:8px;
+.summary-section {
+    margin-bottom: 40px;
+}
+
+.sec-title {
+    font-size: 16px;
+    font-weight: 700;
+    color: #303133;
+    margin-bottom: 16px;
+    display: flex;
+    align-items: center;
+    gap: 8px;
     justify-content: space-between;
     justify-content: space-between;
 }
 }
-.sec-title .left { display: flex; align-items: center; gap: 8px; }
-.icon-box { 
-    width: 28px; height: 28px; background: #ecf5ff; color: #409eff; border-radius: 6px; 
-    display: flex; align-items: center; justify-content: center; font-size: 16px;
+
+.sec-title .left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+}
+
+.icon-box {
+    width: 28px;
+    height: 28px;
+    background: #ecf5ff;
+    color: #409eff;
+    border-radius: 6px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 16px;
+}
+
+.icon-box.text-blue {
+    background: #ecf5ff;
+    color: #409eff;
+}
+
+.icon-box.text-orange {
+    background: #fdf6ec;
+    color: #e6a23c;
 }
 }
-.icon-box.text-blue { background: #ecf5ff; color: #409eff; }
-.icon-box.text-orange { background: #fdf6ec; color: #e6a23c; }
 
 
 /* 3. Descriptions */
 /* 3. Descriptions */
-.spacious-desc :deep(.el-descriptions__cell) { padding: 12px 16px!important; }
-.spacious-desc :deep(.el-descriptions__label) { width: 100px; color: #606266; font-weight: 500; background: #fafafa; }
-.flex-align { display: flex; align-items: center; }
+.spacious-desc :deep(.el-descriptions__cell) {
+    padding: 12px 16px !important;
+}
+
+.spacious-desc :deep(.el-descriptions__label) {
+    width: 100px;
+    color: #606266;
+    font-weight: 500;
+    background: #fafafa;
+}
+
+.flex-align {
+    display: flex;
+    align-items: center;
+}
 
 
 /* 4. Log Area */
 /* 4. Log Area */
-.main-log { background: #fff; }
-.log-content-box { 
-    background: #fff; 
-    border: 1px solid #ebeef5; border-radius: 8px; 
-    padding: 24px; 
-    box-shadow: 0 2px 12px rgba(0,0,0,0.02);
+.main-log {
+    background: #fff;
+}
+
+.log-content-box {
+    background: #fff;
+    border: 1px solid #ebeef5;
+    border-radius: 8px;
+    padding: 24px;
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.02);
     position: relative;
     position: relative;
 }
 }
+
 .log-content-box::before {
 .log-content-box::before {
-    content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: #e6a23c; border-top-left-radius: 8px; border-bottom-left-radius: 8px;
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 4px;
+    height: 100%;
+    background: #e6a23c;
+    border-top-left-radius: 8px;
+    border-bottom-left-radius: 8px;
 }
 }
-.log-text { 
-    white-space: pre-wrap; font-family: 'Inter', system-ui, sans-serif; margin: 0; line-height: 1.8; font-size: 15px; color: #303133; text-align: justify;
+
+.log-text {
+    white-space: pre-wrap;
+    font-family: 'Inter', system-ui, sans-serif;
+    margin: 0;
+    line-height: 1.8;
+    font-size: 15px;
+    color: #303133;
+    text-align: justify;
+}
+
+.edit-actions {
+    display: flex;
+    justify-content: flex-end;
+    gap: 12px;
+    margin-top: 12px;
 }
 }
-.edit-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 12px; }
 
 
 /* 5. Footer */
 /* 5. Footer */
-.summary-footer { 
-    margin-top: 60px; padding-top: 24px; border-top: 1px solid #ebeef5; 
-    display: flex; justify-content: space-between; align-items: center;
-}
-.footer-info { display: flex; gap: 32px; }
-.f-row { display: flex; flex-direction: column; gap: 4px; }
-.f-row .lbl { font-size: 12px; color: #909399; }
-.f-row .val { font-size: 15px; font-weight: 600; color: #303133; }
-.f-row .val.user-active { color: #409eff; }
+.summary-footer {
+    margin-top: 60px;
+    padding-top: 24px;
+    border-top: 1px solid #ebeef5;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.footer-info {
+    display: flex;
+    gap: 32px;
+}
+
+.f-row {
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+}
+
+.f-row .lbl {
+    font-size: 12px;
+    color: #909399;
+}
+
+.f-row .val {
+    font-size: 15px;
+    font-weight: 600;
+    color: #303133;
+}
+
+.f-row .val.user-active {
+    color: #409eff;
+}
 </style>
 </style>

+ 26 - 22
src/views/order/orderList/components/OrderDetailDrawer.vue

@@ -15,7 +15,7 @@
                 <div class="right-head">
                 <div class="right-head">
                     <!-- Action Buttons Group -->
                     <!-- Action Buttons Group -->
                     <div class="detail-actions">
                     <div class="detail-actions">
-                        <template v-if="[0, 1, 2].includes(order.status)">
+                        <template v-if="[0, 1, 2, 3].includes(order.status)">
                             <el-button type="success" icon="Bicycle" @click="emit('dispatch', order)">
                             <el-button type="success" icon="Bicycle" @click="emit('dispatch', order)">
                                 {{ order.fulfiller || order.fulfillerName ? '重新派单' : '立即派单' }}
                                 {{ order.fulfiller || order.fulfillerName ? '重新派单' : '立即派单' }}
                             </el-button>
                             </el-button>
@@ -26,12 +26,12 @@
                                 @click="emit('cancel', order)">取消订单</el-button>
                                 @click="emit('cancel', order)">取消订单</el-button>
                         </template>
                         </template>
 
 
-                        <template v-if="order.status === 3">
+                        <template v-if="order.status === 4">
                             <el-button type="primary" icon="CircleCheck"
                             <el-button type="primary" icon="CircleCheck"
                                 @click="emit('command', 'complete', order)">确认完成</el-button>
                                 @click="emit('command', 'complete', order)">确认完成</el-button>
                         </template>
                         </template>
 
 
-                        <template v-if="[3, 4].includes(order.status)">
+                        <template v-if="[4, 5].includes(order.status)">
                             <el-button icon="Notebook" @click="emit('care-summary', order)">护理小结</el-button>
                             <el-button icon="Notebook" @click="emit('care-summary', order)">护理小结</el-button>
                         </template>
                         </template>
 
 
@@ -42,7 +42,7 @@
                                 <el-dropdown-menu>
                                 <el-dropdown-menu>
                                     <el-dropdown-item command="reward" icon="Trophy">奖惩操作</el-dropdown-item>
                                     <el-dropdown-item command="reward" icon="Trophy">奖惩操作</el-dropdown-item>
                                     <el-dropdown-item command="remark" icon="EditPen">订单备注</el-dropdown-item>
                                     <el-dropdown-item command="remark" icon="EditPen">订单备注</el-dropdown-item>
-                                    <el-dropdown-item command="delete" v-if="[5, 4].includes(order.status)" divided
+                                    <el-dropdown-item command="delete" v-if="[5, 6].includes(order.status)" divided
                                         icon="Delete" style="color: #f56c6c;">删除订单</el-dropdown-item>
                                         icon="Delete" style="color: #f56c6c;">删除订单</el-dropdown-item>
                                 </el-dropdown-menu>
                                 </el-dropdown-menu>
                             </template>
                             </template>
@@ -89,9 +89,9 @@
                         </div>
                         </div>
                         <el-descriptions :column="2" size="small" class="pet-desc" border>
                         <el-descriptions :column="2" size="small" class="pet-desc" border>
                             <el-descriptions-item label="绝育状态">{{ order.petSterilized ? '已绝育' : '未绝育'
                             <el-descriptions-item label="绝育状态">{{ order.petSterilized ? '已绝育' : '未绝育'
-                            }}</el-descriptions-item>
+                                }}</el-descriptions-item>
                             <el-descriptions-item label="疫苗状态"><span style="color:#67c23a">{{ order.petVaccine || '未知'
                             <el-descriptions-item label="疫苗状态"><span style="color:#67c23a">{{ order.petVaccine || '未知'
-                            }}</span></el-descriptions-item>
+                                    }}</span></el-descriptions-item>
                             <el-descriptions-item label="性格特点">{{ order.petCharacter || '温顺' }}</el-descriptions-item>
                             <el-descriptions-item label="性格特点">{{ order.petCharacter || '温顺' }}</el-descriptions-item>
                             <el-descriptions-item label="健康状况">{{ order.petHealth || '健康' }}</el-descriptions-item>
                             <el-descriptions-item label="健康状况">{{ order.petHealth || '健康' }}</el-descriptions-item>
                         </el-descriptions>
                         </el-descriptions>
@@ -105,7 +105,7 @@
                         <div class="user-content">
                         <div class="user-content">
                             <div class="u-row">
                             <div class="u-row">
                                 <el-avatar :size="40" :src="order.userAvatar">{{ (order.userName || '').charAt(0)
                                 <el-avatar :size="40" :src="order.userAvatar">{{ (order.userName || '').charAt(0)
-                                }}</el-avatar>
+                                    }}</el-avatar>
                                 <div class="u-info">
                                 <div class="u-info">
                                     <div class="nm">{{ order.userName }}</div>
                                     <div class="nm">{{ order.userName }}</div>
                                     <div class="ph">{{ order.contactPhone }}</div>
                                     <div class="ph">{{ order.contactPhone }}</div>
@@ -138,15 +138,15 @@
                                     <el-descriptions-item label="归属门店">{{ order.merchantName }}
                                     <el-descriptions-item label="归属门店">{{ order.merchantName }}
                                         ({{ Number(order.platformId) === 1 ? '门店下单' : '平台代下单' }})</el-descriptions-item>
                                         ({{ Number(order.platformId) === 1 ? '门店下单' : '平台代下单' }})</el-descriptions-item>
                                     <el-descriptions-item label="宠主信息">{{ order.userName }} / {{ order.contactPhone
                                     <el-descriptions-item label="宠主信息">{{ order.userName }} / {{ order.contactPhone
-                                    }}</el-descriptions-item>
+                                        }}</el-descriptions-item>
                                     <el-descriptions-item label="服务费用" label-class-name="money-label">
                                     <el-descriptions-item label="服务费用" label-class-name="money-label">
                                         <span style="color:#f56c6c; font-weight:bold;">¥ {{ order.fulfillerFee }}</span>
                                         <span style="color:#f56c6c; font-weight:bold;">¥ {{ order.fulfillerFee }}</span>
                                     </el-descriptions-item>
                                     </el-descriptions-item>
 
 
                                     <el-descriptions-item label="预约时间">{{ getServiceTimeRange(order.serviceTime)
                                     <el-descriptions-item label="预约时间">{{ getServiceTimeRange(order.serviceTime)
-                                    }}</el-descriptions-item>
+                                        }}</el-descriptions-item>
                                     <el-descriptions-item label="团购套餐">{{ order.groupBuyPackage || '未使用团购套餐'
                                     <el-descriptions-item label="团购套餐">{{ order.groupBuyPackage || '未使用团购套餐'
-                                    }}</el-descriptions-item>
+                                        }}</el-descriptions-item>
                                     <el-descriptions-item label="创建时间">{{ order.createTime }}</el-descriptions-item>
                                     <el-descriptions-item label="创建时间">{{ order.createTime }}</el-descriptions-item>
 
 
                                     <el-descriptions-item label="订单备注" :span="3">
                                     <el-descriptions-item label="订单备注" :span="3">
@@ -166,7 +166,7 @@
                                     <div class="t-row">
                                     <div class="t-row">
                                         <span class="t-k">起点</span>
                                         <span class="t-k">起点</span>
                                         <span class="t-v">{{ order.detail?.fromAddress || order.detail?.pickAddr || '--'
                                         <span class="t-v">{{ order.detail?.fromAddress || order.detail?.pickAddr || '--'
-                                            }}</span>
+                                        }}</span>
                                     </div>
                                     </div>
                                     <div class="t-row">
                                     <div class="t-row">
                                         <span class="t-k">终点</span>
                                         <span class="t-k">终点</span>
@@ -186,7 +186,7 @@
                                 <div class="sec-title-bar">服务执行要求</div>
                                 <div class="sec-title-bar">服务执行要求</div>
                                 <el-descriptions :column="2" border size="default" class="custom-desc">
                                 <el-descriptions :column="2" border size="default" class="custom-desc">
                                     <el-descriptions-item label="服务地址" :span="2">{{ order.detail.area || order.address
                                     <el-descriptions-item label="服务地址" :span="2">{{ order.detail.area || order.address
-                                    }}</el-descriptions-item>
+                                        }}</el-descriptions-item>
                                 </el-descriptions>
                                 </el-descriptions>
                             </div>
                             </div>
                         </div>
                         </div>
@@ -198,7 +198,7 @@
                             <div v-if="order.fulfillerName" class="fulfiller-card">
                             <div v-if="order.fulfillerName" class="fulfiller-card">
                                 <div class="f-left">
                                 <div class="f-left">
                                     <el-avatar :size="60" :src="order.fulfillerAvatar">{{ order.fulfillerName.charAt(0)
                                     <el-avatar :size="60" :src="order.fulfillerAvatar">{{ order.fulfillerName.charAt(0)
-                                    }}</el-avatar>
+                                        }}</el-avatar>
                                 </div>
                                 </div>
                                 <div class="f-right">
                                 <div class="f-right">
                                     <div class="f-row1">
                                     <div class="f-row1">
@@ -383,11 +383,11 @@ watch(() => props.order, (val) => {
 const activeDetailTab = ref('basic')
 const activeDetailTab = ref('basic')
 
 
 const getStatusName = (status) => {
 const getStatusName = (status) => {
-    const map = { 0: '待派单', 1: '待接单', 2: '服务中', 3: '待商家确认', 4: '已完成', 5: '已取消' }
+    const map = { 0: '待派单', 1: '待接单', 2: '待服务', 3: '服务中', 4: '待商家确认', 5: '已完成', 6: '已取消' }
     return map[status] || '未知'
     return map[status] || '未知'
 }
 }
 const getStatusTag = (status) => {
 const getStatusTag = (status) => {
-    const map = { 0: 'danger', 1: 'warning', 2: 'primary', 3: 'warning', 4: 'success', 5: 'info' }
+    const map = { 0: 'danger', 1: 'warning', 2: 'primary', 3: 'primary', 4: 'warning', 5: 'success', 6: 'info' }
     return map[status] || 'info'
     return map[status] || 'info'
 }
 }
 const getTypeName = (type) => {
 const getTypeName = (type) => {
@@ -445,33 +445,37 @@ const currentOrderSteps = computed(() => {
     } else {
     } else {
         steps[1].time = findTime('派单') || ''
         steps[1].time = findTime('派单') || ''
     }
     }
-    if ([1, 2, 3, 4].includes(status)) active = 2
+    if ([1, 2, 3, 4, 5].includes(status)) active = 2
     steps[2].time = findTime('接单')
     steps[2].time = findTime('接单')
     if ([1].includes(status)) {
     if ([1].includes(status)) {
         steps[2].title = '待履约者接单'
         steps[2].title = '待履约者接单'
-    } else if ([2, 3, 4].includes(status)) {
+    } else if ([2, 3, 4, 5].includes(status)) {
         steps[2].title = '履约者已接单'
         steps[2].title = '履约者已接单'
         active = 3
         active = 3
     }
     }
     steps[3].time = findTime('到达') || findTime('出发')
     steps[3].time = findTime('到达') || findTime('出发')
     if ([2].includes(status)) {
     if ([2].includes(status)) {
+        steps[3].title = '待服务'
+    } else if ([3].includes(status)) {
         steps[3].title = '服务进行中'
         steps[3].title = '服务进行中'
-    } else if ([3, 4].includes(status)) {
+        active = 4
+    } else if ([4, 5].includes(status)) {
         steps[3].title = '服务已完成'
         steps[3].title = '服务已完成'
         active = 4
         active = 4
     }
     }
     steps[4].time = findTime('等待商家确认') || findTime('待验收')
     steps[4].time = findTime('等待商家确认') || findTime('待验收')
-    if ([3].includes(status)) {
+    if ([4].includes(status)) {
         steps[4].title = '待商家确认'
         steps[4].title = '待商家确认'
-    } else if ([4].includes(status)) {
+        active = 5
+    } else if ([5].includes(status)) {
         steps[4].title = '商家已确认'
         steps[4].title = '商家已确认'
         active = 5
         active = 5
     }
     }
-    if (status === 4) {
+    if (status === 5) {
         steps[5].time = findTime('完成')
         steps[5].time = findTime('完成')
         active = 6
         active = 6
     }
     }
-    if (status === 5) {
+    if (status === 6) {
         return {
         return {
             active: 1,
             active: 1,
             steps: [
             steps: [

+ 88 - 34
src/views/order/orderList/index.vue

@@ -20,10 +20,11 @@
           <el-tab-pane label="全部订单" name="" />
           <el-tab-pane label="全部订单" name="" />
           <el-tab-pane label="待派单" name="0" />
           <el-tab-pane label="待派单" name="0" />
           <el-tab-pane label="待接单" name="1" />
           <el-tab-pane label="待接单" name="1" />
-          <el-tab-pane label="服务中" name="2" />
-          <el-tab-pane label="待商家确认" name="3" />
-          <el-tab-pane label="已完成" name="4" />
-          <el-tab-pane label="已取消" name="5" />
+          <el-tab-pane label="待服务" name="2" />
+          <el-tab-pane label="服务中" name="3" />
+          <el-tab-pane label="待商家确认" name="4" />
+          <el-tab-pane label="已完成" name="5" />
+          <el-tab-pane label="已取消" name="6" />
         </el-tabs>
         </el-tabs>
       </template>
       </template>
 
 
@@ -106,7 +107,8 @@
           <template #default="{ row }">
           <template #default="{ row }">
             <div v-if="row.fulfillerName" class="fulfiller-info">
             <div v-if="row.fulfillerName" class="fulfiller-info">
               <span class="fulfiller-name">{{ row.fulfillerName }}</span>
               <span class="fulfiller-name">{{ row.fulfillerName }}</span>
-              <span class="fulfiller-fee" v-if="row.price !== null && row.price !== undefined">¥{{ row.price / 100.0 }}</span>
+              <span class="fulfiller-fee" v-if="row.price !== null && row.price !== undefined">¥{{ row.price / 100.0
+              }}</span>
             </div>
             </div>
             <span v-else class="text-gray">暂未指派</span>
             <span v-else class="text-gray">暂未指派</span>
           </template>
           </template>
@@ -118,12 +120,12 @@
               <el-button link type="primary" size="small" @click="handleDetail(row)">详情</el-button>
               <el-button link type="primary" size="small" @click="handleDetail(row)">详情</el-button>
               <el-button v-if="row.status === 0" link type="success" size="small"
               <el-button v-if="row.status === 0" link type="success" size="small"
                 @click="openDispatchDialog(row)">派单</el-button>
                 @click="openDispatchDialog(row)">派单</el-button>
-              <el-button v-if="[1, 2].includes(row.status)" link type="warning" size="small"
+              <el-button v-if="[1, 2, 3].includes(row.status)" link type="warning" size="small"
                 @click="openDispatchDialog(row)">重新派单</el-button>
                 @click="openDispatchDialog(row)">重新派单</el-button>
               <el-button v-if="[0, 1].includes(row.status)" link type="danger" size="small"
               <el-button v-if="[0, 1].includes(row.status)" link type="danger" size="small"
                 @click="handleCancel(row)">取消</el-button>
                 @click="handleCancel(row)">取消</el-button>
 
 
-              <el-dropdown v-if="[2, 3, 4].includes(row.status)" trigger="click"
+              <el-dropdown v-if="[3, 4, 5].includes(row.status)" trigger="click"
                 @command="(cmd) => handleCommand(cmd, row)">
                 @command="(cmd) => handleCommand(cmd, row)">
                 <span class="el-dropdown-link">
                 <span class="el-dropdown-link">
                   更多<el-icon class="el-icon--right">
                   更多<el-icon class="el-icon--right">
@@ -132,8 +134,8 @@
                 </span>
                 </span>
                 <template #dropdown>
                 <template #dropdown>
                   <el-dropdown-menu>
                   <el-dropdown-menu>
-                    <el-dropdown-item v-if="row.status === 3" command="complete">确认完成</el-dropdown-item>
-                    <el-dropdown-item v-if="[3, 4].includes(row.status)" command="care_summary">护理小结</el-dropdown-item>
+                    <el-dropdown-item v-if="row.status === 4" command="complete">确认完成</el-dropdown-item>
+                    <el-dropdown-item v-if="[4, 5].includes(row.status)" command="care_summary">护理小结</el-dropdown-item>
                     <el-dropdown-item command="reward">奖惩</el-dropdown-item>
                     <el-dropdown-item command="reward">奖惩</el-dropdown-item>
                     <el-dropdown-item command="remark">备注</el-dropdown-item>
                     <el-dropdown-item command="remark">备注</el-dropdown-item>
                   </el-dropdown-menu>
                   </el-dropdown-menu>
@@ -174,15 +176,19 @@ import DispatchDialog from './components/DispatchDialog.vue';
 import CareSummaryDrawer from './components/CareSummaryDrawer.vue';
 import CareSummaryDrawer from './components/CareSummaryDrawer.vue';
 import RewardDialog from './components/RewardDialog.vue';
 import RewardDialog from './components/RewardDialog.vue';
 import RemarkDialog from './components/RemarkDialog.vue';
 import RemarkDialog from './components/RemarkDialog.vue';
-import { listOnStore as listServiceOnStore } from '@/api/service/list/index';
+import { listServiceOnOrder } from '@/api/service/list/index';
 import { listSubOrder } from '@/api/order/subOrder/index';
 import { listSubOrder } from '@/api/order/subOrder/index';
 import { dispatchSubOrder } from '@/api/order/subOrder/index';
 import { dispatchSubOrder } from '@/api/order/subOrder/index';
 import { getSubOrderInfo } from '@/api/order/subOrder/index';
 import { getSubOrderInfo } from '@/api/order/subOrder/index';
 import { cancelSubOrder } from '@/api/order/subOrder/index';
 import { cancelSubOrder } from '@/api/order/subOrder/index';
 import { remarkSubOrder } from '@/api/order/subOrder/index';
 import { remarkSubOrder } from '@/api/order/subOrder/index';
+import { confirmSubOrder } from '@/api/order/subOrder/index';
+import { nursingSummarySubOrder } from '@/api/order/subOrder/index';
 import { listOnStore as listAreaStationOnStore } from '@/api/system/areaStation';
 import { listOnStore as listAreaStationOnStore } from '@/api/system/areaStation';
 import { getStore } from '@/api/system/store';
 import { getStore } from '@/api/system/store';
 import { reward } from '@/api/fulfiller/pool';
 import { reward } from '@/api/fulfiller/pool';
+import { getPet } from '@/api/archieves/pet';
+import { getCustomer } from '@/api/archieves/customer';
 
 
 const loading = ref(false);
 const loading = ref(false);
 
 
@@ -211,7 +217,7 @@ onMounted(() => {
 });
 });
 
 
 const getServiceList = () => {
 const getServiceList = () => {
-  listServiceOnStore().then((res) => {
+  listServiceOnOrder().then((res) => {
     serviceOptions.value = res.data || [];
     serviceOptions.value = res.data || [];
   });
   });
 };
 };
@@ -327,12 +333,12 @@ const getServiceOrderTypeTag = (row) => {
 };
 };
 
 
 const getStatusName = (status) => {
 const getStatusName = (status) => {
-  const map = { 0: '待派单', 1: '待接单', 2: '服务中', 3: '待商家确认', 4: '已完成', 5: '已取消' };
+  const map = { 0: '待派单', 1: '待接单', 2: '待服务', 3: '服务中', 4: '待商家确认', 5: '已完成', 6: '已取消' };
   return map[status] || '未知';
   return map[status] || '未知';
 };
 };
 
 
 const getStatusClass = (status) => {
 const getStatusClass = (status) => {
-  const map = { 0: 'pending_dispatch', 1: 'pending_accept', 2: 'serving', 3: 'pending_confirm', 4: 'completed', 5: 'cancelled' };
+  const map = { 0: 'pending_dispatch', 1: 'pending_accept', 2: 'pending_service', 3: 'in_service', 4: 'pending_confirm', 5: 'completed', 6: 'cancelled' };
   return map[status] || 'pending_dispatch';
   return map[status] || 'pending_dispatch';
 };
 };
 
 
@@ -533,30 +539,73 @@ const handleDispatchSubmit = (payload) => {
 };
 };
 
 
 // 护理小结
 // 护理小结
-const openCareSummary = (row) => {
-  careSummaryOrder.value = {
+const openCareSummary = async (row) => {
+  const orderData = {
     ...row,
     ...row,
-    petAge: '3岁',
-    petGender: 'male',
-    petTags: ['易过敏', '胆小'],
-    petWeight: '30 kg',
-    petPersonality: '活泼,超级粘人,喜欢玩球',
-    homeTime: '2023-01-01',
-    houseType: '电梯',
-    entryMethod: '密码开门',
-    entryDetail: '密码: 123456 (仅限服务期间使用)',
-    healthStatus: '健康',
-    vaccineImg: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
-    allergy: '海鲜'
+    careSummary: row.nursingSummary || undefined
   };
   };
+
+  // 获取宠物信息
+  const petId = row?.pet || row?.petId;
+  if (petId) {
+    try {
+      const petRes = await getPet(petId);
+      const pet = petRes?.data;
+      if (pet) {
+        orderData.petAge = pet.age ? `${pet.age}岁` : '未知';
+        orderData.petGender = pet.gender || 'male';
+        orderData.petTags = pet.tags || [];
+        orderData.petWeight = pet.weight ? `${pet.weight} kg` : '未知';
+        orderData.petPersonality = pet.personality || '未知';
+        orderData.healthStatus = pet.healthStatus || '未知';
+        orderData.vaccineImg = pet.vaccineImg || '';
+        orderData.allergy = pet.allergy || '无';
+        orderData.petBreed = pet.breed || '未知';
+      }
+    } catch { }
+  }
+
+  // 获取客户信息(宠物主人)
+  const customerId = row?.customer || row?.customerId;
+  if (customerId) {
+    try {
+      const customerRes = await getCustomer(customerId);
+      const customer = customerRes?.data;
+      if (customer) {
+        orderData.userName = customer.name || orderData.userName;
+        orderData.homeTime = customer.homeTime || '未知';
+        orderData.houseType = customer.houseType || '未知';
+        orderData.entryMethod = customer.entryMethod || '未知';
+        orderData.entryDetail = customer.entryMethod === 'password'
+          ? (customer.entryPassword ? `密码: ${customer.entryPassword}` : '未设置密码')
+          : (customer.keyLocation || '未设置');
+      }
+    } catch { }
+  }
+
+  orderData.summaryTime = row.nursingSummaryTime || orderData.summaryTime;
+  careSummaryOrder.value = orderData;
   careSummaryVisible.value = true;
   careSummaryVisible.value = true;
 };
 };
 
 
-const saveCareSummary = (text) => {
-  if (careSummaryOrder.value) {
-    careSummaryOrder.value.careSummary = text;
+const saveCareSummary = async (text) => {
+  if (!careSummaryOrder.value?.id) {
+    ElMessage.warning('订单信息不存在');
+    return;
+  }
+  try {
+    await nursingSummarySubOrder({
+      orderId: careSummaryOrder.value.id,
+      content: text
+    });
+    if (careSummaryOrder.value) {
+      careSummaryOrder.value.careSummary = text;
+      careSummaryOrder.value.nursingSummary = text;
+    }
     ElMessage.success('护理小结已保存');
     ElMessage.success('护理小结已保存');
     handleSearch();
     handleSearch();
+  } catch {
+    // Error handled by interceptor
   }
   }
 };
 };
 
 
@@ -634,10 +683,15 @@ const handleCommand = (cmd, row) => {
   if (cmd === 'remark') openRemarkDialog(row);
   if (cmd === 'remark') openRemarkDialog(row);
   if (cmd === 'care_summary') openCareSummary(row);
   if (cmd === 'care_summary') openCareSummary(row);
   if (cmd === 'complete') {
   if (cmd === 'complete') {
-    ElMessageBox.confirm('确认将该订单手动标记为完成吗?', '提示', { type: 'warning' }).then(() => {
-      row.status = 4;
-      ElMessage.success('订单已标记完成');
-    });
+    ElMessageBox.confirm('确认将该订单手动标记为完成吗?', '提示', { type: 'warning' }).then(async () => {
+      try {
+        await confirmSubOrder({ id: row.id });
+        ElMessage.success('订单已确认完成');
+        handleSearch();
+      } catch {
+        // Error handled by interceptor
+      }
+    }).catch(() => { });
   }
   }
   if (cmd === 'delete') {
   if (cmd === 'delete') {
     ElMessageBox.confirm('确认删除该订单吗?此操作不可恢复', '警告', { type: 'error' }).then(() => {
     ElMessageBox.confirm('确认删除该订单吗?此操作不可恢复', '警告', { type: 'error' }).then(() => {