mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-07 12:39:22 +00:00
Add vuedraggable dependency for improved drag-and-drop functionality. Refactor index.vue to use subject names as keys and streamline subject management. Update settings.vue to include SubjectManagementCard for better subject configuration.
This commit is contained in:
parent
f2d88437e6
commit
f5dab48276
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- '@parcel/watcher'
|
||||||
|
- esbuild
|
||||||
|
- sharp
|
297
src/components/settings/cards/SubjectManagementCard.vue
Normal file
297
src/components/settings/cards/SubjectManagementCard.vue
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<settings-card
|
||||||
|
title="科目管理"
|
||||||
|
icon="mdi-book-multiple"
|
||||||
|
:loading="loading"
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<v-alert
|
||||||
|
v-if="error"
|
||||||
|
type="error"
|
||||||
|
variant="tonal"
|
||||||
|
closable
|
||||||
|
class="mb-4"
|
||||||
|
>
|
||||||
|
{{ error }}
|
||||||
|
</v-alert>
|
||||||
|
|
||||||
|
<div class="d-flex justify-space-between align-center mb-6">
|
||||||
|
<div>
|
||||||
|
<v-btn
|
||||||
|
variant="text"
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
prepend-icon="mdi-refresh"
|
||||||
|
:loading="loading"
|
||||||
|
@click="loadConfig"
|
||||||
|
class="mr-2"
|
||||||
|
>
|
||||||
|
重新加载
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
color="success"
|
||||||
|
size="large"
|
||||||
|
prepend-icon="mdi-content-save"
|
||||||
|
:loading="loading"
|
||||||
|
@click="saveConfig"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
variant="text"
|
||||||
|
prepend-icon="mdi-restore"
|
||||||
|
:loading="loading"
|
||||||
|
@click="resetToDefault"
|
||||||
|
class="mr-2"
|
||||||
|
>
|
||||||
|
重置为默认
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
<v-chip
|
||||||
|
v-if="hasChanges"
|
||||||
|
color="warning"
|
||||||
|
variant="elevated"
|
||||||
|
>
|
||||||
|
有未保存的更改
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 添加新科目 -->
|
||||||
|
<v-card class="mb-4" variant="outlined">
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newSubjectName"
|
||||||
|
label="科目名称"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:rules="[v => !!v || '科目名称不能为空']"
|
||||||
|
@keyup.enter="addSubject"
|
||||||
|
append-inner-icon="mdi-plus"
|
||||||
|
@click:append-inner="addSubject"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<!-- 科目列表 -->
|
||||||
|
<v-card variant="outlined">
|
||||||
|
<v-card-text class="pa-0">
|
||||||
|
<v-list lines="one">
|
||||||
|
<v-list-item
|
||||||
|
v-for="(subject, index) in subjects"
|
||||||
|
:key="subject.order"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="d-flex flex-column align-center mr-2">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-chevron-up"
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
:disabled="index === 0"
|
||||||
|
@click="moveSubject(index, -1)"
|
||||||
|
/>
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-chevron-down"
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
:disabled="index === subjects.length - 1"
|
||||||
|
@click="moveSubject(index, 1)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<v-list-item-title>
|
||||||
|
<v-text-field
|
||||||
|
v-model="subject.name"
|
||||||
|
variant="plain"
|
||||||
|
density="compact"
|
||||||
|
hide-details
|
||||||
|
@blur="updateSubject(subject)"
|
||||||
|
/>
|
||||||
|
</v-list-item-title>
|
||||||
|
|
||||||
|
<template v-slot:append>
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-delete"
|
||||||
|
variant="text"
|
||||||
|
color="error"
|
||||||
|
size="small"
|
||||||
|
@click="deleteSubject(subject)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<!-- 底部提示 -->
|
||||||
|
<v-snackbar
|
||||||
|
v-model="showSnackbar"
|
||||||
|
:color="snackbarColor"
|
||||||
|
:timeout="3000"
|
||||||
|
>
|
||||||
|
{{ snackbarText }}
|
||||||
|
</v-snackbar>
|
||||||
|
</settings-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SettingsCard from '@/components/SettingsCard.vue';
|
||||||
|
import dataProvider from "@/utils/dataProvider.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SubjectManagementCard',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
SettingsCard
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
subjects: [],
|
||||||
|
originalSubjects: null,
|
||||||
|
newSubjectName: '',
|
||||||
|
showSnackbar: false,
|
||||||
|
snackbarText: '',
|
||||||
|
snackbarColor: 'success',
|
||||||
|
defaultSubjects: [
|
||||||
|
{ name: '语文', order: 0 },
|
||||||
|
{ name: '数学', order: 1 },
|
||||||
|
{ name: '英语', order: 2 },
|
||||||
|
{ name: '物理', order: 3 },
|
||||||
|
{ name: '化学', order: 4 },
|
||||||
|
{ name: '生物', order: 5 },
|
||||||
|
{ name: '政治', order: 6 },
|
||||||
|
{ name: '历史', order: 7 },
|
||||||
|
{ name: '地理', order: 8 },
|
||||||
|
{ name: '其他', order: 9 }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasChanges() {
|
||||||
|
return this.originalSubjects &&
|
||||||
|
JSON.stringify(this.subjects) !== JSON.stringify(this.originalSubjects);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.loadConfig();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async loadConfig() {
|
||||||
|
this.loading = true;
|
||||||
|
try {
|
||||||
|
const response = await dataProvider.loadData("classworks-config-subject");
|
||||||
|
if (response) {
|
||||||
|
// 数据存在且加载成功
|
||||||
|
this.subjects = response.map((subject, index) => ({
|
||||||
|
name: subject.name,
|
||||||
|
order: subject.order ?? index
|
||||||
|
})).sort((a, b) => a.order - b.order);
|
||||||
|
this.originalSubjects = JSON.parse(JSON.stringify(this.subjects));
|
||||||
|
this.showMessage('配置已加载', 'success');
|
||||||
|
} else {
|
||||||
|
// 数据不存在,使用空数组
|
||||||
|
this.subjects = [];
|
||||||
|
this.originalSubjects = [];
|
||||||
|
this.showMessage('使用默认配置', 'info');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load config:', error);
|
||||||
|
this.showMessage('加载失败,可继续编辑当前配置', 'warning');
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
async saveConfig() {
|
||||||
|
this.loading = true;
|
||||||
|
try {
|
||||||
|
const response = await dataProvider.saveData("classworks-config-subject", this.subjects);
|
||||||
|
if (response) {
|
||||||
|
this.originalSubjects = JSON.parse(JSON.stringify(this.subjects));
|
||||||
|
this.showMessage('配置已保存', 'success');
|
||||||
|
} else {
|
||||||
|
throw new Error(response || '保存失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save config:', error);
|
||||||
|
this.showMessage(`保存失败: ${error.message},请稍后重试`, 'error');
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
showMessage(text, color = 'success') {
|
||||||
|
this.snackbarText = text;
|
||||||
|
this.snackbarColor = color;
|
||||||
|
this.showSnackbar = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
addSubject() {
|
||||||
|
if (!this.newSubjectName) return;
|
||||||
|
|
||||||
|
const subject = {
|
||||||
|
name: this.newSubjectName,
|
||||||
|
order: this.subjects.length
|
||||||
|
};
|
||||||
|
|
||||||
|
this.subjects.push(subject);
|
||||||
|
this.newSubjectName = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSubject(subject) {
|
||||||
|
const index = this.subjects.findIndex(s => s.order === subject.order);
|
||||||
|
if (index > -1) {
|
||||||
|
this.subjects[index] = { ...subject };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteSubject(subject) {
|
||||||
|
const index = this.subjects.findIndex(s => s.order === subject.order);
|
||||||
|
if (index > -1) {
|
||||||
|
this.subjects.splice(index, 1);
|
||||||
|
// 更新剩余科目的顺序
|
||||||
|
this.subjects.forEach((s, i) => {
|
||||||
|
s.order = i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
moveSubject(index, direction) {
|
||||||
|
const newIndex = index + direction;
|
||||||
|
if (newIndex >= 0 && newIndex < this.subjects.length) {
|
||||||
|
// 交换位置
|
||||||
|
const temp = this.subjects[index];
|
||||||
|
this.subjects[index] = this.subjects[newIndex];
|
||||||
|
this.subjects[newIndex] = temp;
|
||||||
|
// 更新顺序
|
||||||
|
this.subjects.forEach((subject, i) => {
|
||||||
|
subject.order = i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resetToDefault() {
|
||||||
|
this.subjects = JSON.parse(JSON.stringify(this.defaultSubjects));
|
||||||
|
this.showMessage('已重置为默认科目列表', 'info');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.v-list-item {
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
.v-list-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -62,9 +62,9 @@
|
|||||||
<v-btn-group divided variant="outlined">
|
<v-btn-group divided variant="outlined">
|
||||||
<v-btn
|
<v-btn
|
||||||
v-for="subject in unusedSubjects"
|
v-for="subject in unusedSubjects"
|
||||||
:key="subject.key"
|
:key="subject.name"
|
||||||
:disabled="isEditingDisabled"
|
:disabled="isEditingDisabled"
|
||||||
@click="openDialog(subject.key)"
|
@click="openDialog(subject.name)"
|
||||||
>
|
>
|
||||||
<v-icon start> mdi-plus </v-icon>
|
<v-icon start> mdi-plus </v-icon>
|
||||||
{{ subject.name }}
|
{{ subject.name }}
|
||||||
@ -75,11 +75,11 @@
|
|||||||
<TransitionGroup name="v-list">
|
<TransitionGroup name="v-list">
|
||||||
<v-card
|
<v-card
|
||||||
v-for="subject in unusedSubjects"
|
v-for="subject in unusedSubjects"
|
||||||
:key="subject.key"
|
:key="subject.name"
|
||||||
border
|
border
|
||||||
class="empty-subject-card"
|
class="empty-subject-card"
|
||||||
:disabled="isEditingDisabled"
|
:disabled="isEditingDisabled"
|
||||||
@click="openDialog(subject.key)"
|
@click="openDialog(subject.name)"
|
||||||
>
|
>
|
||||||
<v-card-title class="text-subtitle-1">
|
<v-card-title class="text-subtitle-1">
|
||||||
{{ subject.name }}
|
{{ subject.name }}
|
||||||
@ -635,6 +635,19 @@ export default {
|
|||||||
HomeworkEditDialog,
|
HomeworkEditDialog,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
const defaultSubjects = [
|
||||||
|
{ name: "语文", order: 0 },
|
||||||
|
{ name: "数学", order: 1 },
|
||||||
|
{ name: "英语", order: 2 },
|
||||||
|
{ name: "物理", order: 3 },
|
||||||
|
{ name: "化学", order: 4 },
|
||||||
|
{ name: "生物", order: 5 },
|
||||||
|
{ name: "政治", order: 6 },
|
||||||
|
{ name: "历史", order: 7 },
|
||||||
|
{ name: "地理", order: 8 },
|
||||||
|
{ name: "其他", order: 9 }
|
||||||
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dataKey: "",
|
dataKey: "",
|
||||||
provider: "",
|
provider: "",
|
||||||
@ -666,34 +679,11 @@ export default {
|
|||||||
selectedDate: new Date().toISOString().split("T")[0].replace(/-/g, ''),
|
selectedDate: new Date().toISOString().split("T")[0].replace(/-/g, ''),
|
||||||
selectedDateObj: new Date(),
|
selectedDateObj: new Date(),
|
||||||
refreshInterval: null,
|
refreshInterval: null,
|
||||||
subjectOrder: [
|
|
||||||
"语文",
|
|
||||||
"数学",
|
|
||||||
"英语",
|
|
||||||
"物理",
|
|
||||||
"化学",
|
|
||||||
"生物",
|
|
||||||
"政治",
|
|
||||||
"历史",
|
|
||||||
"地理",
|
|
||||||
"其他",
|
|
||||||
],
|
|
||||||
showNoDataMessage: false,
|
showNoDataMessage: false,
|
||||||
noDataMessage: "",
|
noDataMessage: "",
|
||||||
isToday: false,
|
isToday: false,
|
||||||
attendanceDialog: false,
|
attendanceDialog: false,
|
||||||
availableSubjects: [
|
availableSubjects: defaultSubjects,
|
||||||
{ key: "语文", name: "语文" },
|
|
||||||
{ key: "数学", name: "数学" },
|
|
||||||
{ key: "英语", name: "英语" },
|
|
||||||
{ key: "物理", name: "物理" },
|
|
||||||
{ key: "化学", name: "化学" },
|
|
||||||
{ key: "生物", name: "生物" },
|
|
||||||
{ key: "政治", name: "政治" },
|
|
||||||
{ key: "历史", name: "历史" },
|
|
||||||
{ key: "地理", name: "地理" },
|
|
||||||
{ key: "其他", name: "其他" },
|
|
||||||
],
|
|
||||||
isFullscreen: false,
|
isFullscreen: false,
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
@ -750,7 +740,7 @@ export default {
|
|||||||
sortedItems() {
|
sortedItems() {
|
||||||
const key = `${JSON.stringify(
|
const key = `${JSON.stringify(
|
||||||
this.state.boardData.homework
|
this.state.boardData.homework
|
||||||
)}_${this.state.subjectOrder.join()}_${this.dynamicSort}`;
|
)}_${this.subjectOrder.join()}_${this.dynamicSort}`;
|
||||||
if (this.sortedItemsCache.key === key) {
|
if (this.sortedItemsCache.key === key) {
|
||||||
return this.sortedItemsCache.value;
|
return this.sortedItemsCache.value;
|
||||||
}
|
}
|
||||||
@ -760,10 +750,10 @@ export default {
|
|||||||
.map(([key, value]) => ({
|
.map(([key, value]) => ({
|
||||||
key,
|
key,
|
||||||
name:
|
name:
|
||||||
this.state.availableSubjects.find((s) => s.key === key)?.name ||
|
this.state.availableSubjects.find((s) => s.name === key)?.name ||
|
||||||
key,
|
key,
|
||||||
content: value.content,
|
content: value.content,
|
||||||
order: this.state.subjectOrder.indexOf(key),
|
order: this.subjectOrder.indexOf(key),
|
||||||
rowSpan: Math.ceil(
|
rowSpan: Math.ceil(
|
||||||
(value.content.split("\n").filter((line) => line.trim()).length +
|
(value.content.split("\n").filter((line) => line.trim()).length +
|
||||||
1) *
|
1) *
|
||||||
@ -783,9 +773,9 @@ export default {
|
|||||||
const usedKeys = Object.keys(this.state.boardData.homework).filter(
|
const usedKeys = Object.keys(this.state.boardData.homework).filter(
|
||||||
(key) => this.state.boardData.homework[key].content?.trim()
|
(key) => this.state.boardData.homework[key].content?.trim()
|
||||||
);
|
);
|
||||||
return this.state.availableSubjects.filter(
|
return this.state.availableSubjects
|
||||||
(subject) => !usedKeys.includes(subject.key)
|
.filter(subject => !usedKeys.includes(subject.name))
|
||||||
);
|
.sort((a, b) => a.order - b.order);
|
||||||
},
|
},
|
||||||
emptySubjects() {
|
emptySubjects() {
|
||||||
if (this.emptySubjectDisplay !== "button") return [];
|
if (this.emptySubjectDisplay !== "button") return [];
|
||||||
@ -911,6 +901,11 @@ export default {
|
|||||||
return pinyinA.localeCompare(pinyinB);
|
return pinyinA.localeCompare(pinyinB);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
subjectOrder() {
|
||||||
|
return [...this.state.availableSubjects]
|
||||||
|
.sort((a, b) => a.order - b.order)
|
||||||
|
.map(subject => subject.name);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -1183,6 +1178,7 @@ export default {
|
|||||||
|
|
||||||
async loadConfig() {
|
async loadConfig() {
|
||||||
try {
|
try {
|
||||||
|
// 加载学生列表
|
||||||
try {
|
try {
|
||||||
const response = await dataProvider.loadData("classworks-list-main");
|
const response = await dataProvider.loadData("classworks-list-main");
|
||||||
|
|
||||||
@ -1190,7 +1186,6 @@ export default {
|
|||||||
this.state.studentList = response.map(
|
this.state.studentList = response.map(
|
||||||
(student) => student.name
|
(student) => student.name
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn(
|
||||||
@ -1198,6 +1193,18 @@ export default {
|
|||||||
error
|
error
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载科目配置
|
||||||
|
try {
|
||||||
|
const subjectsResponse = await dataProvider.loadData("classworks-config-subject");
|
||||||
|
if (subjectsResponse && Array.isArray(subjectsResponse)) {
|
||||||
|
// 更新科目列表
|
||||||
|
this.state.availableSubjects = subjectsResponse;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to load subject configuration:", error);
|
||||||
|
// 保持默认科目列表
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("加载配置失败:", error);
|
console.error("加载配置失败:", error);
|
||||||
this.$message.error("加载配置失败", error.message);
|
this.$message.error("加载配置失败", error.message);
|
||||||
@ -1225,7 +1232,7 @@ export default {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.state.dialogTitle =
|
this.state.dialogTitle =
|
||||||
this.state.availableSubjects.find((s) => s.key === subject)?.name ||
|
this.state.availableSubjects.find((s) => s.name === subject)?.name ||
|
||||||
subject;
|
subject;
|
||||||
this.state.textarea = this.state.boardData.homework[subject].content;
|
this.state.textarea = this.state.boardData.homework[subject].content;
|
||||||
this.state.dialogVisible = true;
|
this.state.dialogVisible = true;
|
||||||
@ -1404,44 +1411,6 @@ export default {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
fixedGridLayout(items) {
|
|
||||||
const rowSubjects = [
|
|
||||||
["语文", "数学", "英语"],
|
|
||||||
["物理", "化学", "生物"],
|
|
||||||
["政治", "历史", "地理", "其他"],
|
|
||||||
];
|
|
||||||
return items
|
|
||||||
.sort((a, b) => {
|
|
||||||
const getRowIndex = (subject) => {
|
|
||||||
for (let i = 0; i < rowSubjects.length; i++) {
|
|
||||||
if (rowSubjects[i].includes(subject)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rowSubjects.length;
|
|
||||||
};
|
|
||||||
const getColumnIndex = (subject) => {
|
|
||||||
for (const row of rowSubjects) {
|
|
||||||
const index = row.indexOf(subject);
|
|
||||||
if (index !== -1) return index;
|
|
||||||
}
|
|
||||||
return 999;
|
|
||||||
};
|
|
||||||
const rowA = getRowIndex(a.key);
|
|
||||||
const rowB = getRowIndex(b.key);
|
|
||||||
if (rowA !== rowB) {
|
|
||||||
return rowA - rowB;
|
|
||||||
}
|
|
||||||
const colA = getColumnIndex(a.key);
|
|
||||||
const colB = getColumnIndex(b.key);
|
|
||||||
return colA - colB;
|
|
||||||
})
|
|
||||||
.map((item, index) => ({
|
|
||||||
...item,
|
|
||||||
order: index,
|
|
||||||
rowSpan: item.content ? 2 : 1,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
setAllPresent() {
|
setAllPresent() {
|
||||||
this.state.boardData.attendance = {
|
this.state.boardData.attendance = {
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
<div class="settings-page">
|
<div class="settings-page">
|
||||||
<v-app-bar elevation="1">
|
<v-app-bar elevation="1">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
icon="mdi-arrow-left"
|
icon="mdi-arrow-left"
|
||||||
variant="text"
|
variant="text"
|
||||||
@click="$router.push('/')"
|
@click="$router.push('/')"
|
||||||
/> <v-btn
|
/>
|
||||||
|
<v-btn
|
||||||
icon="mdi-menu"
|
icon="mdi-menu"
|
||||||
variant="text"
|
variant="text"
|
||||||
@click="drawer = !drawer"
|
@click="drawer = !drawer"
|
||||||
@ -113,7 +113,9 @@
|
|||||||
@saved="onSettingsSaved"
|
@saved="onSettingsSaved"
|
||||||
/>
|
/>
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
|
<v-tabs-window-item value="student">
|
||||||
|
<student-list-card border :is-mobile="isMobile" />
|
||||||
|
</v-tabs-window-item>
|
||||||
<v-tabs-window-item value="share">
|
<v-tabs-window-item value="share">
|
||||||
<settings-link-generator border class="mt-4" />
|
<settings-link-generator border class="mt-4" />
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
@ -150,15 +152,15 @@
|
|||||||
/>
|
/>
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
|
|
||||||
<v-tabs-window-item value="student">
|
|
||||||
<student-list-card border :is-mobile="isMobile" />
|
|
||||||
</v-tabs-window-item>
|
|
||||||
<v-tabs-window-item value="randomPicker">
|
<v-tabs-window-item value="randomPicker">
|
||||||
<random-picker-card border :is-mobile="isMobile" />
|
<random-picker-card border :is-mobile="isMobile" />
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
<v-tabs-window-item value="homework">
|
<v-tabs-window-item value="subject">
|
||||||
|
<subject-management-card border /> <br />
|
||||||
<homework-template-card border />
|
<homework-template-card border />
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
|
|
||||||
<v-tabs-window-item value="developer"
|
<v-tabs-window-item value="developer"
|
||||||
><settings-card border title="开发者选项" icon="mdi-developer-board">
|
><settings-card border title="开发者选项" icon="mdi-developer-board">
|
||||||
<v-list>
|
<v-list>
|
||||||
@ -237,7 +239,8 @@ import SettingsExplorer from "@/components/settings/SettingsExplorer.vue";
|
|||||||
import SettingsLinkGenerator from "@/components/SettingsLinkGenerator.vue";
|
import SettingsLinkGenerator from "@/components/SettingsLinkGenerator.vue";
|
||||||
import NamespaceSettingsCard from "@/components/settings/cards/NamespaceSettingsCard.vue";
|
import NamespaceSettingsCard from "@/components/settings/cards/NamespaceSettingsCard.vue";
|
||||||
import RandomPickerCard from "@/components/settings/cards/RandomPickerCard.vue";
|
import RandomPickerCard from "@/components/settings/cards/RandomPickerCard.vue";
|
||||||
import HomeworkTemplateCard from '@/components/settings/cards/HomeworkTemplateCard.vue';
|
import HomeworkTemplateCard from "@/components/settings/cards/HomeworkTemplateCard.vue";
|
||||||
|
import SubjectManagementCard from "@/components/settings/cards/SubjectManagementCard.vue";
|
||||||
export default {
|
export default {
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
components: {
|
components: {
|
||||||
@ -257,6 +260,7 @@ export default {
|
|||||||
NamespaceSettingsCard,
|
NamespaceSettingsCard,
|
||||||
RandomPickerCard,
|
RandomPickerCard,
|
||||||
HomeworkTemplateCard,
|
HomeworkTemplateCard,
|
||||||
|
SubjectManagementCard,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { mobile } = useDisplay();
|
const { mobile } = useDisplay();
|
||||||
@ -359,6 +363,16 @@ export default {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
|
{
|
||||||
|
title: "科目",
|
||||||
|
icon: "mdi-book-edit",
|
||||||
|
value: "subject",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "学生列表",
|
||||||
|
icon: "mdi-account-group",
|
||||||
|
value: "student",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "分享设置",
|
title: "分享设置",
|
||||||
icon: "mdi-share",
|
icon: "mdi-share",
|
||||||
@ -384,21 +398,13 @@ export default {
|
|||||||
icon: "mdi-theme-light-dark",
|
icon: "mdi-theme-light-dark",
|
||||||
value: "theme",
|
value: "theme",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "学生列表",
|
|
||||||
icon: "mdi-account-group",
|
|
||||||
value: "student",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "随机点名",
|
title: "随机点名",
|
||||||
icon: "mdi-dice-multiple",
|
icon: "mdi-dice-multiple",
|
||||||
value: "randomPicker",
|
value: "randomPicker",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "作业模板",
|
|
||||||
icon: "mdi-book-edit",
|
|
||||||
value: "homework",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "开发者",
|
title: "开发者",
|
||||||
icon: "mdi-developer-board",
|
icon: "mdi-developer-board",
|
||||||
@ -425,7 +431,7 @@ export default {
|
|||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
this.drawer = !newValue;
|
this.drawer = !newValue;
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true,
|
||||||
},
|
},
|
||||||
studentData: {
|
studentData: {
|
||||||
handler(newData) {
|
handler(newData) {
|
||||||
|
202
vite.config.mjs.timestamp-1751696302207-c76e023be42d5.mjs
Normal file
202
vite.config.mjs.timestamp-1751696302207-c76e023be42d5.mjs
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user