import { reactive, computed, readonly } from 'vue' import * as authService from '../services/auth.js' import * as userProfileService from '../services/userProfile.js' import * as lifeEventService from '../services/lifeEvent.js' import * as epicScriptService from '../services/epicScript.js' import * as lifePathService from '../services/lifePath.js' const state = reactive({ isLoggedIn: false, isLoading: false, currentStep: 1, userInfo: null, userProfile: null, events: [], scripts: [], inspirationRecommendations: [], paths: [], currentPath: null, registrationData: { nickname: '', gender: '', mbti: '', zodiac: '', profession: '', hobbies: [], childhood: { date: '', text: '' }, joy: { date: '', text: '' }, low: { date: '', text: '' }, future: { vision: '', ideal: '' }, city: '', industry: '', company: '', personalityTags: [], personalityTagLibrary: [], hobbyLibrary: [], birthday: '' } }) const SESSION_STATUS = { AUTHENTICATED: 'authenticated', UNAUTHENTICATED: 'unauthenticated', ERROR: 'error' } const logAuth = (label, payload = {}) => { console.log(`[AUTH] ${label}`, payload) } const hasProfile = computed(() => { return state.userProfile && state.userProfile.nickname }) const resetAuthState = () => { state.isLoggedIn = false state.userInfo = null state.userProfile = null } const applyProfileResponse = (profileData) => { const profile = userProfileService.transformToFrontendFormat(profileData) state.userProfile = profile if (profile) { Object.assign(state.registrationData, profile) } return profile } const clearStoredTokens = () => { uni.removeStorageSync('access_token') uni.removeStorageSync('refresh_token') } const login = async (phone, smsCode) => { state.isLoading = true try { const res = await authService.login({ phone, smsCode }) state.isLoggedIn = true await fetchUserProfile() return { success: true, hasProfile: hasProfile.value } } catch (error) { return { success: false, error: error.message } } finally { state.isLoading = false } } const loginWithWechat = async (payload = {}) => { state.isLoading = true try { await authService.wechatLogin(payload) state.isLoggedIn = true await fetchUserProfile() return { success: true, hasProfile: hasProfile.value } } catch (error) { return { success: false, error: error.message } } finally { state.isLoading = false } } const logout = async () => { await authService.logout() resetAuthState() } const fetchUserProfile = async (options = {}) => { const { throwOnError = false } = options try { const res = await userProfileService.getCurrentProfile() if (res.data) { const profile = applyProfileResponse(res.data) logAuth('profile:success', { hasProfile: true }) return profile } else { state.userProfile = null logAuth('profile:empty', { hasProfile: false }) } return null } catch (error) { state.userProfile = null logAuth('profile:fail', { message: error.message, statusCode: error.statusCode, code: error.code, isNetworkError: Boolean(error.isNetworkError) }) if (throwOnError) { throw error } return null } } const saveUserProfile = async () => { state.isLoading = true try { const dataToSave = { ...state.registrationData } let response if (state.userProfile?.id) { response = await userProfileService.updateProfile({ id: state.userProfile.id, ...dataToSave }) } else { response = await userProfileService.createProfile(dataToSave) } if (response?.data) { applyProfileResponse(response.data) } await fetchUserProfile() return { success: true } } catch (error) { return { success: false, error: error.message } } finally { state.isLoading = false } } const updateRegistration = (data) => { Object.assign(state.registrationData, data) } const setCurrentStep = (step) => { state.currentStep = step } const fetchEvents = async () => { try { const res = await lifeEventService.getEventList() state.events = lifeEventService.transformListToFrontend(res.data || []) return state.events } catch (error) { return [] } } const createEvent = async (eventData) => { try { await lifeEventService.createEvent(eventData) await fetchEvents() return { success: true } } catch (error) { return { success: false, error: error.message } } } const updateEvent = async (eventData) => { try { await lifeEventService.updateEvent(eventData) await fetchEvents() return { success: true } } catch (error) { return { success: false, error: error.message } } } const deleteEvent = async (id) => { try { await lifeEventService.deleteEvent(id) await fetchEvents() return { success: true } } catch (error) { return { success: false, error: error.message } } } const assistEventWriting = async (eventData, callbacks = {}) => { try { const res = await lifeEventService.assistEventWriting(eventData, callbacks) return { success: true, data: res.data } } catch (error) { return { success: false, error: error.message } } } const chatAboutEvent = async (eventData) => { try { const res = await lifeEventService.chatAboutEvent(eventData) return { success: true, data: res.data } } catch (error) { return { success: false, error: error.message } } } const shareEvent = async (eventData) => { try { const res = await lifeEventService.shareEvent(eventData) return { success: true, data: res.data } } catch (error) { return { success: false, error: error.message } } } const favoriteEvent = async ({ id, favorite }) => { try { const res = await lifeEventService.favoriteEvent({ id, favorite }) return { success: true, data: res.data } } catch (error) { return { success: false, error: error.message } } } const getEventById = (id) => { return state.events.find(event => String(event.id) === String(id)) || null } const fetchScripts = async () => { try { const res = await epicScriptService.getScriptList() state.scripts = epicScriptService.transformListToFrontend(res.data || []) return state.scripts } catch (error) { return [] } } const createScript = async (scriptData) => { try { const res = await epicScriptService.createScript(scriptData) const script = epicScriptService.transformToFrontendFormat(res.data) await fetchScripts() return { success: true, data: script || res.data } } catch (error) { return { success: false, error: error.message } } } const updateScript = async (scriptData) => { try { const res = await epicScriptService.updateScript(scriptData) const script = epicScriptService.transformToFrontendFormat(res.data) await fetchScripts() return { success: true, data: script || res.data } } catch (error) { return { success: false, error: error.message } } } const deleteScript = async (id) => { try { await epicScriptService.deleteScript(id) await fetchScripts() return { success: true } } catch (error) { return { success: false, error: error.message } } } const fetchInspirationRecommendations = async () => { try { const res = await epicScriptService.getInspirationRecommendations() state.inspirationRecommendations = res.data || [] return state.inspirationRecommendations } catch (error) { state.inspirationRecommendations = [] return [] } } const fetchRandomInspirations = async (size = 3) => { try { const res = await epicScriptService.getRandomInspirations(size) return res.data || [] } catch (error) { return [] } } const generateScriptFromInspiration = async ({ prompt, style, length, useSocialInsights = true }) => { try { const profile = state.userProfile || state.registrationData const res = await epicScriptService.generateFromInspiration({ prompt, style, length, characterInfo: epicScriptService.buildCharacterInfo(profile), lifeEventsSummary: epicScriptService.buildLifeEventsSummary(state.events, profile), useSocialInsights, source: 'mini-program' }) await fetchScripts() return { success: true, data: res.data } } catch (error) { return { success: false, error: error.message } } } const getScriptById = (id) => { return state.scripts.find(script => String(script.id) === String(id)) || null } const selectScript = async (id) => { try { await epicScriptService.selectScript(id) await fetchScripts() return { success: true } } catch (error) { return { success: false, error: error.message } } } const fetchPaths = async () => { try { const res = await lifePathService.getPathList() state.paths = lifePathService.transformListToFrontend(res.data || []) return state.paths } catch (error) { return [] } } const setCurrentPath = (path) => { state.currentPath = path } const restoreSession = async () => { const token = uni.getStorageSync('access_token') const refreshToken = uni.getStorageSync('refresh_token') logAuth('restore:start', { hasAccessToken: Boolean(token), hasRefreshToken: Boolean(refreshToken) }) if (!token) { clearStoredTokens() resetAuthState() logAuth('restore:unauthenticated', { reason: 'missing_access_token' }) return { status: SESSION_STATUS.UNAUTHENTICATED, reason: 'missing_access_token' } } try { const isValid = await authService.validateTokenStrict() if (!isValid) { throw new Error('Token validation returned false') } logAuth('validate:success') state.isLoggedIn = true await fetchUserProfile({ throwOnError: true }) return { status: SESSION_STATUS.AUTHENTICATED, hasProfile: hasProfile.value, reason: 'access_token_valid' } } catch (validateError) { logAuth('validate:fail', { message: validateError.message, statusCode: validateError.statusCode, code: validateError.code, isNetworkError: Boolean(validateError.isNetworkError) }) if (validateError.isNetworkError) { resetAuthState() return { status: SESSION_STATUS.ERROR, reason: 'validate_network_error', error: validateError } } } if (!refreshToken) { clearStoredTokens() resetAuthState() logAuth('refresh:skip', { reason: 'missing_refresh_token' }) return { status: SESSION_STATUS.UNAUTHENTICATED, reason: 'missing_refresh_token' } } try { logAuth('refresh:start') await authService.refreshToken() logAuth('refresh:success') state.isLoggedIn = true await fetchUserProfile({ throwOnError: true }) return { status: SESSION_STATUS.AUTHENTICATED, hasProfile: hasProfile.value, reason: 'refresh_token_valid' } } catch (refreshError) { logAuth('refresh:fail', { message: refreshError.message, statusCode: refreshError.statusCode, code: refreshError.code, isNetworkError: Boolean(refreshError.isNetworkError) }) if (refreshError.isNetworkError) { resetAuthState() return { status: SESSION_STATUS.ERROR, reason: 'refresh_network_error', error: refreshError } } clearStoredTokens() resetAuthState() return { status: SESSION_STATUS.UNAUTHENTICATED, reason: 'refresh_failed', error: refreshError } } } const initialize = async () => { return restoreSession() } export const useAppStore = () => { return readonly({ get isLoggedIn() { return state.isLoggedIn }, get isLoading() { return state.isLoading }, get currentStep() { return state.currentStep }, get userInfo() { return state.userInfo }, get userProfile() { return state.userProfile }, get events() { return state.events }, get scripts() { return state.scripts }, get inspirationRecommendations() { return state.inspirationRecommendations }, get paths() { return state.paths }, get currentPath() { return state.currentPath }, get registrationData() { return state.registrationData }, get hasProfile() { return hasProfile.value }, login, loginWithWechat, logout, fetchUserProfile, saveUserProfile, updateRegistration, setCurrentStep, fetchEvents, createEvent, updateEvent, deleteEvent, assistEventWriting, chatAboutEvent, shareEvent, favoriteEvent, getEventById, fetchScripts, createScript, updateScript, deleteScript, fetchInspirationRecommendations, fetchRandomInspirations, generateScriptFromInspiration, getScriptById, selectScript, fetchPaths, setCurrentPath, initialize, restoreSession, SESSION_STATUS }) } export default useAppStore