Commit a6faeefe authored by JingChao's avatar JingChao

SelectFiled与DateFiled

parent e7960d27
DateFiled 日期组建
```html
<DateFiled
v-model="nowDate" :required="true" label="时间"
@onSelect="select"/>
data () {
return {
nowDate: '2020-12-25',
}
}
```
|字段名称 |字段说明 |类型 |必填 |默认 |
| ----|------|-------|------|------|
|value|当前值|String|Y|-|
|format|格式化类型|String|N|YYYY-MM-DD|
|minYear|最小年份|String|N|1800|
|maxYear|最大年份|String|N|2500|
|disabled|是否禁用|Boolean|N|false|
|label|字端名称|String|Y|-|
|required|必输|Boolean|N|false|
|proportion|字端明与字端占比|Array|N|[1,2]|
|itemHeight|字端默认高度|Number|N|45|
|hasBorder|是否有下边框|Boolean|N|true|
|showIcon|右边下拉箭头|Boolean|N|true|
|rightIcon|自定义下拉箭头|String|N|-|
|@onSelect|下拉框选中函数|Function|N|-|
/**
* @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" type="text" readonly
@click="showDate">
<!--<slot name="icon"/>-->
<img v-if="showIcon" :src="selectIcon" class="icon" >
</section>
</section>
</section>
</template>
<script>
export default {
name: 'DateFiled',
props: {
value: {
default: null,
type: String | Date,
},
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
},
},
methods: {
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>
h-progress 进度条
```html
<h-progress :percent="70" :progress-bg="progressBg" :progress-act-bg="progressActBg"/>
export default {
data() {
return {
percent: 40,
progressBg: 'rgba(0,0,0,.3)'
progressActBg: '#0041c4'
}
}
}
```
percent 当前进度
progressBg 进度条整体背景色
progressActBg 当前进度背景色
/**
* @Author think
* @Date 2020-07-20 14:47
*/
<template>
<div :style="{backgroundColor:progressBg}" class="h-progress">
<div :style="{width:percent+'%',backgroundColor: progressActBg}" class="h-progress-bar"/>
</div>
</template>
<script>
export default {
name: 'HProgress',
props: {
percent: {
request: true,
type: Number,
default: 0,
},
progressBg: {
type: String,
default: 'rgba(0,0,0,.1)',
},
progressActBg: {
type: String,
default: '#0041c4',
},
},
data () {
return {}
},
methods: {},
}
</script>
<style lang="less">
.h-progress{
width: 100%;
height: 3px;
.h-progress-bar{
height: 100%;
}
}
</style>
h-range 滑块
```html
<h-range
:decimal="decimal" v-model="rangeValue" :min="min" :max="max"
:step="step" :disabled="disabled" :disabled-opacity="disabledOpacity" :range-bar-height="rangeBarHeight"
:range-handle-height="rangeHandleHeight" @change="change" @touchstart="touchStart" @touchend="touchEnd"/>
export default {
data() {
return {
decimal: false,
rangeValue: 40,
min: 20,
max: 80,
step: 10,
disabled: true,
disabledOpacity: 0.5,
rangeBarHeight: 1,
rangeHandleHeight: 20,
}
},
methods:{
change (val) {
// this.rangeValue = val
console.log(val)
},
touchStart (e) {
console.log(e)
},
touchEnd (e) {
console.log(e)
},
}
}
```
decimal 是否展示小数 默认false
value 当前滑块值
min 滑块最小值 默认0
max 滑块最大值 默认100
step 滑块步长 默认1
disable 是否禁用 默认false
disabled-opacity 禁用时透明度 默认0.7
range-bar-height 滑道高度 默认1
range-handle-height 滑块高度 默认20
@change 滑块滑动触犯事件 返回当前value值
@touchstart 滑块开始滑动事件
@touchEnd 滑块结束滑动事件
/**
* @Author think
* @Date 2020-07-20 16:47
*/
<template>
<section class="h-range">
<Range
:decimal="decimal" v-model.number="currentValue" :min="min" :max="max"
:maxHTML="maxHTML" :minHTML="minHTML"
:step="step" :disabled="disabled" :disabled-opacity="disabledOpacity" :range-bar-height="rangeBarHeight"
:range-handle-height="rangeHandleHeight" @on-change="change" @on-touchstart="touchStart" @on-touchend="touchEnd"/>
</section>
</template>
<script>
import {Range} from 'vux'
export default {
name: 'HRange',
components: {
Range,
},
props: {
decimal: {
type: Boolean,
default: false,
},
value: {
default: 0,
type: Number,
},
min: {
type: Number,
default: 0,
},
minHTML: {
type: String,
default: '',
},
maxHTML: {
type: String,
default: '',
},
max: {
type: Number,
default: 100,
},
step: {
type: Number,
default: 1,
},
disabled: {
type: Boolean,
default: false,
},
disabledOpacity: {
type: Number,
default: 0.7,
},
rangeBarHeight: {
type: Number,
default: 1,
},
rangeHandleHeight: {
type: Number,
default: 20,
},
},
data () {
return {
currentValue: 0,
}
},
created () {
this.currentValue = this.value
},
mounted () {
let vm = this
setTimeout(() => {
vm.$el.querySelector('.range-handle').style.width = `${vm.rangeHandleHeight}px`
vm.$el.querySelector('.range-handle').style.height = `${vm.rangeHandleHeight}px`
vm.$el.querySelector('.vux-range-input-box').style.marginRight = '40px'
vm.$el.querySelector('.vux-range-input-box').style.marginLeft = '40px'
}, 10)
},
methods: {
change (val) {
this.$emit('input', val)
this.$emit('change', val)
},
touchStart (e) {
this.$emit('touchstart', e)
},
touchEnd (e) {
this.$emit('touchend', e)
},
},
}
</script>
<style lang="less">
.h-range{
// height: 100%;
.range-handle{
height: 20px;
width: 20px;
}
}
</style>
......@@ -109,3 +109,37 @@ select下拉框 插件形式调用
})
},
```
SelectFiled 下拉组建
```html
<SelectFiled
v-model="sex" :dataArray="sexList" :required="true" label="性别"
value-key="code_value"
value-name="code_value_name" @onSelect="select"/>
data () {
return {
sex: 0,
sexList: [{'code_value': 0, 'code_value_name': '女'}, {'code_value': 1, 'code_value_name': '男'}],
}
}
```
|字段名称 |字段说明 |类型 |必填 |默认 |
| ----|------|-------|------|------|
|value|当前值|string|Y|-|
|dataArray|下拉框数据源|Array|Y|-|
|multiple|是否多选|Boolean|N|false|
|disabled|是否禁用|Boolean|N|false|
|valueKey|对应数据源中的存表字端|String|N|code|
|valueName|对应数据源中的展示字端|String|N|code_name|
|label|字端名称|String|Y|-|
|required|必输|Boolean|N|false|
|proportion|字端明与字端占比|Array|N|[1,2]|
|itemHeight|字端默认高度|Number|N|45|
|hasBorder|是否有下边框|Boolean|N|true|
|showIcon|右边下拉箭头|Boolean|N|true|
|rightIcon|自定义下拉箭头|String|N|-|
|@onSelect|下拉框选中函数|Function|N|-|
/**
* @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" type="text" readonly
@click="showSelect">
<input v-model="value" type="text" hidden>
<!--<slot name="icon"/>-->
<img v-if="showIcon" :src="selectIcon" class="icon" >
</section>
</section>
</section>
</template>
<script>
import VueSelect from './index'
export default {
name: 'SelectFiled',
props: {
value: {
default: null,
type: Number | String,
},
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
},
minHeight () {
if (this.$parent.itemHeight) {
return this.$parent.itemHeight + 'px'
} else {
return this.itemHeight + 'px'
}
},
selectIcon () {
return this.rightIcon ? this.rightIcon : this.Icon
},
},
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)
}
},
showSelect () {
let vm = this
if (!vm.disabled) {
let list = []
vum.forEach(vm.dataArray, (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>
<template>
<div :class="{'active': state == 1}" class="show-select-backdrop" @click="returnItem(-1)">
<h-content
<div :class="{'active': state == 1}" class="show-select-backdrop" @click.self="returnItem(-1)">
<div
ref="selectWrap"
:class="{'show-select-up': state == 1}"
class="show-select-wrapper">
<!-- <popup-header
......@@ -18,15 +19,32 @@
{{ confirmText }}
</div>
</h-header>
<h-content :cal-content="false" :style="{'height':contentHeight}" :class="{'select-content':multiple}">
<Picker
v-if="!multiple"
:data="list"
v-model="tempValue"
:columns="3"
:key="index"
@on-change="onPickerChange"
/>
<list-item
v-if="multiple" :item-height="35" @click.native.stop="stop">
<item/>
<input v-model="value" hidden>
<item
v-for="(item,index) in list" :key="index" :show-name="false" :class="{'selected':selectedIndex[index]}"
@click.native="selected($event,index,item)">
<div slot="content" class="select-item"><p>{{ item.name }}</p>
<input v-model="item.value" hidden>
</div>
<!--<i slot="right-icon" :class="{'selected':selectedIndex[index]}" class="icon ion-android-done"/>-->
</item>
<item/>
</list-item>
</h-content>
</div>
</div>
</template>
<style lang="less" scoped>
.show-select-backdrop {
......@@ -55,7 +73,7 @@
width: 100%;
left: 0;
top: auto;
padding-top: 0px;
padding-top: 0;
background-color: #fff;
.h-header {
......@@ -63,8 +81,15 @@
color: #828282;
}
.h-header-right .h-header-btn {
color: #5D98F6;
color: #5d98f6;
}
}
.content{
background-color: #fff;
}
.select-content{
// display: flex;
// align-items: center;
}
}
......@@ -72,6 +97,24 @@
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.hls-list-item{
.hls-item{
.add-content{
.select-item{
width: 100%;
text-align: center;
}
}
}
.selected{
.add-content{
p{
color: #5d98f6;
}
}
}
}
}
.modal-open [vum-show-select] {
......@@ -79,13 +122,14 @@
}
</style>
<script>
// eslint-disable-next-line import/no-extraneous-dependencies
import assign from 'object-assign'
import { Picker } from 'vux'
export default {
components: {
Picker
Picker,
},
data () {
return {
......@@ -94,18 +138,22 @@ export default {
list: [],
object: {},
index: 0,
multiple: false,
},
contentHeight: '380px',
multiple: false,
popupTitle: '',
cancelText: '取消',
confirmText: '确定',
code: '',
value: '',
name: '',
value: [],
name: [],
list: [],
object: {},
state: 0,
tempValue: [],
index: '',
selectedIndex: [],
callBack: null,
childs: {
index: '',
......@@ -129,22 +177,34 @@ export default {
methods: {
show (options) {
let vm = this
let _options = assign({}, this.defaultOptions, options)
this.code = _options.code
this.list = _options.list
this.object = _options.object
this.callBack = _options.callBack
this.multiple = _options.multiple
this.state = 1
this.list.forEach((item, index, array) => {
this.selectedIndex.push(0)
})
setTimeout(function () {
vm.contentHeight = vm.$refs.selectWrap.clientHeight - 44 + 'px'
}, 100)
},
returnItem (index) {
let vm = this
if (index > -1) {
if (!vm.multiple) {
let code = vm.code
let code_name = vm.code + '_n' // eslint-disable-line
vm.object[code] = vm.value
vm.object[code_name] = vm.name // eslint-disable-line
vm.callBack(vm.index, vm.object, vm.childs)
} else {
vm.callBack(vm.value, vm.name)
}
}
this.state = 0
let wrapper = document.querySelector('[vum-show-select]')
......@@ -200,6 +260,13 @@ export default {
vm.value = val[0]
this.findIndex(vm.list, vm.value)
},
stop (e) {
},
selected (e, index, item) {
this.selectedIndex[index] = !this.selectedIndex[index]
this.value.includes(item.value) ? this.value = this.value.filter(n => n !== item.value) : this.value.push(item.value)
this.name.includes(item.name) ? this.name = this.name.filter(n => n !== item.name) : this.name.push(item.name)
},
},
}
</script>
......@@ -28,6 +28,10 @@ import TabButton from './BottomTab/tab-button'
import Modal from './Modal/Modal'
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 errLoadingPic from '../common/picture/errloading.jpg'
......@@ -64,4 +68,8 @@ export default (Vue) => {
Vue.component('h-file', HFile)
Vue.component('h-layout', HLayout)
Vue.component('currency-input', CurrencyInput)
Vue.component('h-progress', HProgress)
Vue.component('h-range', HRange)
Vue.component('SelectFiled', SelectFiled)
Vue.component('DateFiled', DateFiled)
}
......@@ -25,12 +25,16 @@ import TabButton from './components/BottomTab/tab-button'
import HFile from './components/HFile/index'
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 componentInstall from './components/component'
// compontenPlugins
import ActionSheetPlugin from './components/ActionSheet/index'
import ShowPicturePlugin from './components/ShowPicture/index'
import SelectPlugin from './components/select/index'
import SelectPlugin from './components/Select/index'
import NotifyPlugin from './components/Dialog/plugins/index'
import NumberKeyboardPlugin from './components/NumberKeyboard/index'
......@@ -67,6 +71,10 @@ export {
HFile,
HLayout,
CurrencyInput,
HProgress,
HRange,
SelectFiled,
DateFiled,
ActionSheetPlugin,
ShowPicturePlugin,
SelectPlugin,
......
......@@ -10,6 +10,7 @@
<tab-item>Vue</tab-item>
<tab-item>APP</tab-item>
</s-tab>
<div style="backgroundColor:red;height:50px"/>
<h-content >
<list-item>
<item>
......@@ -30,15 +31,17 @@
</item>
<item>
<section slot="name">体重</section>
<input slot="content" type="text">
<section slot="content">111111</section>
</item>
<item>
<section slot="name">身高</section>
<input slot="content" type="text">
<section slot="content">111111</section>
</item>
<item>
<section slot="name">血型</section>
<input slot="content" type="text" >
<section slot="content">111111</section>
</item>
<item>
<section slot="name">胸围</section>
......@@ -52,23 +55,64 @@
<section slot="name">tun</section>
<input slot="content" type="text">
</item>
</list-item>
<list-item :item-height="50">
<item>
<section slot="name">tun</section>
<section slot="name">姓名</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">tun</section>
<section slot="name">年龄</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">tun</section>
<section slot="name">性别</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">出生日前</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">体重</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">身高</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">血型</section>
<input slot="content" type="text" >
</item>
<item>
<section slot="name">胸围</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">腰围</section>
<input slot="content" type="text">
</item>
<item>
<section slot="name">tun</section>
<input slot="content" type="text">
</item>
<SelectFiled
v-model="sex" :dataArray="sexList" :required="true" label="性别"
value-key="code_value"
value-name="code_value_name" @onSelect="select"/>
</list-item>
<DateFiled
v-model="nowDate" :required="true" label="时间"
@onSelect="select"/>
<!-- <h-range
:decimal="decimal" v-model="rangeValue" :min="min" :max="max"
:step="step" :disabled="disabled" :disabled-opacity="disabledOpacity" :range-bar-height="rangeBarHeight"
:range-handle-height="rangeHandleHeight" @change="change" @touchstart="touchStart" @touchend="touchEnd"/>
<h-progress :percent="70"/>-->
</h-content>
<!-- <s-tab>
<tab-item>Vue</tab-item>
......@@ -80,7 +124,11 @@
</template>
<script>
import {Range} from 'vux'
export default {
components: {
Range,
},
data () {
return {
userImg: window.localStorage.userImg || '',
......@@ -93,6 +141,20 @@ export default {
},
autosize: true,
height: '',
decimal: false,
rangeValue: 40,
min: 20,
max: 80,
step: 10,
disabled: true,
disabledOpacity: 0.5,
rangeBarHeight: 1,
rangeHandleHeight: 20,
sex: 0,
sexList: [{'code_value': 0, 'code_value_name': '女'}, {'code_value': 1, 'code_value_name': '男'}],
nowDate: '2020-12-25',
}
},
watch: {},
......@@ -184,6 +246,21 @@ export default {
this.$refs.textarea.style.height = this.height + 'px'
},
change (val) {
// this.rangeValue = val
console.log(val)
},
touchStart (e) {
console.log(e)
},
touchEnd (e) {
console.log(e)
},
select (v1, v2, v3) {
debugger
},
},
}
</script>
......
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