@cj-design/vue
v1.0.9
Published
Vue3 components based on Element Plus
Readme
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';组件文档
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>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;
}Events
| 事件名 | 参数 | 说明 |
| --- | --- | --- |
| update:modelValue | (value: Record<string, any>) | 表单值变更 |
| search | (params: Record<string, any>) | 点击搜索 |
| reset | — | 点击重置 |
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 | 字段名 |
| label | string | 列标题 |
| props | Record<string, any> | 列额外配置,透传给 el-table-column |
| valueEnum | { label: string; value: any }[] | 值枚举,用于自动映射显示文本 |
| search | any | 搜索配置(CjProTable 使用) |
请求相关类型
// 请求参数
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>CjProTable 高级表格组件
集成了 CjSearch + CjTable 的高级表格组件,通过统一的列配置同时生成搜索表单和数据表格。
Props
继承 CjTable 的所有 Props(columns 类型升级为 CjProTableColumnProps[]),额外新增:
| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| columns | CjProTableColumnProps[] | [] | 列配置(含搜索配置) |
| searchProps | Record<string, any> | {} | 透传给 CjSearch 的额外 props |
CjProTableColumnProps等同于CjSearchColumnProps,即在CjTableColumnProps基础上增加了search字段。
只有配置了search的列才会出现在搜索表单中。
Events
| 事件名 | 参数 | 说明 |
| --- | --- | --- |
| search | (params: CjTableRequestParams) | 搜索时触发 |
| reset | — | 重置时触发 |
| update:data | (data: any[]) | 数据更新时触发 |
Expose Methods
| 方法名 | 说明 | | --- | --- | | refresh | 刷新数据(保持当前分页) | | reload | 重新加载(重置到第一页) | | getParams | 获取当前请求参数 | | tableRef | 内部 CjTable 的 ref |
Slots
| 插槽名 | 说明 | | --- | --- | | toolbar | 工具栏区域(左侧) | | toolbar-left | 工具栏左侧 | | toolbar-right | 工具栏右侧 | | table | 自定义渲染整个表格(透传给 CjTable) | | [col.prop] | 自定义列内容(透传给 CjTable) |
基本用法
<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>License
MIT
