117 lines
3.1 KiB
Vue
117 lines
3.1 KiB
Vue
<template>
|
|
<H5OrderTypeSheet v-model:visible="chooserVisible" @select="onSelectType" />
|
|
<H5PlaceOrderSheet v-model:visible="logisticsVisible" @success="onChildSuccess" />
|
|
<H5PickupOrderSheet v-model:visible="pickupVisible" @success="onChildSuccess" />
|
|
<H5CompleteContactSheet
|
|
v-model:visible="contactVisible"
|
|
:profile="contactProfile"
|
|
@success="onContactSuccess"
|
|
@cancel="onContactCancel"
|
|
/>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, ref, watch } from 'vue';
|
|
import type { CustomerProfileCompleteness } from '@/api/customer';
|
|
import { checkCustomerContactRequired } from '@/utils/customerContactGate';
|
|
import H5OrderTypeSheet from './H5OrderTypeSheet.vue';
|
|
import H5PlaceOrderSheet from './H5PlaceOrderSheet.vue';
|
|
import H5PickupOrderSheet from './H5PickupOrderSheet.vue';
|
|
import H5CompleteContactSheet from './H5CompleteContactSheet.vue';
|
|
|
|
defineOptions({ name: 'H5CreateOrderFlow' });
|
|
|
|
const props = defineProps<{ visible: boolean }>();
|
|
const emit = defineEmits<{
|
|
'update:visible': [boolean];
|
|
success: [];
|
|
}>();
|
|
|
|
type Phase = 'idle' | 'choose' | 'logistics' | 'pickup';
|
|
const phase = ref<Phase>('idle');
|
|
/** 从选择页切到表单时,避免 chooser 关闭误关整个 flow */
|
|
let switching = false;
|
|
const contactVisible = ref(false);
|
|
const contactProfile = ref<CustomerProfileCompleteness | null>(null);
|
|
const contactChecking = ref(false);
|
|
/** 补全成功后进入的阶段;取消则关闭整个 flow */
|
|
let pendingPhase: Phase | null = null;
|
|
|
|
watch(
|
|
() => props.visible,
|
|
async (v) => {
|
|
if (!v) {
|
|
phase.value = 'idle';
|
|
contactVisible.value = false;
|
|
pendingPhase = null;
|
|
return;
|
|
}
|
|
// 一进入下单流程即校验联系方式
|
|
contactChecking.value = true;
|
|
try {
|
|
const { needContact, profile } = await checkCustomerContactRequired();
|
|
if (needContact) {
|
|
contactProfile.value = profile;
|
|
pendingPhase = 'choose';
|
|
phase.value = 'idle';
|
|
contactVisible.value = true;
|
|
return;
|
|
}
|
|
phase.value = 'choose';
|
|
} finally {
|
|
contactChecking.value = false;
|
|
}
|
|
},
|
|
);
|
|
|
|
const chooserVisible = computed({
|
|
get: () => props.visible && phase.value === 'choose',
|
|
set: (v: boolean) => {
|
|
if (!v && phase.value === 'choose' && !switching) {
|
|
emit('update:visible', false);
|
|
}
|
|
},
|
|
});
|
|
|
|
const logisticsVisible = computed({
|
|
get: () => props.visible && phase.value === 'logistics',
|
|
set: (v: boolean) => {
|
|
if (!v && phase.value === 'logistics') {
|
|
emit('update:visible', false);
|
|
}
|
|
},
|
|
});
|
|
|
|
const pickupVisible = computed({
|
|
get: () => props.visible && phase.value === 'pickup',
|
|
set: (v: boolean) => {
|
|
if (!v && phase.value === 'pickup') {
|
|
emit('update:visible', false);
|
|
}
|
|
},
|
|
});
|
|
|
|
function onSelectType(type: 'logistics' | 'pickup') {
|
|
switching = true;
|
|
phase.value = type;
|
|
requestAnimationFrame(() => {
|
|
switching = false;
|
|
});
|
|
}
|
|
|
|
function onContactSuccess() {
|
|
const next = pendingPhase || 'choose';
|
|
pendingPhase = null;
|
|
phase.value = next;
|
|
}
|
|
|
|
function onContactCancel() {
|
|
pendingPhase = null;
|
|
emit('update:visible', false);
|
|
}
|
|
|
|
function onChildSuccess() {
|
|
emit('success');
|
|
}
|
|
</script>
|