/** * OmniCard AI (CRMmp) - 名片主移动名片中心业务驱动层 * 分页拉自己的名片、空态与错误、编辑 / 海报跳转 */ import { CardProfile, CardStatus, OwnerPageData, OwnerPageQuery, } from '../../../common/types.uts'; import { fetchOwnerCardPage } from '../../../common/api.uts'; import { getCurrentLocale, getOmniText } from '../../../common/locale.uts'; export type CardHomeItem = { id?: string | number; name: string; title?: string; company?: string; status?: CardStatus; slug?: string; }; export type CardHomeCopyKey = | 'title' | 'subtitle' | 'searchPlaceholder' | 'refresh' | 'poster' | 'empty' | 'error' | 'loading' | 'statusDraft' | 'statusPublished' | 'statusArchived'; export type LoadCardsQuery = { page: number; size: number; keyWord?: string; }; export type LoadCardsApi = { fetchOwnerCardPage: ( query: OwnerPageQuery ) => Promise>; }; export type LoadCardsResult = { list: CardHomeItem[]; pagination: { page: number; size: number; total: number; }; empty: boolean; errorMessage: string; }; export type CardHomeState = { list: CardHomeItem[]; page: number; size: number; total: number; keyWord: string; loading: boolean; empty: boolean; errorMessage: string; }; export type CardHomePageOptions = { keyWord?: string; page?: string; size?: string; }; function isZhLocale(): boolean { return getCurrentLocale() === 'zh-CN'; } /** * 页面文案:分享走词典,标题 / 刷新 / 状态用本地词典 */ export function resolveCardHomeText(key: CardHomeCopyKey): string { const locale = getCurrentLocale(); if (key === 'poster') { return getOmniText(locale, 'card.share'); } if (key === 'empty') { return getOmniText(locale, 'common.empty'); } if (key === 'error') { return getOmniText(locale, 'common.error'); } if (key === 'loading') { return getOmniText(locale, 'common.loading'); } const zh = isZhLocale(); if (key === 'title') { return zh ? '名片中心' : 'Cards'; } if (key === 'subtitle') { return zh ? '编辑资料或生成分享海报' : 'Edit a card or open its poster'; } if (key === 'searchPlaceholder') { return zh ? '搜索姓名、职位或公司' : 'Search name, title or company'; } if (key === 'refresh') { return zh ? '刷新名片' : 'Refresh cards'; } if (key === 'statusDraft') { return zh ? '草稿' : 'Draft'; } if (key === 'statusPublished') { return zh ? '已发布' : 'Published'; } if (key === 'statusArchived') { return zh ? '已归档' : 'Archived'; } return ''; } export function statusLabel(status: string | null | undefined): string { if (status === 'draft') { return resolveCardHomeText('statusDraft'); } if (status === 'published') { return resolveCardHomeText('statusPublished'); } if (status === 'archived') { return resolveCardHomeText('statusArchived'); } return status != null ? status : ''; } export function formatCardField(value: string | null | undefined): string { if (value == null) { return ''; } return value; } function readOptionalSlug(card: CardProfile): string { const extra = card as CardHomeItem; if (extra.slug == null) { return ''; } return extra.slug.trim(); } export function toCardHomeItem(card: CardProfile): CardHomeItem { const slug = readOptionalSlug(card); return { id: card.id, name: card.name, title: card.title, company: card.company, status: card.status, slug: slug !== '' ? slug : undefined, }; } export function sanitizeCardQuery(query: LoadCardsQuery): OwnerPageQuery { const next: OwnerPageQuery = { page: query.page, size: query.size, }; if (query.keyWord != null) { const word = query.keyWord.trim(); if (word !== '') { next.keyWord = word; } } return next; } function readErrorMessage(err: unknown): string { if (err instanceof Error && err.message !== '') { return err.message; } return resolveCardHomeText('error'); } /** * 拉取名片分页。可注入 fetchOwnerCardPage */ export async function loadCards( query: LoadCardsQuery, api?: LoadCardsApi ): Promise { const fetchPage = api != null ? api.fetchOwnerCardPage : fetchOwnerCardPage; try { const data = await fetchPage(sanitizeCardQuery(query)); const rawList = data.list != null ? data.list : []; const list: CardHomeItem[] = []; for (let i = 0; i < rawList.length; i++) { list.push(toCardHomeItem(rawList[i])); } const pagination = data.pagination != null ? data.pagination : { page: query.page, size: query.size, total: list.length }; return { list, pagination, empty: list.length === 0, errorMessage: '', }; } catch (err) { return { list: [], pagination: { page: query.page, size: query.size, total: 0 }, empty: false, errorMessage: readErrorMessage(err), }; } } export function createCardHomeState(): CardHomeState { return { list: [], page: 1, size: 20, total: 0, keyWord: '', loading: false, empty: false, errorMessage: '', }; } export function applyCardHomeOptions( state: CardHomeState, options: CardHomePageOptions | null ): void { if (options == null) { return; } if (options.keyWord != null) { state.keyWord = options.keyWord; } } export function applyLoadResult( state: CardHomeState, result: LoadCardsResult ): void { state.list = result.list; state.page = result.pagination.page; state.size = result.pagination.size; state.total = result.pagination.total; state.empty = result.empty; state.errorMessage = result.errorMessage; } export async function refreshCards( state: CardHomeState, api?: LoadCardsApi ): Promise { if (state.loading) { return { list: state.list, pagination: { page: state.page, size: state.size, total: state.total, }, empty: state.empty, errorMessage: state.errorMessage, }; } state.loading = true; state.errorMessage = ''; const result = await loadCards( { page: state.page, size: state.size, keyWord: state.keyWord, }, api ); applyLoadResult(state, result); state.loading = false; return result; } export function buildEditUrl(id: string | number): string { return `/pages/owner/card/edit?id=${id}`; } export function buildQrcodeUrl(card: CardHomeItem): string { if (card.slug != null && card.slug !== '') { return `/pages/owner/card/qrcode?slug=${card.slug}`; } if (card.id != null) { return `/pages/owner/card/qrcode?id=${card.id}`; } return '/pages/owner/card/qrcode?id='; } export function openCardEdit(id: string | number): void { uni.navigateTo({ url: buildEditUrl(id), }); } export function openCardQrcode(card: CardHomeItem): void { uni.navigateTo({ url: buildQrcodeUrl(card), }); }