Forráskód Böngészése

add 管理端派单业务

tea 2 hónapja
szülő
commit
edd38a234e

+ 9 - 0
kxmall-admin-ui/src/api/rider/rider.js

@@ -109,3 +109,12 @@ export function resetRiderPassword(riderId) {
   })
 }
 
+// 根据订单ID查询可配送的师傅列表
+export function getRiderByOrderId(orderId) {
+  return request({
+    url: '/rider/rider/getRiderByOrderId',
+    method: 'get',
+    params: { orderId }
+  })
+}
+

+ 152 - 118
kxmall-admin-ui/src/views/order/storeOrder/index.vue

@@ -1,45 +1,45 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="queryParams.orderStatus" @tab-click="onOrderStatusChange">
-      <el-tab-pane v-for="item in status" :key="item.name" :label="item.label" :name="item.name"/>
+      <el-tab-pane v-for="item in status" :key="item.name" :label="item.label" :name="item.name" />
     </el-tabs>
-    <el-form ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="68px">
+    <el-form ref="queryForm" :inline="true" :model="queryParams" label-width="68px" size="small">
       <el-form-item prop="storageId">
-        <el-select v-model="queryParams.storageId" placeholder="请选择前置仓" clearable>
-          <el-option v-for="item in storages" :key="item.id" :label="item.name" :value="item.id"/>
+        <el-select v-model="queryParams.storageId" clearable placeholder="请选择前置仓">
+          <el-option v-for="item in storages" :key="item.id" :label="item.name" :value="item.id" />
         </el-select>
       </el-form-item>
       <el-form-item prop="orderId">
-        <el-input v-model="queryParams.orderId" clearable placeholder="输入订单号" @keyup.enter.native="toQuery"/>
+        <el-input v-model="queryParams.orderId" clearable placeholder="输入订单号" @keyup.enter.native="toQuery" />
       </el-form-item>
       <el-form-item prop="createTime">
         <el-date-picker
           v-model="queryParams.createTime"
-          type="datetimerange"
-          value-format="yyyy-MM-dd HH:mm:ss"
-          start-placeholder="创建开始时间"
           end-placeholder="创建结束时间"
           range-separator="至"
+          start-placeholder="创建开始时间"
+          type="datetimerange"
           unlink-panels
+          value-format="yyyy-MM-dd HH:mm:ss"
         />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-search" size="mini" type="primary" @click="handleQuery">搜索</el-button>
       </el-form-item>
     </el-form>
 
     <el-table v-loading="loading" :data="storeOrderList">
       <!-- <el-table-column type="selection" width="55" align="center" /> -->
-      <el-table-column type="index" label="序号" align="center">
+      <el-table-column align="center" label="序号" type="index">
         <template slot-scope="{$index}">
           {{ (queryParams.pageNum - 1) * queryParams.pageSize + $index + 1 }}
         </template>
       </el-table-column>
       <el-table-column
-        width="200"
-        prop="orderId"
         align="center"
         label="订单号"
+        prop="orderId"
+        width="200"
       >
         <template slot-scope="scope">
           <el-tooltip content="点击复制订单号" placement="top">
@@ -51,10 +51,10 @@
         </template>
       </el-table-column>
       <el-table-column
-        width="200"
-        prop="storageId"
         align="center"
         label="仓库"
+        prop="storageId"
+        width="200"
       >
         <template slot-scope="scope">
           {{ storageMap[scope.row.storeId] }}
@@ -62,15 +62,15 @@
       </el-table-column>
       <el-table-column
         v-if="queryParams.orderStatus==='32'"
-        prop="exceptionReason"
         align="center"
         label="异常原因"
+        prop="exceptionReason"
       />
       <el-table-column
         v-if="queryParams.orderStatus==='80'"
-        prop="exceptionReason"
         align="center"
         label="付款状态"
+        prop="exceptionReason"
       />
       <el-table-column
         v-if="queryParams.orderStatus!=='14'&&queryParams.orderStatus!=='16'&&queryParams.orderStatus!=='10'"
@@ -85,36 +85,36 @@
       </el-table-column>
       <el-table-column
         align="left"
-        width="100"
-        prop="realName"
         label="姓名"
