diff --git a/components/_style/images/license-keyboard-del.png b/components/_style/images/license-keyboard-del.png new file mode 100644 index 000000000..588066b94 Binary files /dev/null and b/components/_style/images/license-keyboard-del.png differ diff --git a/components/_style/images/new-energy.png b/components/_style/images/new-energy.png new file mode 100644 index 000000000..24295cd4c Binary files /dev/null and b/components/_style/images/new-energy.png differ diff --git a/components/index.js b/components/index.js index c3339a1d0..32877e080 100644 --- a/components/index.js +++ b/components/index.js @@ -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},%> */ } diff --git a/components/license-plate-input/index.vue b/components/license-plate-input/index.vue new file mode 100644 index 000000000..bfe985017 --- /dev/null +++ b/components/license-plate-input/index.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/components/license-plate-keyboard/index.vue b/components/license-plate-keyboard/index.vue new file mode 100644 index 000000000..dde4fd766 --- /dev/null +++ b/components/license-plate-keyboard/index.vue @@ -0,0 +1,69 @@ + + + diff --git a/components/license-plate-keyboard/mixed-key-board.vue b/components/license-plate-keyboard/mixed-key-board.vue new file mode 100644 index 000000000..fd0ce4eb9 --- /dev/null +++ b/components/license-plate-keyboard/mixed-key-board.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/components/license-plate-keyboard/short-cut-row.vue b/components/license-plate-keyboard/short-cut-row.vue new file mode 100644 index 000000000..13547304c --- /dev/null +++ b/components/license-plate-keyboard/short-cut-row.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/components/license-plate/README.en-US.md b/components/license-plate/README.en-US.md new file mode 100644 index 000000000..627dd19ad --- /dev/null +++ b/components/license-plate/README.en-US.md @@ -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 + + +### 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 diff --git a/components/license-plate/README.md b/components/license-plate/README.md new file mode 100644 index 000000000..6e32807e1 --- /dev/null +++ b/components/license-plate/README.md @@ -0,0 +1,38 @@ +--- +title: LicensePlate 车牌键盘 +preview: +--- + +专用于车牌输入键盘 + +### 引入 + +```javascript +import { LicensePlate } from 'mand-mobile' + +Vue.component(LicensePlate.name, LicensePlate) +``` + +### 代码演示 + + +### 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() +键盘确认事件 diff --git a/components/license-plate/component.js b/components/license-plate/component.js new file mode 100644 index 000000000..c98a71138 --- /dev/null +++ b/components/license-plate/component.js @@ -0,0 +1,7 @@ +export default { + 'name': 'license-plate', + 'text': '车牌号键入', + 'category': 'business', + 'description': '车牌号输入键盘', + 'author': 'weishuodan' +} diff --git a/components/license-plate/demo/cases/demo0.vue b/components/license-plate/demo/cases/demo0.vue new file mode 100644 index 000000000..68245d832 --- /dev/null +++ b/components/license-plate/demo/cases/demo0.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/components/license-plate/demo/cases/demo1.vue b/components/license-plate/demo/cases/demo1.vue new file mode 100644 index 000000000..a6d609ed5 --- /dev/null +++ b/components/license-plate/demo/cases/demo1.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/components/license-plate/demo/index.vue b/components/license-plate/demo/index.vue new file mode 100644 index 000000000..7479b2a07 --- /dev/null +++ b/components/license-plate/demo/index.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/components/license-plate/index.vue b/components/license-plate/index.vue new file mode 100644 index 000000000..e29ad8a8a --- /dev/null +++ b/components/license-plate/index.vue @@ -0,0 +1,514 @@ + + + + + + diff --git a/components/license-plate/test/cases/demo0.vue b/components/license-plate/test/cases/demo0.vue new file mode 100644 index 000000000..8519fa935 --- /dev/null +++ b/components/license-plate/test/cases/demo0.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/components/license-plate/test/demo.spec.js b/components/license-plate/test/demo.spec.js new file mode 100644 index 000000000..9513a5178 --- /dev/null +++ b/components/license-plate/test/demo.spec.js @@ -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() + }) +}) diff --git a/components/license-plate/util.js b/components/license-plate/util.js new file mode 100644 index 000000000..4256beb08 --- /dev/null +++ b/components/license-plate/util.js @@ -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) + }) +} diff --git a/examples/components.json b/examples/components.json index 95073ca53..60208cf12 100644 --- a/examples/components.json +++ b/examples/components.json @@ -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":"滚动区域/下拉刷新"}]}] \ No newline at end of file +[ + { + "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": "滚动区域/下拉刷新" + } + ] + } +] diff --git a/examples/demo-index.js b/examples/demo-index.js index 98cfeb8b5..07c48d02b 100644 --- a/examples/demo-index.js +++ b/examples/demo-index.js @@ -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'%> */ diff --git a/types/mand-mobile.d.ts b/types/mand-mobile.d.ts index 332abf593..3e908f6c2 100644 --- a/types/mand-mobile.d.ts +++ b/types/mand-mobile.d.ts @@ -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 { }%> */