1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-07-02 17:29:23 +00:00
This commit is contained in:
SunWuyuan 2025-03-09 15:14:04 +08:00
parent 96c4ab81d9
commit 49542e5359
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
2 changed files with 126 additions and 138 deletions

View File

@ -65,23 +65,6 @@
class="main-window flex-grow-1"
fluid
>
<div
v-if="state.showNoDataMessage && !state.isToday"
class="no-data-message"
>
<v-card class="text-center pa-4">
<v-card-title class="text-h6">
别看未来的作业了
</v-card-title>
<v-card-text>
<div class="text-body-1">
{{ state.noDataMessage }}
</div>
</v-card-text>
</v-card>
</div>
<template v-else>
<!-- 有内容的科目卡片 -->
<div
ref="gridContainer"
@ -164,7 +147,6 @@
</v-card>
</div>
</div>
</template>
</v-container>
<!-- 出勤统计区域 -->
@ -172,7 +154,7 @@
v-if="state.studentList && state.studentList.length"
class="attendance-area"
cols="1"
@click="!isPastDate ? setAttendanceArea() : null"
@click="setAttendanceArea()"
>
<h1>出勤</h1>
<h2>应到: {{ state.studentList.length }}</h2>
@ -386,17 +368,17 @@
</template>
<script>
import MessageLog from '@/components/MessageLog.vue';
import MessageLog from "@/components/MessageLog.vue";
import dataProvider from "@/utils/dataProvider";
import { getSetting, watchSettings, setSetting } from "@/utils/settings";
import { useDisplay } from "vuetify";
import "../styles/index.scss";
import { debounce, throttle } from '@/utils/debounce';
import { debounce, throttle } from "@/utils/debounce";
export default {
name: "HomeworkBoard",
components: {
MessageLog
MessageLog,
},
data() {
return {
@ -460,8 +442,8 @@ export default {
debouncedUpload: null,
throttledReflow: null,
_sortedItemsCache: {
key: '',
value: []
key: "",
value: [],
},
};
},
@ -492,7 +474,9 @@ export default {
}
},
sortedItems() {
const key = `${JSON.stringify(this.state.homeworkData)}_${this.state.subjectOrder.join()}_${this.dynamicSort}`;
const key = `${JSON.stringify(
this.state.homeworkData
)}_${this.state.subjectOrder.join()}_${this.dynamicSort}`;
if (this._sortedItemsCache.key === key) {
return this._sortedItemsCache.value;
}
@ -504,7 +488,11 @@ export default {
name: value.name,
content: value.content,
order: this.state.subjectOrder.indexOf(key),
rowSpan: Math.ceil((value.content.split('\n').filter(line => line.trim()).length + 1) * 0.8)
rowSpan: Math.ceil(
(value.content.split("\n").filter((line) => line.trim()).length +
1) *
0.8
),
}));
const result = this.dynamicSort
@ -538,22 +526,15 @@ export default {
dynamicSort() {
return getSetting("display.dynamicSort");
},
isPastDate() {
const selected = new Date(this.state.dateString);
const today = new Date();
selected.setHours(0, 0, 0, 0);
today.setHours(0, 0, 0, 0);
return selected < today;
},
isEditingDisabled() {
return this.state.uploadLoading || this.state.downloadLoading || this.isPastDate;
return this.state.uploadLoading || this.state.downloadLoading;
},
unreadCount() {
return this.$refs.messageLog?.unreadCount || 0;
},
showRandomButton() {
return getSetting('display.showRandomButton');
}
return getSetting("display.showRandomButton");
},
},
watch: {
@ -615,7 +596,8 @@ export default {
const domain = getSetting("server.domain");
const classNum = getSetting("server.classNumber");
this.dataKey = this.provider === 'server' ? `${domain}/${classNum}` : classNum;
this.dataKey =
this.provider === "server" ? `${domain}/${classNum}` : classNum;
this.state.classNumber = classNum;
// URL 使
@ -626,10 +608,7 @@ export default {
this.state.dateString = dateFromUrl || today;
this.state.isToday = this.state.dateString === today;
await Promise.all([
this.downloadData(),
this.loadConfig()
]);
await Promise.all([this.downloadData(), this.loadConfig()]);
},
async downloadData() {
@ -645,7 +624,7 @@ export default {
if (!response.success) {
//
if (response.error.code === 'NOT_FOUND') {
if (response.error.code === "NOT_FOUND") {
this.state.showNoDataMessage = true;
this.state.noDataMessage = response.error.message;
this.state.homeworkData = {};
@ -662,10 +641,10 @@ export default {
this.state.lateSet = new Set(attendance.late || []);
this.state.synced = true;
this.state.showNoDataMessage = false;
this.showMessage('下载成功', '数据已更新');
this.showMessage("下载成功", "数据已更新");
}
} catch (error) {
this.showError('下载失败', error.message);
this.showError("下载失败", error.message);
} finally {
this.loading.download = false;
}
@ -683,8 +662,8 @@ export default {
homework: this.state.homeworkData,
attendance: {
absent: Array.from(this.state.selectedSet),
late: Array.from(this.state.lateSet)
}
late: Array.from(this.state.lateSet),
},
},
this.state.dateString
);
@ -694,10 +673,10 @@ export default {
}
this.state.synced = true;
this.showMessage(response.message || '保存成功');
this.showMessage(response.message || "保存成功");
} catch (error) {
console.error('保存失败:', error);
this.showError('保存失败', error.message || '请重试');
console.error("保存失败:", error);
this.showError("保存失败", error.message || "请重试");
} finally {
this.loading.upload = false;
}
@ -727,8 +706,10 @@ export default {
const content = this.state.textarea.trim();
if (content) {
this.state.homeworkData[this.currentEditSubject] = {
name: this.state.availableSubjects.find(s => s.key === this.currentEditSubject)?.name,
content
name: this.state.availableSubjects.find(
(s) => s.key === this.currentEditSubject
)?.name,
content,
};
this.state.synced = false;
if (this.autoSave) {
@ -831,7 +812,7 @@ export default {
const classNum = getSetting("server.classNumber");
this.provider = provider;
this.dataKey = provider === 'server' ? `${domain}/${classNum}` : classNum;
this.dataKey = provider === "server" ? `${domain}/${classNum}` : classNum;
this.state.classNumber = classNum;
},
@ -869,9 +850,11 @@ export default {
this.state.dateString = formattedDate;
// 使 replace push
this.$router.replace({
query: { date: formattedDate }
}).catch(() => {});
this.$router
.replace({
query: { date: formattedDate },
})
.catch(() => {});
this.downloadData();
}
@ -884,11 +867,14 @@ export default {
if (maxColumns <= 1) return items;
// 使
const columns = Array.from({ length: maxColumns }, () => ({ height: 0, items: [] }));
const columns = Array.from({ length: maxColumns }, () => ({
height: 0,
items: [],
}));
items.forEach(item => {
items.forEach((item) => {
const shortestColumn = columns.reduce(
(min, col, i) => col.height < columns[min].height ? i : min,
(min, col, i) => (col.height < columns[min].height ? i : min),
0
);
columns[shortestColumn].items.push(item);
@ -896,9 +882,11 @@ export default {
});
//
return columns.flatMap(col => col.items).map((item, index) => ({
return columns
.flatMap((col) => col.items)
.map((item, index) => ({
...item,
order: index
order: index,
}));
},
@ -997,14 +985,14 @@ export default {
}
},
showMessage(title, content = '', type = 'success') {
showMessage(title, content = "", type = "success") {
this.$message[type](title, content);
},
updateSortedItemsCache(key, value) {
this._sortedItemsCache = {
key,
value
value,
};
},
},

View File

@ -48,9 +48,9 @@ const settingsDefinitions = {
validate: value => /^[A-Za-z0-9]*$/.test(value),
description: '班级编号(无论使用哪种存储方式都需要设置)'
},
'server.provider': { // 新增项
'server.provider': {
type: 'string',
default: 'localStorage',
default: 'indexedDB',
validate: value => ['server', 'localStorage', 'indexedDB'].includes(value),
description: '数据提供者,用于决定数据存储方式'
},