+        prop="realName"
+        width="100"
       />
       <el-table-column
         align="left"
-        width="110"
-        prop="userPhone"
         label="电话"
+        prop="userPhone"
+        width="110"
       />
       <el-table-column
         :show-overflow-tooltip="true"
         align="left"
-        width="80"
-        prop="address"
         label="订单类型"
+        prop="address"
+        width="80"
       >
         <template slot-scope="{row}">
           <el-tag :type="row.shippingType==1 ? 'error' : 'success'">{{
-              row.shippingType == 1 ? '配送' : '自提'
-            }}
+            row.shippingType == 1 ? '配送' : '自提'
+          }}
           </el-tag>
         </template>
       </el-table-column>
       <el-table-column
         :show-overflow-tooltip="true"
         align="left"
-        width="200"
-        prop="userAddress"
         label="地址"
+        prop="userAddress"
+        width="200"
       />
       <el-table-column
         align="center"
@@ -133,28 +133,28 @@
         </template>
       </el-table-column>
       <el-table-column
-        width="90"
         align="center"
         label="实付金额"
+        width="90"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.payIntegral ? '积分' + scope.row.payIntegral : '¥' + scope.row.payPrice }}</span>
         </template>
       </el-table-column>
       <el-table-column
-        width="200"
         align="center"
         label="要求送达时间"
+        width="200"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.predictTime }}</span>
         </template>
       </el-table-column>
       <el-table-column
-        prop="phone"
-        width="160"
         align="center"
         label="下单时间"
+        prop="phone"
+        width="160"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.createTime }}</span>
@@ -162,18 +162,18 @@
       </el-table-column>
       <el-table-column
         align="center"
-        width="160"
         label="支付时间"
         prop="payTime"
+        width="160"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.payTime }}</span>
         </template>
       </el-table-column>
       <el-table-column
-        width="280"
         align="center"
         label="付款交易号"
+        width="280"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.payId }}</span>
@@ -182,8 +182,8 @@
 
       <el-table-column
         align="center"
-        width="160"
         label="创建时间"
+        width="160"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.createTime }}</span>
@@ -191,73 +191,69 @@
       </el-table-column>
       <el-table-column
         align="center"
-        width="160"
         label="修改时间"
+        width="160"
       >
         <template slot-scope="scope">
           <span>{{ scope.row.updateTime }}</span>
         </template>
       </el-table-column>
       <el-table-column
-        fixed="right"
         align="center"
+        fixed="right"
         label="操作"
         width="400"
       >
         <template slot-scope="{row}">
           <el-button
-            type="primary"
             size="mini"
+            type="primary"
             @click="viewDetail(row.id)"
           >详情
           </el-button>
           <el-button
             v-if="row.status===14"
-            type="primary"
             size="mini"
+            type="primary"
             @click="handleOperation(row.id,'startStocking')"
           >开始配货
           </el-button>
           <el-button
             v-if="row.status===16"
-            type="primary"
             size="mini"
+            type="primary"
             @click="handleOperation(row.id,'completeAllocation')"
           >完成配货
           </el-button>
           <el-button
             v-if="row.status===30"
-            type="primary"
             size="mini"
+            type="primary"
             @click="handleOperation(row.id,'completeDelivery')"
           >完成配送
           </el-button>
           <el-button
             v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===2"
-            type="success"
             size="mini"
+            type="success"
             @click="showVerifyDialog(row.id)"
           >完成取货
           </el-button>
           <!-- 合并后的配送下拉按钮 -->
-          <el-dropdown
-            v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===1"
-            @command="handleDeliveryCommand(row, $event)"
-          >
-            <el-button type="primary" size="mini">
-              配送方式<i class="el-icon-arrow-down el-icon--right"/>
-            </el-button>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item command="system">系统配送</el-dropdown-item>
-              <el-dropdown-item command="thirdParty">第三方配送</el-dropdown-item>
-              <el-dropdown-item command="merchant">商家自配</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <el-button
+            v-if="(row.status === 20 || row.status===32||row.status===30) && row.shippingType===1"
+            size="mini"
+            style="margin-left: 10px;"
+            type="primary"
+            plain
+            @click="handleDeliveryCommand(row)"
+          >指定师傅
+          </el-button>
           <el-button
             v-if="[16,20,30,32,34].includes(row.status)"
