npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xinlian-frontend/lui

v0.0.1-beta.17

Published

组件库

Readme

L-UI 组件库文档

基于 Ant Design Vue 封装的业务组件库,提供表单、表格、抽屉、弹窗等常用业务组件。

组件总览

| 组件 | 名称 | 说明 | | ------------------------------------- | ------------ | ---------------------------------------------- | | LButton | 按钮 | 基于 AButton 的简单封装 | | LPageTable | 分页表格 | 集成筛选、分页、列设置、全屏等功能的高级表格 | | LModal | 弹窗 | 支持拖拽的模态框 | | LDrawer | 抽屉 | 可全屏、刷新的抽屉组件 | | LFilterPanel | 筛选面板 | 表单筛选组件,支持多种筛选项类型 | | LFormFooter | 表单底部栏 | 固定底部的操作按钮栏 | | LFormSubmitPage | 表单提交页 | 表单提交页通用外壳,支持卡片/分区两种布局 | | LFormSectionPage | 分区表单页 | 固定为分区样式的表单提交页 | | LSectionBlock | 区块容器 | 区块标题+内容的通用容器 | | LDetailLayout | 详情布局 | 详情页布局,含描述信息和 Tab 切换 | | LInfoLayout | 信息布局 | 滚动同步 Tab 锚点的信息展示布局 | | LFixedFooter | 固定底部 | 固定在页面底部的插槽容器 | | LSecondBar | 二级标签栏 | 顶部二级 Tab 切换栏 | | LPageNotFound | 404 页面 | 404 错误页面 | | LApprovalSteps | 审批流程 | 审批流程时间线展示组件 | | LRoleTree | 角色菜单树 | 带复选框的菜单树形结构 | | LSignStatusFlow | 签署状态流程 | 签署流程状态展示 | | LUploadFile | 文件上传 | 文件上传组件,支持附件上传和预览 | | LUploadImage | 图片上传 | 图片/视频上传组件,支持预览 | | LFilePreview | 文件预览 | 支持图片、PDF、Word、Excel、视频等多种文件预览 |


LButton

介绍

基于 Ant Design Vue AButton 的简单封装。

基本用法

<LButton type="primary">主要按钮</LButton>

Props

| 参数 | 说明 | 类型 | 默认值 | | ---- | -------- | ------------ | ----------- | | type | 按钮类型 | ButtonType | 'default' |

ButtonType 类型

type ButtonType =
  | 'primary' // 主要按钮
  | 'secondary' // 次要按钮
  | 'tertiary' // 幽灵按钮
  | 'ghost' // 幽灵按钮
  | 'link' // 链接按钮
  | 'text' // 文本按钮
  | 'icon' // 图标按钮
  | 'default' // 默认按钮

其他属性继承自 Ant Design Vue AButton


LPageTable

介绍

基于 Ant Design Vue Table 封装的高级表格组件,集成了筛选、分页、列设置、全屏等功能,适用于数据展示和管理场景。

基础用法

<script setup lang="ts">
import { ref } from 'vue'
import {
  type LFilterPanelItem,
  LPageTable,
  type LPageTableColumn,
  type LPageTableRefresh,
  type LPageType,
} from '@xinlian-frontend/lui'

const tableRef = ref<LPageTableRef>()
const data = ref<any[]>([])
const pageInfo = ref<LPageType>({ total: 0, pageNum: 1, pageSize: 10 })
const condition = ref<Record<string,any>>({})

const columns = ref<<LPageTableColumn[]>>([
  { title: '姓名', dataIndex: 'name', width: 120 },
  { title: '年龄', dataIndex: 'age', width: 80 },
  { title: '创建时间', dataIndex: 'createTime', formatType: 'DateTime', width: 180 },
  { title: '操作', dataIndex: 'options', fixed: 'right' },
])

const filterItems = ref<LFilterPanelItem[]>([
  { key: 'name', label: '姓名', type: 'input' },
  {
    key: 'status',
    label: '状态',
    type: 'select',
    options: [
      { label: '全部', value: '' },
      { label: '启用', value: '1' },
    ],
  },
])

const refresh: LPageTableRefresh = async done => {
  try {
    await mockApi({ ...condition.value, ...pageInfo.value })
  } finally {
    done()
  }
}
</script>

