refactor: 拆分小程序 vue 结构

This commit is contained in:
2026-03-11 14:11:26 +08:00
commit b050c01a24
141 changed files with 24904 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
import type { Ref } from 'vue'
import { showToast } from '@tarojs/taro'
import { getOrderDetail, mockPayOrder } from '@/services'
import type { OrderDetail } from '@/shared'
import { openRoute } from '@/utils/router'
export function createOrderDetailActions (payload: {
loading: Ref<boolean>
order: Ref<OrderDetail | null>
orderId: Ref<string>
}) {
const { loading, order, orderId } = payload
async function loadDetail () {
if (!orderId.value) {
order.value = null
loading.value = false
return
}
loading.value = true
try {
order.value = await getOrderDetail(orderId.value)
} finally {
loading.value = false
}
}
async function handlePrimaryAction () {
if (!order.value) return
if (order.value.actionText === '再来一单') {
void openRoute('/pages/menu/index')
return
}
if (order.value.actionText === '去支付') {
await mockPayOrder(order.value.id)
await showToast({ title: '支付成功', icon: 'success' })
await loadDetail()
return
}
await showToast({ title: '当前订单处理中', icon: 'none' })
}
function handleContact () {
void showToast({ title: '拨号功能暂不可用', icon: 'none' })
}
function goOrders () {
void openRoute('/pages/orders/index')
}
return {
goOrders,
handleContact,
handlePrimaryAction,
loadDetail
}
}

View File

@@ -0,0 +1,40 @@
import { FulfillmentScenes, formatPrice as formatPriceUtil, SCENE_LABEL_MAP } from '@/shared'
import type { FulfillmentScene, OrderDetail } from '@/shared'
export function formatPrice (value: number) {
return formatPriceUtil(value)
}
export function resolveSceneLabel (scene: FulfillmentScene) {
return SCENE_LABEL_MAP[scene]
}
export function resolveOrderSubtitle (order: OrderDetail | null) {
if (!order) return ''
if (order.tableNo) return `桌号 ${order.tableNo}`
return order.customerName
}
export function resolveStatusDescription (order: OrderDetail | null) {
if (!order) return ''
const statusText = order.statusText
if (statusText === '待支付') return '请尽快完成支付'
if (statusText === '已接单' || statusText === '制作中') return '商家已接单,正在为您精心准备餐品'
if (statusText === '配送中') return '骑手正在为您配送'
if (statusText === '已完成') return '订单已完成,欢迎再次光临'
return '订单处理中'
}
export function resolveFulfillmentHint (order: OrderDetail | null) {
if (!order) return ''
if (order.scene === FulfillmentScenes.DineIn) return '餐品制作完成后将尽快为您上桌,请留意取餐提醒'
if (order.scene === FulfillmentScenes.Pickup) return '餐品制作完成后请到店取餐'
return '预计 30 分钟送达'
}
export function resolveTimelineNodeClass (index: number, currentTimelineIndex: number) {
if (index < currentTimelineIndex) return 'od-page__tl-node--done'
if (index === currentTimelineIndex) return 'od-page__tl-node--current'
return 'od-page__tl-node--pending'
}

View File

@@ -0,0 +1,64 @@
import { computed, ref } from 'vue'
import { useDidShow, useLoad } from '@tarojs/taro'
import { pinia, useAppStore } from '@/stores'
import type { OrderDetail } from '@/shared'
import { createOrderDetailActions } from './order-detail-page/actions'
import {
formatPrice,
resolveFulfillmentHint,
resolveOrderSubtitle,
resolveSceneLabel,
resolveStatusDescription,
resolveTimelineNodeClass
} from './order-detail-page/status-helpers'
export function useOrderDetailPage () {
const appStore = useAppStore(pinia)
const orderId = ref('')
const loading = ref(true)
const order = ref<OrderDetail | null>(null)
const { goOrders, handleContact, handlePrimaryAction, loadDetail } = createOrderDetailActions({
loading,
order,
orderId
})
const sceneLabel = computed(() => order.value ? resolveSceneLabel(order.value.scene) : '')
const orderSubtitle = computed(() => resolveOrderSubtitle(order.value))
const statusDescription = computed(() => resolveStatusDescription(order.value))
const storeAddress = computed(() => appStore.currentStore.address)
const fulfillmentHint = computed(() => resolveFulfillmentHint(order.value))
const currentTimelineIndex = computed(() => {
if (!order.value) return 0
return Math.max(order.value.timeline.length - 1, 0)
})
function timelineNodeClass (index: number) {
return resolveTimelineNodeClass(index, currentTimelineIndex.value)
}
useLoad((options) => {
orderId.value = options?.id || ''
})
useDidShow(() => {
void loadDetail()
})
return {
currentTimelineIndex,
fulfillmentHint,
formatPrice,
goOrders,
handleContact,
handlePrimaryAction,
loading,
order,
orderSubtitle,
sceneLabel,
statusDescription,
storeAddress,
timelineNodeClass
}
}