企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 一、基本介绍 本组件库为 EE CMS 移动组件库,基于 vant 2.8.7 版本二次封装 # 二、适用范围 - 基于 KeepFe 开发的 CMS H5 应用,风格请参考移动 OA # 三、安装 step1. `npm i @keepfe/plugin-vant-ui -S` step2. 在 `layout/index.html` 中,导入框架的依赖: ``` {% block head %} <script src="https://staticweb.keepcdn.com/fecommon/package/moment@2.27.0/dist/moment.min.js"></script> <script src="https://staticweb.keepcdn.com/fe/commons/js/js-cookie-2.2.0.min.js"></script> <script src="https://staticweb.keepcdn.com/fecommon/package/vue@2.5.17/dist/vue.min.js"></script> <script src="https://staticweb.keepcdn.com/fecommon/package/vant@2.8.7/vant/vant.min.js"></script> <link rel="stylesheet" href="https://staticweb.keepcdn.com/fecommon/package/vant@2.8.7/vant/index.css"> {% endblock %} ``` step3. 在 `kfe-entries/pack.js` 中 的 `client.injectResolve` 方法内添加以上 externals: ```js injectResolve: function(conf) { conf.externals({ 'js-cookie': 'Cookies', 'vue': 'Vue', 'vant': 'vant', 'moment': 'moment', }) }, ``` > 强烈建议项目本身所依赖的第三方框架、插件通过 externals + 外链的方式引入,以优化构建体积大小和加载速度。 step4. 在 `kfe-entries/entry.js` 中,加载 `plugin-vant-ui` 样式文件: ``` import '@keepfe/plugin-vant-ui/lib/vant-ui.min.css' ``` # 四、组件列表 - DatetimePicker 日期时间选择组件 - ImgUpload 图片上传、预览组件 - Loading 加载提示组件 - FooterButton 页面底部操作按钮组 - Steps 步骤条组件 - Form 表单组件 - FormItem 表单项组件 - ApproveLine 审批线展示组件 - FormList 表单列表组件 - FormDetail 表单详情组件 # 五、使用方法 ## 基础组件 #### DatetimePicker 基于 `vant.datetime-picker` 封装,可自定义日期格式和日期项显隐 ```html <template> <datetime-picker title="日期时间选择器" v-model="datetimes" @on-confirm="onConfirm" /> </template> ``` ```vue import { DatetimePicker } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { DatetimePicker }, data() { return { datetimes: new Date() } }, methods: { onConfirm(v, i) { console.log(v, i) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ value | 日期值| date/string | '' tittle | 顶部栏标题,同 `vant.datetime-picker.title` | string | '' formatter | 选项格式化函数,同 `vant.datetime-picker.formatter` | function | - columnsOrder | 自定义列排序数组,同 `vant.datetime-picker.columnsOrder` | [string] | - hideLine | 需要隐藏的列,支持 1-5,若不在该范围内,则显示全部列 | number | 5(默认隐藏分钟) 方法 | 说明 ----|----- on-confirm | 点击完成按钮时触发的事件,同 `vant.datetime-picker.confirm` on-cancel | 点击取消按钮时触发的事件,同 `vant.datetime-picker.cancel` #### ImgUpload 基于 `@keepfe/plugin-upload.qiniu-uploader` 封装,支持图片上传、预览、删除 ```html <template> <img-upload v-model="imgs" /> </template> ``` ```vue import { ImgUpload } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { ImgUpload }, data() { return { imgs: [] } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ value | 图片组| [string] | [] thumbnail | 图片缩略图配置 | object | { width: 60, height: 60 } hasDelete | 是否展示删除按钮 | boolean | true openLoading | 上传图片是是否展示加载按钮 | boolean | false canAdd | 是否可以上传图片 | boolean | true disabled | 是否禁用 | boolean | false 方法 | 说明 ----|----- on-success | 图片上传成功后触发,返回包装后的图片上传对象 on-error | 图片上传失败时触发,返回错误信息 #### Loading 基于 `vant.loading` 封装,支持遮罩层 ```html <template> <loading :loading="isLoading"/> </template> ``` ```vue import { Loading } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Loading }, data() { return { isLoading: true } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ loading | 是否展示 | boolean | false type | 类型,同 `vant.loading.type` | string | circular hasMask | 是否有遮罩层 | boolean | false touchable | 在 loading 状态下是否可以点击其他元素 | boolean | false #### FooterButton 页面底部操作按钮组,用于审批、详情页操作 ```html <template> <FooterButton> <ButtonOne text="审批"/> </FooterButton> </template> ``` ```vue import { FooterButton } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FooterButton, ButtonOne: FooterButton.ButtonOne } } ``` ##### FooterButton:无属性与方法 ##### FooterButton.ButtonOne: 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ text | 按钮文字 | string | '' icon | 按钮图标,接收完整图片路径 | string |'' colors | 颜色配置 | object |{ background: 'white', font: '#333' } flex | 同 `css.flex.flex` 属性,在整个按钮组中的占比 | number | 1 separator | 右侧是否展示分隔符 | boolean | false disabled | 是否禁用 | boolean | false className | 自定义类名 | string |'' #### Steps 重写 `vant.steps`,提供全新的样式和扩展支持 ```html <template> <Steps :active="1"> <Step>步骤1</Step> <Step>步骤2</Step> <Step>步骤3</Step> </Steps> </template> ``` ```vue import { Steps } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Steps, Step: Steps.Step } } ``` ##### Steps: 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ active | 当前步骤 | number | - ##### Steps.Step:无属性与方法 #### Form 基于 `vant.form` 封装,靠拢 `iview.form` API ```html <template> <Form ref="form" :rules="rules" :model="form" > <FormItem v-model="form.name" type="input" label="姓名" prop="name" /> </Form> </template> ``` ```vue import { Form, FormItem } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Form, FormItem }, data() { return { form: { name: '' }, rules: { name: { required: true, message: '请输入姓名' } } } }, methods: { submit() { this.$refs.form.validate(valid => { console.log(valid) }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ labelWidth | 表单整体名称的长度,用法同 `iview.form.label-width` | string/number | - rules | 表单校验规则,用法与 `iview.form.rules` 相同 | object | - model | 表单数据对象,用法与 `iview.form.model` 相同 | object | - #### FormItem 基于 `vant.field` 封装,靠拢 `iview.form-item` API,请结合 `Form` 组件使用 ```html <template> <Form ref="form" :rules="rules" :model="form" > <FormItem v-model="form.name" type="input" label="姓名" prop="name" /> <FormItem v-model="form.password" type="input" type="password" label="password" /> <FormItem v-model="form.remark" type="textarea" label="备注" /> <FormItem v-model="form.sex" type="radio" label="单选框" :data="[{ id: 'male', name: '男' }, { id: 'female', name: '女' }]" prop="sex" /> <FormItem v-model="form.date" type="datetime" label="时间选择器" :picker-info="{ name: 'datetime', title: '日期选择框' }" prop="datetime" /> <FormItem v-model="form.type" type="picker" label="选择器" :picker-info="{ name: 'picker', message: '请选择内容', title: '选择器' }" :data="list" prop="country" /> <FormItem v-model="form.images" type="upload" label="图片上传" /> <FormItem type="custom" label="自定义组件"> <van-rate v-model="form.custom" /> </FormItem> </Form> </template> ``` ```vue import { Form, FormItem } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Form, FormItem }, data() { const validator = (r, v, c) => { if(!v) { c(new Error('请选择性别')) } c() } return { form: { name: '', sex: '', date: null, type: '' }, rules: { name: { required: true, message: '请输入姓名' }, sex: { required: true, message: '请选择性别', validator }, date: { required: false } }, list: [{ id: 0, name: 'beijing' }, { id: 1, name: 'shanghai' }] } }, methods: { submit() { this.$refs.form.validate(valid => { console.log(valid) }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ type | 表单组件类型 | string | '' label | 表单名称 | string | '' labelWidth | 表单项名称的长度,用法同 `iview.form-item.labelWidth` | string/number | - value | 表单值 | string/number/array/date |- data | type 为 radio/picker 时使用,配置数据源 |array/object |{} placeholder | 表单提示信息 | string | '' pickerInfo | type 为 datetime/picker 时使用,配置 picker 信息 | object | {} hasArrow | 右侧是否展示箭头 | boolean | false rules | 表单项校验规则,用法同 `iview.form-item.rules` | object | {} disabled | 表单项是否禁用 | boolean | false prop | 对应 v-model 的名称,form 表单会根据该属性执行相应的 rules,当 type 为 picker 或 datetime 时,必填,以获取 `vant.picker` 实例 | string | - 方法 | 说明 ----|----- on-click | 表单项的点击事件,需要 disabled 为 false 并且 type 不为 picker/datetime on-change | 表单值发生改变时触发,返回当前的表单值,需要 type 为 picker type 值: - input - tel - digit - password - number - radio - picker - datetime - textarea - upload - custom PickerInfo 配置: * title: picker 标题 * message: type 为 picker 时,当没有选值的时候,点击「确定」按钮时的提示 ## 业务组件 #### ApproveLine 审批线展示组件,用于表单详情页展示审批信息 ```html <template> <ApproveLine :data="process" /> </template> ``` ```vue import { ApproveLine } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { ApproveLine }, data() { return [{ activityType: 'startEvent', assignee: '发起人 xxx', endTime: 'xxxx-xx-xx xx:xx:xx' }, { assignee: '直属上级 xxx', approveStatusName: '审批中', endTime: 'xxxx-xx-xx xx:xx:xx', approving: true, comments: [{ userId: 'ldapusername', message: 'xxxx', time: 'xxxx-xx-xx xx:xx:xx' }] }, { activityType: 'endEvent', assignee: '二级部门负责人 xxx', endTime: 'xxxx-xx-xx xx:xx:xx' }] } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ data | 审批线数据 | array | [] ##### Data 属性配置见下: * activityType: 节点类型,可为 startEvent(开始节点,标题为“开始节点”),endEvent(结束节点,标题为“结束节点”)或空(中间节点,标题取自 assignee) * assignee:当节点类型为中间节点时,节点的标题 * approveStatusName:审批状态名称 * endTime:审批操作时间 * approving:是否正在审批 * comments:备注信息,见下: ##### Comments: * userId:备注人 * message:备注信息 * time:备注时间 #### FormList 以配置的方式快速渲染表单列表页 ```html <template> <FormList :module="module" :render="render" @on-load="handleLoad" @on-next-page="handleNextPage" @on-search="handleSearch" @on-row-click="handleRowClick"/> </template> ``` ```vue import { FormList } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FormList }, data() { return { module: { listLoading: true, condition: {}, pagination: { pageSize: 5, total: 0, current: 1 }, finished: false, list: [] }, render: data => ({ title: '列表标题', color: '#71c7ac', date: data.createdTime, user: data.creatorId, status: { text: '待处理', color: '#68b1ed' }, column: [{ label: '工单号', text: data.code }, { label: '预计完结时间', text: data.estimateDoneTime }, { label: '问题分类', text: data.probTypeName }, { label: '问题描述', text: data.probDesc }] }) } }, methods: { handleLoad() { setTimeout(() => { this.module.list = [{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }] this.module.pagination.total = 5 this.module.listLoading = false }, 1000) }, handleNextPage(n) { setTimeout(() => { this.module.list = this.module.list.concat([{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }]) this.module.pagination.total = 7 this.module.finished = true }, 1000) }, handleSearch() { this.module.list = [{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }] this.module.pagination.current = 1 this.module.pagination.total = 1 }, handleRowClick(index) { console.log(index) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ module | 列表数据模型,见下 | object |{} searchHolder | 搜索提示文字 | string | '搜索单号' searchText | 搜索按钮文字 | string | '搜索' render | 列表项渲染规则,见下| function | - 方法 | 说明 ----|----- on-load | 列表初始化、加载下一页时触发 on-next-page| 加载下一页时触发,返回新页码 on-search| 点击搜索按钮时触发 on-row-click | 点击列表项时触发,返回该项在列表中的索引 ##### Module 模型 * listLoading: 列表是否处于加载状态 * condition: 搜索信息 ```js { query: string, // 搜索关键字 approveStatus: number, // 审批状态,1 待审批 2 已审批 } ``` * pagination: 分页信息 ```js { pageSize: number, // 每页条数 total: number, // 总条数 current: number, // 当前页 } ``` * finished:是否已加载到最后一页 * list:列表数据 ##### Render 规则 * title:列表项标题 * user:用户名 * date: 提单日期 * color:主体颜色 * status: 状态信息 ```js { text: string, // 状态文字 color: string, // 状态颜色 } ``` * column 表单信息数据渲染列表 ```js [{ label: string, // 数据标题, value: any, // 数据值 }] ``` #### FormDetail 以配置的方式快速渲染表单详情页 ```html <template> <FormDetail :loading="false" :form="form" :render="render"> <template #buttonGroup> <FooterButton> <ButtonOne text='取消' :colors="{ font: 'white', background: '#ff4f4f' }"/> <ButtonOne text='提交' :colors="{ font: 'white', background: '#68b1ed' }"/> </FooterButton> </template> </FormDetail> </template> ``` ```vue import { FormDetail, FooterButton } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FormDetail, FooterButton, ButtonOne: FooterButton.ButtonOne }, data() { return { // 服务端返回 form: { code: 1, name: 2, attachments: [{ path: 'https://static1.keepcdn.com/newoa/2021/02/26/10/23/8da380e1c5e110cd206fa475fe6e828b17a1e6ec_159x159_f32797289f461caf69bf67200faf37a47ac8283d.png', name: '附件1', key: 'group1/M00/00/BB/rBQF6V7p58GATUiKAALoQbbcoqU373' }], flow: [{ 'activityType': 'startEvent', 'approving': false, 'approveStatusName': null, 'assignee': null, 'comments': null, 'endTime': '2020-05-18 19:23:13', }, { 'activityType': 'userTask', 'approving': false, 'approveStatusName': '已通过', 'assignee': 'qinchuan', 'comments': [{ 'message': '同意', 'time': 1589801048956, 'userId': 'qinchuan' }, { 'message': '同意111', 'time': 1589801048956, 'userId': 'zhouximin01' }], 'endTime': '2020-05-18 19:24:08', }, { 'activityType': 'endEvent', 'approving': true, 'approveStatusName': null, 'assignee': null, 'comments': null, 'endTime': '2020-05-18 19:24:08' }], notices: ['qinchuan', 'zhouximin01'] }, render: data => ({ title: '详情信息', formTitle: '基本信息', user: 'qinchuan', watermark: { show: true, url: FormDetail.watermark.WATERMARK_AGREE }, approveLine: { show: true, key: 'flow', title: '审批线' }, attachments: { show: true, key: 'attachments', title: '图片' }, notices: { show: true, key: 'notices', title: `已通知 ${data.notices.length} 人` }, column: [{ label: 'code', text: data.code }, { label: 'name', text: data.name }] }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ loading | 数据是否加载中 | boolean | true form | 表单数据 | object | {} render | 渲染规则,见下| function | - ##### Render 规则 * title:页面标题 * formTitle:表单信息标题 * user:表单信息主体用户 * watermark 水印模块配置 ```js { show: boolean, // 是否展示审批状态水印 url: string, // 水印链接,可直接使用 FormDetail.watermark 提供的水印,或自定义 } ``` * attachments 附件模块配置 ```js { show: boolean, // 是否展示附件模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * approveLine 审批线模块配置 ```js { show: boolean, // 是否展示审批线模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * notices 告知模块配置 ```js { show: boolean, // 是否展示告知模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * column 表单信息数据渲染列表 ```js [{ label: string, // 数据标题, value: any, // 数据值 }] ``` # 六、扩展指南 1. 运行安装命令,`npm i` ,安装所有依赖 2. 绑定测试域名 ```shell > sudo vim /etc/hosts # 增加一项 127.0.0.1 local.dev.gotokeep.com ``` ## 基本配置 在 package.json 文件中有组件库的基本信息,包括 git、名称、标签前缀等 - 规范好 namefix ## 开发组件 > 注意事项 1. 组件的开发避免使用在ssr端可以执行的生命周期,比如 beforecreate 和 created 等 2. 组件规范要符合vue官方规范 https://cn.vuejs.org/v2/style-guide/ ### 1. 开发组件 1. 运行开发环境 `npm run dev` , 一定不能忘记, 打开 url: http://local.dev.gotokeep.com:8081/ 预览 2. 修改组件配置 - 修改文件 `components/list`, 按照格式增加组件 compxxx - `isGlobal`代表是否需要绑定到vue全局,比如toast组件 - `notShow`代表是否不展示到示例列表中# 一、基本介绍 本组件库为 EE CMS 移动组件库,基于 vant 2.8.7 版本二次封装 # 二、适用范围 - 基于 KeepFe 开发的 CMS H5 应用,风格请参考移动 OA # 三、安装 step1. `npm i @keepfe/plugin-vant-ui -S` step2. 在 `layout/index.html` 中,导入框架的依赖: ``` {% block head %} <script src="https://staticweb.keepcdn.com/fecommon/package/moment@2.27.0/dist/moment.min.js"></script> <script src="https://staticweb.keepcdn.com/fe/commons/js/js-cookie-2.2.0.min.js"></script> <script src="https://staticweb.keepcdn.com/fecommon/package/vue@2.5.17/dist/vue.min.js"></script> <script src="https://staticweb.keepcdn.com/fecommon/package/vant@2.8.7/vant/vant.min.js"></script> <link rel="stylesheet" href="https://staticweb.keepcdn.com/fecommon/package/vant@2.8.7/vant/index.css"> {% endblock %} ``` step3. 在 `kfe-entries/pack.js` 中 的 `client.injectResolve` 方法内添加以上 externals: ```js injectResolve: function(conf) { conf.externals({ 'js-cookie': 'Cookies', 'vue': 'Vue', 'vant': 'vant', 'moment': 'moment', }) }, ``` > 强烈建议项目本身所依赖的第三方框架、插件通过 externals + 外链的方式引入,以优化构建体积大小和加载速度。 step4. 在 `kfe-entries/entry.js` 中,加载 `plugin-vant-ui` 样式文件: ``` import '@keepfe/plugin-vant-ui/lib/vant-ui.min.css' ``` # 四、组件列表 - DatetimePicker 日期时间选择组件 - ImgUpload 图片上传、预览组件 - Loading 加载提示组件 - FooterButton 页面底部操作按钮组 - Steps 步骤条组件 - Form 表单组件 - FormItem 表单项组件 - ApproveLine 审批线展示组件 - FormList 表单列表组件 - FormDetail 表单详情组件 # 五、使用方法 ## 基础组件 #### DatetimePicker 基于 `vant.datetime-picker` 封装,可自定义日期格式和日期项显隐 ```html <template> <datetime-picker title="日期时间选择器" v-model="datetimes" @on-confirm="onConfirm" /> </template> ``` ```vue import { DatetimePicker } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { DatetimePicker }, data() { return { datetimes: new Date() } }, methods: { onConfirm(v, i) { console.log(v, i) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ value | 日期值| date/string | '' tittle | 顶部栏标题,同 `vant.datetime-picker.title` | string | '' formatter | 选项格式化函数,同 `vant.datetime-picker.formatter` | function | - columnsOrder | 自定义列排序数组,同 `vant.datetime-picker.columnsOrder` | [string] | - hideLine | 需要隐藏的列,支持 1-5,若不在该范围内,则显示全部列 | number | 5(默认隐藏分钟) 方法 | 说明 ----|----- on-confirm | 点击完成按钮时触发的事件,同 `vant.datetime-picker.confirm` on-cancel | 点击取消按钮时触发的事件,同 `vant.datetime-picker.cancel` #### ImgUpload 基于 `@keepfe/plugin-upload.qiniu-uploader` 封装,支持图片上传、预览、删除 ```html <template> <img-upload v-model="imgs" /> </template> ``` ```vue import { ImgUpload } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { ImgUpload }, data() { return { imgs: [] } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ value | 图片组| [string] | [] thumbnail | 图片缩略图配置 | object | { width: 60, height: 60 } hasDelete | 是否展示删除按钮 | boolean | true openLoading | 上传图片是是否展示加载按钮 | boolean | false canAdd | 是否可以上传图片 | boolean | true disabled | 是否禁用 | boolean | false 方法 | 说明 ----|----- on-success | 图片上传成功后触发,返回包装后的图片上传对象 on-error | 图片上传失败时触发,返回错误信息 #### Loading 基于 `vant.loading` 封装,支持遮罩层 ```html <template> <loading :loading="isLoading"/> </template> ``` ```vue import { Loading } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Loading }, data() { return { isLoading: true } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ loading | 是否展示 | boolean | false type | 类型,同 `vant.loading.type` | string | circular hasMask | 是否有遮罩层 | boolean | false touchable | 在 loading 状态下是否可以点击其他元素 | boolean | false #### FooterButton 页面底部操作按钮组,用于审批、详情页操作 ```html <template> <FooterButton> <ButtonOne text="审批"/> </FooterButton> </template> ``` ```vue import { FooterButton } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FooterButton, ButtonOne: FooterButton.ButtonOne } } ``` ##### FooterButton:无属性与方法 ##### FooterButton.ButtonOne: 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ text | 按钮文字 | string | '' icon | 按钮图标,接收完整图片路径 | string |'' colors | 颜色配置 | object |{ background: 'white', font: '#333' } flex | 同 `css.flex.flex` 属性,在整个按钮组中的占比 | number | 1 separator | 右侧是否展示分隔符 | boolean | false disabled | 是否禁用 | boolean | false className | 自定义类名 | string |'' #### Steps 重写 `vant.steps`,提供全新的样式和扩展支持 ```html <template> <Steps :active="1"> <Step>步骤1</Step> <Step>步骤2</Step> <Step>步骤3</Step> </Steps> </template> ``` ```vue import { Steps } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Steps, Step: Steps.Step } } ``` ##### Steps: 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ active | 当前步骤 | number | - ##### Steps.Step:无属性与方法 #### Form 基于 `vant.form` 封装,靠拢 `iview.form` API ```html <template> <Form ref="form" :rules="rules" :model="form" > <FormItem v-model="form.name" type="input" label="姓名" prop="name" /> </Form> </template> ``` ```vue import { Form, FormItem } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Form, FormItem }, data() { return { form: { name: '' }, rules: { name: { required: true, message: '请输入姓名' } } } }, methods: { submit() { this.$refs.form.validate(valid => { console.log(valid) }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ labelWidth | 表单整体名称的长度,用法同 `iview.form.label-width` | string/number | - rules | 表单校验规则,用法与 `iview.form.rules` 相同 | object | - model | 表单数据对象,用法与 `iview.form.model` 相同 | object | - #### FormItem 基于 `vant.field` 封装,靠拢 `iview.form-item` API,请结合 `Form` 组件使用 ```html <template> <Form ref="form" :rules="rules" :model="form" > <FormItem v-model="form.name" type="input" label="姓名" prop="name" /> <FormItem v-model="form.password" type="input" type="password" label="password" /> <FormItem v-model="form.remark" type="textarea" label="备注" /> <FormItem v-model="form.sex" type="radio" label="单选框" :data="[{ id: 'male', name: '男' }, { id: 'female', name: '女' }]" prop="sex" /> <FormItem v-model="form.date" type="datetime" label="时间选择器" :picker-info="{ name: 'datetime', title: '日期选择框' }" prop="datetime" /> <FormItem v-model="form.type" type="picker" label="选择器" :picker-info="{ name: 'picker', message: '请选择内容', title: '选择器' }" :data="list" prop="country" /> <FormItem v-model="form.images" type="upload" label="图片上传" /> <FormItem type="custom" label="自定义组件"> <van-rate v-model="form.custom" /> </FormItem> </Form> </template> ``` ```vue import { Form, FormItem } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { Form, FormItem }, data() { const validator = (r, v, c) => { if(!v) { c(new Error('请选择性别')) } c() } return { form: { name: '', sex: '', date: null, type: '' }, rules: { name: { required: true, message: '请输入姓名' }, sex: { required: true, message: '请选择性别', validator }, date: { required: false } }, list: [{ id: 0, name: 'beijing' }, { id: 1, name: 'shanghai' }] } }, methods: { submit() { this.$refs.form.validate(valid => { console.log(valid) }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ type | 表单组件类型 | string | '' label | 表单名称 | string | '' labelWidth | 表单项名称的长度,用法同 `iview.form-item.labelWidth` | string/number | - value | 表单值 | string/number/array/date |- data | type 为 radio/picker 时使用,配置数据源 |array/object |{} placeholder | 表单提示信息 | string | '' pickerInfo | type 为 datetime/picker 时使用,配置 picker 信息 | object | {} hasArrow | 右侧是否展示箭头 | boolean | false rules | 表单项校验规则,用法同 `iview.form-item.rules` | object | {} disabled | 表单项是否禁用 | boolean | false prop | 对应 v-model 的名称,form 表单会根据该属性执行相应的 rules,当 type 为 picker 或 datetime 时,必填,以获取 `vant.picker` 实例 | string | - 方法 | 说明 ----|----- on-click | 表单项的点击事件,需要 disabled 为 false 并且 type 不为 picker/datetime on-change | 表单值发生改变时触发,返回当前的表单值,需要 type 为 picker type 值: - input - tel - digit - password - number - radio - picker - datetime - textarea - upload - custom PickerInfo 配置: * title: picker 标题 * message: type 为 picker 时,当没有选值的时候,点击「确定」按钮时的提示 ## 业务组件 #### ApproveLine 审批线展示组件,用于表单详情页展示审批信息 ```html <template> <ApproveLine :data="process" /> </template> ``` ```vue import { ApproveLine } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { ApproveLine }, data() { return [{ activityType: 'startEvent', assignee: '发起人 xxx', endTime: 'xxxx-xx-xx xx:xx:xx' }, { assignee: '直属上级 xxx', approveStatusName: '审批中', endTime: 'xxxx-xx-xx xx:xx:xx', approving: true, comments: [{ userId: 'ldapusername', message: 'xxxx', time: 'xxxx-xx-xx xx:xx:xx' }] }, { activityType: 'endEvent', assignee: '二级部门负责人 xxx', endTime: 'xxxx-xx-xx xx:xx:xx' }] } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ data | 审批线数据 | array | [] ##### Data 属性配置见下: * activityType: 节点类型,可为 startEvent(开始节点,标题为“开始节点”),endEvent(结束节点,标题为“结束节点”)或空(中间节点,标题取自 assignee) * assignee:当节点类型为中间节点时,节点的标题 * approveStatusName:审批状态名称 * endTime:审批操作时间 * approving:是否正在审批 * comments:备注信息,见下: ##### Comments: * userId:备注人 * message:备注信息 * time:备注时间 #### FormList 以配置的方式快速渲染表单列表页 ```html <template> <FormList :module="module" :render="render" @on-load="handleLoad" @on-next-page="handleNextPage" @on-search="handleSearch" @on-row-click="handleRowClick"/> </template> ``` ```vue import { FormList } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FormList }, data() { return { module: { listLoading: true, condition: {}, pagination: { pageSize: 5, total: 0, current: 1 }, finished: false, list: [] }, render: data => ({ title: '列表标题', color: '#71c7ac', date: data.createdTime, user: data.creatorId, status: { text: '待处理', color: '#68b1ed' }, column: [{ label: '工单号', text: data.code }, { label: '预计完结时间', text: data.estimateDoneTime }, { label: '问题分类', text: data.probTypeName }, { label: '问题描述', text: data.probDesc }] }) } }, methods: { handleLoad() { setTimeout(() => { this.module.list = [{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }] this.module.pagination.total = 5 this.module.listLoading = false }, 1000) }, handleNextPage(n) { setTimeout(() => { this.module.list = this.module.list.concat([{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }, { code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }]) this.module.pagination.total = 7 this.module.finished = true }, 1000) }, handleSearch() { this.module.list = [{ code: 'TY202002040000', createdTime: '2020-02-04 10:25', creatorId: 'xxx', orderId: 146, orderMode: 6, priority: 2, probDesc: '测试', estimateDoneTime: '1111', probTypeName: '2222' }] this.module.pagination.current = 1 this.module.pagination.total = 1 }, handleRowClick(index) { console.log(index) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ module | 列表数据模型,见下 | object |{} searchHolder | 搜索提示文字 | string | '搜索单号' searchText | 搜索按钮文字 | string | '搜索' render | 列表项渲染规则,见下| function | - 方法 | 说明 ----|----- on-load | 列表初始化、加载下一页时触发 on-next-page| 加载下一页时触发,返回新页码 on-search| 点击搜索按钮时触发 on-row-click | 点击列表项时触发,返回该项在列表中的索引 ##### Module 模型 * listLoading: 列表是否处于加载状态 * condition: 搜索信息 ```js { query: string, // 搜索关键字 approveStatus: number, // 审批状态,1 待审批 2 已审批 } ``` * pagination: 分页信息 ```js { pageSize: number, // 每页条数 total: number, // 总条数 current: number, // 当前页 } ``` * finished:是否已加载到最后一页 * list:列表数据 ##### Render 规则 * title:列表项标题 * user:用户名 * date: 提单日期 * color:主体颜色 * status: 状态信息 ```js { text: string, // 状态文字 color: string, // 状态颜色 } ``` * column 表单信息数据渲染列表 ```js [{ label: string, // 数据标题, value: any, // 数据值 }] ``` #### FormDetail 以配置的方式快速渲染表单详情页 ```html <template> <FormDetail :loading="false" :form="form" :render="render"> <template #buttonGroup> <FooterButton> <ButtonOne text='取消' :colors="{ font: 'white', background: '#ff4f4f' }"/> <ButtonOne text='提交' :colors="{ font: 'white', background: '#68b1ed' }"/> </FooterButton> </template> </FormDetail> </template> ``` ```vue import { FormDetail, FooterButton } from '@keepfe/plugin-vant-ui/lib/vant-ui.min.js' export default { components: { FormDetail, FooterButton, ButtonOne: FooterButton.ButtonOne }, data() { return { // 服务端返回 form: { code: 1, name: 2, attachments: [{ path: 'https://static1.keepcdn.com/newoa/2021/02/26/10/23/8da380e1c5e110cd206fa475fe6e828b17a1e6ec_159x159_f32797289f461caf69bf67200faf37a47ac8283d.png', name: '附件1', key: 'group1/M00/00/BB/rBQF6V7p58GATUiKAALoQbbcoqU373' }], flow: [{ 'activityType': 'startEvent', 'approving': false, 'approveStatusName': null, 'assignee': null, 'comments': null, 'endTime': '2020-05-18 19:23:13', }, { 'activityType': 'userTask', 'approving': false, 'approveStatusName': '已通过', 'assignee': 'qinchuan', 'comments': [{ 'message': '同意', 'time': 1589801048956, 'userId': 'qinchuan' }, { 'message': '同意111', 'time': 1589801048956, 'userId': 'zhouximin01' }], 'endTime': '2020-05-18 19:24:08', }, { 'activityType': 'endEvent', 'approving': true, 'approveStatusName': null, 'assignee': null, 'comments': null, 'endTime': '2020-05-18 19:24:08' }], notices: ['qinchuan', 'zhouximin01'] }, render: data => ({ title: '详情信息', formTitle: '基本信息', user: 'qinchuan', watermark: { show: true, url: FormDetail.watermark.WATERMARK_AGREE }, approveLine: { show: true, key: 'flow', title: '审批线' }, attachments: { show: true, key: 'attachments', title: '图片' }, notices: { show: true, key: 'notices', title: `已通知 ${data.notices.length} 人` }, column: [{ label: 'code', text: data.code }, { label: 'name', text: data.name }] }) } } } ``` 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ loading | 数据是否加载中 | boolean | true form | 表单数据 | object | {} render | 渲染规则,见下| function | - ##### Render 规则 * title:页面标题 * formTitle:表单信息标题 * user:表单信息主体用户 * watermark 水印模块配置 ```js { show: boolean, // 是否展示审批状态水印 url: string, // 水印链接,可直接使用 FormDetail.watermark 提供的水印,或自定义 } ``` * attachments 附件模块配置 ```js { show: boolean, // 是否展示附件模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * approveLine 审批线模块配置 ```js { show: boolean, // 是否展示审批线模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * notices 告知模块配置 ```js { show: boolean, // 是否展示告知模块 key: string, // 数据源在 form 属性中的 key title: string, // 标题 } ``` * column 表单信息数据渲染列表 ```js [{ label: string, // 数据标题, value: any, // 数据值 }] ``` # 六、扩展指南 1. 运行安装命令,`npm i` ,安装所有依赖 2. 绑定测试域名 ```shell > sudo vim /etc/hosts # 增加一项 127.0.0.1 local.dev.gotokeep.com ``` ## 基本配置 在 package.json 文件中有组件库的基本信息,包括 git、名称、标签前缀等 - 规范好 namefix ## 开发组件 > 注意事项 1. 组件的开发避免使用在ssr端可以执行的生命周期,比如 beforecreate 和 created 等 2. 组件规范要符合vue官方规范 https://cn.vuejs.org/v2/style-guide/ ### 1. 开发组件 1. 运行开发环境 `npm run dev` , 一定不能忘记, 打开 url: http://local.dev.gotokeep.com:8081/ 预览 2. 修改组件配置 - 修改文件 `components/list`, 按照格式增加组件 compxxx - `isGlobal`代表是否需要绑定到vue全局,比如toast组件 - `notShow`代表是否不展示到示例列表中 3. 添加外部扩展 - 安装依赖的扩展npm包 - 修改 build 中 webpack.comp.js 的配置,添加扩展引入(参考其他扩展) 3. 前往 `components/compxxx/` 目录进行组件代码编写 - 编写 `index.vue` 组件源码 - 编写 `demo/demox.vue` 组件开发展示代码, x 表示 1,2,3... ## 组件库发布 1. 运行 `sh publish.sh` 2. 手动代码diff,push 3. 运行 `npm publish` ## 规范约定 规范要求: 1. 组件内的样式命名一律使用bem函数生成 2. 公共样式文件在 components/style 中, 其中var.less是公共 变量,可以用来定制主题;其他的为特殊样式的实现代码 3. components/ 中如果有非组件和基础样式的文件夹可以用_作为开通,如 _utils 4. 组件分类参考:vant 的分类 5. 组件的代码实现 不局限 于用一个文件实现 6. 组件的样式统一使用 less 实现 3. 添加外部扩展 - 安装依赖的扩展npm包 - 修改 build 中 webpack.comp.js 的配置,添加扩展引入(参考其他扩展) 3. 前往 `components/compxxx/` 目录进行组件代码编写 - 编写 `index.vue` 组件源码 - 编写 `demo/demox.vue` 组件开发展示代码, x 表示 1,2,3... ## 组件库发布 1. 运行 `sh publish.sh` 2. 手动代码diff,push 3. 运行 `npm publish` ## 规范约定 规范要求: 1. 组件内的样式命名一律使用bem函数生成 2. 公共样式文件在 components/style 中, 其中var.less是公共 变量,可以用来定制主题;其他的为特殊样式的实现代码 3. components/ 中如果有非组件和基础样式的文件夹可以用_作为开通,如 _utils 4. 组件分类参考:vant 的分类 5. 组件的代码实现 不局限 于用一个文件实现 6. 组件的样式统一使用 less 实现