refactor: 项目重构

This commit is contained in:
Ray.Hao
2025-05-24 07:35:46 +08:00
parent cfe041d7d2
commit 32686ad807
51 changed files with 1201 additions and 696 deletions

View File

@@ -547,7 +547,7 @@ const initSort = () => {
const setNodeSort = (oldIndex: number, newIndex: number) => {
// 使用arr复制一份表格数组数据
let arr = Object.assign([], genConfigFormData.value.fieldConfigs);
const arr = Object.assign([], genConfigFormData.value.fieldConfigs);
const currentRow = arr.splice(oldIndex, 1)[0];
arr.splice(newIndex, 0, currentRow);
arr.forEach((item: FieldConfig, index) => {

View File

@@ -21,7 +21,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
list: res.list,
};
},
indexAction: function (params) {
indexAction (params) {
return UserAPI.getPage(params);
},
deleteAction: UserAPI.deleteByIds,
@@ -35,7 +35,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
console.log("importsAction", data);
return Promise.resolve();
},
exportsAction: async function (params) {
async exportsAction (params) {
// 模拟获取到的是全量数据
const res = await UserAPI.getPage(params);
console.log("exportsAction", res.list);

View File

@@ -15,7 +15,7 @@ const modalConfig: IModalConfig<UserForm> = {
beforeSubmit(data) {
console.log("beforeSubmit", data);
},
formAction: function (data) {
formAction (data) {
return UserAPI.update(data.id as string, data);
},
formItems: [

View File

@@ -9,9 +9,9 @@ interface OptionType {
}
// 明确指定类型为 OptionType[]
export let deptArr = ref<OptionType[]>([]);
export let roleArr = ref<OptionType[]>([]);
export let stateArr = ref<OptionType[]>([
export const deptArr = ref<OptionType[]>([]);
export const roleArr = ref<OptionType[]>([]);
export const stateArr = ref<OptionType[]>([
{ label: "启用", value: 1 },
{ label: "禁用", value: 0 },
]);

View File

@@ -1,4 +1,4 @@
import { type UserForm } from "@/api/system/user.api";
import type { UserForm } from "@/api/system/user.api";
import type { IModalConfig } from "@/components/CURD/types";
import { deptArr } from "../config/options";

View File

@@ -7,7 +7,7 @@ const contentConfig: IContentConfig = {
},
pagePosition: "right",
toolbar: [],
indexAction: function (params) {
indexAction (params) {
// 模拟发起网络请求获取列表数据
console.log("indexAction:", params);
return Promise.resolve({

View File

@@ -15,7 +15,7 @@ const modalConfig: IModalConfig = {
beforeSubmit(data) {
console.log("beforeSubmit", data);
},
formAction: function (data) {
formAction (data) {
// return UserAPI.update(data.id as string, data);
// 模拟发起网络请求修改字段
ElMessage.success(JSON.stringify(data));

View File

@@ -35,7 +35,7 @@ const searchConfig: ISearchConfig = {
attrs: { placeholder: "全部", clearable: true },
options: stateArr as any,
events: {
change: function (e) {
change (e) {
console.log("选中的值: ", e);
},
},

View File

@@ -1,10 +1,4 @@
<!-- 字典组件示例 -->
<script setup lang="ts">
const stringValue = ref("1"); // 性别(值为String)
const numberValue = ref(1); // 性别(值为Number)
const arrayValue = ref(["1", "2"]); // 性别(值为Array)
</script>
<template>
<div class="app-container">
<el-link
@@ -46,3 +40,9 @@ const arrayValue = ref(["1", "2"]); // 性别(值为Array)
</el-form>
</div>
</template>
<script setup lang="ts">
const stringValue = ref("1"); // 性别(值为String)
const numberValue = ref(1); // 性别(值为Number)
const arrayValue = ref(["1", "2"]); // 性别(值为Array)
</script>

View File

@@ -1,11 +1,4 @@
<!-- 图标选择器示例 -->
<script setup lang="ts">
// element-plus 图标格式以el-icon-开头
const iconName = ref("el-icon-edit");
// 本地SVG图标格式取 src/assets/icons 下的文件名不需要svg后缀
// const iconName = ref("api");
</script>
<template>
<div class="app-container">
<el-link
@@ -19,3 +12,10 @@ const iconName = ref("el-icon-edit");
<icon-select v-model="iconName" />
</div>
</template>
<script setup lang="ts">
// element-plus 图标格式以el-icon-开头
const iconName = ref("el-icon-edit");
// 本地SVG图标格式取 src/assets/icons 下的文件名不需要svg后缀
// const iconName = ref("api");
</script>

View File

@@ -1,3 +1,25 @@
<template>
<div class="canvas-dom">
<h3>基于canvas实现的签名组件</h3>
<header>
<el-button type="primary" @click="handleSaveImg">保存为图片</el-button>
<el-button @click="handleToFile">保存到后端</el-button>
<el-button @click="handleClearSign">清空签名</el-button>
</header>
<canvas
ref="canvas"
height="200"
width="500"
@mousedown="onEventStart"
@mousemove.stop.prevent="onEventMove"
@mouseup="onEventEnd"
@touchstart="onEventStart"
@touchmove.stop.prevent="onEventMove"
@touchend="onEventEnd"
/>
<img v-if="imgUrl" :src="imgUrl" alt="签名" />
</div>
</template>
<script setup lang="ts">
import FileAPI from "@/api/file.api";
@@ -133,28 +155,6 @@ function paint(
ctx.stroke();
}
</script>
<template>
<div class="canvas-dom">
<h3>基于canvas实现的签名组件</h3>
<header>
<el-button type="primary" @click="handleSaveImg">保存为图片</el-button>
<el-button @click="handleToFile">保存到后端</el-button>
<el-button @click="handleClearSign">清空签名</el-button>
</header>
<canvas
ref="canvas"
height="200"
width="500"
@mousedown="onEventStart"
@mousemove.stop.prevent="onEventMove"
@mouseup="onEventEnd"
@touchstart="onEventStart"
@touchmove.stop.prevent="onEventMove"
@touchend="onEventEnd"
/>
<img v-if="imgUrl" :src="imgUrl" alt="签名" />
</div>
</template>
<style scoped lang="scss">
.canvas-dom {
width: 100%;

View File

@@ -81,7 +81,7 @@ const selectConfig: ISelectConfig = {
},
},
],
indexAction: function (params) {
indexAction (params) {
if ("createAt" in params) {
const createAt = params.createAt as string[];
if (createAt?.length > 1) {

View File

@@ -1,4 +1,27 @@
<!-- 列表选择器示例 -->
<template>
<div class="app-container">
<el-link
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/table-select/index.vue"
type="primary"
target="_blank"
class="mb-10"
>
示例源码 请点击>>>>
</el-link>
<table-select :text="text" :select-config="selectConfig" @confirm-click="handleConfirm">
<template #status="scope">
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
</el-tag>
</template>
<template #gender="scope">
<DictLabel v-model="scope.row.gender" code="gender" />
</template>
</table-select>
</div>
</template>
<script setup lang="ts">
import selectConfig from "./config/select";
import { useDictStore } from "@/store";
@@ -29,26 +52,3 @@ const text = computed(() => {
: "";
});
</script>
<template>
<div class="app-container">
<el-link
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/table-select/index.vue"
type="primary"
target="_blank"
class="mb-10"
>
示例源码 请点击>>>>
</el-link>
<table-select :text="text" :select-config="selectConfig" @confirm-click="handleConfirm">
<template #status="scope">
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
</el-tag>
</template>
<template #gender="scope">
<DictLabel v-model="scope.row.gender" code="gender" />
</template>
</table-select>
</div>
</template>

View File

@@ -13,7 +13,7 @@
<TextScroll type="info" text="这是一条信息类型的滚动公告" />
<!-- 自定义速度和方向 -->
<TextScroll text="这是一条速度较慢、向右滚动的公告" :speed="30" direction="right" showClose />
<TextScroll text="这是一条速度较慢、向右滚动的公告" :speed="30" direction="right" show-close />
</div>
</template>

View File

@@ -1,10 +1,4 @@
<!-- wangEditor富文本编辑器示例 -->
<script setup lang="ts">
import WangEditor from "@/components/WangEditor/index.vue";
const value = ref("初始化内容");
</script>
<template>
<div class="app-container">
<el-link
@@ -22,3 +16,9 @@ const value = ref("初始化内容");
</div>
</div>
</template>
<script setup lang="ts">
import WangEditor from "@/components/WangEditor/index.vue";
const value = ref("初始化内容");
</script>

View File

@@ -135,7 +135,7 @@ const loginFormData = ref<LoginFormData>({
password: "123456",
captchaKey: "",
captchaCode: "",
rememberMe: rememberMe,
rememberMe,
});
const loginRules = computed(() => {
@@ -195,12 +195,16 @@ async function handleLoginSubmit() {
// 2. 执行登录
await userStore.login(loginFormData.value);
// 3. 获取用户信息
// 3. 获取用户信息(包含用户角色,用于路由生成)
await userStore.getUserInfo();
// 4. 解析并跳转目标地址
// 4. 登录成功,让路由守卫处理跳转逻辑
// 解析目标地址,但不直接跳转
const redirect = resolveRedirectTarget(route.query);
await router.push(redirect);
console.log("🎉 Login successful, target redirect:", redirect);
// 通过替换当前路由触发路由守卫,让守卫处理后续的路由生成和跳转
await router.replace(redirect);
// 5. 记住我功能已实现根据用户选择决定token的存储方式:
// - 选中"记住我": token存储在localStorage中浏览器关闭后仍然有效