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 🙏

© 2024 – Pkg Stats / Ryan Hefner

slb_public_components

v0.0.73

Published

This is a Vue3 + ts + ELement-Plus pulic components.

Downloads

967

Readme

slb_public_components

介绍

Vue3 +ts+ELement-Plus 公用组件库

依赖的库有 vue3,ELement-Plus,windicss,wangeditor,请在系统中自行安装

配置文件(.env.xxxxx),依赖vite

需要在环境变量配置中配置以下字段

VITE_APP_CONFIG = {
    // 翻页器配置
    "page":{
        "current":1,
        "size":10
    },
    // 页码
    "pageSizes": [5,10, 20, 30, 40, 50],
    // 七牛云上传配置
    "qiniuyun":{
        // 图床地址
        "url":"https://xxx.xx.com",
        "token": {
             // 后端token校验请求头字段映射
            "requestTokenName":"token",
            // 前端获取本地token的请求头字段映射
            "getTokenName": "token"
        },
        // 获取七牛云上传token接口请求地址
        "reqUrl":"/xxxxx/xxxx/get",
        // 请求方法,默认为POST
        "method":"POST",
        // 请求参数
        "body":{},
        // 自定义请求头配置
        "headers":{
            "service":"/xxx/xx/get"
        }
    },
    // 是否滚动加载,不写就是正常分页
    "scrollRequest":{
        // 是否滚动加载
        "isScroll": false, 
        // 滚动加载获取list最后一条数据的翻页参数名称, 如果没有则使用page 的页码翻页
        "endParameterName": "id",
        // 后端接受最后一条数据的参数名称 
        "requestParameterName": "lastId"
    },
    // 分页组件位置
    'paginationPosition': '' // 'start' | 'center' | 'end'
    // 是否隐藏单页不显示分页
    "hideOnSinglePage": true,
}

MergeFormTable 组件参数及用法

用于带有搜索和表格的页面,是 PublicTable 组件和 SearchForm 组件的包装组件

<MergeFormTable
    :table-data="tablData" // form搜索菜单的配置
    :form-data="formData"  // table表格的配置
    :call-back="getList"  // 获取列表的方法
    v-model="reqParams" // 必填,搜索栏绑定的mode
    :exportExcelApi="apixxx" // 选填,页面会多一个导出Excel的按钮,
    @exportExce="exportFn" // 导出Excel按钮的返回事件,返回值为exportExcelApi请求的结果
    @selectionChange="selectionChange" //表格多选:当选择项发生变化时会触发该事件
>
    <template #customBtn> // customBtn插槽插入到搜索栏下方的自定义内容
        <el-button type="primary" @click="$router.push('/system/version/add')">添加版本类型</el-button>
    </template>
     <template #exportExcelBtn> //与导出Excel按钮同级,用于添加按钮权限
        <el-button type="success">导出Excel</el-button>
    </template>
    <template #control="{ row }">
        <el-button 
            type="primary" 
            @click="$router.push({ path: '/system/version/add', query: { id: row.id } })"
        >
            编辑版本
        </el-button>
    </template>
</MergeFormTable>
//一般情况下可以搭配获取列表的hook一起使用,下方代码就能创建一个只有显示,搜索功能的表格页面
import { useGetList } from 'slb_public_components';

