|
@@ -1,38 +1,43 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref } from 'vue'
|
|
import { ref } from 'vue'
|
|
|
|
|
+import type { Dayjs } from 'dayjs'
|
|
|
|
|
+import dayjs from 'dayjs'
|
|
|
|
|
|
|
|
-const value = ref()
|
|
|
|
|
|
|
+const value = ref<Dayjs>(dayjs())
|
|
|
|
|
|
|
|
// ✅ 修正:精确匹配年月日
|
|
// ✅ 修正:精确匹配年月日
|
|
|
-const getListData = (current: Date) => {
|
|
|
|
|
- const dateStr = current.toISOString().split('T')[0] // "YYYY-MM-DD"
|
|
|
|
|
-
|
|
|
|
|
- // 定义事件数据(示例:2026年1月)
|
|
|
|
|
- const events: Record<string, Array<{ type: string; content: string }>> = {
|
|
|
|
|
- '2026-01-08': [
|
|
|
|
|
- { type: 'warning', content: 'This is warning event.' },
|
|
|
|
|
- { type: 'success', content: 'This is usual event.' }
|
|
|
|
|
- ],
|
|
|
|
|
- '2026-01-10': [
|
|
|
|
|
- { type: 'warning', content: 'This is warning event.' },
|
|
|
|
|
- { type: 'success', content: 'This is usual event.' },
|
|
|
|
|
- { type: 'error', content: 'This is error event.' }
|
|
|
|
|
- ],
|
|
|
|
|
- '2026-01-15': [
|
|
|
|
|
- { type: 'warning', content: 'This is warning event' },
|
|
|
|
|
- { type: 'success', content: 'This is very long usual event。。....' },
|
|
|
|
|
- { type: 'error', content: 'This is error event 1.' },
|
|
|
|
|
- { type: 'error', content: 'This is error event 2.' },
|
|
|
|
|
- { type: 'error', content: 'This is error event 3.' },
|
|
|
|
|
- { type: 'error', content: 'This is error event 4.' }
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+const getListData = (value: Dayjs) => {
|
|
|
|
|
+ let listData
|
|
|
|
|
+ switch (value.date()) {
|
|
|
|
|
+ case 8:
|
|
|
|
|
+ listData = [
|
|
|
|
|
+ { type: 'warning', content: 'This is warning event.' },
|
|
|
|
|
+ { type: 'success', content: 'This is usual event.' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ break
|
|
|
|
|
+ case 10:
|
|
|
|
|
+ listData = [
|
|
|
|
|
+ { type: 'warning', content: 'This is warning event.' },
|
|
|
|
|
+ { type: 'success', content: 'This is usual event.' },
|
|
|
|
|
+ { type: 'error', content: 'This is error event.' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ break
|
|
|
|
|
+ case 15:
|
|
|
|
|
+ listData = [
|
|
|
|
|
+ { type: 'warning', content: 'This is warning event' },
|
|
|
|
|
+ { type: 'success', content: 'This is very long usual event。。....' },
|
|
|
|
|
+ { type: 'error', content: 'This is error event 1.' },
|
|
|
|
|
+ { type: 'error', content: 'This is error event 2.' },
|
|
|
|
|
+ { type: 'error', content: 'This is error event 3.' },
|
|
|
|
|
+ { type: 'error', content: 'This is error event 4.' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ break
|
|
|
|
|
+ default:
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return events[dateStr] || []
|
|
|
|
|
|
|
+ return listData || []
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const getMonthData = (current: Date) => {
|
|
const getMonthData = (current: Date) => {
|
|
|
- // 示例:2026年9月(注意:JS 月份从 0 开始)
|
|
|
|
|
if (current.getFullYear() === 2026 && current.getMonth() === 8) {
|
|
if (current.getFullYear() === 2026 && current.getMonth() === 8) {
|
|
|
return 1394
|
|
return 1394
|
|
|
}
|
|
}
|
|
@@ -42,17 +47,13 @@ const getMonthData = (current: Date) => {
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
|
<div class="calendar-container">
|
|
<div class="calendar-container">
|
|
|
- <!-- 关键:添加 fullscreen 属性 -->
|
|
|
|
|
- <a-calendar
|
|
|
|
|
- v-model:value="value"
|
|
|
|
|
- fullscreen
|
|
|
|
|
- :date-cell-render="({ current }) => $slots.dateCellRender?.({ current })"
|
|
|
|
|
- :month-cell-render="({ current }) => $slots.monthCellRender?.({ current })"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <a-calendar v-model:value="value" fullscreen>
|
|
|
<template #dateCellRender="{ current }">
|
|
<template #dateCellRender="{ current }">
|
|
|
<ul class="events">
|
|
<ul class="events">
|
|
|
<li v-for="(item, index) in getListData(current)" :key="index">
|
|
<li v-for="(item, index) in getListData(current)" :key="index">
|
|
|
- <a-badge :status="item.type" :text="item.content" />
|
|
|
|
|
|
|
+ <!-- 使用原生 span 替代 a-badge(更易控制暗黑样式) -->
|
|
|
|
|
+ <span class="event-badge" :class="`event- $ {item.type}`"></span>
|
|
|
|
|
+ <span class="event-text">{{ item.content }}</span>
|
|
|
</li>
|
|
</li>
|
|
|
</ul>
|
|
</ul>
|
|
|
</template>
|
|
</template>
|
|
@@ -68,75 +69,135 @@ const getMonthData = (current: Date) => {
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
-/* 容器宽度必须足够 */
|
|
|
|
|
.calendar-container {
|
|
.calendar-container {
|
|
|
- width: 860px;
|
|
|
|
|
- margin: 20px auto;
|
|
|
|
|
|
|
+ padding: 0 24px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 深色主题覆盖 ===== */
|
|
|
|
|
+:deep(.ant-picker-calendar) {
|
|
|
|
|
+ background-color: var(--color-mode);
|
|
|
|
|
+ color: #e0e0e0;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+:deep(.ant-picker-calendar-header) {
|
|
|
|
|
+ background-color: var(--color-mode);
|
|
|
|
|
+ /* border-bottom: 1px solid #333; */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+:deep(.ant-picker-calendar-header .ant-picker-year-select),
|
|
|
|
|
+:deep(.ant-picker-calendar-header .ant-picker-month-select) {
|
|
|
|
|
+ /* background-color: #2d2d2d; */
|
|
|
|
|
+ border: 1px solid #444;
|
|
|
|
|
+ color: #e0e0e0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+:deep(.ant-picker-calendar-body) {
|
|
|
|
|
+ background-color: #1a1a1a;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 修复日期格子布局 —— 关键! */
|
|
|
|
|
+:deep(.ant-picker-calendar-date) {
|
|
|
|
|
+ /* width: calc(100% / 7) !important; */
|
|
|
|
|
+ height: 100px !important;
|
|
|
|
|
+ display: block !important;
|
|
|
|
|
+ /* float: left !important; */
|
|
|
|
|
+ /* box-sizing: border-box !important; */
|
|
|
|
|
+ /* padding: 8px !important; */
|
|
|
|
|
+ /* text-align: center !important; */
|
|
|
|
|
+ /* border: 1px solid #333 !important; */
|
|
|
|
|
+ background-color: var(--color-calendar-cell-bg) !important;
|
|
|
|
|
+ /* cursor: pointer; */
|
|
|
|
|
+ /* position: relative; */
|
|
|
|
|
+}
|
|
|
|
|
+.ant-picker-calendar .ant-picker-content td.ant-picker-cell:not(.ant-picker-cell-in-view),
|
|
|
|
|
+.ant-picker-dropdown .ant-picker-content td.ant-picker-cell:not(.ant-picker-cell-in-view) {
|
|
|
|
|
+ background-color: red !important;
|
|
|
|
|
+}
|
|
|
|
|
+:deep(.ant-picker-calendar-date:hover) {
|
|
|
|
|
+ background-color: #2a2a2a !important;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 日期数字 */
|
|
|
|
|
+:deep(.ant-picker-calendar-date-value) {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ line-height: 1.2;
|
|
|
|
|
+ color: #e0e0e0;
|
|
|
|
|
+ margin-bottom: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 选中状态 */
|
|
|
|
|
+:deep(.ant-picker-calendar-date-selected) {
|
|
|
|
|
+ background-color: #0066ff !important;
|
|
|
|
|
+ border-color: #0066ff !important;
|
|
|
|
|
+ color: white !important;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 事件列表样式 */
|
|
|
|
|
|
|
+/* 今天 */
|
|
|
|
|
+:deep(.ant-picker-calendar-date-today) {
|
|
|
|
|
+ background-color: #2a2a2a !important;
|
|
|
|
|
+ border-color: #555 !important;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 事件列表 */
|
|
|
.events {
|
|
.events {
|
|
|
list-style: none;
|
|
list-style: none;
|
|
|
margin: 0;
|
|
margin: 0;
|
|
|
padding: 0;
|
|
padding: 0;
|
|
|
- max-height: 80px;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
|
|
+ max-height: 70px;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+ font-size: 12px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.events li {
|
|
.events li {
|
|
|
- margin-top: 4px;
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 4px;
|
|
|
|
|
+ margin-top: 2px;
|
|
|
|
|
+ color: #ccc;
|
|
|
|
|
+ text-align: left;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.events .ant-badge-status {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- white-space: nowrap;
|
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
|
|
|
+.event-badge {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ width: 8px;
|
|
|
|
|
+ height: 8px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 月份备注样式 */
|
|
|
|
|
-.notes-month {
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- font-size: 28px;
|
|
|
|
|
- line-height: 1.2;
|
|
|
|
|
|
|
+.event-warning {
|
|
|
|
|
+ background-color: #faad14;
|
|
|
}
|
|
}
|
|
|
-.notes-month span {
|
|
|
|
|
- display: block;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- color: rgba(0, 0, 0, 0.45);
|
|
|
|
|
|
|
+.event-success {
|
|
|
|
|
+ background-color: #52c41a;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-/* 使用 :deep() 穿透 scoped 限制 */
|
|
|
|
|
-:deep(.ant-picker-calendar) {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- max-width: 900px;
|
|
|
|
|
- margin: 0 auto;
|
|
|
|
|
|
|
+.event-error {
|
|
|
|
|
+ background-color: #ff4d4f;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-:deep(.ant-picker-calendar-date) {
|
|
|
|
|
- width: calc(100% / 7) !important;
|
|
|
|
|
- display: block !important;
|
|
|
|
|
- float: left !important; /* 关键:确保横向排列 */
|
|
|
|
|
- box-sizing: border-box !important;
|
|
|
|
|
|
|
+/* 月份备注 */
|
|
|
|
|
+:deep(.notes-month) {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ color: #e0e0e0;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-/* 清除可能的 flex 干扰 */
|
|
|
|
|
-:deep(.ant-picker-calendar-body),
|
|
|
|
|
-:deep(.ant-picker-calendar-panel) {
|
|
|
|
|
- display: block !important;
|
|
|
|
|
- flex: none !important;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* ✅ 修复:仅作用于弹窗日期选择器,不影响 ACalendar */
|
|
|
|
|
-/* .ant-picker-dropdown {
|
|
|
|
|
- .ant-picker-cell-inner {
|
|
|
|
|
- display: flex !important;
|
|
|
|
|
- align-items: center !important;
|
|
|
|
|
- justify-content: center !important;
|
|
|
|
|
- width: 32px !important;
|
|
|
|
|
- height: 32px !important;
|
|
|
|
|
- border-radius: 6px !important;
|
|
|
|
|
|
|
+:deep(.notes-month section) {
|
|
|
|
|
+ font-size: 28px;
|
|
|
|
|
+ line-height: 28px;
|
|
|
|
|
+}
|
|
|
|
|
+:deep(.notes-month span) {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #aaa;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+<style lang="scss">
|
|
|
|
|
+div:where(.css-dev-only-do-not-override-1p3hq3p).ant-picker-calendar.ant-picker-calendar-full
|
|
|
|
|
+ .ant-picker-panel {
|
|
|
|
|
+ background-color: var(--color-mode);
|
|
|
|
|
+ span,
|
|
|
|
|
+ td,
|
|
|
|
|
+ th {
|
|
|
|
|
+ color: var(--color-neutral-1);
|
|
|
}
|
|
}
|
|
|
-} */
|
|
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|