新增 H5 店铺订单列表/创建运单流程,优化登录首屏与分包加载;店铺订单状态标签素雅化;PC 露出创建运单/代发运单并移除仓库产品下拉。 Co-authored-by: Cursor <cursoragent@cursor.com>
121 lines
3.2 KiB
Vue
121 lines
3.2 KiB
Vue
<template>
|
|
<H5OrderTypeSheet v-model:visible="chooserVisible" @select="onSelectType" />
|
|
<H5PlaceOrderSheet v-model:visible="logisticsVisible" @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 { useRouter } from 'vue-router';
|
|
import type { CustomerProfileCompleteness } from '@/api/customer';
|
|
import { checkCustomerContactRequired } from '@/utils/customerContactGate';
|
|
import { h5Navigate } from '@/utils/device';
|
|
import H5OrderTypeSheet from './H5OrderTypeSheet.vue';
|
|
import H5PlaceOrderSheet from './H5PlaceOrderSheet.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';
|
|
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;
|
|
|
|
const router = useRouter();
|
|
|
|
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;
|
|
}
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
|
|
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);
|
|
}
|
|
},
|
|
});
|
|
|
|
function onSelectType(type: 'logistics' | 'pickup') {
|
|
if (type === 'pickup') {
|
|
switching = true;
|
|
phase.value = 'idle';
|
|
emit('update:visible', false);
|
|
h5Navigate(router, { path: '/h5/orders', query: { pickupSelect: '1' } });
|
|
requestAnimationFrame(() => {
|
|
switching = false;
|
|
});
|
|
return;
|
|
}
|
|
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>
|