Commit fd870ca4 authored by Administrator's avatar Administrator
Browse files

added multiple feat

UI: add Settings skeleton page with v-tabs + 6 categories
UI: enlarge TaskView event fonts and replace progress bar with SVG ring
UI: add native title tooltip on TaskView events
UI: convert filter panel toggle to floating icon button with slide animation
UI: set browser tab title to "学生管理系统"
parent 1e2ed63c
...@@ -39,4 +39,5 @@ clipboard* ...@@ -39,4 +39,5 @@ clipboard*
*.xlsx *.xlsx
*.yaml *.yaml
暑假日程表.txt 暑假日程表.txt
import-assignments.cjs import-assignments.cjs
\ No newline at end of file to-do-feature.md
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title> <title>学生管理系统</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
......
...@@ -49,5 +49,11 @@ export const GLOBAL_MENU_ITEMS = [ ...@@ -49,5 +49,11 @@ export const GLOBAL_MENU_ITEMS = [
mdiIcon: 'mdi-clipboard-check-multiple-outline', mdiIcon: 'mdi-clipboard-check-multiple-outline',
hasRouter: true hasRouter: true
}, },
{
nameKey: 'navigation.menu.settings',
path: '/settings',
mdiIcon: 'mdi-cog-outline',
hasRouter: true
},
// 可以继续添加更多菜单项 // 可以继续添加更多菜单项
]; ];
...@@ -11,6 +11,7 @@ import task from './modules/task' ...@@ -11,6 +11,7 @@ import task from './modules/task'
import story from './modules/story' import story from './modules/story'
import auth from './modules/auth' import auth from './modules/auth'
import navigation from './modules/navigation' import navigation from './modules/navigation'
import settings from './modules/settings'
import appHeader from './components/app-header' import appHeader from './components/app-header'
// 组合所有翻译 // 组合所有翻译
...@@ -29,6 +30,7 @@ export default { ...@@ -29,6 +30,7 @@ export default {
story, story,
auth, auth,
navigation, navigation,
settings,
components: { components: {
appHeader appHeader
} }
......
...@@ -27,7 +27,8 @@ export default { ...@@ -27,7 +27,8 @@ export default {
terms: 'Terms', terms: 'Terms',
stories: 'Story', stories: 'Story',
tasks: 'Task Management', tasks: 'Task Management',
profile: 'Profile' profile: 'Profile',
settings: 'Settings'
}, },
drawer: { drawer: {
......
export default {
title: 'Settings',
subtitle: 'Manage your preferences and account',
// 分类 tab 标签
categories: {
general: { label: 'General', description: 'Language, region, basic preferences' },
appearance: { label: 'Appearance', description: 'Theme, density, color scheme' },
notifications: { label: 'Notifications', description: 'Reminders, alerts, sound' },
data: { label: 'Data', description: 'Import, export, cache, reset' },
account: { label: 'Account', description: 'Profile, password, devices' },
about: { label: 'About', description: 'Version, licenses, acknowledgements' }
},
// 顶部动作
actions: {
reset: 'Reset to defaults',
save: 'Save changes'
},
// 占位说明(各 tab 卡片复用)
placeholders: {
comingSoon: 'This section is not implemented yet (phase-1 skeleton).'
},
// 各分类的字段(phase-1 仅占位)
fields: {
language: 'Display language',
timezone: 'Time zone',
theme: 'Theme',
density: 'Interface density',
weekStart: 'Week starts on',
reminderLeadTime: 'Default reminder lead time',
exportFormat: 'Default export format',
autoBackup: 'Auto-backup enabled'
},
messages: {
phase1Hint: 'Skeleton only — values are not persisted yet.',
resetConfirm: 'Reset all settings to defaults?'
}
}
\ No newline at end of file
...@@ -14,7 +14,16 @@ export default { ...@@ -14,7 +14,16 @@ export default {
}, },
noEvents: 'No tasks this month', noEvents: 'No tasks this month',
enterFullscreen: 'Enter Fullscreen', enterFullscreen: 'Enter Fullscreen',
exitFullscreen: 'Exit Fullscreen' exitFullscreen: 'Exit Fullscreen',
tooltip: {
progress: 'Progress: {percent}%'
},
buttonText: {
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day'
}
}, },
task: { task: {
name: 'Task Name', name: 'Task Name',
...@@ -57,6 +66,13 @@ export default { ...@@ -57,6 +66,13 @@ export default {
title: 'Edit Task', title: 'Edit Task',
createTitle: 'Create New Task' createTitle: 'Create New Task'
}, },
dialog: {
delete: 'Delete Confirmation'
},
deleteConfirmation: {
message: 'Are you sure you want to delete this task? This action cannot be undone.',
warning: 'This action is irreversible.'
},
messages: { messages: {
loadError: 'Failed to load task data', loadError: 'Failed to load task data',
noData: 'No task data available', noData: 'No task data available',
......
...@@ -11,6 +11,7 @@ import task from './modules/task' ...@@ -11,6 +11,7 @@ import task from './modules/task'
import story from './modules/story' import story from './modules/story'
import auth from './modules/auth' import auth from './modules/auth'
import navigation from './modules/navigation' import navigation from './modules/navigation'
import settings from './modules/settings'
import appHeader from './components/app-header' import appHeader from './components/app-header'
// 组合所有翻译 // 组合所有翻译
...@@ -29,6 +30,7 @@ export default { ...@@ -29,6 +30,7 @@ export default {
story, story,
auth, auth,
navigation, navigation,
settings,
components: { components: {
appHeader appHeader
} }
......
...@@ -27,7 +27,8 @@ export default { ...@@ -27,7 +27,8 @@ export default {
terms: '学期', terms: '学期',
stories: '系列任务', stories: '系列任务',
tasks: '作业管理', tasks: '作业管理',
profile: '个人资料' profile: '个人资料',
settings: '设置'
}, },
drawer: { drawer: {
......
export default {
title: '设置',
subtitle: '管理您的偏好与账户',
// 分类 tab 标签
categories: {
general: { label: '通用', description: '语言、区域、基本偏好' },
appearance: { label: '外观', description: '主题、密度、配色' },
notifications: { label: '通知', description: '提醒、弹窗、声音' },
data: { label: '数据', description: '导入、导出、缓存、重置' },
account: { label: '账户', description: '资料、密码、设备' },
about: { label: '关于', description: '版本、许可、致谢' }
},
// 顶部动作
actions: {
reset: '恢复默认',
save: '保存修改'
},
// 占位说明
placeholders: {
comingSoon: '本分区尚未实现(phase-1 骨架)。'
},
// 各分类的字段
fields: {
language: '显示语言',
timezone: '时区',
theme: '主题',
density: '界面密度',
weekStart: '一周起始日',
reminderLeadTime: '默认提醒提前时间',
exportFormat: '默认导出格式',
autoBackup: '启用自动备份'
},
messages: {
phase1Hint: '当前仅为骨架,暂不会持久化。',
resetConfirm: '确定要把所有设置恢复为默认值吗?'
}
}
\ No newline at end of file
...@@ -14,7 +14,16 @@ export default { ...@@ -14,7 +14,16 @@ export default {
}, },
noEvents: '本月没有作业', noEvents: '本月没有作业',
enterFullscreen: '全屏显示', enterFullscreen: '全屏显示',
exitFullscreen: '退出全屏' exitFullscreen: '退出全屏',
tooltip: {
progress: '进度: {percent}%'
},
buttonText: {
today: '今天',
month: '',
week: '',
day: ''
}
}, },
task: { task: {
name: '作业名称', name: '作业名称',
...@@ -57,6 +66,13 @@ export default { ...@@ -57,6 +66,13 @@ export default {
title: '编辑作业', title: '编辑作业',
createTitle: '新增作业' createTitle: '新增作业'
}, },
dialog: {
delete: '删除确认'
},
deleteConfirmation: {
message: '您确定要删除此作业吗?此操作无法撤销。',
warning: '此操作不可撤销,请谨慎。'
},
messages: { messages: {
loadError: '加载作业数据失败', loadError: '加载作业数据失败',
noData: '暂无作业数据', noData: '暂无作业数据',
......
...@@ -9,6 +9,7 @@ import SubjectView from '../views/SubjectView.vue' ...@@ -9,6 +9,7 @@ import SubjectView from '../views/SubjectView.vue'
import TermView from '../views/TermView.vue' import TermView from '../views/TermView.vue'
import StoryView from '../views/StoryView.vue' import StoryView from '../views/StoryView.vue'
import TaskView from '../views/TaskView.vue' import TaskView from '../views/TaskView.vue'
import SettingsView from '../views/SettingsView.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
...@@ -138,6 +139,23 @@ const router = createRouter({ ...@@ -138,6 +139,23 @@ const router = createRouter({
] ]
}, },
}, },
{
path: '/settings',
name: 'settings',
component: SettingsView,
meta: {
requiresAuth: true,
layout: 'default',
title: 'Settings',
breadcrumb: {
key: 'navigation.breadcrumb.settings'
},
breadcrumbPath: [
{ key: 'navigation.breadcrumb.home', to: '/', disabled: false },
{ key: 'navigation.breadcrumb.settings', to: '/settings', disabled: true }
]
},
},
{ {
path: '/:pathMatch(.*)*', path: '/:pathMatch(.*)*',
redirect: '/', redirect: '/',
......
<script setup>
import { ref } from 'vue'
// 分类配置(phase-1: 数组驱动 tabs; phase-2: 改为 { key, icon, component })
const categories = [
{ key: 'general', icon: 'mdi-tune-variant' },
{ key: 'appearance', icon: 'mdi-palette-outline' },
{ key: 'notifications', icon: 'mdi-bell-outline' },
{ key: 'data', icon: 'mdi-database-outline' },
{ key: 'account', icon: 'mdi-account-cog-outline' },
{ key: 'about', icon: 'mdi-information-outline' }
]
const activeTab = ref('general')
// phase-1 占位状态; phase-2 替换为 usePreferencesStore()
const general = ref({ language: 'zh-CN', timezone: 'Asia/Shanghai' })
const appearance = ref({ theme: 'system', density: 'comfortable' })
const notifications = ref({ weekStart: 1, reminderLeadTime: 15 })
const data = ref({ exportFormat: 'xlsx', autoBackup: true })
</script>
<template>
<v-container fluid>
<!-- 页面标题区(与 HomeView/TaskView 一致) -->
<v-row class="mb-4">
<v-col cols="12">
<h2>{{ $t('settings.title') }}</h2>
<p class="text-body-2 text-medium-emphasis mt-1">
{{ $t('settings.subtitle') }}
</p>
</v-col>
</v-row>
<v-card>
<!-- 分类 tabs -->
<v-tabs v-model="activeTab" show-arrows density="comfortable">
<v-tab v-for="cat in categories" :key="cat.key" :value="cat.key">
<v-icon class="me-2" :icon="cat.icon" />
{{ $t(`settings.categories.${cat.key}.label`) }}
</v-tab>
</v-tabs>
<v-divider />
<!-- 分类内容 -->
<v-window v-model="activeTab">
<v-window-item v-for="cat in categories" :key="cat.key" :value="cat.key">
<v-card flat>
<v-card-title>
{{ $t(`settings.categories.${cat.key}.label`) }}
</v-card-title>
<v-card-subtitle>
{{ $t(`settings.categories.${cat.key}.description`) }}
</v-card-subtitle>
<v-card-text>
<p class="text-body-2 text-medium-emphasis mb-4">
{{ $t('settings.placeholders.comingSoon') }}
</p>
<v-row dense>
<!-- general -->
<template v-if="cat.key === 'general'">
<v-col cols="12" md="6">
<v-select
v-model="general.language"
:items="[
{ title: '中文', value: 'zh-CN' },
{ title: 'English', value: 'en' }
]"
:label="$t('settings.fields.language')"
variant="outlined"
density="comfortable"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="general.timezone"
:label="$t('settings.fields.timezone')"
variant="outlined"
density="comfortable"
/>
</v-col>
</template>
<!-- appearance -->
<template v-else-if="cat.key === 'appearance'">
<v-col cols="12" md="6">
<v-select
v-model="appearance.theme"
:items="['system', 'light', 'dark']"
:label="$t('settings.fields.theme')"
variant="outlined"
density="comfortable"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
v-model="appearance.density"
:items="['comfortable', 'compact', 'default']"
:label="$t('settings.fields.density')"
variant="outlined"
density="comfortable"
/>
</v-col>
</template>
<!-- notifications -->
<template v-else-if="cat.key === 'notifications'">
<v-col cols="12" md="6">
<v-select
v-model="notifications.weekStart"
:items="[0, 1, 6]"
:label="$t('settings.fields.weekStart')"
variant="outlined"
density="comfortable"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model.number="notifications.reminderLeadTime"
type="number"
:label="$t('settings.fields.reminderLeadTime')"
variant="outlined"
density="comfortable"
/>
</v-col>
</template>
<!-- data -->
<template v-else-if="cat.key === 'data'">
<v-col cols="12" md="6">
<v-select
v-model="data.exportFormat"
:items="['xlsx', 'csv', 'json']"
:label="$t('settings.fields.exportFormat')"
variant="outlined"
density="comfortable"
/>
</v-col>
<v-col cols="12" md="6" class="d-flex align-center">
<v-switch
v-model="data.autoBackup"
:label="$t('settings.fields.autoBackup')"
color="primary"
hide-details
/>
</v-col>
</template>
<!-- account: 占位 -->
<template v-else-if="cat.key === 'account'">
<v-col cols="12">
<v-alert type="info" variant="tonal">
{{ $t('settings.placeholders.comingSoon') }}
</v-alert>
</v-col>
</template>
<!-- about -->
<template v-else-if="cat.key === 'about'">
<v-col cols="12">
<v-list>
<v-list-item title="Version" subtitle="0.1.0 (phase-1)" />
<v-list-item title="Vue" subtitle="3.x" />
<v-list-item title="Vuetify" subtitle="3.x" />
</v-list>
</v-col>
</template>
</v-row>
</v-card-text>
</v-card>
</v-window-item>
</v-window>
<!-- 底部共享按钮: 跨所有 tab, 只显示一对 Reset / Save -->
<v-divider />
<v-card-actions>
<v-spacer />
<v-btn variant="text" color="error">
{{ $t('settings.actions.reset') }}
</v-btn>
<v-btn color="primary" variant="elevated">
{{ $t('settings.actions.save') }}
</v-btn>
</v-card-actions>
</v-card>
</v-container>
</template>
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment