Commit 63c1508e authored by JingChao's avatar JingChao

修复问题

parent 0ce9e464
......@@ -9,8 +9,6 @@
<!-- safari私有meta标签 允许全屏模式浏览 指定safari顶部状态栏样式(黑色) -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<script type="text/javascript" src="./static/vuePlatform.js"></script>
<script type="text/javascript" src="../../cordova.js"></script>
<title>车租易</title>
</head>
<body>
......
......@@ -50,3 +50,73 @@ export function detectOS () {
return 'other'
}
}
export function range (num, min, max) {
return Math.min(Math.max(num, min), max)
}
function trimExtraChar (value, char, regExp) {
const index = value.indexOf(char)
if (index === -1) {
return value
}
if (char === '-' && index !== 0) {
return value.slice(0, index)
}
return value.slice(0, index + 1) + value.slice(index).replace(regExp, '')
}
export function formatNumber (value, allowDot) {
if (value) {
if (allowDot) {
value = trimExtraChar(value, '.', /\./g)
} else {
value = value.split('.')[0]
}
value = trimExtraChar(value, '-', /-/g)
const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g
return value.replace(regExp, '')
}
}
export function isDef (val) {
return val !== undefined && val !== null && val !== ''
}
export function isUndefined (value) {
return Object.prototype.toString.call(value) === '[object Undefined]'
}
export function isString (value) {
return Object.prototype.toString.call(value) === '[object String]'
}
export function isNumber (value) {
return Object.prototype.toString.call(value) === '[object Number]'
}
export function isBoolean (value) {
return Object.prototype.toString.call(value) === '[object Boolean]'
}
export function isNull (value) {
return Object.prototype.toString.call(value) === '[object Null]'
}
export function isObject (value) {
return Object.prototype.toString.call(value) === '[object Object]'
}
export function isFunction (value) {
return Object.prototype.toString.call(value) === '[object Function]'
}
export function isArray (value) {
return Object.prototype.toString.call(value) === '[object Array]'
}
export function isDate (value) {
return Object.prototype.toString.call(value) === '[object Date]'
}
export function isRegExp (value) {
return Object.prototype.toString.call(value) === '[object RegExp]'
}
......@@ -20,6 +20,7 @@ curreny-input 金额输入框
```
v-model 绑定value值 number值
disable 是否只读 true/false
......@@ -5,19 +5,31 @@
<template>
<input
:value="formatValue" :readonly="disable" type="text"
ref="currencyInput"
v-bind="$attrs"
:value="formatValue" :readonly="readonly" :disabled="disabled" type="text"
@input="onInput($event.target.value)" @focus="onFocus" @blur="onBlur">
</template>
<script>
import {formatNumber} from '../../../packages/common/utils'
export default {
name: 'CurrencyInput',
inheritAttrs: false,
props: {
value: {
type: Number,
type: Number | String,
default: 0,
},
disable: {
decimal: {
type: Boolean,
default: true,
},
disabled: {
type: Boolean,
default: false,
},
readonly: {
type: Boolean,
default: false,
},
......@@ -35,9 +47,16 @@ export default {
},
},
computed: {
inputMode () {
if (this.decimal) {
return 'decimal'
} else {
return 'numeric'
}
},
formatValue () {
let currency = this.$options.filters['currency']
if (!this.focused) {
if (!this.focused && this.value) {
return currency(this.value)
} else {
return this.value
......@@ -46,19 +65,42 @@ export default {
},
methods: {
onInput: function (value) {
const allowDot = this.decimal
value = formatNumber(value, allowDot)
const { currencyInput } = this.$refs
if (currencyInput && value !== currencyInput.value) {
currencyInput.value = value
}
let uncurrency = this.$options.filter['uncurrency']
this.currencyValue = uncurrency(value)
this.$emit('input', this.currencyValue)
},
onFocus (event) {
if (this.readonly || this.disabled) {
if (this.$refs.currencyInput) {
this.$refs.currencyInput.blur()
this.focused = false
}
} else {
this.focused = true
if (this.decimal) {
setTimeout(function () {
event.target.type = 'number'
event.target.type = 'text'
event.target.inputMode = 'decimal'
event.target.focus()
}, 0)
} else {
setTimeout(function () {
event.target.type = 'tel'
event.target.inputMode = 'numeric'
event.target.focus()
}, 0)
}
}
},
onBlur (event) {
event.target.type = 'text'
event.target.inputMode = ''
this.focused = false
},
},
......
/**
* @Author think
* @Date 2020-07-30 09:34
*/
<template>
<div :style="{'min-height':minHeight}" :class="{'h-field-disabled':disabled}" class="h-field h-date">
<div v-if="showLeftIcon" class="field-icon field-left-icon" @click="onClickLeftIcon">
<img v-if="!hasLeftIcon" :src="leftIcon">
<slot name="left-icon"/>
</div>
<div v-if="label" :class="{'required': required}" :style="{'flex':proportion[0] }" class="field-title field-label">
<span>{{ label }}</span>
</div>
<div :style="{'flex':proportion[1] }" class="field-value">
<div class="field-body">
<input
v-bind="$attrs"
v-model="value"
:disabled="disabled" :placeholder="dataPlaceholder" :class="('field-control-'+inputAlign)" class="field-control"
type="text" readonly
@click="showDate">
<!--<slot name="icon"/>-->
<i v-if="showClean" class="field-icon field-right-icon icon ion-close-circled" @click="cleanValue"/>
<!--<slot name="icon"/>-->
<img v-if="!showClean" :src="rightIcon" class="field-right-icon date-field-icon" >
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DateField',
inheritAttrs: false,
props: {
value: {
default: null,
type: String | Date,
},
placeholder: {
type: String,
default: null,
},
clearable: {
type: Boolean,
default: true,
},
format: {
default: 'YYYY-MM-DD',
type: String,
},
minYear: {
type: String,
default: '1800',
},
maxYear: {
type: String,
default: '2500',
},
disabled: {
type: Boolean,
default: false,
},
label: {
type: String,
default: '',
required: true,
},
required: {
type: Boolean,
default: false,
},
inputAlign: {
type: String,
default: 'right',
},
proportion: {
// name/content 横向面积比例
type: Array,
default: () => [1, 2],
},
itemHeight: {
type: Number,
default: 45,
},
showIcon: {
type: Boolean,
default: true,
},
leftIcon: {
type: String,
default: null,
},
rightIcon: {
type: String,
default: require('./right-gray@2x.png'),
},
},
data () {
return {
}
},
computed: {
minHeight () {
if (this.$parent.itemHeight) {
return this.$parent.itemHeight + 'px'
} else {
return this.itemHeight + 'px'
}
},
hasLeftIcon () {
return !!this.$slots['left-icon']
},
showLeftIcon () {
return !!(this.leftIcon || this.$slots['left-icon'])
},
dataPlaceholder () {
return this.placeholder ? this.placeholder : '请输入' + this.label
},
showClean () {
let vm = this
if (vm.disabled) {
return false
}
if (vm.clearable && (vm.value !== '' && vm.value !== undefined && vm.value !== null)) {
return true
} else {
return !vm.showIcon
}
},
},
methods: {
cleanValue () {
this.$emit('input', null)
this.$emit('clean', null)
},
showDate () {
let vm = this
if (!vm.disabled) {
let date = new Date().format('yyyy-MM-dd')
if (vm.value) {
date = vm.value
}
vm.$vux.datetime.show({
cancelText: '取消',
confirmText: '确定',
minYear: vm.minYear,
maxYear: vm.maxYear,
format: vm.format,
value: date,
onConfirm (val) {
vm.$emit('input', val)
vm.$emit('onSelect', val)
},
})
}
},
},
}
</script>
<style lang="less">
.h-date{
background-color: #fff;
position: relative;
.field-value{
.date-field-icon{
height: 0.25rem;
}
}
}
</style>
/**
* @Author think
* @Date 2020-07-30 09:34
*/
<template>
<section :style="{'min-height':minHeight}" class="h-date">
<section :style="{'min-height':minHeight}" :class="{'vue-1px-b':hasBorder}" class="date-border">
<section :class="{'required':required}" :style="{'flex':proportion[0] }" class="name">{{ label }}</section>
<section :style="{'flex':proportion[1] }" class="date-content">
<input
v-model="value" :disabled="disabled" :placeholder="dataPlaceholder" type="text"
readonly
@click="showDate">
<!--<slot name="icon"/>-->
<i v-if="showClean" class="icon ion-close-circled" @click="cleanValue"/>
<!--<slot name="icon"/>-->
<img v-if="!showClean" :src="selectIcon" class="icon" >
</section>
</section>
</section>
</template>
<script>
export default {
name: 'DateFiled',
props: {
value: {
default: null,
type: String | Date,
},
placeholder: {
type: String,
default: null,
},
clearable: {
type: Boolean,
default: false,
},
format: {
default: 'YYYY-MM-DD',
type: String,
},
minYear: {
type: String,
default: '1800',
},
maxYear: {
type: String,
default: '2500',
},
disabled: {
type: Boolean,
default: false,
},
label: {
type: String,
default: '',
required: true,
},
required: {
type: Boolean,
default: false,
},
proportion: {
// name/content 横向面积比例
type: Array,
default: () => [1, 2],
},
itemHeight: {
type: Number,
default: 45,
},
hasBorder: {
type: Boolean,
default: true,
},
showIcon: {
type: Boolean,
default: true,
},
rightIcon: {
type: String,
default: '',
},
},
data () {
return {
Icon: require('./right-gray@2x.png'),
}
},
computed: {
minHeight () {
if (this.$parent.itemHeight) {
return this.$parent.itemHeight + 'px'
} else {
return this.itemHeight + 'px'
}
},
selectIcon () {
return this.rightIcon ? this.rightIcon : this.Icon
},
dataPlaceholder () {
return this.placeholder ? this.placeholder : '请输入' + this.label
},
showClean () {
let vm = this
if (vm.clearable && (vm.value !== '' && vm.value !== undefined && vm.value !== null)) {
return true
} else {
return !vm.showIcon
}
},
},
methods: {
cleanValue () {
this.$emit('input', null)
this.$emit('clean', null)
},
showDate () {
let vm = this
if (!vm.disabled) {
let date = new Date().format('yyyy-MM-dd')
if (vm.value) {
date = vm.value
}
vm.$vux.datetime.show({
cancelText: '取消',
confirmText: '确定',
minYear: vm.minYear,
maxYear: vm.maxYear,
format: vm.format,
value: date,
onConfirm (val) {
vm.$emit('input', val)
vm.$emit('onSelect', val)
},
})
}
},
},
}
</script>
<style lang="less">
.h-date{
width: 100%;
display: flex;
align-items: center;
border: none;
padding: 0 0 0 0.3rem;
background-color: #fff;
.date-border{
width: 100%;
height: 100%;
display: flex;
align-items: center;
padding: 0 0.3rem 0 0;
min-height: 45px;
}
.name{
line-height: 0.5rem;
font-size: 14px;
color: #333;
}
.required {
display: flex;
align-items: center;
}
.required::after {
content: '*';
color: #D24E4E;
//height: 0.16rem;
padding-top: 0.08rem;
margin-left: 0.05rem;
}
.date-content{
height: 100%;
width: 100%;
font-size: 14px;
color: #666;
display: flex;
align-items: center;
input{
font-size: 14px;
color: #666;
line-height: 0.4rem;
width: 100%;
text-align: right;
border: none;
}
.icon{
height: 0.25rem;
margin-left: 4px
}
}
}
</style>
Field 输入框
```html
<h-field v-model="number" label="金额"/>
<h-field
v-model="number" format type="number"
clearable error
required label="金额"/>
<h-field
v-model="name"
clearable
required label="姓名"/>
<h-field
v-model="age"
:decimal="false"
type="number"
clearable error
required label="年龄"/>
<h-field
v-model="phone" :left-icon="leftIcon"
type="tel"
required label="手机号"/>
<h-field
v-model="password"
type="password"
required label="密码">
<i slot="left-icon" class="field-icon field-right-icon icon ion-close-circled"/>
</h-field>
<h-field
v-model="address" :autosize="true"
type="textarea"
inputAlign="left"
rows="1"
error
required label="通讯地址"/>
<h-field
v-model="homeAddress"
:autosize="true"
:word-limit="true" type="textarea" maxlength="50"
inputAlign="left"
clearable error
required label="家庭地址"/>
```
|字段名称 |字段说明 |类型 |必填 |默认 |
| ----|------|-------|------|------|
|value|当前值|String|Y|-|
|type|输入类型|String|N|text|
|decimal|是否支持小数(type=number有效)|Boolean|N|false|
|proportion|label与value比例|Array|N|[1,2]|
|required|是否必填|Boolean|N|false|
|readonly|只读属性|Boolean|N|false|
|disabled|禁用属性|Boolean|N|false|
|itemHeight|字端默认高度|Number|N|45|
|label|输入框左侧文本|String|Y|-|
|leftIcon|左侧图标名称或图片链接|String|N|-|
|rightIcon|右侧图标名称或图片链接|String|N|-|
|clearable|是否启用清除图标,点击清除图标后会清空输入框|Boolean|false|-|
|clearTrigger|显示清除图标的时机,always 表示输入框不为空时展示,focus 表示输入框聚焦且不为空时展示|String|N|focus|
|format|是否启用金额千分位化(type=number有效)|Boolean|false|-|
|maxlength|输入的最大字符数|Number,String|false|-|
|inputAlign|输入框对齐方式,可选值为 center left|String|false|right|
|placeholder|输入框默认提示|String|N|请输入+label|
|showPlaceholder|是否显示placeholder|Boolean|N|true|
|error|必输校验后输入框标红|Boolean|N|false|
|autosize|是否自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为px|Boolean,Object|N|-|
|wordLimit|是否显示字数统计,需要设置maxlength属性|Boolean|N|false|
This diff is collapsed.
......@@ -101,7 +101,7 @@ export default {
this.$refs.input.value = ''
}
},
change ($event) {
change (event) {
let vm = this
let { files } = event.target
if (vm.disabled || !files.length) {
......@@ -124,13 +124,11 @@ export default {
.catch(vm.resetInput)
}
}
vm.fileRead(files)
vm.fileRead(toArray(files))
},
fileRead (files) {
const oversize = isOversize(files, this.maxSize)
if (oversize) {
files = files.filter(file => file.size <= this.maxSize)
}
const oversizeFiles = isOversize(files, this.maxSize)
if (Array.isArray(files)) {
const maxCount = this.maxCount - this.fileList.length
......@@ -144,17 +142,18 @@ export default {
content: contents[index],
}))
this.onAfterRead(fileList, oversize)
this.onAfterRead(fileList, oversizeFiles)
})
} else {
readFile(files, this.resultType).then(content => {
this.onAfterRead({ file: files, content: content }, oversize)
this.onAfterRead({ file: files, content: content }, oversizeFiles)
})
}
},
onAfterRead (files, oversize) {
if (oversize) {
this.$emit('oversize', toArray(files))
onAfterRead (files, oversizeFiles) {
if (oversizeFiles.length) {
this.$emit('oversize', toArray(oversizeFiles))
files = files.filter(file => file.size <= this.maxSize)
// return
}
this.resetInput()
......
......@@ -23,7 +23,7 @@ export function readFile (file, resultType) {
}
export function isOversize (files, maxSize) {
return toArray(files).some(file => file.size > maxSize)
return toArray(files).filter(file => file.size > maxSize)
}
export function isImageDataUrl (dataUrl) {
......
/**
* @Author Think
* @Date 2018/11/24
*/
* @Author Think
* @Date 2018/11/24
*/
<template>
<div :class="{'h-ios': isIos}" class="h-view">
<slot />
<slot/>
</div>
</template>
......@@ -42,39 +42,48 @@ export default {
},
created () {
this.fullScreen && detectOS() === 'ios' && (this.isIos = true)
document.body.classList.add('platform-' + detectOS())
},
}
</script>
<style lang="less" scoped>
.h-view {
<style lang="less">
::selection {
background: #3367d6;
color: #fff;
}
input:hover ,input:focus{
caret-color: #3367d6;
}
.h-view {
width: 100%;
height: 100%;
overflow: hidden;
// padding-bottom: 44px;
// background-color: $bgColor;
}
.platform-ios{
.h-view{
}
.platform-ios {
.h-view {
// padding-bottom: 64px;
}
}
}
// iPhoneX适配
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
// iPhoneX适配
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
.platform-ios {
.h-view {
// padding-bottom: 120px;
}
}
}
}
// iPhoneX Max适配
@media only screen and (device-width: 414px) and (device-height: 896px) {
// iPhoneX Max适配
@media only screen and (device-width: 414px) and (device-height: 896px) {
.platform-ios {
.h-view {
// padding-bottom: 120px;
}
}
}
}
</style>
<template>
<div :class="type" class="function">{{ text }}</div>
<div :class="type" class="function" @click="itemClick">{{ text }}</div>
</template>
<script>
......@@ -22,8 +22,8 @@ export default {
this.$parent && this.$parent.optionItem.splice(this.$parent.optionItem.indexOf(this), 1)
},
methods: {
buttonClick (e) {
this.$emit('press', this.type)
itemClick (e) {
this.$parent && this.$parent.reset()
},
},
}
......
<template>
<div :class="cusClass" class="swipeout-list">
<div ref="item" :class="bottomBorder" class="item" data-type="0">
<div ref="optionItem" :class="bottomBorder" class="option-item" data-type="0">
<div
class="list-box"
@touchstart.capture="touchStart"
......@@ -62,7 +62,7 @@ export default {
},
methods: {
touchStart (ev) {
this.$refs.item.style.transform = 'translate3d(0px,0px,0px)'
this.$refs.optionItem.style.transform = 'translate3d(0px,0px,0px)'
this.reset()
ev = ev || event
// tounches类数组,等于1时表示此时有只有一只手指在触摸屏幕
......@@ -88,7 +88,7 @@ export default {
},
// 判断当前是否有滑块处于滑动状态
checkSlide () {
let listItems = this.$refs.item
let listItems = this.$refs.optionItem
for (let i = 0; i < listItems.length; i++) {
if (listItems[i].dataset.type === '1') {
return true
......@@ -106,10 +106,10 @@ export default {
})
},
reset () {
let l = document.getElementsByClassName('item').length
let l = document.getElementsByClassName('option-item').length
for (let i = 0; i < l; i++) {
document.getElementsByClassName('item')[i].style.transform = 'translate3d(0px,0px,0px)'
document.getElementsByClassName('item')[i].dataset.type = '0'
document.getElementsByClassName('option-item')[i].style.transform = 'translate3d(0px,0px,0px)'
document.getElementsByClassName('option-item')[i].dataset.type = '0'
}
},
},
......@@ -124,14 +124,14 @@ export default {
overflow: visible;
padding: 0 0 0 15px;
width: 100%;
.item[data-type="0"] {
.option-item[data-type="0"] {
transform: translate3d(0px, 0px, 0px);
transition: all 0.4s;
}
.item[data-type="1"] {
.option-item[data-type="1"] {
transition: all 1s;
}
.item {
.option-item {
overflow: visible;
position: relative;
height: 100%;
......
<template>
<div
:class="[showActivated,focus]"
:class="[showActivated,cusClass]"
:style="{'min-height':minHeight}"
class="hls-item">
<div
......@@ -11,14 +11,12 @@
@touchcancel="end"
@mousedown="start"
@mouseup="end"
@mouseleave="end"
@focusin="focusin"
@focusout="focusout">
<div v-if="showName" :style="{'min-height':minHeight,'flex':proportion[0] }" class="add-name">
@mouseleave="end">
<div v-if="showName && hasName" :style="{'min-height':minHeight,'flex':proportion[0] }" class="add-name">
<slot name="left-icon"/>
<slot name="name"/>
</div>
<div v-if="showContent" :style="{'min-height':minHeight,'flex':proportion[1] }" class="add-content">
<div v-if="showContent && hasContent" :style="{'min-height':minHeight,'flex':proportion[1] }" class="add-content">
<slot name="content"/>
<slot name="right-icon"/>
<img v-if="showArrow" :src="rightIcon" class="right-icon" style="height: 0.2rem">
......@@ -55,6 +53,10 @@ export default {
type: String,
default: '',
},
cusClass: {
type: String,
default: '',
},
hasBorder: {
type: Boolean,
default: true,
......@@ -67,7 +69,6 @@ export default {
data () {
return {
showActivated: '',
focus: '',
hasTouchEvent: 'ontouchstart' in document,
Icon: require('./right-gray@2x.png'),
}
......@@ -82,6 +83,12 @@ export default {
bottomBorder () {
return this.hasBorder ? 'vue-1px-b' : ''
},
hasName () {
return !!this.$slots['name'] || !!this.$slots['left-icon']
},
hasContent () {
return !!this.$slots['content'] || !!this.$slots['right-icon']
},
},
mounted () {
},
......@@ -90,12 +97,6 @@ export default {
// 移动浏览器中长按元素会触发显示菜单,导致touchend事件不会触发,需要阻止该行为
e.preventDefault()
},
focusin (e) {
this.focus = 'focus'
},
focusout (e) {
this.focus = ''
},
start (e) {
if (e.target.readOnly) return
if (e.target.nodeName === 'INPUT' || e.target.nodeName === 'TEXTAREA' || e.target.nodeName === 'BUTTON' || e.target.nodeName === 'LABEL') return
......@@ -157,15 +158,15 @@ export default {
}
.required {
display: flex;
position: relative;
}
.required::after {
content: '*';
.required::before {
position: absolute;
left: -8px;
color: #D24E4E;
height: 8px;
padding-top: 2px;
margin-left: 2px;
font-size: 14px;
content: '*';
}
}
......
......@@ -20,7 +20,10 @@ export default {
cusClass: {
type: String,
default: '',
},
showFocusBorder: {
type: Boolean,
default: false,
},
},
data () {
......
......@@ -34,6 +34,10 @@ export default {
type: Boolean,
default: false,
},
showBottomBorder: {
type: Boolean,
default: false,
},
overflowX: {
type: Boolean,
default: true,
......@@ -83,7 +87,7 @@ export default {
throw 'tab index out of bound exception'
} else {
this.defaultActive === value
this.setTabActive(value)
// this.setTabActive(value)
}
},
},
......
......@@ -2,7 +2,7 @@
<section :class="[tabClass]" class="h-tab-item" @click="titleClick">
<div class="h-item">
<slot/>
<div class="bottom-border"/>
<div v-if="showBottomBorder" class="bottom-border"/>
</div>
<div v-show="showDivider" class="tab-divider"/>
</section>
......@@ -21,6 +21,9 @@ export default {
showDivider () {
return this.$parent.showDivider
},
showBottomBorder () {
return this.$parent.showBottomBorder
},
tabClass () {
if (this.$parent.hasBorder) {
return this.$parent.position === 'top' ? 'vue-1px-b' : 'vue-1px-t'
......
......@@ -13,7 +13,7 @@ export default {
data () {
return {
width: 50,
height: 80,
height: 60,
}
},
computed: {
......@@ -33,10 +33,10 @@ export default {
this.ratio = 1
this.width *= this.ratio
this.height *= this.ratio
this.initRadius = 18 * this.ratio
this.initRadius = 11 * this.ratio // 外面阴影
this.minHeadRadius = 12 * this.ratio
this.minTailRadius = 5 * this.ratio
this.initArrowRadius = 10 * this.ratio
this.initArrowRadius = 6 * this.ratio // 里面的刷新
this.minArrowRadius = 6 * this.ratio
this.arrowWidth = 3 * this.ratio
this.maxDistance = 40 * this.ratio
......
......@@ -36,7 +36,8 @@
:bubbleY="bubbleY"
name="pulldown"
>
<div v-if="pullDown" ref="pulldown" :style="pullDownStyle" :class="c('__pulldown')">
<div
v-if="pullDown" ref="pulldown" :style="pullDownStyle" :class="c('__pulldown')">
<div v-if="pullDownBefore" :class="c('__pulldown__before')">
<Bubble :y="bubbleY"/>
</div>
......@@ -113,8 +114,8 @@ export default {
// 下拉刷新配置
type: Object,
default: () => ({
threshold: 90, // 触发 pullingDown 的距离
stop: 40, // pullingDown 正在刷新 hold 时的距离
threshold: 40, // 触发 pullingDown 的距离
stop: 20, // pullingDown 正在刷新 hold 时的距离
txt: '刷新成功',
}),
},
......@@ -188,6 +189,9 @@ export default {
bubbleY: 0, // 气泡y坐标,
isIos: false,
fullScreen: true,
fontSize: Number(window.document.documentElement.style.fontSize.replace('px', '')),
winHeight: window.innerHeight,
winWidth: window.innerWidth,
}
},
computed: {
......@@ -220,7 +224,7 @@ export default {
this.fullScreen && detectOS() === 'ios' && (this.isIos = true)
},
async mounted () {
this.pullDownInitTop = parseInt(this.$refs.pulldown && getComputedStyle(this.$refs.pulldown).top) || -100
this.pullDownInitTop = parseInt(this.$refs.pulldown && getComputedStyle(this.$refs.pulldown).top) || -60
await this.$nextTick()
this.initScroll()
......@@ -232,6 +236,60 @@ export default {
})
},
methods: {
getHeaderHeight () {
let vm = this
let $el = vm.$el.previousElementSibling
let headerHeight = 0
do {
if ($el) {
let elHeight = window.getComputedStyle($el).height
let part = /^\d+(\.\d+)?px$/
if (elHeight && part.test(elHeight)) {
headerHeight += Number(elHeight.replace('px', ''))
}
if ($el._prevClass && $el._prevClass.indexOf('h-header') === 0) {
if (detectOS() === 'ios' && vm.winWidth === 375 && vm.winHeight === 812) {
headerHeight += 0.8 * vm.fontSize
} else if (detectOS() === 'ios' && vm.winWidth === 414 && vm.winHeight === 896) {
headerHeight += 0.8 * vm.fontSize
} else if (detectOS() === 'ios') {
headerHeight += 0.4 * vm.fontSize
}
}
$el = $el.previousElementSibling
}
} while ($el)
return headerHeight
},
getNextElementHeight () {
let vm = this
let nextElement = this.$el.nextElementSibling
let nextHeight = 0
do {
if (nextElement) {
let elHeight = window.getComputedStyle(nextElement).height
let part = /^\d+(\.\d+)?px$/
if (elHeight && part.test(elHeight)) {
nextHeight += Number(elHeight.replace('px', ''))
}
if (nextElement._prevClass && nextElement._prevClass.indexOf('h-bottom-tab') === 0) {
let height = nextElement.clientHeight
if (detectOS() === 'ios' && height > Math.ceil(vm.fontSize * 0.88)) {
nextHeight += 0
} else {
if (detectOS() === 'ios' && vm.winWidth === 375 && vm.winHeight === 812) {
nextHeight += vm.fontSize * 0.68
} else if (detectOS() === 'ios' && vm.winWidth === 414 && vm.winHeight === 896) {
nextHeight += vm.fontSize * 0.68
}
}
}
nextElement = nextElement.nextElementSibling
}
} while (nextElement)
return nextHeight
},
// 初始化scroll
initScroll () {
let vm = this
......@@ -239,7 +297,10 @@ export default {
// 设置scrollContent的最小高,实现高度不足时也有回弹效果
if (this.$refs.scrollContent) {
const headerHeight = vm.getHeaderHeight()
// const nextHeight = vm.getNextElementHeight()
this.$refs.scrollContent.style.minHeight = `${this.$refs.scroll.getBoundingClientRect().height + 1}px`
this.$refs.scrollContent.style.paddingTop = `${headerHeight}px`
if (vm.hasFoot.footFlag) {
let height = vm.hasFoot.height || 88
// this.$refs.scrollContent.style.minHeight = `${this.$refs.scroll.getBoundingClientRect().height - height}px`
......@@ -408,7 +469,8 @@ export default {
width 100%
overflow hidden !important
box-sizing border-box
position relative
position absolute !important
top 0
height 100%
&__wrapper {
......@@ -422,7 +484,7 @@ export default {
text-size-adjust: none;
-webkit-transform-origin: left top;
transform-origin: left top;
padding-bottom: 0.9rem;
padding-bottom: 0.4rem;
}
&__pullup {
......@@ -438,7 +500,7 @@ export default {
&__pulldown {
position absolute
left 0
top -50px; /*no*/
top 0; /*no*/
width 100%
display flex
justify-content center
......@@ -461,20 +523,24 @@ export default {
}
}
}
.has-footer {
.vue-better-scroll__wrapper {
padding-bottom: 1rem;
}
}
.platform-ios{
.vue-better-scroll {
&__wrapper {
// padding-bottom: 2.16rem;
.has-footer {
.vue-better-scroll__wrapper {
padding-bottom: 1rem;
}
}
}
// iPhoneX适配
@media (device-width: 375px) and (device-height: 812px) and (-webkit-min-device-pixel-ratio: 3) {
.platform-ios {
.vue-better-scroll {
&__wrapper {
// padding-bottom: 2.84rem;
.has-footer {
.vue-better-scroll__wrapper {
padding-bottom: 1.8rem;
}
}
}
......@@ -483,9 +549,9 @@ export default {
// iPhoneX Max适配
@media (device-width: 414px) and (device-height: 896px) {
.platform-ios {
.vue-better-scroll {
&__wrapper {
// padding-bottom: 2.84rem;
.has-footer {
.vue-better-scroll__wrapper {
padding-bottom: 1.8rem;
}
}
}
......
/**
* @Author think
* @Date 2020-07-30 09:34
*/
<template>
<div :style="{'min-height':minHeight}" :class="{'h-field-disabled':disabled}" class="h-field h-select">
<div v-if="showLeftIcon" class="field-icon field-left-icon" @click="onClickLeftIcon">
<img v-if="!hasLeftIcon" :src="leftIcon">
<slot name="left-icon"/>
</div>
<div v-if="label" :class="{'required': required}" :style="{'flex':proportion[0] }" class="field-title field-label">
<span>{{ label }}</span>
</div>
<div :style="{'flex':proportion[1] }" class="field-value">
<div class="field-body">
<input
v-bind="$attrs"
v-model="codeName" :disabled="disabled" :placeholder="selectPlaceholder" :class="('field-control-'+inputAlign)"
type="text" class="field-control"
readonly
@click="showSelect">
<input v-model="value" type="text" hidden>
<i v-if="showClean" class="field-icon field-right-icon icon ion-close-circled" @click="cleanValue"/>
<!--<slot name="icon"/>-->
<img v-if="!showClean" :src="rightIcon" class="field-right-icon date-field-icon" >
</div>
</div>
</div>
<!--</section>-->
</template>
<script>
import VueSelect from './index'
export default {
name: 'SelectField',
inheritAttrs: false,
props: {
value: {
default: null,
type: Number | String,
},
placeholder: {
type: String,
default: null,
},
clearable: {
type: Boolean,
default: true,
},
dataArray: {
type: Array,
default: () => [],
},
multiple: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
valueKey: {
type: String,
default: 'code',
},
valueName: {
type: String,
default: 'code_name',
},
code: {
type: String,
default: 'code',
},
object: {
type: Object,
default: () => {},
},
label: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
proportion: {
// name/content 横向面积比例
type: Array,
default: () => [1, 2],
},
itemHeight: {
type: Number,
default: 45,
},
inputAlign: {
type: String,
default: 'right',
},
showIcon: {
type: Boolean,
default: true,
},
leftIcon: {
type: String,
default: null,
},
rightIcon: {
type: String,
default: require('./right-gray@2x.png'),
},
},
data () {
return {
}
},
computed: {
hasLeftIcon () {
return !!this.$slots['left-icon']
},
showLeftIcon () {
return !!(this.leftIcon || this.$slots['left-icon'])
},
codeName () {
let vm = this
let name
if (vm.multiple) {
name = []
if (Array.isArray(vm.value)) {
vm.dataArray.forEach((selectItem, listIndex, listArray) => {
vm.value.forEach((index, item, array) => {
if (selectItem[vm.valueKey] === item) {
name.push(selectItem[vm.valueName])
}
})
})
} else {
console.error('multiple select value must be Array')
}
} else {
vm.dataArray.forEach((selectItem, listIndex, listArray) => {
// eslint-disable-next-line eqeqeq
if (selectItem[vm.valueKey] == vm.value) {
name = selectItem[vm.valueName]
}
})
}
return name
},
showClean () {
let vm = this
if (vm.disabled) {
return false
}
if (vm.clearable && (vm.value !== '' && vm.value !== undefined && vm.value !== null)) {
return true
} else {
return !vm.showIcon
}
},
minHeight () {
if (this.$parent.itemHeight) {
return this.$parent.itemHeight + 'px'
} else {
return this.itemHeight + 'px'
}
},
selectPlaceholder () {
return this.placeholder ? this.placeholder : '请选择' + this.label
},
},
methods: {
selectCall (v1, v2, v3) {
let vm = this
if (!vm.multiple) {
this.$emit('input', v2[vm.code])
this.$emit('onSelect', v1, v2, v3)
} else {
this.$emit('input', v1)
this.$emit('onSelect', v1, v2)
}
},
cleanValue () {
this.$emit('input', null)
this.$emit('clean', null)
},
showSelect () {
let vm = this
if (!vm.disabled) {
let list = []
vm.dataArray.forEach((date, index, array) => {
list.push({
value: date[vm.valueKey],
name: date[vm.valueName],
parent: date.parent,
})
})
VueSelect.show({
list: list,
callBack: vm.selectCall,
code: vm.code,
object: vm.object || {},
multiple: vm.multiple,
})
}
},
},
}
</script>
<style lang="less">
.h-select{
background-color: #fff;
position: relative;
.field-value{
.date-field-icon{
height: 0.25rem;
}
}
}
</style>
/**
* @Author think
* @Date 2020-07-30 09:34
*/
<template>
<section :style="{'min-height':minHeight}" class="h-select">
<section :style="{'min-height':minHeight}" :class="{'vue-1px-b':hasBorder}" class="select-border">
<section :class="{'required':required}" :style="{'flex':proportion[0] }" class="name">{{ label }}</section>
<section :style="{'flex':proportion[1] }" class="select-content">
<input
v-model="codeName" :disabled="disabled" :placeholder="selectPlaceholder" type="text"
readonly
@click="showSelect">
<input v-model="value" type="text" hidden>
<i v-if="showClean" class="icon ion-close-circled" @click="cleanValue"/>
<!--<slot name="icon"/>-->
<img v-if="!showClean" :src="selectIcon" class="icon" >
</section>
</section>
</section>
</template>
<script>
import VueSelect from './index'
export default {
name: 'SelectFiled',
props: {
value: {
default: null,
type: Number | String,
},
placeholder: {
type: String,
default: null,
},
clearable: {
type: Boolean,
default: false,
},
dataArray: {
type: Array,
default: () => [],
},
multiple: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
valueKey: {
type: String,
default: 'code',
},
valueName: {
type: String,
default: 'code_name',
},
code: {
type: String,
default: 'code',
},
object: {
type: Object,
default: () => {},
},
label: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
proportion: {
// name/content 横向面积比例
type: Array,
default: () => [1, 2],
},
itemHeight: {
type: Number,
default: 45,
},
hasBorder: {
type: Boolean,
default: true,
},
showIcon: {
type: Boolean,
default: true,
},
rightIcon: {
type: String,
default: '',
},
},
data () {
return {
Icon: require('./right-gray@2x.png'),
}
},
computed: {
codeName () {
let vm = this
let name
if (vm.multiple) {
name = []
if (Array.isArray(vm.value)) {
vm.dataArray.forEach((selectItem, listIndex, listArray) => {
vm.value.forEach((index, item, array) => {
if (selectItem[vm.valueKey] === item) {
name.push(selectItem[vm.valueName])
}
})
})
} else {
console.error('multiple select value must be Array')
}
} else {
vm.dataArray.forEach((selectItem, listIndex, listArray) => {
// eslint-disable-next-line eqeqeq
if (selectItem[vm.valueKey] == vm.value) {
name = selectItem[vm.valueName]
}
})
}
return name
},
showClean () {
let vm = this
if (vm.clearable && (vm.value !== '' && vm.value !== undefined && vm.value !== null)) {
return true
} else {
return !vm.showIcon
}
},
minHeight () {
if (this.$parent.itemHeight) {
return this.$parent.itemHeight + 'px'
} else {
return this.itemHeight + 'px'
}
},
selectIcon () {
return this.rightIcon ? this.rightIcon : this.Icon
},
selectPlaceholder () {
return this.placeholder ? this.placeholder : '请选择' + this.label
},
},
methods: {
selectCall (v1, v2, v3) {
let vm = this
if (!vm.multiple) {
this.$emit('input', v2[vm.code])
this.$emit('onSelect', v1, v2, v3)
} else {
this.$emit('input', v1)
this.$emit('onSelect', v1, v2)
}
},
cleanValue () {
this.$emit('input', null)
this.$emit('clean', null)
},
showSelect () {
let vm = this
if (!vm.disabled) {
let list = []
vm.dataArray.forEach((date, index, array) => {
list.push({
value: date[vm.valueKey],
name: date[vm.valueName],
parent: date.parent,
})
})
VueSelect.show({
list: list,
callBack: vm.selectCall,
code: vm.code,
object: vm.object || {},
multiple: vm.multiple,
})
}
},
},
}
</script>
<style lang="less">
.h-select{
width: 100%;
display: flex;
align-items: center;
border: none;
padding: 0 0 0 0.3rem;
background-color: #fff;
.select-border{
width: 100%;
height: 100%;
display: flex;
align-items: center;
padding: 0 0.3rem 0 0;
min-height: 45px;
}
.name{
line-height: 0.5rem;
font-size: 14px;
color: #333;
}
.required {
display: flex;
align-items: center;
}
.required::after {
content: '*';
color: #D24E4E;
//height: 0.16rem;
padding-top: 0.08rem;
margin-left: 0.05rem;
}
.select-content{
height: 100%;
width: 100%;
font-size: 14px;
color: #666;
display: flex;
align-items: center;
input{
font-size: 14px;
color: #666;
line-height: 0.4rem;
width: 100%;
text-align: right;
border: none;
}
.icon{
height: 0.25rem;
margin-left: 4px
}
}
}
</style>
......@@ -30,8 +30,9 @@ import HLayout from './HLayout/index'
import CurrencyInput from './CurrencyInput/index'
import HProgress from './Progress/index'
import HRange from './Range/index'
import SelectFiled from './Select/SelectFiled'
import DateFiled from './DateFiled/index'
import SelectField from './Select/SelectField'
import DateField from './DateField/index'
import Field from './Field/index'
import errLoadingPic from '../common/picture/errloading.jpg'
......@@ -70,6 +71,7 @@ export default (Vue) => {
Vue.component('currency-input', CurrencyInput)
Vue.component('h-progress', HProgress)
Vue.component('h-range', HRange)
Vue.component('SelectFiled', SelectFiled)
Vue.component('DateFiled', DateFiled)
Vue.component('SelectField', SelectField)
Vue.component('DateField', DateField)
Vue.component('h-field', Field)
}
......@@ -27,8 +27,9 @@ import HLayout from './components/HLayout/index'
import CurrencyInput from './components/CurrencyInput/index'
import HProgress from './components/Progress/index'
import HRange from './components/Range/index'
import SelectFiled from './components/Select/SelectFiled'
import DateFiled from './components/DateFiled/index'
import SelectField from './components/Select/SelectField'
import DateField from './components/DateField/index'
import Field from './components/Field/index'
import componentInstall from './components/component'
// compontenPlugins
......@@ -73,8 +74,9 @@ export {
CurrencyInput,
HProgress,
HRange,
SelectFiled,
DateFiled,
SelectField,
DateField,
Field,
ActionSheetPlugin,
ShowPicturePlugin,
SelectPlugin,
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment