refactor: ♻️ 代码规范优化
This commit is contained in:
32
CHANGELOG.md
32
CHANGELOG.md
@@ -3,7 +3,7 @@
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持后端文件导入([#142](https://github.com/youlaitech/vue3-element-admin/pull/142)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持后端文件导入([#142](https://github.com/youlaitech/vue3-element-admin/pull/142)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
|
||||
## 🐛 fix
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 操作栏增加render配置参数([#138](https://github.com/youlaitech/vue3-element-admin/pull/140)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 操作栏增加render配置参数([#138](https://github.com/youlaitech/vue3-element-admin/pull/140)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 左侧工具栏增加type配置参数([#141](https://github.com/youlaitech/vue3-element-admin/pull/141)) [@diamont1001](https://github.com/diamont1001)
|
||||
|
||||
## ♻️ refactor
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持默认工具栏的导入([#138](https://github.com/youlaitech/vue3-element-admin/pull/138)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持默认工具栏的导入([#138](https://github.com/youlaitech/vue3-element-admin/pull/138)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 添加CURD导入示例([19e7bb](https://github.com/youlaitech/vue3-element-admin/commit/eab91effd6a01d5a3d9257249c8d06aa252b3bf8)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## ♻️ refactor
|
||||
@@ -40,13 +40,13 @@
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持表格远程筛选([#131](https://github.com/youlaitech/vue3-element-admin/pull/131)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持表格远程筛选([#131](https://github.com/youlaitech/vue3-element-admin/pull/131)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持标签输入框([#132](https://github.com/youlaitech/vue3-element-admin/pull/132)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 表单项支持tips配置([#133](https://github.com/youlaitech/vue3-element-admin/pull/133)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 前端导出支持全量数据([#134](https://github.com/youlaitech/vue3-element-admin/pull/134)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持选中数据导出([#135](https://github.com/youlaitech/vue3-element-admin/pull/135)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 表格默认工具栏的导出、搜索按钮增加权限点控制([883128](https://github.com/youlaitech/vue3-element-admin/commit/8831289b655f2cc086ecdababaa89f8d8a087c42)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 页签title支持动态设置([23876a](https://github.com/youlaitech/vue3-element-admin/commit/23876aa396143bf77cb5c86af8d6023d9ff6555a)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
- 表单项支持tips配置([#133](https://github.com/youlaitech/vue3-element-admin/pull/133)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 前端导出支持全量数据([#134](https://github.com/youlaitech/vue3-element-admin/pull/134)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持选中数据导出([#135](https://github.com/youlaitech/vue3-element-admin/pull/135)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 表格默认工具栏的导出、搜索按钮增加权限点控制([883128](https://github.com/youlaitech/vue3-element-admin/commit/8831289b655f2cc086ecdababaa89f8d8a087c42)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 页签title支持动态设置([23876a](https://github.com/youlaitech/vue3-element-admin/commit/23876aa396143bf77cb5c86af8d6023d9ff6555a)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
## ♻️ refactor
|
||||
- 默认工具栏支持自定义([#136](https://github.com/youlaitech/vue3-element-admin/pull/136)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
@@ -59,9 +59,9 @@
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 增加pagination、request、parseData配置参数([#119](https://github.com/youlaitech/vue3-element-admin/pull/119)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 增加pagination、request、parseData配置参数([#119](https://github.com/youlaitech/vue3-element-admin/pull/119)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 增加返回顶部功能([#120](https://github.com/youlaitech/vue3-element-admin/pull/120)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持前端导出([#126](https://github.com/youlaitech/vue3-element-admin/pull/126)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持前端导出([#126](https://github.com/youlaitech/vue3-element-admin/pull/126)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## ♻️ refactor
|
||||
- 重构布局样式(解决页面抖动问题)([#116](https://github.com/youlaitech/vue3-element-admin/pull/116)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
@@ -174,7 +174,7 @@
|
||||
- 本地缓存的 token 变量重命名(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 完善 Vite 环境变量类型声明(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## 🐛 fix
|
||||
## 🐛 fix
|
||||
- 修复构建时提示iconComponent.name可能为undefined的报错 (author by [wangji1042](https://github.com/wangji1042))
|
||||
- 修复浏览器密码自动填充时可能存在的报错 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修复eslint报错(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
@@ -211,7 +211,7 @@
|
||||
## ♻️ refactor
|
||||
- 项目配置按钮移入navbar(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 优化user数据定义(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 统一设置栏的 SVG 图标风格
|
||||
- 统一设置栏的 SVG 图标风格
|
||||
|
||||
## 🐛 fix
|
||||
- 规整一些开发依赖(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
@@ -241,7 +241,7 @@
|
||||
# 2.8.1 (2024/01/10)
|
||||
|
||||
## ✨ feat
|
||||
- 替换 Mock 解决方案 vite-plugin-mock 为 vite-plugin-mock-dev-server 适配 Vite5
|
||||
- 替换 Mock 解决方案 vite-plugin-mock 为 vite-plugin-mock-dev-server 适配 Vite5
|
||||
|
||||
# 2.8.0 (2023/12/27)
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
## ✨ feat
|
||||
- 菜单管理新增目录只有一级子路由是否始终显示(alwaysShow)和路由页面是否缓存(keepAlive)的配置
|
||||
- 接口文档新增 swagger、knife4j
|
||||
- 引入和支持 tsx
|
||||
- 引入和支持 tsx
|
||||
|
||||
## ♻️ refactor
|
||||
- 代码瘦身,整理并删除未使用的 svg
|
||||
@@ -329,7 +329,7 @@
|
||||
- 字典组件封装(author by [haoxr](https://juejin.cn/user/4187394044331261/posts))
|
||||
|
||||
## 🐛 fix
|
||||
- 分页组件hidden无效
|
||||
- 分页组件hidden无效
|
||||
- 签名无法保存至后端
|
||||
- Git 提交 stylelint 校验部分机器报错
|
||||
|
||||
|
||||
@@ -74,9 +74,7 @@ module.exports = {
|
||||
breaklineNumber: 100,
|
||||
breaklineChar: "|",
|
||||
skipQuestions: [],
|
||||
issuePrefixes: [
|
||||
{ value: "closed", name: "closed: ISSUES has been processed" },
|
||||
],
|
||||
issuePrefixes: [{ value: "closed", name: "closed: ISSUES has been processed" }],
|
||||
customIssuePrefixAlign: "top",
|
||||
emptyIssuePrefixAlias: "skip",
|
||||
customIssuePrefixAlias: "custom",
|
||||
|
||||
@@ -586,6 +586,7 @@ cols.value.forEach((item) => {
|
||||
fields.push(item.prop);
|
||||
}
|
||||
});
|
||||
|
||||
const enum ExportsOriginEnum {
|
||||
CURRENT = "current",
|
||||
SELECTED = "selected",
|
||||
@@ -950,7 +951,7 @@ function exportPageData(formData: IObject = {}) {
|
||||
}
|
||||
|
||||
// 浏览器保存文件
|
||||
function saveXlsx(fileData: BlobPart, fileName: string) {
|
||||
function saveXlsx(fileData: any, fileName: string) {
|
||||
const fileType =
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<slot
|
||||
:name="item.slotName ?? item.prop"
|
||||
:prop="item.prop"
|
||||
:formData="formData"
|
||||
:form-data="formData"
|
||||
:attrs="item.attrs"
|
||||
/>
|
||||
</template>
|
||||
@@ -137,11 +137,11 @@ function getFormData(key?: string) {
|
||||
// 设置表单值
|
||||
function setFormData(data: IObject) {
|
||||
for (const key in formData) {
|
||||
if (formData.hasOwnProperty(key) && key in data) {
|
||||
if (Object.prototype.hasOwnProperty.call(formData, key) && key in data) {
|
||||
formData[key] = data[key];
|
||||
}
|
||||
}
|
||||
if (data?.hasOwnProperty(props.pk)) {
|
||||
if (Object.prototype.hasOwnProperty.call(data, props.pk)) {
|
||||
formData[props.pk] = data[props.pk];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<slot
|
||||
:name="item.slotName ?? item.prop"
|
||||
:prop="item.prop"
|
||||
:formData="formData"
|
||||
:form-data="formData"
|
||||
:attrs="item.attrs"
|
||||
/>
|
||||
</template>
|
||||
@@ -208,7 +208,7 @@
|
||||
<slot
|
||||
:name="item.slotName ?? item.prop"
|
||||
:prop="item.prop"
|
||||
:formData="formData"
|
||||
:form-data="formData"
|
||||
:attrs="item.attrs"
|
||||
/>
|
||||
</template>
|
||||
@@ -294,11 +294,11 @@ function getFormData(key?: string) {
|
||||
// 设置表单值
|
||||
function setFormData(data: IObject) {
|
||||
for (const key in formData) {
|
||||
if (formData.hasOwnProperty(key) && key in data) {
|
||||
if (Object.prototype.hasOwnProperty.call(formData, key) && key in data) {
|
||||
formData[key] = data[key];
|
||||
}
|
||||
}
|
||||
if (data?.hasOwnProperty(pk)) {
|
||||
if (Object.prototype.hasOwnProperty.call(data, pk)) {
|
||||
formData[pk] = data[pk];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from "vue";
|
||||
import { onClickOutside, useResizeObserver } from "@vueuse/core";
|
||||
import { useResizeObserver } from "@vueuse/core";
|
||||
import type { FormInstance, PopoverProps, TableInstance } from "element-plus";
|
||||
|
||||
// 对象类型
|
||||
@@ -157,7 +157,7 @@ export interface ISelectConfig<T = any> {
|
||||
// popover组件属性
|
||||
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
|
||||
// 列表的网络请求函数(需返回promise)
|
||||
indexAction: (queryParams: T) => Promise<any>;
|
||||
indexAction: (_queryParams: T) => Promise<any>;
|
||||
// 主键名(跨页选择必填,默认为id)
|
||||
pk?: string;
|
||||
// 多选
|
||||
@@ -284,7 +284,7 @@ const selectedItems = ref<IObject[]>([]);
|
||||
const confirmText = computed(() => {
|
||||
return selectedItems.value.length > 0 ? `已选(${selectedItems.value.length})` : "确 定";
|
||||
});
|
||||
function handleSelect(selection: any[], row: any) {
|
||||
function handleSelect(selection: any[], _row: any) {
|
||||
if (isMultiple || selection.length === 0) {
|
||||
// 多选
|
||||
selectedItems.value = selection;
|
||||
|
||||
@@ -192,7 +192,11 @@ const handleSuccess = (fileInfo: FileInfo) => {
|
||||
modelValue.value = [...modelValue.value, fileInfo.url];
|
||||
};
|
||||
|
||||
const handleError = (error: any) => {
|
||||
/**
|
||||
* 上传失败
|
||||
*/
|
||||
const handleError = (_error: any) => {
|
||||
console.error(_error);
|
||||
ElMessage.error("上传失败");
|
||||
};
|
||||
|
||||
@@ -223,8 +227,8 @@ function handleDownload(file: UploadUserFile) {
|
||||
color: var(--el-text-color-regular);
|
||||
cursor: pointer;
|
||||
opacity: 0.75;
|
||||
transition: opacity var(--el-transition-duration);
|
||||
transform: translateY(-50%);
|
||||
transition: opacity var(--el-transition-duration);
|
||||
}
|
||||
|
||||
:deep(.el-upload-list) {
|
||||
|
||||
@@ -169,7 +169,7 @@ function handleUpload(options: UploadRequestOptions) {
|
||||
/**
|
||||
* 上传文件超出限制
|
||||
*/
|
||||
function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
|
||||
function handleExceed() {
|
||||
ElMessage.warning("最多只能上传" + props.limit + "张图片");
|
||||
}
|
||||
|
||||
|
||||
@@ -67,12 +67,12 @@ const isMobile = computed(() => appStore.device === DeviceEnum.MOBILE);
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.dark .navbar__right > *:hover {
|
||||
background: rgb(255 255 255 / 20%);
|
||||
}
|
||||
|
||||
.layout-top .navbar__right > *,
|
||||
.layout-mix .navbar__right > * {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .navbar__right > *:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -149,10 +149,10 @@ function resolvePath(routePath: string) {
|
||||
|
||||
& > span {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +178,10 @@ function resolvePath(routePath: string) {
|
||||
.el-sub-menu {
|
||||
& > .el-sub-menu__title > span {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div :class="{ 'has-logo': sidebarLogo }">
|
||||
<!-- 混合 -->
|
||||
<div v-if="isMixLayout" class="flex w-full">
|
||||
<!-- 混合布局 -->
|
||||
<div v-if="layout == LayoutEnum.MIX" class="flex w-full">
|
||||
<SidebarLogo v-if="sidebarLogo" :collapse="isSidebarCollapsed" />
|
||||
<SidebarMixTopMenu class="flex-1" />
|
||||
<NavbarRight />
|
||||
</div>
|
||||
|
||||
<!-- 顶部 || 左侧 -->
|
||||
<!-- 顶部布局 || 左侧布局 -->
|
||||
<template v-else>
|
||||
<SidebarLogo v-if="sidebarLogo" :collapse="isSidebarCollapsed" />
|
||||
<el-scrollbar>
|
||||
@@ -15,7 +15,7 @@
|
||||
</el-scrollbar>
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<NavbarRight v-if="isTopLayout" />
|
||||
<NavbarRight v-if="layout == LayoutEnum.TOP" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -33,8 +33,6 @@ const permissionStore = usePermissionStore();
|
||||
const sidebarLogo = computed(() => settingsStore.sidebarLogo);
|
||||
const layout = computed(() => settingsStore.layout);
|
||||
|
||||
const isMixLayout = computed(() => layout.value === LayoutEnum.MIX);
|
||||
const isTopLayout = computed(() => layout.value === LayoutEnum.TOP);
|
||||
const isSidebarCollapsed = computed(() => !appStore.sidebar.opened);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -187,25 +187,17 @@ function isAffix(tag: TagView) {
|
||||
}
|
||||
|
||||
function isFirstView() {
|
||||
try {
|
||||
return (
|
||||
selectedTag.value.path === "/dashboard" ||
|
||||
selectedTag.value.fullPath === tagsViewStore.visitedViews[1].fullPath
|
||||
);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
selectedTag.value.path === "/dashboard" ||
|
||||
selectedTag.value.fullPath === tagsViewStore.visitedViews[1]?.fullPath
|
||||
);
|
||||
}
|
||||
|
||||
function isLastView() {
|
||||
try {
|
||||
return (
|
||||
selectedTag.value.fullPath ===
|
||||
tagsViewStore.visitedViews[tagsViewStore.visitedViews.length - 1].fullPath
|
||||
);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
selectedTag.value.fullPath ===
|
||||
tagsViewStore.visitedViews[tagsViewStore.visitedViews.length - 1]?.fullPath
|
||||
);
|
||||
}
|
||||
|
||||
function refreshSelectedTag(view: TagView) {
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="{ hasTagsView: showTagsView }" class="main-container">
|
||||
<TagsView v-if="showTagsView" />
|
||||
<div :class="{ hasTagsView: isShowTagsView }" class="main-container">
|
||||
<TagsView v-if="isShowTagsView" />
|
||||
<AppMain />
|
||||
<Settings v-if="defaultSettings.showSettings" />
|
||||
<!-- 返回顶部 -->
|
||||
@@ -33,9 +33,9 @@
|
||||
</div>
|
||||
|
||||
<!-- 左侧和顶部布局 -->
|
||||
<div v-else :class="{ hasTagsView: showTagsView }" class="main-container">
|
||||
<div v-else :class="{ hasTagsView: isShowTagsView }" class="main-container">
|
||||
<NavBar v-if="layout === LayoutEnum.LEFT" />
|
||||
<TagsView v-if="showTagsView" />
|
||||
<TagsView v-if="isShowTagsView" />
|
||||
<AppMain />
|
||||
<Settings v-if="defaultSettings.showSettings" />
|
||||
<!-- 返回顶部 -->
|
||||
@@ -62,7 +62,7 @@ const width = useWindowSize().width;
|
||||
const WIDTH_DESKTOP = 992; // 响应式布局容器固定宽度 大屏(>=1200px) 中屏(>=992px) 小屏(>=768px)
|
||||
const isMobile = computed(() => appStore.device === DeviceEnum.MOBILE);
|
||||
const isOpenSidebar = computed(() => appStore.sidebar.opened);
|
||||
const showTagsView = computed(() => settingsStore.tagsView); // 是否显示tagsView
|
||||
const isShowTagsView = computed(() => settingsStore.tagsView); // 是否显示tagsView
|
||||
const layout = computed(() => settingsStore.layout); // 布局模式 left top mix
|
||||
const activeTopMenuPath = computed(() => appStore.activeTopMenuPath); // 顶部菜单激活path
|
||||
const mixedLayoutLeftRoutes = computed(() => permissionStore.mixedLayoutLeftRoutes); // 混合布局左侧菜单
|
||||
@@ -245,8 +245,10 @@ watch(route, () => {
|
||||
}
|
||||
|
||||
.hideSidebar {
|
||||
.main-container {
|
||||
margin-left: $sidebar-width-collapsed;
|
||||
&.layout-left {
|
||||
.main-container {
|
||||
margin-left: $sidebar-width-collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
&.layout-top {
|
||||
@@ -280,7 +282,7 @@ watch(route, () => {
|
||||
&.mobile {
|
||||
.sidebar-container {
|
||||
pointer-events: none;
|
||||
transform: translate3d(-210px, 0, 0);
|
||||
transform: translate3d(-$sidebar-width, 0, 0);
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
@@ -291,13 +293,10 @@ watch(route, () => {
|
||||
}
|
||||
|
||||
.mobile {
|
||||
.main-container {
|
||||
.layout-mix,
|
||||
.layout-top,
|
||||
.layout-left {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.layout-top {
|
||||
// 顶部模式全局变量修改
|
||||
--el-menu-item-height: $navbar-height;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,8 +25,8 @@ body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
|
||||
"微软雅黑", Arial, sans-serif;
|
||||
line-height: inherit;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
@@ -44,7 +44,8 @@ service.interceptors.response.use(
|
||||
ElMessage.error(msg || "系统出错");
|
||||
return Promise.reject(new Error(msg || "Error"));
|
||||
},
|
||||
async (error: any) => {
|
||||
async (error) => {
|
||||
console.error("request error", error); // for debug
|
||||
// 非 2xx 状态码处理 401、403、500 等
|
||||
const { config, response } = error;
|
||||
if (response) {
|
||||
@@ -64,20 +65,21 @@ service.interceptors.response.use(
|
||||
|
||||
export default service;
|
||||
|
||||
// 刷新 Token 的锁
|
||||
// 是否正在刷新标识,避免重复刷新
|
||||
let isRefreshing = false;
|
||||
// 因 Token 过期导致失败的请求队列
|
||||
let requestsQueue: Array<() => void> = [];
|
||||
// 因 Token 过期导致的请求等待队列
|
||||
const waitingQueue: Array<() => void> = [];
|
||||
|
||||
// 刷新 Token 处理
|
||||
async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
|
||||
return new Promise((resolve) => {
|
||||
const requestCallback = () => {
|
||||
// 封装需要重试的请求
|
||||
const retryRequest = () => {
|
||||
config.headers.Authorization = getToken();
|
||||
resolve(service(config));
|
||||
};
|
||||
|
||||
requestsQueue.push(requestCallback);
|
||||
waitingQueue.push(retryRequest);
|
||||
|
||||
if (!isRefreshing) {
|
||||
isRefreshing = true;
|
||||
@@ -86,13 +88,13 @@ async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
|
||||
useUserStoreHook()
|
||||
.refreshToken()
|
||||
.then(() => {
|
||||
// Token 刷新成功,执行请求队列
|
||||
requestsQueue.forEach((callback) => callback());
|
||||
requestsQueue = [];
|
||||
// 依次重试队列中所有请求, 重试后清空队列
|
||||
waitingQueue.forEach((callback) => callback());
|
||||
waitingQueue.length = 0;
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch((error: any) => {
|
||||
console.log("handleTokenRefresh error", error);
|
||||
// Token 刷新失败,清除用户数据并跳转到登录
|
||||
// 刷新 Token 失败,跳转登录页
|
||||
ElNotification({
|
||||
title: "提示",
|
||||
message: "您的会话已过期,请重新登录",
|
||||
|
||||
@@ -437,7 +437,7 @@ interface TreeNode {
|
||||
}
|
||||
const treeData = ref<TreeNode[]>([]);
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const queryParams = reactive<TablePageQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
@@ -535,7 +535,6 @@ const initSort = () => {
|
||||
ghostClass: "sortable-ghost", //拖拽样式
|
||||
handle: ".sortable-handle", //拖拽区域
|
||||
easing: "cubic-bezier(1, 0, 0, 1)",
|
||||
onStart: (item: any) => {},
|
||||
|
||||
// 结束拖动事件
|
||||
onEnd: (item: any) => {
|
||||
|
||||
@@ -236,7 +236,6 @@ defineOptions({
|
||||
name: "Dashboard",
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
import VisitTrend from "./components/visit-trend.vue";
|
||||
|
||||
import router from "@/router";
|
||||
|
||||
@@ -89,8 +89,8 @@ function back() {
|
||||
}
|
||||
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
display: block;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -268,7 +268,7 @@ import { Camera } from "@element-plus/icons-vue";
|
||||
|
||||
const userProfile = ref<UserProfileVO>({});
|
||||
|
||||
enum DialogType {
|
||||
const enum DialogType {
|
||||
ACCOUNT = "account",
|
||||
PASSWORD = "password",
|
||||
MOBILE = "mobile",
|
||||
@@ -287,10 +287,10 @@ const mobileUpdateForm = reactive<MobileUpdateForm>({});
|
||||
const emailUpdateForm = reactive<EmailUpdateForm>({});
|
||||
|
||||
const mobileCountdown = ref(0);
|
||||
const mobileTimer = ref<NodeJS.Timeout | null>(null);
|
||||
const mobileTimer = ref();
|
||||
|
||||
const emailCountdown = ref(0);
|
||||
const emailTimer = ref<NodeJS.Timeout | null>(null);
|
||||
const emailTimer = ref();
|
||||
|
||||
// 修改密码校验规则
|
||||
const passwordChangeRules = {
|
||||
@@ -466,6 +466,7 @@ const handleFileChange = async (event: Event) => {
|
||||
avatar: data.url,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("头像上传失败:" + error);
|
||||
ElMessage.error("头像上传失败");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ defineOptions({
|
||||
|
||||
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const dataFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const dataFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const selectIds = ref<number[]>([]);
|
||||
|
||||
@@ -160,8 +160,8 @@ defineOptions({
|
||||
|
||||
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/system/dept";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const deptFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const deptFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const selectIds = ref<number[]>([]);
|
||||
|
||||
@@ -144,8 +144,8 @@ const route = useRoute();
|
||||
|
||||
const dictCode = ref(route.query.dictCode as string);
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const dataFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const dataFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const ids = ref<number[]>([]);
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
link
|
||||
size="small"
|
||||
icon="edit"
|
||||
@click.stop="handleEditClick(scope.row.id, scope.row.name)"
|
||||
@click.stop="handleEditClick(scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
@@ -133,8 +133,8 @@ import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict"
|
||||
|
||||
import router from "@/router";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const dataFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const dataFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const ids = ref<number[]>([]);
|
||||
@@ -198,7 +198,7 @@ function handleAddClick() {
|
||||
*
|
||||
* @param id 字典ID
|
||||
*/
|
||||
function handleEditClick(id: number, name: string) {
|
||||
function handleEditClick(id: number) {
|
||||
dialog.visible = true;
|
||||
dialog.title = "修改字典";
|
||||
DictAPI.getFormData(id).then((data) => {
|
||||
|
||||
@@ -62,7 +62,7 @@ defineOptions({
|
||||
|
||||
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
|
||||
@@ -338,8 +338,8 @@ defineOptions({
|
||||
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/system/menu";
|
||||
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const menuFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const menuFormRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const dialog = reactive({
|
||||
|
||||
@@ -87,7 +87,7 @@ defineOptions({
|
||||
|
||||
import NoticeAPI, { NoticePageVO, NoticePageQuery } from "@/api/system/notice";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const noticeDetailRef = ref();
|
||||
|
||||
const pageData = ref<NoticePageVO[]>([]);
|
||||
|
||||
@@ -223,8 +223,8 @@ defineOptions({
|
||||
import NoticeAPI, { NoticePageVO, NoticeForm, NoticePageQuery } from "@/api/system/notice";
|
||||
import UserAPI from "@/api/system/user";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const dataFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const dataFormRef = ref();
|
||||
const noticeDetailRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
@@ -211,9 +211,9 @@ defineOptions({
|
||||
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role";
|
||||
import MenuAPI from "@/api/system/menu";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const roleFormRef = ref(ElForm);
|
||||
const permTreeRef = ref<InstanceType<typeof ElTree>>();
|
||||
const queryFormRef = ref();
|
||||
const roleFormRef = ref();
|
||||
const permTreeRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
const ids = ref<number[]>([]);
|
||||
|
||||
@@ -30,7 +30,7 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const deptList = ref<OptionType[]>(); // 部门列表
|
||||
const deptTreeRef = ref(ElTree); // 部门树
|
||||
const deptTreeRef = ref(); // 部门树
|
||||
const deptName = ref(); // 部门名称
|
||||
|
||||
const emits = defineEmits(["node-click"]);
|
||||
|
||||
@@ -175,8 +175,9 @@ const handleUpload = async () => {
|
||||
invalidCount.value = result.invalidCount;
|
||||
validCount.value = result.validCount;
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error("上传失败");
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
ElMessage.error("上传失败:" + error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -249,9 +249,8 @@ defineOptions({
|
||||
name: "User",
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const userFormRef = ref(ElForm);
|
||||
const queryFormRef = ref();
|
||||
const userFormRef = ref();
|
||||
|
||||
const queryParams = reactive<UserPageQuery>({
|
||||
pageNum: 1,
|
||||
|
||||
Reference in New Issue
Block a user