<template>
  <LPageTable
    ref="tableRef"
    v-model:page="pageInfo"
    v-model:condition="condition"
    v-model:columns="columns"
    :data="data"
    :filter-items="filterItems"
    @refresh="refresh"
  >
    <template #action>
      <a-button type="primary" @click="addRef?.open">添加</a-button>
    </template>
    <template #name="{ record }">
      <a-button type="link" @click="detailRef?.open()">{{ record.name }}</a-button>
    </template>
    <template #options>
      <a-button type="link">删除</a-button>
    </template>
    <template #name-header>
      {{ '姓名(自定义表头)' }}
    </template>
    <template #filter-age>
      {{ '自定义组件' }}
    </template>
  </LPageTable>
</template>

Props

| 参数 | 说明 | 类型 | 默认值 | | ----------------- | ------------------ | ----------------------- | ------- | | data | 表格数据 | Record<string, any>[] | [] | | columns | 列配置 | LPageTableColumn[] | [] | | filterItems | 筛选项配置 | LFilterPanelItem[] | [] | | autoSearch | 是否自动发起搜索 | boolean | true | | showFilter | 是否显示顶部筛选 | boolean | true | | showRefresh | 是否显示刷新按钮 | boolean | true | | showAction | 是否显示顶部操作列 | boolean | true | | showRadio | 是否显示单选 | boolean | false | | showSelection | 是否显示多选 | boolean | false | | showPage | 是否显示分页 | boolean | true | | showSetting | 是否显示列设置 | boolean | true | | radioSelected | 单选选中项 | number \| string | - | | selectionSelected | 多选选中项 | (number \| string)[] | [] | | condition | 筛选条件 | Record<string, any> | {} | | page | 分页信息 | LPageType | 见下文 | | refreshLoading | 刷新加载状态 | boolean | false | | card | 是否卡片布局 | boolean | true | | bordered | 是否显示边框 | boolean | true | | rowKey | 行标识字段 | string | 'id' |

LPageType 默认值

{
  total: 0,
  pageSize: 10,
  pageNum: 1,
}

Events

| 事件名 | 说明 | 参数 | | ---------------- | ---------------------------------------------- | ------------------------------------------ | | refresh | 刷新数据事件,参数 done 需在数据加载完成后调用 | (done: Done) => void | | update:page | 分页变化事件 | (page: LPageType) => void | | update:condition | 筛选条件变化事件 | (condition: Record<string, any>) => void | | update:sortInfo | 排序信息变化事件 | (sortInfo: LTableSortInfo) => void | | update:columns | 列配置变化事件 | (columns: LPageTableColumn[]) => void |

Slots

| 插槽名 | 说明 | | ------------------ | ----------------------------------------- | | action | 顶部操作区域 | | filter-{key} | 自定义筛选项,key 为 filterItems 中的 key | | {dataIndex} | 自定义列内容 | | {dataIndex}-header | 自定义列头 | | expandedRowRender | 展开行内容 | | expandColumnTitle | 展开列标题 | | summary | 表格底部汇总 |

方法(通过 ref 调用)

| 方法名 | 说明 | | ----------------- | ---------------- | | refresh() | 刷新表格数据 | | getRootTableRef() | 获取原生表格实例 |

类型定义

LPageTableColumn

interface LPageTableColumn<T> extends TableColumnProps {
  dataIndex: T extends object ? keyof T : string
  visible?: boolean // 是否显示列
  promission?: boolean // 权限控制
  formatType?: 'Date' | 'DateTime' | 'Money' // 格式化类型
  require?: boolean // 是否必填(显示红色 *)
}

LFilterPanelItem

interface LFilterPanelItem {
  key: string
  label: string
  type?: 'input' | 'select' | 'daterange' | 'datetimerange'
  options?: { label: string; value: any; disabled?: boolean }[]
  placeholder?: string
  startPlaceholder?: string
  endPlaceholder?: string
  multiple?: boolean
  hide?: boolean
  change?: (...args: any[]) => void
}

自定义列渲染示例

<LPageTable :data="data" :columns="columns">
  <!-- 自定义状态列 -->
  <template #status="{ record }">
    <a-tag :color="record.status === 1 ? 'green' : 'red'">
      {{ record.status === 1 ? '启用' : '禁用' }}
    </a-tag>
  </template>

  <!-- 自定义操作列 -->
  <template #operation="{ record }">
    <a-space>
      <a-button type="link" size="small" @click="handleEdit(record)">编辑</a-button>
      <a-button type="link" size="small" danger @click="handleDelete(record)">删除</a-button>
    </a-space>
  </template>
</LPageTable>

LModal

介绍

基于 Ant Design Vue Modal 封装,支持拖拽移动的模态框组件。

基础用法

