Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c44d763e63 | |||
| 8d4ed8099c | |||
| b02fa37350 |
@@ -79,7 +79,13 @@
|
|||||||
<div class="day-date">{{ day.date }}</div>
|
<div class="day-date">{{ day.date }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-body">
|
<div
|
||||||
|
ref="landscapeBodyRef"
|
||||||
|
class="ml-body"
|
||||||
|
@touchstart="onLandscapeBodyTouchStart"
|
||||||
|
@touchmove.prevent="onLandscapeBodyTouchMove"
|
||||||
|
@wheel="onLandscapeBodyWheel"
|
||||||
|
>
|
||||||
<div v-for="slot in timeSlots" :key="slot.key" class="ml-row">
|
<div v-for="slot in timeSlots" :key="slot.key" class="ml-row">
|
||||||
<div class="ml-label">
|
<div class="ml-label">
|
||||||
<div class="header-label">{{ slot.label }}</div>
|
<div class="header-label">{{ slot.label }}</div>
|
||||||
@@ -114,7 +120,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, PropType } from 'vue';
|
import { computed, defineComponent, PropType, ref } from 'vue';
|
||||||
import { NormalizedClazzEvent } from '../useClazzViewModel';
|
import { NormalizedClazzEvent } from '../useClazzViewModel';
|
||||||
import { DateFormatter, formatDate, hexToRgb } from '~/utils';
|
import { DateFormatter, formatDate, hexToRgb } from '~/utils';
|
||||||
|
|
||||||
@@ -172,6 +178,8 @@ export default defineComponent({
|
|||||||
emits: ['cell-click', 'event-click'],
|
emits: ['cell-click', 'event-click'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const today = computed(() => new Date());
|
const today = computed(() => new Date());
|
||||||
|
const landscapeBodyRef = ref<HTMLElement | null>(null);
|
||||||
|
const landscapeTouchLastY = ref<number | null>(null);
|
||||||
|
|
||||||
const weekDays = computed<WeekDay[]>(() => {
|
const weekDays = computed<WeekDay[]>(() => {
|
||||||
const days: WeekDay[] = [];
|
const days: WeekDay[] = [];
|
||||||
@@ -253,7 +261,30 @@ export default defineComponent({
|
|||||||
emit('event-click', ev);
|
emit('event-click', ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onLandscapeBodyTouchStart(e: TouchEvent) {
|
||||||
|
if (!props.landscape) return;
|
||||||
|
landscapeTouchLastY.value = e.touches[0]?.clientY ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLandscapeBodyTouchMove(e: TouchEvent) {
|
||||||
|
if (!props.landscape) return;
|
||||||
|
const currentY = e.touches[0]?.clientY;
|
||||||
|
const previousY = landscapeTouchLastY.value;
|
||||||
|
const body = landscapeBodyRef.value;
|
||||||
|
if (currentY == null || previousY == null || !body) return;
|
||||||
|
body.scrollTop += currentY - previousY;
|
||||||
|
landscapeTouchLastY.value = currentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLandscapeBodyWheel(e: WheelEvent) {
|
||||||
|
if (!props.landscape) return;
|
||||||
|
const body = landscapeBodyRef.value;
|
||||||
|
if (!body) return;
|
||||||
|
body.scrollTop += e.deltaY;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
landscapeBodyRef,
|
||||||
timeSlots,
|
timeSlots,
|
||||||
weekDays,
|
weekDays,
|
||||||
eventMap,
|
eventMap,
|
||||||
@@ -262,6 +293,9 @@ export default defineComponent({
|
|||||||
eventStyle,
|
eventStyle,
|
||||||
onCellClick,
|
onCellClick,
|
||||||
onEventClick,
|
onEventClick,
|
||||||
|
onLandscapeBodyTouchStart,
|
||||||
|
onLandscapeBodyTouchMove,
|
||||||
|
onLandscapeBodyWheel,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -270,6 +304,8 @@ export default defineComponent({
|
|||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@sidebar-width: 1.2rem;
|
@sidebar-width: 1.2rem;
|
||||||
@cell-width: 1.8rem;
|
@cell-width: 1.8rem;
|
||||||
|
@portrait-header-height: 0.72rem;
|
||||||
|
@portrait-day-row-min-height: 1.16rem;
|
||||||
|
|
||||||
.matrix-wrapper {
|
.matrix-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -300,9 +336,12 @@ export default defineComponent({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
pointer-events: none; /* allow click-through to cells underneath */
|
pointer-events: none; /* allow click-through to cells underneath */
|
||||||
|
|
||||||
.sidebar-corner {
|
.sidebar-corner {
|
||||||
|
height: @portrait-header-height;
|
||||||
|
box-sizing: border-box;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background: #f7f8fa;
|
background: #f7f8fa;
|
||||||
border-bottom: 1px solid #e8e8e8;
|
border-bottom: 1px solid #e8e8e8;
|
||||||
@@ -312,7 +351,8 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-row {
|
.sidebar-row {
|
||||||
flex: 1;
|
flex: 1 0 @portrait-day-row-min-height;
|
||||||
|
min-height: @portrait-day-row-min-height;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -353,18 +393,20 @@ export default defineComponent({
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
min-width: fit-content;
|
min-width: fit-content;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── 行:共用 ─── */
|
/* ─── 行:共用 ─── */
|
||||||
.sr-header {
|
.sr-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: @portrait-header-height;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sr-row {
|
.sr-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1 0 @portrait-day-row-min-height;
|
||||||
min-height: 0;
|
min-height: @portrait-day-row-min-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── Spacer(占位与 sidebar 同宽) ─── */
|
/* ─── Spacer(占位与 sidebar 同宽) ─── */
|
||||||
@@ -484,6 +526,8 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ml-header {
|
.ml-header {
|
||||||
@@ -491,6 +535,9 @@ export default defineComponent({
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background: #f7f8fa;
|
background: #f7f8fa;
|
||||||
border-bottom: 1px solid #e8e8e8;
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ml-corner {
|
.ml-corner {
|
||||||
@@ -521,8 +568,12 @@ export default defineComponent({
|
|||||||
|
|
||||||
.ml-body {
|
.ml-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
touch-action: none;
|
||||||
padding-bottom: 0.08rem;
|
padding-bottom: 0.08rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1265,7 +1265,15 @@ export default defineComponent({
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.matrix-sidebar) {
|
||||||
|
padding-bottom: calc(0.72rem + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.matrix-scroll) {
|
:deep(.matrix-scroll) {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.scroll-inner) {
|
||||||
padding-bottom: calc(0.72rem + env(safe-area-inset-bottom));
|
padding-bottom: calc(0.72rem + env(safe-area-inset-bottom));
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
@@ -1473,7 +1481,7 @@ export default defineComponent({
|
|||||||
.landscape-stage-viewport--matrix {
|
.landscape-stage-viewport--matrix {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: auto;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landscape-stage {
|
.landscape-stage {
|
||||||
|
|||||||
Reference in New Issue
Block a user