Skip to content

最佳实践

项目组织

推荐目录结构

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 组件。文档中标注 [透传] 的属性即为此类。

透传属性示例

控件类型透传属性底层组件
numberminmaxstepprecisioncontrolscontrolsPositionel-input-number
textarearowsautosizeel-input
selectfilterableremotemultiplecollapseTagsel-select
dateformatvalueFormatdisabledDateel-date-picker

查找更多属性

如需使用文档中未列出的属性,请参考 Element Plus 官方文档,大部分原生属性都支持透传。

Released under the MIT License.