小程序初始提交
This commit is contained in:
136
cool-unix/cool/store/dict.ts
Normal file
136
cool-unix/cool/store/dict.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { reactive } from "vue";
|
||||
import { request } from "../service";
|
||||
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: string): DictItem[] {
|
||||
return this.find(key)?.list ?? new Array<DictItem>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key和value的字典项
|
||||
* @param key 字典key
|
||||
* @param value 字典项值
|
||||
* @returns 字典项或null
|
||||
*/
|
||||
getItem(key: string, 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: string, 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: string, 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?: string[] | null): Promise<void> {
|
||||
const res = await request({
|
||||
url: "/app/dict/info/data",
|
||||
method: "POST",
|
||||
data: { types }
|
||||
});
|
||||
|
||||
if (res == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历返回的字典数据
|
||||
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();
|
||||
17
cool-unix/cool/store/index.ts
Normal file
17
cool-unix/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";
|
||||
185
cool-unix/cool/store/user.ts
Normal file
185
cool-unix/cool/store/user.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { forInObject, isNull, isObject, parse, storage } from "../utils";
|
||||
import { router } from "../router";
|
||||
import { request } from "../service";
|
||||
import type { UserInfo } from "@/types";
|
||||
|
||||
export type Token = {
|
||||
token: string; // 访问token
|
||||
expire: number; // token过期时间(秒)
|
||||
refreshToken: string; // 刷新token
|
||||
refreshExpire: number; // 刷新token过期时间(秒)
|
||||
};
|
||||
|
||||
export class User {
|
||||
/**
|
||||
* 用户信息,响应式对象
|
||||
*/
|
||||
info = ref<UserInfo | null>(null);
|
||||
|
||||
/**
|
||||
* 当前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;
|
||||
|
||||
// 初始化用户信息
|
||||
if (userInfo != null && isObject(userInfo)) {
|
||||
this.set(userInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息(从服务端拉取最新信息并更新本地)
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async get() {
|
||||
if (this.token != null) {
|
||||
await request({
|
||||
url: "/app/user/info/person"
|
||||
})
|
||||
.then((res) => {
|
||||
if (res != null) {
|
||||
this.set(res);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// this.logout();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户信息并存储到本地
|
||||
* @param data 用户信息对象
|
||||
*/
|
||||
set(data: any) {
|
||||
if (isNull(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置
|
||||
this.info.value = parse<UserInfo>(data)!;
|
||||
|
||||
// 持久化到本地存储
|
||||
storage.set("userInfo", data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息(本地与服务端同步)
|
||||
* @param data 新的用户信息
|
||||
*/
|
||||
async update(data: any) {
|
||||
if (isNull(data) || isNull(this.info.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 本地同步更新
|
||||
forInObject(data, (value, key) => {
|
||||
this.info.value![key] = value;
|
||||
});
|
||||
|
||||
// 同步到服务端
|
||||
await request({
|
||||
url: "/app/user/info/updatePerson",
|
||||
method: "POST",
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除用户信息
|
||||
*/
|
||||
remove() {
|
||||
this.info.value = null;
|
||||
storage.remove("userInfo");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户信息是否为空
|
||||
* @returns boolean
|
||||
*/
|
||||
isNull() {
|
||||
return this.info.value == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除本地所有用户信息和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) => {
|
||||
request({
|
||||
url: "/app/user/login/refreshToken",
|
||||
method: "POST",
|
||||
data: {
|
||||
refreshToken: storage.get("refreshToken")
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
if (res != null) {
|
||||
const token = parse<Token>(res);
|
||||
|
||||
if (token != null) {
|
||||
this.setToken(token);
|
||||
resolve(token.token);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例用户对象,项目全局唯一
|
||||
*/
|
||||
export const user = new User();
|
||||
|
||||
/**
|
||||
* 用户信息,响应式对象
|
||||
*/
|
||||
export const userInfo = computed(() => user.info.value);
|
||||
Reference in New Issue
Block a user