refactor: ♻️ 代码规范优化

This commit is contained in:
ray
2025-02-12 13:40:27 +08:00
parent e865b33bd9
commit cd72290d06
31 changed files with 113 additions and 120 deletions

View File

@@ -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";

View File

@@ -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];
}
}

View File

@@ -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];
}
}

View File

@@ -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;

View File

@@ -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) {

View File

@@ -169,7 +169,7 @@ function handleUpload(options: UploadRequestOptions) {
/**
* 上传文件超出限制
*/
function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
function handleExceed() {
ElMessage.warning("最多只能上传" + props.limit + "张图片");
}

View File

@@ -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>

View File

@@ -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;
}
}
}

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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>

View File

@@ -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;

View File

@@ -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: "您的会话已过期,请重新登录",

View File

@@ -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) => {

View File

@@ -236,7 +236,6 @@ defineOptions({
name: "Dashboard",
inheritAttrs: false,
});
import VisitTrend from "./components/visit-trend.vue";
import router from "@/router";

View File

@@ -89,8 +89,8 @@ function back() {
}
&__return-home {
display: block;
float: left;
display: block;
width: 110px;
height: 36px;
font-size: 14px;

View File

@@ -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("头像上传失败");
}
}

View File

@@ -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[]>([]);

View File

@@ -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[]>([]);

View File

@@ -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[]>([]);

View File

@@ -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) => {

View File

@@ -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);

View File

@@ -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({

View File

@@ -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[]>([]);

View File

@@ -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);

View File

@@ -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[]>([]);

View File

@@ -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"]);

View File

@@ -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);
}
};

View File

@@ -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,