feat(miniprogram): 初始化 Taro 4 + React 小程序项目
- 手动创建 Taro 4.2 + React 18 + TypeScript 项目骨架 - 配置 webpack5 编译、SCSS 样式、医疗清新主题 - 实现 API 请求层(JWT 自动注入 + token 刷新) - 实现 auth store(微信登录 + 手机号绑定 + 就诊人管理) - 实现登录页(微信一键登录 + 手机号授权绑定) - 实现首页(问候栏 + 今日健康卡片 + 快捷服务 + 即将到来) - 实现我的页面(个人信息 + 功能菜单 + 退出登录) - 健康/预约/资讯占位页 - TabBar 5 个入口:首页/健康/预约/资讯/我的
This commit is contained in:
101
apps/miniprogram/src/stores/auth.ts
Normal file
101
apps/miniprogram/src/stores/auth.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { create } from 'zustand';
|
||||
import Taro from '@tarojs/taro';
|
||||
import * as authApi from '../services/auth';
|
||||
|
||||
interface AuthState {
|
||||
token: string | null;
|
||||
refreshToken: string | null;
|
||||
user: { id: string; username: string; display_name?: string; phone?: string } | null;
|
||||
currentPatient: authApi.PatientInfo | null;
|
||||
patients: authApi.PatientInfo[];
|
||||
loading: boolean;
|
||||
|
||||
login: (code: string) => Promise<boolean>;
|
||||
bindPhone: (openid: string, encryptedData: string, iv: string) => Promise<boolean>;
|
||||
setCurrentPatient: (patient: authApi.PatientInfo) => void;
|
||||
loadPatients: () => Promise<void>;
|
||||
logout: () => void;
|
||||
restore: () => void;
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthState>((set, get) => ({
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
user: null,
|
||||
currentPatient: null,
|
||||
patients: [],
|
||||
loading: false,
|
||||
|
||||
restore: () => {
|
||||
const token = Taro.getStorageSync('access_token') || null;
|
||||
const refreshToken = Taro.getStorageSync('refresh_token') || null;
|
||||
const user = Taro.getStorageSync('user') || null;
|
||||
const currentPatient = Taro.getStorageSync('current_patient') || null;
|
||||
set({ token, refreshToken, user, currentPatient });
|
||||
},
|
||||
|
||||
login: async (code: string) => {
|
||||
set({ loading: true });
|
||||
try {
|
||||
const resp = await authApi.wechatLogin(code);
|
||||
if (resp.bound && resp.token) {
|
||||
const { access_token, refresh_token, user } = resp.token;
|
||||
Taro.setStorageSync('access_token', access_token);
|
||||
Taro.setStorageSync('refresh_token', refresh_token);
|
||||
Taro.setStorageSync('user', user);
|
||||
Taro.setStorageSync('tenant_id', user.tenant_id || '');
|
||||
set({ token: access_token, refreshToken: refresh_token, user, loading: false });
|
||||
return true;
|
||||
}
|
||||
set({ loading: false });
|
||||
return false;
|
||||
} catch {
|
||||
set({ loading: false });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
bindPhone: async (openid: string, encryptedData: string, iv: string) => {
|
||||
set({ loading: true });
|
||||
try {
|
||||
const resp: any = await authApi.wechatBindPhone(openid, encryptedData, iv);
|
||||
const { access_token, refresh_token, user } = resp;
|
||||
Taro.setStorageSync('access_token', access_token);
|
||||
Taro.setStorageSync('refresh_token', refresh_token);
|
||||
Taro.setStorageSync('user', user);
|
||||
set({ token: access_token, refreshToken: refresh_token, user, loading: false });
|
||||
return true;
|
||||
} catch {
|
||||
set({ loading: false });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
setCurrentPatient: (patient) => {
|
||||
Taro.setStorageSync('current_patient_id', patient.id);
|
||||
Taro.setStorageSync('current_patient', patient);
|
||||
set({ currentPatient: patient });
|
||||
},
|
||||
|
||||
loadPatients: async () => {
|
||||
try {
|
||||
const patients = await authApi.getPatients();
|
||||
set({ patients });
|
||||
if (patients.length > 0 && !get().currentPatient) {
|
||||
get().setCurrentPatient(patients[0]);
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
Taro.removeStorageSync('access_token');
|
||||
Taro.removeStorageSync('refresh_token');
|
||||
Taro.removeStorageSync('user');
|
||||
Taro.removeStorageSync('current_patient');
|
||||
Taro.removeStorageSync('current_patient_id');
|
||||
set({ token: null, refreshToken: null, user: null, currentPatient: null, patients: [] });
|
||||
Taro.redirectTo({ url: '/pages/login/index' });
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user