-            type="danger"
             size="mini"
             style="margin-left: 10px;"
+            type="danger"
             @click="handleCancelOrder(row)"
           >取消订单
           </el-button>
@@ -266,14 +262,19 @@
     </el-table>
     <pagination
       v-show="total > 0"
-      :total="total"
-      :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
+      :page.sync="queryParams.pageNum"
+      :total="total"
       @pagination="getList"
     />
     <!-- 添加或修改订单对话框 -->
-    <el-dialog title="订单详情" :visible.sync="open" width="1050px" append-to-body class="order-detail-dialog"
-               :custom-class="order-detail-dialog">
+    <el-dialog
+      :visible.sync="open"
+      append-to-body
+      class="order-detail-dialog"
+      title="订单详情"
+      width="1050px"
+    >
       <div class="detail-container">
         <!-- 基本信息部分 -->
         <div class="detail-section">
@@ -324,7 +325,7 @@
 
           <div class="detail-item">
             <span class="item-label">备注:</span>
-            <span class="item-value" :class="{'empty-remark': !form.remark}">
+            <span :class="{'empty-remark': !form.remark}" class="item-value">
               {{ form.remark || '无备注' }}
             </span>
           </div>
@@ -437,10 +438,10 @@
           <h3 class="section-title">商品信息</h3>
           <el-table
             :data="form.productList"
-            size="small"
             border
             fit
             highlight-current-row
+            size="small"
             style="width: 100%"
           >
             <el-table-column
@@ -464,8 +465,8 @@
             <el-table-column
               align="center"
               label="商品名称"
-              prop="productTitle"
               min-width="150"
+              prop="productTitle"
             />
             <el-table-column
               align="center"
@@ -550,7 +551,7 @@
                 >
                   <img :src="photo.imageUrl" alt="订单照片" class="photo-thumbnail">
                   <div class="photo-overlay">
-                    <i class="el-icon-zoom-in"/>
+                    <i class="el-icon-zoom-in" />
                   </div>
                 </div>
               </div>
@@ -571,21 +572,39 @@
         style="width: 100%; margin-top:20px"
       >
         <el-table-column
-          prop="name"
           align="center"
           label="骑手名"
+          prop="name"
         />
         <el-table-column
           align="center"
-          label="配送时间"
+          label="匹配度分数"
+          prop="matchScore"
+          width="120"
         >
           <template slot-scope="scope">
-            <span>{{ scope.row.deliveryStart }}-{{ scope.row.deliveryEnd }}</span>
+            <span v-if="scope.row.matchScore">{{ scope.row.matchScore }}</span>
+            <span v-else>-</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          align="center"
+          label="冲突时间"
+          width="150"
+        >
+          <template slot-scope="scope">
+            <div v-if="scope.row.conflictTime && scope.row.conflictTime.length > 0">
+              <div v-for="(time, index) in scope.row.conflictTime" :key="index" class="conflict-time">
+                {{ formatDateTime(time) }}
+              </div>
+            </div>
+            <span v-else class="no-conflict">无冲突</span>
           </template>
         </el-table-column>
         <el-table-column
           align="center"
           label="操作"
+          width="110"
         >
           <template slot-scope="scope">
             <el-button @click="check(scope.row.id)">选 择</el-button>
@@ -602,7 +621,7 @@
     >
       <el-form>
         <el-form-item label="核销码">
-          <el-input v-model="verifyCode" placeholder="请输入核销码"/>
+          <el-input v-model="verifyCode" placeholder="请输入核销码" />
         </el-form-item>
       </el-form>
       <span slot="footer" class="dialog-footer">
@@ -613,11 +632,11 @@
 
     <!-- 照片预览弹窗 -->
     <el-dialog
-      :visible.sync="photoPreviewVisible"
-      :show-close="false"
       :modal="true"
-      width="80%"
+      :show-close="false"
+      :visible.sync="photoPreviewVisible"
       class="photo-preview-dialog"
+      width="80%"
       @close="closePhotoPreview"
     >
       <div class="photo-preview-container">
