150 lines
6.2 KiB
Vue
150 lines
6.2 KiB
Vue
<script setup lang="ts">
|
|
import { onMounted, reactive, ref } from 'vue'
|
|
import { Plus, Refresh, Van } from '@element-plus/icons-vue'
|
|
import { ElMessage } from 'element-plus'
|
|
import { listGoodsOrders, listExpressOrders } from '../api/orderApi'
|
|
import {
|
|
filterPendingDeliveryGroupBuyOrders,
|
|
groupBuyOrderDispatchLabel,
|
|
listGroupBuyOrders,
|
|
listGroupBuys
|
|
} from '../api/groupBuyApi'
|
|
import {
|
|
assignExpressOrder,
|
|
assignGoodsOrder,
|
|
assignGroupBuyOrder,
|
|
createDeliveryUser,
|
|
filterUnassignedDispatchTargets,
|
|
listDeliveryOrders,
|
|
listDeliveryUsers
|
|
} from '../api/deliveryApi'
|
|
import type { DeliveryOrder, DeliveryUser, ExpressOrder, GoodsOrder, GroupBuyOrder } from '../types'
|
|
import { statusText } from '../utils/format'
|
|
|
|
const loading = ref(false)
|
|
const riders = ref<DeliveryUser[]>([])
|
|
const tasks = ref<DeliveryOrder[]>([])
|
|
const goodsOrders = ref<GoodsOrder[]>([])
|
|
const expressOrders = ref<ExpressOrder[]>([])
|
|
const groupBuyOrders = ref<GroupBuyOrder[]>([])
|
|
const riderForm = reactive({ userId: 3, name: '', phone: '', enabled: true })
|
|
const dispatchForm = reactive({ goodsOrderId: undefined as number | undefined, expressOrderId: undefined as number | undefined, groupBuyOrderId: undefined as number | undefined, riderId: undefined as number | undefined })
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
const [riderRows, taskRows, goodsRows, expressRows, groupBuyRows] = await Promise.all([
|
|
listDeliveryUsers(),
|
|
listDeliveryOrders(),
|
|
listGoodsOrders({ status: 'PENDING_DELIVERY' }),
|
|
listExpressOrders('PENDING_PICKUP'),
|
|
listGroupBuys()
|
|
])
|
|
const groupOrderRows = groupBuyRows.length
|
|
? ([] as GroupBuyOrder[]).concat(...await Promise.all(groupBuyRows.map((item) => listGroupBuyOrders(item.id))))
|
|
: []
|
|
riders.value = riderRows
|
|
tasks.value = taskRows
|
|
goodsOrders.value = filterUnassignedDispatchTargets(goodsRows, taskRows, 'GOODS_ORDER')
|
|
expressOrders.value = filterUnassignedDispatchTargets(expressRows, taskRows, 'EXPRESS_ORDER')
|
|
groupBuyOrders.value = filterUnassignedDispatchTargets(filterPendingDeliveryGroupBuyOrders(groupOrderRows), taskRows, 'GROUP_BUY_ORDER')
|
|
if (!dispatchForm.riderId && riderRows[0]) dispatchForm.riderId = riderRows[0].id
|
|
} catch (error) {
|
|
ElMessage.error(error instanceof Error ? error.message : '加载失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function saveRider() {
|
|
try {
|
|
await createDeliveryUser(riderForm)
|
|
riderForm.name = ''
|
|
riderForm.phone = ''
|
|
ElMessage.success('已创建配送员')
|
|
await load()
|
|
} catch (error) {
|
|
ElMessage.error(error instanceof Error ? error.message : '保存失败')
|
|
}
|
|
}
|
|
|
|
async function dispatch(type: 'goods' | 'express' | 'group') {
|
|
if (!dispatchForm.riderId) {
|
|
ElMessage.warning('请选择配送员')
|
|
return
|
|
}
|
|
try {
|
|
if (type === 'goods' && dispatchForm.goodsOrderId) {
|
|
await assignGoodsOrder(dispatchForm.goodsOrderId, dispatchForm.riderId)
|
|
}
|
|
if (type === 'express' && dispatchForm.expressOrderId) {
|
|
await assignExpressOrder(dispatchForm.expressOrderId, dispatchForm.riderId)
|
|
}
|
|
if (type === 'group' && dispatchForm.groupBuyOrderId) {
|
|
await assignGroupBuyOrder(dispatchForm.groupBuyOrderId, dispatchForm.riderId)
|
|
}
|
|
ElMessage.success('派单成功')
|
|
await load()
|
|
} catch (error) {
|
|
ElMessage.error(error instanceof Error ? error.message : '派单失败')
|
|
}
|
|
}
|
|
|
|
onMounted(load)
|
|
</script>
|
|
|
|
<template>
|
|
<h1 class="page-title">配送派单</h1>
|
|
<div class="panel">
|
|
<div class="toolbar">
|
|
<strong>配送员</strong>
|
|
<el-input v-model="riderForm.name" placeholder="姓名" style="width: 140px" />
|
|
<el-input v-model="riderForm.phone" placeholder="手机号" style="width: 160px" />
|
|
<el-input-number v-model="riderForm.userId" :min="1" />
|
|
<el-button type="primary" :icon="Plus" @click="saveRider">新增</el-button>
|
|
<el-button :icon="Refresh" :loading="loading" @click="load">刷新</el-button>
|
|
</div>
|
|
<el-select v-model="dispatchForm.riderId" placeholder="选择配送员" style="width: 220px; margin-bottom: 12px">
|
|
<el-option v-for="rider in riders" :key="rider.id" :label="`${rider.name} ${rider.phone}`" :value="rider.id" />
|
|
</el-select>
|
|
<el-tabs>
|
|
<el-tab-pane label="商品订单">
|
|
<div class="toolbar">
|
|
<el-select v-model="dispatchForm.goodsOrderId" placeholder="待配送商品订单" style="width: 260px">
|
|
<el-option v-for="item in goodsOrders" :key="item.id" :label="item.orderNo" :value="item.id" />
|
|
</el-select>
|
|
<el-button type="primary" :icon="Van" @click="dispatch('goods')">派单</el-button>
|
|
</div>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="快递代取">
|
|
<div class="toolbar">
|
|
<el-select v-model="dispatchForm.expressOrderId" placeholder="待取件订单" style="width: 260px">
|
|
<el-option v-for="item in expressOrders" :key="item.id" :label="`${item.orderNo} ${item.pickupCode}`" :value="item.id" />
|
|
</el-select>
|
|
<el-button type="primary" :icon="Van" @click="dispatch('express')">派单</el-button>
|
|
</div>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="团购订单">
|
|
<div class="toolbar">
|
|
<el-select v-model="dispatchForm.groupBuyOrderId" placeholder="待配送团购订单" style="width: 320px">
|
|
<el-option v-for="item in groupBuyOrders" :key="item.id" :label="groupBuyOrderDispatchLabel(item)" :value="item.id" />
|
|
</el-select>
|
|
<el-button type="primary" :icon="Van" @click="dispatch('group')">派单</el-button>
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
<div class="panel">
|
|
<div class="toolbar"><strong>配送任务</strong></div>
|
|
<el-table :data="tasks" border>
|
|
<el-table-column prop="bizOrderNo" label="业务单号" min-width="150" />
|
|
<el-table-column prop="bizType" label="类型" width="150" />
|
|
<el-table-column prop="riderName" label="配送员" width="120" />
|
|
<el-table-column label="状态" width="120">
|
|
<template #default="{ row }">{{ statusText(row.status) }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="address" label="地址" min-width="180" />
|
|
</el-table>
|
|
</div>
|
|
</template>
|