import { getToken, request, subscribeProfile } from './request' import { isFrontendPreview } from './frontendPreview' import { isAvatarDemo } from './avatarDemo' import { createTiangongStore, RemoteDeity } from '../utils/tiangongStore' import { createTiangongMock, DeityId } from '../utils/tiangongMock' import wealth from '../assets/tiangong/proto-wealth.jpg' import fortune from '../assets/tiangong/proto-fortune.jpg' import longevity from '../assets/tiangong/proto-longevity.jpg' import wenchang from '../assets/tiangong/proto-wenchang.jpg' import matchmaker from '../assets/tiangong/proto-matchmaker.jpg' import wealthStatue from '../assets/tiangong/proto-wealth-statue.png' import fortuneStatue from '../assets/tiangong/proto-fortune-statue.png' export type Deity = { id: DeityId; name: string; ritualName: string; icon: string; statue: string; introduction?: string; missingStatue?: boolean } export const deityCatalog: Deity[] = [ { id: 'wealth', name: '财神', ritualName: '武财神', icon: wealth, statue: wealthStatue }, { id: 'fortune', name: '禄星', ritualName: '禄星', icon: fortune, statue: fortuneStatue, introduction: '上清灵宝天尊灵宝天尊列在第二神阶之中位,仅次于元始天尊。他居三十六天之第二高位上清境,治蕊珠日阙,管七映紫房。其核心神职是演说灵宝真经、开度三界六道众生,掌金箓玉策、敷演道法,主万物生化,调和阴阳,是灵宝法系与斋醮科仪的核心尊神。' }, { id: 'longevity', name: '寿星', ritualName: '寿星', icon: longevity, statue: longevity, missingStatue: true }, { id: 'wenchang', name: '文昌星', ritualName: '文昌星', icon: wenchang, statue: wenchang, missingStatue: true }, { id: 'matchmaker', name: '月老', ritualName: '月老', icon: matchmaker, statue: matchmaker, missingStatue: true } ] export const getDeity = (id: string | undefined) => deityCatalog.find(item => item.id === id) export const tiangongMock = createTiangongMock() export const isTiangongDemo = () => isFrontendPreview() || isAvatarDemo() const live = createTiangongStore({ key: getToken, resolve: name => deityCatalog.find(item => item.name === name || item.ritualName === name)?.id, load: () => request('/api/tiangong/items'), offer: (holdingId, type, content) => request<{ id: number }>('/api/user/virtual-items/offerings', { method: 'POST', data: { userVirtualItemId: holdingId, offeringType: type, content } }), dedicate: (holdingId, name, content) => request<{ id: number }>('/api/user/virtual-items/dedications', { method: 'POST', data: { userVirtualItemId: holdingId, name, content } }) }) export const tiangongSession = { snapshot: () => isTiangongDemo() ? tiangongMock.snapshot() : live.snapshot(), refresh: (force = false) => isTiangongDemo() ? Promise.resolve() : live.refresh(force), subscribe: (listener: () => void) => { const demo = tiangongMock.subscribe(listener), remote = live.subscribe(listener) const account = subscribeProfile(() => { listener(); tiangongSession.refresh().catch(() => {}) }) return () => { demo(); remote(); account() } }, incense: (id: DeityId) => { if (!isTiangongDemo()) return live.incense(id) const startsRound = !tiangongMock.snapshot().deities[id].lit tiangongMock.incense(id) return { startsRound } }, refreshIncense: (id: DeityId) => isTiangongDemo() ? tiangongMock.refreshIncense(id) : live.refreshIncense(), wish: async (id: DeityId, text: string) => { if (isTiangongDemo()) tiangongMock.wish(id, text); else await live.wish(id, text) }, dedicate: async (id: DeityId, name: string, text: string) => { if (isTiangongDemo()) tiangongMock.dedicate(id, name, text); else await live.dedicate(id, name, text) } } export const listMockDeities = () => { const snapshot = tiangongMock.snapshot(); return deityCatalog.map(item => ({ ...item, ...snapshot.deities[item.id] })) } export type DeityBindingInfo = { bindingId: string deityId: DeityId uniqueId: string bound: boolean guardedDays: number remainingUnbinds: number } export type UnbindResult = { binding: DeityBindingInfo; hasAnyBoundDeity: boolean } // 其余绑定/送神契约尚未接入,不会自动请求。实际供奉接口见 tiangongSession。 export const tiangongRemoteContract = { list: () => request('/api/tiangong/items'), detail: (id: DeityId) => request(`/api/tiangong/items/${id}`), invite: (id: DeityId, bindingId: string) => request(`/api/tiangong/items/${id}/invite`, { method: 'POST', data: { bindingId } }), sendOff: (id: DeityId) => request(`/api/tiangong/items/${id}/send-off`, { method: 'POST' }), binding: (bindingId: string) => request(`/api/tiangong/bindings/${encodeURIComponent(bindingId)}`), // 拟定接口:服务端需验证NFC凭证、一物一账号及年度额度。Mock不会调用。 resolveBinding: (nfcCredential: string) => request('/api/tiangong/bindings/resolve', { method: 'POST', data: { nfcCredential } }), unbind: (bindingId: string) => request(`/api/tiangong/bindings/${encodeURIComponent(bindingId)}/unbind`, { method: 'POST' }) }