<template>
  <LModal v-model:open="visible" title="弹窗标题">
    <p>弹窗内容</p>
    <template #footer>
      <a-button @click="visible = false">取消</a-button>
      <a-button type="primary" @click="handleOk">确定</a-button>
    </template>
  </LModal>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(false)
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | -------- | --------- | ------- | | modelValue (v-model) | 是否显示 | boolean | false | | title | 弹窗标题 | string | - |

Slots

| 插槽名 | 说明 | | ------- | -------------- | | default | 弹窗内容 | | title | 自定义标题区域 | | footer | 自定义底部 |

其他属性继承自 Ant Design Vue AModal


LDrawer

介绍

基于 Ant Design Vue Drawer 封装的抽屉组件,支持全屏切换、刷新、遮罩控制等功能。

基础用法

<template>
  <LDrawer
    v-model:open="visible"
    title="抽屉标题"
    :width="600"
    placement="right"
    @close="handleClose"
  >
    <p>抽屉内容</p>
    <template #footer>
      <a-space>
        <a-button @click="visible = false">取消</a-button>
        <a-button type="primary" @click="handleConfirm">确定</a-button>
      </a-space>
    </template>
  </LDrawer>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(false)
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ----------- | ---------------------------- | ---------------------------------------- | --------- | | mask | 是否显示遮罩 | boolean | true | | placement | 抽屉方向 | 'top' \| 'right' \| 'bottom' \| 'left' | 'right' | | width | 抽屉宽度 | string \| number | '75%' | | title | 抽屉标题 | string | - | | loading | 加载状态,显示 Spin | boolean | false | | showRefresh | 是否显示刷新按钮 | boolean | false | | page | 是否启用分页模式(预留功能) | boolean | false |

Events

| 事件名 | 说明 | | ------- | ------------------- | | prev | 上一步(page 模式) | | next | 下一步(page 模式) | | refresh | 点击刷新按钮 | | close | 关闭抽屉 |

Slots

| 插槽名 | 说明 | | ----------- | ------------------ | | default | 抽屉内容 | | footer | 自定义底部 | | extra | 标题栏右侧扩展区域 | | title | 自定义标题 | | title-extra | 标题后方扩展 |

方法(通过 ref 调用)

| 方法名 | 说明 | | ------- | ------------------------ | | open() | 打开抽屉 | | close() | 关闭抽屉 | | visable | 抽屉可见性状态(响应式) |


LFilterPanel

介绍

表单筛选面板组件,支持 input、select、日期范围等多种筛选项类型,自动处理查询/重置逻辑。

基础用法

<template>
  <LFilterPanel
    v-model="condition"
    :filter-items="filterItems"
    label-width="80px"
    @search="handleSearch"
    @reset="handleReset"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const condition = ref({})
