1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-07-03 01:39:22 +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" class="main-window flex-grow-1"
fluid 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 <div
ref="gridContainer" ref="gridContainer"
@ -164,7 +147,6 @@
</v-card> </v-card>
</div> </div>
</div> </div>
</template>
</v-container> </v-container>
<!-- 出勤统计区域 --> <!-- 出勤统计区域 -->
@ -172,7 +154,7 @@
v-if="state.studentList && state.studentList.length" v-if="state.studentList && state.studentList.length"
class="attendance-area" class="attendance-area"
cols="1" cols="1"
@click="!isPastDate ? setAttendanceArea() : null" @click="setAttendanceArea()"
> >
<h1>出勤</h1> <h1>出勤</h1>
<h2>应到: {{ state.studentList.length }}</h2> <h2>应到: {{ state.studentList.length }}</h2>
@ -386,17 +368,17 @@
</template> </template>
<script> <script>
import MessageLog from '@/components/MessageLog.vue'; import MessageLog from "@/components/MessageLog.vue";
import dataProvider from "@/utils/dataProvider"; import dataProvider from "@/utils/dataProvider";
import { getSetting, watchSettings, setSetting } from "@/utils/settings"; import { getSetting, watchSettings, setSetting } from "@/utils/settings";
import { useDisplay } from "vuetify"; import { useDisplay } from "vuetify";
import "../styles/index.scss"; import "../styles/index.scss";
import { debounce, throttle } from '@/utils/debounce'; import { debounce, throttle } from "@/utils/debounce";
export default { export default {
name: "HomeworkBoard", name: "HomeworkBoard",
components: { components: {
MessageLog MessageLog,
}, },
data() { data() {
return { return {
@ -460,8 +442,8 @@ export default {
debouncedUpload: null, debouncedUpload: null,
throttledReflow: null, throttledReflow: null,
_sortedItemsCache: { _sortedItemsCache: {
key: '', key: "",
value: [] value: [],
}, },
}; };
}, },
@ -492,7 +474,9 @@ export default {
} }
}, },
sortedItems() { 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) { if (this._sortedItemsCache.key === key) {
return this._sortedItemsCache.value; return this._sortedItemsCache.value;
} }
@ -504,7 +488,11 @@ export default {
name: value.name, name: value.name,
content: value.content, content: value.content,
order: this.state.subjectOrder.indexOf(key), 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 const result = this.dynamicSort
@ -538,22 +526,15 @@ export default {
dynamicSort() { dynamicSort() {
return getSetting("display.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() { isEditingDisabled() {
return this.state.uploadLoading || this.state.downloadLoading || this.isPastDate; return this.state.uploadLoading || this.state.downloadLoading;
}, },
unreadCount() { unreadCount() {
return this.$refs.messageLog?.unreadCount || 0; return this.$refs.messageLog?.unreadCount || 0;
}, },
showRandomButton() { showRandomButton() {
return getSetting('display.showRandomButton'); return getSetting("display.showRandomButton");
} },
}, },
watch: { watch: {
@ -615,7 +596,8 @@ export default {
const domain = getSetting("server.domain"); const domain = getSetting("server.domain");
const classNum = getSetting("server.classNumber"); 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; this.state.classNumber = classNum;
// URL 使 // URL 使
@ -626,10 +608,7 @@ export default {
this.state.dateString = dateFromUrl || today; this.state.dateString = dateFromUrl || today;
this.state.isToday = this.state.dateString === today; this.state.isToday = this.state.dateString === today;
await Promise.all([ await Promise.all([this.downloadData(), this.loadConfig()]);
this.downloadData(),
this.loadConfig()
]);
}, },
async downloadData() { async downloadData() {
@ -645,7 +624,7 @@ export default {
if (!response.success) { if (!response.success) {
// //
if (response.error.code === 'NOT_FOUND') { if (response.error.code === "NOT_FOUND") {
this.state.showNoDataMessage = true; this.state.showNoDataMessage = true;
this.state.noDataMessage = response.error.message; this.state.noDataMessage = response.error.message;
this.state.homeworkData = {}; this.state.homeworkData = {};
@ -662,10 +641,10 @@ export default {
this.state.lateSet = new Set(attendance.late || []); this.state.lateSet = new Set(attendance.late || []);
this.state.synced = true; this.state.synced = true;
this.state.showNoDataMessage = false; this.state.showNoDataMessage = false;
this.showMessage('下载成功', '数据已更新'); this.showMessage("下载成功", "数据已更新");
} }
} catch (error) { } catch (error) {
this.showError('下载失败', error.message); this.showError("下载失败", error.message);
} finally { } finally {
this.loading.download = false; this.loading.download = false;
} }
@ -683,8 +662,8 @@ export default {
homework: this.state.homeworkData, homework: this.state.homeworkData,
attendance: { attendance: {
absent: Array.from(this.state.selectedSet), absent: Array.from(this.state.selectedSet),
late: Array.from(this.state.lateSet) late: Array.from(this.state.lateSet),
} },
}, },
this.state.dateString this.state.dateString
); );
@ -694,10 +673,10 @@ export default {
} }
this.state.synced = true; this.state.synced = true;
this.showMessage(response.message || '保存成功'); this.showMessage(response.message || "保存成功");
} catch (error) { } catch (error) {
console.error('保存失败:', error); console.error("保存失败:", error);
this.showError('保存失败', error.message || '请重试'); this.showError("保存失败", error.message || "请重试");
} finally { } finally {
this.loading.upload = false; this.loading.upload = false;
} }
@ -727,8 +706,10 @@ export default {
const content = this.state.textarea.trim(); const content = this.state.textarea.trim();
if (content) { if (content) {
this.state.homeworkData[this.currentEditSubject] = { this.state.homeworkData[this.currentEditSubject] = {
name: this.state.availableSubjects.find(s => s.key === this.currentEditSubject)?.name, name: this.state.availableSubjects.find(
content (s) => s.key === this.currentEditSubject
)?.name,
content,
}; };
this.state.synced = false; this.state.synced = false;
if (this.autoSave) { if (this.autoSave) {
@ -831,7 +812,7 @@ export default {
const classNum = getSetting("server.classNumber"); const classNum = getSetting("server.classNumber");
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;
}, },
@ -869,9 +850,11 @@ export default {
this.state.dateString = formattedDate; this.state.dateString = formattedDate;
// 使 replace push // 使 replace push
this.$router.replace({ this.$router
query: { date: formattedDate } .replace({
}).catch(() => {}); query: { date: formattedDate },
})
.catch(() => {});
this.downloadData(); this.downloadData();
} }
@ -884,11 +867,14 @@ export default {
if (maxColumns <= 1) return items; 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( 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 0
); );
columns[shortestColumn].items.push(item); 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, ...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); this.$message[type](title, content);
}, },
updateSortedItemsCache(key, value) { updateSortedItemsCache(key, value) {
this._sortedItemsCache = { this._sortedItemsCache = {
key, key,
value value,
}; };
}, },
}, },

View File

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