小程序初始提交
This commit is contained in:
273
cool-unix/uni_modules/cool-ui/components/cl-calendar/picker.uvue
Normal file
273
cool-unix/uni_modules/cool-ui/components/cl-calendar/picker.uvue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<view
|
||||
class="cl-calendar-picker"
|
||||
:class="{
|
||||
'is-dark': isDark
|
||||
}"
|
||||
v-if="visible"
|
||||
>
|
||||
<view class="cl-calendar-picker__header">
|
||||
<view
|
||||
class="cl-calendar-picker__prev"
|
||||
:class="{
|
||||
'is-dark': isDark
|
||||
}"
|
||||
@tap="prev"
|
||||
>
|
||||
<cl-icon name="arrow-left-double-line"></cl-icon>
|
||||
</view>
|
||||
|
||||
<view class="cl-calendar-picker__date" @tap="toMode('year')">
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: 'text-lg'
|
||||
}"
|
||||
>
|
||||
{{ title }}
|
||||
</cl-text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="cl-calendar-picker__next"
|
||||
:class="{
|
||||
'is-dark': isDark
|
||||
}"
|
||||
@tap="next"
|
||||
>
|
||||
<cl-icon name="arrow-right-double-line"></cl-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cl-calendar-picker__list">
|
||||
<view
|
||||
class="cl-calendar-picker__item"
|
||||
v-for="item in list"
|
||||
:key="item.value"
|
||||
@tap="select(item.value)"
|
||||
>
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass([[item.value == value, 'text-primary-500']])
|
||||
}"
|
||||
>{{ item.label }}</cl-text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { first, isDark, last, parseClass } from "@/cool";
|
||||
import { t } from "@/locale";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-calendar-picker"
|
||||
});
|
||||
|
||||
// 定义日历选择器的条目类型
|
||||
type Item = {
|
||||
label: string; // 显示的标签,如"1月"、"2024"
|
||||
value: number; // 对应的数值,如1、2024
|
||||
};
|
||||
|
||||
// 定义组件接收的属性:年份和月份,均为数字类型,默认值为0
|
||||
const props = defineProps({
|
||||
year: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
month: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
// 定义组件可触发的事件,这里只定义了"change"事件
|
||||
const emit = defineEmits(["change"]);
|
||||
|
||||
// 当前选择的模式,"year"表示选择年份,"month"表示选择月份,默认是"month"
|
||||
const mode = ref<"year" | "month">("month");
|
||||
|
||||
// 当前选中的年份
|
||||
const year = ref(0);
|
||||
|
||||
// 当前选中的月份
|
||||
const month = ref(0);
|
||||
|
||||
// 当前年份选择面板的起始年份(如2020-2029,则startYear为2020)
|
||||
const startYear = ref(0);
|
||||
|
||||
// 当前选中的值,若为月份模式则为月份,否则为年份
|
||||
const value = computed(() => {
|
||||
return mode.value == "month" ? month.value : year.value;
|
||||
});
|
||||
|
||||
// 计算可供选择的列表:
|
||||
// - 若为月份模式,返回1-12月
|
||||
// - 若为年份模式,返回以startYear为起点的连续10年
|
||||
const list = computed(() => {
|
||||
if (mode.value == "month") {
|
||||
return [
|
||||
{ label: t("1月"), value: 1 },
|
||||
{ label: t("2月"), value: 2 },
|
||||
{ label: t("3月"), value: 3 },
|
||||
{ label: t("4月"), value: 4 },
|
||||
{ label: t("5月"), value: 5 },
|
||||
{ label: t("6月"), value: 6 },
|
||||
{ label: t("7月"), value: 7 },
|
||||
{ label: t("8月"), value: 8 },
|
||||
{ label: t("9月"), value: 9 },
|
||||
{ label: t("10月"), value: 10 },
|
||||
{ label: t("11月"), value: 11 },
|
||||
{ label: t("12月"), value: 12 }
|
||||
] as Item[];
|
||||
} else {
|
||||
const years: Item[] = [];
|
||||
// 生成10个连续年份
|
||||
for (let i = 0; i < 10; i++) {
|
||||
years.push({
|
||||
label: `${startYear.value + i}`,
|
||||
value: startYear.value + i
|
||||
});
|
||||
}
|
||||
return years;
|
||||
}
|
||||
});
|
||||
|
||||
// 计算标题内容:
|
||||
// - 月份模式下显示“xxxx年”
|
||||
// - 年份模式下显示“起始年 - 结束年”
|
||||
const title = computed(() => {
|
||||
return mode.value == "month"
|
||||
? `${year.value}`
|
||||
: `${first(list.value)?.label} - ${last(list.value)?.label}`;
|
||||
});
|
||||
|
||||
// 控制选择器弹窗的显示与隐藏
|
||||
const visible = ref(false);
|
||||
|
||||
/**
|
||||
* 打开选择器,并初始化年份、月份、起始年份
|
||||
*/
|
||||
function open() {
|
||||
visible.value = true;
|
||||
|
||||
// 初始化当前年份和月份为传入的props
|
||||
year.value = props.year;
|
||||
month.value = props.month;
|
||||
|
||||
// 计算当前年份所在的十年区间的起始年份
|
||||
startYear.value = Math.floor(year.value / 10) * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭选择器
|
||||
*/
|
||||
function close() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换选择模式(年份/月份)
|
||||
* @param val "year" 或 "month"
|
||||
*/
|
||||
function toMode(val: "year" | "month") {
|
||||
mode.value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择某个值(年份或月份)
|
||||
* @param val 选中的值
|
||||
*/
|
||||
function select(val: number) {
|
||||
if (mode.value == "month") {
|
||||
// 选择月份后,关闭弹窗并触发change事件
|
||||
month.value = val;
|
||||
close();
|
||||
emit("change", [year.value, month.value]);
|
||||
} else {
|
||||
// 选择年份后,切换到月份选择模式
|
||||
year.value = val;
|
||||
toMode("month");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到上一个区间
|
||||
* - 月份模式下,年份减1
|
||||
* - 年份模式下,起始年份减10
|
||||
*/
|
||||
function prev() {
|
||||
if (mode.value == "month") {
|
||||
year.value -= 1;
|
||||
} else {
|
||||
startYear.value -= 10;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到下一个区间
|
||||
* - 月份模式下,年份加1
|
||||
* - 年份模式下,起始年份加10
|
||||
*/
|
||||
function next() {
|
||||
if (mode.value == "month") {
|
||||
year.value += 1;
|
||||
} else {
|
||||
startYear.value += 10;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cl-calendar-picker {
|
||||
@apply flex flex-col absolute left-0 top-0 w-full h-full bg-white z-10;
|
||||
|
||||
&__header {
|
||||
@apply flex flex-row items-center justify-between w-full p-3;
|
||||
}
|
||||
|
||||
&__prev,
|
||||
&__next {
|
||||
@apply flex flex-row items-center justify-center rounded-full bg-surface-100;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
|
||||
&.is-dark {
|
||||
@apply bg-surface-700;
|
||||
}
|
||||
}
|
||||
|
||||
&__date {
|
||||
@apply flex flex-row items-center justify-center;
|
||||
}
|
||||
|
||||
&__list {
|
||||
@apply flex flex-row flex-wrap;
|
||||
}
|
||||
|
||||
&__item {
|
||||
@apply flex flex-row items-center justify-center;
|
||||
height: 100rpx;
|
||||
width: 25%;
|
||||
|
||||
&-bg {
|
||||
@apply px-4 py-2;
|
||||
|
||||
&.is-active {
|
||||
@apply bg-primary-500 rounded-xl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-dark {
|
||||
@apply bg-surface-800 rounded-2xl;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user