# 一、基本介绍
本组件库为 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 实现