|
|
- <template>
- <view class="select-datetime-container">
- <picker
- mode="multiSelector"
- :range="pickerRange"
- :value="pickerValue"
- @change="onPickerChange"
- @columnchange="onColumnChange"
- >
- <slot>
- <view class="datetime-display">
- <text>{{ displayText }}</text>
- <uv-icon name="arrow-down" size="16" color="#999"></uv-icon>
- </view>
- </slot>
- </picker>
- </view>
- </template>
-
- <script>
- export default {
- name: 'SelectDatetime',
- props: {
- // 选择器类型: 'datetime', 'date', 'time'
- type: {
- type: String,
- default: 'datetime'
- },
- // 默认值
- value: {
- type: String,
- default: ''
- },
- // 占位文本
- placeholder: {
- type: String,
- default: '请选择时间'
- },
- // 最小年份
- minYear: {
- type: Number,
- default: 2020
- },
- // 最大年份
- maxYear: {
- type: Number,
- default: 2030
- }
- },
- data() {
- return {
- pickerValue: [0, 0, 0, 0, 0],
- pickerRange: [],
- currentDate: new Date(),
- selectedDateTime: ''
- }
- },
- computed: {
- displayText() {
- if (this.selectedDateTime) {
- return this.selectedDateTime;
- }
- return this.placeholder;
- },
-
- // 年份数组
- years() {
- const years = [];
- for (let i = this.minYear; i <= this.maxYear; i++) {
- years.push(i + '年');
- }
- return years;
- },
-
- // 月份数组
- months() {
- const months = [];
- for (let i = 1; i <= 12; i++) {
- months.push(i + '月');
- }
- return months;
- },
-
- // 日期数组
- days() {
- const year = this.minYear + this.pickerValue[0];
- const month = this.pickerValue[1] + 1;
- const daysInMonth = new Date(year, month, 0).getDate();
-
- const days = [];
- for (let i = 1; i <= daysInMonth; i++) {
- days.push(i + '日');
- }
- return days;
- },
-
- // 小时数组
- hours() {
- const hours = [];
- for (let i = 0; i < 24; i++) {
- hours.push(i.toString().padStart(2, '0') + '时');
- }
- return hours;
- },
-
- // 分钟数组
- minutes() {
- const minutes = [];
- for (let i = 0; i < 60; i += 5) { // 每5分钟一个选项
- minutes.push(i.toString().padStart(2, '0') + '分');
- }
- return minutes;
- }
- },
- mounted() {
- this.initPicker();
- if (this.value) {
- this.parseValue(this.value);
- }
- },
- watch: {
- value(newVal) {
- if (newVal) {
- this.parseValue(newVal);
- }
- },
- type() {
- this.initPicker();
- }
- },
- methods: {
- // 初始化选择器
- initPicker() {
- switch (this.type) {
- case 'datetime':
- this.pickerRange = [this.years, this.months, this.days, this.hours, this.minutes];
- this.pickerValue = [0, 0, 0, 0, 0];
- break;
- case 'date':
- this.pickerRange = [this.years, this.months, this.days];
- this.pickerValue = [0, 0, 0];
- break;
- case 'time':
- this.pickerRange = [this.hours, this.minutes];
- this.pickerValue = [0, 0];
- break;
- }
- this.setDefaultValue();
- },
-
- // 设置默认值为当前时间
- setDefaultValue() {
- const now = new Date();
- const year = now.getFullYear();
- const month = now.getMonth();
- const day = now.getDate() - 1;
- const hour = now.getHours();
- const minute = Math.floor(now.getMinutes() / 5);
-
- switch (this.type) {
- case 'datetime':
- this.pickerValue = [
- year - this.minYear,
- month,
- day,
- hour,
- minute
- ];
- break;
- case 'date':
- this.pickerValue = [
- year - this.minYear,
- month,
- day
- ];
- break;
- case 'time':
- this.pickerValue = [hour, minute];
- break;
- }
- this.updateDisplayText();
- },
-
- // 解析传入的值
- parseValue(value) {
- try {
- const date = new Date(value);
- if (isNaN(date.getTime())) {
- return;
- }
-
- const year = date.getFullYear();
- const month = date.getMonth();
- const day = date.getDate() - 1;
- const hour = date.getHours();
- const minute = Math.floor(date.getMinutes() / 5);
-
- switch (this.type) {
- case 'datetime':
- this.pickerValue = [
- year - this.minYear,
- month,
- day,
- hour,
- minute
- ];
- break;
- case 'date':
- this.pickerValue = [
- year - this.minYear,
- month,
- day
- ];
- break;
- case 'time':
- this.pickerValue = [hour, minute];
- break;
- }
- this.updateDisplayText();
- } catch (e) {
- console.error('解析时间值失败:', e);
- }
- },
-
- // 选择器值改变
- onPickerChange(e) {
- this.pickerValue = e.detail.value;
- this.updateDisplayText();
- this.emitChange();
- },
-
- // 列改变时更新日期选项
- onColumnChange(e) {
- const column = e.detail.column;
- const value = e.detail.value;
-
- // 如果改变的是年份或月份,需要更新日期选项
- if ((column === 0 || column === 1) && this.type !== 'time') {
- this.pickerValue[column] = value;
- this.$nextTick(() => {
- this.pickerRange[2] = this.days;
- // 如果当前选择的日期超出了新月份的天数,调整到最后一天
- if (this.pickerValue[2] >= this.days.length) {
- this.pickerValue[2] = this.days.length - 1;
- }
- });
- }
- },
-
- // 更新显示文本
- updateDisplayText() {
- switch (this.type) {
- case 'datetime':
- this.selectedDateTime = `${this.years[this.pickerValue[0]]} ${this.months[this.pickerValue[1]]} ${this.days[this.pickerValue[2]]} ${this.hours[this.pickerValue[3]]} ${this.minutes[this.pickerValue[4]]}`;
- break;
- case 'date':
- this.selectedDateTime = `${this.years[this.pickerValue[0]]} ${this.months[this.pickerValue[1]]} ${this.days[this.pickerValue[2]]}`;
- break;
- case 'time':
- this.selectedDateTime = `${this.hours[this.pickerValue[0]]} ${this.minutes[this.pickerValue[1]]}`;
- break;
- }
- },
-
- // 发送改变事件
- emitChange() {
- let dateValue = '';
-
- switch (this.type) {
- case 'datetime':
- const year = this.minYear + this.pickerValue[0];
- const month = (this.pickerValue[1] + 1).toString().padStart(2, '0');
- const day = (this.pickerValue[2] + 1).toString().padStart(2, '0');
- const hour = this.pickerValue[3].toString().padStart(2, '0');
- const minute = (this.pickerValue[4] * 5).toString().padStart(2, '0');
- dateValue = `${year}-${month}-${day} ${hour}:${minute}:00`;
- break;
- case 'date':
- const dateYear = this.minYear + this.pickerValue[0];
- const dateMonth = (this.pickerValue[1] + 1).toString().padStart(2, '0');
- const dateDay = (this.pickerValue[2] + 1).toString().padStart(2, '0');
- dateValue = `${dateYear}-${dateMonth}-${dateDay}`;
- break;
- case 'time':
- const timeHour = this.pickerValue[0].toString().padStart(2, '0');
- const timeMinute = (this.pickerValue[1] * 5).toString().padStart(2, '0');
- dateValue = `${timeHour}:${timeMinute}:00`;
- break;
- }
-
- this.$emit('change', {
- value: dateValue,
- displayText: this.selectedDateTime,
- pickerValue: this.pickerValue
- });
- }
- }
- }
- </script>
-
- <style scoped lang="scss">
- .select-datetime-container {
- width: 100%;
- }
-
- .datetime-display {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 20rpx;
- background-color: #fff;
- border: 1rpx solid #e0e0e0;
- border-radius: 8rpx;
- font-size: 28rpx;
- color: #333;
-
- text {
- flex: 1;
- }
- }
- </style>
|