feat: list group buy orders for dispatch

This commit is contained in:
王鹏
2026-07-07 17:41:09 +08:00
parent 88b7841f8e
commit 09217c4821
4 changed files with 87 additions and 5 deletions

View File

@@ -0,0 +1,40 @@
import { describe, expect, it } from 'vitest'
import { filterPendingDeliveryGroupBuyOrders, groupBuyOrderDispatchLabel } from './groupBuyApi'
import type { GroupBuyOrder } from '../types'
describe('group buy dispatch helpers', () => {
it('keeps only group buy orders waiting for delivery', () => {
const orders = [
groupBuyOrder({ id: 1, status: 'PENDING_DELIVERY' }),
groupBuyOrder({ id: 2, status: 'DELIVERING' }),
groupBuyOrder({ id: 3, status: 'PENDING_PICKUP' })
]
expect(filterPendingDeliveryGroupBuyOrders(orders).map((item) => item.id)).toEqual([1])
})
it('builds a readable dispatch label', () => {
expect(groupBuyOrderDispatchLabel(groupBuyOrder({
orderNo: 'GB00000001',
groupBuyTitle: 'Today eggs',
quantity: 2,
amountCent: 5980
}))).toBe('GB00000001 Today eggs x2 ¥59.80')
})
})
function groupBuyOrder(overrides: Partial<GroupBuyOrder>): GroupBuyOrder {
return {
id: 1,
orderNo: 'GB00000001',
groupBuyId: 1,
groupBuyTitle: 'Today eggs',
quantity: 1,
priceCent: 2990,
amountCent: 2990,
deliveryMethod: 'IMMEDIATE',
status: 'PENDING_DELIVERY',
offlinePayStatus: 'UNPAID',
...overrides
}
}

View File

@@ -1,10 +1,22 @@
import type { GroupBuy } from '../types'
import type { GroupBuy, GroupBuyOrder } from '../types'
import { apiGet, apiPost, apiPut } from './http'
export function listGroupBuys() {
return apiGet<GroupBuy[]>('/api/admin/group-buys')
}
export function listGroupBuyOrders(groupBuyId: number) {
return apiGet<GroupBuyOrder[]>(`/api/admin/group-buys/${groupBuyId}/orders`)
}
export function filterPendingDeliveryGroupBuyOrders(orders: GroupBuyOrder[]) {
return orders.filter((order) => order.status === 'PENDING_DELIVERY')
}
export function groupBuyOrderDispatchLabel(order: GroupBuyOrder) {
return `${order.orderNo} ${order.groupBuyTitle} x${order.quantity} ¥${(order.amountCent / 100).toFixed(2)}`
}
export function createGroupBuy(data: Partial<GroupBuy>) {
return apiPost<GroupBuy>('/api/admin/group-buys', data)
}

View File

@@ -101,6 +101,22 @@ export interface GroupBuy {
pickupAddress?: string
}
export interface GroupBuyOrder {
id: number
orderNo: string
groupBuyId: number
groupBuyTitle: string
coverUrl?: string
quantity: number
priceCent: number
amountCent: number
deliveryMethod: string
status: string
offlinePayStatus: string
remark?: string
createdAt?: string
}
export interface SecondGoods {
id: number
title: string

View File

@@ -3,6 +3,12 @@ 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,
@@ -11,7 +17,7 @@ import {
listDeliveryOrders,
listDeliveryUsers
} from '../api/deliveryApi'
import type { DeliveryOrder, DeliveryUser, ExpressOrder, GoodsOrder } from '../types'
import type { DeliveryOrder, DeliveryUser, ExpressOrder, GoodsOrder, GroupBuyOrder } from '../types'
import { statusText } from '../utils/format'
const loading = ref(false)
@@ -19,22 +25,28 @@ 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] = await Promise.all([
const [riderRows, taskRows, goodsRows, expressRows, groupBuyRows] = await Promise.all([
listDeliveryUsers(),
listDeliveryOrders(),
listGoodsOrders({ status: 'PENDING_DELIVERY' }),
listExpressOrders('PENDING_PICKUP')
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 = goodsRows
expressOrders.value = expressRows
groupBuyOrders.value = filterPendingDeliveryGroupBuyOrders(groupOrderRows)
if (!dispatchForm.riderId && riderRows[0]) dispatchForm.riderId = riderRows[0].id
} catch (error) {
ElMessage.error(error instanceof Error ? error.message : '加载失败')
@@ -113,7 +125,9 @@ onMounted(load)
</el-tab-pane>
<el-tab-pane label="团购订单">
<div class="toolbar">
<el-input-number v-model="dispatchForm.groupBuyOrderId" :min="1" />
<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>