@@ -625,9 +644,9 @@
           <span class="preview-title">{{ currentPhotoGroup.title }}</span>
           <span class="preview-counter">{{ currentPhotoIndex + 1 }} / {{ currentPhotoGroup.photos.length }}</span>
           <el-button
-            type="text"
             class="close-btn"
             icon="el-icon-close"
+            type="text"
             @click="closePhotoPreview"
           />
         </div>
@@ -635,25 +654,25 @@
           <div class="photo-navigation">
             <el-button
               v-if="currentPhotoIndex > 0"
-              type="text"
               class="nav-btn prev-btn"
               icon="el-icon-arrow-left"
+              type="text"
               @click="prevPhoto"
             />
             <div class="main-photo">
               <img
-                :src="currentPhoto.imageUrl"
                 :alt="currentPhoto.imageUrl"
+                :src="currentPhoto.imageUrl"
                 class="preview-image"
-                @load="onImageLoad"
                 @error="onImageError"
+                @load="onImageLoad"
               >
             </div>
             <el-button
               v-if="currentPhotoIndex < currentPhotoGroup.photos.length - 1"
-              type="text"
               class="nav-btn next-btn"
               icon="el-icon-arrow-right"
+              type="text"
               @click="nextPhoto"
             />
           </div>
@@ -661,11 +680,11 @@
             <div
               v-for="(photo, index) in currentPhotoGroup.photos"
               :key="photo.id"
-              class="thumbnail-item"
               :class="{ active: index === currentPhotoIndex }"
+              class="thumbnail-item"
               @click="setCurrentPhoto(index)"
             >
-              <img :src="photo.imageUrl" :alt="photo.imageUrl" class="thumbnail-image">
+              <img :alt="photo.imageUrl" :src="photo.imageUrl" class="thumbnail-image">
             </div>
           </div>
         </div>
@@ -676,7 +695,7 @@
 
 <script>
 import Clipboard from 'clipboard'
