refactor: ♻️ 完善TS的类型定义,更高的类型安全

This commit is contained in:
超凡
2025-04-17 23:09:42 +08:00
parent 5f886825bb
commit c3aefbb2df
3 changed files with 44 additions and 90 deletions

View File

@@ -1,5 +1,5 @@
<template> <template>
<div v-show="visible" style="margin-bottom: 12px" v-bind="cardAttrs"> <div v-show="visible" v-bind="{ style: { 'margin-bottom': '12px' }, ...cardAttrs }">
<el-card <el-card
v-hasPerm="searchConfig?.pageName ? `${searchConfig.pageName}:query` : '*:*:*'" v-hasPerm="searchConfig?.pageName ? `${searchConfig.pageName}:query` : '*:*:*'"
v-bind="cardAttrs" v-bind="cardAttrs"
@@ -12,16 +12,15 @@
:prop="item.prop" :prop="item.prop"
> >
<!-- Label --> <!-- Label -->
<template v-if="item?.tips" #label> <template #label>
<span class="flex-y-center"> <span class="flex-y-center">
{{ item.label }} {{ item?.label || "" }}
<el-tooltip v-bind="getTooltipProps(item.tips)"> <el-tooltip v-if="item?.tips" v-bind="getTooltipProps(item.tips)">
<QuestionFilled class="w-4 h-4 mx-1" /> <QuestionFilled class="w-4 h-4 mx-1" />
</el-tooltip> </el-tooltip>
{{ searchConfig.colon ? ":" : "" }} <span v-if="searchConfig.colon" class="ml-0.5">:</span>
</span> </span>
</template> </template>
<template v-else #label>{{ item.label }} {{ searchConfig.colon ? ":" : "" }}</template>
<el-cascader <el-cascader
v-if="item.type === 'cascader'" v-if="item.type === 'cascader'"
@@ -44,6 +43,7 @@
</component> </component>
</el-form-item> </el-form-item>
</template> </template>
<el-form-item :class="{ 'col-[auto/-1] justify-self-end': searchConfig?.grid === 'right' }"> <el-form-item :class="{ 'col-[auto/-1] justify-self-end': searchConfig?.grid === 'right' }">
<el-button icon="search" type="primary" @click="handleQuery">搜索</el-button> <el-button icon="search" type="primary" @click="handleQuery">搜索</el-button>
<el-button icon="refresh" @click="handleReset">重置</el-button> <el-button icon="refresh" @click="handleReset">重置</el-button>
@@ -61,9 +61,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { IObject, ISearchConfig, ComponentType } from "./types"; import type { IObject, IForm, ISearchConfig, ISearchComponent } from "./types";
import { ArrowUp, ArrowDown } from "@element-plus/icons-vue"; import { ArrowUp, ArrowDown } from "@element-plus/icons-vue";
import { type FormInstance } from "element-plus"; import type { FormInstance, ElTooltipProps } from "element-plus";
import InputTag from "@/components/InputTag/index.vue"; import InputTag from "@/components/InputTag/index.vue";
// 定义接收的属性 // 定义接收的属性
@@ -74,7 +74,7 @@ const emit = defineEmits<{
resetClick: [queryParams: IObject]; resetClick: [queryParams: IObject];
}>(); }>();
// 组件映射表 // 组件映射表
const componentMap = new Map<ComponentType, Component>([ const componentMap = new Map<ISearchComponent, Component>([
/* eslint-disable */ /* eslint-disable */
// @ts-ignore // @ts-ignore
["input", markRaw(ElInput)], // @ts-ignore ["input", markRaw(ElInput)], // @ts-ignore
@@ -108,7 +108,7 @@ const cardAttrs = computed<IObject>(() => {
return { shadow: "never", ...props.searchConfig?.cardAttrs }; return { shadow: "never", ...props.searchConfig?.cardAttrs };
}); });
// 表单组件自定义属性label位置、宽度、对齐方式等 // 表单组件自定义属性label位置、宽度、对齐方式等
const formAttrs = computed(() => { const formAttrs = computed<IForm>(() => {
return { inline: true, ...props.searchConfig?.form }; return { inline: true, ...props.searchConfig?.form };
}); });
// 是否使用自适应网格布局 // 是否使用自适应网格布局
@@ -120,7 +120,7 @@ const isGrid = computed(() =>
// 搜索表单数据 // 搜索表单数据
const queryParams = reactive<IObject>({}); const queryParams = reactive<IObject>({});
// 获取tooltip的属性 // 获取tooltip的属性
const getTooltipProps = (tips: any) => { const getTooltipProps = (tips: string | Partial<ElTooltipProps>) => {
return typeof tips === "string" ? { content: tips } : tips; return typeof tips === "string" ? { content: tips } : tips;
}; };

View File

@@ -1,14 +1,6 @@
import type { import type { DialogProps, DrawerProps, FormItemRule, PaginationProps } from "element-plus";
DialogProps, import type { FormProps, TableProps, ColProps, ButtonProps, CardProps } from "element-plus";
DrawerProps, import type { ButtonType, ElTooltipProps } from "element-plus";
FormItemRule,
FormProps,
PaginationProps,
TableProps,
ColProps,
ButtonType,
CardProps,
} from "element-plus";
import type PageContent from "./PageContent.vue"; import type PageContent from "./PageContent.vue";
import type PageForm from "./PageForm.vue"; import type PageForm from "./PageForm.vue";
import type PageModal from "./PageModal.vue"; import type PageModal from "./PageModal.vue";
@@ -22,6 +14,25 @@ export type PageFormInstance = InstanceType<typeof PageForm>;
export type IObject = Record<string, any>; export type IObject = Record<string, any>;
type DataComponent = "date-picker" | "time-picker" | "time-select" | "custom-tag" | "input-tag";
type InputComponent = "input" | "select" | "input-number" | "cascader" | "tree-select";
type OtherComponent = "text" | "radio" | "checkbox" | "switch" | "custom";
export type ISearchComponent = DataComponent | InputComponent;
export type IComponentType = DataComponent | InputComponent | OtherComponent;
type ToolbarLeft = "add" | "delete" | "import" | "export";
type ToolbarRight = "refresh" | "filter" | "imports" | "exports" | "search";
type ToolbarTable = "edit" | "view" | "delete";
type IToolsButton = {
name?: string; // 按钮名称
text?: string; // 按钮文本
icon?: string; // 按钮图标
type?: ButtonType; // 按钮类型
auth?: Array<string> | string; // 按钮权限
attrs?: Partial<ButtonProps>; // 按钮属性
};
export type IToolsDefault = ToolbarLeft | ToolbarRight | ToolbarTable | IToolsButton;
export interface IOperatData { export interface IOperatData {
name: string; name: string;
row: IObject; row: IObject;
@@ -29,18 +40,6 @@ export interface IOperatData {
$index: number; $index: number;
} }
export type ComponentType =
| "input"
| "select"
| "input-number"
| "date-picker"
| "time-picker"
| "time-select"
| "tree-select"
| "input-tag"
| "custom-tag"
| "cascader";
export interface ISearchConfig { export interface ISearchConfig {
// 页面名称(参与组成权限标识,如sys:user:xxx),不填则不进行权限校验 // 页面名称(参与组成权限标识,如sys:user:xxx),不填则不进行权限校验
pageName?: string; pageName?: string;
@@ -49,11 +48,11 @@ export interface ISearchConfig {
// 表单项(默认:[]) // 表单项(默认:[])
formItems?: Array<{ formItems?: Array<{
// 组件类型(如input,select等) // 组件类型(如input,select等)
type?: ComponentType; type?: ISearchComponent;
// 标签文本 // 标签文本
label?: string; label?: string;
// 标签提示 // 标签提示
tips?: string | IObject; tips?: string | Partial<ElTooltipProps>;
// 键名 // 键名
prop: string; prop: string;
// 组件属性(input-tag组件支持join,btnText,size属性) // 组件属性(input-tag组件支持join,btnText,size属性)
@@ -63,7 +62,7 @@ export interface ISearchConfig {
// 可选项(适用于select组件) // 可选项(适用于select组件)
options?: Array<{ label: string; value: any }>; options?: Array<{ label: string; value: any }>;
// 组件事件 // 组件事件
events?: Record<string, (...args: any[]) => void>; events?: Record<string, (...args: any) => void>;
// 初始化数据函数扩展 // 初始化数据函数扩展
initFn?: (formItem: IObject) => void; initFn?: (formItem: IObject) => void;
}>; }>;
@@ -81,7 +80,7 @@ export interface ISearchConfig {
export interface IContentConfig<T = any> { export interface IContentConfig<T = any> {
// 页面名称(参与组成权限标识,如sys:user:xxx) // 页面名称(参与组成权限标识,如sys:user:xxx)
pageName: string; pageName?: string;
// table组件属性 // table组件属性
table?: Omit<TableProps<any>, "data">; table?: Omit<TableProps<any>, "data">;
// 分页组件位置(默认left) // 分页组件位置(默认left)
@@ -128,34 +127,10 @@ export interface IContentConfig<T = any> {
importsAction?: (data: IObject[]) => Promise<any>; importsAction?: (data: IObject[]) => Promise<any>;
// 主键名(默认为id) // 主键名(默认为id)
pk?: string; pk?: string;
// 表格工具栏(默认支持add,delete,export,也可自定义) // 表格工具栏(默认:add,delete,export,也可自定义)
toolbar?: Array< toolbar?: Array<ToolbarLeft | IToolsButton>;
| "add" // 表格工具栏右侧图标(默认:refresh,filter,imports,exports,search)
| "delete" defaultToolbar?: Array<ToolbarRight | IToolsButton>;
| "import"
| "export"
| {
auth: string;
icon?: string;
name: string;
text: string;
type?: ButtonType;
}
>;
// 表格工具栏右侧图标
defaultToolbar?: Array<
| "refresh"
| "filter"
| "imports"
| "exports"
| "search"
| {
name: string;
icon: string;
title?: string;
auth?: string;
}
>;
// table组件列属性(额外的属性templet,operat,slotName) // table组件列属性(额外的属性templet,operat,slotName)
cols: Array<{ cols: Array<{
type?: "default" | "selection" | "index" | "expand"; type?: "default" | "selection" | "index" | "expand";
@@ -197,18 +172,7 @@ export interface IContentConfig<T = any> {
// date模板相关参数 // date模板相关参数
dateFormat?: string; dateFormat?: string;
// tool模板相关参数 // tool模板相关参数
operat?: Array< operat?: Array<ToolbarTable | IToolsButton>;
| "edit"
| "delete"
| {
auth?: string;
icon?: string;
name: string;
text: string;
type?: ButtonType;
render?: (row: IObject) => boolean;
}
>;
// filter值拼接符 // filter值拼接符
filterJoin?: string; filterJoin?: string;
[key: string]: any; [key: string]: any;
@@ -243,17 +207,7 @@ export type IForm = Partial<Omit<FormProps, "model" | "rules">>;
// 表单项 // 表单项
export type IFormItems<T = any> = Array<{ export type IFormItems<T = any> = Array<{
// 组件类型(如input,select,radio,custom等默认input) // 组件类型(如input,select,radio,custom等默认input)
type?: type?: IComponentType;
| "input"
| "select"
| "radio"
| "switch"
| "checkbox"
| "tree-select"
| "date-picker"
| "input-number"
| "text"
| "custom";
// 组件属性 // 组件属性
attrs?: IObject; attrs?: IObject;
// 组件可选项(适用于select,radio,checkbox组件) // 组件可选项(适用于select,radio,checkbox组件)

View File

@@ -46,7 +46,7 @@ export default defineConfig({
primary_dark: "var(--el-color-primary-light-5)", primary_dark: "var(--el-color-primary-light-5)",
}, },
breakpoints: Object.fromEntries( breakpoints: Object.fromEntries(
[640, 768, 1024, 1280, 1536, 1920, 2048].map((size, index) => [ [640, 768, 1024, 1280, 1536, 1920, 2560].map((size, index) => [
["sm", "md", "lg", "xl", "2xl", "3xl", "4xl"][index], ["sm", "md", "lg", "xl", "2xl", "3xl", "4xl"][index],
`${size}px`, `${size}px`,
]) ])