// 见下方SearchForm配置
const formData: ISearchFormConfig = [
   ...
];
// 见下方PublicTable配置,如果没有特殊显示需求只用配置config
// 其余配置也可以添加,但是会覆盖hook中默认的配置
const tableConfig: ItableDataConfigProps = {
    config: [
        ...
    ]
};
const getListParam = {
    requestFn:  getRecommendGoodsList // 获取列表的api
    tableConfig: tableConfig, //table的配置
    obtainField: 'records',//返回结果参数获取字段,默认"$$$data",获取后端返回全部数据
    immediately: false,//是否立即执行函数
    //自定义回调方法,常用于处理后端返回特殊数据
    //如果涉及多层级数据应当返回 { list: AnyObject[];total: number }
    resultProcessing(v:AnyObject){
        // 只有一层时,直接返回数组
        // return v.records

        // 指定数据列表和分页数据
        return {
            list: v.page.records,
            total: v.page.total
        };
    },
    // 翻页字段顺序不变依次为:当前页数,显示条目个数,总条目数 默认从环境变量VITE_APP_CONFIG读取
    page:{
        "current": 1,
        "size": 10,
        "total":0
    },
    /**
     * 请求参数初始值,通常用于设置时间搜索默认值
     * ```ts
     * // 列子:
     *  const example:ISearchFormConfig = {
            type: 'dateTime',
            prop: 'delivery',
            label: '发货时间',
            placeholder: ['发货开始时间', '发货结束时间'],
            config: ['deliveryStartTime', 'deliveryEndTime']
        };

        const { getList, queryParams, tableData } = useGetList({
            queryParamsAdditional:{
                deliveryStartTime:"2024-12-15 08:12:56",
                deliveryEndTime:"2024-12-15 08:12:56",
            }
        });
     * 
     * ```
     */
    queryParamsAdditional:{} 

};
/**获取列表hook,注意hook内部已进行onBeforeMount初始化请求过一次列表了,具体使用方法使用时查看useGetList()函数注释*/
const { getList, queryParams, tableData } = useGetList(getListParam);

使用 MergeFormTable 组件时是否使用 useGetList 这个 hook 看实际项目中的情况并不是必须的只是为了减少代码量 主要差别在于:

  1. 需要将 tableConfig 配置书写完整
  2. 需要自定义 queryParams 对象属性
  3. 需要自定义获取列表函数

