auto-vue-manual
自用组件库
安装
npm install auto-vue-manual
使用
import AutoVueManual from "auto-vue-manual";
import type { InstallOptions } from 'auto-vue-manual';
import 'auto-vue-manual/dist/index.css';
import request from "@/global/request";
import { Translate } from "@/languages/index";
const options: InstallOptions = {
request,
translate: Translate
}
const app = createApp(App);
app.use(AutoVueManual, options);
app.mount('#app');
目录
Table
ProTable/ProTableSummary
ProTableList
Modal
BasicDialog
BasicDrawer
FormDialog
TableDialog
Upload
UploadAvatar
UploadImage
UploadImages
Storybook
npm run storybook # 本地起 Storybook(http://localhost:6006)
npm run build-storybook # 产出静态站点到 storybook-static/
- stories:
package/**/*.stories.@(js|jsx|mjs|ts|tsx)(如package/components/table/table.stories.tsx,title: 'Base/Table') - 配置:
.storybook/main.ts/.storybook/preview.ts
接口全部走本地 mock(离线可用)
stories 不依赖任何外部域名,数据由 .storybook/mocks/*.json 提供(requestBaseUrl 设为 /api)。
.storybook/mock-api.ts——createMockAdapter()查表返回{ code: 200, data, message: 'ok', status: 'success' };未登记的路径console.warn并返回data: null。- 现有 fixture:
/api/menu/search(分页,{ list, total })、/api/menu/list(非分页,直接数组)、/api/menu/summaries(SumResult[])、/api/menu/change_status。 - 新增 fixture:放
.storybook/mocks/xxx.json→ 在MOCK_FIXTURES登记'/api/xxx'→ story 里写url: '/xxx'。 - 个别 story 想临时关掉 mock:在请求 config 里显式传
adapter(mergeConfig会优先取请求侧)。
⚠️ 必须在 axios 实例上装 adapter,不能只改
axios.defaults:axios.create()会把创建那一刻的axios.defaults.adapter(默认['xhr','http','fetch']数组)快照进实例自己的 defaults;且实例是bind(Axios.prototype.request, context)出来的绑定副本,事后改原型也拦不住。而package/utils/request.ts的实例是模块顶层创建的,静态构建时还会更早求值 —— 所以request.ts导出该实例(export { api }),preview.ts在模块体里installMockAdapter(api)。机制细节与踩坑记录见workbench/docs/manual/components/ProTableList.md的「Storybook」一节。
Button
组件列表
- OpenButton 新建按钮
- RefreshButton 刷新按钮
- SearchButton 搜索按钮
- ResetButton 重置按钮
通用 Props
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| type | string | 按钮类型 | 'primary'(Open/Search),'default'(Refresh),'warning'(Reset) |
| size | string | 按钮尺寸 | 'default' |
| showIcon | boolean | 是否显示图标 | true |
| circle | boolean | 是否圆形按钮 | true |
| plain | boolean | 是否朴素按钮 | false |
| disabled | boolean | 是否禁用 | false |
| loading | boolean | 是否加载中 | false |
| t | string | 按钮文本 | '' |
OpenButton
- 用于新建操作,蓝色圆形加号图标。
- 事件:
@open点击触发
RefreshButton
- 用于刷新操作,圆形刷新图标。
- 事件:
@refresh点击触发 - 支持 loading 状态自定义
SearchButton
- 用于搜索操作,蓝色圆形放大镜图标。
- 事件:
@search点击触发
ResetButton
- 用于重置操作,橙色圆形刷新图标。
- 事件:
@reset点击触发
示例代码
<template>
<OpenButton @open="onOpen" />
<RefreshButton :loading="loading" @refresh="onRefresh" />
<SearchButton t="搜索" @search="onSearch" />
<ResetButton t="重置" @reset="onReset" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { OpenButton, RefreshButton, SearchButton, ResetButton } from 'auto-vue-manual'
const loading = ref(false)
const onOpen = () => {
/* 新建逻辑 */
}
const onRefresh = () => {
loading.value = true
setTimeout(() => (loading.value = false), 1000)
}
const onSearch = () => {
/* 搜索逻辑 */
}
const onReset = () => {
/* 重置逻辑 */
}
</script>
Document
Table
ProTable / ProTableSummary
ColumnProps
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| type | string |
列类型, index / selection / radio / expand / switch / status / tooltip / icon / tag / copy | - |
| prop | string |
列数据字段名 | - |
| label | string |
列标题 | - |
| width | number |
列宽 | - |
| align | string |
列对齐方式 | center |
| isShow | boolean |
是否显示在表格当中 | true |
| search | { defaultValue } |
搜索项配置, defaultValue可以设置默认的init-param | - |
| headerRender | (scope: HeaderRenderScope<T>) => VNode |
自定义表头内容渲染(tsx语法) | - |
| render | (scope: RenderScope<T>) => VNode string |
自定义单元格内容渲染(tsx语法),Basic和list的scope略有不同,请注意 | - |
| props | { api?: string, activeValue?: any, inactiveValue?: any, refresh?: boolean } |
type = switch 时,props 配置 (TODO 更新其他type) | - |
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| columns | ColumnProps[] |
必填,列配置项 | - |
| data | any[] |
静态 table data 数据,若存在则不会使用 request url 返回的 data | - |
| url | string |
实际请求接口 | - |
| auto-search | boolean |
是否自动执行请求 api | true |
| request-error | (params: any) => void |
表格 api 请求错误监听 | - |
| data-callback | (data: any) => any |
返回数据的回调函数,可以对数据进行处理 | - |
| has-pagination | boolean |
是否需要分页组件 | true |
| init-param | any |
初始化请求参数 | {} |
| search-param | any |
搜索参数 | {} |
| border | boolean |
是否带有纵向边框 | true |
| row-key | string |
行数据的 Key,用来优化 Table 的渲染,当表格数据多选时,所指定的 id ) | id |
| size | string |
列表大小,default/small/large | small |
| page-size | number |
列表页大小 | 0 |
| row-h | number |
列表行高 | 0 |
| ext-h | number |
列表额外高度 | 0 |
| sum-url | string |
汇总接口 url,仅 ProTableSummary 有效 |
sumUrl的响应结构(SumResult[])汇总接口的响应体固定为
{ data: SumResult[] },元素结构为{ index: number; text: string }:
index—— 该汇总值落在第几列(对应columns扁平化后的下标,与el-table的summary-method对齐);text—— 该单元格显示的文本。{ "data": [{ "index": 0, "text": "合计" }, { "index": 3, "text": "128,900" }] }请求参数为
{ ...initParam, ...totalParam, page: 1, size: 1 }—— 即当前查询条件,不随分页变化(汇总始终是全量口径)。刷新时机:随
getTableList()一起刷新,因此首次加载、search()、reset()、翻页、改每页条数都会重取;请求失败会走requestError回调,并保留上一次的汇总值(不会闪成空白)。宿主也可通过 ref 主动调用getSummaries()读取当前汇总结果。
Event 事件说明
| 事件名 | 说明 | 参数 |
|---|---|---|
| @row-click | 行点击事件,已排除 status / operation 列 | (row: any, column: any) => void |
| @row-dblclick | 行双击事件,已排除 status / operation 列 | (row: any, column: any) => void |
| @switch-change | 开关切换事件 | (value, scope, column) => void |
Expose 暴露方法说明
| 方法名 | 说明 | 参数 |
|---|---|---|
| @search | 搜索事件 | (searchParam?: Record<string, any>) => void |
| @reset | 重置事件 | () => void |
| @getTableList | 获取表格数据,不更新搜索参数及分页参数 | () => void |
| @getSummaries | 读取当前汇总结果(仅 ProTableSummary,返回按列 index 索引的文本数组) |
() => string[] |
示例代码
<template>
<div>
<el-button @click="search">搜索</el-button>
<el-button @click="reset">重置</el-button>
</div>
<ProTable ref="proTableRef" :columns="columns" url="/league/search" :search-param="params" @row-dblclick="onRowDblclick">
<template #logo="{ row }">
<div class="flex-center h-100">
<el-image style="width: 36px; height: 36px" :src="row.logo" />
</div>
</template>
</ProTable>
</template>
<script setup lang="ts">
import type { ColumnProps, RenderScope, HeaderRenderScope } from 'auto-vue-manual'
import { reactive, ref } from 'vue'
import { ProTable } from 'auto-vue-manual'
const proTableRef = ref<InstanceType<typeof ProTable>>()
const columns: ColumnProps[] = [
{ label: 'index', type: 'index' },
{ prop: 'code', label: '代号', width: 100, type: 'tag' },
{ prop: 'logo', label: '标志', width: 100 },
{
prop: 'status',
label: '状态',
width: 100,
type: 'switch',
props: {
activeValue: 1,
inactiveValue: 2,
api: '/league/change_status',
refresh: true
}
},
{
prop: 'name',
label: '名称',
width: 0,
align: 'right',
headerRender: ({ column }: HeaderRenderScope<any>) => {
return <span>headerRender: {column.label}</span>
},
render: ({ row }: RenderScope<any>) => {
return <span>render: {row.name}</span>
}
}
]
const params = reactive({
keyword: ''
})
const search = () => {
// 修改搜索参数
params.keyword = 'League'
proTableRef.value?.search()
// 直接传入参数
// proTableRef.value?.search({
// keyword: "League",
// })
}
const reset = () => {
proTableRef.value?.reset()
}
const onRowDblclick = (row: any, column: any, event: any) => {
console.log('onRowDblclick', row, column, event)
}
</script>
ProTableList
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| row-key | string |
行数据的 Key,用来优化 Table 的渲染,当表格数据多选时,所指定的 id ) | id |
其余同 ProTable,但 hasPagination 不在 ProTableList 的契约内(ProTableListProps extends Omit<BaseTableProps, 'hasPagination'>)。
⚠️ Breaking change:
ProTableList基于el-table-v2虚拟滚动,模板中不渲染分页器,取数固定为「一次拉全量」(useTable以非分页模式调用,请求不带page/size,响应直接读整个data而非data.list)。历史上hasPagination会切换请求形态却画不出分页器,还会白扣 44px 高度,故已从契约中移除 —— 传入该 prop 不再生效(且会作为普通 attribute 透传到根元素)。需要分页请改用ProTable/ProTableSummary。
Event 事件说明
| 事件名 | 说明 | 参数 |
|---|---|---|
| @row-click | 行点击事件,已排除 status / operation 列(与 ProTable 一致) |
({ rowKey, rowData, rowIndex, event }: RowEventHandlerParams) => void |
| @row-dblclick | 行双击事件,已排除 status / operation 列(与 ProTable 一致) |
({ rowKey, rowData, rowIndex, event }: RowEventHandlerParams) => void |
与
ProTable的(row, column, event)不同:el-table-v2的行事件包装器只回传{ event, rowData, rowIndex, rowKey },没有column。因此列过滤由组件内部完成 —— 用:cell-props给每个单元格打上data-column-key,事件里从event.target.closest('[role="cell"]')反查(取的是列的key,即item.key || item.prop)。载荷形状不受影响,宿主代码无需改动。
Expose 暴露方法说明
与 ProTable 相同(含 radio —— type: 'radio' 单选列的选中值,与 v1 一样不 emit,经 tableRef.value.radio 读取)。
示例代码
<template>
<div>
<el-button @click="search">搜索</el-button>
<el-button @click="reset">重置</el-button>
</div>
<ProTableList ref="proTableRef" row-key="key" :columns="columns" :search-param="params" url="/page/list" @row-dblclick="onRowDblclick" />
</template>
<script setup lang="tsx">
import type { RowEventHandlerParams } from 'element-plus'
import type { ColumnProps, HeaderRenderScope, RenderScope } from 'auto-vue-manual'
import { ref, reactive } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { ProTableList } from 'auto-vue-manual'
const proTableRef = ref<InstanceType<typeof ProTableList>>()
const columns: ColumnProps[] = [
{ label: 'index', type: 'index' },
{ prop: 'label', label: 'Label', width: 100, type: 'tag' },
{ prop: 'key', label: 'Key', width: 100, type: 'copy' },
{
prop: 'value',
label: 'Value',
width: 200,
headerRender: (scope: HeaderRenderScope<any>) => {
return <span>HeaderRender: {scope.column.label}</span>
}
},
{
prop: 'status',
label: 'Status',
width: 100,
type: 'switch',
props: {
activeValue: 1,
inactiveValue: 2,
api: '/league/change_status',
refresh: true
}
},
{
prop: 'action',
label: 'Action',
width: 60,
align: 'center',
render: (scope: RenderScope<any>) => {
return (
<el-button
type="primary"
size="small"
link
icon={Plus}
onClick={(e: Event) => {
e.stopPropagation()
console.log('onclick', e)
}}
>
<span>render: {scope.rowData.label}</span>
</el-button>
)
}
}
]
const params = reactive({
keyword: ''
})
const search = () => {
// 修改搜索参数
params.keyword = 'League'
proTableRef.value?.search()
// 直接传入参数
// proTableRef.value?.search({
// keyword: "League",
// })
}
const reset = () => {
proTableRef.value?.reset()
}
const onRowDblclick = (row: RowEventHandlerParams) => {
console.log('onRowDblclick', row)
}
</script>
Modal 弹窗/抽屉
统一说明
- 所有弹窗类组件(BasicDialog、FormDialog、TableDialog)均基于 BasicDialog 实现,props/事件/用法风格统一。
- 所有抽屉类组件均基于 BasicDrawer 实现。
- 支持 v-bind 透传 Element Plus Dialog/Drawer 的所有原生属性。
通用 Props
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| modelValue | boolean | 是否显示(配合 v-model) |
false |
| showClose | boolean | 是否显示关闭按钮 | true |
| title | string | 标题(i18n key,经 Translate() 翻译) |
'' |
| width | string | Dialog 宽度;Drawer 映射到 el-drawer 的 size |
520px |
| top | string | 顶部距离(仅 Dialog) | 15vh |
| center | boolean | 头部/底部居中(仅 Dialog) | true |
| divider | boolean | 正文顶部是否渲染 el-divider |
Dialog true / Drawer false |
| appendToBody | boolean | 是否插入 body | true |
| lockScroll | boolean | 是否锁定滚动 | true |
| closeOnClickModal | boolean | 点击遮罩关闭 | false |
除上表外的 Element Plus Dialog / Drawer 原生属性(
fullscreen、draggable、headerClass、beforeClose等)均通过v-bind直接透传。
通用事件
| 事件名 | 说明 |
|---|---|
| update:modelValue | v-model 回写 |
| close | 关闭动画开始时触发(对应 Element Plus 的 close) |
| closed | 关闭动画结束时触发(对应 Element Plus 的 closed) |
BasicDialog
- 通用弹窗基类,支持所有通用 props 和事件。
- 事件:
update:modelValue、close、closed - 暴露(
defineExpose):close()、dialogRef(内部el-dialog实例)
BasicDrawer
- 通用抽屉基类,支持所有通用 props 和事件(无
top/center)。 - 事件:
update:modelValue、close、closed - 暴露(
defineExpose):close()、drawerRef(内部el-drawer实例)
FormDialog
- 基于 BasicDialog 扩展,内置底部按钮,适合表单场景。
- 额外 props:
executing(是否执行中)、btnSize、okText、okType、cancelText、cancelType - 事件:
update:modelValue、close、closed、submit
TableDialog
- 基于 BasicDialog 扩展,适合表格弹窗场景。
- 额外 props:
requesting(是否请求中) - 事件:
update:modelValue、close、closed
示例代码
<template>
<OpenButton @open="visible = true" />
<BasicDialog v-model="visible" title="base.confirm" width="520px" @closed="onClosed">
<template #default>内容区域</template>
</BasicDialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { BasicDialog, OpenButton } from 'auto-vue-manual'
const visible = ref(false)
const onClosed = () => {
/* 关闭动画结束后 */
}
</script>
FormDialog 示例
<template>
<OpenButton @open="visible = true" />
<FormDialog v-model="visible" title="base.confirm" @submit="onSubmit">
<template #default>
<el-input v-model="form.name" placeholder="请输入名称" />
</template>
</FormDialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { FormDialog, OpenButton } from 'auto-vue-manual'
const visible = ref(false)
const form = ref({ name: '' })
const onSubmit = () => {
/* 提交逻辑 */
}
</script>
Upload
UploadAvatar
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| url | string |
上传地址 | - |
| avatar | string |
头像地址 | - |
| text | string |
上传提示 | - |
| path | string |
保存路径 | - |
| preview | boolean |
是否显示预览 | true |
| disabled | boolean |
是否禁用 | false |
| size | number |
大小(KB) | 5120 |
UploadImage
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| image | string |
图片地址 | - |
其余同 UploadAvatar
示例代码
<template>
<UploadAvatar ref="uploadAvatarRef" url="/upload/image" :avatar="avatar" text="上传头像" path="/avatar" preview :size="1024" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import UploadAvatar from 'auto-vue-manual'
const uploadAvatarRef = ref<InstanceType<typeof UploadAvatar>>()
const avatar = ref('')
</script>
UploadImages
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| images | FileList[] |
图片地址 | - |
| limit | number |
限制数量 | 10 |
其余同 UploadAvatar
示例代码
<template>
<UploadImages ref="uploadImagesRef" url="/upload/image" :images="images" text="上传图片" path="/image" preview :size="1024" />
</template>
<script setup lang="ts">
import type { FileList } from 'auto-vue-manual'
import { ref } from 'vue'
import UploadImages from 'auto-vue-manual'
const uploadImagesRef = ref<InstanceType<typeof UploadImages>>()
const images = ref<FileList[]>([])
</script>
Tinymce 富文本编辑器
组件说明
基于 tinymce 封装的富文本编辑器,支持图片上传、字数统计、代码高亮等常用功能,适用于内容管理、文章编辑等场景。
Props 参数说明
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| url | string | 图片上传接口 | /upload/image |
| content | string | 编辑器内容(v-model) | '' |
| height | number | 编辑器高度 | 600 |
| disabled | boolean | 是否禁用编辑 | false |
事件
| 事件名 | 说明 | 参数 |
|---|---|---|
| update:content | 内容变更时触发 | value: string |
功能特性
- 支持图片粘贴/上传,自动调用
url接口 - 支持字数统计、代码高亮、列表、字体样式等
- 支持自定义高度、禁用状态
- 默认中文界面
示例代码
<template>
<Tinymce v-model:content="content" :height="400" :url="'/upload/image'" />
<p>内容:{{ content }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Tinymce from 'auto-vue-manual'
const content = ref('<p>初始内容</p>')
</script>
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.3.20 | ^3.5.13 | ||
| 0.3.19 | ^3.5.13 | ||
| 0.3.16 | ^3.5.13 | ||
| 0.3.15 | ^3.5.13 | ||
| 0.3.13 | ^3.5.13 | ||
| 0.3.12 | ^3.5.13 | ||
| 0.3.10 | ^3.5.13 | ||
| 0.3.9 | ^3.5.13 | ||
| 0.3.8 | ^3.5.13 | ||
| 0.3.7 | ^3.5.13 | ||
| 0.3.6 | ^3.5.13 | ||
| 0.3.5 | ^3.5.13 | ||
| 0.3.4 | ^3.5.13 | ||
| 0.3.3 | ^3.5.13 | ||
| 0.3.2 | ^3.5.13 | ||
| 0.2.101 | ^3.5.13 | ||
| 0.2.99 | ^3.5.13 | ||
| 0.2.98 | ^3.5.13 | ||
| 0.2.97 | ^3.5.13 | ||
| 0.2.96 | ^3.5.13 | ||
| 0.2.95 | ^3.5.13 | ||
| 0.2.94 | ^3.5.13 | ||
| 0.2.93 | ^3.5.13 | ||
| 0.2.92 | ^3.5.13 | ||
| 0.2.91 | ^3.5.13 | ||
| 0.2.90 | ^3.5.13 | ||
| 0.2.89 | ^3.5.13 | ||
| 0.2.88 | ^3.5.13 | ||
| 0.2.87 | ^3.5.13 | ||
| 0.2.86 | ^3.5.13 |
Showing the latest 30 of 267. See every release on npm