|
|
@@ -1,102 +1,105 @@
|
|
|
<template>
|
|
|
- <CalendarDateSelectHeader
|
|
|
- v-if="showCalendarSelector"
|
|
|
- v-model:currentYear="currentYear"
|
|
|
- v-model:currentMonth="currentMonth"
|
|
|
- ></CalendarDateSelectHeader>
|
|
|
- <!-- 日历主体 -->
|
|
|
- <!-- 日历网格(包含星期表头行+日期行) -->
|
|
|
- <div class="cal_body" :style="{ gridTemplateRows: `50px repeat(${calendarRows}, 1fr)` }">
|
|
|
- <!-- 星期表头行 -->
|
|
|
- <div class="cal_header"
|
|
|
- v-for="(d, idx) in weekdays" :key="d"
|
|
|
- :class="{ is_weekend: idx === 0 || idx === 6 }">
|
|
|
- {{ d }}
|
|
|
- </div>
|
|
|
+ <div class="calendar_todo">
|
|
|
+ <CalendarDateSelectHeader
|
|
|
+ v-if="showCalendarSelector"
|
|
|
+ v-model:currentYear="currentYear"
|
|
|
+ v-model:currentMonth="currentMonth"
|
|
|
+ ></CalendarDateSelectHeader>
|
|
|
+ <!-- 日历主体 -->
|
|
|
+ <!-- 日历网格(包含星期表头行+日期行) -->
|
|
|
+ <div class="cal_body" :style="{ gridTemplateRows: `50px repeat(${calendarRows}, 1fr)` }">
|
|
|
+ <!-- 星期表头行 -->
|
|
|
+ <div class="cal_header"
|
|
|
+ v-for="(d, idx) in weekdays" :key="d"
|
|
|
+ :class="{ is_weekend: idx === 0 || idx === 6 }">
|
|
|
+ {{ d }}
|
|
|
+ </div>
|
|
|
|
|
|
- <!-- 日期行(从索引 7 开始,前 7 个是表头) -->
|
|
|
- <div class="cal_cell" v-for="(cell, idx) in calendarCells"
|
|
|
- :key="'c' + idx" :class="{
|
|
|
- is_other_month: !cell.inCurrentMonth,
|
|
|
- is_today: cell.isToday,
|
|
|
- is_selected: cell.isSelected,
|
|
|
- is_weekend: cell.weekday === 0 || cell.weekday === 6,
|
|
|
- is_last_row: cell.isLastRow}"
|
|
|
- @click="handleCellClick(cell.date, cell.inCurrentMonth)">
|
|
|
+ <!-- 日期行(从索引 7 开始,前 7 个是表头) -->
|
|
|
+ <div class="cal_cell" v-for="(cell, idx) in calendarCells"
|
|
|
+ :key="'c' + idx" :class="{
|
|
|
+ is_other_month: !cell.inCurrentMonth,
|
|
|
+ is_today: cell.isToday,
|
|
|
+ is_selected: cell.isSelected,
|
|
|
+ is_weekend: cell.weekday === 0 || cell.weekday === 6,
|
|
|
+ is_last_row: cell.isLastRow}"
|
|
|
+ @click="handleCellClick(cell.date, cell.inCurrentMonth)">
|
|
|
|
|
|
-
|
|
|
- <!-- 日期信息 -->
|
|
|
- <div class="cal_cell_top" v-if="cell.inCurrentMonth">
|
|
|
- <span class="cal_cell_num">{{ cell.num < 10 ? '0' + cell.num : cell.num }}</span>
|
|
|
- <span class="cal_cell_count" v-if="cell.events.length > 0">共{{ cell.events.length
|
|
|
- }}项</span>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 日历所属日期下的待办事项 -->
|
|
|
- <div class="cal_cell_events" v-if="cell.inCurrentMonth">
|
|
|
- <div class="cal_event_item"
|
|
|
- v-for="(ev, ei) in cell.events" :key="ev.id"
|
|
|
- @click.stop="handleEventClick(cell.date, ev, ei)"
|
|
|
- >
|
|
|
- <div class="event_main" :class="{ is_selected: selectedEventId === ev.id }">
|
|
|
- <span class="cal_event_dot"></span>
|
|
|
- <div style="display: flex;flex-direction: column;">
|
|
|
- <span class="cal_event_text">{{ ev.title }}</span>
|
|
|
- <span class="cal_event_text">{{ ev.desc }}</span>
|
|
|
+
|
|
|
+ <!-- 日期信息 -->
|
|
|
+ <div class="cal_cell_top" v-if="cell.inCurrentMonth">
|
|
|
+ <span class="cal_cell_num">{{ cell.num < 10 ? '0' + cell.num : cell.num }}</span>
|
|
|
+ <span class="cal_cell_count" v-if="cell.events.length > 0">共{{ cell.events.length
|
|
|
+ }}项</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 日历所属日期下的待办事项 -->
|
|
|
+ <div class="cal_cell_events" v-if="cell.inCurrentMonth">
|
|
|
+ <div class="cal_event_item"
|
|
|
+ v-for="(ev, ei) in cell.events" :key="ev.id"
|
|
|
+ @click.stop="handleEventClick(cell.date, ev, ei)"
|
|
|
+ >
|
|
|
+ <div class="event_main" :class="{ is_selected: selectedEventId === ev.id }">
|
|
|
+ <span class="cal_event_dot"></span>
|
|
|
+ <div style="display: flex;flex-direction: column;">
|
|
|
+ <span class="cal_event_text">{{ ev.title }}</span>
|
|
|
+ <span class="cal_event_text">{{ ev.desc }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 日历事件弹窗 -->
|
|
|
- <!-- 事件悬浮窗挂载到 cell 外,避免被 cal_cell_events 的 overflow 裁剪 -->
|
|
|
- <div v-if="hoverState.dateKey === formatDate(cell.date) && hoverState.event"
|
|
|
- class="event_popup"
|
|
|
- :class="cell.weekday === 5 || cell.weekday === 6 ? 'popup_left' : 'popup_right'"
|
|
|
- :style="{ top: `${10 + hoverState.eventIndex * 24}px` }">
|
|
|
- <div class="event_popup_title">{{ hoverState.event.isCustomToDo ? hoverState.event.desc : hoverState.event.customerName}}</div>
|
|
|
- <div class="event_popup_middle_title" v-if="!(hoverState.event.isCustomToDo)">{{ hoverState.event.productName }}</div>
|
|
|
- <div class="event_popup_desc" v-if="!(hoverState.event.isCustomToDo)">{{ hoverState.event.desc }}</div>
|
|
|
-
|
|
|
- <div class="event_popup_actions">
|
|
|
- <span class="event_popup_date">{{ formatPopupDate(cell.date) }} {{ hoverState.event.title.split(' ')[0] }}</span>
|
|
|
- <span class="event_actions_right" v-if="hasSchoolManager">
|
|
|
- <template v-if="hoverState.event.isCustomToDo">
|
|
|
- <span class="event_btn event_edit" @click.stop="editEvent(hoverState.event)">编辑</span>
|
|
|
- <span class="event_btn event_delete" @click.stop="deleteEvent(hoverState.event)">删除</span>
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <span class="event_btn event_edit" @click.stop="detailEvent(hoverState.event)">详情</span>
|
|
|
- </template>
|
|
|
- </span>
|
|
|
+ <!-- 日历事件弹窗 -->
|
|
|
+ <!-- 事件悬浮窗挂载到 cell 外,避免被 cal_cell_events 的 overflow 裁剪 -->
|
|
|
+ <div v-if="hoverState.dateKey === formatDate(cell.date) && hoverState.event"
|
|
|
+ class="event_popup"
|
|
|
+ :class="cell.weekday === 5 || cell.weekday === 6 ? 'popup_left' : 'popup_right'"
|
|
|
+ :style="{ top: `${10 + hoverState.eventIndex * 24}px` }">
|
|
|
+ <div class="event_popup_title">{{ hoverState.event.isCustomToDo ? hoverState.event.desc : hoverState.event.customerName}}</div>
|
|
|
+ <div class="event_popup_middle_title" v-if="!(hoverState.event.isCustomToDo)">{{ hoverState.event.productName }}</div>
|
|
|
+ <div class="event_popup_desc" v-if="!(hoverState.event.isCustomToDo)">{{ hoverState.event.desc }}</div>
|
|
|
+
|
|
|
+ <div class="event_popup_actions">
|
|
|
+ <span class="event_popup_date">{{ formatPopupDate(cell.date) }} {{ hoverState.event.title.split(' ')[0] }}</span>
|
|
|
+ <span class="event_actions_right" v-if="hasSchoolManager">
|
|
|
+ <template v-if="hoverState.event.isCustomToDo">
|
|
|
+ <span class="event_btn event_edit" @click.stop="editEvent(hoverState.event)">编辑</span>
|
|
|
+ <span class="event_btn event_delete" @click.stop="deleteEvent(hoverState.event)">删除</span>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span class="event_btn event_edit" @click.stop="detailEvent(hoverState.event)">详情</span>
|
|
|
+ </template>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 创建日历事件弹窗 日期格子悬浮窗:展示当天所有日程列表 + 新增日程按钮 -->
|
|
|
- <div v-if="cellHoverState.dateKey === formatDate(cell.date) && !hoverState.event"
|
|
|
- class="cell_popup"
|
|
|
- :class="[cell.weekday === 5 || cell.weekday === 6 ? 'popup_left' : 'popup_right', cell.isLastRow ? 'popup_top' : '']">
|
|
|
- <div class="cell_popup_header">
|
|
|
- <span class="cell_popup_date">{{ formatDate(cell.date) }}</span>
|
|
|
- <span class="cell_popup_count">共{{ cell.events.length }}项</span>
|
|
|
- </div>
|
|
|
- <div class="cell_popup_events">
|
|
|
- <div class="cell_popup_event" v-for="(ev, ei) in cell.events" :key="ev.id">
|
|
|
- <span class="cell_popup_dot"></span>
|
|
|
- <div style="display: flex;flex-direction: column;">
|
|
|
- <span class="cell_popup_title">{{ ev.title }}</span>
|
|
|
- <span class="cell_popup_text">{{ ev.desc }}</span>
|
|
|
+ <!-- 创建日历事件弹窗 日期格子悬浮窗:展示当天所有日程列表 + 新增日程按钮 -->
|
|
|
+ <div v-if="cellHoverState.dateKey === formatDate(cell.date) && !hoverState.event"
|
|
|
+ class="cell_popup"
|
|
|
+ :class="[cell.weekday === 5 || cell.weekday === 6 ? 'popup_left' : 'popup_right', cell.isLastRow ? 'popup_top' : '']">
|
|
|
+ <div class="cell_popup_header">
|
|
|
+ <span class="cell_popup_date">{{ formatDate(cell.date) }}</span>
|
|
|
+ <span class="cell_popup_count">共{{ cell.events.length }}项</span>
|
|
|
+ </div>
|
|
|
+ <div class="cell_popup_events">
|
|
|
+ <div class="cell_popup_event" v-for="(ev, ei) in cell.events" :key="ev.id">
|
|
|
+ <span class="cell_popup_dot"></span>
|
|
|
+ <div style="display: flex;flex-direction: column;">
|
|
|
+ <span class="cell_popup_title">{{ ev.title }}</span>
|
|
|
+ <span class="cell_popup_text">{{ ev.desc }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <div v-if="cell.events.length === 0" class="cell_popup_empty">暂无日程安排</div>
|
|
|
</div>
|
|
|
- <div v-if="cell.events.length === 0" class="cell_popup_empty">暂无日程安排</div>
|
|
|
+ <div class="cell_popup_add" v-if="hasSchoolManager" @click.stop="openAddSchedule(cell.date)">
|
|
|
+ <img :src="addIcon" alt="" style="width: 16px; height: 16px;">
|
|
|
+ <span>新增日程</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="cell_popup_add" v-if="hasSchoolManager" @click.stop="openAddSchedule(cell.date)">
|
|
|
- <img :src="addIcon" alt="" style="width: 16px; height: 16px;">
|
|
|
- <span>新增日程</span>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
</template>
|
|
|
|
|
|
|
|
|
@@ -295,7 +298,10 @@ const detailEvent = async (ev: { id: string; title: string }) => {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
-
|
|
|
+.calendar_todo{
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
|
|
|
/* ===== 日历主体 ===== */
|
|
|
/* 统一日历网格:星期表头 + 日期格共用同一 grid 容器,保证列宽/竖线完全对齐 */
|
|
|
@@ -389,7 +395,7 @@ const detailEvent = async (ev: { id: string; title: string }) => {
|
|
|
}
|
|
|
|
|
|
&.is_today {
|
|
|
- .cal_cell_num {
|
|
|
+ .cal_cell_top .cal_cell_num {
|
|
|
color: #2E64FA;
|
|
|
}
|
|
|
}
|