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

@wg-song/bare

v0.1.2

Published

Vue3 业务组件库 - Form / Table / Feedback 等多层结构支持

Readme

@wg-song/bare — Vue3 业务组件库

基于 Vue 3 + Ant Design Vue + vxe-table 的业务组件库,提供表单、表格、列表页、弹窗、标签页等高频业务场景组件。

安装

pnpm add @wg-song/bare

Peer dependencies(必需,由接入应用提供):

{
  "vue": "^3.0.0",
  "ant-design-vue": "^4.0.0",
  "vxe-table": "^4.0.0",
  "@ant-design/icons-vue": "^7.0.0",
  "vue-router": "^4.0.0 || ^5.0.0"
}

推荐一并安装(以获得完整 vxe-table 体验):

pnpm add vxe-pc-ui

vxe-pc-uivxe-table 的配套 UI 包,提供 tooltip、loading、筛选面板等能力。本库表格组件默认使用 showOverflow: 'title' 避免强依赖,不强制要求 vxe-pc-ui;但建议接入方一并安装并注册,否则部分 vxe-table 高级交互可能表现不一致。

快速开始

main.ts先注册 vxe-table / vxe-pc-ui,再安装本库:

import { createApp } from 'vue'
import VXETable from 'vxe-table'
import VXEPcUI from 'vxe-pc-ui'
import BareComponents from '@wg-song/bare'
import 'vxe-table/lib/style.css'
import 'vxe-pc-ui/lib/style.css'
import '@wg-song/bare/index.css'

const app = createApp(App)
app.use(VXEPcUI)
app.use(VXETable)
app.use(BareComponents)
app.mount('#app')

若未注册 vxe-table,表格组件会报 [Vue warn]: Failed to resolve component: vxe-grid。开发环境下本库 install 阶段会在控制台给出明确提示。

组件能力矩阵

场景组件

| 组件 / API | 说明 | |---|---| | PageList | 完整列表页(搜索 + 工具栏 + 表格 + 分页 + 详情弹窗) | | PageShell | 列表页外壳(搜索 + 工具栏 + 表格插槽 + 分页) | | PageEditList | 可编辑列表页 | | PageChildList | 子列表页 | | TableRead | 只读表格(固定操作列等) | | TableEdit | 行内编辑表格 | | TableChild | 父子表格 | | TableGroup / TableGroupPage | 分组表格 | | DialogForm | 弹窗表单场景 | | PageModals / PageModalSlot | 页面级弹窗管理器 | | PageListTabs | 标签页 + 列表组合 |

基础组件

| 组件 / API | 说明 | |---|---| | Form | Schema 驱动表单 | | SearchForm | 搜索表单(含高级搜索、FilterBar) | | SearchFormSimple | 简易单行搜索 | | Table | 基础 vxe-table 封装 | | Pagination | 分页 | | Modal / Drawer | 声明式弹窗/抽屉 | | Button | 按钮 | | Switch | 开关 | | Tag | 标签 | | Link | 链接 | | Icon | 图标 | | Col | 布局列 | | Dropdown / DropdownMenuItem / DropdownSplitButton | 下拉菜单 | | Dialog | 对话框 | | Popover / Tooltip / Popconfirm | 反馈类浮层 | | Tabs / TabsView / PageTabs | 标签页 | | SplitPane / SplitPaneLayout | 分割面板 | | ToolbarActionBar / ToolbarActionButtonMenu | 表格工具栏操作 |

Hooks / 工具函数

| API | 说明 | |---|---| | useForm / useSearchForm | 表单核心 hook | | usePageList | 列表页逻辑 hook | | definePageList / defineLoader | 列表页配置定义 | | usePageModals / usePageModalContext / definePageModals | 页面弹窗管理 | | useTabState / useTabbedList | 标签页状态 hook | | openModal / openDrawer / confirm / alert / setupModal / useModalContext | 命令式弹窗/反馈 | | localColDriver / remoteColDriver / storeColDriver / setupColPref | 列偏好存储 | | mapToOptions / formatDictLabel / formatAmountValue / formatDateValue / formatCellDisplay | 表格格式化工具 |

当前版本未提供独立的 InputSelectCard 组件;表单输入请使用 Form / SearchFormFormField 配置,或继续使用 Ant Design Vue 原生组件。

核心使用模式

1. Schema 表单

<script setup lang="ts">
import { ref } from 'vue'
import { Form } from '@wg-song/bare'
import type { FormField } from '@wg-song/bare'