-import {multiply} from '@/utils/math'
+import { multiply } from '@/utils/math'
 import {
   listStoreOrder /** delStoreOrder, addStoreOrder, updateStoreOrder*/,
   getStoreOrder,
@@ -689,8 +708,8 @@ import {
   thirdPartyDistribution,
   cancelOrder
 } from '@/api/order/storeOrder'
-import {listAllStorage} from '@/api/storage/storage'
-import {getRiderByStorageId} from '@/api/rider/rider'
+import { listAllStorage } from '@/api/storage/storage'
+import { getRiderByOrderId } from '@/api/rider/rider'
 
 export default {
   name: 'StoreOrder',
@@ -744,17 +763,17 @@ export default {
       form: {},
       // 表单校验
       status: [
-        {label: '待配货', name: '14'},
-        {label: '配货中', name: '16'},
-        {label: '待配送', name: '20'},
-        {label: '配送中', name: '30'},
-        {label: '已完成', name: '40,50'},
-        {label: '配送异常', name: '32'},
-        {label: '超时订单', name: '34'},
-        {label: '待支付', name: '10'},
-        {label: '已退款', name: '70'},
-        {label: '已取消', name: '80'},
-        {label: '全部订单', name: 'all'}
+        { label: '待配货', name: '14' },
+        { label: '配货中', name: '16' },
+        { label: '待配送', name: '20' },
+        { label: '配送中', name: '30' },
+        { label: '已完成', name: '40,50' },
+        { label: '配送异常', name: '32' },
+        { label: '超时订单', name: '34' },
+        { label: '待支付', name: '10' },
+        { label: '已退款', name: '70' },
+        { label: '已取消', name: '80' },
+        { label: '全部订单', name: 'all' }
       ],
       storages: []
     }
@@ -797,8 +816,19 @@ export default {
   },
   methods: {
     multiply,
+    // 格式化日期时间
+    formatDateTime(dateTime) {
+      if (!dateTime) return '-'
+      const date = new Date(dateTime)
+      return date.toLocaleString('zh-CN', {
+        month: '2-digit',
+        day: '2-digit',
+        hour: '2-digit',
+        minute: '2-digit'
+      })
+    },
     listAllStorage() {
-      listAllStorage().then(({data}) => {
+      listAllStorage().then(({ data }) => {
         this.storages = data
         this.storages.forEach(storage => {
           this.storageMap[storage.id] = storage.name
@@ -874,18 +904,8 @@ export default {
       })
     },
     // 添加这个新方法
-    handleDeliveryCommand(row, command) {
-      switch (command) {
-        case 'system':
-          this.allot(row.storeId, row.orderId, row.postId)
-          break
-        case 'thirdParty':
-          this.handleOperation(row.id, 'thirdPartyDistribution')
-          break
-        case 'merchant':
-          this.handleOperation(row.id, 'merchantDistribution')
-          break
-      }
+    handleDeliveryCommand(row) {
+      this.allot(row.storeId, row.id, row.postId)
     },
     async confirmCompletePickup() {
       if (!this.verifyCode) {
@@ -930,7 +950,7 @@ export default {
     getList() {
       this.loading = true
       this.storeOrderList = []
-      const params = {...this.queryParams}
+      const params = { ...this.queryParams }
       if (params.createTime) {
         params.startTime = params.createTime[0]
         params.endTime = params.createTime[1]
@@ -962,7 +982,7 @@ export default {
       this.handleQuery()
     },
     viewDetail(id) {
-      getStoreOrder(id).then(({data}) => {
+      getStoreOrder(id).then(({ data }) => {
         this.form = data
         this.open = true
       })
@@ -970,33 +990,36 @@ export default {
     allot(val, id, postId) {
       this.orderId = id
       if (postId) {
-        this.reAllot(val, id)
+        this.reAllot(id)
         return
       }
-      getRiderByStorageId({
-        storageId: val
-      }).then(res => {
+      getRiderByOrderId(id).then(res => {
         if (res.code !== 200) {
           this.$message.warning(res.message)
           return
         }
         this.courierList = res.data
-        if (res.data[0].automatic === 1) {
+        if (res.data && res.data.length > 0 && res.data[0].automatic === 1) {
           this.check(res.data[0].id)
         } else {
           this.allotShow = true
-          this.allotValue = val
         }
       })
     },
-    reAllot(val, id) {
+    reAllot(id) {
       this.orderId = id
       this.allotShow = true
-      this.allotValue = val
-      getRiderByStorageId({
-        storageId: val
-      }).then(res => {
+      getRiderByOrderId(id).then(res => {
+        if (res.code !== 200) {
+          this.$message.warning(res.message)
+          return
+        }
         this.courierList = res.data
+        if (res.data && res.data.length > 0 && res.data[0].automatic === 1) {
+          this.check(res.data[0].id)
+        } else {
+          this.allotShow = true
+        }
       })
     },
     getStatusTagType(status) {
@@ -1052,7 +1075,7 @@ export default {
         thirdPartyDistribution,
         cancelOrder
       }
-      operations[operation]({id}).then(() => {
+      operations[operation]({ id }).then(() => {
         this.$message({
           message: '操作成功',
           type: 'success'
@@ -1061,7 +1084,7 @@ export default {
       })
     },
     check(val) {
-      const loadingInstance = this.$loading({text: '正在分配中...'})
+      const loadingInstance = this.$loading({ text: '正在分配中...' })
       distributeOrder({
         orderNo: this.orderId,
         riderId: val
@@ -1145,6 +1168,17 @@ export default {
 }
 </script>
 <style lang="scss" scoped>
+.conflict-time {
+  color: #e6a23c;
+  font-size: 12px;
+  margin: 2px 0;
+}
+
+.no-conflict {
+  color: #67c23a;
+  font-size: 12px;
+}
+
 .order-detail-dialog {
 
   .detail-container {

+ 1 - 1
kxmall-rider-ui/pages/task/complete.vue

@@ -2,7 +2,7 @@
   <view class="complete-page">
     <view class="success-container">
       <image class="success-image" src="/static/task/success.png" mode="widthFix" />
-      <view style="padding-top: 50upx; color: #1c84c6"> 订单已完成,谢您的付出! </view>
+      <view style="padding-top: 50upx; color: #1c84c6"> 订单已完成,谢您的付出! </view>
       
       <view class="btn-group" style="padding-top: 200upx">
         <view class="btn btn-primary " @click="goToHome">去首页</view>