配置http,完成登录信息缓存,添加部分pinia配置
| | |
| | | /* eslint-disable no-param-reassign */ |
| | | import qs from 'qs' |
| | | import { useUserStore } from '@/store' |
| | | import { useAccessStore } from '@/store' |
| | | import { platform } from '@/utils/platform' |
| | | import { getEnvBaseUrl } from '@/utils' |
| | | const clientId = import.meta.env.VITE_APP_CLIENT_ID |
| | | |
| | | export type CustomRequestOptions = UniApp.RequestOptions & { |
| | | query?: Record<string, any> |
| | |
| | | ...options.header, |
| | | } |
| | | // 3. æ·»å token 请æ±å¤´æ è¯ |
| | | const userStore = useUserStore() |
| | | const { token } = userStore.userInfo as unknown as IUserInfo |
| | | const accessStore = useAccessStore() |
| | | const token = accessStore.accessInfo.access_token |
| | | if (token) { |
| | | options.header.Authorization = `Bearer ${token}` |
| | | options.header.clientid = clientId |
| | | } |
| | | }, |
| | | } |
| | |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import { TestEnum } from '@/typings' |
| | | import PLATFORM from '@/utils/platform' |
| | | import { getAllMenusApi } from '@/service/menu' |
| | | |
| | | defineOptions({ |
| | | name: 'Home', |
| | |
| | | |
| | | // è·åå±å¹è¾¹çå°å®å
¨åºåè·ç¦» |
| | | const { safeAreaInsets } = uni.getSystemInfoSync() |
| | | const author = ref('è²é¸½') |
| | | const description = ref( |
| | | 'unibest æ¯ä¸ä¸ªéæäºå¤ç§å·¥å
·åææ¯ç uniapp å¼å模æ¿ï¼ç± uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode æå»ºï¼æ¨¡æ¿å
·æä»£ç æç¤ºãèªå¨æ ¼å¼åãç»ä¸é
ç½®ã代ç çæ®µçåè½ï¼å¹¶å
ç½®äºè®¸å¤å¸¸ç¨çåºæ¬ç»ä»¶ååºæ¬åè½ï¼è®©ä½ ç¼å uniapp æ¥æ best ä½éªã', |
| | | ) |
| | | // æµè¯ uni API èªå¨å¼å
¥ |
| | | |
| | | const getAllMenus = async () => { |
| | | const menuList = await getAllMenusApi() |
| | | console.error(menuList) |
| | | } |
| | | |
| | | onLoad(() => { |
| | | console.log(author) |
| | | console.log(TestEnum.A) |
| | | // getAllMenus() |
| | | }) |
| | | |
| | | const menuList = reactive([ |
| | |
| | | ]) |
| | | |
| | | function handleUserInfo() { |
| | | console.error('12121') |
| | | getAllMenus() |
| | | } |
| | | |
| | | |
| | |
| | | <wd-cell-group border> |
| | | <wd-input |
| | | label="ç¨æ·å" |
| | | label-width="100px" |
| | | label-width="200rpx" |
| | | prop="username" |
| | | clearable |
| | | v-model="model.username" |
| | |
| | | /> |
| | | <wd-input |
| | | label="å¯ç " |
| | | label-width="100px" |
| | | label-width="200rpx" |
| | | prop="password" |
| | | show-password |
| | | clearable |
| | |
| | | :rules="[{ required: true, message: '请填åå¯ç ' }]" |
| | | /> |
| | | </wd-cell-group> |
| | | <view class="footer mt-6"> |
| | | <wd-button type="primary" size="large" @click="handleSubmit" block>æäº¤</wd-button> |
| | | <view class="footer"> |
| | | <view class="w-full text-end"> |
| | | <wd-checkbox v-model="rember" shape="square" @change="handleChange"> |
| | | è®°ä½å¯ç |
| | | </wd-checkbox> |
| | | </view> |
| | | <wd-button class="mt-6" type="primary" size="large" @click="handleSubmit" block> |
| | | æäº¤ |
| | | </wd-button> |
| | | </view> |
| | | </wd-form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { currRoute } from '@/utils' |
| | | import { useUserStore, useAccessStore } from '@/store' |
| | | import { useUserStore, useAccessStore, useSystemConfigStore } from '@/store' |
| | | import { useToast } from 'wot-design-uni' |
| | | import { login } from '@/service/login' |
| | | import { login, getUserInfo } from '@/service/login' |
| | | import type { UserInfo } from '@/service/login.d' |
| | | import { TestEnum } from '@/typings' |
| | | const userStore = useUserStore() |
| | | const accessStore = useAccessStore() |
| | | const configStore = useSystemConfigStore() |
| | | const { success: showSuccess } = useToast() |
| | | |
| | | const model = reactive<{ |
| | | username: string |
| | | password: string |
| | | }>({ |
| | | username: 'admin', |
| | | password: 'admin123', |
| | | username: '', |
| | | password: '', |
| | | }) |
| | | const rember = ref<boolean>(false) |
| | | |
| | | function handleChange({ value }) { |
| | | console.log(value) |
| | | } |
| | | |
| | | const form = ref() |
| | | function handleSubmit() { |
| | |
| | | console.log(error, 'error') |
| | | }) |
| | | } |
| | | |
| | | onLoad(() => { |
| | | const { remberPassword, username, password } = configStore.systemConfigInfo |
| | | if (remberPassword) { |
| | | rember.value = true |
| | | model.username = username |
| | | model.password = password |
| | | } |
| | | }) |
| | | |
| | | const toLogin = async () => { |
| | | // è®°ä½å¯ç |
| | | if (rember.value) { |
| | | configStore.setConfigInfo({ ...model, ...{ remberPassword: true } }) |
| | | } |
| | | |
| | | const res = await login(model) |
| | | console.error(res) |
| | | accessStore.setAccessInfo(res as any) |
| | | console.error(accessStore.accessInfo.access_token) |
| | | // userStore.setUserInfo({ nickname: 'è²é¸½', avatar: '', token: 'abcdef' }) |
| | | const backUserInfo: any = await getUserInfo() |
| | | /** |
| | | * ç»å½è¶
æ¶çæ
åµ |
| | | */ |
| | | if (!backUserInfo) { |
| | | throw new Error('è·åç¨æ·ä¿¡æ¯å¤±è´¥.') |
| | | } |
| | | const { permissions = [], roles = [], user } = backUserInfo |
| | | /** |
| | | * ä»åå°user -> vben userè½¬æ¢ |
| | | */ |
| | | const userInfo: UserInfo = { |
| | | avatar: user.avatar ?? '', |
| | | permissions, |
| | | realName: user.nickName, |
| | | roles, |
| | | userId: user.userId, |
| | | deptId: user.deptId, |
| | | username: user.userName, |
| | | } |
| | | userStore.setUserInfo(userInfo) |
| | | const { query } = currRoute() |
| | | console.error(query.redirect) |
| | | uni.switchTab({ url: query.redirect }) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | tenantId?: string; |
| | | grantType?: string; |
| | | } |
| | | |
| | | |
| | | export interface User { |
| | | avatar: string; |
| | | createTime: string; |
| | | deptId: number; |
| | | deptName: string; |
| | | email: string; |
| | | loginDate: string; |
| | | loginIp: string; |
| | | nickName: string; |
| | | phonenumber: string; |
| | | remark: string; |
| | | roles: Role[]; |
| | | sex: string; |
| | | status: string; |
| | | tenantId: string; |
| | | userId: number; |
| | | userName: string; |
| | | userType: string; |
| | | } |
| | | |
| | | |
| | | export interface UserInfoResp { |
| | | permissions: string[]; |
| | | roles: string[]; |
| | | user: User; |
| | | } |
| | | |
| | | |
| | | |
| | | interface BasicUserInfo { |
| | | /** |
| | | * 头å |
| | | */ |
| | | avatar: string; |
| | | /** |
| | | * é¨é¨id |
| | | */ |
| | | deptId: number; |
| | | /** |
| | | * ç¨æ·æé |
| | | */ |
| | | permissions: string[]; |
| | | /** |
| | | * ç¨æ·æµç§° |
| | | */ |
| | | realName: string; |
| | | /** |
| | | * ç¨æ·è§è² |
| | | */ |
| | | roles: string[]; |
| | | /** |
| | | * ç¨æ·id |
| | | */ |
| | | userId: number | string; |
| | | |
| | | /** |
| | | * ç¨æ·å |
| | | */ |
| | | username: string; |
| | | } |
| | | |
| | | |
| | | /** ç¨æ·ä¿¡æ¯ */ |
| | | interface UserInfo extends BasicUserInfo { |
| | | /** |
| | | * æå±ä½¿ç¨ |
| | | */ |
| | | [key: string]: any; |
| | | } |
| | |
| | | import { http } from '@/utils/http' |
| | | import type { LoginParams } from './login.d' |
| | | import type { LoginParams, UserInfoResp } from './login.d' |
| | | const clientId = import.meta.env.VITE_APP_CLIENT_ID |
| | | |
| | | const DEFAULT_TENANT_ID = '000000' |
| | | const GRANT_TYPE = 'password' |
| | | |
| | | /** GET è¯·æ± */ |
| | | export const getFooAPI = (name: string) => { |
| | | return http.get<LoginParams>('/foo', { name }) |
| | | } |
| | | |
| | | /** POST è¯·æ± */ |
| | | /** get è¯·æ± */ |
| | | export const login = (params: LoginParams) => { |
| | | const { username, password } = params |
| | | // æé æ°ç请æ±åæ°ï¼é¿å
ç´æ¥ä¿®æ¹åå§å¯¹è±¡ |
| | |
| | | } |
| | | return http.post<any>('/auth/login', requestData) |
| | | } |
| | | |
| | | export const getUserInfo = () => { |
| | | return http.get<null | UserInfoResp>('/system/user/getInfo') |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * @description: èåmeta |
| | | * @param title èåå |
| | | * @param icon èå徿 |
| | | * @param noCache æ¯å¦ä¸ç¼å |
| | | * @param link å¤é¾é¾æ¥ |
| | | */ |
| | | export interface MenuMeta { |
| | | icon: string; |
| | | link?: string; |
| | | noCache: boolean; |
| | | title: string; |
| | | } |
| | | |
| | | /** |
| | | * @description: èå |
| | | * @param name èåå |
| | | * @param path èåè·¯å¾ |
| | | * @param hidden æ¯å¦éè |
| | | * @param component ç»ä»¶åç§° Laout |
| | | * @param alwaysShow æ»æ¯æ¾ç¤º |
| | | * @param query è·¯ç±åæ°(jsonå½¢å¼) |
| | | * @param meta è·¯ç±ä¿¡æ¯ |
| | | * @param children åè·¯ç±ä¿¡æ¯ |
| | | */ |
| | | export interface Menu { |
| | | alwaysShow?: boolean; |
| | | children: Menu[]; |
| | | component: string; |
| | | hidden: boolean; |
| | | meta: MenuMeta; |
| | | name: string; |
| | | path: string; |
| | | query?: string; |
| | | redirect?: string; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { http } from '@/utils/http' |
| | | import type { Menu } from './menu.d' |
| | | |
| | | export const getAllMenusApi = () => { |
| | | return http.get<Menu>('/system/menu/getRouters') |
| | | } |
| | |
| | | } |
| | | |
| | | export const useAccessStore = defineStore( |
| | | 'access', |
| | | 'accessInfo', |
| | | () => { |
| | | const accessInfo = ref<AccessInfo>({ ...initState }) |
| | | |
| | |
| | | // 模åç»ä¸å¯¼åº |
| | | export * from './user' |
| | | export * from './access' |
| | | export * from './system-config' |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineStore } from 'pinia' |
| | | import { ref } from 'vue' |
| | | |
| | | const initState = { |
| | | remberPassword: false, |
| | | username: '', |
| | | password: '', |
| | | } |
| | | |
| | | export const useSystemConfigStore = defineStore( |
| | | 'systemConfig', |
| | | () => { |
| | | const systemConfigInfo = ref<any>({ ...initState }) |
| | | |
| | | const setConfigInfo = (val: any) => { |
| | | systemConfigInfo.value = val |
| | | } |
| | | |
| | | const clearConfigInfo = () => { |
| | | systemConfigInfo.value = { ...initState } |
| | | } |
| | | // ä¸è¬æ²¡æresetéæ±ï¼ä¸éè¦çå¯ä»¥å é¤ |
| | | const reset = () => { |
| | | systemConfigInfo.value = { ...initState } |
| | | } |
| | | |
| | | return { |
| | | systemConfigInfo, |
| | | setConfigInfo, |
| | | clearConfigInfo, |
| | | reset, |
| | | } |
| | | }, |
| | | { |
| | | persist: true, |
| | | }, |
| | | ) |
| | |
| | | import { defineStore } from 'pinia' |
| | | import { ref } from 'vue' |
| | | import type { UserInfoResp, UserInfo } from '@/service/login.d' |
| | | |
| | | const initState = { nickname: '', avatar: '' } |
| | | const initState = null |
| | | |
| | | export const useUserStore = defineStore( |
| | | 'user', |
| | | 'userInfo', |
| | | () => { |
| | | const userInfo = ref<IUserInfo>({ ...initState }) |
| | | const userInfo = ref<UserInfo>({ ...initState }) |
| | | |
| | | const setUserInfo = (val: IUserInfo) => { |
| | | const setUserInfo = (val: UserInfo) => { |
| | | userInfo.value = val |
| | | } |
| | | |
| | |
| | | const reset = () => { |
| | | userInfo.value = { ...initState } |
| | | } |
| | | const isLogined = computed(() => !!userInfo.value.token) |
| | | |
| | | return { |
| | | userInfo, |
| | | setUserInfo, |
| | | clearUserInfo, |
| | | isLogined, |
| | | reset, |
| | | } |
| | | }, |
| | |
| | | import { CustomRequestOptions } from '@/interceptors/request' |
| | | import { useUserStore, useAccessStore } from '@/store' |
| | | |
| | | export const http = <T>(options: CustomRequestOptions) => { |
| | | // 1. è¿å Promise 对象 |
| | |
| | | } |
| | | } else if (res.statusCode === 401) { |
| | | // 401é误 -> æ¸
çç¨æ·ä¿¡æ¯ï¼è·³è½¬å°ç»å½é¡µ |
| | | // userStore.clearUserInfo() |
| | | useAccessStore().clearAccessInfo() |
| | | useUserStore().clearUserInfo() |
| | | uni.navigateTo({ url: '/pages/login/index' }) |
| | | reject(res) |
| | | } else { |