Merge branch 'feat_license_plate_keyboard' into feat_icon_optimized

This commit is contained in:
weishuodan 2024-01-05 14:49:40 +08:00
commit 64d10e42f0
20 changed files with 1500 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -64,6 +64,7 @@ import Progress from './progress'
import Ruler from './ruler'
import TextareaItem from './textarea-item'
import Skeleton from './skeleton'
import LicensePlate from './license-plate'
/* @init<%import ${componentNameUpper} from './${componentName}'%> */
// Totally importing reminder
@ -136,6 +137,7 @@ export const components = {
Ruler,
TextareaItem,
Skeleton,
LicensePlate,
/* @init<%${componentNameUpper},%> */
}
@ -231,6 +233,7 @@ export {
Skeleton,
setLocale,
t,
LicensePlate,
/* @init<%${componentNameUpper},%> */
}

View File

@ -0,0 +1,139 @@
<template>
<div class="md-license-plate-input">
<div
v-for="(item, index) in keyArray"
:key="index"
class="md-license-plate-input-item"
:class="{
'active': selectedIndex === index,
'animation': selectedIndex === index && !item
}"
@click="keyMapping(index)"
>
<!-- 非新能源键位 -->
<div
v-if="index !== keyArray.length-1"
class="md-license-plate-input-item_content"
>
{{ item }}
</div>
<!-- 新能源键位 -->
<div
v-else
class="md-license-plate-input-item_content"
>
<div v-if="item && item !== ' '">{{ item }}</div>
<div v-else class="emptyValue"></div>
</div>
</div>
</div>
</template>
<script> export default {
name: 'md-license-plate-input',
components: {},
props: {
keyArray: {
type: Array,
default: () => {
return []
},
},
selectedIndex: {
type: Number,
default: 0,
},
},
data() {
return {}
},
methods: {
keyMapping(index) {
this.$emit('keyMapping', index)
},
},
}
</script>
<style lang="stylus">
.md-license-plate-input{
display: flex;
.md-license-plate-input-item{
width: 64px;
height: 94px;
background: #F4F8FF;
border: 1px solid rgba(222,237,255,1);
border-radius: 8px;
margin-right: 11px;
&_content {
width: 100%;
height: 100%;
font-family: font-family-number;
font-size: 40px;
color: #111A34;
letter-spacing: 0;
text-align: center;
line-height: 94px;
font-weight: 500;
.emptyValue{
width: 100%;
height: 100%;
background: url(../_style/images/new-energy.png) center no-repeat;
background-size: 49px 51px;
}
}
}
>.md-license-plate-input-item:nth-child(2){
margin-right: 28px;
position: relative;
&::after{
top: 0.47rem;
right: -0.22rem;
content: "";
position: absolute;
width: .06rem;
height: .06rem;
background: #000;
border-radius: 50%;
transform: translate(-50%, -50%);
}
}
>.md-license-plate-input-item:last-child{
margin-right: 0px;
background: #E8FBE7;
border: 1px solid rgba(203,242,201,1);
border-radius: 8px;
font-size: 16px;
color: #61686F;
}
.md-license-plate-input-item.active{
border-color: rgba(25,140,255,1);
}
.md-license-plate-input-item.active.animation{
animation keyboard-cursor 1s step-start 2s
}
}
@keyframes keyboard-cursor{
0%{
border-color: rgba(25,140,255,1);
}
25%{
border-color: rgba(222,237,255,1);
}
50%{
border-color: rgba(25,140,255,1);
}
75%{
border-color: rgba(222,237,255,1);
}
100%{
border-color: rgba(25,140,255,1);
}
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<div class="md-license-plate-keyboard">
<div v-if="keyboardType === 1">
<md-shortcut-row
:shortcuts="shortcuts"
@enter="$_onEnter"
/>
</div>
<div v-else>
<md-mixed-key-board
:mixedKeyboard="mixedKeyboard"
@enter="$_onEnter"
@delete="$_onDelete"
@confirm="$_onConfirm"
/>
</div>
</div>
</template>
<script> import MixedKeyBoard from './mixed-key-board'
import ShortcutRow from './short-cut-row'
export default {
name: 'md-license-plate-keyboard',
components: {
[MixedKeyBoard.name]: MixedKeyBoard,
[ShortcutRow.name]: ShortcutRow,
},
props: {
//
keyboard: {
type: Object,
default: {},
},
},
data() {
return {}
},
computed: {
shortcuts() {
return this.keyboard.shortcuts || []
},
//
keyboardType() {
return this.keyboard.keyboardType || 1
},
//
mixedKeyboard() {
return this.keyboard.mixedKeyboard || []
},
},
methods: {
$_onEnter(value) {
this.$emit('enter', value)
},
$_onDelete() {
this.$emit('delete')
},
$_onConfirm() {
this.$emit('confirm')
},
},
}
</script>

View File

@ -0,0 +1,107 @@
<template>
<div class="md-mixed-key-board">
<div
v-for="(item, index) in mixedKeyboard"
:key="index"
class="md-mixed-key-board-item"
:class="{disabled: item.disabled}"
>
<template v-if="item.type">
<div
:class="item.type"
v-tap="{
methods:
item.type === 'delete' ? $_onDelete : $_onConfirm,
disabled: item.disabled
}"
>
<div v-if="item.type === 'confirm' && item.text">{{ item.text }}</div>
</div>
</template>
<template v-else>
<div
v-tap="{
methods: $_onEnter,
disabled: item.disabled
}"
>{{ item.value }}</div>
</template>
</div>
</div>
</template>
<script> export default {
name: 'md-mixed-key-board',
components: {},
props: {
//
mixedKeyboard: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {}
},
methods: {
$_onEnter(value) {
this.$emit('enter', value)
},
$_onDelete() {
this.$emit('delete')
},
$_onConfirm() {
this.$emit('confirm')
},
},
}
</script>
<style lang="stylus">
.md-mixed-key-board {
padding: 32px 0px;
display: flex;
flex-wrap: wrap;
.md-mixed-key-board-item {
>div{
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 104px;
background: #FFFFFF;
box-shadow: 0px 2px 0px 0px rgba(159,159,159,0.5);
border-radius: 10px;
font-family: font-family-normal;
font-size: 40px;
color: #111A34;
font-weight: 400;
margin: 0px 0px 10px 10px;
&.delete{
background: url(../_style/images/license-keyboard-del.png) center no-repeat;
background-color: #FFFFFF;
background-size: 40px 40px;
}
&.confirm{
width: 212px;
background: #198CFF;
box-shadow: none;
font-size: 36px;
color: #FFFFFF;
}
}
&.disabled{
>div{
background: #F5F5F5;
color: #C1C8CF;
}
}
}
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<div class="md-shortcut-row">
<div
v-for="(item, index) in shortcuts"
:key="index"
class="md-shortcut-row-item"
v-tap="{ methods: $_onEnter }"
>{{ item }}</div>
</div>
</template>
<script> export default {
name: 'md-shortcut-row',
components: {},
props: {
//
shortcuts: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {}
},
methods: {
$_onEnter(value) {
this.$emit('enter', value)
},
},
}
</script>
<style lang="stylus">
.md-shortcut-row {
padding: 32px 10px;
display: flex;
flex-wrap: wrap;
.md-shortcut-row-item {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 104px;
background: #FFFFFF;
box-shadow: 0px 2px 0px 0px rgba(159,159,159,0.5);
border-radius: 12px;
font-family: font-family-normal;
font-size: 40px;
color: #01080F;
letter-spacing: 0;
font-weight: 400;
margin: 0px 0px 10px 10px;
}
}
</style>

View File

@ -0,0 +1,38 @@
---
title: license-plate
preview:
---
To display ads or descriptions in a floating layer
### Import
```javascript
import { Landscape } from 'mand-mobile'
Vue.component(Landscape.name, Landscape)
```
### Code Examples
<!-- DEMO -->
### API
#### LicensePlate Props
|Props | Description | Type | Default | Note |
|----|-----|------|------|-----|
|shortcuts|Province key position data|Array|`['京','津','渝','沪','冀','晋','辽','吉','黑','苏','浙','皖','闽','赣','鲁','豫','鄂','湘','粤','琼','川','贵','云','陕','甘','青','蒙','桂','宁','新','藏']`| - |
|letterData|Alphabetic keyboard data|Array|`[{value: 'Q',disabled: false,},{value: 'W',disabled: false,},{value: 'E',disabled: false,},{value: 'R',disabled: false,},{value: 'T',disabled: false,},{value: 'Y',disabled: false,},{value: 'U',disabled: false,},{value: 'I',disabled: true,},{value: 'O',disabled: true,},{value: 'P',disabled: false,},{value: 'A',disabled: false,},{value: 'S',disabled: false,},{value: 'D',disabled: false,},{value: 'F',disabled: false,},{value: 'G',disabled: false,},{value: 'H',disabled: false,},{value: 'J',disabled: false,},{value: 'K',disabled: false,},{value: 'L',disabled: false,},{value: 'Z',disabled: false,},{value: 'X',disabled: false,},{value: 'C',disabled: false,},{value: 'V',disabled: false,},{value: 'B',disabled: false,},{value: 'N',disabled: false,},{value: 'M',disabled: false,}]`| - |
|modeShow|Display mode|String|`division`| division/popUp |
|showPopUp|Control display in popup mode|Boolean|`false`| - |
|title|The title is displayed in pop-up mode|String|`请输入车牌号码`| - |
|subtitle|The subtitle is displayed in pop-up mode|String|``| - |
|defaultValue|Default key value|String|``| - |
#### LicensePlate Events
##### @hide()
hide Pop
##### @confirm()
confirm

View File

@ -0,0 +1,38 @@
---
title: LicensePlate 车牌键盘
preview:
---
专用于车牌输入键盘
### 引入
```javascript
import { LicensePlate } from 'mand-mobile'
Vue.component(LicensePlate.name, LicensePlate)
```
### 代码演示
<!-- DEMO -->
### API
#### LicensePlate Props
|属性 | 说明 | 类型 | 默认值| 备注 |
|----|-----|------|------|-----|
|shortcuts|省份键位数据|Array|`['京','津','渝','沪','冀','晋','辽','吉','黑','苏','浙','皖','闽','赣','鲁','豫','鄂','湘','粤','琼','川','贵','云','陕','甘','青','蒙','桂','宁','新','藏']`| - |
|letterData|字母键盘数据|Array|`[{value: 'Q',disabled: false,},{value: 'W',disabled: false,},{value: 'E',disabled: false,},{value: 'R',disabled: false,},{value: 'T',disabled: false,},{value: 'Y',disabled: false,},{value: 'U',disabled: false,},{value: 'I',disabled: true,},{value: 'O',disabled: true,},{value: 'P',disabled: false,},{value: 'A',disabled: false,},{value: 'S',disabled: false,},{value: 'D',disabled: false,},{value: 'F',disabled: false,},{value: 'G',disabled: false,},{value: 'H',disabled: false,},{value: 'J',disabled: false,},{value: 'K',disabled: false,},{value: 'L',disabled: false,},{value: 'Z',disabled: false,},{value: 'X',disabled: false,},{value: 'C',disabled: false,},{value: 'V',disabled: false,},{value: 'B',disabled: false,},{value: 'N',disabled: false,},{value: 'M',disabled: false,}]`| - |
|modeShow|展示模式|String|`division`| division/popUp |
|showPopUp|弹窗模式下控制展示|Boolean|`false`| - |
|title|弹窗模式下展示标题|String|`请输入车牌号码`| - |
|subtitle|弹窗模式下展示副标题|String|``| - |
|defaultValue|默认键位值|String|``| - |
#### LicensePlate Events
##### @hide()
半弹层关闭事件
##### @confirm()
键盘确认事件

View File

@ -0,0 +1,7 @@
export default {
'name': 'license-plate',
'text': '车牌号键入',
'category': 'business',
'description': '车牌号输入键盘',
'author': 'weishuodan'
}

View File

@ -0,0 +1,29 @@
<template>
<div>
<md-license-plate :defaultValue="defaultValue"></md-license-plate>
</div>
</template>
<script> import {LicensePlate} from 'mand-mobile'
export default {
name: 'license-plate-demo',
components: {
[LicensePlate.name]: LicensePlate,
},
data() {
return {
defaultValue: '',
}
},
mounted() {
// setTimeout(()=>{
// this.defaultValue = '2333888 '
// },10000)
},
methods: {},
}
</script>
<style lang="stylus" scoped>
</style>

View File

@ -0,0 +1,52 @@
<template>
<div>
<!-- 投保人车牌号 -->
<md-field title="车辆信息">
<div @click="changeNumber">
<md-detail-item title="车牌号码">
{{ licensePlate }}
</md-detail-item>
</div>
</md-field>
<md-license-plate
:modeShow="'popUp'"
:showPopUp="showPopUp"
@hide="hide"
@confirm="confirm"
></md-license-plate>
</div>
</template>
<script> import {LicensePlate, DetailItem, Field} from 'mand-mobile'
export default {
name: 'license-plate-demo',
title: '半弹层版',
components: {
[LicensePlate.name]: LicensePlate,
[DetailItem.name]: DetailItem,
[Field.name]: Field,
},
data() {
return {
showPopUp: false,
licensePlate: '',
}
},
methods: {
hide() {
this.showPopUp = false
},
changeNumber() {
this.showPopUp = true
},
confirm(value) {
this.hide()
this.licensePlate = value
},
},
}
</script>
<style lang="stylus">
</style>

View File

@ -0,0 +1,21 @@
<template>
<div class="md-example" id="licensePlateContainer">
<section class="md-example-section" v-for="(demo, index) in demos" :key="index">
<div class="md-example-title" v-html="demo.title || '基础'"></div>
<div class="md-example-describe" v-html="demo.describe"></div>
<div class="md-example-content">
<component :is="demo"></component>
</div>
</section>
</div>
</template>
<script> import createDemoModule from '../../../examples/create-demo-module'
import Demo0 from './cases/demo0'
import Demo1 from './cases/demo1'
export default {...createDemoModule('license-plate', [Demo0, Demo1])}
</script>
<style lang="stylus" scoped>
</style>

View File

@ -0,0 +1,512 @@
<template>
<div class="md-license-plate">
<div v-if="modeShow === 'division'">
<div
class="md-license-plate-input-container division"
:id="inputViewId"
>
<md-license-plate-input
:keyArray="keyArray"
:selectedIndex="dyCurrentIndex"
@keyMapping="keyMapping"
/>
</div>
<div
v-if="showDivisionKeyboard"
class="md-license-plate-keyboard-container division"
:id="keyboardViewId"
>
<md-license-plate-keyboard
:keyboard="dyKeyboard"
@enter="$_onEnter"
@delete="$_onDelete"
@confirm="$_onConfirm"
/>
</div>
</div>
<div v-if="modeShow === 'popUp'">
<md-popup
:value="showPopUp"
:hasMask="true"
position="bottom"
:maskClosable="false"
>
<md-popup-title-bar
only-close
large-radius
:title="title"
:describe="subtitle"
title-align="left"
@cancel="$_onHide"
></md-popup-title-bar>
<div class="md-popup-content">
<div class="md-license-plate-input-container popUp">
<md-license-plate-input
:keyArray="keyArray"
:selectedIndex="dyCurrentIndex"
@keyMapping="keyMapping"
/>
</div>
<div class="md-license-plate-keyboard-container popUp">
<md-license-plate-keyboard
:keyboard="dyKeyboard"
@enter="$_onEnter"
@delete="$_onDelete"
@confirm="$_onConfirm"
/>
</div>
</div>
</md-popup>
</div>
</div>
</template>
<script> import LicensePlateKeyboard from '../license-plate-keyboard'
import LicensePlateInput from '../license-plate-input'
import Popup from '../popup'
import PopupTitlebar from '../popup/title-bar'
import {directiveInit, queryCurParentNode, unique} from './util'
export default {
name: 'md-license-plate',
components: {
[LicensePlateKeyboard.name]: LicensePlateKeyboard,
[LicensePlateInput.name]: LicensePlateInput,
[Popup.name]: Popup,
[PopupTitlebar.name]: PopupTitlebar,
},
props: {
//
shortcuts: {
type: Array,
default: () => {
return [
'京',
'津',
'渝',
'沪',
'冀',
'晋',
'辽',
'吉',
'黑',
'苏',
'浙',
'皖',
'闽',
'赣',
'鲁',
'豫',
'鄂',
'湘',
'粤',
'琼',
'川',
'贵',
'云',
'陕',
'甘',
'青',
'蒙',
'桂',
'宁',
'新',
'藏',
]
},
},
//
letterData: {
type: Array,
default: () => {
return [
{
value: 'Q',
disabled: false,
},
{
value: 'W',
disabled: false,
},
{
value: 'E',
disabled: false,
},
{
value: 'R',
disabled: false,
},
{
value: 'T',
disabled: false,
},
{
value: 'Y',
disabled: false,
},
{
value: 'U',
disabled: false,
},
{
value: 'I',
disabled: true,
},
{
value: 'O',
disabled: true,
},
{
value: 'P',
disabled: false,
},
{
value: 'A',
disabled: false,
},
{
value: 'S',
disabled: false,
},
{
value: 'D',
disabled: false,
},
{
value: 'F',
disabled: false,
},
{
value: 'G',
disabled: false,
},
{
value: 'H',
disabled: false,
},
{
value: 'J',
disabled: false,
},
{
value: 'K',
disabled: false,
},
{
value: 'L',
disabled: false,
},
{
value: 'Z',
disabled: false,
},
{
value: 'X',
disabled: false,
},
{
value: 'C',
disabled: false,
},
{
value: 'V',
disabled: false,
},
{
value: 'B',
disabled: false,
},
{
value: 'N',
disabled: false,
},
{
value: 'M',
disabled: false,
},
]
},
},
//
modeShow: {
type: String,
default: 'division',
},
//
showPopUp: {
type: Boolean,
default: false,
},
//
title: {
type: String,
default: '请输入车牌号码',
},
//
subtitle: {
type: String,
default: '',
},
//
defaultValue: {
type: String,
default: '',
},
//
disorderClick: {
type: Boolean,
default: true,
},
},
data() {
return {
//
numbers: [
{
value: 1,
disabled: false,
},
{
value: 2,
disabled: false,
},
{
value: 3,
disabled: false,
},
{
value: 4,
disabled: false,
},
{
value: 5,
disabled: false,
},
{
value: 6,
disabled: false,
},
{
value: 7,
disabled: false,
},
{
value: 8,
disabled: false,
},
{
value: 9,
disabled: false,
},
{
value: 0,
disabled: false,
},
],
//
keyArray: ['', '', '', '', '', '', '', ''],
selectedIndex: 0, //
showDivisionKeyboard: false,
inputViewId: unique() + '_divisionInput',
keyboardViewId: unique() + '_divisionKeyboard',
}
},
computed: {
//
dyCurrentIndex: function() {
return this.selectedIndex
},
dyKeyboard() {
let numbers = [],
shortcuts = [],
letterData = [],
keyboardType,
mixedKeyboard = []
//
shortcuts = this.shortcuts
// ()
if (this.dyCurrentIndex === 0) {
keyboardType = 1
} else {
keyboardType = 2
//
letterData = JSON.parse(JSON.stringify(this.letterData))
//
letterData.splice(19, 0, {
type: 'delete',
disabled: false,
})
//
letterData.push({
type: 'confirm',
text: '确定',
disabled: false,
})
//
numbers = this.numbers
// ()
if (this.selectedIndex === 1) {
numbers = this.numbers.map(item => {
return {
value: item.value,
disabled: true,
}
})
}
mixedKeyboard = numbers.concat(letterData)
}
return {
shortcuts,
mixedKeyboard,
keyboardType,
}
},
// null
keyArrayCopy() {
return this.keyArray.map(item => {
if (item) {
return item
} else {
return ' '
}
})
},
},
created() {
//
directiveInit()
},
methods: {
keyMapping(index) {
//
if (!this.showDivisionKeyboard) {
this.showDivisionKeyboard = true
//
this.$emit('sdKeyboard', this.keyboardViewId)
}
//
if (!this.disorderClick && !this.keyArray[index + 1] && !this.keyArray[index - 1] && index > 0) {
return
}
this.selectedIndex = index
},
//
$_onHide() {
this.$emit('hide')
},
//
$_onEnter(value) {
//
this.$set(this.keyArray, this.selectedIndex, value)
//
if (this.selectedIndex === this.keyArray.length - 1) {
this.$_onConfirm()
} else {
this.selectedIndex = this.selectedIndex + 1
}
},
//
$_onDelete() {
//
this.$set(this.keyArray, this.selectedIndex, '')
//
if (this.selectedIndex <= 0) {
if (this.modeShow === 'division') {
this.hideDivisionKeyboard()
}
} else {
this.selectedIndex = this.selectedIndex - 1
}
},
//
$_onConfirm() {
if (this.modeShow === 'division') {
this.hideDivisionKeyboard()
}
this.$emit('confirm', this.keyArrayCopy.join(''))
},
//
hideDivisionKeyboard(e) {
let isKeyboard = false
if (e && e.target) {
isKeyboard = queryCurParentNode(e.target, [this.keyboardViewId, this.inputViewId])
}
if (this.showDivisionKeyboard && !isKeyboard) {
this.showDivisionKeyboard = false
//
this.$emit('hdKeyboard', this.keyArrayCopy.join(''))
}
},
},
mounted() {
//
this.modeShow === 'division' && document.addEventListener('click', this.hideDivisionKeyboard)
},
beforeDestroy() {
this.modeShow === 'division' && document.removeEventListener('click', this.hideDivisionKeyboard)
},
watch: {
defaultValue: {
handler(newVal) {
if (newVal !== '') {
const defaultValueArray = this.defaultValue.split('')
const keyArrayCopy = JSON.parse(JSON.stringify(this.keyArray))
keyArrayCopy.forEach((item, index) => {
if (defaultValueArray[index]) {
keyArrayCopy[index] = defaultValueArray[index]
} else {
keyArrayCopy[index] = ''
}
})
this.keyArray = keyArrayCopy
}
},
immediate: true,
},
},
}
</script>
<style lang="stylus">
.md-license-plate {
.md-license-plate-keyboard-container {
width: 100%;
background: #D9E0E7;
&.division {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
position: fixed;
bottom: 0px;
left: 0px;
z-index: 99999;
}
}
.md-license-plate-input-container{
&.popUp{
background: #fff;
padding: 20px 40px 40px;
}
}
}
</style>

View File

@ -0,0 +1,22 @@
<template>
<div>
<md-license-plate></md-license-plate>
</div>
</template>
<script> import {LicensePlate} from 'mand-mobile'
export default {
name: 'license-plate-demo',
components: {
[LicensePlate.name]: LicensePlate,
},
data() {
return {}
},
methods: {},
}
</script>
<style lang="stylus">
</style>

View File

@ -0,0 +1,8 @@
import Demo0 from './cases/demo0'
import {renderToString} from '@vue/server-test-utils'
describe('Landscape - Demo', () => {
test('Basic', () => {
expect(renderToString(Demo0)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,131 @@
// Vue插件Tap事件处理
import Vue from 'vue'
const _IS_MOBILE = /mobile|table|ip(ad|hone|od)|android/i.test(navigator.userAgent)
const plugin = {
bind: function(el, binding) {
el.binding_ref = binding
el.tapEventHandler = function(evt) {
const {disabled = false, methods} = el.binding_ref.value
// 阻止事件冒泡
evt.stopPropagation()
// 禁止点击,直接返回
if (disabled) {
return
}
// 执行点击方法,并回传值
methods(el.innerHTML)
}
el.tapEventHandler_nop = function() {}
// 绑定监听事件
if (_IS_MOBILE) {
el.addEventListener('touchstart', el.tapEventHandler, false)
el.addEventListener('touchend', el.tapEventHandler_nop, false)
} else {
el.addEventListener('click', el.tapEventHandler, false)
}
},
unbind: function(el) {
// 移除监听事件
if (_IS_MOBILE) {
el.removeEventListener('touchstart', el.tapEventHandler, false)
el.removeEventListener('touchend', el.tapEventHandler_nop, false)
} else {
el.removeEventListener('click', el.tapEventHandler, false)
}
},
update: function(el, binding) {
el.binding_ref = binding
},
}
export const directiveInit = () => {
Vue.directive('tap', plugin)
}
export const getParentTag = (startTag, parentTagList = []) => {
// 传入标签是否是DOM对象
if (!(startTag instanceof HTMLElement)) {
return parentTagList
}
// 没有父节点
if (!startTag.parentElement) {
return parentTagList
}
// 父级标签是否是body,是着停止返回集合,反之继续
if (startTag.parentElement.nodeName !== 'BODY') {
// 放入集合
parentTagList.push(startTag.parentElement)
// 再上一层寻找
return getParentTag(startTag.parentElement, parentTagList)
} else {
// 返回集合,结束
return parentTagList
}
}
export const queryCurParentNode = (startTag, idList) => {
// 查询所有父节点
const parentTagList = getParentTag(startTag)
// 查询当前父节点是否含有当前查找className
const tParentNode = parentTagList.findIndex(item => {
return (item.id && idList.includes(item.id)) || false
})
return tParentNode !== -1
}
/**
* 将元素滚动到顶部
* @param {number} position 滚动位置
* @param {element} elem 要滚动的元素
*/
function scrollToTop(elem, position) {
if (elem && elem.scrollTo) {
elem.scrollTo(0, position)
} else {
elem.scrollTop = position
}
}
/**
* 将元素平滑滚动到指定位置
* @param position 要滚动的位置
* @param elem 有滑动的元素
*/
export function scrollSmoothTo(position, elem) {
// 当前滚动高度
let scrollTop = elem && elem.scrollTop
// 滚动step方法
let step = function() {
// 距离目标滚动距离
let distance = position - scrollTop
// 目标滚动位置
scrollTop = scrollTop + distance / 5
if (Math.abs(distance) < 1) {
scrollToTop(elem, position)
} else {
scrollToTop(elem, scrollTop)
requestAnimationFrame(step)
}
}
step()
}
// 生成唯一值
export function unique() {
let nowTime = Date.now() || new Date().getTime()
let str = 'xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx'
// 高精度计时器
if (window.performance && typeof window.performance.now === 'function') {
nowTime += performance.now()
}
return str.replace(/[xy]/gi, c => {
let r = ((nowTime + Math.random() * 16) % 16) | 0
nowTime = Math.floor(nowTime / 16)
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16)
})
}

View File

@ -1 +1,261 @@
[{"category":"basic","name":"Basic","text":"基础","list":[{"name":"ActionBar","path":"/action-bar","icon":"action-bar","text":"操作栏"},{"name":"ActivityIndicator","path":"/activity-indicator","icon":"activity-indicator","text":"活动指示器"},{"path":"/button","name":"Button","icon":"button","text":"按钮"},{"name":"CellItem","path":"/cell-item","icon":"cell-item","text":"列表单元"},{"name":"DetailItem","path":"/detail-item","icon":"detail-item","text":"清单项"},{"name":"DropMenu","path":"/drop-menu","icon":"drop-menu","text":"下拉菜单"},{"path":"/icon","name":"Icon","icon":"icon","text":"图标"},{"name":"ImageReader","path":"/image-reader","icon":"image-reader","text":"图片选择器"},{"name":"ImageViewer","path":"/image-viewer","icon":"image-viewer","text":"图片浏览器"},{"name":"NoticeBar","path":"/notice-bar","icon":"notice-bar","text":"通知栏"},{"name":"Progress","path":"/progress","icon":"progress","text":"进度"},{"name":"Skeleton","path":"/skeleton","icon":"skeleton","text":"骨架屏"},{"name":"Stepper","path":"/stepper","icon":"stepper","text":"步进器"},{"name":"Steps","path":"/steps","icon":"steps","text":"步骤条"},{"name":"Swiper","path":"/swiper","icon":"swiper","text":"轮播"},{"name":"TabBar","path":"/tab-bar","icon":"tab-bar","text":"标签栏"},{"name":"Tabs","path":"/tabs","icon":"tabs","text":"标签页"},{"name":"Tag","path":"/tag","icon":"tag","text":"标签"}]},{"category":"business","name":"Business","text":"业务相关","list":[{"name":"Amount","path":"/amount","icon":"amount","text":"金融数字"},{"name":"Bill","path":"/bill","icon":"bill","text":"票据"},{"name":"Captcha","path":"/captcha","icon":"captcha","text":"验证码窗口"},{"name":"Cashier","path":"/cashier","icon":"cashier","text":"收银台"},{"name":"Chart","path":"/chart","icon":"chart","text":"折线图表"},{"name":"Landscape","path":"/landscape","icon":"landscape","text":"压屏窗"},{"name":"ResultPage","path":"/result-page","icon":"result-page","text":"结果页"},{"name":"Ruler","path":"/ruler","icon":"ruler","text":"刻度尺"},{"name":"WaterMark","path":"/water-mark","icon":"water-mark","text":"水印"}]},{"category":"feedback","name":"Feedback","text":"操作反馈","list":[{"name":"ActionSheet","path":"/action-sheet","icon":"action-sheet","text":"动作面板"},{"name":"DatePicker","path":"/date-picker","icon":"date-picker","text":"日期选择器"},{"name":"Dialog","path":"/dialog","icon":"dialog","text":"模态窗"},{"name":"Picker","path":"/picker","icon":"picker","text":"选择器"},{"name":"Popup","path":"/popup","icon":"popup","text":"弹出层"},{"name":"Selector","path":"/selector","icon":"selector","text":"列表选择器"},{"name":"TabPicker","path":"/tab-picker","icon":"tab-picker","text":"多频道选择器"},{"name":"Tip","path":"/tip","icon":"tip","text":"气泡提示"},{"name":"Toast","path":"/toast","icon":"toast","text":"轻提示"},{"name":"Transition","path":"/transition","icon":"transition","text":"动画"}]},{"category":"form","name":"Form","text":"表单相关","list":[{"name":"Agree","path":"/agree","icon":"agree","text":"勾选按钮"},{"name":"Check","path":"/check","icon":"check","text":"选择项组"},{"name":"Codebox","path":"/codebox","icon":"codebox","text":"字符码输入框"},{"name":"Field","path":"/field","icon":"field","text":"区域列表组合"},{"name":"InputItem","path":"/input-item","icon":"input-item","text":"输入框"},{"name":"NumberKeyboard","path":"/number-keyboard","icon":"number-keyboard","text":"数字键盘"},{"name":"Radio","path":"/radio","icon":"radio","text":"单选框"},{"name":"Slider","path":"/slider","icon":"slider","text":"滑块"},{"name":"Switch","path":"/switch","icon":"switch","text":"开关"},{"name":"TextareaItem","path":"/textarea-item","icon":"textarea-item","text":"文本域"}]},{"category":"gesture","name":"Gesture","text":"手势","list":[{"name":"ScrollView","path":"/scroll-view","icon":"scroll-view","text":"滚动区域/下拉刷新"}]}]
[
{
"category": "basic",
"name": "Basic",
"text": "基础",
"list": [
{
"name": "ActionBar",
"path": "/action-bar",
"icon": "action-bar",
"text": "操作栏"
},
{
"name": "ActivityIndicator",
"path": "/activity-indicator",
"icon": "activity-indicator",
"text": "活动指示器"
},
{ "path": "/button", "name": "Button", "icon": "button", "text": "按钮" },
{
"name": "CellItem",
"path": "/cell-item",
"icon": "cell-item",
"text": "列表单元"
},
{
"name": "DetailItem",
"path": "/detail-item",
"icon": "detail-item",
"text": "清单项"
},
{
"name": "DropMenu",
"path": "/drop-menu",
"icon": "drop-menu",
"text": "下拉菜单"
},
{ "path": "/icon", "name": "Icon", "icon": "icon", "text": "图标" },
{
"name": "ImageReader",
"path": "/image-reader",
"icon": "image-reader",
"text": "图片选择器"
},
{
"name": "ImageViewer",
"path": "/image-viewer",
"icon": "image-viewer",
"text": "图片浏览器"
},
{
"name": "NoticeBar",
"path": "/notice-bar",
"icon": "notice-bar",
"text": "通知栏"
},
{
"name": "Progress",
"path": "/progress",
"icon": "progress",
"text": "进度"
},
{
"name": "Skeleton",
"path": "/skeleton",
"icon": "skeleton",
"text": "骨架屏"
},
{
"name": "Stepper",
"path": "/stepper",
"icon": "stepper",
"text": "步进器"
},
{ "name": "Steps", "path": "/steps", "icon": "steps", "text": "步骤条" },
{ "name": "Swiper", "path": "/swiper", "icon": "swiper", "text": "轮播" },
{
"name": "TabBar",
"path": "/tab-bar",
"icon": "tab-bar",
"text": "标签栏"
},
{ "name": "Tabs", "path": "/tabs", "icon": "tabs", "text": "标签页" },
{ "name": "Tag", "path": "/tag", "icon": "tag", "text": "标签" }
]
},
{
"category": "business",
"name": "Business",
"text": "业务相关",
"list": [
{
"name": "Amount",
"path": "/amount",
"icon": "amount",
"text": "金融数字"
},
{ "name": "Bill", "path": "/bill", "icon": "bill", "text": "票据" },
{
"name": "Captcha",
"path": "/captcha",
"icon": "captcha",
"text": "验证码窗口"
},
{
"name": "Cashier",
"path": "/cashier",
"icon": "cashier",
"text": "收银台"
},
{
"name": "Chart",
"path": "/chart",
"icon": "chart",
"text": "折线图表"
},
{
"name": "Landscape",
"path": "/landscape",
"icon": "landscape",
"text": "压屏窗"
},
{
"name": "ResultPage",
"path": "/result-page",
"icon": "result-page",
"text": "结果页"
},
{ "name": "Ruler", "path": "/ruler", "icon": "ruler", "text": "刻度尺" },
{
"name": "WaterMark",
"path": "/water-mark",
"icon": "water-mark",
"text": "水印"
},
{
"name": "LicensePlate",
"path": "/license-plate",
"icon": "license-plate",
"text": "车牌号"
}
]
},
{
"category": "feedback",
"name": "Feedback",
"text": "操作反馈",
"list": [
{
"name": "ActionSheet",
"path": "/action-sheet",
"icon": "action-sheet",
"text": "动作面板"
},
{
"name": "DatePicker",
"path": "/date-picker",
"icon": "date-picker",
"text": "日期选择器"
},
{
"name": "Dialog",
"path": "/dialog",
"icon": "dialog",
"text": "模态窗"
},
{
"name": "Picker",
"path": "/picker",
"icon": "picker",
"text": "选择器"
},
{ "name": "Popup", "path": "/popup", "icon": "popup", "text": "弹出层" },
{
"name": "Selector",
"path": "/selector",
"icon": "selector",
"text": "列表选择器"
},
{
"name": "TabPicker",
"path": "/tab-picker",
"icon": "tab-picker",
"text": "多频道选择器"
},
{ "name": "Tip", "path": "/tip", "icon": "tip", "text": "气泡提示" },
{ "name": "Toast", "path": "/toast", "icon": "toast", "text": "轻提示" },
{
"name": "Transition",
"path": "/transition",
"icon": "transition",
"text": "动画"
}
]
},
{
"category": "form",
"name": "Form",
"text": "表单相关",
"list": [
{
"name": "Agree",
"path": "/agree",
"icon": "agree",
"text": "勾选按钮"
},
{
"name": "Check",
"path": "/check",
"icon": "check",
"text": "选择项组"
},
{
"name": "Codebox",
"path": "/codebox",
"icon": "codebox",
"text": "字符码输入框"
},
{
"name": "Field",
"path": "/field",
"icon": "field",
"text": "区域列表组合"
},
{
"name": "InputItem",
"path": "/input-item",
"icon": "input-item",
"text": "输入框"
},
{
"name": "NumberKeyboard",
"path": "/number-keyboard",
"icon": "number-keyboard",
"text": "数字键盘"
},
{ "name": "Radio", "path": "/radio", "icon": "radio", "text": "单选框" },
{ "name": "Slider", "path": "/slider", "icon": "slider", "text": "滑块" },
{ "name": "Switch", "path": "/switch", "icon": "switch", "text": "开关" },
{
"name": "TextareaItem",
"path": "/textarea-item",
"icon": "textarea-item",
"text": "文本域"
}
]
},
{
"category": "gesture",
"name": "Gesture",
"text": "手势",
"list": [
{
"name": "ScrollView",
"path": "/scroll-view",
"icon": "scroll-view",
"text": "滚动区域/下拉刷新"
}
]
}
]

View File

@ -49,4 +49,5 @@ export {default as Progress} from '../components/progress/demo'
export {default as Ruler} from '../components/ruler/demo'
export {default as TextareaItem} from '../components/textarea-item/demo'
export {default as Skeleton} from '../components/skeleton/demo'
export {default as LicensePlate} from '../components/license-plate/demo'
/* @init<%export {default as ${componentNameUpper}} from '../components/${componentName}/demo'%> */

View File

@ -65,6 +65,7 @@ export class Transition extends MandComponent { }
export class WaterMark extends MandComponent { }
export class TextareaItem extends MandComponent { }
export class Skeleton extends MandComponent { }
export class LicensePlate extends MandComponent { }
/* @init<%export class ${componentNameUpper} extends MandComponent { }%> */