const filterItems = [
  { key: 'name', label: '姓名', type: 'input', placeholder: '请输入姓名' },
  {
    key: 'status',
    label: '状态',
    type: 'select',
    options: [
      { label: '全部', value: '' },
      { label: '启用', value: '1' },
    ],
  },
  {
    key: 'date',
    label: '日期',
    type: 'daterange',
    startPlaceholder: '开始日期',
    endPlaceholder: '结束日期',
  },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | ---------------- | --------------------- | -------- | | modelValue (v-model) | 筛选条件双向绑定 | Record<string, any> | {} | | filterItems | 筛选项配置数组 | LFilterPanelItem[] | [] | | labelWidth | 表单标签宽度 | number \| string | '80px' | | collapsible | 是否可折叠 | boolean | false | | collapsedRows | 折叠时显示的行数 | number | 1 | | searchText | 查询按钮文本 | string | '查询' | | resetText | 重置按钮文本 | string | '重置' | | expandText | 展开文本 | string | '展开' | | collapseText | 收起文本 | string | '收起' | | card | 是否显示卡片背景 | boolean | true |

LFilterPanelItem

| 字段 | 说明 | 类型 | | ---------------- | -------------------- | ------------------------------------------------------- | | key | 字段标识 | string | | label | 字段标签 | string | | type | 筛选项类型 | 'input' \| 'select' \| 'daterange' \| 'datetimerange' | | options | select 选项列表 | { label: string; value: any; disabled?: boolean }[] | | placeholder | 输入框占位文本 | string | | startPlaceholder | 日期范围开始占位文本 | string | | endPlaceholder | 日期范围结束占位文本 | string | | multiple | select 是否多选 | boolean | | hide | 是否隐藏该筛选项 | boolean | | change | 值变化时的回调 | (...args: any[]) => void |

Events

| 事件名 | 说明 | | ----------------- | ----------------------------- | | update:modelValue | 筛选条件变化 | | search | 点击查询按钮 | | reset | 点击重置按钮 | | toggle | 折叠/展开变化,参数为展开状态 |


LFormFooter

介绍

固定在页面底部的操作按钮栏组件,支持自定义按钮配置。

基础用法

<template>
  <LFormFooter
    :loading="submitLoading"
    @close="handleClose"
    @save="handleSave"
    @submit="handleSubmit"
  />
</template>

<script setup lang="ts">
const submitLoading = ref(false)
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ---------- | ------------------ | -------------------- | -------- | | buttons | 自定义按钮配置列表 | FormFooterButton[] | [] | | showClose | 是否显示关闭按钮 | boolean | true | | showSave | 是否显示保存按钮 | boolean | true | | showSubmit | 是否显示提交按钮 | boolean | true | | loading | 全局 loading 状态 | boolean | false | | closeText | 关闭按钮文本 | string | '关闭' | | saveText | 保存按钮文本 | string | '保存' | | submitText | 提交按钮文本 | string | '提交' |

FormFooterButton

interface FormFooterButton {
  text: string // 按钮文本
  type?: 'default' | 'primary' | 'dashed' | 'link' | 'text' // 按钮类型
  loading?: boolean // loading 状态
  disabled?: boolean // 是否禁用
  onClick?: () => void | Promise<void> // 点击事件
}

Events

| 事件名 | 说明 | | -------- | ------------ | | onClose | 点击关闭按钮 | | onSave | 点击保存按钮 | | onSubmit | 点击提交按钮 |


LFormSubmitPage

介绍

表单提交页通用外壳组件,统一页面容器、表单布局与底部操作栏。支持 卡片 (card)分区 (section) 两种布局形态,可通过 props 切换或用户手动切换(自动同步到 localStorage)。

基础用法

<template>
  <LFormSubmitPage
    ref="pageRef"
    :model="formData"
    :rules="rules"
    :show-save="true"
    @cancel="handleCancel"
    @save="handleSave"
    @submit="handleSubmit"
  >
    <a-card title="基础信息">
      <a-form-item label="名称" name="name">
        <a-input v-model:value="formData.name" />
      </a-form-item>
    </a-card>
  </LFormSubmitPage>
</template>

<script setup lang="ts">
import { message } from 'ant-design-vue'
import { reactive, ref } from 'vue'

const pageRef = ref()
const formData = reactive({ name: '' })
const rules = { name: [{ required: true, message: '请输入名称', trigger: 'blur' }] }

async function handleSubmit() {
  await pageRef.value?.formRef?.validate()
  message.success('提交成功')
}
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ---------------- | -------------------- | ---------------------------------------- | -------------- | | model | 表单绑定数据 | Record<string, unknown> | - | | rules | 校验规则 | Record<string, unknown> | - | | layout | 表单布局 | 'horizontal' \| 'vertical' \| 'inline' | 'horizontal' | | variant | 展示形态 | 'card' \| 'section' | 'section' | | showLayoutSwitch | 是否显示布局切换图标 | boolean | true | | sections | 卡片区块配置 | FormSubmitPageSection[] | - | | showSave | 是否显示保存按钮 | boolean | true | | showSubmit | 是否显示提交按钮 | boolean | true | | submitLoading | 提交按钮 loading | boolean | false | | saveLoading | 保存按钮 loading | boolean | false | | cancelText | 取消按钮文案 | string | '取消' | | saveText | 保存按钮文案 | string | '保存' | | submitText | 提交按钮文案 | string | '提交' |

FormSubmitPageSection

interface FormSubmitPageSection {
  key: string // 区块唯一标识
  title: string // 区块标题
  desc?: string // 区块描述
}

Events

| 事件名 | 说明 | | -------------- | ------------ | | cancel | 点击取消按钮 | | save | 点击保存按钮 | | submit | 点击提交按钮 | | update:variant | 布局形态变化 |

Slots

| 插槽名 | 说明 | | ------------ | ------------------------------- | | default | 表单内容区 | | card-{key} | 按 section 配置渲染卡片区块内容 | | footer | 整块自定义底部栏 | | footer-left | 底部左侧扩展 | | footer-right | 底部右侧扩展 |

Expose

| 名称 | 类型 | 说明 | | ------- | --------- | -------------------------------------------------------- | | formRef | Form 实例 | ant-design-vue Form 实例,可调用 validate/resetFields 等 |

多区块使用示例

<template>
  <LFormSubmitPage
    ref="pageRef"
    :model="formData"
    :sections="[
      { key: 'basic', title: '基础信息' },
      { key: 'detail', title: '详细信息' },
    ]"
  >
    <template #card-basic>
      <a-form-item label="名称" name="name">
        <a-input v-model:value="formData.name" />
      </a-form-item>
    </template>
    <template #card-detail>
      <a-form-item label="描述" name="desc">
        <a-textarea v-model:value="formData.desc" />
      </a-form-item>
    </template>
  </LFormSubmitPage>
