This commit is contained in:
Julian Freeman
2026-03-26 15:04:10 -04:00
parent bf435d4986
commit ba4084170e
2 changed files with 51 additions and 9 deletions

View File

@@ -1,13 +1,16 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { ref, computed, onMounted, onUnmounted } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { save } from "@tauri-apps/plugin-dialog";
import { X, Calendar, ChevronLeft, ChevronRight } from "lucide-vue-next";
import { currentDate, showToast, getTagName, logicalMinutesToTime } from "../../store";
import { currentDate, showToast, getTagName, logicalMinutesToTime, toISODate } from "../../store";
import { DBEvent } from "../../types";
defineEmits(['close']);
const startCalendarRef = ref<HTMLElement | null>(null);
const endCalendarRef = ref<HTMLElement | null>(null);
const exportStartDate = ref(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toLocaleDateString('sv'));
const exportEndDate = ref(currentDate.value);
const exportStartMonth = ref(new Date(exportStartDate.value));
@@ -15,6 +18,24 @@ const exportEndMonth = ref(new Date(exportEndDate.value));
const isExportStartCalendarOpen = ref(false);
const isExportEndCalendarOpen = ref(false);
const handleClickOutside = (event: MouseEvent) => {
const target = event.target as HTMLElement;
if (isExportStartCalendarOpen.value && startCalendarRef.value && !startCalendarRef.value.contains(target)) {
isExportStartCalendarOpen.value = false;
}
if (isExportEndCalendarOpen.value && endCalendarRef.value && !endCalendarRef.value.contains(target)) {
isExportEndCalendarOpen.value = false;
}
};
onMounted(() => {
window.addEventListener('mousedown', handleClickOutside);
});
onUnmounted(() => {
window.removeEventListener('mousedown', handleClickOutside);
});
const exportStartCalendarDays = computed(() => {
const y = exportStartMonth.value.getFullYear();
const m = exportStartMonth.value.getMonth();
@@ -77,7 +98,7 @@ const handleExport = async () => {
<div class="space-y-2">
<label class="text-[10px] font-bold text-text-sec">日期范围</label>
<div class="flex gap-4 items-center">
<div class="relative flex-1">
<div class="relative flex-1" ref="startCalendarRef">
<button @click="isExportStartCalendarOpen = !isExportStartCalendarOpen; isExportEndCalendarOpen = false" class="w-full bg-bg-input rounded-xl pl-10 pr-4 py-3 text-sm outline-none border border-transparent focus:border-[#007AFF] transition-all text-left flex items-center">
<Calendar :size="16" class="absolute left-4 text-text-sec" />
{{ exportStartDate }}
@@ -91,13 +112,13 @@ const handleExport = async () => {
<div class="grid grid-cols-7 gap-1 text-center mb-2"><div v-for="d in ['一','二','三','四','五','六','日']" :key="d" class="text-[10px] font-bold text-text-sec">{{d}}</div></div>
<div class="grid grid-cols-7 gap-1">
<div v-for="(date, i) in exportStartCalendarDays" :key="i" class="aspect-square flex items-center justify-center">
<button v-if="date" @click="exportStartDate = date.toLocaleDateString('sv'); isExportStartCalendarOpen = false" class="w-8 h-8 rounded-full text-xs font-medium transition-all" :class="date.toLocaleDateString('sv') === exportStartDate ? 'bg-[#007AFF] text-white font-bold' : 'hover:bg-bg-input text-main'">{{ date.getDate() }}</button>
<button v-if="date" @click="exportStartDate = toISODate(date); isExportStartCalendarOpen = false" class="w-8 h-8 rounded-full text-xs font-medium transition-all" :class="toISODate(date) === exportStartDate ? 'bg-[#007AFF] text-white font-bold' : 'hover:bg-bg-input text-main'">{{ date.getDate() }}</button>
</div>
</div>
</div>
</div>
<span class="text-text-sec font-black text-xs"></span>
<div class="relative flex-1">
<div class="relative flex-1" ref="endCalendarRef">
<button @click="isExportEndCalendarOpen = !isExportEndCalendarOpen; isExportStartCalendarOpen = false" class="w-full bg-bg-input rounded-xl pl-10 pr-4 py-3 text-sm outline-none border border-transparent focus:border-[#007AFF] transition-all text-left flex items-center">
<Calendar :size="16" class="absolute left-4 text-text-sec" />
{{ exportEndDate }}
@@ -111,7 +132,7 @@ const handleExport = async () => {
<div class="grid grid-cols-7 gap-1 text-center mb-2"><div v-for="d in ['一','二','三','四','五','六','日']" :key="d" class="text-[10px] font-bold text-text-sec">{{d}}</div></div>
<div class="grid grid-cols-7 gap-1">
<div v-for="(date, i) in exportEndCalendarDays" :key="i" class="aspect-square flex items-center justify-center">
<button v-if="date" @click="exportEndDate = date.toLocaleDateString('sv'); isExportEndCalendarOpen = false" class="w-8 h-8 rounded-full text-xs font-medium transition-all" :class="date.toLocaleDateString('sv') === exportEndDate ? 'bg-[#007AFF] text-white font-bold' : 'hover:bg-bg-input text-main'">{{ date.getDate() }}</button>
<button v-if="date" @click="exportEndDate = toISODate(date); isExportEndCalendarOpen = false" class="w-8 h-8 rounded-full text-xs font-medium transition-all" :class="toISODate(date) === exportEndDate ? 'bg-[#007AFF] text-white font-bold' : 'hover:bg-bg-input text-main'">{{ date.getDate() }}</button>
</div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { ref, computed, onMounted, onUnmounted } from "vue";
import { BarChart2, Calendar, ChevronLeft, ChevronRight } from "lucide-vue-next";
import {
dashboardStats, dashboardRange, dailyAverageMode, dashboardStartDate, dashboardEndDate,
@@ -9,9 +9,30 @@ import {
} from "../../store/dashboardStore";
import { toISODate } from "../../store";
const startCalendarRef = ref<HTMLElement | null>(null);
const endCalendarRef = ref<HTMLElement | null>(null);
const startCalendarMonth = ref(new Date(customStartDate.value));
const endCalendarMonth = ref(new Date(customEndDate.value));
const handleClickOutside = (event: MouseEvent) => {
const target = event.target as HTMLElement;
if (isStartCalendarOpen.value && startCalendarRef.value && !startCalendarRef.value.contains(target)) {
isStartCalendarOpen.value = false;
}
if (isEndCalendarOpen.value && endCalendarRef.value && !endCalendarRef.value.contains(target)) {
isEndCalendarOpen.value = false;
}
};
onMounted(() => {
window.addEventListener('mousedown', handleClickOutside);
});
onUnmounted(() => {
window.removeEventListener('mousedown', handleClickOutside);
});
const getCalendarDays = (month: Date) => {
const y = month.getFullYear();
const m = month.getMonth();
@@ -48,7 +69,7 @@ const endCalendarDays = computed(() => getCalendarDays(endCalendarMonth.value));
<!-- Custom Date Pickers -->
<div v-if="dashboardRange === 'custom'" class="flex items-center gap-4 animate-in slide-in-from-top-2 duration-300">
<div class="relative flex-1">
<div class="relative flex-1" ref="startCalendarRef">
<button @click="isStartCalendarOpen = !isStartCalendarOpen; isEndCalendarOpen = false" class="w-full bg-bg-card border border-border-main rounded-xl pl-10 pr-4 py-2.5 text-xs font-bold text-left flex items-center hover:bg-bg-input transition-all">
<Calendar :size="14" class="absolute left-3.5 text-[#007AFF]" />
<span class="text-text-sec mr-2"></span> {{ customStartDate }}
@@ -68,7 +89,7 @@ const endCalendarDays = computed(() => getCalendarDays(endCalendarMonth.value));
</div>
</div>
<div class="text-text-sec font-black text-xs"></div>
<div class="relative flex-1">
<div class="relative flex-1" ref="endCalendarRef">
<button @click="isEndCalendarOpen = !isEndCalendarOpen; isStartCalendarOpen = false" class="w-full bg-bg-card border border-border-main rounded-xl pl-10 pr-4 py-2.5 text-xs font-bold text-left flex items-center hover:bg-bg-input transition-all">
<Calendar :size="14" class="absolute left-3.5 text-[#007AFF]" />
<span class="text-text-sec mr-2"></span> {{ customEndDate }}