mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-04 18:39:22 +00:00
1
This commit is contained in:
parent
08e95a3efc
commit
96c4ab81d9
@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "7.4.47",
|
"@mdi/font": "7.4.47",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
|
"idb": "^8.0.2",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"vue": "^3.4.31",
|
"vue": "^3.4.31",
|
||||||
"vue-masonry-wall": "^0.3.2",
|
"vue-masonry-wall": "^0.3.2",
|
||||||
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -14,6 +14,9 @@ importers:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.7.7
|
specifier: ^1.7.7
|
||||||
version: 1.7.7
|
version: 1.7.7
|
||||||
|
idb:
|
||||||
|
specifier: ^8.0.2
|
||||||
|
version: 8.0.2
|
||||||
roboto-fontface:
|
roboto-fontface:
|
||||||
specifier: '*'
|
specifier: '*'
|
||||||
version: 0.10.0
|
version: 0.10.0
|
||||||
@ -990,6 +993,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
idb@8.0.2:
|
||||||
|
resolution: {integrity: sha512-CX70rYhx7GDDQzwwQMDwF6kDRQi5vVs6khHUumDrMecBylKkwvZ8HWvKV08AGb7VbpoGCWUQ4aHzNDgoUiOIUg==}
|
||||||
|
|
||||||
ignore@5.3.2:
|
ignore@5.3.2:
|
||||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
@ -2752,6 +2758,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
|
|
||||||
|
idb@8.0.2: {}
|
||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
immutable@4.3.7: {}
|
immutable@4.3.7: {}
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
<v-row class="mb-6">
|
<v-row class="mb-6">
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="newStudent"
|
v-model="newStudentName"
|
||||||
label="添加学生"
|
label="添加学生"
|
||||||
placeholder="输入学生姓名后回车添加"
|
placeholder="输入学生姓名后回车添加"
|
||||||
prepend-inner-icon="mdi-account-plus"
|
prepend-inner-icon="mdi-account-plus"
|
||||||
@ -67,7 +67,7 @@
|
|||||||
icon="mdi-plus"
|
icon="mdi-plus"
|
||||||
variant="text"
|
variant="text"
|
||||||
color="primary"
|
color="primary"
|
||||||
:disabled="!newStudent.trim()"
|
:disabled="!newStudentName.trim()"
|
||||||
@click="addStudent"
|
@click="addStudent"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -131,8 +131,8 @@
|
|||||||
</v-menu>
|
</v-menu>
|
||||||
|
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-if="editingIndex === index"
|
v-if="editState.index === index"
|
||||||
v-model="editingName"
|
v-model="editState.name"
|
||||||
density="compact"
|
density="compact"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
hide-details
|
hide-details
|
||||||
@ -219,6 +219,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'StudentListCard',
|
name: 'StudentListCard',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -240,22 +241,33 @@ export default {
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
newStudent: '',
|
newStudentName: '', // 重命名以更清晰
|
||||||
editingIndex: -1,
|
editState: {
|
||||||
editingName: '',
|
index: -1,
|
||||||
internalOriginalList: [] // 添加内部状态
|
name: ''
|
||||||
|
},
|
||||||
|
savedState: null // 初始为 null,用于判断是否已初始化
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
// 初始化内部状态
|
// 使用 modelValue 初始化保存状态
|
||||||
this.internalOriginalList = [...this.originalList];
|
this.savedState = {
|
||||||
|
list: [...this.modelValue.list],
|
||||||
|
text: this.modelValue.text
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
originalList: {
|
originalList: {
|
||||||
handler(newList) {
|
handler(newList) {
|
||||||
this.internalOriginalList = [...newList];
|
// 仅在首次加载时更新保存状态
|
||||||
|
if (!this.savedState || this.savedState.list.length === 0) {
|
||||||
|
this.savedState = {
|
||||||
|
list: [...newList],
|
||||||
|
text: newList.join('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
}
|
}
|
||||||
@ -273,60 +285,66 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasChanges() {
|
hasChanges() {
|
||||||
const currentList = this.modelValue.list;
|
if (!this.savedState) return false;
|
||||||
const originalList = this.internalOriginalList;
|
|
||||||
|
|
||||||
if (currentList.length !== originalList.length) {
|
const currentState = JSON.stringify({
|
||||||
return true;
|
list: this.modelValue.list,
|
||||||
}
|
text: this.modelValue.text
|
||||||
|
});
|
||||||
// 使用 JSON 字符串比较来优化性能
|
const savedState = JSON.stringify(this.savedState);
|
||||||
return JSON.stringify(currentList) !== JSON.stringify(originalList);
|
return currentState !== savedState;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
// 初始化方法
|
||||||
|
initializeSavedList() {
|
||||||
|
// 优先使用 modelValue 的当前值,否则使用 originalList
|
||||||
|
this.savedList = this.modelValue.list.length > 0
|
||||||
|
? [...this.modelValue.list]
|
||||||
|
: [...this.originalList];
|
||||||
|
},
|
||||||
|
|
||||||
|
// 列表状态检查
|
||||||
|
isListChanged(current, original) {
|
||||||
|
if (current.length !== original.length) return true;
|
||||||
|
return JSON.stringify(current) !== JSON.stringify(original);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 编辑模式切换
|
||||||
toggleAdvanced() {
|
toggleAdvanced() {
|
||||||
const advanced = !this.modelValue.advanced;
|
const advanced = !this.modelValue.advanced;
|
||||||
const text = advanced ? this.modelValue.list.join('\n') : this.modelValue.text;
|
this.updateModelValue({
|
||||||
|
|
||||||
this.$emit('update:modelValue', {
|
|
||||||
...this.modelValue,
|
|
||||||
advanced,
|
advanced,
|
||||||
text
|
text: advanced ? this.modelValue.list.join('\n') : this.modelValue.text,
|
||||||
|
list: this.modelValue.list
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTextInput(value) {
|
// 更新数据方法
|
||||||
const list = value
|
updateModelValue(newData) {
|
||||||
.split('\n')
|
|
||||||
.map(s => s.trim())
|
|
||||||
.filter(s => s);
|
|
||||||
|
|
||||||
this.$emit('update:modelValue', {
|
this.$emit('update:modelValue', {
|
||||||
...this.modelValue,
|
...this.modelValue,
|
||||||
text: value,
|
...newData
|
||||||
list
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 学生管理方法
|
||||||
addStudent() {
|
addStudent() {
|
||||||
const name = this.newStudent.trim();
|
const name = this.newStudentName.trim();
|
||||||
if (name && !this.modelValue.list.includes(name)) {
|
if (!name || this.modelValue.list.includes(name)) return;
|
||||||
const newList = [...this.modelValue.list, name];
|
|
||||||
this.$emit('update:modelValue', {
|
const newList = [...this.modelValue.list, name];
|
||||||
...this.modelValue,
|
this.updateModelValue({
|
||||||
list: newList,
|
list: newList,
|
||||||
text: newList.join('\n')
|
text: newList.join('\n')
|
||||||
});
|
});
|
||||||
this.newStudent = '';
|
this.newStudentName = '';
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
removeStudent(index) {
|
removeStudent(index) {
|
||||||
const newList = this.modelValue.list.filter((_, i) => i !== index);
|
const newList = this.modelValue.list.filter((_, i) => i !== index);
|
||||||
this.$emit('update:modelValue', {
|
this.updateModelValue({
|
||||||
...this.modelValue,
|
|
||||||
list: newList,
|
list: newList,
|
||||||
text: newList.join('\n')
|
text: newList.join('\n')
|
||||||
});
|
});
|
||||||
@ -348,32 +366,30 @@ export default {
|
|||||||
const [student] = newList.splice(index, 1);
|
const [student] = newList.splice(index, 1);
|
||||||
newList.splice(targetIndex, 0, student);
|
newList.splice(targetIndex, 0, student);
|
||||||
|
|
||||||
this.$emit('update:modelValue', {
|
this.updateModelValue({
|
||||||
...this.modelValue,
|
|
||||||
list: newList,
|
list: newList,
|
||||||
text: newList.join('\n')
|
text: newList.join('\n')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 编辑状态管理
|
||||||
startEdit(index, name) {
|
startEdit(index, name) {
|
||||||
this.editingIndex = index;
|
this.editState = { index, name };
|
||||||
this.editingName = name;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
saveEdit() {
|
saveEdit() {
|
||||||
if (this.editingIndex !== -1 && this.editingName.trim()) {
|
const { index, name } = this.editState;
|
||||||
const newList = [...this.modelValue.list];
|
if (index === -1 || !name.trim()) return;
|
||||||
newList[this.editingIndex] = this.editingName.trim();
|
|
||||||
|
|
||||||
this.$emit('update:modelValue', {
|
const newList = [...this.modelValue.list];
|
||||||
...this.modelValue,
|
newList[index] = name.trim();
|
||||||
list: newList,
|
|
||||||
text: newList.join('\n')
|
this.updateModelValue({
|
||||||
});
|
list: newList,
|
||||||
}
|
text: newList.join('\n')
|
||||||
this.editingIndex = -1;
|
});
|
||||||
this.editingName = '';
|
this.editState = { index: -1, name: '' };
|
||||||
},
|
},
|
||||||
|
|
||||||
handleClick(index, student) {
|
handleClick(index, student) {
|
||||||
@ -383,10 +399,26 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 保存和加载处理
|
||||||
async handleSave() {
|
async handleSave() {
|
||||||
await this.$emit('save');
|
await this.$emit('save');
|
||||||
// 保存成功后更新内部状态
|
// 保存时更新状态
|
||||||
this.internalOriginalList = [...this.modelValue.list];
|
this.savedState = {
|
||||||
|
list: [...this.modelValue.list],
|
||||||
|
text: this.modelValue.text
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleTextInput(value) {
|
||||||
|
const list = value
|
||||||
|
.split('\n')
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(s => s);
|
||||||
|
|
||||||
|
this.updateModelValue({
|
||||||
|
text: value,
|
||||||
|
list: list
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,14 +435,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.unsaved-changes {
|
.unsaved-changes {
|
||||||
animation: subtle-pulse 2s infinite;
|
animation: pulse-warning 2s infinite; /* 更有意义的动画名称 */
|
||||||
border: 2px solid rgb(var(--v-theme-warning));
|
border: 2px solid rgb(var(--v-theme-warning));
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes subtle-pulse {
|
@keyframes pulse-warning {
|
||||||
0% { border-color: rgba(var(--v-theme-warning), 1); }
|
0%, 100% { border-color: rgba(var(--v-theme-warning), 1); }
|
||||||
50% { border-color: rgba(var(--v-theme-warning), 0.5); }
|
50% { border-color: rgba(var(--v-theme-warning), 0.5); }
|
||||||
100% { border-color: rgba(var(--v-theme-warning), 1); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
|
@ -211,6 +211,16 @@
|
|||||||
@click="showSyncMessage"
|
@click="showSyncMessage"
|
||||||
>
|
>
|
||||||
同步完成
|
同步完成
|
||||||
|
</v-btn><v-btn
|
||||||
|
v-if="showRandomButton"
|
||||||
|
color="yellow"
|
||||||
|
prepend-icon="mdi-account-question"
|
||||||
|
append-icon="mdi-dice-multiple"
|
||||||
|
size="large"
|
||||||
|
class="ml-2"
|
||||||
|
href="classisland://plugins/IslandCaller/Run"
|
||||||
|
>
|
||||||
|
随机点名
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-container>
|
</v-container>
|
||||||
<v-dialog
|
<v-dialog
|
||||||
@ -540,6 +550,9 @@ export default {
|
|||||||
},
|
},
|
||||||
unreadCount() {
|
unreadCount() {
|
||||||
return this.$refs.messageLog?.unreadCount || 0;
|
return this.$refs.messageLog?.unreadCount || 0;
|
||||||
|
},
|
||||||
|
showRandomButton() {
|
||||||
|
return getSetting('display.showRandomButton');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -605,10 +618,13 @@ export default {
|
|||||||
this.dataKey = this.provider === 'server' ? `${domain}/${classNum}` : classNum;
|
this.dataKey = this.provider === 'server' ? `${domain}/${classNum}` : classNum;
|
||||||
this.state.classNumber = classNum;
|
this.state.classNumber = classNum;
|
||||||
|
|
||||||
const date = new URLSearchParams(window.location.search).get("date")
|
// 从 URL 获取日期,如果没有则使用今天的日期
|
||||||
|| new Date().toISOString().split("T")[0];
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
this.state.dateString = date;
|
const dateFromUrl = urlParams.get("date");
|
||||||
this.state.isToday = date === new Date().toISOString().split("T")[0];
|
const today = new Date().toISOString().split("T")[0];
|
||||||
|
|
||||||
|
this.state.dateString = dateFromUrl || today;
|
||||||
|
this.state.isToday = this.state.dateString === today;
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.downloadData(),
|
this.downloadData(),
|
||||||
@ -816,6 +832,7 @@ export default {
|
|||||||
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.dataKey = provider === 'server' ? `${domain}/${classNum}` : classNum;
|
this.dataKey = provider === 'server' ? `${domain}/${classNum}` : classNum;
|
||||||
|
|
||||||
this.state.classNumber = classNum;
|
this.state.classNumber = classNum;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -846,9 +863,18 @@ export default {
|
|||||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
const day = String(date.getDate()).padStart(2, "0");
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
const formattedDate = `${year}-${month}-${day}`;
|
const formattedDate = `${year}-${month}-${day}`;
|
||||||
this.state.dateString = formattedDate;
|
|
||||||
this.$router.push(`/?date=${formattedDate}`);
|
// 只有当日期真正改变时才更新
|
||||||
this.downloadData();
|
if (this.state.dateString !== formattedDate) {
|
||||||
|
this.state.dateString = formattedDate;
|
||||||
|
|
||||||
|
// 使用 replace 而不是 push 来避免创建新的历史记录
|
||||||
|
this.$router.replace({
|
||||||
|
query: { date: formattedDate }
|
||||||
|
}).catch(() => {});
|
||||||
|
|
||||||
|
this.downloadData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -181,6 +181,23 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-divider class="my-2" />
|
||||||
|
|
||||||
|
<v-list-item>
|
||||||
|
<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>
|
||||||
|
<template #append>
|
||||||
|
<v-switch
|
||||||
|
v-model="settings.display.showRandomButton"
|
||||||
|
density="comfortable"
|
||||||
|
hide-details
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</settings-card>
|
</settings-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
@ -330,6 +347,7 @@ export default {
|
|||||||
display: {
|
display: {
|
||||||
emptySubjectDisplay: getSetting('display.emptySubjectDisplay'),
|
emptySubjectDisplay: getSetting('display.emptySubjectDisplay'),
|
||||||
dynamicSort: getSetting('display.dynamicSort'),
|
dynamicSort: getSetting('display.dynamicSort'),
|
||||||
|
showRandomButton: getSetting('display.showRandomButton')
|
||||||
},
|
},
|
||||||
developer: {
|
developer: {
|
||||||
enabled: getSetting('developer.enabled'),
|
enabled: getSetting('developer.enabled'),
|
||||||
@ -346,7 +364,8 @@ export default {
|
|||||||
settings,
|
settings,
|
||||||
dataProviders: [
|
dataProviders: [
|
||||||
{ title: '服务器', value: 'server' },
|
{ title: '服务器', value: 'server' },
|
||||||
{ title: '本地存储', value: 'localStorage' }
|
{ title: '本地存储', value: 'localStorage' },
|
||||||
|
{ title:'本地数据库',value:'indexedDB'}
|
||||||
],
|
],
|
||||||
studentData: {
|
studentData: {
|
||||||
list: [],
|
list: [],
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { openDB } from 'idb';
|
||||||
|
|
||||||
|
const DB_NAME = 'HomeworkDB';
|
||||||
|
const DB_VERSION = 1;
|
||||||
|
|
||||||
|
const initDB = async () => {
|
||||||
|
return openDB(DB_NAME, DB_VERSION, {
|
||||||
|
upgrade(db) {
|
||||||
|
if (!db.objectStoreNames.contains('homework')) {
|
||||||
|
db.createObjectStore('homework');
|
||||||
|
}
|
||||||
|
if (!db.objectStoreNames.contains('config')) {
|
||||||
|
db.createObjectStore('config');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const formatResponse = (data, message = null) => ({
|
const formatResponse = (data, message = null) => ({
|
||||||
success: true,
|
success: true,
|
||||||
@ -157,6 +174,96 @@ const providers = {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
indexedDB: {
|
||||||
|
async loadData(key, date) {
|
||||||
|
try {
|
||||||
|
const classNumber = key.split('/').pop();
|
||||||
|
if (!classNumber) {
|
||||||
|
return formatError('请先设置班号', 'CONFIG_ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await initDB();
|
||||||
|
const storageKey = `homework_${classNumber}_${date}`;
|
||||||
|
const data = await db.get('homework', storageKey);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
const today = new Date().toISOString().split('T')[0];
|
||||||
|
if (date === today) {
|
||||||
|
return formatResponse({
|
||||||
|
homework: {},
|
||||||
|
attendance: { absent: [], late: [] }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return formatError('数据不存在', 'NOT_FOUND');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从字符串解析数据
|
||||||
|
return formatResponse(JSON.parse(data));
|
||||||
|
} catch (error) {
|
||||||
|
return formatError('读取IndexedDB数据失败:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async saveData(key, data, date) {
|
||||||
|
try {
|
||||||
|
const classNumber = key.split('/').pop();
|
||||||
|
if (!classNumber) {
|
||||||
|
return formatError('请先设置班号', 'CONFIG_ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await initDB();
|
||||||
|
const storageKey = `homework_${classNumber}_${date}`;
|
||||||
|
// 将数据序列化为字符串存储
|
||||||
|
await db.put('homework', JSON.stringify(data), storageKey);
|
||||||
|
return formatResponse(null, '保存成功');
|
||||||
|
} catch (error) {
|
||||||
|
return formatError('保存IndexedDB数据失败:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadConfig(key) {
|
||||||
|
try {
|
||||||
|
const classNumber = key.split('/').pop();
|
||||||
|
if (!classNumber) {
|
||||||
|
return formatError('请先设置班号', 'CONFIG_ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await initDB();
|
||||||
|
const storageKey = `config_${classNumber}`;
|
||||||
|
const config = await db.get('config', storageKey);
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
return formatResponse({
|
||||||
|
studentList: [],
|
||||||
|
displayOptions: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从字符串解析配置
|
||||||
|
return formatResponse(JSON.parse(config));
|
||||||
|
} catch (error) {
|
||||||
|
return formatError('读取IndexedDB配置失败:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async saveConfig(key, config) {
|
||||||
|
try {
|
||||||
|
const classNumber = key.split('/').pop();
|
||||||
|
if (!classNumber) {
|
||||||
|
return formatError('请先设置班号', 'CONFIG_ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await initDB();
|
||||||
|
const storageKey = `config_${classNumber}`;
|
||||||
|
// 将配置序列化为字符串存储
|
||||||
|
await db.put('config', JSON.stringify(config), storageKey);
|
||||||
|
return formatResponse(null, '保存成功');
|
||||||
|
} catch (error) {
|
||||||
|
return formatError('保存IndexedDB配置失败:' + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ const settingsDefinitions = {
|
|||||||
default: true,
|
default: true,
|
||||||
description: '是否启用动态排序以优化显示效果'
|
description: '是否启用动态排序以优化显示效果'
|
||||||
},
|
},
|
||||||
|
'display.showRandomButton': {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: '是否显示随机按钮'
|
||||||
|
},
|
||||||
|
|
||||||
// 服务器设置(合并了数据提供者设置)
|
// 服务器设置(合并了数据提供者设置)
|
||||||
'server.domain': {
|
'server.domain': {
|
||||||
@ -46,7 +51,7 @@ const settingsDefinitions = {
|
|||||||
'server.provider': { // 新增项
|
'server.provider': { // 新增项
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'localStorage',
|
default: 'localStorage',
|
||||||
validate: value => ['server', 'localStorage'].includes(value),
|
validate: value => ['server', 'localStorage', 'indexedDB'].includes(value),
|
||||||
description: '数据提供者,用于决定数据存储方式'
|
description: '数据提供者,用于决定数据存储方式'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user