CJ Design
基于 Vue3 + Element Plus 的业务组件库。
安装
npm install @cj-design/vue
# 或
pnpm add @cj-design/vue
依赖要求
| 依赖 |
版本 |
| vue |
^3.4.0 |
| element-plus |
^2.5.0 |
| @element-plus/icons-vue |
^2.3.0 |
快速开始
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import CjDesign from '@cj-design/vue';
import '@cj-design/vue/dist/index.css';
const app = createApp(App);
app.use(ElementPlus);
app.use(CjDesign);
app.mount('#app');
也可以按需引入:
import { CjTable, CjProTable, CjSearch, CjUpload } from '@cj-design/vue';
组件文档
CjProTable 高级表格组件
集成 CjSearch + CjTable 的高级表格组件,通过统一的列配置同时生成搜索表单和数据表格,内置列设置(拖拽排序)、刷新等工具栏功能。
Props
继承 CjTable 的所有 Props(columns 类型升级为 CjProTableColumnProps[]),额外新增:
| 属性 |
类型 |
默认值 |
说明 |
| columns |
CjProTableColumnProps[] |
[] |
列配置(含搜索配置) |
| searchProps |
Record<string, any> |
{} |
透传给 CjSearch 的额外 props |
| toolbarRight |
CjProTableToolbarRightValue |
true |
右侧工具栏配置 |
CjProTableColumnProps 等同于 CjSearchColumnProps,即在 CjTableColumnProps 基础上增加了 search 字段。
只有配置了 search 的列才会出现在搜索表单中。
CjProTableToolbarRightValue
type CjProTableToolbarRightType = 'refresh' | 'setting';
// false 隐藏全部,true 显示全部,数组指定显示哪些
type CjProTableToolbarRightValue =
| boolean
| CjProTableToolbarRightType[];
CjProTableColumnProps
interface CjProTableColumnProps extends CjTableColumnProps {
search?: CjSearchConfigProps;
}
Events
| 事件名 |
参数 |
说明 |
| search |
(params: CjTableRequestParams) |
搜索时触发 |
| reset |
— |
重置时触发 |
| update:data |
(data: any[]) |
数据更新时触发 |
Expose Methods
| 方法名 |
说明 |
| refresh |
刷新数据(保持当前分页) |
| reload |
重新加载(重置到第一页) |
| getParams |
获取当前请求参数 |
| tableRef |
内部 CjTable 的 ref |
Slots
| 插槽名 |
说明 |
| toolbar-left |
工具栏左侧 |
| toolbar-right |
工具栏右侧(提供此插槽时替换默认刷新/列设置按钮) |
| table |
自定义渲染整个表格(透传给 CjTable) |
| [col.prop] |
自定义列内容(透传给 CjTable) |
列设置功能
内置列设置弹窗,支持:
- 勾选/取消列的显示隐藏
- 拖拽排序调整列顺序
- 全选/清除快捷操作
- 重置为初始状态
通过 toolbarRight 控制显示:
// 显示全部工具栏按钮(默认)
toolbarRight: true
// 仅显示刷新按钮
toolbarRight: ['refresh']
// 仅显示列设置按钮
toolbarRight: ['setting']
// 隐藏全部工具栏按钮
toolbarRight: false
基本用法
<template>
<CjProTable :columns="columns" :request-api="fetchList">
<template #toolbar-left>
<el-button type="primary" @click="handleAdd">新增</el-button>
</template>
<template #action="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
</template>
</CjProTable>
</template>
<script setup lang="ts">
import { CjProTable } from '@cj-design/vue';
import type { CjProTableColumnProps, CjProTableRequestApi } from '@cj-design/vue';
const columns: CjProTableColumnProps[] = [
{
prop: 'name',
label: '姓名',
search: { type: 'el-input' },
},
{
prop: 'status',
label: '状态',
valueEnum: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
search: { type: 'el-select' },
},
{
prop: 'createTime',
label: '创建时间',
props: { width: 180 },
},
{
prop: 'action',
label: '操作',
props: { width: 150, fixed: 'right' },
},
];
const fetchList: CjProTableRequestApi = async (params) => {
const res = await fetch(`/api/list?page=${params.current}&size=${params.pageSize}`);
return res.json();
};
const handleAdd = () => console.log('新增');
const handleEdit = (row: any) => console.log('编辑', row);
const handleDelete = (row: any) => console.log('删除', row);
</script>
CjSearch 搜索表单组件
基于 el-form 的搜索表单组件,支持通过列配置动态生成搜索表单,支持 Grid 布局。
Props
| 属性 |
类型 |
默认值 |
必填 |
说明 |
| columns |
CjSearchColumnProps[] |
[] |
是 |
搜索列配置 |
| modelValue |
Record<string, any> |
{} |
否 |
搜索表单值(v-model) |
| colsPerRow |
number |
4 |
否 |
每行显示的列数 |
| gap |
string | number |
16 |
否 |
网格间距 |
| labelWidth |
string | number |
80 |
否 |
label 宽度 |
CjSearchColumnProps
继承自 CjTableColumnProps,新增 search 配置项:
interface CjSearchColumnProps extends CjTableColumnProps {
search?: CjSearchConfigProps;
}
CjSearchConfigProps
| 属性 |
类型 |
默认值 |
说明 |
| type |
string |
— |
搜索组件类型,如 'el-input'、'el-select'、'el-date-picker' 等 |
| props |
Record<string, any> |
— |
透传给搜索组件的 props |
| defaultValue |
any |
— |
默认值 |
| span |
number |
1 |
该项占据的列数 |
CjSearchValueEnumItem
interface CjSearchValueEnumItem {
label: string;
value: any;
disabled?: boolean;
children?: CjSearchValueEnumItem[];
}
Events
| 事件名 |
参数 |
说明 |
| update:modelValue |
(value: Record<string, any>) |
表单值变更 |
| search |
(params: Record<string, any>) |
点击搜索 |
| reset |
— |
点击重置(重置后自动触发 search) |
Expose Methods
| 方法名 |
参数 |
说明 |
| getFormData |
— |
获取当前表单数据 |
| setFormData |
(data: Record<string, any>) |
设置表单数据 |
| resetForm |
— |
重置表单 |
基本用法
<template>
<CjSearch v-model="searchParams" :columns="columns" @search="onSearch" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { CjSearch } from '@cj-design/vue';
import type { CjSearchColumnProps } from '@cj-design/vue';
const searchParams = ref({});
const columns: CjSearchColumnProps[] = [
{
prop: 'name',
label: '姓名',
search: { type: 'el-input' },
},
{
prop: 'status',
label: '状态',
valueEnum: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
search: { type: 'el-select' },
},
{
prop: 'date',
label: '日期',
search: { type: 'el-date-picker', props: { type: 'daterange' }, span: 2 },
},
];
const onSearch = (params: Record<string, any>) => {
console.log('搜索参数', params);
};
</script>
CjTable 表格组件
基于 el-table + el-pagination 封装的表格组件,支持自动分页请求、列枚举映射、自定义列插槽。
Props
| 属性 |
类型 |
默认值 |
必填 |
说明 |
| columns |
CjTableColumnProps[] |
[] |
是 |
列配置 |
| requestApi |
CjTableRequestApi |
— |
否 |
简化版请求 API |
| request |
CjTableRequestFunction |
— |
否 |
ProTable 风格请求函数 |
| immediate |
boolean |
true |
否 |
是否立即执行请求 |
| showPagination |
boolean |
true |
否 |
是否显示分页 |
| defaultPage |
number |
1 |
否 |
默认页码 |
| defaultPageSize |
number |
10 |
否 |
默认每页条数 |
| pageSizes |
number[] |
[10, 20, 50, 100] |
否 |
分页选项 |
| initParams |
Record<string, any> |
{} |
否 |
初始搜索参数 |
| dataCallback |
(data: any) => { list: any[]; total: number } |
— |
否 |
数据回调,用于自定义处理响应数据 |
CjTableColumnProps
| 属性 |
类型 |
说明 |
| prop |
string |
字段名(type 为 index 时可省略) |
| label |
string |
列标题 |
| type |
'index' |
列类型,index 为序号列 |
| props |
Record<string, any> |
列额外配置,透传给 el-table-column |
| valueEnum |
{ label: string; value: any; children?: any[] }[] |
值枚举,用于自动映射显示文本(支持树形结构) |
| search |
any |
搜索配置(CjProTable 使用) |
| hideInTable |
boolean |
是否在表格中隐藏该列(仅展示在搜索区域) |
请求相关类型
// 请求参数
interface CjTableRequestParams {
current: number;
pageSize: number;
[key: string]: any;
}
// 响应数据体(兼容 list / records 两种格式)
interface CjTableRequestData<T = any> {
list?: T[];
records?: T[];
total: number;
}
// 响应结果
interface CjTableRequestResult<T = any> {
data: CjTableRequestData<T>;
success?: boolean;
}
// 简化版请求 API
type CjTableRequestApi<T = any> = (
params: CjTableRequestParams,
) => Promise<CjTableRequestResult<T>>;
// ProTable 风格请求函数
type CjTableRequestFunction<T = any> = (
params: CjTableRequestParams & Record<string, any>,
sort?: Record<string, 'ascend' | 'descend'>,
filter?: Record<string, any>,
) => Promise<CjTableRequestResult<T>>;
Events
| 事件名 |
参数 |
说明 |
| search |
(params: CjTableRequestParams) |
每次请求时触发 |
| update:data |
(data: any[]) |
数据更新时触发 |
Expose Methods
| 方法名 |
参数 |
说明 |
| refresh |
(extraParams?: Record<string, any>) |
刷新数据(保持当前分页) |
| reload |
(extraParams?: Record<string, any>) |
重新加载(重置到第一页) |
| getParams |
— |
获取当前请求参数 |
| tableRef |
— |
内部 el-table 的 ref |
Slots
| 插槽名 |
作用域参数 |
说明 |
| table |
{ loading, tableData, columns, formatCellValue } |
自定义渲染整个表格区域 |
| [col.prop] |
scope(同 el-table-column default) |
自定义列内容 |
基本用法
<template>
<CjTable :columns="columns" :request-api="fetchList">
<template #status="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
<template #action="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
</template>
</CjTable>
</template>
<script setup lang="ts">
import { CjTable } from '@cj-design/vue';
import type { CjTableColumnProps, CjTableRequestApi } from '@cj-design/vue';
const columns: CjTableColumnProps[] = [
{ prop: 'name', label: '姓名' },
{
prop: 'status',
label: '状态',
valueEnum: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
},
{ prop: 'action', label: '操作', props: { width: 150, fixed: 'right' } },
];
const fetchList: CjTableRequestApi = async (params) => {
const res = await fetch(`/api/list?page=${params.current}&size=${params.pageSize}`);
return res.json(); // { data: { list: [], total: 0 } }
};
const handleEdit = (row: any) => {
console.log('编辑', row);
};
</script>
CjUpload 上传组件
基于 el-upload 封装的文件上传组件,提供简化的 API。
Props
| 属性 |
类型 |
默认值 |
必填 |
说明 |
| action |
string |
— |
是 |
上传的地址 |
| headers |
Record<string, string> |
— |
否 |
请求头 |
| data |
Record<string, any> |
— |
否 |
上传时附带的额外参数 |
| name |
string |
'file' |
否 |
上传的文件字段名 |
| accept |
string |
— |
否 |
接受的文件类型 |
| limit |
number |
— |
否 |
最大上传文件数 |
| multiple |
boolean |
false |
否 |
是否支持多选 |
| disabled |
boolean |
false |
否 |
是否禁用 |
| showFileList |
boolean |
true |
否 |
是否显示文件列表 |
| buttonText |
string |
'点击上传' |
否 |
按钮文字 |
| buttonType |
'primary' | 'success' | 'warning' | 'danger' | 'info' | 'default' |
'primary' |
否 |
按钮类型 |
| icon |
boolean |
true |
否 |
是否显示上传图标 |
| tip |
string |
— |
否 |
提示文字 |
| maxSize |
number |
— |
否 |
文件最大大小 |
| fileList |
any[] |
[] |
否 |
默认文件列表 |
Events
| 事件名 |
参数 |
说明 |
| success |
(response: any, file: UploadFile) |
上传成功回调 |
| error |
(error: any, file: UploadFile) |
上传失败回调 |
| exceed |
(files: File[]) |
超出文件数量限制回调 |
基本用法
<template>
<CjUpload
action="/api/upload"
:headers="{ Authorization: 'Bearer token' }"
tip="仅支持 jpg/png 文件,大小不超过 2MB"
@success="onSuccess"
/>
</template>
<script setup lang="ts">
import { CjUpload } from '@cj-design/vue';
const onSuccess = (response: any, file: any) => {
console.log('上传成功', response, file);
};
</script>
License
MIT