Skip to content

Hooks

useState

页面状态管理 Hook,用于配置 CRUD 页面。

typescript
import { useState } from 'vue-admin-kit'

useState({
  api: {
    list: (params) => getList(params),
    add: (data) => addItem(data),
    edit: (data) => updateItem(data),
    delete: (id) => deleteItem(id),
    detail: (id) => getDetail(id),
    batchDelete: (ids) => batchDelete(ids),
    export: (params) => exportData(params),
    import: (file) => importData(file)
  },
  searchConfig: [...],
  formConfig: [...],
  columnsConfig: [...],
  tableOptions: {
    tableOperationConfig: [...],  // 工具栏按钮
    operateColumns: [...]          // 行操作按钮
  }
})

useDialog

对话框状态管理 Hook。

typescript
import { useDialog } from "vue-admin-kit";

const { visible, title, openDialog, closeDialog, toggleDialog, setTitle } =
  useDialog({
    title: "新增用户",
    visible: false,
  });

// 打开对话框
openDialog("新增用户");

// 关闭对话框
closeDialog();

// 切换显示状态
toggleDialog();

// 设置标题
setTitle("编辑用户");

多个对话框

typescript
const addDialog = useDialog({ title: "新增" });
const editDialog = useDialog({ title: "编辑" });
const detailDialog = useDialog({ title: "详情" });

// 分别控制
addDialog.openDialog();
editDialog.openDialog("编辑用户");
detailDialog.closeDialog();

在模板中使用

vue
<template>
  <el-dialog v-model="visible" :title="title">
    <!-- 对话框内容 -->
  </el-dialog>
</template>

useDict

字典数据获取 Hook。

typescript
import {
  useDict,
  useDictReactive,
  useDictLabel,
  useDictOptions,
  useDictTagType,
} from "vue-admin-kit";

// 响应式获取字典数据
const { dictData, loaded } = useDict("sys_status");

// 响应式字典(返回 ref)
const statusDict = useDictReactive("sys_status");

// 获取字典标签(响应式)
const statusLabel = useDictLabel("sys_status", "1");

// 获取字典选项列表(用于 Select 组件)
const statusOptions = useDictOptions("sys_status");

// 获取字典标签类型(用于 Tag 组件)
const tagType = useDictTagType("sys_status", "1");

同步方法

typescript
import {
  getDictLabel,
  getDictLabels,
  preloadDicts,
  clearDictCache,
  isDictLoaded,
  areDictsLoaded,
} from "vue-admin-kit";

// 同步获取标签(需确保已加载)
const label = getDictLabel("sys_status", "1");

// 批量获取标签
const labels = getDictLabels("sys_status", ["1", "2"]);

// 预加载字典
await preloadDicts(["sys_status", "sys_yes_no", "sys_user_sex"]);

// 清除字典缓存
clearDictCache("sys_status"); // 清除单个
clearDictCache(); // 清除全部

// 检查字典是否已加载
const loaded = isDictLoaded("sys_status");
const allLoaded = areDictsLoaded(["sys_status", "sys_yes_no"]);

useTableHeight

表格高度管理 Hook。从 v1.0.3 开始,每个 PageTemplate 实例自动创建独立的高度状态,无需手动配置。

提示

一般情况下,你不需要直接使用 useTableHeight,PageTemplate 组件会自动处理表格高度计算。以下内容主要用于了解内部机制或高级自定义场景。

通过 tableOptions 配置 otherHeight(推荐)

从 v1.0.4 开始,推荐通过 useStatetableOptions.otherHeight 配置额外高度偏移:

typescript
useState({
  api: { list: getList },
  tableOptions: {
    // 数值类型
    otherHeight: 40,
    // 或函数类型(支持响应式)
    // otherHeight: () => tabHeight.value,
  },
});

使用场景:页面有额外的 Tab 栏、统计卡片等固定高度元素时使用。

tableCardPadding 配置

tableCardPadding 用于指定表格区域 el-card 的 padding 高度,当 ui.tableCard: true 时会自动减去此值。

配置优先级:页面级配置 > 全局配置 > 默认值(8px)

typescript
// 全局配置(所有页面生效)
setupPageTemplate({
  ui: {
    tableCardPadding: 10, // 自定义 el-card padding 高度
  },
});

// 页面级配置(覆盖全局配置)
useState({
  ui: {
    tableCard: true,
    tableCardPadding: 12, // 仅当前页面生效
  },
});

注意

v1.0.4 移除了 Table 组件的 otherHeight prop,请使用 tableOptions.otherHeight 替代。

返回值

typescript
interface TableHeightState {
  tableHeight: Ref<number>; // 表格高度
  queryFormRef: Ref<HTMLElement | null>; // 搜索表单 DOM 引用
  showSearch: Ref<boolean>; // 是否显示搜索
  isHeightReady: Ref<boolean>; // 高度是否已计算完成
  calculateTableHeight: () => Promise<void>; // 手动触发高度计算
  debouncedCalculateHeight: (delay?: number) => void; // 防抖计算高度
  preCalculateHeight: (extraFormHeight: number) => void; // 预计算高度
  setActive: (active: boolean) => void; // 设置激活状态
}

高级用法

如果需要在自定义组件中访问表格高度状态,可以通过 inject 获取:

typescript
import { inject } from "vue";
import type { TableHeightState } from "vue-admin-kit";

// 在 PageTemplate 的子组件中获取高度状态
const heightState = inject<TableHeightState>("tableHeightState");

// 手动触发高度计算
await heightState?.calculateTableHeight();

// 防抖计算(适用于频繁触发的场景)
heightState?.debouncedCalculateHeight(200);