const schemas: FormField[] = [
  { field: 'name', label: '名称', component: 'input', required: true },
  { field: 'status', label: '状态', component: 'select', options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 },
  ]},
]

const model = ref({ name: '', status: 1 })

function onSubmit(values: Record<string, any>) {
  console.log(values)
}
</script>

<template>
  <Form v-model="model" :schemas="schemas" @submit="onSubmit" />
</template>

2. 搜索表单 + 表格

<script setup lang="ts">
import { SearchForm, Table } from '@wg-song/bare'
import type { FormField, TableColumn } from '@wg-song/bare'

const searchSchemas: FormField[] = [
  { field: 'keyword', label: '关键词', component: 'input' },
]

const columns: TableColumn[] = [
  { field: 'name', title: '名称' },
  { field: 'status', title: '状态' },
]

const data = [
  { name: '示例', status: '启用' },
]
</script>

<template>
  <SearchForm :schemas="searchSchemas" />
  <Table :columns="columns" :data="data" />
</template>

3. 列表页(推荐)

<script setup lang="ts">
import { PageShell } from '@wg-song/bare'
import type { FormField, PageShellProps, ActionItem } from '@wg-song/bare'

const searchSchemas: FormField[] = [
  { field: 'keyword', label: '关键词', component: 'input' },
]

const toolbarActions: ActionItem[] = [
  { label: '新增', onClick: () => {} },
]

const loader: PageShellProps['loader'] = async ({ params, page, pageSize }) => {
  // 调用业务 API,params 为搜索表单值
  return { list: [], total: 0 }
}
</script>

<template>
  <PageShell
    :search-schemas="searchSchemas"
    :loader="loader"
    :toolbar-actions="toolbarActions"
  >
    <template #default="{ tableData, loading }">
      <!-- 渲染表格或其他内容 -->
    </template>
  </PageShell>
</template>

4. 命令式弹窗

import { confirm, openModal } from '@wg-song/bare'

async function onDelete() {
  const ok = await confirm('确认删除', '删除后不可恢复')
  if (ok) {
    // 执行删除
  }
}

function onOpen() {
  openModal(MyComponent, { title: '详情', data: row })
}

完整 CRUD 示例:角色管理

<!-- views/role/index.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import { ref } from 'vue'
import { PageList, confirm } from '@wg-song/bare'
import type {
  FormField,
  TableColumn,
  ActionItem,
  PageListProps,
  PageListToolbarContext,
} from '@wg-song/bare'
import RoleDetail from './RoleDetail.vue'

const pageListRef = ref<InstanceType<typeof PageList> | null>(null)

const searchSchemas: FormField[] = [
  { field: 'roleName', label: '角色名称', component: 'input' },
  { field: 'status', label: '状态', component: 'select', options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 },
  ]},
]

const columns: TableColumn[] = [
  { field: 'roleName', title: '角色名称', component: 'link' },
  { field: 'roleCode', title: '角色编码' },
  { field: 'status', title: '状态', component: 'tag', tagColor: ({ value }) => value === 1 ? 'success' : 'default' },
  { field: 'updateTime', title: '更新时间' },
]

function toolbarActions(ctx: PageListToolbarContext): ActionItem[] {
  return [
    { label: '新增', type: 'primary', onClick: () => pageListRef.value?.openDetail(null) },
    {
      label: '批量删除',
      danger: true,
      disabled: ctx.selectedCount === 0,
      onClick: async () => {
        const rows = ctx.getSelectedRows()
        const ok = await confirm(`确认删除选中的 ${rows.length} 项?`)
        if (!ok) return
        // 业务侧调用删除 API,例如 await deleteRole(rows.map((r) => r.id))
        pageListRef.value?.reload()
      },
    },
  ]
}

function rowActions(row: any): ActionItem[] {
  return [
    { label: '编辑', onClick: () => pageListRef.value?.openDetail(row) },
    { label: '删除', danger: true, onClick: async () => {
      const ok = await confirm('确认删除该角色?')
      if (!ok) return
      // 业务侧调用删除 API,例如 await deleteRole([row.id])
      pageListRef.value?.reload()
    }},
  ]
}

const page: PageListProps['page'] = {
  tableId: 'role-management',
  search: searchSchemas,
  columns,
  loader: async ({ params, page, pageSize }) => {
    // 业务侧调用分页 API,例如 const res = await getRolePage({ ...params, currentPage: page, pageSize })
    return { list: [], total: 0 }
  },
  toolbarActions,
  rowActions,
  detailComponent: RoleDetail,
  detailTitle: '角色详情',
  detailWidth: 600,
}
</script>

