mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-04 10:29:23 +00:00
修复
This commit is contained in:
parent
ac417b1432
commit
3c021c1bd8
@ -1,25 +1,26 @@
|
||||
<template>
|
||||
<settings-card
|
||||
title="显示设置"
|
||||
icon="mdi-monitor-dashboard"
|
||||
icon="mdi-monitor"
|
||||
border
|
||||
>
|
||||
<v-form v-model="isValid" @submit.prevent="save">
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-eye" class="mr-3" />
|
||||
<v-icon icon="mdi-card-outline" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>空科目显示</v-list-item-title>
|
||||
<v-list-item-title>空科目显示方式</v-list-item-title>
|
||||
<v-list-item-subtitle>选择空科目的显示方式</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-btn-toggle
|
||||
v-model="localSettings.emptySubjectDisplay"
|
||||
density="comfortable"
|
||||
color="primary"
|
||||
>
|
||||
<v-btn value="button" :ripple="false">按钮</v-btn>
|
||||
<v-btn value="card" :ripple="false">卡片</v-btn>
|
||||
</v-btn-toggle>
|
||||
<v-select
|
||||
v-model="emptySubjectDisplay"
|
||||
:items="displayOptions"
|
||||
density="compact"
|
||||
hide-details
|
||||
variant="outlined"
|
||||
style="max-width: 150px"
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
@ -27,14 +28,13 @@
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-sort" class="mr-3" />
|
||||
<v-icon icon="mdi-sort-variant" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>动态排序</v-list-item-title>
|
||||
<v-list-item-subtitle>根据科目动态排序</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>优化卡片布局以提高显示效果</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
disabled
|
||||
v-model="localSettings.dynamicSort"
|
||||
v-model="dynamicSort"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
@ -47,11 +47,11 @@
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-dice-multiple" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>随机点名按钮</v-list-item-title>
|
||||
<v-list-item-subtitle>指向IslandCaller的链接</v-list-item-subtitle>
|
||||
<v-list-item-title>显示随机按钮</v-list-item-title>
|
||||
<v-list-item-subtitle>在主页显示随机点名按钮</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.showRandomButton"
|
||||
v-model="showRandomButton"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
@ -65,10 +65,44 @@
|
||||
<v-icon icon="mdi-fullscreen" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>显示全屏按钮</v-list-item-title>
|
||||
<v-list-item-subtitle>在主页面显示全屏切换按钮</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>在主页显示全屏切换按钮</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.showFullscreenButton"
|
||||
v-model="showFullscreenButton"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-cards-outline" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>卡片悬浮效果</v-list-item-title>
|
||||
<v-list-item-subtitle>启用卡片悬停时的动画效果</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="cardHoverEffect"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-gesture-tap" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>增强触摸模式</v-list-item-title>
|
||||
<v-list-item-subtitle>优化触摸屏操作体验</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="enhancedTouchMode"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
@ -109,18 +143,78 @@ export default {
|
||||
emptySubjectDisplay: getSetting('display.emptySubjectDisplay'),
|
||||
dynamicSort: getSetting('display.dynamicSort'),
|
||||
showRandomButton: getSetting('display.showRandomButton'),
|
||||
showFullscreenButton: getSetting('display.showFullscreenButton')
|
||||
showFullscreenButton: getSetting('display.showFullscreenButton'),
|
||||
cardHoverEffect: getSetting('display.cardHoverEffect'),
|
||||
enhancedTouchMode: getSetting('display.enhancedTouchMode')
|
||||
};
|
||||
|
||||
return {
|
||||
localSettings: { ...settings },
|
||||
originalSettings: settings,
|
||||
isValid: true
|
||||
isValid: true,
|
||||
displayOptions: [
|
||||
{ title: '卡片', value: 'card' },
|
||||
{ title: '按钮', value: 'button' }
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasChanges() {
|
||||
return JSON.stringify(this.localSettings) !== JSON.stringify(this.originalSettings);
|
||||
},
|
||||
emptySubjectDisplay: {
|
||||
get() {
|
||||
return this.localSettings.emptySubjectDisplay;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.emptySubjectDisplay = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
dynamicSort: {
|
||||
get() {
|
||||
return this.localSettings.dynamicSort;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.dynamicSort = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
showRandomButton: {
|
||||
get() {
|
||||
return this.localSettings.showRandomButton;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.showRandomButton = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
showFullscreenButton: {
|
||||
get() {
|
||||
return this.localSettings.showFullscreenButton;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.showFullscreenButton = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
cardHoverEffect: {
|
||||
get() {
|
||||
return this.localSettings.cardHoverEffect;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.cardHoverEffect = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
enhancedTouchMode: {
|
||||
get() {
|
||||
return this.localSettings.enhancedTouchMode;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.enhancedTouchMode = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -373,6 +373,7 @@ import { useDisplay } from "vuetify";
|
||||
import "../styles/index.scss";
|
||||
import "../styles/transitions.scss"; // 添加新的样式导入
|
||||
import { debounce, throttle } from "@/utils/debounce";
|
||||
import '../styles/global.scss';
|
||||
|
||||
export default {
|
||||
name: "Classworks 作业板",
|
||||
@ -514,7 +515,9 @@ export default {
|
||||
return result;
|
||||
},
|
||||
unusedSubjects() {
|
||||
const usedKeys = Object.keys(this.state.boardData.homework);
|
||||
const usedKeys = Object.keys(this.state.boardData.homework).filter(
|
||||
key => this.state.boardData.homework[key].content?.trim()
|
||||
);
|
||||
return this.state.availableSubjects.filter(
|
||||
(subject) => !usedKeys.includes(subject.key)
|
||||
);
|
||||
@ -784,14 +787,11 @@ export default {
|
||||
|
||||
// 如果内容发生变化(包括清空),就视为修改
|
||||
if (content !== originalContent.trim()) {
|
||||
if (content) {
|
||||
// 使用精简的数据结构
|
||||
this.state.boardData.homework[this.currentEditSubject] = {
|
||||
content,
|
||||
};
|
||||
} else {
|
||||
delete this.state.boardData.homework[this.currentEditSubject];
|
||||
}
|
||||
// 无论内容是否为空,都保留科目结构
|
||||
this.state.boardData.homework[this.currentEditSubject] = {
|
||||
content: content,
|
||||
};
|
||||
|
||||
this.state.synced = false;
|
||||
|
||||
// 处理自动保存
|
||||
@ -1181,8 +1181,8 @@ export default {
|
||||
const rect = card.getBoundingClientRect();
|
||||
const x = ((e.clientX - rect.left) / rect.width) * 100;
|
||||
const y = ((e.clientY - rect.top) / rect.height) * 100;
|
||||
card.style.setProperty("--x", `${x}%`);
|
||||
card.style.setProperty("--y", `${y}%`);
|
||||
card.style.setProperty('--x', `${x}%`);
|
||||
card.style.setProperty('--y', `${y}%`);
|
||||
},
|
||||
|
||||
handleTouchMove(e) {
|
||||
@ -1192,8 +1192,8 @@ export default {
|
||||
const rect = card.getBoundingClientRect();
|
||||
const x = ((touch.clientX - rect.left) / rect.width) * 100;
|
||||
const y = ((touch.clientY - rect.top) / rect.height) * 100;
|
||||
card.style.setProperty("--x", `${x}%`);
|
||||
card.style.setProperty("--y", `${y}%`);
|
||||
card.style.setProperty('--x', `${x}%`);
|
||||
card.style.setProperty('--y', `${y}%`);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1285,8 +1285,56 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.gray-text {
|
||||
opacity: 0.6;
|
||||
<style lang="scss">
|
||||
// 添加卡片发光效果
|
||||
.glow-track {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: radial-gradient(circle at var(--x, 50%) var(--y, 50%),
|
||||
rgba(255, 255, 255, 0.15) 0%,
|
||||
rgba(255, 255, 255, 0) 70%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加卡片悬浮效果
|
||||
.grid-item .v-card {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加空科目卡片样式
|
||||
.empty-subject-card {
|
||||
transition: all 0.3s ease;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
65
src/styles/cards.scss
Normal file
65
src/styles/cards.scss
Normal file
@ -0,0 +1,65 @@
|
||||
// 触摸友好的卡片样式
|
||||
|
||||
.touch-card {
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
.v-card-title {
|
||||
font-size: 1.25rem;
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.v-card-text {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.v-card-actions {
|
||||
padding: 12px 20px;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
// 卡片发光效果
|
||||
.glow-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: radial-gradient(circle at var(--x, 50%) var(--y, 50%),
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0) 60%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 网格布局优化
|
||||
.grid-masonry {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: 20px;
|
||||
grid-gap: 16px;
|
||||
}
|
||||
|
||||
// 空科目网格
|
||||
.empty-subjects-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
grid-gap: 16px;
|
||||
margin-top: 16px;
|
||||
}
|
86
src/styles/global.scss
Normal file
86
src/styles/global.scss
Normal file
@ -0,0 +1,86 @@
|
||||
// 全局 UI 美化样式
|
||||
|
||||
// 卡片悬浮效果
|
||||
.hover-card {
|
||||
transition: transform 0.2s ease, box-shadow 0.3s ease;
|
||||
will-change: transform, box-shadow;
|
||||
|
||||
&:hover, &:focus {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸友好的按钮
|
||||
.touch-button {
|
||||
min-height: 48px;
|
||||
min-width: 48px;
|
||||
border-radius: 12px;
|
||||
padding: 12px 24px;
|
||||
|
||||
&.v-btn--icon {
|
||||
min-height: 56px;
|
||||
min-width: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
// 波纹效果增强
|
||||
.ripple-enhanced {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: radial-gradient(circle at var(--x, 50%) var(--y, 50%),
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0) 60%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:active::after {
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
// 平滑滚动
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
// 触摸友好的列表项
|
||||
.touch-list-item {
|
||||
min-height: 56px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
// 大型触摸目标
|
||||
.large-touch-target {
|
||||
min-height: 56px;
|
||||
min-width: 56px;
|
||||
}
|
||||
|
||||
// 全屏模式样式
|
||||
.fullscreen-mode {
|
||||
.v-app-bar {
|
||||
background-color: rgba(var(--v-theme-surface-variant), 0.85) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.main-window {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
@ -163,3 +163,76 @@ $standard-accelerate: cubic-bezier(0.3, 0.0, 1.0, 1.0);
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
// 动画过渡效果
|
||||
|
||||
// 网格项目过渡
|
||||
.grid-enter-active,
|
||||
.grid-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.grid-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
.grid-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
|
||||
// 列表项目过渡
|
||||
.v-list-enter-active,
|
||||
.v-list-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.v-list-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
|
||||
.v-list-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
// 页面过渡
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
}
|
||||
|
||||
.page-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
|
||||
// 淡入淡出
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// 缩放过渡
|
||||
.scale-enter-active,
|
||||
.scale-leave-active {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.scale-enter-from,
|
||||
.scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
@ -102,6 +102,16 @@ const settingsDefinitions = {
|
||||
default: true,
|
||||
description: "是否显示全屏按钮",
|
||||
},
|
||||
"display.cardHoverEffect": {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
description: "是否启用卡片悬浮效果",
|
||||
},
|
||||
"display.enhancedTouchMode": {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
description: "是否启用增强触摸模式(更大的触摸目标)",
|
||||
},
|
||||
|
||||
// 服务器设置(合并了数据提供者设置)
|
||||
"server.domain": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user