281 lines
5.1 KiB
Vue
281 lines
5.1 KiB
Vue
<template>
|
|
<view class="cl-select-date" @tap="open">
|
|
<slot :value="modelValue" :label="modelValue">
|
|
<cl-select-inner
|
|
:height="height"
|
|
:placeholder="placeholder"
|
|
:disabled="disabled"
|
|
:border="border"
|
|
:round="round"
|
|
:backgroundColor="backgroundColor"
|
|
:borderRadius="borderRadius"
|
|
arrowIcon="cl-icon-time"
|
|
:padding="padding"
|
|
:text="text"
|
|
/>
|
|
</slot>
|
|
</view>
|
|
|
|
<!-- 弹出框 -->
|
|
<cl-select-popup :ref="setRefs('popup')" :title="title" :show-picker="false">
|
|
<template #list>
|
|
<view class="cl-select-date__wrap">
|
|
<picker-view :value="value" class="cl-select-date__picker" @change="onChange">
|
|
<picker-view-column v-for="(c, ci) in columns" :key="ci">
|
|
<view
|
|
class="cl-select-date__picker-item"
|
|
v-for="(item, index) in c.list"
|
|
:key="index"
|
|
>
|
|
{{ item }}{{ c.unit }}
|
|
</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
</view>
|
|
</template>
|
|
|
|
<template #confirm>
|
|
<cl-button type="primary" size="large" round fill @tap="confirm">选择</cl-button>
|
|
</template>
|
|
</cl-select-popup>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { range } from "lodash-es";
|
|
import dayjs from "dayjs";
|
|
import { type PropType, computed, defineComponent, ref, nextTick } from "vue";
|
|
import { useRefs } from "/@/cool";
|
|
import { Props } from "../cl-select-inner/config";
|
|
|
|
export default defineComponent({
|
|
name: "cl-select-date",
|
|
|
|
props: {
|
|
...Props,
|
|
// 绑定值
|
|
modelValue: String,
|
|
// 标题
|
|
title: {
|
|
type: String,
|
|
default: "选择日期",
|
|
},
|
|
// 开始年
|
|
startYear: {
|
|
type: Number,
|
|
default: 2000,
|
|
},
|
|
// 模式
|
|
mode: {
|
|
type: Array as PropType<("year" | "month" | "date" | "hour" | "minute" | "second")[]>,
|
|
default: ["year", "month", "date", "hour", "minute", "second"],
|
|
},
|
|
// 格式化值
|
|
format: {
|
|
type: String,
|
|
default: "YYYY-MM-DD HH:mm:ss",
|
|
},
|
|
// 格式化显示内容
|
|
displayFormat: Function,
|
|
// 开始时间
|
|
start: String,
|
|
// 结束时间
|
|
end: String,
|
|
// 占位文本
|
|
placeholder: {
|
|
type: String,
|
|
default: "请选择时间",
|
|
},
|
|
},
|
|
|
|
emits: ["update:modelValue", "change"],
|
|
|
|
setup(props, { emit }) {
|
|
const { refs, setRefs } = useRefs();
|
|
|
|
// 选中日期
|
|
const date = ref();
|
|
|
|
// picker 绑定值
|
|
const value = ref<number[]>([]);
|
|
|
|
// 显示文本
|
|
const text = computed(() => {
|
|
return props.displayFormat ? props.displayFormat(props.modelValue) : props.modelValue;
|
|
});
|
|
|
|
// 列数据
|
|
const columns = computed(() => {
|
|
const years = range(props.startYear, props.startYear + 50);
|
|
const months = range(1, 13);
|
|
|
|
// 当前月多少天
|
|
const ed = getDate(date.value).endOf("month").date();
|
|
const days = range(1, ed + 1);
|
|
|
|
const hours = range(24);
|
|
const minutes = range(60);
|
|
const seconds = range(60);
|
|
|
|
// 格式化
|
|
const d = {
|
|
year: {
|
|
list: years,
|
|
unit: "年",
|
|
},
|
|
month: {
|
|
list: months,
|
|
unit: "月",
|
|
},
|
|
date: {
|
|
list: days,
|
|
unit: "日",
|
|
},
|
|
hour: {
|
|
list: hours,
|
|
unit: "时",
|
|
},
|
|
minute: {
|
|
list: minutes,
|
|
unit: "分",
|
|
},
|
|
second: {
|
|
list: seconds,
|
|
unit: "秒",
|
|
},
|
|
};
|
|
|
|
return props.mode.map((k) => d[k]);
|
|
});
|
|
|
|
// 获取时间
|
|
function getDate(val: string) {
|
|
let a = dayjs();
|
|
|
|
if (val) {
|
|
let b = val.split(/\D+/g);
|
|
|
|
props.mode.forEach((k, i) => {
|
|
let v = Number(b[i]);
|
|
|
|
if (k == "month") {
|
|
v -= 1;
|
|
}
|
|
|
|
a = a.set(k, v);
|
|
});
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
// 设置值
|
|
function setDate(val?: string, isChange = true) {
|
|
date.value = val || undefined;
|
|
|
|
// 日期
|
|
const d = getDate(date.value);
|
|
|
|
// 取下标
|
|
const arr = props.mode.map((k, i) => {
|
|
let v = d[k]?.();
|
|
|
|
if (k == "month") {
|
|
v += 1;
|
|
}
|
|
|
|
return columns.value[i].list.findIndex((e) => e == v);
|
|
});
|
|
|
|
// 清空,避免 value 重复不刷新
|
|
value.value = props.mode.map(() => 0);
|
|
|
|
nextTick(() => {
|
|
value.value = arr;
|
|
|
|
// 触发监听
|
|
if (isChange) {
|
|
onChange({ detail: { value: arr } });
|
|
}
|
|
});
|
|
}
|
|
|
|
// 监听选择
|
|
function onChange(e: { detail: { value: number[] } }) {
|
|
value.value = e.detail.value;
|
|
|
|
let d = dayjs();
|
|
|
|
// 设置值
|
|
props.mode.forEach((k, i) => {
|
|
let v = value.value[i];
|
|
|
|
if (k == "year") {
|
|
v += props.startYear;
|
|
}
|
|
|
|
if (k == "date") {
|
|
v += 1;
|
|
|
|
const ed = d.endOf("month").date();
|
|
|
|
if (v > ed) {
|
|
v = ed;
|
|
}
|
|
}
|
|
|
|
d = d.set(k, v);
|
|
});
|
|
|
|
date.value = d.format(props.format);
|
|
|
|
// 小于开始时间
|
|
if (props.start) {
|
|
if (d.isBefore(dayjs(getDate(props.start)))) {
|
|
setDate(props.start, false);
|
|
}
|
|
}
|
|
|
|
// 大于结束时间
|
|
if (props.end) {
|
|
if (d.isAfter(dayjs(getDate(props.end)))) {
|
|
setDate(props.end, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 保存
|
|
function confirm() {
|
|
emit("update:modelValue", date.value);
|
|
emit("change", date.value);
|
|
close();
|
|
}
|
|
|
|
// 打开
|
|
function open() {
|
|
setDate(props.modelValue);
|
|
refs.popup.open();
|
|
}
|
|
|
|
// 关闭
|
|
function close() {
|
|
refs.popup.close();
|
|
}
|
|
|
|
return {
|
|
date,
|
|
columns,
|
|
value,
|
|
text,
|
|
getDate,
|
|
setDate,
|
|
confirm,
|
|
onChange,
|
|
refs,
|
|
setRefs,
|
|
open,
|
|
close,
|
|
};
|
|
},
|
|
});
|
|
</script>
|