feat: 项目初始化,未病局

This commit is contained in:
fuenmao
2025-09-20 10:36:39 +08:00
commit 39f70340a0
421 changed files with 48180 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
import { PersistedStateOptions } from "pinia-plugin-persistedstate";
/**
* @description pinia 持久化参数配置
* @param {String} key 存储到持久化的 name
* @param {Array} paths 需要持久化的 state name
* @return persist
* */
const piniaPersistConfig = (key: string, paths?: string[]) => {
const persist: PersistedStateOptions = {
key,
storage: localStorage,
// storage: sessionStorage,
paths
};
return persist;
};
export default piniaPersistConfig;
+22
View File
@@ -0,0 +1,22 @@
/**
* @description Pinia store
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
// pinia persist
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
export default pinia;
+59
View File
@@ -0,0 +1,59 @@
/**
* @description 接口
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
export type LayoutType = "vertical" | "classic" | "transverse" | "columns";
export type AssemblySizeType = "large" | "default" | "small";
/* GlobalState */
export interface GlobalState {
layout: LayoutType;
assemblySize: AssemblySizeType;
maximize: boolean;
primary: string;
isDark: boolean;
isGrey: boolean;
isWeak: boolean;
asideInverted: boolean;
headerInverted: boolean;
isCollapse: boolean;
accordion: boolean;
breadcrumb: boolean;
breadcrumbIcon: boolean;
tabs: boolean;
tabsIcon: boolean;
footer: boolean;
drawerForm: boolean;
watermark: boolean;
}
/* tabsMenuProps */
export interface TabsMenuProps {
icon: string;
title: string;
path: string;
name: string;
close: boolean;
isKeepAlive: boolean;
}
/* TabsState */
export interface TabsState {
tabsMenuList: TabsMenuProps[];
}
/* KeepAliveState */
export interface KeepAliveState {
keepAliveName: string[];
}
+42
View File
@@ -0,0 +1,42 @@
/**
* @description mqtt消息接口
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
*/
export type MsgType = "NewMessage" | "LoginOut" | "UpdatePassword";
export enum MsgTypeEnum {
/** 新消息 */
NewMessage = "NewMessage",
/** 退出登录 */
LoginOut = "LoginOut",
/** 修改密码 */
UpdatePassword = "UpdatePassword"
}
/**mqtt消息**/
export interface MqttMessage {
/** 消息类型 */
MsgType: MsgTypeEnum;
/** 消息内容 */
Data: MqttData;
/** 发送时间 */
DetTime: string;
}
/**mqtt消息内容**/
export interface MqttData {
/** 主题 */
Subject: string;
/** 内容 */
Content: string;
}
+200
View File
@@ -0,0 +1,200 @@
/**
* @description 认证模块
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { defineStore } from "pinia";
import { getFlatMenuList, getShowMenuList, getAllBreadcrumbList } from "@/utils";
import { Login, UserCenter } from "@/api/interface";
import { loginApi, userCenterApi } from "@/api";
import { useUserStore } from "./user";
import { useTabsStore } from "./tabs";
import { useMessageStore } from "./message";
import { useKeepAliveStore } from "./keepAlive";
import { useConfigStore } from "./config";
import { initDynamicRouter } from "@/routers/modules/dynamicRouter";
import { ElNotification } from "element-plus";
import { getTimeState } from "@/utils";
import router from "@/routers";
import { TabsMenuProps } from "../interface";
const name = "simple-auth"; // 定义模块名称
/* AuthState */
export interface AuthState {
/** 登录的加载状态 */
loginLoading: boolean;
/** 是否开启选择模块 */
showChooseModule: boolean;
/** 模块列表 */
moduleList: Login.ModuleInfo[];
/** 菜单权限列表 */
authButtonList: string[];
/** 菜单权限列表 */
authMenuList: Menu.MenuOptions[];
}
/** 认证模块 */
export const useAuthStore = defineStore({
id: name,
state: (): AuthState => ({
loginLoading: false,
showChooseModule: false,
moduleList: [],
authButtonList: [],
authMenuList: []
}),
getters: {
// 按钮权限列表
authButtonListGet: state => state.authButtonList,
// 菜单权限列表 ==> 这里的菜单没有经过任何处理
authMenuListGet: state => state.authMenuList,
// 菜单权限列表 ==> 左侧菜单栏渲染,需要剔除 isHide == true
showMenuListGet: state => getShowMenuList(state.authMenuList),
// 菜单权限列表 ==> 扁平化之后的一维数组菜单,主要用来添加动态路由
flatMenuListGet: state => getFlatMenuList(state.authMenuList),
// 递归处理后的所有面包屑导航列表
breadcrumbListGet: state => getAllBreadcrumbList(state.authMenuList)
},
actions: {
/** 设置模块列表 */
SetModuleList(moduleList: Login.ModuleInfo[]) {
this.moduleList = moduleList;
},
/** 选择应用模块 */
async chooseModule(config: UserCenter.ResModuleDefault) {
const userStore = useUserStore();
userStore.setModule(config.id); //存储选择的模块
await userCenterApi.setDefaultModule(config); //设置默认模块
this.showChooseModule = false; //选择模块状态为关闭
},
/** 获取按钮列表 */
async getAuthButtonList() {
const userStore = useUserStore();
const { userInfo } = userStore;
this.authButtonList = userInfo?.buttonCodeList || [];
},
/** 获取菜单列表 */
async getAuthMenuList(moduleId: number | string) {
const { data } = await userCenterApi.getAuthMenuList({ id: moduleId });
this.authMenuList = data;
},
/** 账号密码登录 */
async loginPwd(model: Login.LoginForm) {
this.loginLoading = true;
this.setTenantId(model); // 存储租户id
// 登录接口
await loginApi
.login(model)
.then(res => {
if (res.data) {
this.loginSuccess(res.data); //登录成功
}
})
.catch(err => {
return Promise.reject(err);
})
.finally(() => {
this.loginLoading = false;
});
},
/** 账号密码登录 */
async loginPhone(model: Login.PhoneLoginForm) {
this.loginLoading = true;
this.setTenantId(model); // 存储租户id
// 登录接口
await loginApi
.loginByPhone(model)
.then(res => {
if (res.data) {
this.loginSuccess(res.data); //登录成功
}
})
.catch(err => {
return Promise.reject(err);
})
.finally(() => {
this.loginLoading = false;
});
},
/** 登录成功后的操作 */
async handleActionAfterLogin() {
await initDynamicRouter()
.then(path => {
// 初始化动态路由
const tabsStore = useTabsStore();
const keepAliveStore = useKeepAliveStore();
const messageStore = useMessageStore();
// 3.清空keepAlive 数据
keepAliveStore.setKeepAliveName([]);
messageStore.reSet();
const home = this.authMenuList.filter(item => item.path === path); // 获取首页
if (home.length) {
//定义tab
const tabsParams: TabsMenuProps[] = [
{
icon: home[0].meta.icon as string,
title: home[0].meta.title as string,
path: path,
name: home[0].name as string,
close: !home[0].meta.isAffix,
isKeepAlive: home[0].meta.isKeepAlive as boolean
}
];
tabsStore.setTabs(tabsParams); // 添加首页tab
}
// 4.跳转到首页
router.push(path);
ElNotification({
title: getTimeState(),
message: "欢迎回来 SimpleAdmin",
type: "success",
duration: 3000
});
})
.catch(err => {
console.log("[ err ] >", err);
ElNotification({
title: "系统错误",
message: "系统错误,请联系系统管理员!",
type: "warning",
duration: 3000
});
});
},
/** 存储租户id供下次登录自动选择 */
setTenantId(model: Login.LoginForm | Login.PhoneLoginForm) {
// 如果是租户登录,存储id
if (model.tenantId) {
const configStore = useConfigStore();
configStore.setTenantId(model.tenantId);
}
},
/** 登录请求成功 */
loginSuccess(data: Login.Login) {
const { defaultModule, moduleList } = data;
const userStore = useUserStore();
this.SetModuleList(moduleList); // 设置模块列表
if (moduleList.length === 1) {
// 如果只有一个模块,直接登录
userStore.setModule(moduleList[0].id); //存储选择的模块
this.handleActionAfterLogin(); //登录成功后的操作
return;
} else if (defaultModule && moduleList.find(item => item.id === defaultModule)) {
userStore.setModule(defaultModule); //存储选择的模块为默认模块
this.handleActionAfterLogin(); //登录成功后的操作
} else {
this.showChooseModule = true; //开启选择模块
}
}
}
});
+101
View File
@@ -0,0 +1,101 @@
/**
* @description 系统配置
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
*/
import { defineStore } from "pinia";
import piniaPersistConfig from "@/stores/helper/persist";
import { SysConfig, SysOrg, commonApi } from "@/api";
import { SysBaseEnum, TenantEnum } from "@/enums";
const name = "simple-config"; // 定义模块名称
/** DictState */
export interface SysConfigState {
/** 系统基本信息 */
sysInfo: SysConfig.SysBaseConfig;
/** 租户列表 */
tenantList: SysOrg.SysOrgInfo[];
/** 租户id,用来下次登录自动选择租户 */
tenantId?: number | string;
}
/** 配置模块 */
export const useConfigStore = defineStore({
id: name,
state: (): SysConfigState => ({
sysInfo: {
SYS_NAME: "",
SYS_LOGO: "",
SYS_ICO: "",
SYS_VERSION: "",
SYS_COPYRIGHT: "",
SYS_COPYRIGHT_URL: "",
SYS_FOOTER_LINKS: [],
SYS_TENANT_OPTIONS: TenantEnum.CHOSE
},
tenantList: [],
tenantId: undefined
}),
getters: {
sysBaseInfoGet: state => state.sysInfo,
tenantIdGet: state => state.tenantId,
tenantListGet: state => state.tenantList
},
actions: {
/** 设置系统基本信息 */
async setSysBaseInfo() {
/** 获取系统基本信息 */
const { data } = await commonApi.sysInfo();
if (data) {
//sysConfigProps赋值
data.forEach((item: SysConfig.ConfigInfo) => {
//如果是对象类型的属性就转成对象
if (item.configKey == SysBaseEnum.SYS_DEFAULT_WORKBENCH_DATA) {
const workBenchData: SysConfig.WorkBenchData = JSON.parse(item.configValue);
this.sysInfo.SYS_DEFAULT_WORKBENCH_DATA = workBenchData;
} else if (item.configKey == SysBaseEnum.SYS_FOOTER_LINKS) {
const footerLinks: SysConfig.FooterLinkProps[] = JSON.parse(item.configValue);
this.sysInfo.SYS_FOOTER_LINKS = footerLinks;
} else {
// 其他属性直接赋值
(this.sysInfo[item.configKey as keyof SysConfig.SysBaseConfig] as string) = item.configValue;
}
});
}
return this.sysInfo;
},
/** 获取系统基本信息 */
async getSysBaseInfo() {
if (this.sysInfo.SYS_NAME != "") {
return this.sysInfo;
} else {
return await this.setSysBaseInfo();
}
},
/** 获取租户列表 */
async setTenantList() {
const { data } = await commonApi.tenantList();
this.tenantList = data;
return data;
},
/** 设置租户ID */
setTenantId(tenantId: number | string) {
this.tenantId = tenantId;
},
/** 删除租户ID */
delTenantId() {
this.tenantId = null;
this.tenantList = [];
}
},
persist: piniaPersistConfig(name)
});
+111
View File
@@ -0,0 +1,111 @@
/**
* @description 字典模块
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { defineStore } from "pinia";
import piniaPersistConfig from "@/stores/helper/persist";
import { sysDictApi, SysDict } from "@/api";
import { ElNotification } from "element-plus";
import { SysDictEnum, CommonStatusEnum } from "@/enums";
const name = "simple-dict"; // 定义模块名称
/** 字典值约束 */
type dictValue = string | SysDictEnum;
/** DictState */
export interface DictState {
/** 字典信息 */
dictInfo: SysDict.DictTree[];
}
/** 字典模块 */
export const useDictStore = defineStore({
id: name,
state: (): DictState => ({
dictInfo: []
}),
getters: {
dictInfoGet: state => state.dictInfo
},
actions: {
/** 设置字典信息 */
async setDictTree() {
/** 获取字典信息 */
const { data } = await sysDictApi.tree();
if (data) {
this.dictInfo = data;
} else {
ElNotification({
title: "系统错误",
message: "获取系统字典信息失败,请联系系统管理员!",
type: "warning",
duration: 3000
});
}
},
/** 字典翻译 */
dictTranslation(dictValue: dictValue, value: string) {
const tree = this.dictInfo.find((item: { dictValue: string }) => item.dictValue === dictValue); // 通过字典值找到字典
//如果没有找到字典,返回无此字典
if (!tree) {
return "无此字典";
}
// 通过传的值找到字典的子项
const dict = tree.children.find((item: { dictValue: string }) => item.dictValue === value);
return dict?.dictLabel || "无此字典";
},
/** 获取某个code下字典的列表,多用于字典下拉框 */
getDictList(dictValue: dictValue, isBool?: boolean) {
const tree = this.dictInfo.find((item: { dictValue: string }) => item.dictValue === dictValue);
if (tree) {
//过滤停用的子项
tree.children = tree.children.filter((item: { status: CommonStatusEnum }) => item.status === CommonStatusEnum.ENABLE);
return tree.children.map((item: { [x: string]: any }) => {
//是和否要特殊处理
if (isBool) {
return {
value: item["dictValue"] === "true" ? true : false,
label: item["dictLabel"]
};
} else {
return {
value: item["dictValue"],
label: item["dictLabel"]
};
}
});
}
return [];
},
/** //获取字典有包含dictValue的列表,比如传F_,获取所有F_开头的字典 */
getDictContainsList(dictValue: dictValue): SysDict.DictTree[] {
const tree = this.dictInfo.filter((item: { dictValue: string }) => item.dictValue.includes(dictValue));
if (tree.length > 0) {
return tree;
}
return [];
},
/**获取所有字典 */
getDictAll() {
return this.dictInfo.map(item => {
return {
label: item.dictLabel,
value: item.dictValue
};
});
}
},
persist: piniaPersistConfig(name)
});
+72
View File
@@ -0,0 +1,72 @@
/**
* @description
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { defineStore } from "pinia";
import { GlobalState } from "@/stores/interface";
import { DEFAULT_PRIMARY } from "@/config";
import piniaPersistConfig from "@/stores/helper/persist";
const name = "simple-global"; // 定义模块名称
/** 全局 */
export const useGlobalStore = defineStore({
id: name,
// 修改默认值之后,需清除 localStorage 数据
state: (): GlobalState => ({
// 布局模式 (纵向:vertical | 经典:classic | 横向:transverse | 分栏:columns)
layout: "vertical",
// element 组件大小
assemblySize: "default",
// 当前页面是否全屏
maximize: false,
// 主题颜色
primary: DEFAULT_PRIMARY,
// 深色模式
isDark: false,
// 灰色模式
isGrey: false,
// 色弱模式
isWeak: false,
// 侧边栏反转
asideInverted: false,
// 头部反转
headerInverted: false,
// 折叠菜单
isCollapse: false,
// 菜单手风琴
accordion: true,
// 面包屑导航
breadcrumb: true,
// 面包屑导航图标
breadcrumbIcon: true,
// 标签页
tabs: true,
// 标签页图标
tabsIcon: true,
// 页脚
footer: true,
// 抽屉表单
drawerForm: false,
//页面水印
watermark: false
}),
getters: {},
actions: {
// Set GlobalState
setGlobalState(...args: ObjToKeyValArray<GlobalState>) {
this.$patch({ [args[0]]: args[1] });
}
},
persist: piniaPersistConfig(name)
});
+10
View File
@@ -0,0 +1,10 @@
export * from "./auth";
export * from "./global";
export * from "./keepAlive";
export * from "./tabs";
export * from "./user";
export * from "./dict";
export * from "./config";
export * from "./mqtt";
export * from "./message";
export * from "./userCenter";
+40
View File
@@ -0,0 +1,40 @@
/**
* @description
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { defineStore } from "pinia";
import { KeepAliveState } from "@/stores/interface";
const name = "simple-keepAlive"; // 定义模块名称
/** KeepAlive模块 */
export const useKeepAliveStore = defineStore({
id: name,
state: (): KeepAliveState => ({
keepAliveName: []
}),
actions: {
// Add KeepAliveName
async addKeepAliveName(name: string) {
!this.keepAliveName.includes(name) && this.keepAliveName.push(name);
},
// Remove KeepAliveName
async removeKeepAliveName(name: string) {
this.keepAliveName = this.keepAliveName.filter((item: string) => item !== name);
},
// Set KeepAliveName
async setKeepAliveName(keepAliveName: string[] = []) {
this.keepAliveName = keepAliveName;
}
}
});
+122
View File
@@ -0,0 +1,122 @@
/**
* @description 系统消息
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
*/
import { defineStore } from "pinia";
import { userCenterApi, UserCenter, SysMessage } from "@/api";
import { ElNotification } from "element-plus";
import { Message } from "@element-plus/icons-vue";
const name = "simple-message"; // 定义模块名称
/* MqttState */
export interface MessageState {
/** 未读消息信息 */
unReadInfo: any;
/** 未读消息数 */
unReadCount: number;
/** 新未读消息 */
newUnRead: SysMessage.SysMessageInfo[];
}
/** Mqtt模块 */
export const useMessageStore = defineStore({
id: name,
state: (): MessageState => ({
unReadInfo: {},
unReadCount: 0,
newUnRead: []
}),
getters: {
unReadCountGet: state => state.unReadCount,
unReadInfoGet: state => state.unReadInfo
},
actions: {
/** 显示更多 */
setShowMore(state: boolean) {
this.showMore = state;
},
/** 增加未读消息数 */
unReadCountAdd(value: number) {
this.unReadCount += value;
},
/** 减少未读消息数 */
unReadCountSubtract(value: number) {
this.unReadCount -= value;
},
/** 设置未读消息数 */
unReadCountSet(value: number) {
this.unReadCount = value;
},
/** 获取未读消息数 */
async getUnReadInfo(notice: boolean = false) {
await userCenterApi.unReadCount().then(res => {
if (res.data.length > 0) {
//未读消息信息数量转换
this.unReadInfo = res.data.reduce((acc, item) => {
acc[item.category] = item.unReadCount;
return acc;
}, {});
//遍历未读消息信息,获取未读消息总数
let count = 0;
res.data.map((item: UserCenter.ResUnReadCount) => {
count += item.unReadCount;
});
//如果未读消息总数大于当前未读消息总数,则获取最新未读消息
if (count > this.unReadCount) {
this.getNewMessage(notice);
}
this.unReadCountSet(count);
} else {
this.unReadCountSet(0);
}
});
},
/** 获取最新未读消息 */
async getNewUnRead() {
await userCenterApi.newUnRead().then(res => {
if (res.data.length > 0) {
this.newUnRead = res.data;
}
});
},
/** 获取未读消息数 */
getUnReadCount(category: string) {
return this.unReadInfo[category] || 0;
},
/**提示有新消息 */
getNewMessage(notice: boolean = false, message: string = "您有一条新消息,请注意查收!") {
this.getNewUnRead();
if (notice) {
ElNotification({
title: "收到一条新消息",
message: message,
icon: Message,
offset: 40
});
}
},
/**定时刷新最新消息*/
async getNewMessageInterval() {
setInterval(() => {
// this.getUnReadInfo(true);
}, 10000);
},
/* 重置未读消息数 */
reSet() {
this.unReadCount = 0;
this.unReadInfo = {};
this.newUnRead = [];
}
}
});
+178
View File
@@ -0,0 +1,178 @@
/**
* @description mqtt 消息订阅
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
*/
import mqtt from "mqtt";
import { defineStore } from "pinia";
import { mqttApi } from "@/api";
import { useMessageStore } from "@/stores/modules";
import { MqttMessage, MsgTypeEnum } from "../interface/mqtt";
const name = "simple-mqtt"; // 定义模块名称
/* MqttState */
export interface MqttState {
/** 服务端地址 */
url: string | undefined;
/** 是否清除 */
clean: boolean;
/** 客户端 */
client: any;
/** 客户端id */
clientId: string;
/** 订阅主题列表 */
topics: string[];
/** 订阅主题的集合,key为topic, value为接收到该topic时需要执行的回调 */
subscribeMembers: [{ string: any }] | undefined;
}
/** 订阅参数 */
export interface subscribeParams {
/** 订阅主题 */
topic: string;
/** 订阅回调 */
callback: number;
/** 订阅选项 */
subscribeOption: any;
}
/** Mqtt模块 */
export const useMqttStore = defineStore({
id: name,
state: (): MqttState => ({
url: undefined,
client: undefined,
clientId: "",
clean: true,
topics: [],
subscribeMembers: undefined
}),
getters: {},
actions: {
/** 获取mqtt参数 */
async getMqttParameter() {
return await mqttApi.getMqttParameter().then(res => {
console.log("[ res ] >", res);
this.clientId = res.data.clientId;
this.url = res.data.url;
this.topics = res.data.topics;
return res.data;
});
},
/** 初始化mqtt客户端 */
async initMqttClient() {
console.log("[ mqtt初始化 ] >");
if (this.client) {
this.disconnect();
}
await this.getMqttParameter().then(res => {
const url = this.url;
const options = {
username: res.userName,
password: res.password,
clientId: this.clientId,
clean: true, // true: 清除会话, false: 保留会话
connectTimeout: 4000, // 超时时间
keepAlive: 60 // 心跳时间
};
console.log("[ options ] >", options);
// return;
if (url) {
this.client = mqtt.connect(url, options);
this.client.on("connect", e => {
this.onConnect(e);
});
this.client.on("reconnect", err => {
this.onReconnect(err);
});
this.client.on("error", err => {
this.onError(err);
});
this.client.on("message", (topic, message) => {
this.onMessage(topic, message);
});
}
});
},
/** 断开连接 */
disconnect() {
this.client.end();
this.client = undefined;
this.subscribeMembers = {};
},
/** 订阅 */
subscribe(topics: string[]) {
topics.forEach((item: string) => {
this.client.subscribe(item, {}, (err, res) => {
if (err) {
console.log(`客户端: ${this.clientId}, 订阅主题: ${item}失败: `, err);
} else {
console.log(`客户端: ${this.clientId}, 订阅主题: ${item}成功,${JSON.stringify(res)}`);
}
});
});
},
/** 订阅带回调函数 */
subscribeCallback(params: subscribeParams) {
const { topic, callback, subscribeOption } = params;
this.client.subscribe(topic, subscribeOption, (err, res) => {
if (err) {
console.log(`客户端: ${this.clientId}, 订阅主题: ${topic}失败: `, err);
} else {
console.log(`客户端: ${this.clientId}, 订阅主题: ${topic}成功,${res}`);
}
});
this.subscribeMembers.push({ topic, callback });
},
/** 取消订阅 */
unsubscribe(topic: string) {
if (!this.client) return;
this.client.unsubscribe(topic, {}, (err, res) => {
if (err) {
console.log(`客户端: ${this.clientId}, 取消订阅主题: ${topic}失败: `, err);
} else {
console.log(`客户端: ${this.clientId}, 取消订阅主题: ${topic}成功,${res}`);
}
});
this.subscribeMembers = this.subscribeMembers.filter((item: any) => item.topic !== topic);
},
/** 连接事件 */
onConnect(e: any) {
console.log(`客户端: ${this.clientId}, 连接mqtt服务器成功:`, e);
this.subscribe(this.topics);
},
/** 重连事件 */
onReconnect(err: any) {
console.log(`客户端: ${this.clientId}, 正在重连mqtt服务器...`, err);
},
/** 错误事件 */
onError(err: any) {
console.log(`客户端: ${this.clientId}, 连接mqtt服务器失败:`, err);
},
/** 消息事件 */
onMessage(topic: string, message: any) {
console.log(message.toString());
const messageStore = useMessageStore();
const msg = JSON.parse(message.toString()) as MqttMessage;
console.log(`客户端: ${this.clientId}, 接收到消息:`, topic, msg);
switch (msg.MsgType) {
case MsgTypeEnum.NewMessage:
messageStore.getNewMessage(true, msg.Data.Subject);
break;
case MsgTypeEnum.LoginOut:
break;
case MsgTypeEnum.UpdatePassword:
break;
}
}
}
});
+98
View File
@@ -0,0 +1,98 @@
/**
* @description
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import router from "@/routers";
import { defineStore } from "pinia";
import { getUrlWithParams } from "@/utils";
import { useKeepAliveStore } from "./keepAlive";
import { TabsState, TabsMenuProps } from "@/stores/interface";
import piniaPersistConfig from "@/stores/helper/persist";
const name = "simple-tabs"; // 定义模块名称
/** 标签页 */
export const useTabsStore = defineStore({
id: name,
state: (): TabsState => ({
tabsMenuList: []
}),
actions: {
// Add Tabs
async addTabs(tabItem: TabsMenuProps) {
const keepAliveStore = useKeepAliveStore();
if (this.tabsMenuList.every((item: { path: string }) => item.path !== tabItem.path)) {
// 如果tabItem的路径不等于当前tabsMenuList的路径,则添加tabItem
this.tabsMenuList.push(tabItem);
}
// 如果tabItem的name不包含在keepAliveStore的keepAliveName中,并且tabItem的isKeepAlive为true,则添加keepAliveStore的keepAliveName
if (!keepAliveStore.keepAliveName.includes(tabItem.name) && tabItem.isKeepAlive) {
keepAliveStore.addKeepAliveName(tabItem.path);
}
},
// Remove Tabs
async removeTabs(tabPath: string, isCurrent: boolean = true) {
const keepAliveStore = useKeepAliveStore();
if (isCurrent) {
this.tabsMenuList.forEach((item: { path: string }, index: number) => {
if (item.path !== tabPath) return;
const nextTab = this.tabsMenuList[index + 1] || this.tabsMenuList[index - 1];
if (!nextTab) return;
router.push(nextTab.path);
});
}
this.tabsMenuList = this.tabsMenuList.filter((item: { path: string }) => item.path !== tabPath);
// remove keepalive
const tabItem = this.tabsMenuList.find((item: { path: string }) => item.path === tabPath);
tabItem?.isKeepAlive && keepAliveStore.removeKeepAliveName(tabItem.path);
// set tabs
this.tabsMenuList = this.tabsMenuList.filter((item: { path: string }) => item.path !== tabPath);
},
// Close Tabs On Side
async closeTabsOnSide(path: string, type: "left" | "right") {
const keepAliveStore = useKeepAliveStore();
const currentIndex = this.tabsMenuList.findIndex((item: { path: string }) => item.path === path);
if (currentIndex !== -1) {
const range = type === "left" ? [0, currentIndex] : [currentIndex + 1, this.tabsMenuList.length];
this.tabsMenuList = this.tabsMenuList.filter((item: { close: any }, index: number) => {
return index < range[0] || index >= range[1] || !item.close;
});
}
// set keepalive
const KeepAliveList = this.tabsMenuList.filter((item: { isKeepAlive: any }) => item.isKeepAlive);
keepAliveStore.setKeepAliveName(KeepAliveList.map((item: { path: any }) => item.path));
},
// Close MultipleTab
async closeMultipleTab(tabsMenuValue?: string) {
const keepAliveStore = useKeepAliveStore();
this.tabsMenuList = this.tabsMenuList.filter((item: { path: string | undefined; close: any }) => {
return item.path === tabsMenuValue || !item.close;
});
// set keepalive
const KeepAliveList = this.tabsMenuList.filter((item: { isKeepAlive: any }) => item.isKeepAlive);
keepAliveStore.setKeepAliveName(KeepAliveList.map((item: { path: any }) => item.path));
},
// Set Tabs
async setTabs(tabsMenuList: TabsMenuProps[]) {
this.tabsMenuList = tabsMenuList;
},
// Set Tabs Title
async setTabsTitle(title: string) {
this.tabsMenuList.forEach((item: { path: string; title: string }) => {
if (item.path == getUrlWithParams()) item.title = title;
});
}
},
persist: piniaPersistConfig(name)
});
+108
View File
@@ -0,0 +1,108 @@
/**
* @description 用户模块
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { defineStore } from "pinia";
import { Login } from "@/api/interface";
import piniaPersistConfig from "@/stores/helper/persist";
import { loginApi } from "@/api";
import { ElNotification } from "element-plus";
const name = "simple-user"; // 定义模块名称
/* UserState */
export interface UserState {
/** token */
accessToken: string;
/** 刷新token */
refreshToken: string;
/** 用户信息 */
userInfo: Login.LoginUserInfo | null;
/** 默认模块 */
defaultModule: number | string | null;
/** 选择模块 */
chooseModule: number | string | null;
/** 模块列表 */
moduleList: Login.ModuleInfo[];
}
/** 用户模块 */
export const useUserStore = defineStore({
id: name,
state: (): UserState => ({
accessToken: "",
refreshToken: "",
userInfo: null,
defaultModule: null,
chooseModule: null,
moduleList: []
}),
getters: {
userInfoGet: state => state.userInfo,
chooseModuleGet: state => state.chooseModule,
moduleListGet: state => state.moduleList
},
actions: {
// Set Token
setToken(token: string, refreshToken: string) {
this.accessToken = token;
this.refreshToken = refreshToken;
},
async getUserInfo() {
/** 获取用户信息 */
const { data } = await loginApi.getLoginUser();
if (data) {
this.setUserInfo(data);
} else {
ElNotification({
title: "系统错误",
message: "获取个人信息失败,请联系系统管理员!",
type: "warning",
duration: 3000
});
}
return this.userInfo;
},
/** 设置用户信息 */
setUserInfo(userInfo: Login.LoginUserInfo) {
this.userInfo = userInfo;
this.defaultModule = userInfo.defaultModule;
this.moduleList = userInfo.moduleList;
},
/** 设置用户签名 */
setSignature(signature: string) {
this.userInfo.signature = signature;
},
/** 设置用户单个属性 */
setUserInfoItem(key: string, value: any) {
this.userInfo[key] = value;
},
/** 清除token */
clearToken() {
this.accessToken = "";
this.refreshToken = "";
},
/** 清理用户信息 */
clearUserStore() {
this.clearToken();
this.userInfo = null;
this.defaultModule = null;
this.moduleList = [];
},
/** 选择模块 */
setModule(moduleId: number | string | null) {
this.chooseModule = moduleId;
}
},
persist: piniaPersistConfig(name)
});
+61
View File
@@ -0,0 +1,61 @@
/**
* @description 用户中心
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
*/
import { defineStore } from "pinia";
const name = "simple-userCenter"; // 定义模块名称
const accountBasic = "accountBasic";
const file = "file";
const message = "message";
const short = "short";
/* MqttState */
export interface UserCenterState {
/** 当前标签页 */
tab: string;
accountBasic: string;
file: string;
message: string;
short: string;
}
/** Mqtt模块 */
export const useCenterStore = defineStore({
id: name,
state: (): UserCenterState => ({
tab: accountBasic,
accountBasic: accountBasic,
file: file,
message: message,
short: short
}),
getters: {
getTab: state => state.tab,
getAccountBasic: state => state.accountBasic,
getFile: state => state.file,
getMessage: state => state.message,
getShort: state => state.short
},
actions: {
setTab(tab: string) {
this.tab = tab;
},
resetTab() {
this.tab = accountBasic;
},
setMessage() {
this.tab = "message";
}
}
});