智能照明系统APP-本地串口
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LightingSystemApp-serial/.svn/pristine/04/04a3530d13e94f2079c2f9f4729...

637 lines
15 KiB

3 years ago
<template>
<uni-picker
:disabled="disabled"
@click="_show"
v-on="$listeners"
>
<div
ref="picker"
class="uni-picker-container"
@touchmove.prevent
>
<transition name="uni-fade">
<div
v-show="visible"
class="uni-mask"
@click="_cancel"
/>
</transition>
<div
:class="{'uni-picker-toggle':visible}"
class="uni-picker"
>
<div
class="uni-picker-header"
@click.stop
>
<div
class="uni-picker-action uni-picker-action-cancel"
@click="_cancel"
>
取消
</div>
<div
class="uni-picker-action uni-picker-action-confirm"
@click="_change"
>
确定
</div>
</div>
<v-uni-picker-view
v-if="visible"
:value.sync="valueArray"
class="uni-picker-content"
>
<v-uni-picker-view-column
v-for="(rangeItem,index0) in rangeArray"
:key="index0"
>
<div
v-for="(item,index) in rangeItem"
:key="index"
class="uni-picker-item"
>
{{ typeof item==='object'?item[rangeKey]||'':item }}{{ units[index0]||'' }}
</div>
</v-uni-picker-view-column>
</v-uni-picker-view>
<!-- 第二种时间单位展示方式-暂时不用这种 -->
<!-- <div v-if="units.length" class="uni-picker-units">
<div v-for="(item,index) in units" :key="index">{{item}}</div>
</div>-->
</div>
</div>
<div>
<slot />
</div>
</uni-picker>
</template>
<script>
import { emitter } from 'uni-mixins'
import { formatDateTime } from 'uni-shared'
function getDefaultStartValue () {
if (this.mode === mode.TIME) {
return '00:00'
}
if (this.mode === mode.DATE) {
const year = new Date().getFullYear() - 100
switch (this.fields) {
case fields.YEAR:
return year.toString()
case fields.MONTH:
return year + '-01'
case fields.DAY:
return year + '-01-01'
}
}
return ''
}
function getDefaultEndValue () {
if (this.mode === mode.TIME) {
return '23:59'
}
if (this.mode === mode.DATE) {
const year = new Date().getFullYear() + 100
switch (this.fields) {
case fields.YEAR:
return year.toString()
case fields.MONTH:
return year + '-12'
case fields.DAY:
return year + '-12-31'
}
}
return ''
}
const mode = {
SELECTOR: 'selector',
MULTISELECTOR: 'multiSelector',
TIME: 'time',
DATE: 'date'
// 暂不支持城市选择
// REGION: 'region'
}
const fields = {
YEAR: 'year',
MONTH: 'month',
DAY: 'day'
}
export default {
name: 'Picker',
mixins: [emitter],
props: {
name: {
type: String,
default: ''
},
range: {
type: Array,
default () {
return []
}
},
rangeKey: {
type: String,
default: ''
},
value: {
type: [Number, String, Array],
default: 0
},
mode: {
type: String,
default: mode.SELECTOR,
validator (val) {
return Object.values(mode).indexOf(val) >= 0
}
},
fields: {
type: String,
default: 'day',
validator (val) {
return Object.values(fields).indexOf(val) >= 0
}
},
start: {
type: String,
default: getDefaultStartValue
},
end: {
type: String,
default: getDefaultEndValue
},
disabled: {
type: [Boolean, String],
default: false
}
},
data () {
return {
valueSync: null,
visible: false,
valueChangeSource: '',
timeArray: [],
dateArray: [],
valueArray: [],
oldValueArray: []
}
},
computed: {
rangeArray () {
var val = this.range
switch (this.mode) {
case mode.SELECTOR:
return [val]
case mode.MULTISELECTOR:
return val
case mode.TIME:
return this.timeArray
case mode.DATE:
{
const dateArray = this.dateArray
switch (this.fields) {
case fields.YEAR:
return [dateArray[0]]
case fields.MONTH:
return [dateArray[0], dateArray[1]]
case fields.DAY:
return [dateArray[0], dateArray[1], dateArray[2]]
}
}
}
return []
},
startArray () {
return this._getDateValueArray(this.start, getDefaultStartValue.bind(this)())
},
endArray () {
return this._getDateValueArray(this.end, getDefaultEndValue.bind(this)())
},
units () {
switch (this.mode) {
case mode.DATE:
return ['年', '月', '日']
case mode.TIME:
return ['时', '分']
default:
return []
}
}
},
watch: {
value () {
this._setValueSync()
},
mode () {
this._setValueSync()
},
range () {
this._setValueSync()
},
valueSync () {
this._setValueArray()
},
valueArray (val) {
if (this.mode === mode.TIME || this.mode === mode.DATE) {
const getValue =
this.mode === mode.TIME ? this._getTimeValue : this._getDateValue
const valueArray = this.valueArray
const startArray = this.startArray
const endArray = this.endArray
if (this.mode === mode.DATE) {
const dateArray = this.dateArray
const max = dateArray[2].length
const day = Number(dateArray[2][valueArray[2]]) || 1
const realDay = new Date(
`${dateArray[0][valueArray[0]]}/${
dateArray[1][valueArray[1]]
}/${day}`
).getDate()
if (realDay < day) {
valueArray[2] -= realDay + max - day
}
}
if (getValue(valueArray) < getValue(startArray)) {
this._cloneArray(valueArray, startArray)
} else if (getValue(valueArray) > getValue(endArray)) {
this._cloneArray(valueArray, endArray)
}
}
val.forEach((value, column) => {
if (value !== this.oldValueArray[column]) {
this.oldValueArray[column] = value
if (this.mode === mode.MULTISELECTOR) {
this.$trigger('columnchange', {}, {
column,
value
}
)
}
}
})
}
},
created () {
this.$dispatch('Form', 'uni-form-group-update', {
type: 'add',
vm: this
})
this._createTime()
this._createDate()
this._setValueSync()
},
beforeDestroy () {
this.$refs.picker.remove()
this.$dispatch('Form', 'uni-form-group-update', {
type: 'remove',
vm: this
})
},
methods: {
_show () {
if (this.disabled) {
return
}
this.valueChangeSource = ''
var $picker = this.$refs.picker
$picker.remove();
(document.querySelector('uni-app') || document.body).appendChild($picker)
$picker.style.display = 'block'
setTimeout(() => {
this.visible = true
}, 20)
},
_getFormData () {
return {
value: this.valueSync,
key: this.name
}
},
_resetFormData () {
switch (this.mode) {
case mode.SELECTOR:
this.valueSync = 0
break
case mode.MULTISELECTOR:
this.valueSync = this.value.map(val => 0)
break
case mode.DATE:
case mode.TIME:
this.valueSync = ''
break
default:
break
}
},
_createTime () {
var hours = []
var minutes = []
hours.splice(0, hours.length)
for (let i = 0; i < 24; i++) {
hours.push((i < 10 ? '0' : '') + i)
}
minutes.splice(0, minutes.length)
for (let i = 0; i < 60; i++) {
minutes.push((i < 10 ? '0' : '') + i)
}
this.timeArray.push(hours, minutes)
},
_createDate () {
var years = []
var year = new Date().getFullYear()
for (let i = year - 150, end = year + 150; i <= end; i++) {
years.push(String(i))
}
var months = []
for (let i = 1; i <= 12; i++) {
months.push((i < 10 ? '0' : '') + i)
}
var days = []
for (let i = 1; i <= 31; i++) {
days.push((i < 10 ? '0' : '') + i)
}
this.dateArray.push(years, months, days)
},
_getTimeValue (val) {
return val[0] * 60 + val[1]
},
_getDateValue (val) {
return val[0] * 366 + (val[1] || 0) * 31 + (val[2] || 0)
},
/**
* 将右侧数组值同步到左侧(交集部分)
*/
_cloneArray (val1, val2) {
for (let i = 0; i < val1.length && i < val2.length; i++) {
val1[i] = val2[i]
}
},
_setValueSync () {
let val = this.value
switch (this.mode) {
case mode.MULTISELECTOR:
{
if (!Array.isArray(val)) {
val = []
}
if (!Array.isArray(this.valueSync)) {
this.valueSync = []
}
const length = this.valueSync.length = Math.max(val.length, this.range.length)
for (let index = 0; index < length; index++) {
const val0 = Number(val[index])
const val1 = Number(this.valueSync[index])
const val2 = isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0
const maxVal = this.range[index] ? this.range[index].length - 1 : 0
this.valueSync.splice(index, 1, (val2 < 0 || val2 > maxVal) ? 0 : val2)
}
}
break
case mode.TIME:
case mode.DATE:
this.valueSync = String(val)
break
default: {
const valueSync = Number(val)
this.valueSync = valueSync < 0 ? 0 : valueSync
break
}
}
},
_setValueArray () {
var val = this.valueSync
var valueArray
switch (this.mode) {
case mode.MULTISELECTOR:
valueArray = [...val]
break
case mode.TIME:
valueArray = this._getDateValueArray(val, formatDateTime({
mode: mode.TIME
}))
break
case mode.DATE:
valueArray = this._getDateValueArray(val, formatDateTime({
mode: mode.DATE
}))
break
default:
valueArray = [val]
break
}
this.oldValueArray = [...valueArray]
this.valueArray = [...valueArray]
},
_getValue () {
var val = this.valueArray
switch (this.mode) {
case mode.SELECTOR:
return val[0]
case mode.MULTISELECTOR:
return val.map(val => val)
case mode.TIME:
return this.valueArray
.map((val, i) => this.timeArray[i][val])
.join(':')
case mode.DATE:
return this.valueArray
.map((val, i) => this.dateArray[i][val])
.join('-')
}
},
_getDateValueArray (valueStr, defaultValue) {
const splitStr = this.mode === mode.DATE ? '-' : ':'
const array = this.mode === mode.DATE ? this.dateArray : this.timeArray
let max
if (this.mode === mode.TIME) {
max = 2
} else {
switch (this.fields) {
case fields.YEAR:
max = 1
break
case fields.MONTH:
max = 2
break
default:
max = 3
break
}
}
const inputArray = String(valueStr).split(splitStr)
let value = []
for (let i = 0; i < max; i++) {
const val = inputArray[i]
value.push(array[i].indexOf(val))
}
if (value.indexOf(-1) >= 0) {
value = defaultValue ? this._getDateValueArray(defaultValue) : value.map(() => 0)
}
return value
},
_change () {
this._close()
this.valueChangeSource = 'click'
const value = this._getValue()
this.valueSync = Array.isArray(value) ? value.map(val => val) : value
this.$trigger('change', {}, {
value
})
},
_cancel () {
this._close()
this.$trigger('cancel', {}, {})
},
_close () {
this.visible = false
setTimeout(() => {
var $picker = this.$refs.picker
$picker.remove()
this.$el.prepend($picker)
$picker.style.display = 'none'
}, 260)
}
}
}
</script>
<style>
uni-picker {
display: block;
cursor: pointer;
}
uni-picker[hidden] {
display: none;
}
uni-picker[disabled] {
cursor: not-allowed;
}
.uni-picker-container {
display: none;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
box-sizing: border-box;
z-index: 999;
font-size: 16px;
}
.uni-picker-container .uni-picker * {
box-sizing: border-box;
}
.uni-picker-container .uni-picker {
position: fixed;
left: 0;
bottom: 0;
transform: translate(0, 100%);
backface-visibility: hidden;
z-index: 999;
width: 100%;
background-color: #efeff4;
visibility: hidden;
transition: transform 0.3s, visibility 0.3s;
}
.uni-picker-container .uni-picker.uni-picker-toggle {
visibility: visible;
transform: translate(0, 0);
}
.uni-picker-container .uni-picker-content {
position: relative;
display: block;
width: 100%;
height: 238px;
background-color: white;
}
.uni-picker-container .uni-picker-item {
padding: 0;
height: 34px;
line-height: 34px;
text-align: center;
color: #000;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.uni-picker-container .uni-picker-header {
display: block;
position: relative;
text-align: center;
width: 100%;
height: 45px;
background-color: #fff;
}
.uni-picker-container .uni-picker-header:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
clear: both;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.uni-picker-container .uni-picker-action {
display: block;
max-width: 50%;
top: 0;
height: 100%;
box-sizing: border-box;
padding: 0 14px;
font-size: 17px;
line-height: 45px;
overflow: hidden;
cursor: pointer;
}
.uni-picker-container .uni-picker-action.uni-picker-action-cancel {
float: left;
color: #888;
}
.uni-picker-container .uni-picker-action.uni-picker-action-confirm {
float: right;
color: #007aff;
}
/* .uni-picker {
position: relative;
}
.uni-picker-units {
position: absolute;
display: flex;
width: 100%;
line-height: 16px;
font-size: 14px;
top: 50%;
margin-top: 22.5px;
transform: translateY(-50%);
overflow: hidden;
color: #666666;
pointer-events: none;
}
.uni-picker-units > div {
flex: 1;
text-align: center;
transform: translateX(2em);
} */
</style>