123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- <template>
- <view :show="show && !disabled" mode="bottom" :round="round">
- <view class="time-content">
- <view class="header-top">
- <slot name="header">
- <view class="cancel" @click="cancel">{{cancelText}}</view>
- <view class="title">{{title}}</view>
- <view class="confirm" @click="confirm">{{confirmText}}</view>
- </slot>
- </view>
- <view class="time-wrapper">
- <picker-view
- :value="pickerValue"
- indicator-class="picker-box"
- :indicator-style="indicatorStyle"
- @change="bindChange"
- >
- <picker-view-column v-for="(item,index) in innerColumns" :key="index">
- <view class="item" v-for="(item1,index1) in item.values" :key="index1">
- {{item1}}{{item.label}}
- </view>
- </picker-view-column>
- </picker-view>
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'GDatepicker',
- /**
- * 插槽
- * header 自定义头部样式
- */
- props:{
- value:{
- type: [String,Number],
- default:''
- },
- show: {
- type:[Boolean,String],
- default:false
- },
- cancelText: {
- type:String,
- default:'取消'
- },
- confirmText: {
- type:String,
- default:'确定'
- },
- title: {
- type:String,
- default:'时间选择'
- },
- /**
- * 是否格式化时间
- * format 格式同 uView timeFormat API,如:"yyyy-mm-dd"
- * 格式可以自由搭配: 年为"yyyy",月为"mm",日为"dd",时为"hh",分为"MM",秒为"ss",
- * 注意分为 大写M
- */
- format: {
- type:String,
- default:''
- },
- // 是否转换成json格式数据 如:2020-01-01T19:19:20.253Z
- formatToJson: {
- type: Boolean,
- default: false
- },
- /**
- * 时间模式(选择器可选时间格式)(如果mode为date,则format不应包含时分秒格式)
- * datetime 全时间:年月日时分秒
- * date 只包含年月日
- */
- mode: {
- type: String,
- default: 'datetime'
- },
- // 可选的最大时间 时间戳毫秒 默认后十年
- maxDate: {
- type: [String, Number],
- default: new Date(new Date().getFullYear() + 10, 0, 1).getTime(),
- },
- // 可选的最小时间 时间戳毫秒 默认前十年
- minDate: {
- type: [String, Number],
- default: new Date(new Date().getFullYear() - 10, 0, 1).getTime(),
- },
- minMonth: {
- type: [String, Number],
- default: 1
- },
- maxMonth: {
- type: [String, Number],
- default: 12
- },
- minDay: {
- type: [String, Number],
- default: 1
- },
- maxDay: {
- type: [String, Number],
- default: 31
- },
- // 弹窗圆角值
- round: {
- type: [String, Number],
- default:0
- },
- disabled:{
- type:Boolean,
- default:false
- }
- },
- model: {
- prop: 'value',
- event: 'input'
- },
- data() {
- return {
- year: 2022,
- month: 0,
- day: 0,
- hour: 0,
- minute: 0,
- second: 0,
- pickerValue: [], // picker-view绑定值
- innerColumns: [],
- indicatorStyle: `color: red;!important`
- }
- },
- watch:{
- show(val) {
- if(val) {
- this.initData()
- if(this.value) {
- this.setData(this.value)
- } else {
- this.setData()
- }
- }
- }
- },
- // mounted() {
- // this.initData()
- // },
- methods: {
- initData() {
- const startYear = new Date(Number(this.minDate)).getFullYear()
- const endYear = new Date(Number(this.maxDate)).getFullYear()
- let result = [
- {
- type: 'year',
- label: '年',
- range: [startYear, endYear]
- },
- {
- type: 'month',
- label: '月',
- range: [this.minMonth, this.maxMonth]
- },
- {
- type: 'day',
- label: '日',
- range: [this.minDay, this.maxDay]
- },
- {
- type: 'hour',
- label: '时',
- range: [0,23]
- },
- {
- type: 'minute',
- label: '分',
- range: [0, 59]
- },
- {
- type: 'secode',
- label: '秒',
- range: [0, 59]
- }
- ]
- this.innerColumns = result.map(({ type, label, range }) => {
- const num = range[1] - range[0] + 1;
- let values = this.getColumnTimes(num, (index) => {
- let value = range[0] + index
- value = type === 'year' ? `${value}` : this.padZero(value)
- return value
- })
- return { type, label, values }
- })
- if(this.mode === "date") {
- this.innerColumns.splice(3,3)
- }
- },
- bindChange (e) {
- const val = e.detail.value;
- const date = new Date();
- this.year = this.getCurrCol(0)[val[0]] || date.getFullYear()
- this.month = this.getCurrCol(1)[val[1]] ||date.getMonth() + 1;
- this.day = this.getCurrCol(2)[val[2]] || date.getDate()
- this.hour = this.getCurrCol(3)[val[3]] || date.getHours();
- this.minute = this.getCurrCol(4)[val[4]] || date.getMinutes();
- this.second = this.getCurrCol(5)[val[5]] || date.getSeconds();
- /* // change事件 需要启用取消注释
- const currentTime = new Date(this.year,this.month - 1,this.day,this.hour,this.minute,this.second).getTime()
- if(this.format) {
- this.$emit('change',uni.$u.timeFormat(currentTime,this.format))
- } else {
- this.$emit('change',currentTime)
- } */
- },
- getCurrCol(index) {
- if(!this.innerColumns[index]) {
- return []
- }
- return this.innerColumns[index].values
- },
- cancel() {
- this.$emit('cancel')
- this.$emit('update:show',false)
- },
- confirm() {
- const str = `${this.year}/${this.month}/${this.day} ${this.hour}:${this.minute}:${this.second}`
- const time = new Date(str).getTime()
- this.$emit('confirm',this.formatDate(time))
- this.$emit('input', this.formatDate(time));
- },
- // set data
- setData(value) {
- let date;
- if(value) {
- const n = isNaN(value) ? value : Number(value)
- date = new Date(n)
- } else {
- date = new Date()
- }
- const startYear = new Date(Number(this.minDate)).getFullYear()
- this.year = date.getFullYear()
- // 绑定时间小于当前时间列表的开始时间则取第一项
- const yearColumnIndex = this.year > startYear ? this.year - startYear : 0
- this.day = date.getDate()
- this.month = date.getMonth() + 1
- this.hour = date.getHours()
- this.minute = date.getMinutes()
- this.second = date.getSeconds()
- // pickerValue数组中的项依次表示 picker-view 内的 picker-view-column 选择的第几项
- this.pickerValue = [yearColumnIndex,this.month - 1,this.day - 1,this.hour,this.minute,this.second]
- this.$nextTick(() => {
- if(this.mode === "date") {
- this.pickerValue.splice(3,3)
- }
- })
- },
- formatDate(time) {
- if(this.format) {
- return uni.$u.timeFormat(time,this.format)
- } else if(this.formatToJson) {
- return new Date(time).toJSON()
- } else {
- return time
- }
- },
- // 设置列数据
- getColumnTimes(n, iteratee) {
- let index = -1
- const result = Array(n < 0 ? 0 : n)
- while (++index < n) {
- result[index] = iteratee(index)
- }
- return result
- },
- // 字符串转换
- padZero(num, targetLength = 2) {
- let str = `${num}`
- while (str.length < targetLength) {
- str = `0${str}`
- }
- return str
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- picker-view {
- width: 100%;
- height: 100%;
- }
-
- .time-content {
- height: 280px;
- .header-top {
- height: 44px;
- line-height: 44px;
- display: flex;
- padding: 0 16px;
- font-size: 15px;
- border-bottom: 1px solid #EEEEEE;
- overflow: hidden;
- .cancel {
- color: #999999;
- }
- .title {
- flex: 1;
- text-align: center;
- color: #666666;
- }
- .confirm {
- color: #27B57D;
- }
- }
- .time-wrapper {
- height: calc(100% - 44px);
- box-sizing: border-box;
- text-align: center;
- .picker-box {
- height: 44px;
- font-size: 18px!important;
- font-weight: 800!important;
- color: #333333!important;
- }
- .item {
- line-height: 44px;
- text-align: center;
- }
- }
- }
- </style>
|