// 预计算高度(展开/收起搜索前调用,避免闪烁)
heightState?.preCalculateHeight(-64); // 收起时减少高度
heightState?.preCalculateHeight(64); // 展开时增加高度

工作原理

PageTemplate 内部会自动调用 useTableHeight() 创建状态,并通过 provide('tableHeightState', heightState) 传递给 Table 组件。Table 组件通过 inject 获取状态,实现高度同步。

typescript
// PageTemplate 内部实现
const heightState = useTableHeight({
  otherHeight: () => pageData.tableOptions?.otherHeight ?? 0,
  tableCardPadding: () => computedTableCardPadding.value,
});
provide("tableHeightState", heightState);

// Table 内部实现
const heightState = inject<TableHeightState>("tableHeightState");

提示

从 v1.0.3 开始,不再需要手动配置 instanceKey,状态隔离是自动的。

useTableHeightEmitter

表格高度事件发射器。

typescript
import { useTableHeightEmitter } from "vue-admin-kit";

// 在组件中使用
const emit = defineEmits(["setTableHeight"]);
const { emitSetTableHeight } = useTableHeightEmitter(emit);

// 手动触发高度更新
emitSetTableHeight();

useConfirmAction

确认操作 Hook。

typescript
import { useConfirmAction } from "vue-admin-kit";

const { confirmAction } = useConfirmAction();

// 基础用法
await confirmAction("确定删除吗?", async () => {
  await deleteApi(id);
});

// 自定义成功消息
await confirmAction("确定提交吗?", submitFn, "提交成功");

// 带回调判断
const success = await confirmAction("确定吗?", actionFn);
if (success) {
  refreshList();
}

直接函数调用

typescript
import { confirmAction } from "vue-admin-kit";

// 不需要 hook,直接调用
await confirmAction("确定删除吗?", deleteFn);

创建状态切换函数

typescript
import { createStatusToggle } from 'vue-admin-kit'

// 创建状态切换函数(上架/下架场景)
const toggleStatus = createStatusToggle(updateStatusApi, getData)

// 在操作列中使用
{
  title: '下架',
  onClick: (row) => toggleStatus(row.id, '0', '确定下架该商品吗?')
}

usePackageAppConfig

用户偏好设置 Hook,管理持久化到 localStorage 的用户配置。

typescript
import { usePackageAppConfig } from "vue-admin-kit";

const appConfig = usePackageAppConfig();

// 获取/设置组件尺寸
console.log(appConfig.size.value); // 'default'
appConfig.size.value = "small";

// 获取/设置表格对齐方式
console.log(appConfig.tableAlign.value); // 'center'
appConfig.tableAlign.value = "left";

// 获取/设置表格大小
console.log(appConfig.tableSize.value); // 'medium'
appConfig.tableSize.value = "small";

// 获取/设置表格宽度(非持久化)
appConfig.tableWidth.value = 1200;

返回值类型

typescript
interface AppConfigStore {
  size: Ref<"large" | "default" | "small">; // 组件尺寸(持久化)
  tableAlign: Ref<"left" | "center" | "right">; // 表格对齐方式(持久化)
  tableSize: Ref<"medium" | "small" | "mini">; // 表格大小(持久化)
  tableWidth: Ref<number>; // 表格宽度(非持久化)
}

使用场景

typescript
// 在布局组件中使用
const appConfig = usePackageAppConfig();

// 响应式绑定到组件
<el-table :size="appConfig.tableSize.value" :align="appConfig.tableAlign.value">

提示

此 Hook 用于用户偏好设置,数据持久化到 localStorage。如需获取全局配置(通过 setupPageTemplate 设置),请使用 usePageTemplateConfig

usePageTemplateConfig

获取全局配置 Hook,返回通过 setupPageTemplate 设置的配置。

typescript
import { usePageTemplateConfig } from "vue-admin-kit";

const config = usePageTemplateConfig();

// 访问 UI 配置
const size = config.ui.formItemSize;
const tableCardPadding = config.ui.tableCardPadding;

// 访问依赖配置
const dictLoader = config.dependencies.dictLoader;
const oss = config.dependencies.oss;
const calculateHeight = config.dependencies.calculateHeight;

// 访问字典配置
const preload = config.dict.preload;
const commonTypes = config.dict.commonTypes;
const cacheTime = config.dict.cacheTime;

返回值类型

typescript
interface InternalConfig {
  dict: {
    preload: boolean;
    cacheTime: number;
    timeout: number;
    retryCount: number;
    commonTypes: string[];
  };
  dependencies: {
    oss?: OssApi;
    permissionChecker?: (value?: string[]) => boolean;
    dictLoader?: (
      dictType: string,
      options: DictLoadOptions
    ) => Promise<DictLoadResult>;
    calculateHeight?: (formHeight: number, otherHeight: number) => number;
    calculateWidth?: (options?: {
      waitForVisible?: boolean;
    }) => Promise<number> | number;
    customAdapters?: Record<string, DictAdapterConfig>;
  };
  ui: {
    formItemSize: FormItemSizeType | (() => FormItemSizeType);
    tableCardPadding: number; // 表格区域 el-card 的 padding 高度
  };
}

使用场景

typescript
// 在自定义组件中获取 OSS 配置
const config = usePageTemplateConfig();
const uploadFile = async (file: File) => {
  if (config.dependencies.oss) {
    return await config.dependencies.oss.uploadOSS(file);
  }
  throw new Error("OSS 未配置");
};

// 获取响应式表单尺寸
const getFormSize = () => {
  const { formItemSize } = config.ui;
  return typeof formItemSize === "function" ? formItemSize() : formItemSize;
};

Released under the MIT License.