feat(@vben/web-antd): 客户画像页面与二级抽屉

This commit is contained in:
2026-03-03 14:41:04 +08:00
parent 543b82ab5e
commit 4fe8bbdba7
38 changed files with 3591 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
import type { Ref } from 'vue';
import type { CustomerProfileListFilters } from '../../types';
import type { CustomerProfileDto, CustomerTagFilter } from '#/api/customer';
import type { StoreListItemDto } from '#/api/store';
import { getCustomerListApi, getCustomerProfileApi } from '#/api/customer';
import { getStoreListApi } from '#/api/store';
import {
PROFILE_DEFAULT_LIST_PAGE,
PROFILE_DEFAULT_LIST_PAGE_SIZE,
PROFILE_STORE_QUERY_PAGE_SIZE,
} from './constants';
import {
normalizeOrderCountRangeFilter,
normalizeRegisterPeriodFilter,
normalizeTagFilter,
} from './helpers';
interface CreateDataActionsOptions {
filters: CustomerProfileListFilters;
isProfileLoading: Ref<boolean>;
isStoreLoading: Ref<boolean>;
profile: Ref<CustomerProfileDto | null>;
stores: Ref<StoreListItemDto[]>;
}
/**
* 文件职责:客户画像页数据加载动作。
*/
export function createDataActions(options: CreateDataActionsOptions) {
async function loadStores() {
options.isStoreLoading.value = true;
try {
const result = await getStoreListApi({
page: 1,
pageSize: PROFILE_STORE_QUERY_PAGE_SIZE,
});
options.stores.value = result.items;
return result.items;
} finally {
options.isStoreLoading.value = false;
}
}
async function pickDefaultCustomerKey(storeId: string) {
if (!storeId) {
return '';
}
const result = await getCustomerListApi({
storeId,
page: PROFILE_DEFAULT_LIST_PAGE,
pageSize: PROFILE_DEFAULT_LIST_PAGE_SIZE,
keyword: options.filters.keyword.trim() || undefined,
tag: normalizeTagFilter(options.filters.tag as CustomerTagFilter),
orderCountRange: normalizeOrderCountRangeFilter(
options.filters.orderCountRange,
),
registerPeriod: normalizeRegisterPeriodFilter(
options.filters.registerPeriod,
),
});
return result.items[0]?.customerKey || '';
}
async function loadProfile(storeId: string, customerKey: string) {
if (!storeId || !customerKey) {
options.profile.value = null;
return null;
}
options.isProfileLoading.value = true;
try {
const result = await getCustomerProfileApi({
storeId,
customerKey,
});
options.profile.value = result;
return result;
} finally {
options.isProfileLoading.value = false;
}
}
return {
loadProfile,
loadStores,
pickDefaultCustomerKey,
};
}