You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

651 lines
18 KiB
Vue

11 months ago
<!-- 日期组件 -->
<template>
<view class="tm-pickersDateView flex-start px-24" :class="[black_tmeme ? 'grey-darken-5' : bgColor]">
<!-- :value="value_default" @change="change" -->
<picker-view
@pickstart="$emit('aniStart')"
@pickend="$emit('aniEnd')"
@change="change"
v-if="list_cD != null"
:value="value_default"
:mask-style="black_tmeme ? 'opacity:0;' : ''"
indicator-style="height:50px;"
indicator-class="tm-pickersCView-item-h"
class="tm-pickersCView-wk"
>
<picker-view-column v-show="syheng_key[key]" v-for="(item, key) in list_cD" :key="key">
<view
class="tm-pickersCView-item fulled-height flex-center "
style="margin: 0 5px;"
:class="[value_default[key] == index_pub ? ' text-weight-b active' : '', black_tmeme ? 'bk' : '', 'text-size-n']"
v-for="(item_data, index_pub) in item"
:key="index_pub"
>
<text>{{ buqi(item_data) }}</text>
<text v-if="mode">{{ modhz[key] }}</text>
</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
/**
* 日期下拉选择器(嵌入式)
* @description 多级关联单级关联选择
* @property {Array} default-value = [] 默认当前的时间初始显示的时间
* @property {String|Number} item-height = [34|42|50|58|62] 项目的高度单位px
* @property {String|Boolean} black = [true|false] 是否开启暗黑模式
* @property {String|Boolean} disabled = [true|false] 是否禁用
* @property {String} bg-color = [white|blue] 默认white,白色背景请填写背景的主题色名称
* @property {Object} show-detail = [{year:true,month:true,day:true,hour:false,min:false,sec:false}] 默认{year:true,month:true,day:true,hour:false,min:false,sec:false}
* @property {String} start = [1900-1-1 00:00:00] 默认1900-1-1 00:00:00开始的时间
* @property {String} end = [] 默认当前结束的时间
* @property {String|Boolean} mode = [true|false] 默认true是否显示中文年月后缀
* @property {String|Boolean} full-number = [true|false] 默认true是否把个位数补齐双位数
*/
export default {
name: 'tm-pickersDateView',
props: {
// 行高。
itemHeight: {
type: String | Number,
default: 40
},
black: {
type: String | Boolean,
default: null
},
// 是否禁用
disabled: {
type: String | Boolean,
default: false
},
// 背景颜色,主题色名称。
bgColor: {
type: String,
default: 'white'
},
//要展示的时间。
showDetail: {
type: Object,
default: () => {
return {
year: true, //年
month: true, //月
day: true, //天
hour: false, //小时
min: false, //分
sec: false //秒
};
}
},
start: {
type: String,
default: '1949-1-1 00:00:00'
},
end: {
type: String,
default: ''
},
defaultValue: '',
// 是否显示中文年,月后缀
mode: {
type: String | Boolean,
default: true
},
//要展示的时间。
modeValue: {
type: Object,
default: () => {
return {
year: '年', //年
month: '月', //月
day: '日', //天
hour: '时', //小时
min: '分', //分
sec: '秒' //秒
};
}
},
// 是否把个位数补齐双位数
fullNumber: {
type: String | Boolean,
default: true
}
},
data() {
return {
dataCauser: {
year: false, //年
month: false, //月
day: false, //天
hour: false, //小时
min: false, //分
sec: false //秒
},
hoz: {
year: '年', //年
month: '月', //月
day: '日', //天
hour: '时', //小时
min: '分', //分
sec: '秒' //秒
},
totalRow:0,
syheng_key: {},
//当前生成的所有数据年~秒
r_list:[],
list_cD: null,
value_default: [],
nowObj:null,
};
},
created() {
this.dataCauser = {...this.dataCauser,...(this.showDetail||{})}
this.setdataCauserArray();
this._reInits();
},
mounted() {
},
watch: {
showDetail:{
deep:true,
handler(){
this.dataCauser = {...this.dataCauser,...this.showDetail};
this.setdataCauserArray();
}
},
defaultValue: function(val) {
let nowdateVal;
if (val) {
nowdateVal = new Date(val.replace(/-/g, '/'));
} else {
nowdateVal = new Date();
}
this.nowObj = nowdateVal;
if(this.list_cD==null) return;
this._reInits();
},
start: async function() {
if(this.list_cD==null) return;
this._reInits();
},
end: async function() {
if(this.list_cD==null) return;
this._reInits();
}
},
computed: {
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
modhz: function() {
let hz = [];
let moz = { ...this.hoz, ...this.modeValue };
hz.push(moz.year)
hz.push(moz.month)
hz.push(moz.day)
hz.push(moz.hour)
hz.push(moz.min)
hz.push(moz.sec)
return hz;
},
detavlue:function () {
let d = this.defaultValue;
if(!d){
let ys = new Date();
d = ys.getFullYear()+'-'+(ys.getMonth()+1)+'-'+ys.getDate()+' '+ys.getHours()+':'+ys.getMinutes()+':'+ys.getSeconds()
}
return d.replace(/-/g, '/');
},
//结束的日期,默认为当前
end_str:function () {
let d = this.end;
if(!d){
let ys = new Date();
d = ys.getFullYear()+'-'+(ys.getMonth()+1)+'-'+ys.getDate()+' '+ys.getHours()+':'+ys.getMinutes()+':'+ys.getSeconds()
}
return d.replace(/-/g, '/');
},
//开始默认为1960年
start_str:function () {
let d = this.start;
if(!d){
d='1960-1-1 00:00:00'
}
return d.replace(/-/g, '/');
},
},
methods: {
//设置显示的行当。
setdataCauserArray(){
let t = this;
let f = {
'0':this.dataCauser['year'],
'1':this.dataCauser['month'],
'2':this.dataCauser['day'],
'3':this.dataCauser['hour'],
'4':this.dataCauser['min'],
'5':this.dataCauser['sec'],
}
//显示的列表数。
let totalHoz = 0;
let p = Object.keys(this.dataCauser);
p = p.filter(el=>t.dataCauser[el]==true)
this.totalRow = p.length;
this.syheng_key = f;
},
//初始生成对应的开始和结束日期数据。
_reInits(date){
let t = this;
let nowdateVal;
if (date) {
nowdateVal = new Date(date.replace(/-/g, '/'));
} else {
nowdateVal = new Date(this.detavlue);
}
this.nowObj = nowdateVal;
/**
* 接下来需要比对年月
* 分开比较的原因是如果年不变的话只是改变月那么只需重新
* 更改日的数据如果每月的日期一样也不需要改变
*/
//根据提供的值nodwdateVal来划定开始和结束的日期数据。为了保证流畅采用一次性生成的方法。
//先生成开始的数据。
//开始
const start = new Date(this.start_str);
//结束
const end = new Date(this.end_str);
//当前
const now = nowdateVal;
let list = [];
let year = this.range(start.getFullYear(),end.getFullYear())
list.push(year)
// 月。是需要根据nowdateVal提供的值来生成。因为月是不固定的。
//默认先生成start到12的
let month_s = this.range(start.getMonth()+1,12)
let month_e = this.range(1,end.getMonth()+1)
//同年同月
if(start.getFullYear()==end.getFullYear()&&start.getMonth()==end.getMonth()){
let tn = this.range(start.getMonth()+1,end.getMonth()+1);
list.push([tn,tn])
}else{
list.push([month_s,month_e])
}
let day_s = this.range(start.getDate(),this.monthDay(start.getFullYear(),start.getMonth()))
let day_e = this.range(1,end.getDate())
//同年同月同日
if(start.getFullYear()==end.getFullYear()
&&start.getMonth()==end.getMonth()
&&start.getDate()==end.getDate()
){
let tn = this.range(start.getDate(),end.getDate());
list.push([tn,tn])
}else{
list.push([day_s,day_e])
}
let hours_s = this.range(start.getHours(),23)
let hours_e = this.range(0,end.getHours())
//同年同月同日同时
if(start.getFullYear()==end.getFullYear()
&&start.getMonth()==end.getMonth()
&&start.getDate()==end.getDate()
&&start.getHours()==end.getHours()
){
let tn = this.range(start.getHours(),end.getHours());
list.push([tn,tn])
}else{
list.push([hours_s,hours_e])
}
let minutes_s = this.range(start.getMinutes(),59)
let minutes_e = this.range(0,end.getMinutes())
//同年同月同日同时同分
if(start.getFullYear()==end.getFullYear()
&&start.getMonth()==end.getMonth()
&&start.getDate()==end.getDate()
&&start.getHours()==end.getHours()
){
let tn = this.range(start.getMinutes(),end.getMinutes());
list.push([tn,tn])
}else{
list.push([minutes_s,minutes_e])
}
let seconds_s = this.range(start.getSeconds(),59)
let seconds_e = this.range(0,end.getSeconds())
//同年同月同日同时同分同秒
if(start.getFullYear()==end.getFullYear()
&&start.getMonth()==end.getMonth()
&&start.getDate()==end.getDate()
&&start.getHours()==end.getHours()
&&start.getSeconds()==end.getSeconds()
){
let tn = this.range(start.getSeconds(),end.getSeconds());
list.push([tn,tn])
}else{
list.push([seconds_s,seconds_e])
}
this.r_list = list;
this.$nextTick(function () {
this._getListCd(start,end,now)
})
},
//生成对应的列表数据,以供选择。不需要生成所有,只要生成默认当前时间的。
_getListCd(start,end,now,issetd){
let list_cD = [];
//年
list_cD.push(this.r_list[0])
//月。
let year_s = new Date(String(start.getFullYear())+'/1/1').getTime()
let year_e = new Date(String(end.getFullYear())+'/1/1').getTime()
let year_n = new Date(String(now.getFullYear())+'/1/1').getTime()
if(
year_s===year_e //开始和结束相同
||(year_s!=year_e&&year_n==year_s) //现在=开始。
||(year_s!=year_e&&year_n<year_s) //
){
list_cD.push(this.r_list[1][0])
}else if(
(year_s!=year_e&&year_n==year_e) //现在=结束。
||(year_s!=year_e&&year_n>year_e) //现在大于结束
){
list_cD.push(this.r_list[1][1])
}else{ //在开始和结束之间。
list_cD.push(this.range(1,12))
}
//日。
let day_s = new Date(start.getFullYear()+'/'+(start.getMonth()+1)+'/1').getTime()
let day_e = new Date(end.getFullYear()+'/'+(end.getMonth()+1)+'/1').getTime()
let day_n = new Date(now.getFullYear()+'/'+(now.getMonth()+1)+'/1').getTime()
if(
day_s===day_e //开始和结束相同
||(day_s!=day_e&&day_n==day_s) //现在=开始。
||(day_s!=day_e&&day_n<day_s) //
){
list_cD.push(this.r_list[2][0])
}else if(
(day_s!=day_e&&day_n==day_e) //现在=结束。
||(day_s!=day_e&&day_n>day_e) //现在大于结束
){
list_cD.push(this.r_list[2][1])
}else{ //在开始和结束之间。
list_cD.push(this.range(1,this.monthDay(now.getFullYear(),now.getMonth())))
}
//时。
let hours_s = new Date(String(start.getFullYear())+'/'+(start.getMonth()+1)+'/'+start.getDate()).getTime()
let hours_e = new Date(String(end.getFullYear())+'/'+(end.getMonth()+1)+'/'+end.getDate()).getTime()
let hours_n = new Date(String(now.getFullYear())+'/'+(now.getMonth()+1)+'/'+now.getDate()).getTime()
if(
hours_s===hours_e //开始和结束相同
||(hours_s!=hours_e&&hours_n==hours_s) //现在=开始。
||(hours_s!=hours_e&&hours_n<hours_s) //
){
list_cD.push(this.r_list[3][0])
}else if(
(hours_s!=hours_e&&hours_n==hours_e) //现在=结束。
||(hours_s!=hours_e&&hours_n>hours_e) //现在大于结束
){
list_cD.push(this.r_list[3][1])
}else{ //在开始和结束之间。
list_cD.push(this.range(0,23))
}
//分。
let min_s = new Date(String(start.getFullYear())+'/'+(start.getMonth()+1)+'/'+start.getDate()+' '+start.getHours()+':00:00').getTime()
let min_e = new Date(String(end.getFullYear())+'/'+(end.getMonth()+1)+'/'+end.getDate()+' '+end.getHours()+':00:00').getTime()
let min_n = new Date(String(now.getFullYear())+'/'+(now.getMonth()+1)+'/'+now.getDate()+' '+now.getHours()+':00:00').getTime()
if(
min_s===min_e //开始和结束相同
||(min_s!=min_e&&min_n==min_s) //现在=开始。
||(min_s!=min_e&&min_n<min_s) //
){
list_cD.push(this.r_list[4][0])
}else if(
(min_s!=min_e&&min_n==min_e) //现在=结束。
||(min_s!=min_e&&min_n>min_e) //现在大于结束
){
list_cD.push(this.r_list[4][1])
}else{ //在开始和结束之间。
list_cD.push(this.range(0,59))
}
//秒。
let seccode_s = new Date(String(start.getFullYear())+'/'+(start.getMonth()+1)+'/'+start.getDate()+' '+start.getHours()+':'+start.getMinutes()+':00').getTime()
let seccode_e = new Date(String(end.getFullYear())+'/'+(end.getMonth()+1)+'/'+end.getDate()+' '+end.getHours()+':'+start.getMinutes()+':00').getTime()
let seccode_n = new Date(String(now.getFullYear())+'/'+(now.getMonth()+1)+'/'+now.getDate()+' '+now.getHours()+':'+start.getMinutes()+':00').getTime()
if(
seccode_s===seccode_e //开始和结束相同
||(seccode_s!=seccode_e&&seccode_n==seccode_s) //现在=开始。
||(seccode_s!=seccode_e&&seccode_n<seccode_s) //
){
list_cD.push(this.r_list[4][0])
}else if(
(seccode_s!=seccode_e&&seccode_n==seccode_e) //现在=结束。
||(seccode_s!=seccode_e&&seccode_n>seccode_e) //现在大于结束
){
list_cD.push(this.r_list[4][1])
}else{ //在开始和结束之间。
list_cD.push(this.range(0,59))
}
this.$nextTick(function () {
this.list_cD = list_cD;
if(!issetd){
this.$nextTick(function () {
this.setDefaultIndex();
})
}
})
},
monthDay(year, month) {
let date = new Date(year, month, 1, 0, 0, 0);
date.setMonth(date.getMonth()+1)
let yesterDay = new Date(date - 1000);
return yesterDay.getDate();
},
//生成一个数据数组。
range(from=0,to){
const range = [];
if(from===to) return [from];
for (let i = from; i <= to; i++) {
range.push(i)
}
return range
},
//设置当前选中的索引。
setDefaultIndex(){
if(!this.list_cD) return;
let value_default = [];
let t = this;
// 年。
let year = this.list_cD[0].findIndex(el=>el==t.nowObj.getFullYear());
year=year<=0?0:year;
let month = this.list_cD[1].findIndex(el=>el==t.nowObj.getMonth()+1);
month=month<=0?0:month;
let day = this.list_cD[2].findIndex(el=>el==t.nowObj.getDate());
day=day<=0?0:day;
let hours = this.list_cD[3].findIndex(el=>el==t.nowObj.getHours());
hours=hours<=0?0:hours;
let minutes = this.list_cD[4].findIndex(el=>el==t.nowObj.getMinutes());
minutes=minutes<=0?0:minutes;
let seconds = this.list_cD[5].findIndex(el=>el==t.nowObj.getSeconds());
seconds=seconds<=0?0:seconds;
// 开始设置,如果当前默认的日期不在范围内。默认选中的索引日期。
value_default = [year,month,day,hours,minutes,seconds]
this.$nextTick(function () {
this.value_default = value_default;
})
},
//回显到初始化值。
resetVal(setd){
let val = this.defaultValue;
if(setd) val = setd;
let nowdateVal;
if (val) {
nowdateVal = new Date(val.replace(/-/g, '/'));
} else {
nowdateVal = new Date();
}
this.nowObj = nowdateVal;
if(this.list_cD==null) return;
this._reInits();
this.$nextTick(function () {
this.setDefaultIndex();
})
},
buqi(val) {
return val > 9 ? '' + val : '0' + val;
},
//通过索引获取当前数据
SeletecdeIndexdefault(value_default) {
if(!value_default) value_default = this.value_default;
let t = this;
let ap = [];
this.value_default.forEach((item,index) => {
let f = t.list_cD[index][parseInt(item)];
f = typeof(f)=="undefined"? t.list_cD[index][ t.list_cD[index].length-1]:f;
ap.push(f);
});
return ap;
},
// 获取当前选中的数据。
getSelectedValue() {
let t = this;
let ap = this.SeletecdeIndexdefault();
let jg = {
year: ap[0], //年
month: ap[1], //月
day: ap[2], //天
hour: ap[3], //小时
min: ap[4], //分
sec: ap[5] //秒
};
let ar = Object.keys(this.dataCauser);
ar.forEach(item => {
if (t.dataCauser[item] === false) {
delete jg[item];
}
});
return jg;
},
getSelsectDate() {
let t = this;
let ap = this.SeletecdeIndexdefault();
let jg = {
year: ap[0], //年
month: ap[1], //月
day: ap[2], //天
hour: ap[3], //小时
min: ap[4], //分
sec: ap[5] //秒
};
return new Date(ap[0]+'/'+ap[1]+'/'+ap[2]+' '+ap[3]+':'+ap[4]+':'+ap[5]);
},
change(e) {
//滑动后,要动态修改数据。
let val = e.detail.value;
let index =0;
// 找出修改的index项。
let nowD = [this.nowObj.getFullYear(),1,1,0,0,0];
let nowObj = [this.nowObj.getFullYear(),this.nowObj.getMonth()+1,this.nowObj.getDate(),this.nowObj.getHours(),this.nowObj.getMinutes(),this.nowObj.getSeconds()];
for (var i = 0; i < 6; i++) {
if(this.value_default[i]!==val[i]){
nowD[i] = this.list_cD[i][val[i]]
}else{
let idx = this.list_cD[i].findIndex(el=>el==nowObj[i])
if(idx==-1){
nowD[i] = this.list_cD[i][0]
}else{
nowD[i] = nowObj[i]
}
}
}
const now = nowD[0]+'/'+(nowD[1])+'/'+nowD[2]+' '+nowD[3]+':'+nowD[4]+':'+nowD[5];
this._reInits(now)
let nowVal = val.map(el=>{
let dsdd = el<=0?0:el;
return dsdd
})
this.$nextTick(function () {
this.value_default = nowVal;
// 发送滚动选中的时间数据。
this.$emit('change',this.getSelectedValue());
})
},
jswid() {
let wd = this.gridNum - 1 - 2;
if (wd <= 0) wd = 1;
return 100 / wd;
},
}
};
</script>
<style>
.tm-pickersDateView .tm-pickersCView-item-h {
height: 50px;
background-color: rgba(0, 0, 0, 0.03);
width: calc(100% - 10px);
margin-left: 5px;
border-radius: 20rpx;
border: none;
}
.tm-pickersDateView .tm-pickersCView-item-h::after,
.tm-pickersDateView .tm-pickersCView-item-h::before {
border: none;
}
.tm-pickersDateView .tm-pickersCView-wk {
position: relative;
width: 750rpx;
height: 500rpx;
}
.tm-pickersDateView .tm-pickersCView-wk .tm-pickersCView-item.bk {
opacity: 0.4;
}
.tm-pickersDateView .tm-pickersCView-wk .tm-pickersCView-item.active {
opacity: 1;
border-radius: 20rpx;
border: none;
background-color: rgba(0, 0, 0, 0.06);
}
.tm-pickersDateView .tm-pickersCView-wk .tm-pickersCView-item.active.bk {
background-color: rgba(255, 255, 255, 0.06);
}
</style>