153 lines
3.8 KiB
TypeScript
153 lines
3.8 KiB
TypeScript
import type { CustomerProfileDto } from '#/api/customer';
|
|
import type { StoreListItemDto } from '#/api/store';
|
|
|
|
import { computed, onActivated, onMounted, ref, watch } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
import { createDefaultListFilters } from './customer-profile-page/constants';
|
|
import { createDataActions } from './customer-profile-page/data-actions';
|
|
import {
|
|
buildRouteQuery,
|
|
parseRouteQueryValue,
|
|
} from './customer-profile-page/helpers';
|
|
|
|
export function useCustomerProfilePage() {
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const PROFILE_ROUTE_PATH = '/customer/profile';
|
|
|
|
const stores = ref<StoreListItemDto[]>([]);
|
|
const selectedStoreId = ref('');
|
|
const activeCustomerKey = ref('');
|
|
const profile = ref<CustomerProfileDto | null>(null);
|
|
|
|
const isStoreLoading = ref(false);
|
|
const isProfileLoading = ref(false);
|
|
|
|
const filters = createDefaultListFilters();
|
|
|
|
const { loadStores, pickDefaultCustomerKey, loadProfile } = createDataActions(
|
|
{
|
|
stores,
|
|
profile,
|
|
filters,
|
|
isStoreLoading,
|
|
isProfileLoading,
|
|
},
|
|
);
|
|
|
|
const emptyDescription = computed(() => {
|
|
if (isStoreLoading.value || isProfileLoading.value) {
|
|
return '';
|
|
}
|
|
if (stores.value.length === 0) {
|
|
return '暂无门店,请先创建门店';
|
|
}
|
|
if (!activeCustomerKey.value) {
|
|
return '当前门店暂无客户';
|
|
}
|
|
return '暂无画像';
|
|
});
|
|
|
|
async function syncRouteQuery(storeId: string, customerKey: string) {
|
|
if (route.path !== PROFILE_ROUTE_PATH) {
|
|
return;
|
|
}
|
|
|
|
const currentStoreId = parseRouteQueryValue(route.query.storeId);
|
|
const currentCustomerKey = parseRouteQueryValue(route.query.customerKey);
|
|
if (currentStoreId === storeId && currentCustomerKey === customerKey) {
|
|
return;
|
|
}
|
|
|
|
await router.replace({
|
|
path: PROFILE_ROUTE_PATH,
|
|
query: buildRouteQuery(
|
|
route.query as Record<string, unknown>,
|
|
storeId,
|
|
customerKey,
|
|
),
|
|
});
|
|
}
|
|
|
|
function resolveStoreId(routeStoreId: string) {
|
|
if (!routeStoreId) {
|
|
return stores.value[0]?.id || '';
|
|
}
|
|
|
|
const matched = stores.value.find((item) => item.id === routeStoreId);
|
|
return matched?.id || stores.value[0]?.id || '';
|
|
}
|
|
|
|
async function loadProfileByRoute() {
|
|
if (route.path !== PROFILE_ROUTE_PATH) {
|
|
return;
|
|
}
|
|
|
|
if (stores.value.length === 0) {
|
|
await loadStores();
|
|
}
|
|
if (stores.value.length === 0) {
|
|
selectedStoreId.value = '';
|
|
activeCustomerKey.value = '';
|
|
profile.value = null;
|
|
return;
|
|
}
|
|
|
|
const routeStoreId = parseRouteQueryValue(route.query.storeId);
|
|
const routeCustomerKey = parseRouteQueryValue(route.query.customerKey);
|
|
|
|
const nextStoreId = resolveStoreId(routeStoreId);
|
|
selectedStoreId.value = nextStoreId;
|
|
|
|
let nextCustomerKey = routeCustomerKey;
|
|
if (!nextCustomerKey) {
|
|
nextCustomerKey = await pickDefaultCustomerKey(nextStoreId);
|
|
}
|
|
|
|
activeCustomerKey.value = nextCustomerKey;
|
|
if (!nextCustomerKey) {
|
|
profile.value = null;
|
|
await syncRouteQuery(nextStoreId, '');
|
|
return;
|
|
}
|
|
|
|
await loadProfile(nextStoreId, nextCustomerKey);
|
|
await syncRouteQuery(nextStoreId, nextCustomerKey);
|
|
}
|
|
|
|
watch(
|
|
() => route.fullPath,
|
|
() => {
|
|
if (route.path !== PROFILE_ROUTE_PATH) {
|
|
return;
|
|
}
|
|
void loadProfileByRoute();
|
|
},
|
|
);
|
|
|
|
onMounted(() => {
|
|
if (route.path === PROFILE_ROUTE_PATH) {
|
|
void loadProfileByRoute();
|
|
}
|
|
});
|
|
|
|
onActivated(() => {
|
|
if (route.path !== PROFILE_ROUTE_PATH) {
|
|
return;
|
|
}
|
|
|
|
if (stores.value.length === 0) {
|
|
void loadProfileByRoute();
|
|
}
|
|
});
|
|
|
|
return {
|
|
activeCustomerKey,
|
|
emptyDescription,
|
|
isProfileLoading,
|
|
isStoreLoading,
|
|
profile,
|
|
};
|
|
}
|