refactor: 大规模代码整理与功能优化

1. 重构后端API路由、CRUD与模块结构,整合日志管理,移除废弃demo代码
2. 优化前端组件类型定义、样式与路由配置,修复权限判断逻辑
3. 调整默认排序规则、滚动条样式与工具类函数,更新依赖与配置文件
4. 修复多处类型不匹配与默认值问题,完善表单与菜单验证逻辑
This commit is contained in:
zhangtao
2026-06-17 01:56:31 +08:00
parent 17b3cd0a4c
commit 73f2823692
500 changed files with 40763 additions and 26616 deletions
@@ -45,9 +45,11 @@ const hasAnyAuthItem = computed(() => {
return props.list.some((item) => !item.auth || hasAuth(item.auth));
});
const emit = defineEmits<{
(e: "click", item: ButtonMoreItem): void;
}>();
interface Emits {
click: [item: ButtonMoreItem];
}
const emit = defineEmits<Emits>();
const handleClick = (item: ButtonMoreItem) => {
emit("click", item);
@@ -30,9 +30,11 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {});
const emit = defineEmits<{
(e: "click"): void;
}>();
interface Emits {
click: [];
}
const emit = defineEmits<Emits>();
// 默认按钮配置
const defaultButtons = {
@@ -46,7 +46,7 @@ defineOptions({ name: "FaDragVerify" });
const emit = defineEmits(["handlerMove", "update:value", "passCallback"]);
// 组件属性接口定义
interface PropsType {
interface Props {
/** 是否通过验证 */
value: boolean;
/** 组件宽度 */
@@ -80,7 +80,7 @@ interface PropsType {
}
// 属性默认值设置
const props = withDefaults(defineProps<PropsType>(), {
const props = withDefaults(defineProps<Props>(), {
value: false,
width: "100%",
height: 40,
@@ -46,7 +46,7 @@ interface ColumnConfig {
}
/** 导出配置选项 */
interface ExportOptions {
interface Props {
/** 数据源 */
data: ExportData[];
/** 文件名(不含扩展名) */
@@ -90,7 +90,7 @@ interface ExportOptions {
};
}
const props = withDefaults(defineProps<ExportOptions>(), {
const props = withDefaults(defineProps<Props>(), {
filename: () => `export_${new Date().toISOString().slice(0, 10)}`,
sheetName: "Sheet1",
type: "primary",
@@ -108,12 +108,14 @@ const props = withDefaults(defineProps<ExportOptions>(), {
workbookOptions: () => ({}),
});
const emit = defineEmits<{
interface Emits {
"before-export": [data: ExportData[]];
"export-success": [filename: string, rowCount: number];
"export-error": [error: ExportError];
"export-progress": [progress: number];
}>();
}
const emit = defineEmits<Emits>();
/** 导出错误类型 */
class ExportError extends Error {
@@ -3,12 +3,13 @@
<div class="inline-block">
<ElUpload
:auto-upload="false"
accept=".xlsx, .xls"
:accept="accept"
:show-file-list="false"
:disabled="disabled"
@change="handleFileChange"
>
<ElButton type="primary" v-ripple>
<slot>导入 Excel</slot>
<ElButton type="primary" v-ripple :loading="loading">
<slot>{{ buttonText }}</slot>
</ElButton>
</ElUpload>
</div>
@@ -20,6 +21,24 @@ import type { UploadFile } from "element-plus";
defineOptions({ name: "FaExcelImport" });
interface Props {
/** 接受的文件类型 */
accept?: string;
/** 按钮文本 */
buttonText?: string;
/** 加载状态 */
loading?: boolean;
/** 是否禁用 */
disabled?: boolean;
}
withDefaults(defineProps<Props>(), {
accept: ".xlsx, .xls",
buttonText: "导入 Excel",
loading: false,
disabled: false,
});
// Excel 导入工具函数
async function importExcel(file: File): Promise<Array<Record<string, unknown>>> {
return new Promise((resolve, reject) => {
@@ -44,10 +63,12 @@ async function importExcel(file: File): Promise<Array<Record<string, unknown>>>
}
// 定义 emits
const emit = defineEmits<{
interface Emits {
"import-success": [data: Array<Record<string, unknown>>];
"import-error": [error: Error];
}>();
}
const emit = defineEmits<Emits>();
// 处理文件导入
const handleFileChange = async (uploadFile: UploadFile) => {
@@ -277,7 +277,7 @@ export interface FormItem {
}
// 表单配置
interface FormProps {
interface Props {
/** 表单数据 */
items: FormItem[];
/** 每列的宽度(基于 24 格布局) */
@@ -319,7 +319,7 @@ interface SanitizeOutputOptions {
keepFalse: boolean;
}
const props = withDefaults(defineProps<FormProps>(), {
const props = withDefaults(defineProps<Props>(), {
items: () => [],
span: 6,
gutter: 12,
@@ -334,12 +334,12 @@ const props = withDefaults(defineProps<FormProps>(), {
maxHeight: "75vh",
});
interface FormEmits {
interface Emits {
reset: [];
submit: [Record<string, any>];
}
const emit = defineEmits<FormEmits>();
const emit = defineEmits<Emits>();
const modelValue = defineModel<Record<string, any>>({ default: {} });
const initialModelValue = ref<Record<string, any>>({});
@@ -520,9 +520,20 @@ const getSanitizedOutput = () => {
};
const getProps = (item: FormItem) => {
if (item.props) return item.props;
const props = { ...item };
rootProps.forEach((key) => delete (props as Record<string, any>)[key]);
let props: Record<string, any>;
if (item.props) {
props = { ...item.props };
} else {
props = { ...item };
rootProps.forEach((key) => delete props[key]);
}
// 对于日期选择器组件,确保 type 被传递给 FaDatePicker
const datePickerTypes = ["date", "daterange", "datetime", "datetimerange", "monthrange"];
if (item.type && datePickerTypes.includes(item.type) && !props.type) {
props.type = item.type;
}
return props;
};
@@ -31,24 +31,29 @@ type DatePickerType =
| "daterange"
| "monthrange";
const props = withDefaults(
defineProps<{
modelValue?: any;
type?: DatePickerType;
format?: string;
rangeSeparator?: string;
startPlaceholder?: string;
endPlaceholder?: string;
}>(),
{
type: "datetimerange",
rangeSeparator: "至",
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
}
);
defineOptions({ name: "FaDatePicker" });
const emit = defineEmits(["update:model-value"]);
interface Props {
modelValue?: any;
type?: DatePickerType;
format?: string;
rangeSeparator?: string;
startPlaceholder?: string;
endPlaceholder?: string;
}
const props = withDefaults(defineProps<Props>(), {
type: "datetimerange",
rangeSeparator: "至",
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
});
interface Emits {
(e: "update:model-value", value: any): void;
}
const emit = defineEmits<Emits>();
/** 是否为范围选择模式 */
const isRangeType = computed(() => {
@@ -47,22 +47,23 @@ import {
defineOptions({ name: "FaSearchBarWithAudit", inheritAttrs: false });
const props = withDefaults(
defineProps<{
/** 仅业务条件表单项,不含审计四字段 */
items: SearchFormItem[];
/** 为 false 时与原生 FaSearchBar 一致,仅使用 `items` */
includeAudit?: boolean;
/** 传给 getAuditSearchFormItems 的选项 */
auditItemOptions?: GetAuditSearchFormItemsOptions;
}>(),
{ includeAudit: true }
);
interface Props {
/** 仅业务条件表单项,不含审计四字段 */
items: SearchFormItem[];
/** 为 false 时与原生 FaSearchBar 一致,仅使用 `items` */
includeAudit?: boolean;
/** 传给 getAuditSearchFormItems 的选项 */
auditItemOptions?: GetAuditSearchFormItemsOptions;
}
const emit = defineEmits<{
const props = withDefaults(defineProps<Props>(), { includeAudit: true });
interface Emits {
search: [Record<string, any>];
reset: [];
}>();
}
const emit = defineEmits<Emits>();
const modelValue = defineModel<Record<string, any>>({ default: () => ({}) });
const attrs = useAttrs();
@@ -18,14 +18,20 @@
import type { ISelectConfig } from "@/components/others/fa-table-select/index.vue";
import UserAPI, { UserPageQuery } from "@/api/module_system/user";
// 父组件双向绑定的值(选中用户ID)
const props = defineProps<{ modelValue?: number }>();
defineOptions({ name: "FaUserTableSelect" });
// 事件向上派发,支持父组件监听和 v-model(仅回传选中用户ID)
const emit = defineEmits<{
interface Props {
modelValue?: number;
}
const props = withDefaults(defineProps<Props>(), {});
interface Emits {
confirmClick: [data: IUser[]];
"update:modelValue": [val: number | undefined];
}>();
}
const emit = defineEmits<Emits>();
const selectConfig: ISelectConfig = {
pk: "id",
@@ -190,7 +190,7 @@ export interface SearchFormItem {
}
// 表单配置
interface SearchBarProps {
interface Props {
/** 表单数据 */
items: SearchFormItem[];
/** 每列的宽度(基于 24 格布局) */
@@ -234,7 +234,7 @@ interface SanitizeOutputOptions {
keepFalse: boolean;
}
const props = withDefaults(defineProps<SearchBarProps>(), {
const props = withDefaults(defineProps<Props>(), {
items: () => [],
span: 6,
gutter: 12,
@@ -250,12 +250,12 @@ const props = withDefaults(defineProps<SearchBarProps>(), {
sanitizeOutput: () => ({}),
});
interface SearchBarEmits {
interface Emits {
reset: [];
search: [Record<string, any>];
}
const emit = defineEmits<SearchBarEmits>();
const emit = defineEmits<Emits>();
const modelValue = defineModel<Record<string, any>>({ default: {} });
const initialModelValue = ref<Record<string, any>>({});