# 一、基本介紹
本組件庫為 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 實現