automated_uniapp/uni_modules/cool-ui/components/cl-select-date/cl-select-date.vue
2025-01-09 16:16:11 +08:00

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>