版本发布
This commit is contained in:
137
cool/store/dict.ts
Normal file
137
cool/store/dict.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { reactive } from "vue";
|
||||
import { service } from "../service";
|
||||
import type { DictKey } from "../types";
|
||||
import { forInObject, isNull, parse } from "../utils";
|
||||
|
||||
// 字典项类型定义
|
||||
export type DictItem = {
|
||||
id: number; // 字典项ID
|
||||
typeId: number; // 字典类型ID
|
||||
label: string; // 显示标签
|
||||
name: string; // 可选名称
|
||||
value: any; // 字典项值
|
||||
orderNum: number; // 排序号
|
||||
parentId?: number | null; // 父级ID,可选
|
||||
};
|
||||
|
||||
// 字典数据类型定义
|
||||
export type DictData = {
|
||||
key: string; // 字典key
|
||||
list: DictItem[]; // 字典项列表
|
||||
};
|
||||
|
||||
// 字典管理类
|
||||
export class Dict {
|
||||
private data: DictData[] = reactive([]); // 存储所有字典数据
|
||||
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* 获取指定key的字典数据
|
||||
* @param key 字典key
|
||||
* @returns 字典数据
|
||||
*/
|
||||
find(key: string) {
|
||||
return this.data.find((e) => e.key == key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key的字典项列表
|
||||
* @param key 字典key
|
||||
* @returns 字典项数组
|
||||
*/
|
||||
get(key: DictKey): DictItem[] {
|
||||
return this.find(key)?.list ?? new Array<DictItem>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key和value的字典项
|
||||
* @param key 字典key
|
||||
* @param value 字典项值
|
||||
* @returns 字典项或null
|
||||
*/
|
||||
getItem(key: DictKey, value: any): DictItem | null {
|
||||
const item = this.get(key).find((e) => e.value == value);
|
||||
|
||||
if (isNull(item)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return item!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key和多个value的字典项数组
|
||||
* @param key 字典key
|
||||
* @param values 字典项值数组
|
||||
* @returns 字典项数组
|
||||
*/
|
||||
getItems(key: DictKey, values: any[]): DictItem[] {
|
||||
return values.map((e) => this.getItem(key, e)).filter((e) => !isNull(e)) as DictItem[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key和value的字典项的label
|
||||
* @param key 字典key
|
||||
* @param value 字典项值
|
||||
* @returns 字典项label字符串
|
||||
*/
|
||||
getItemLabel(key: DictKey, value: any): string {
|
||||
const item = this.getItem(key, value);
|
||||
|
||||
if (isNull(item) || isNull(item?.label)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return item!.label;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新字典数据
|
||||
* @param types 可选,指定需要刷新的字典key数组
|
||||
*/
|
||||
async refresh(types?: DictKey[] | null): Promise<void> {
|
||||
const res = await service.dict.info.data({ types });
|
||||
|
||||
// 遍历返回的字典数据
|
||||
forInObject(res, (arr, key) => {
|
||||
let list: DictItem[] = [];
|
||||
|
||||
(arr as UTSJSONObject[]).forEach((e) => {
|
||||
e["label"] = e["name"];
|
||||
const d = parse<DictItem>(e);
|
||||
|
||||
if (d != null) {
|
||||
list.push(d);
|
||||
}
|
||||
});
|
||||
|
||||
const item = this.find(key);
|
||||
|
||||
// 如果不存在则新增,否则更新
|
||||
if (isNull(item)) {
|
||||
this.data.push({
|
||||
key,
|
||||
list
|
||||
});
|
||||
} else {
|
||||
item!.list = list;
|
||||
}
|
||||
});
|
||||
|
||||
// #ifdef H5
|
||||
console.log("[DICT]", this.data);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
|
||||
// 单例字典对象
|
||||
export const dict = new Dict();
|
||||
|
||||
/**
|
||||
* 获取字典实例
|
||||
* @returns Dict实例
|
||||
*/
|
||||
export function useDict() {
|
||||
return dict;
|
||||
}
|
||||
17
cool/store/index.ts
Normal file
17
cool/store/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Dict, dict } from "./dict";
|
||||
import { User, user } from "./user";
|
||||
|
||||
type Store = {
|
||||
user: User;
|
||||
dict: Dict;
|
||||
};
|
||||
|
||||
export function useStore(): Store {
|
||||
return {
|
||||
user,
|
||||
dict
|
||||
};
|
||||
}
|
||||
|
||||
export * from "./dict";
|
||||
export * from "./user";
|
||||
197
cool/store/user.ts
Normal file
197
cool/store/user.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
import { reactive } from "vue";
|
||||
import type { UserInfoEntity } from "../types";
|
||||
import { forInObject, isNull, parse, storage } from "../utils";
|
||||
import { service } from "../service";
|
||||
import { router } from "../router";
|
||||
|
||||
/**
|
||||
* Token类型定义
|
||||
* @property token 访问token
|
||||
* @property expire token过期时间(秒)
|
||||
* @property refreshToken 刷新token
|
||||
* @property refreshExpire 刷新token过期时间(秒)
|
||||
*/
|
||||
export type Token = {
|
||||
token: string;
|
||||
expire: number;
|
||||
refreshToken: string;
|
||||
refreshExpire: number;
|
||||
};
|
||||
|
||||
export class User {
|
||||
/**
|
||||
* 用户信息,响应式对象,属性结构见UserInfoEntity
|
||||
*/
|
||||
info = reactive<UserInfoEntity>({});
|
||||
|
||||
/**
|
||||
* 当前token,字符串或null
|
||||
*/
|
||||
token: string | null = null;
|
||||
|
||||
constructor() {
|
||||
// 获取本地用户信息
|
||||
const userInfo = storage.get("userInfo");
|
||||
|
||||
// 获取本地token
|
||||
const token = storage.get("token") as string | null;
|
||||
|
||||
// 如果token为空字符串则置为null
|
||||
this.token = token == "" ? null : token;
|
||||
|
||||
// 初始化用户信息
|
||||
this.set(userInfo!);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息(从服务端拉取最新信息并更新本地)
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async get() {
|
||||
if (this.token != null) {
|
||||
await service.user.info
|
||||
.person({})
|
||||
.then((res) => {
|
||||
if (!isNull(res)) {
|
||||
this.set(res);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.logout();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户信息并存储到本地
|
||||
* @param data 用户信息对象
|
||||
*/
|
||||
set(data: any) {
|
||||
if (isNull(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 先清空原有信息
|
||||
this.remove();
|
||||
|
||||
// 逐项赋值到响应式info对象
|
||||
forInObject(data, (value, key) => {
|
||||
this.info[key] = value;
|
||||
});
|
||||
|
||||
// 持久化到本地存储
|
||||
storage.set("userInfo", data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息(本地与服务端同步)
|
||||
* @param data 新的用户信息
|
||||
*/
|
||||
async update(data: UserInfoEntity) {
|
||||
if (isNull(data) || this.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = { ...data };
|
||||
|
||||
// 本地同步更新
|
||||
forInObject(params as any, (value, key) => {
|
||||
this.info[key] = value;
|
||||
});
|
||||
|
||||
// 同步到服务端
|
||||
await service.user.info.updatePerson(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除用户信息(仅清空本地响应式对象,不清除本地存储)
|
||||
*/
|
||||
remove() {
|
||||
forInObject({ ...this.info } as any, (_, key) => {
|
||||
// #ifdef APP
|
||||
this.info[key] = null;
|
||||
// #endif
|
||||
|
||||
// #ifndef APP
|
||||
delete this.info[key];
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户信息是否为空(以id字段为准)
|
||||
* @returns boolean
|
||||
*/
|
||||
isNull() {
|
||||
return isNull(this.info["id"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除本地所有用户信息和token
|
||||
*/
|
||||
clear() {
|
||||
storage.remove("userInfo");
|
||||
storage.remove("token");
|
||||
storage.remove("refreshToken");
|
||||
this.token = null;
|
||||
this.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录,清除所有信息并跳转到登录页
|
||||
*/
|
||||
logout() {
|
||||
this.clear();
|
||||
router.login();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置token并存储到本地
|
||||
* @param data Token对象
|
||||
*/
|
||||
setToken(data: Token) {
|
||||
this.token = data.token;
|
||||
|
||||
// 访问token,提前5秒过期,防止边界问题
|
||||
storage.set("token", data.token, data.expire - 5);
|
||||
// 刷新token,提前5秒过期
|
||||
storage.set("refreshToken", data.refreshToken, data.refreshExpire - 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token(调用服务端接口,自动更新本地token)
|
||||
* @returns Promise<string> 新的token
|
||||
*/
|
||||
refreshToken(): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
service.user.login
|
||||
.refreshToken({
|
||||
refreshToken: storage.get("refreshToken")
|
||||
})
|
||||
.then((res) => {
|
||||
const token = parse<Token>(res);
|
||||
|
||||
if (token != null) {
|
||||
this.setToken(token);
|
||||
resolve(token.token);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例用户对象,项目全局唯一
|
||||
*/
|
||||
export const user = new User();
|
||||
|
||||
/**
|
||||
* 获取用户单例实例(组合式API用法)
|
||||
* @returns User
|
||||
*/
|
||||
export function useUser() {
|
||||
return user;
|
||||
}
|
||||
Reference in New Issue
Block a user