<template>
  <PageList ref="pageListRef" :page="page" />
</template>
<!-- views/role/RoleDetail.vue -->
<script setup lang="ts">
import { computed } from 'vue'
import { Form, usePageModalContext } from '@wg-song/bare'
import type { FormField } from '@wg-song/bare'
const { row, close, confirmLoading } = usePageModalContext<any>()

/** row 存在表示编辑,不存在表示新增 */
const isEdit = computed(() => !!row.value)

const schemas: FormField[] = [
  { field: 'roleName', label: '角色名称', component: 'input', required: true },
  { field: 'roleCode', label: '角色编码', component: 'input', required: true },
  { field: 'status', label: '状态', component: 'select', options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 },
  ]},
  { field: 'remark', label: '备注', component: 'textarea' },
]

async function submit() {
  confirmLoading.value = true
  try {
    // 业务侧调用保存 API,例如 await saveRole(row.value)
    close({ success: true })
  } finally {
    confirmLoading.value = false
  }
}

defineExpose({ submit })
</script>

<template>
  <Form
    :model="row"
    :schemas="schemas"
    :disabled="!isEdit && false"
  />
</template>

关键约定:

  • detailComponent 通过 usePageModalContext() 获取 rowrownull/undefined 表示新增,否则为编辑。
  • 详情组件必须 defineExpose({ submit }),PageList 在点击「确定」时调用该方法。
  • submit 中通过 confirmLoading.value = true/false 控制确认按钮加载态;调用 close(result) 关闭弹窗。

核心 API 速查

PageList 实例方法(通过 ref 获取)

| 方法 | 说明 | |---|---| | openDetail(row?) | 打开详情弹窗;row 为空表示新增 | | reload() | 重新加载当前页数据 | | load() | 同 reload | | reset() | 重置搜索条件 | | gotoPage(page) | 跳转到指定页 | | getSelectedRows() | 获取当前已选行 | | setFieldsValue(values) | 设置搜索表单字段值 | | clearCheckboxSelection() | 清空复选框选择 |

usePageModalContext()

| 属性 / 方法 | 类型 | 说明 | |---|---|---| | row | Ref<D \| undefined> | 当前行数据;为空表示新增 | | close | (result?: any) => void | 关闭并触发 ok | | cancel | () => void | 关闭并触发 cancel | | confirmLoading | Ref<boolean> | 确认按钮加载状态 |

ActionItem 常用字段

| 字段 | 说明 | |---|---| | label | 按钮文字 | | type | Ant Design Vue Button typeprimary / default / dashed / link / text | | danger | 是否危险样式 | | disabled | 是否禁用 | | onClick | 点击回调 |

全局配置

通过 app.use(BareComponents, { globalConfig }) 传入:

app.use(BareComponents, {
  globalConfig: {
    table: { /* Table 默认配置 */ },
    pageList: { /* PageList 默认配置 */ },
    colPref: { /* 列偏好设置默认配置 */ },
  },
})

类型导入

import type {
  // 表单
  FormField,
  FormProps,
  SearchFormProps,
  DialogFormProps,

  // 表格
  TableColumn,
  TableProps,
  TableReadProps,
  TableEditColumn,
  TableChildProps,
  TableGroupProps,

  // 列表页
  PageShellProps,
  PageListProps,
  PageListConfig,
  PageListRowActions,
  PageListToolbarContext,
  ActionItem,

  // 弹窗
  ModalContext,
  ModalProps,
  DrawerProps,
  PageModalContext,
  PageModalConfig,

  // 工具
  OptionItem,
  ColProps,
} from '@wg-song/bare'

包内示例

本包附带可直接运行的业务场景示例,统一使用 from '@wg-song/bare' 导入:

  • examples/role-management/ — 角色管理完整 CRUD
  • examples/user-management/ — 用户管理 PageShell + TableRead

复制到业务项目的 views/ 目录即可参考使用。

构建产物

pnpm build:bare 输出到 dist/packages/

  • index.mjs — ESM 主入口
  • index.cjs — CommonJS 入口
  • index.umd.js — UMD 入口
  • index.css — 样式
  • types.d.ts — TypeScript 类型声明
  • README.md / AGENTS.md — 使用文档与 AI 指南
  • examples/ — 业务场景示例
  • package.json

本地联调可在其他项目中:

"@wg-song/bare": "file:../songwg-business-components/dist/packages"