- Vue 3 + TypeScript + Pinia + SCSS - 3-tab navigation (home, booking, profile) + 11 sub-pages - HTTP client with JWT auth, request interceptors - Pinia stores: user (auth, profile, memberships), studio, booking - Utility functions: price formatting, date helpers - WeChat login helper - All pages as stubs ready for implementation
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { post } from './request'
|
|
import type { UserProfileResponse } from '@mp-pilates/shared'
|
|
|
|
interface LoginResponse {
|
|
readonly token: string
|
|
readonly user: UserProfileResponse
|
|
}
|
|
|
|
export async function wxLogin(): Promise<LoginResponse> {
|
|
return new Promise((resolve, reject) => {
|
|
uni.login({
|
|
provider: 'weixin',
|
|
success: async (loginRes) => {
|
|
try {
|
|
const result = await post<LoginResponse>('/auth/login', {
|
|
code: loginRes.code,
|
|
})
|
|
uni.setStorageSync('token', result.token)
|
|
resolve(result)
|
|
} catch (err) {
|
|
reject(err)
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
reject(new Error(err.errMsg || '微信登录失败'))
|
|
},
|
|
})
|
|
})
|
|
}
|
|
|
|
export async function wxBindPhone(e: {
|
|
readonly detail: { readonly encryptedData: string; readonly iv: string }
|
|
}): Promise<UserProfileResponse> {
|
|
const { encryptedData, iv } = e.detail
|
|
return post<UserProfileResponse>('/auth/phone', { encryptedData, iv })
|
|
}
|
|
|
|
export function isLoggedIn(): boolean {
|
|
return !!uni.getStorageSync('token')
|
|
}
|
|
|
|
export function logout(): void {
|
|
uni.removeStorageSync('token')
|
|
}
|