KidsMode: 取消 controlsVisible 自动隐藏底部导航

Made-with: Cursor
This commit is contained in:
zhonghua 2026-03-17 17:25:43 +08:00
parent 95b3e973e0
commit 971f78e630
3 changed files with 34 additions and 39 deletions

View File

@ -7,11 +7,16 @@ export {}
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
AAlert: typeof import('ant-design-vue/es')['Alert']
AAvatar: typeof import('ant-design-vue/es')['Avatar'] AAvatar: typeof import('ant-design-vue/es')['Avatar']
ABadge: typeof import('ant-design-vue/es')['Badge'] ABadge: typeof import('ant-design-vue/es')['Badge']
AButton: typeof import('ant-design-vue/es')['Button'] AButton: typeof import('ant-design-vue/es')['Button']
AButtonGroup: typeof import('ant-design-vue/es')['ButtonGroup']
ACard: typeof import('ant-design-vue/es')['Card'] ACard: typeof import('ant-design-vue/es')['Card']
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
ACol: typeof import('ant-design-vue/es')['Col'] ACol: typeof import('ant-design-vue/es')['Col']
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
ADescriptions: typeof import('ant-design-vue/es')['Descriptions'] ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem'] ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem']
ADivider: typeof import('ant-design-vue/es')['Divider'] ADivider: typeof import('ant-design-vue/es')['Divider']
@ -21,6 +26,7 @@ declare module 'vue' {
AForm: typeof import('ant-design-vue/es')['Form'] AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem'] AFormItem: typeof import('ant-design-vue/es')['FormItem']
AImage: typeof import('ant-design-vue/es')['Image'] AImage: typeof import('ant-design-vue/es')['Image']
AImagePreviewGroup: typeof import('ant-design-vue/es')['ImagePreviewGroup']
AInput: typeof import('ant-design-vue/es')['Input'] AInput: typeof import('ant-design-vue/es')['Input']
AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
@ -29,23 +35,43 @@ declare module 'vue' {
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent'] ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader'] ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider'] ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
AList: typeof import('ant-design-vue/es')['List']
AListItem: typeof import('ant-design-vue/es')['ListItem']
AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta']
AMenu: typeof import('ant-design-vue/es')['Menu'] AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider'] AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
AModal: typeof import('ant-design-vue/es')['Modal'] AModal: typeof import('ant-design-vue/es')['Modal']
APageHeader: typeof import('ant-design-vue/es')['PageHeader'] APageHeader: typeof import('ant-design-vue/es')['PageHeader']
APagination: typeof import('ant-design-vue/es')['Pagination']
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
AProgress: typeof import('ant-design-vue/es')['Progress']
ARadio: typeof import('ant-design-vue/es')['Radio']
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
ARangePicker: typeof import('ant-design-vue/es')['RangePicker'] ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
ARate: typeof import('ant-design-vue/es')['Rate']
ARow: typeof import('ant-design-vue/es')['Row'] ARow: typeof import('ant-design-vue/es')['Row']
ASelect: typeof import('ant-design-vue/es')['Select'] ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOptGroup: typeof import('ant-design-vue/es')['SelectOptGroup']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASkeleton: typeof import('ant-design-vue/es')['Skeleton'] ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
ASpace: typeof import('ant-design-vue/es')['Space'] ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin']
AStatistic: typeof import('ant-design-vue/es')['Statistic'] AStatistic: typeof import('ant-design-vue/es')['Statistic']
AStep: typeof import('ant-design-vue/es')['Step']
ASteps: typeof import('ant-design-vue/es')['Steps']
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
ASwitch: typeof import('ant-design-vue/es')['Switch']
ATable: typeof import('ant-design-vue/es')['Table'] ATable: typeof import('ant-design-vue/es')['Table']
ATabPane: typeof import('ant-design-vue/es')['TabPane']
ATabs: typeof import('ant-design-vue/es')['Tabs']
ATag: typeof import('ant-design-vue/es')['Tag'] ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATimeRangePicker: typeof import('ant-design-vue/es')['TimeRangePicker']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
ATypographyText: typeof import('ant-design-vue/es')['TypographyText']
AUpload: typeof import('ant-design-vue/es')['Upload'] AUpload: typeof import('ant-design-vue/es')['Upload']
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
FilePreviewModal: typeof import('./components/FilePreviewModal.vue')['default'] FilePreviewModal: typeof import('./components/FilePreviewModal.vue')['default']
FileUploader: typeof import('./components/course/FileUploader.vue')['default'] FileUploader: typeof import('./components/course/FileUploader.vue')['default']
LessonConfigPanel: typeof import('./components/course/LessonConfigPanel.vue')['default'] LessonConfigPanel: typeof import('./components/course/LessonConfigPanel.vue')['default']

View File

@ -1,5 +1,6 @@
<template> <template>
<div v-if="!expire" ref="containerRef" class="!w-full !h-full z-999" :class="noPage ? 'absolute top-0 left-0' : 'pos-fixed top-0 left-0'"></div> <div v-if="!expire" ref="containerRef" class="!w-full !h-full z-999"
:class="noPage ? 'absolute top-0 left-0' : 'pos-fixed top-0 left-0'"></div>
<div v-else class="flex justify-center items-center w-full h-full"> <div v-else class="flex justify-center items-center w-full h-full">
<div class="my-60px text-center"> <div class="my-60px text-center">
链接已失效! 链接已失效!
@ -116,7 +117,7 @@ onUnmounted(() => {
window.addEventListener('beforeunload', updateSize); window.addEventListener('beforeunload', updateSize);
function home() { function home() {
router.replace("/datas"); router.replace("/");
} }
const baseInstance = ref<any>(null); const baseInstance = ref<any>(null);
async function init(mount: HTMLElement | null) { async function init(mount: HTMLElement | null) {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="kids-mode" @click="showControls" @mousemove="showControls"> <div class="kids-mode">
<!-- 静音开关 --> <!-- 静音开关 -->
<button class="mute-toggle" @click.stop="toggleMute" :class="{ muted: isMuted }"> <button v-if="false" class="mute-toggle" @click.stop="toggleMute" :class="{ muted: isMuted }">
<VolumeX v-if="isMuted" :size="24" :stroke-width="2.5" class="mute-icon" /> <VolumeX v-if="isMuted" :size="24" :stroke-width="2.5" class="mute-icon" />
<Volume2 v-else :size="24" :stroke-width="2.5" class="mute-icon" /> <Volume2 v-else :size="24" :stroke-width="2.5" class="mute-icon" />
</button> </button>
@ -17,14 +17,8 @@
<!-- 视频播放 --> <!-- 视频播放 -->
<div v-else-if="currentResourceType === 'video'" key="video" class="content-viewer"> <div v-else-if="currentResourceType === 'video'" key="video" class="content-viewer">
<Player <Player v-if="currentResourceUrl" :key="currentResourceUrl" :url="currentResourceUrl"
v-if="currentResourceUrl" :title="currentResourceName" :no-page="true" @ended="handleMediaEnded" />
:key="currentResourceUrl"
:url="currentResourceUrl"
:title="currentResourceName"
:no-page="true"
@ended="handleMediaEnded"
/>
</div> </div>
<!-- 图片展示 --> <!-- 图片展示 -->
@ -87,7 +81,7 @@
</div> </div>
<!-- 底部固定导航 --> <!-- 底部固定导航 -->
<div class="kids-nav" :class="{ hidden: !controlsVisible }"> <div class="kids-nav">
<!-- 教学资源区域 --> <!-- 教学资源区域 -->
<div class="resources-section"> <div class="resources-section">
<div class="section-label"> <div class="section-label">
@ -230,10 +224,6 @@ const emit = defineEmits<{
(e: 'stepChange', index: number): void; (e: 'stepChange', index: number): void;
}>(); }>();
//
const controlsVisible = ref(true);
let hideControlsTimer: number | null = null;
// //
const currentResourceType = ref<string>(''); const currentResourceType = ref<string>('');
const currentResourceUrl = ref<string>(''); const currentResourceUrl = ref<string>('');
@ -794,18 +784,6 @@ const getResourceById = (resId: string) => {
return null; return null;
}; };
const showControls = () => {
controlsVisible.value = true;
resetHideTimer();
};
const resetHideTimer = () => {
if (hideControlsTimer) clearTimeout(hideControlsTimer);
hideControlsTimer = setTimeout(() => {
controlsVisible.value = false;
}, 5000) as unknown as number;
};
const handleExit = () => { const handleExit = () => {
playSound('click'); playSound('click');
emit('exit'); emit('exit');
@ -864,7 +842,6 @@ const handleResourceClick = (resource: { id: string; type: string; name: string;
showingResource.value = null; showingResource.value = null;
} else { } else {
showingResource.value = resource; showingResource.value = resource;
showControls();
} }
}; };
@ -954,7 +931,6 @@ const toggleMute = () => {
// //
const handleKeydown = (e: KeyboardEvent) => { const handleKeydown = (e: KeyboardEvent) => {
showControls();
if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') prevStep(); if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') prevStep();
else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') nextStep(); else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') nextStep();
else if (e.key === 'Escape') handleExit(); else if (e.key === 'Escape') handleExit();
@ -999,12 +975,10 @@ watch(() => props.currentStepIndex, () => {
onMounted(() => { onMounted(() => {
document.addEventListener('keydown', handleKeydown); document.addEventListener('keydown', handleKeydown);
resetHideTimer();
}); });
onUnmounted(() => { onUnmounted(() => {
document.removeEventListener('keydown', handleKeydown); document.removeEventListener('keydown', handleKeydown);
if (hideControlsTimer) clearTimeout(hideControlsTimer);
}); });
</script> </script>
@ -1262,13 +1236,7 @@ onUnmounted(() => {
backdrop-filter: blur(20px); backdrop-filter: blur(20px);
border-top: 3px solid #FF9800; border-top: 3px solid #FF9800;
padding: 16px 24px 24px; padding: 16px 24px 24px;
transform: translateY(0);
transition: transform 0.3s ease;
box-shadow: 0 -4px 20px rgba(255, 152, 0, 0.15); box-shadow: 0 -4px 20px rgba(255, 152, 0, 0.15);
&.hidden {
transform: translateY(100%);
}
} }
.steps-section { .steps-section {