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

@cj-design/vue

v1.2.0

Published

Vue3 components based on Element Plus

Downloads

2,321

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';

组件文档

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