PublicTable 组件参数及用法

    <PublicTable
        :tableData="tableData"
        @handlePageChange="handlePageChange" //点击分页回调
        @SelectionChange="SelectionChange" //表格多选结果回调
    >

        <template #name="{ row, column, $index }">
            <el-button>{{ row.name }}</el-button>
        </template>
    </PublicTable>
    const tableData:ItableDataProps = {
        loading: false, //加载动画
        attrs: {} // table 属性方法,
        defaultConfig: {
            //是否开启多选
            selection: true,
            //是否开启数字展示
            index: true 
            // 表头和内容都居中展示
            allAlignCenter: true; 
            // 自动计算表头宽度
            isAutoHeaderWidth: true; 
            // 返回值用来决定这一行的 CheckBox 是否可以勾选
            selectable: (row: AnyObject, index: number) => boolean; 
        },
        config: [
            {
                prop: 'name', //表格对应字段,如果type为slot时也是插槽名
                label: '日期', //表格对应字段中文描述
                width: '130', //表格单个格子宽度
                type: 'slot' // 插槽类型,在html标签中自定义样式
                ShowFn: () => false // 是否显示该列
            },
            {
                prop: 'status',
                label: '活动状态',
                type: 'switch', // 使用开关
                options: {
                    activeValue: 0, //自定义参数值 打开状态
                    inactiveValue: 1 //自定义参数值 关闭状态
                },
                //开关切换回调方法
                callBack(v: any) {
                    console.log(v);
                }
            },
            {
                prop: 'address',
                label: '地址',
                // 用于表格的回显
                formatter(val: any) {
                    return val.province + val.city + val.district + val.address;
                }
            },
            // 排序
            {
                type: 'money',
                prop: 'money',
                sort: {
                    method: (a, b) => a.money - b.money
                },
                label: '金额'
            },
            {
                prop: 'url',
                label: '图片',
                type: 'img' //使用图片
            },
            {
                prop: 'time',
                label: '开始时间',
                type: 'time' // 自动处理显示时间为YYYY-MM-DD HH:mm:ss
            },
            {
                prop: 'money',
                label: '现金',
                type: 'money' // 后端返回金额单位为分,处理数据为元进行显示
            },
            {
                prop: 'id',
                label: 'id', // 不做任何处理直接显示后端返回数据
            },
            // 多级表头
            {
                type: 'column',
                label: '伙人',
                children: [
                    {
                        label: '钱',
                        type: 'column',
                        children: [
                            {
                                prop: 'address',
                                label: '分',
                                type: 'slot'
                            },
                            {
                                prop: 'name',
                                label: '源'
                            },
                            {
                                type: 'column',
                                label: '金额',
                                children: [
                                    {
                                        type: 'img',
                                        prop: 'url',
                                        label: '开盘价'
                                    },
                                    {
                                        type: 'money',
                                        prop: 'money',
                                        label: '价'
                                    },
                                    {
                                        type: 'slot',
                                        prop: 'name',
                                        label: '源来的'
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        prop: 'city',
                        label: '动态'
                    }

                ]
            }
        ],
        // 为table树形结构时才设置tree
        tree:{
                defaultExpandAll: true, // 是否默认展开
                treeProps: { children: 'children', hasChildren: 'hasChildren' }, // 字段设置
                lazy: false, // 是否异步展开子级
                rowKey:"id", // key的键
                load: ()=> {}, // 异步方法
        },
        page: {
            page_index: 1, //当前分页页码
            page_size: 10, //当前分页展示条数
            total: 0 //总数
        },
        //后端返回的数据
        data: []
    };

SearchForm 组件参数及用法

    <SearchForm :form-data="data" :v-model=defaultValue>

        <template #d>
            <el-button>{{ 11111 }}</el-button>
        </template>
    </SearchForm>
    // 表单mode用于请求的对象,这里面的默值对应dateTime中的config的字段名就行能实现默认时间
    const defaultValue = ref({createStartTime: '时间',createEndTime: '时间'}) 
    const data:ISearchFormConfig = [
        /** input输入框 */
        {
            prop: 'ab', //对应mode中字段
            label: '兴趣:', //表单label,标题
            type: 'ipt', //组件类型
            placeholder: '请输入兴趣',// 支持placeholder的el组件
            labelWidth:80 //label宽度
        },
        /** 条件显示 */
        {
            prop: 'abc',
            label: '兴趣:',
            type: 'ipt',
            placeholder: '请输入兴趣',
            labelWidth:80,
            showFn: (v: any) => {  // 条件显示这个组件v其实就是defaultValue
                return v.ab ? false : true
            }
        },
        /** 日期范围选择器 */
        // dateTime类型比较特殊
        // 1,如果后端接受的数据为一个字段时:数据格式['时间xx','时间xx']可以直接填入prop,此时prop就能直接使用,用于后端请求数据
        // 2,如果后端需要接受的参数是两个属性,就需要在config中填入两个属性名第一个是开始时间,第二个为结束时间,
        {
            prop: 'e',
            label: '日期:',
            type: 'dateTime',
            placeholder: ['开始日期', '结束日期'] //自定义placeholder
            config: ['createStartTime','createEndTime'] // 当需要将数组解析为两个字段时的参数
        },
        /** 日期选择器 */
        {
            prop: 'eqq',
            label: '日期:',
            type: 'date',
            placeholder: '选择日期'
        },
        /** 级连选择器 */
        {
            prop: 'eerr',
            label: '日期:',
            type: 'cascader',
            placeholder: '选择日期',
            cascaderData: treeData,
            cascaderOptions: {
                showAllLevels: false, //仅显示最后一级,false为显示
                multiple: false, //开启多选
                checkStrictly: true, //选择任意一级选项
                emitPath: false, //选择是否为数组格式
                value: "val", //自定义对象的某个属性值
                label: "name", //自定义对象的某个字段
                children: "chilieMenu" //自定义对象子级名称
            }
        },
        /** 下拉框用法一 */
        {
            prop: 'c',
            label: '选择:',
            type: 'select',
            placeholder: '请选择',
            /**下拉框参数,{自定义:自定义} 需要自己设置,需要添加到下面config与数组中保持一致 */
            options: [
                {
                    val: '1',
                    name: 'Option1'
                },
                {
                    val: '2',
                    name: 'Option2'
                },
                {
                    val: '3',
                    name: 'Option3'
                },
                {
                    val: '4',
                    name: 'Option4'
                }
            ],
            config: ['val', 'name']
        },
        /** 下拉框用法二 */
        {
            prop: 'c',
            label: '选择:',
            type: 'select',
            placeholder: '请选择',
            /** 返回一个异步函数  */
            options:async ()=>([]),
            /**下拉框参数,{自定义:自定义} 需要自己设置,需要添加到下面config与数组中保持一致 */
            config: ['val', 'name']
        },
        /** 级联选择器 */
        {
            type: 'cascader',
            prop: 'deliveryType3',
            label: '配送方式3',
            placeholder: '请选择配送方式',
            options: async ()=>([]) || [{id:123, name: '张三',children:[id:23, name: '张三',]}],
            cascaderOptions: {
                showAllLevels: true, // 输入框中是否显示选中值的完整路径
                multiple: true, // 开启多选
                checkStrictly: true, // 选择任意一级选项
                emitPath: true, // 选择是否为数组格式
                value: 'id', // 自定义对象的某个属性值
                label: 'name', // 自定义对象的某个字段
                children: 'children' // 自定义对象子级名称
            }
        },
        /**自定义组件 */
        {
            prop: 'd',
            label: 'xx'
            type: 'slot' // 为插槽时prop就是插槽名,可以自定义样式
        },
        //icon组件名称,可自定义(参考:https://element-plus.org/zh-CN/component/icon.html#icon-collection)
        {
            type: 'search',
            icon: 'Search',
            /** 参数值为整个f/orm表单输入值 */
            event: (v) => {
                console.log(v);
            }
        },
        {
            type: 'reset',
            icon: 'Refresh',
            event: (v) => {}
        }
    ];

SForm 组件参数及用法

<SForm ref="formRef" :options="options" label-width="100px" v-mode="formData">
    <template #slot>
        <el-button size="small" type="primary">上传</el-button>
    </template>
</SForm>
    // 组件配置
    Attributes: {
        options: [] //菜单配置必传
        allTextNullReplace: string // 默认为空字符串,当为text组件时值为空时,组件会自动将所有空值替换为空字符串,
        modelValue: []// form组件的mode,必传
        isDetails: false //是否在详情页展示为true时,可通过h插槽定义标题,f插槽定义底部按钮
        formWidth: 100% // 控制整个表单宽度
        resetSaveFormItemValue: false // 重置表单时是否保留mode的初始值,
        EliminateUnnecessaryParameter: false // 提交时是否剔除掉和options配置中prop无关的属性,为true只保留options中配置的prop属性
        isDeepCopy: false // 是否开启深拷贝,为true时,mode的初始值会进行深拷贝,防止mode被修改
        isDynamicChildren: false // // 是否根据modelValue改变时重新渲染子元素
        // 注意: el-from本身拥有的属性也可直接配置参考https://element-plus.gitee.io/zh-CN/component/form.html#form-attributes
    }
// 内置有默认的七牛云上传方法,如果项目里不是七牛云或者通过后端上传的请自定义方法
import { useQiniuUpload } from 'slb_public_components';
const formData = ref<AnyObject>({});
// 注意: 当涉及到动态修改配置时请使用ref或者计算属性
let options: ISFormConfig = [
    // 正常组件使用
  {
    type: 'input', // 组件根据element-plus组件去掉el
    label: '用户名', // lable名称
    prop: 'username', // 组件双向绑定的值,输入后在formData中获取值
    textNullReplace: '--' // text组件时候为空时的显示内容
    rules: [ // 校验方法
      { required: true, message: '用户名不能为空', trigger: 'blur' },
      { min: 2, max: 6, message: '用户名长度为2-6位', trigger: 'blur' },
    ],
    attrs: { // 这里可以配置element-plus中所有对应组件的Attributes
      clearable: true
    },
    showFn(val: any) { // 传入方法通过条件进行显隐
        return val.role ? false : true
    }
  },
  // select组件使用方法1
  {
    type: 'select',
    placeholder: '请选择',
    label: '职位',
    prop: 'role',
    attrs: {
      style: {
        width: '100%',
      },
    },
    rules: [
      { required: true, message: '职位不能为空', trigger: 'change' }
    ],
    childrenConfig: {
        type: 'option',
        props: {
            label: 'label',
            value: 'value';
        }
    }
    children: [
      {
        label: '经理',
        value: '1'
      },
      {
        label: '总裁',
        value: '2'
      },
      {
        label: 'CEO',
        value: '3'
      },
    ]
  },
  // select组件使用方法2
  {
    type: 'select',
    placeholder: '请选择',
    label: '职位',
    prop: 'role',
    attrs: {
      style: {
        width: '100%',
      },
    },
    rules: [
      { required: true, message: '职位不能为空', trigger: 'change' }
    ],
    children: [
      {
        type: 'option',
        label: '经理',
        value: '1'
      },
      {
        type: 'option',
        label: '总裁',
        value: '2'
      },
      {
        type: 'option',
        label: 'CEO',
        value: '3'
      },
    ]
  },
  // select组件使用方法3
   {
    type: 'select',
    placeholder: '请选择',
    label: '职位',
    prop: 'role',
    attrs: {
      style: {
        width: '100%',
      },
    },
    rules: [
      { required: true, message: '职位不能为空', trigger: 'change' }
    ],
    childrenConfig: {
        type: 'option',
        props: {
            label: 'label',
            value: 'value';
        }
    }
    children: async ()=>([]) //返回一个异步函数
  },
  // checkbox-group
  {
    type: 'checkbox-group',
    value: [],
    prop: 'like',
    label: '爱好',
    rules: [
      { required: true, message: '爱好不能为空', trigger: 'change' }
    ],
    children: [
      {
        type: 'checkbox',
        label: '篮球',
        value: '1',
      },
      {
        type: 'checkbox',
        label: '足球',
        value: '2',
      },
    ]
  },
  // radio-group
    {
        type: 'radio-group',
        prop: 'terminalType',
        label: '终端类型:',
        children: [
            {
                type: 'radio',
                value: 'ANDROID',
                label: '安卓'
            },
            {
                type: 'radio',
                value: 'IOS',
                label: '苹果'
            }
        ],
        rules: [{ required: true, message: '请选择终端类型', trigger: 'change' }]
    },
    // upload 自定义的uploadImage组件attrs配置见uploadImage组件
  {
    type: 'upload',
    label: '上传',
    prop: 'avatar',
    rules: [
      { required: true, message: '图片不能为空', trigger: 'change' }
    ],
    attrs: {
      ...
    },
    uploadFn: useQiniuUpload().qiniuUplaod // 上传图片组件必须传入上传方法
  },
  // 文字显示
  {
    type: 'text',
    label: '文字显示',
    prop: 'text',
  }
  // 富文本
  {
    type: 'editor',
    label: '富文本',
    prop: 'editor',
    uploadFn: useQiniuUpload().qiniuUplaod // 富文本组件必须传入上传方法
  }
  // 自定义组件,当使用特殊样式和该组件不支持的组件时使用插槽插入
  {
    type: 'slot',
    label: '自定义组件',
    prop: 'slot',
  }
]
// 通过ref 可以获取到表单的resetFields: 重置方法和validate()返回拷贝后的值: 校验方法然后进行后续操作
const formRef = ref<SFomInstance>();

ImageUpload 组件

<ImageUpload v-model="formData.url" :limit="1" :uploadFn: useQiniuUpload().qiniuUplaod ></ImageUpload>

// 内置有默认的七牛云上传方法,如果项目里不是七牛云或者通过后端上传的请自定义方法
import { useQiniuUpload } from 'slb_public_components'; 

// 组件配置
Attributes: {
    uploadFn: useQiniuUpload().qiniuUplaod; // 必传,或者自定义方法
    modelValue: xx; //接受上传图片返回的值,必传
    multiple: false; // 是否多选,也就是一次性选取多张同时上传
    limit: 1; //数量限制,当为0时只用作图片预览
    fileSize: 5; // 图片大小
    fileType: ['png', 'jpg', 'jpeg']; // 可接收的文件格式
    isShowTip: true; // 是否显示下方提示信息
}
// emit 事件
const emit = defineEmits({
    'update:modelValue': (v: string[] | string) => typeof v === 'string' || Array.isArray(v),
    'uploadSuccess': null,
    'removeIndex': (index: number) => typeof index === 'number'
});