</template>

布局切换说明

开启 showLayoutSwitch 后,页面右上角会显示卡片/分区切换图标。切换结果会自动写入 localStorage(key: l-form-submit-page-layout-variant),所有开启此功能的页面会共用该状态,实现跨页面无缝同步。


LFormSectionPage

介绍

固定为 分区 (section) 形态的表单提交页,用法与 LFormSubmitPage 完全一致,仅固定为分区布局。

<LFormSectionPage :model="formData" :rules="rules">
  <a-form-item label="名称" name="name">
    <a-input v-model:value="formData.name" />
  </a-form-item>
</LFormSectionPage>

所有 Props、Slots、Events、Expose 与 LFormSubmitPage 保持一致。


LSectionBlock

介绍

区块标题+内容的通用容器组件,仅负责结构复用,样式由使用方工程提供。

基础用法

<template>
  <LSectionBlock title="基本信息">
    <template #header-extra>
      <a-button type="link">编辑</a-button>
    </template>
    <p>区块内容</p>
  </LSectionBlock>
</template>

Props

| 参数 | 说明 | 类型 | 默认值 | | ---------- | ---------------- | ----------- | ----------- | | title | 标题文案 | string | '' | | blockClass | 最外层额外 class | ClassType | undefined | | showHeader | 是否显示头部 | boolean | true | | loading | 加载状态 | boolean | false |

Slots

| 插槽名 | 说明 | | ------------ | ---------------- | | default | 区块内容 | | title | 自定义标题 | | header-extra | 标题右侧扩展区域 |


LDetailLayout

介绍

详情页布局组件,包含顶部描述信息区域和下方 Tab 切换区域,内置 FixedFooter 固定底部栏。

基础用法

<template>
  <LDetailLayout
    title="详情"
    :descriptions="descriptions"
    :tabs="tabs"
    @tab-change="handleTabChange"
  >
    <template #extra>
      <a-space>
        <a-button>编辑</a-button>
      </a-space>
    </template>

    <template #tab-basic>
      <p>基本信息内容</p>
    </template>
    <template #tab-record>
      <p>记录信息内容</p>
    </template>

    <template #footer>
      <a-button @click="goBack">返回</a-button>
      <a-button type="primary">提交</a-button>
    </template>
  </LDetailLayout>
</template>

