2024-10-02 20:09:17 +08:00

169 lines
4.7 KiB
Vue

<script lang="ts" setup>
import type { ThingType } from './type';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek';
import weekday from 'dayjs/plugin/weekday';
import { getWeekDates } from './helper';
const props = withDefaults(defineProps<Props>(), {
groupedEvents: () => new Map(),
timeLineWidth: 80,
});
dayjs.extend(isoWeek);
dayjs.extend(weekday);
defineComponent({ name: 'GantDate' });
interface Props {
groupedEvents?: Map<number, ThingType[]>
timeLineWidth?: number
}
const value = defineModel('value', {
type: Number,
default: dayjs().valueOf(),
});
/** ** 正确的格式一定为某一天的起始 */
const selectedDate = computed({
get: () => dayjs(value.value).startOf('day').valueOf(),
set: (val) => {
value.value = val;
},
});
const weekDates = defineModel('weekDates', {
type: Object as () => { date: number, day: string, weekDay: string }[],
default: () => [],
});
// 选择日期
function selectDate(date: number) {
selectedDate.value = date;
}
// 日历选择器事件
// function datePickerChange(time: number) {
// selectDate(time);
// weekDates.value = getWeekDates(time);
// }
// 回到今天
function backToToday() {
selectDate(dayjs().startOf('day').valueOf());
weekDates.value = getWeekDates(dayjs().startOf('day').valueOf());
}
// 上一周
function prevWeek() {
const prevWeekDate = dayjs(selectedDate.value).subtract(7, 'day').valueOf();
selectDate(prevWeekDate);
weekDates.value = getWeekDates(prevWeekDate);
}
// 下一周
function nextWeek() {
const nextWeekDate = dayjs(selectedDate.value).add(7, 'day').valueOf();
selectDate(nextWeekDate);
weekDates.value = getWeekDates(nextWeekDate);
}
const weekDatesForMarks = computed(() => {
return weekDates.value.map((item) => {
return {
...item,
isMark: props.groupedEvents.get(item.date)?.length,
};
});
});
</script>
<template>
<div class="gantDateShadow flex flex-col pb-2 pt-2">
<div class="relative flex flex-1 flex-row items-center justify-center flex-self-stretch">
<div class="relative flex flex-row items-center gap-2">
<!-- <n-date-picker
class="absolute left-0 top-0 z-2 wh-full overflow-hidden opacity-0 !cursor-pointer"
:value="selectedDate"
:default-value="selectedDate"
type="date"
@update:value="datePickerChange"
/> -->
<span class="font-bold">
{{ dayjs(selectedDate).format('YYYY年M月') }}
</span>
<SvgIcon class="rotate-0 font-bold" icon="i-ic-round-keyboard-arrow-down" />
</div>
<div class="absolute b h-full flex-col flex items-center justify-center right-0 flex-self-stretch">
<div
class="text-onPrimary text-20 bg-primary py-1 pr-1 pl-2 rounded-l-full flex items-center justify-center line-height-none"
@click="backToToday"
>
回到今日
</div>
</div>
</div>
<div
class="relative mt-8rpx flex flex-row items-center flex-self-stretch"
:style="{
paddingLeft: `${props.timeLineWidth}rpx`,
}"
>
<div
class="absolute h-32 w-32 flex items-center justify-center rounded-full bg-primary left-8rpx" @click="prevWeek"
>
<SvgIcon class="text-28 text-white font-bold" icon="i-material-symbols-chevron-left-rounded" />
</div>
<!-- 周历表 -->
<div class="flex w-[calc((100%/7.5)*7)] flex-row items-center justify-between flex-self-stretch">
<div
v-for="(item, index) in weekDatesForMarks"
:key="index"
class="flex flex-col cursor-pointer flex-1 items-center justify-center"
@click="selectDate(item.date)"
>
<span
class="text-20"
:class="{
'text-primary': item.date === selectedDate,
}"
>
{{ item.weekDay }}
</span>
<span
class="text-20 font-bold"
:class="{
'text-primary': item.date === selectedDate,
}"
>
{{ item.day }}
</span>
<!-- 标记点 -->
<div
class="mt-0 h-1 w-1 rounded-full"
:class="{
'bg-primary': item.isMark,
'!bg-[#CCCCCC]': item.isMark && item.date < dayjs().startOf('day').valueOf(),
}"
/>
</div>
</div>
<div class="absolute right-8rpx h-32 w-32 flex items-center justify-center rounded-full bg-primary" @click="nextWeek">
<SvgIcon class="text-5 text-white font-bold" icon="i-material-symbols-chevron-right-rounded" />
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.gantDateShadow {
box-shadow: 0rpx 16rpx 40rpx 20rpx rgba(0, 0, 0, 0.02);
}
</style>