最佳实践
项目组织
推荐目录结构
src/
├── config/
│ └── vueAdminKit/ # vue-admin-kit 配置
│ ├── index.ts # 主配置入口
│ ├── tableHeight.ts # 表格高度计算
│ ├── dictAdapters.ts # 自定义字典适配器
│ └── columnConfigs/ # 配置注册
│ ├── index.ts
│ ├── columns.ts
│ ├── forms.ts
│ └── search.ts
├── views/
│ └── system/
│ └── user/
│ ├── index/ # 列表页
│ │ ├── index.vue
│ │ └── config/
│ │ ├── index.ts # 统一导出
│ │ ├── api.ts
│ │ ├── columnsConfig.ts
│ │ ├── formConfig.ts
│ │ ├── searchConfig.ts
│ │ └── permissions.ts
│ ├── detail/ # 详情页(可选)
│ └── components/ # 共享组件(可选)
└── main.ts全局配置
typescript
// src/config/vueAdminKit/index.ts
import "vue-admin-kit/style.css";
import { setupPageTemplate, configurePermissionDirective } from "vue-admin-kit";
export function setupPageTemplateConfig() {
setupPageTemplate({
// ========== UI 配置 ==========
ui: {
formItemSize: () => "default", // 表单项尺寸: 'default' | 'small' | 'large'
},
// ========== 依赖注入 ==========
dependencies: {
// 表格高度计算函数
calculateHeight: (formHeight, otherHeight) => {
return window.innerHeight - formHeight - otherHeight - 200;
},
// 自定义字典适配器
customAdapters: CUSTOM_ADAPTERS,
// OSS 文件上传/删除
oss: {
uploadOSS: async (file) => {
// 返回: { url, fileName, ossId }
},
deleteOSS: async (ossId) => {
// 返回: { code, msg }
},
},
// 字典加载器
dictLoader: async (dictType) => {
// 返回: { success, data: [{ label, value, elTagType }] }
},
},
});
// 配置权限指令
configurePermissionDirective({
getPermissions: () => [], // 获取用户权限列表
getRoles: () => [], // 获取用户角色列表
superPermission: "*:*:*", // 超级权限标识
superRoles: ["admin"], // 超级角色列表
});
}页面配置文件
config/api.ts
typescript
import { defineApiConfig } from "vue-admin-kit";
export default defineApiConfig({
list: api.list, // 列表查询接口(必须)
add: api.add, // 新增接口
update: api.update, // 编辑接口
delete: api.del, // 删除接口
detail: api.get, // 详情接口(可选,不配置则使用列表数据)
});config/columnsConfig.ts
typescript
import { defineColumnsConfig, getColumnConfig } from "vue-admin-kit";
export default defineColumnsConfig([
// ========== 特殊列类型 ==========
{
type: "checkbox", // 列类型: 'checkbox' | 'seq' | 'expand' | 'radio'
fixed: "left", // 固定位置: 'left' | 'right'
width: 70, // 列宽度(固定)
},
{
type: "seq", // 序号列
width: 100,
title: "序号",
},
{
type: "expand", // 展开列
width: 80,
slots: { content: "detailContent" }, // 插槽名称
},
// ========== 普通数据列 ==========
{
field: "name", // 字段名(对应数据属性)
title: "名称", // 列标题
width: 200, // 固定宽度
minWidth: 120, // 最小宽度(自适应)
sortable: true, // 是否可排序
align: "center", // 对齐方式: 'left' | 'center' | 'right'
fixed: "left", // 固定位置
visible: true, // 是否显示
showOverflow: true, // 内容过长时显示省略号
className: "custom-class", // 自定义类名
headerClassName: "", // 表头类名
},
// ========== 字典列 ==========
{
field: "status",
title: "状态",
dictType: "sys_status", // 字典类型
displayType: "tag", // 显示方式: 'tag' | 'text'
minWidth: 120,
},
// ========== 格式化列 ==========
{
field: "amount",
title: "金额",
formatter: ({ cellValue, row }) => {
return cellValue ? `${cellValue} 元` : "-";
},
},
// ========== 插槽列 ==========
{
field: "action",
title: "操作",
slots: { default: "action" }, // 使用插槽自定义内容
},
// ========== 使用全局注册的配置 ==========
...getColumnConfig(["checkbox", "序号", "用户名", "状态", "创建日期"]),
]);config/formConfig.ts
typescript
import { defineFormConfig, getFormConfig } from "vue-admin-kit";
export default defineFormConfig(
[
// ========== 输入框 ==========
{
type: "input", // 表单类型
prop: "name", // 字段名(支持嵌套: 'contact.name')
label: "名称", // 标签文本
span: 12, // 栅格占比(1-24)
required: true, // 是否必填
disabled: false, // 是否禁用
readonly: false, // 是否只读
placeholder: "请输入", // 占位文本
maxlength: 100, // 最大长度
showWordLimit: true, // 显示字数统计
clearable: true, // 是否可清空
prefixIcon: "", // 前缀图标
suffixIcon: "", // 后缀图标
defaultValue: "", // 默认值(支持函数)
rules: [
// 验证规则
{ required: true, message: "请输入名称", trigger: "blur" },
{ min: 2, max: 50, message: "长度在 2 到 50 个字符", trigger: "blur" },
{ pattern: /^[a-zA-Z]+$/, message: "只能输入字母", trigger: "blur" },
],
// 动态属性(函数形式)
show: ({ formData }) => formData.type === "1", // 动态显示
required: ({ formData }) => formData.status === "2", // 动态必填
disabled: ({ formData }) => formData.locked, // 动态禁用
},
// ========== 数字输入 ==========
// 注意:min、max、step、precision、controls、controlsPosition 等属性
// 会透传给底层的 Element Plus el-input-number 组件
{
type: "number",
prop: "amount",
label: "金额",
span: 12,
min: 0, // [透传] 最小值
max: 999999, // [透传] 最大值
step: 1, // [透传] 步长
precision: 2, // [透传] 小数位数
controls: true, // [透传] 是否显示控制按钮
controlsPosition: "right", // [透传] 控制按钮位置
},
// ========== 下拉选择 ==========
{
type: "select",
prop: "status",
label: "状态",
span: 12,
dictType: "sys_status", // 字典类型(自动加载选项)
options: [
// 或手动指定选项
{ label: "启用", value: "1" },
{ label: "禁用", value: "0" },
],
multiple: false, // 是否多选
filterable: true, // 是否可搜索
remote: true, // 是否远程搜索
remoteParam: "keyword", // 远程搜索参数名
clearable: true,
collapseTags: true, // 多选时折叠标签
collapseTagsTooltip: true, // 折叠标签显示提示
},
// ========== 单选/多选 ==========
{
type: "radio", // 或 'checkbox'
prop: "gender",
label: "性别",
span: 12,
options: [
{ label: "男", value: "1" },
{ label: "女", value: "0" },
],
// dictType: 'sys_gender', // 或使用字典
},
// ========== 日期选择 ==========
{
type: "date",
prop: "birthday",
label: "生日",
span: 12,
dateType: "date", // 日期类型: 'date' | 'datetime' | 'daterange' | 'datetimerange' | 'month' | 'year'
format: "YYYY-MM-DD", // 显示格式
valueFormat: "YYYY-MM-DD", // 值格式
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
disabledDate: (date) => date > new Date(), // 禁用日期
},
// ========== 时间选择 ==========
{
type: "time",
prop: "sendTime",
label: "发送时间",
span: 12,
format: "HH:mm:ss",
valueFormat: "HH:mm:ss",
},
// ========== 文本域 ==========
// 注意:rows、autosize 等属性会透传给底层的 Element Plus el-input 组件
{
type: "textarea",
prop: "remark",
label: "备注",
span: 24,
rows: 4, // [透传] 行数
autosize: { minRows: 2, maxRows: 6 }, // [透传] 自适应高度
maxlength: 500,
showWordLimit: true,
},
// ========== 分组标题 ==========
{
type: "line", // 分割线/标题
label: "联系人信息",
span: 24,
style: { color: "#f59a23" },
},
// ========== 文件上传 ==========
{
type: "upload", // 普通上传
prop: "fileList",
label: "附件",
span: 24,
accept: ".pdf,.doc,.docx", // 接受的文件类型
multiple: true, // 是否多选
limit: 5, // 最大数量
maxSize: 10, // 最大大小(MB)
},
{
type: "uploadCard", // 卡片式上传(多类型)
prop: "ossIdList",
uploadConfigList: [
{
label: "身份证正面",
required: true,
accept: ".jpg,.png,.jpeg",
bizType: "ID_CARD_FRONT", // 业务类型
multiple: false,
compress: true, // 是否压缩图片
},
{
label: "身份证反面",
required: true,
accept: ".jpg,.png,.jpeg",
bizType: "ID_CARD_BACK",
multiple: false,
},
],
},
// ========== 使用全局注册的配置 ==========
...getFormConfig(["用户名", "手机号", "状态"]),
],
// ========== 表单选项 ==========
{
labelWidth: "120px", // 标签宽度
labelPosition: "right", // 标签位置: 'left' | 'right' | 'top'
size: "default", // 尺寸
addTitle: "新增用户", // 新增弹窗标题
editTitle: "编辑用户", // 编辑弹窗标题(支持模板: '编辑【name】')
drawerWidth: "800px", // 抽屉宽度
dialogWidth: "600px", // 对话框宽度
}
);config/searchConfig.ts
typescript
import { defineSearchConfig, getSearchConfig } from "vue-admin-kit";
export default defineSearchConfig([
// ========== 输入搜索 ==========
{
type: "input",
prop: "name", // 搜索参数名
label: "名称",
placeholder: "请输入名称",
clearable: true,
},
// ========== 下拉搜索 ==========
{
type: "select",
prop: "status",
label: "状态",
dictType: "sys_status", // 字典类型
filterable: true, // 可搜索
clearable: true,
multiple: false, // 是否多选
},
// ========== 远程搜索 ==========
{
type: "select",
prop: "userId",
label: "用户",
dictType: "user_list", // 自定义适配器
filterable: true,
remote: true, // 开启远程搜索
remoteParam: "keyword", // 远程搜索参数名
},
// ========== 日期范围搜索 ==========
{
type: "daterange",
prop: "createTime",
label: "创建时间",
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
valueFormat: "YYYY-MM-DD",
},
// ========== 使用全局注册的配置 ==========
...getSearchConfig(["用户名", "状态"]),
]);config/permissions.ts
typescript
import { definePermissions } from "vue-admin-kit";
export default definePermissions({
add: ["system:user:add"], // 新增权限
edit: ["system:user:edit"], // 编辑权限
delete: ["system:user:remove"], // 删除权限
export: ["system:user:export"], // 导出权限
import: ["system:user:import"], // 导入权限
all: ["system:user:*"], // 所有权限
});useState 完整参数
typescript
const { data, getData, autoIntegrateOperations } = useState({
// ========== 基础配置 ==========
provideName: "mainData", // 数据隔离标识(多实例时使用)
// ========== API 配置 ==========
api: {
list: api.list, // 列表接口
add: api.add, // 新增接口
update: api.update, // 编辑接口
delete: api.del, // 删除接口
detail: api.get, // 详情接口
},
// ========== 初始参数 ==========
params: {
status: "1", // 默认查询参数
pageNum: 1,
pageSize: 10,
},
// ========== 搜索配置 ==========
searchConfig: [], // 搜索表单配置
// ========== 表单配置 ==========
formConfig: {
config: [], // 表单项配置
options: {
// 表单选项
labelWidth: "120px",
addTitle: "新增",
editTitle: "编辑",
drawerWidth: "800px",
},
},
// 注意:formConfig 也支持简写形式(直接传入配置数组),如:formConfig: []
// ========== 列配置 ==========
columnsConfig: [],
// ========== 表格选项 ==========
tableOptions: {
// ---------- 工具栏按钮 ----------
tableOperationConfig: [
{
type: "primary", // 按钮类型: 'primary' | 'success' | 'warning' | 'danger' | 'info'
title: "新增", // 按钮文本
icon: "Plus", // 图标名称
hasPermi: ["add"], // 权限标识
fixed: "right", // 固定位置
dropdown: false, // 是否为下拉菜单
children: [], // 下拉菜单子项
show: true, // 是否显示(支持函数)
show: (data) => data.params.status === "1",
onClick: () => {}, // 点击事件
onClick: async (data) => {
// data 包含: params, tableData, selectedRows 等
},
},
],
// ---------- 操作列按钮 ----------
operateColumns: [
{
type: "primary", // 按钮类型
title: "编辑", // 按钮文本
size: "small", // 按钮尺寸
link: true, // 是否为链接样式
hasPermi: ["edit"], // 权限标识
show: true, // 是否显示(支持函数)
show: (data) => data.params.status === "1",
onClick: (row) => {}, // 点击事件,row 为当前行数据
},
{
title: "更多",
dropdown: true, // 下拉菜单
children: [
{ title: "详情", onClick: (row) => {} },
{ title: "删除", type: "danger", onClick: (row) => {} },
],
},
],
// ---------- 表格事件 ----------
onSelectionChange: (rows) => {}, // 选择变化
onRowClick: (row) => {}, // 行点击
onRowDblclick: (row) => {}, // 行双击
onSortChange: ({ field, order }) => {}, // 排序变化
// ---------- 表格样式 ----------
stripe: true, // 斑马纹
border: true, // 边框
maxHeight: 600, // 最大高度
},
// ========== UI 配置 ==========
ui: {
searchCard: true, // 搜索区域使用卡片
tableCard: true, // 表格区域使用卡片
formItemSize: "default", // 表单项尺寸
},
});配置注册
列配置注册
typescript
// config/vueAdminKit/columnConfigs/columns.ts
import { col, withUnit, registerColumnConfigs } from "vue-admin-kit";
export function setupColumnConfigs() {
registerColumnConfigs([
// col(名称, 配置) - 快捷注册
col("序号", { type: "seq", minWidth: 100 }),
col("checkbox", { type: "checkbox", fixed: "left", width: 70 }),
col("创建日期", { field: "createTime", sortable: true }),
col("状态", {
field: "status",
dictType: "sys_status",
displayType: "tag",
}),
col("金额", { field: "amount", formatter: withUnit("元") }),
]);
}
// 使用: getColumnConfig(['序号', '状态', '创建日期'])表单配置注册
typescript
// config/vueAdminKit/columnConfigs/forms.ts
import { formCol, registerFormConfigs } from "vue-admin-kit";
export function setupFormConfigs() {
registerFormConfigs([
// formCol(名称, 配置) - 快捷注册
formCol("用户名", {
prop: "userName",
type: "input",
required: true,
span: 12,
}),
formCol("状态", {
prop: "status",
type: "select",
dictType: "sys_status",
span: 12,
}),
formCol("手机号", {
prop: "phone",
type: "input",
span: 12,
rules: [
{
pattern: /^1[3-9]\d{9}$/,
message: "请输入正确的手机号",
trigger: "blur",
},
],
}),
// 复杂配置使用数组形式 [名称, 配置]
[
"自定义字段",
{
prop: "custom",
label: "自定义标签",
type: "input",
span: 12,
change: ({ formData, value }) => {
// 值变化回调
},
mounted: ({ formData }) => {
// 挂载回调
},
},
],
]);
}
// 使用: getFormConfig(['用户名', '状态', '手机号'])搜索配置注册
typescript
// config/vueAdminKit/columnConfigs/search.ts
import { searchCol, registerSearchConfigs } from "vue-admin-kit";
export function setupSearchConfigs() {
registerSearchConfigs([
searchCol("用户名", { prop: "userName", type: "input" }),
searchCol("状态", {
prop: "status",
type: "select",
dictType: "sys_status",
}),
searchCol("创建时间", { prop: "createTime", type: "daterange" }),
]);
}
// 使用: getSearchConfig(['用户名', '状态'])自定义字典适配器
typescript
// config/vueAdminKit/dictAdapters.ts
export interface DictAdapterConfig {
api: (...args: any[]) => Promise<any>; // API 接口
params?: (context?: any) => any; // 请求参数(支持函数)
transform: (data: any) => Array<{
// 数据转换
label: string;
value: string;
[key: string]: any;
}>;
}
export const CUSTOM_ADAPTERS: Record<string, DictAdapterConfig> = {
user_list: {
api: getUserList,
params: (pageData) => ({
keyword: pageData?.searchKey || "", // 支持远程搜索
}),
transform: (data) =>
data.map((item: any) => ({
label: item.name,
value: String(item.id),
})),
},
};
export const CUSTOM_DICT_TYPES = {
USER_LIST: "user_list",
} as const;条件显示工具
typescript
import { showWhen, showWhenIn, showAll, showAny } from "vue-admin-kit";
// 单条件
show: showWhen("status", "1"); // status === '1'
show: showWhen("status", "1", "!="); // status !== '1'
// 多值匹配
show: showWhenIn("status", ["1", "2"]); // status in ['1', '2']
// 组合条件
show: showAll(
// AND 条件
showWhen("status", "1"),
showWhen("type", "admin")
);
show: showAny(
// OR 条件
showWhen("role", "admin"),
showWhen("isOwner", true)
);
// 函数形式
show: (data) => data.params.status === "1" && data.row?.type === "admin";PageTemplate 方法
typescript
const pageRef = ref<PageTemplateExposed>();
// 基础操作
pageRef.value?.handleAdd(); // 打开新增弹窗
pageRef.value?.handleAdd(defaultData); // 带默认值新增
pageRef.value?.handleEdit(row); // 打开编辑弹窗
pageRef.value?.handleDelete(row); // 删除
pageRef.value?.handleDetail(row); // 查看详情
pageRef.value?.handleSearch(); // 刷新列表
// 文件操作
pageRef.value?.importFile(importApi, callback); // 导入文件
pageRef.value?.downloadFile(exportApi, fileName); // 导出文件
// 获取数据
pageRef.value?.getSelectedRows(); // 获取选中行
pageRef.value?.getTableData(); // 获取表格数据代码风格
typescript
// ✅ 推荐:使用 defineXxxConfig 获得类型提示
const columnsConfig = defineColumnsConfig([...])
const formConfig = defineFormConfig([...])
// ✅ 推荐:静态配置
const config = defineColumnsConfig([...])
// ❌ 避免:computed 包装静态配置
const config = computed(() => [...])
// useState 配置顺序(推荐)
useState({
provideName, // 1. 数据标识
api, // 2. API
params, // 3. 初始参数
searchConfig, // 4. 搜索
formConfig, // 5. 表单
columnsConfig, // 6. 列
tableOptions, // 7. 表格选项
ui // 8. UI 配置
})属性透传说明
表单控件配置中,部分属性会直接透传给底层的 Element Plus 组件。文档中标注 [透传] 的属性即为此类。
透传属性示例
| 控件类型 | 透传属性 | 底层组件 |
|---|---|---|
number | min、max、step、precision、controls、controlsPosition | el-input-number |
textarea | rows、autosize | el-input |
select | filterable、remote、multiple、collapseTags | el-select |
date | format、valueFormat、disabledDate | el-date-picker |
查找更多属性
如需使用文档中未列出的属性,请参考 Element Plus 官方文档,大部分原生属性都支持透传。