<script setup lang="ts">
const descriptions = [
  { label: '姓名', value: '张三' },
  { label: '状态', value: '启用' },
]
const tabs = [
  { key: 'basic', label: '基本信息' },
  { key: 'record', label: '记录信息' },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ---------------- | -------------- | -------------------------- | ------------- | | title | 页面标题 | string | - | | descriptions | 顶部描述项配置 | LDetailDescriptionItem[] | [] | | headerColumn | 描述信息列数 | number | 3 | | tabs | Tab 配置列表 | LDetailTabItem[] | [] | | defaultActiveKey | 默认激活的 Tab | string | '' | | tabSize | Tab 尺寸 | 'small' \| 'default' | 'small' | | loading | 加载状态 | boolean | false | | loadingTip | 加载提示文本 | string | '加载中...' |

LDetailDescriptionItem

interface LDetailDescriptionItem {
  label: string // 标签
  value: string | number | undefined | null // 值
  span?: number // 跨列数
}

LDetailTabItem

interface LDetailTabItem {
  key: string // Tab 唯一标识
  label: string // Tab 显示文本
}

Events

| 事件名 | 说明 | 参数 | | --------- | ------------ | ------------- | | tabChange | Tab 切换事件 | key: string |

Slots

| 插槽名 | 说明 | | ------------------- | ----------------------------- | | extra | 右上角扩展区域 | | description-{label} | 自定义描述项渲染,参数为 item | | tab-{key} | Tab 内容区 | | footer | 固定底部栏内容 |


LInfoLayout

介绍

信息展示布局组件,左侧为可滚动的内容区,右侧为固定 Tab 导航,支持滚动时自动高亮对应 Tab。

基础用法

<template>
  <LInfoLayout :items="items" :show-menu="true">
    <template #base>
      <p>基础信息内容...</p>
    </template>
    <template #detail>
      <p>详细信息内容...</p>
    </template>
  </LInfoLayout>
</template>

<script setup lang="ts">
const items = [
  { label: '基础信息', value: 'base', show: true },
  { label: '详细信息', value: 'detail', show: true },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------- | ---------------------- | -------------------- | ------ | | items | 导航项配置(双向绑定) | LInfoLayoutItems[] | [] | | showMenu | 是否显示右侧 Tab 导航 | boolean | true |

LInfoLayoutItems

interface LInfoLayoutItems {
  label: string // 导航标签
  value: string // 导航值(对应插槽名)
  show: boolean // 是否显示该项
  hide?: boolean // 是否隐藏
}

Events

| 事件名 | 说明 | | ------------ | -------------- | | update:items | items 变化事件 |

Slots

| 插槽名 | 说明 | | ------------- | ------------------ | | {value} | 各导航项对应内容 | | title-{value} | 各导航项自定义标题 | | footer | 底部内容 |


LFixedFooter

介绍

固定在页面底部的插槽容器,通过 teleport 挂载到指定容器中,适用于详情页底部操作栏。

基础用法

<template>
  <LFixedFooter>
    <template #footer>
      <a-button @click="goBack">返回</a-button>
      <a-button type="primary">提交</a-button>
    </template>
  </LFixedFooter>
</template>

组件通过 teleport 将内容挂载到 #smartAdminMain 容器中,配合 LDetailLayout 等布局组件使用效果更佳。


LSecondBar

介绍

顶部二级 Tab 切换栏组件,适用于页面顶部的分类导航。

基础用法

<template>
  <LSecondBar v-model="activeTab" :tabs="tabs" @change="handleChange" />
</template>

<script setup lang="ts">
const activeTab = ref('tab1')
const tabs = [
  { label: 'Tab 1', value: 'tab1' },
  { label: 'Tab 2', value: 'tab2' },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | ------------ | ------------------------------------ | ------ | | modelValue (v-model) | 当前选中值 | string | - | | tabs | Tab 配置列表 | { label: string; value: string }[] | [] |

Events

| 事件名 | 说明 | 参数 | | ----------------- | ---------- | --------------- | | update:modelValue | 值变化事件 | value: string | | change | 切换事件 | value: string |


LPageNotFound

介绍

404 错误页面组件,点击按钮返回首页。

基础用法

<LPageNotFound />

LApprovalSteps

介绍

审批流程时间线展示组件,以树形结构展示父流程节点和子节点审批记录,支持文件附件预览。

基础用法

<template>
  <LApprovalSteps :nodes="flowData" />
</template>

<script setup lang="ts">
import type { LFlowData } from '@xinlian-frontend/lui'

const flowData: LFlowData[] = [
  {
    nodeName: '审批1',
    enterpriseName: '企业A',
    nodeStatus: 'PASS',
    subInstRecordList: [
      {
        actualUsers: [
          {
            assignee: { name: '张三' },
            result: 1, // 1=同意
            createTime: '2024-01-01 10:00:00',
          },
        ],
      },
    ],
  },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ----- | -------------- | ------------- | ------ | | nodes | 父流程节点列表 | LFlowData[] | [] |

LFlowData

interface LFlowData {
  approvalRole?: number // 审批身份
  approvalRoleName?: string // 审批身份名称
  createTime?: string // 创建时间
  enterpriseId?: number // 企业id
  enterpriseName?: string // 企业名称
  id?: number // 主键id
  nodeName?: string // 节点名
  nodeStatus?: string // 节点状态
  nodeStatusDesc?: string // 节点状态描述
  remark?: string // 备注
  subInstId?: string // 子流程实例id
  subInstRecordList?: FlowInstRecordVo[] // 子流程实例审批记录
  updateTime?: string // 更新时间
}

节点状态说明

| 状态值 | 说明 | | --------- | ------ | | PASS | 已通过 | | RUNNING | 进行中 | | PENDING | 待审批 | | REFUSE | 驳回 | | REVOKED | 已撤回 | | DELETED | 已删除 |


LRoleTree

介绍

带复选框的角色菜单树形结构组件,支持多级菜单的勾选联动(向上向下级联),自动过滤按钮类型节点。

基础用法

<template>
  <LRoleTree v-model="selectedMenus" :menu="menuTree" @update:model-value="handleChange" />
</template>

<script setup lang="ts">
import type { LMenuTreeOption } from '@xinlian-frontend/lui'

const selectedMenus = ref<Array<string | number>>([])

const menuTree: LMenuTreeOption[] = [
  {
    id: 1,
    label: '系统管理',
    menuName: '系统管理',
    parentId: 0,
    weight: 1,
    menuType: 'M',
    children: [
      { id: 2, label: '用户管理', menuName: '用户管理', parentId: 1, weight: 1, menuType: 'C' },
      { id: 3, label: '角色管理', menuName: '角色管理', parentId: 1, weight: 2, menuType: 'C' },
    ],
  },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | -------------- | ------------------------- | ------ | | menu | 菜单树形数据 | LMenuTreeOption[] | [] | | modelValue (v-model) | 选中值 | Array<string \| number> | [] | | showCheckbox | 是否显示复选框 | boolean | true |

LMenuTreeOption

interface LMenuTreeOption {
  id: string | number // 唯一标识
  label: string // 显示文本
  menuName: string // 菜单名称
  parentId: string | number // 父节点id
  weight: number // 权重
  menuType: 'M' | 'C' | 'F' // M=目录 C=菜单 F=按钮
  children?: LMenuTreeOption[] // 子节点
}

Events

| 事件名 | 说明 | 参数 | | ----------------- | --------------------------------------------- | ------------------------- | | update:modelValue | 选中值变化,包含全选节点和半选父节点的 id | Array<string \| number> |

方法(通过 ref 调用)

| 方法名 | 说明 | | ------------- | ------------ | | expandAll() | 展开全部节点 | | collapseAll() | 收起全部节点 |

节点联动规则

  • 勾选非按钮类型节点:自动勾选其所有后代非按钮类型节点
  • 取消勾选非按钮类型节点:自动取消勾选其所有后代非按钮类型节点
  • 按钮类型节点 (menuType: 'F'):不参与级联计算

LSignStatusFlow

介绍

签署状态流程展示组件,以列表形式展示签署人及其签署状态。

基础用法

<template>
  <LSignStatusFlow :items="signList" />
</template>

<script setup lang="ts">
const signList = [
  { id: 1, psnName: '张三', orgName: '公司A', signResult: 2, operateTime: '2024-01-01 10:00' },
  { id: 2, psnName: '李四', orgName: '公司B', signResult: 1, operateTime: '' },
]
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | ----- | ------------ | ----------------------- | ------ | | items | 签署记录列表 | LSignStatusFlowItem[] | [] |

LSignStatusFlowItem

interface LSignStatusFlowItem {
  id?: string | number // 唯一标识
  psnName?: string // 签署人姓名
  orgName?: string // 组织名称
  signResult?: string | number // 签署结果:2=已签署,4=已拒绝,其他=待签署
  operateTime?: string // 操作时间
}

签署状态说明

| signResult | 状态 | 标签颜色 | | ---------- | ------ | --------- | | 2 | 已签署 | success | | 4 | 已拒绝 | error | | 其他 | 待签署 | warning |


LUploadFile

介绍

文件上传组件,基于 Ant Design Vue Upload 封装,支持附件上传、文件预览、只读模式。

基础用法

<template>
  <LUploadFile
    v-model="fileList"
    :action="uploadUrl"
    :max-count="6"
    accept=".jpg,.png,.pdf,.docx"
  />
</template>

<script setup lang="ts">
import type { LUploadFileList } from '@xinlian-frontend/lui'

const fileList = ref<LUploadFileList>([])
const uploadUrl = '/api/upload'
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | ------------------------ | ---------------------- | --------------------------------------- | | modelValue (v-model) | 已上传文件列表 | LUploadFileList | [] | | type | 展示类型 | 'normal' \| 'inline' | 'normal' | | readonly | 只读模式(隐藏上传按钮) | boolean | false | | accept | 允许的文件类型 | string | .jpg,.png,.jpeg,.docx,.pdf,.xls,.xlsx | | hint | 提示文本 | string | - | | action | 上传地址 | string | - | | uploadText | 上传按钮文本 | string | '上传附件' | | headers | 请求头 | any | - | | maxCount | 最大上传数量 | number | 6 | | maxSizeMb | 单个文件大小限制(MB) | number | - |

LUploadFileList

interface LUploadFileItem {
  fileId: string // 文件id
  url?: string // 文件地址
  fileUrl?: string // 文件地址(别名)
  originalFileName?: string // 原文件名
}

type LUploadFileList = LUploadFileItem[]

Events

| 事件名 | 说明 | 参数 | | ----------------- | ------------ | ----------------- | | update:modelValue | 文件列表变化 | LUploadFileList |

组件内部集成了 LFilePreview,上传后可直接点击文件进行预览。

完整使用示例

<template>
  <LUploadFile
    v-model="fileList"
    action="/api/file/upload"
    :max-count="6"
    :max-size-mb="10"
    hint="支持 jpg、png、pdf、docx 格式,单个文件不超过 10MB"
    @change="handleFileChange"
  />
</template>

<script setup lang="ts">
import type { LUploadFileList } from '@xinlian-frontend/lui'

const fileList = ref<LUploadFileList>([])

function handleFileChange(files: LUploadFileList) {
  console.log('当前文件列表:', files)
}
</script>

LUploadImage

介绍

图片/视频上传组件,基于 Ant Design Vue Upload 封装,使用卡片样式展示,支持预览。

基础用法

<template>
  <LUploadImage v-model="imageList" :action="uploadUrl" :max-count="6" accept="image/*" />
</template>

<script setup lang="ts">
import type { LUploadFileList } from '@xinlian-frontend/lui'

const imageList = ref<LUploadFileList>([])
const uploadUrl = '/api/upload'
</script>

Props

| 参数 | 说明 | 类型 | 默认值 | | -------------------- | -------------- | ---------------------- | ----------------- | | modelValue (v-model) | 已上传文件列表 | LUploadFileList | [] | | type | 展示类型 | 'normal' \| 'inline' | 'normal' | | readonly | 只读模式 | boolean | false | | accept | 允许的文件类型 | string | image/*,video/* | | hint | 提示文本 | string | - | | action | 上传地址 | string | - | | uploadText | 上传按钮文本 | string | '上传图片' | | headers | 请求头 | any | - | | maxCount | 最大上传数量 | number | 6 |

类型定义与事件同 LUploadFile


LFilePreview

介绍

通用文件预览组件,支持图片、PDF、Word、Excel、视频等多种文件格式的在线预览。

基础用法

<template>
  <LFilePreview ref="previewRef" />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const previewRef = ref()

// 预览图片
previewRef.value?.showDialog('https://example.com/image.jpg')

// 预览 PDF
previewRef.value?.showDialog('https://example.com/document.pdf')

// 预览 Word
previewRef.value?.showDialog('https://example.com/document.docx')

// 预览 Excel
previewRef.value?.showDialog('https://example.com/spreadsheet.xlsx')

// 预览视频
previewRef.value?.showDialog('https://example.com/video.mp4')
</script>

方法

| 方法名 | 说明 | 参数 | | ---------------------- | ------------ | ---------------------------------------------------------------------------- | | showDialog(url, type?) | 打开预览弹窗 | url: string 文件地址;type?: string 可选文件类型,不传则根据后缀自动识别 |

支持的文件类型

| 类型 | 扩展名 | 预览方式 | | ----- | --------------------------------------- | --------------------------------- | | 图片 | png、jpg、jpeg、gif、bmp、webp | Ant Design Vue Image 组件全屏预览 | | PDF | pdf | VueOfficePdf 组件 | | Word | doc、docx | VueOfficeDocx 组件 | | Excel | xls、xlsx | VueOfficeExcel 组件 | | 视频 | mp4、webm、ogg、avi、mov、wmv、flv、mkv | HTML5 video 标签 | | 其他 | - | 显示"暂不支持预览"提示 |

注意事项

  • 图片预览不通过弹窗,直接以全屏方式展示
  • 文件地址需可直接访问(含权限、跨域配置等)
  • 组件内部通过 showDialog 方法暴露给外部调用

全局引入

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import Lui from '@xinlian-frontend/lui'

const app = createApp(App)
app.use(L Lui)
app.mount('#app')

按需引入

// 按需引入单个组件
import LPageTable from '@xinlian-frontend/lui/es/page-table'
import LDrawer from '@xinlian-frontend/lui/es/drawer'

注意事项

  1. 组件库基于 Ant Design Vue 封装,使用前请确保已正确安装 ant-design-vue
  2. 组件样式使用 SCSS 预处理器,支持主题变量覆盖
  3. 组件内部已处理大部分常见场景,如需深度定制可查看源码
  4. 所有涉及 id 的字段统一按 string 类型传递,避免长整型精度丢失
  5. 接口请求方法 request 的泛型无需嵌套 ResponseData