import type { Ref } from 'vue' import type { Router } from 'vue-router' import type { Profile } from '@yuxingu/types' import { api } from '../api/client' import { copyText } from '../lib/shareLink' export const profileRelationOptions = [ { value: 'family', label: '家人' }, { value: 'friend', label: '朋友' }, { value: 'partner', label: '伴侣' }, { value: 'colleague', label: '同事' }, { value: 'other', label: '其他' }, ] export function formatProfileDate(v: string) { return (v || '').slice(0, 10) } export function avatarInitial(p: Profile) { const n = p.display_name || (p.relation === 'self' ? '我' : 'T') return n.slice(0, 1) } export function relationLabel(t?: string | null) { const map: Record = { partner: '伴侣', friend: '朋友', family: '家人', colleague: '同事', other: '关系对象', } return map[t || ''] || '关系对象' } export function splitBirth(v: string) { const s = formatProfileDate(v) const [y, m, d] = s.split('-') return { y: y || '', m: m ? String(Number(m)) : '', d: d ? String(Number(d)) : '' } } export function joinBirth(y: string, m: string, d: string) { const yi = Number(y) const mi = Number(m) const di = Number(d) if (!yi || !mi || !di) return '' return `${yi}-${String(mi).padStart(2, '0')}-${String(di).padStart(2, '0')}` } export type ProfilePageActionRefs = { items: Ref loading: Ref error: Ref busyId: Ref editing: Ref showAddForm: Ref showInviteFill: Ref formName: Ref formY: Ref formM: Ref formD: Ref formPlace: Ref formRelationType: Ref formGeoVisible: Ref formError: Ref saving: Ref newName: Ref newY: Ref newM: Ref newD: Ref newPlace: Ref newRelationType: Ref addError: Ref adding: Ref inviting: Ref invitePath: Ref inviteError: Ref inviteHint: Ref copyBusy: Ref selfProfile: { value: Profile | undefined } routeAdd: () => string | undefined routeInviteFill: () => string | undefined router: Router } export function createProfilePageActions(r: ProfilePageActionRefs) { function toggleAdd() { r.showAddForm.value = !r.showAddForm.value if (r.showAddForm.value) { r.editing.value = null r.showInviteFill.value = false } } function openAddForm() { r.showAddForm.value = true r.showInviteFill.value = false r.editing.value = null } function openInviteFill() { r.showInviteFill.value = true r.showAddForm.value = false r.editing.value = null r.inviteError.value = '' if (!r.selfProfile.value) { r.inviteHint.value = '请先完成自己的档案,再邀请好友填写。' } else { r.inviteHint.value = '' } } function closeInviteFill() { r.showInviteFill.value = false void r.router.replace({ path: '/profile', query: {} }) } function applyQueryFlags() { if (r.routeAdd() === '1') openAddForm() if (r.routeInviteFill() === '1') openInviteFill() } async function createFillInvite() { if (!r.selfProfile.value) { r.inviteError.value = '请先完成自己的档案' return } r.inviting.value = true r.inviteError.value = '' r.inviteHint.value = '' try { const res = await api.createSynastryInvite(r.selfProfile.value.id) r.invitePath.value = `${location.origin}${res.path}` r.inviteHint.value = '好友打开链接后填写生日即可;也可用于合盘。' } catch (e) { r.inviteError.value = e instanceof Error ? e.message : '生成失败' } finally { r.inviting.value = false } } async function copyInvite() { if (!r.invitePath.value) return r.copyBusy.value = true const ok = await copyText(r.invitePath.value) r.inviteHint.value = ok ? '链接已复制,发给家人或朋友即可。' : '复制失败,请长按链接手动复制。' r.copyBusy.value = false } async function load() { r.loading.value = true r.error.value = '' try { const res = await api.listProfiles() r.items.value = res.items || [] } catch (e) { r.error.value = e instanceof Error ? e.message : '加载失败' } finally { r.loading.value = false } } function startEdit(p: Profile) { r.editing.value = p r.showAddForm.value = false r.formName.value = p.display_name || '' const b = splitBirth(p.birth_date) r.formY.value = b.y r.formM.value = b.m r.formD.value = b.d r.formPlace.value = p.birth_place || '' r.formRelationType.value = p.relation_type || 'partner' r.formGeoVisible.value = !!p.geo_visible r.formError.value = '' } async function saveEdit() { if (!r.editing.value) return r.saving.value = true r.formError.value = '' try { const birth = joinBirth(r.formY.value, r.formM.value, r.formD.value) if (!birth) throw new Error('请填写生日') const body: { display_name: string birth_date: string relation_type?: string birth_place?: string geo_visible?: boolean } = { display_name: r.formName.value.trim(), birth_date: birth, birth_place: r.formPlace.value || '', } if (r.editing.value.relation === 'other') body.relation_type = r.formRelationType.value if (r.editing.value.relation === 'self') body.geo_visible = r.formGeoVisible.value await api.updateProfile(r.editing.value.id, body) r.editing.value = null await load() } catch (e) { r.formError.value = e instanceof Error ? e.message : '保存失败' } finally { r.saving.value = false } } async function remove(p: Profile) { if (!confirm(`确定删除「${p.display_name || '档案'}」?`)) return r.busyId.value = p.id r.error.value = '' try { await api.deleteProfile(p.id) if (r.editing.value?.id === p.id) r.editing.value = null await load() } catch (e) { r.error.value = e instanceof Error ? e.message : '删除失败' } finally { r.busyId.value = '' } } async function addOther() { r.adding.value = true r.addError.value = '' try { const birth = joinBirth(r.newY.value, r.newM.value, r.newD.value) if (!birth) throw new Error('请填写生日') await api.createProfile({ relation: 'other', birth_date: birth, display_name: r.newName.value.trim() || 'TA', relation_type: r.newRelationType.value, birth_place: r.newPlace.value || undefined, }) r.newName.value = '' r.newY.value = '' r.newM.value = '' r.newD.value = '' r.newPlace.value = '' r.showAddForm.value = false await load() if (r.routeAdd() === '1') void r.router.replace({ path: '/profile', query: {} }) } catch (e) { r.addError.value = e instanceof Error ? e.message : '添加失败' } finally { r.adding.value = false } } return { toggleAdd, openAddForm, openInviteFill, closeInviteFill, applyQueryFlags, createFillInvite, copyInvite, load, startEdit, saveEdit, remove, addOther, } }