From ab20d6cecb72781bbb92293e97f940385d27f19d Mon Sep 17 00:00:00 2001 From: SunWuyuan Date: Sun, 18 May 2025 16:04:25 +0800 Subject: [PATCH] Refactor StudentListCard.vue and settings.vue to improve student data handling and UI interactions. Update student list management methods, enhance data loading and saving functionality, and streamline component props. Remove redundant code and improve overall readability. --- src/components/settings/StudentListCard.vue | 315 ++++++++++++-------- src/pages/settings.vue | 138 ++------- 2 files changed, 204 insertions(+), 249 deletions(-) diff --git a/src/components/settings/StudentListCard.vue b/src/components/settings/StudentListCard.vue index 0485afc..8bd4797 100644 --- a/src/components/settings/StudentListCard.vue +++ b/src/components/settings/StudentListCard.vue @@ -142,7 +142,7 @@ class="text-body-1 flex-grow-1" @click="handleClick(index, student)" > - {{ student }} + {{ student.name }}
@@ -194,7 +194,7 @@ size="large" :loading="loading" :disabled="loading" - @click="$emit('save')" + @click="saveStudents" > 保存名单 @@ -205,7 +205,7 @@ size="large" :loading="loading" :disabled="loading" - @click="$emit('reload')" + @click="loadStudents" > 重载名单 @@ -219,6 +219,8 @@ import UnsavedWarning from "../common/UnsavedWarning.vue"; import "@/styles/warnings.scss"; import { pinyin } from "pinyin-pro"; +import dataProvider from "@/utils/dataProvider"; +import { getSetting } from "@/utils/settings"; export default { name: "StudentListCard", @@ -226,19 +228,7 @@ export default { UnsavedWarning, }, props: { - modelValue: { - type: Object, - required: true, - default: () => ({ - list: [], - text: "", - advanced: false, - }), - }, - loading: Boolean, - error: String, isMobile: Boolean, - unsavedChanges: Boolean, }, data() { @@ -248,101 +238,200 @@ export default { index: -1, name: "", }, + modelValue: { + list: [], + text: "", + advanced: false, + }, + loading: false, + error: null, + lastSavedData: null, + unsavedChanges: false, }; }, - emits: ["update:modelValue", "save", "reload"], - - computed: { - text: { - get() { - return this.modelValue.text; - }, - set(value) { - this.handleTextInput(value); + watch: { + modelValue: { + handler(newData) { + if (this.lastSavedData) { + this.unsavedChanges = JSON.stringify(newData.list) !== JSON.stringify(this.lastSavedData); + } + if (!this.modelValue.advanced) { + this.modelValue.text = newData.list + .slice() + .sort((a, b) => a.id - b.id) + .map(s => s.name) + .join("\n"); + } }, + deep: true, }, }, + mounted() { + this.loadStudents(); + }, + methods: { - // UI 相关方法 + async loadStudents() { + this.error = null; + try { + this.loading = true; + const classNum = getSetting("server.classNumber"); + + if (!classNum) { + throw new Error("请先设置班号"); + } + + try { + const response = await dataProvider.loadData("classworks-list-main"); + + if (response.success != false && Array.isArray(response)) { + this.modelValue.list = response.map((item, index) => { + if (typeof item === 'string') { + return { id: index + 1, name: item }; + } + return { + id: item.id || index + 1, + name: item.name || item.toString() + }; + }); + + this.modelValue.list.sort((a, b) => a.id - b.id); + this.modelValue.text = this.modelValue.list.map(s => s.name).join("\n"); + this.lastSavedData = JSON.parse(JSON.stringify(this.modelValue.list)); + this.unsavedChanges = false; + return; + } + } catch (error) { + console.warn( + "Failed to load student list from dedicated key, falling back to config", + error + ); + } + } catch (error) { + console.error("加载学生列表失败:", error); + this.error = error.message || "加载失败,请检查设置"; + this.$message?.error("加载失败", this.error); + } finally { + this.loading = false; + } + }, + + async saveStudents() { + try { + const classNum = getSetting("server.classNumber"); + + if (!classNum) { + throw new Error("请先设置班号"); + } + + const formattedList = this.modelValue.list + .slice() + .sort((a, b) => a.id - b.id) + .map((student, index) => ({ + id: index + 1, + name: student.name + })); + + const response = await dataProvider.saveData( + "classworks-list-main", + formattedList + ); + + if (response.success === false) { + throw new Error(response.error?.message || "保存失败"); + } + + this.modelValue.list = formattedList; + this.lastSavedData = JSON.parse(JSON.stringify(formattedList)); + this.unsavedChanges = false; + this.$message?.success("保存成功", "学生列表已更新"); + } catch (error) { + console.error("保存学生列表失败:", error); + this.$message?.error("保存失败", error.message || "请重试"); + } + }, + toggleAdvanced() { - const advanced = !this.modelValue.advanced; - this.updateModelValue({ - advanced, - text: advanced ? this.modelValue.list.join("\n") : this.modelValue.text, - list: this.modelValue.list, - }); + this.modelValue.advanced = !this.modelValue.advanced; }, - updateModelValue(newData) { - this.$emit("update:modelValue", { - ...this.modelValue, - ...newData, + handleTextInput(text) { + if (!this.modelValue.advanced) return; + + // Split the text into lines and filter out empty lines + const lines = text.split("\n").filter((line) => line.trim()); + + // Create a map of existing student names to their IDs + const currentIds = new Map(this.modelValue.list.map(s => [s.name, s.id])); + let maxId = Math.max(0, ...this.modelValue.list.map(s => s.id)); + + // Create new list preserving IDs for existing names and generating new IDs for new names + const newList = lines.map(name => { + name = name.trim(); + if (currentIds.has(name)) { + return { id: currentIds.get(name), name }; + } + return { id: ++maxId, name }; }); + + // Update the list + this.modelValue.list = newList; }, - // 基础编辑操作 addStudent() { const name = this.newStudentName.trim(); - if (!name || this.modelValue.list.includes(name)) return; - - const newList = [...this.modelValue.list, name]; - this.updateModelValue({ - list: newList, - text: newList.join("\n"), - }); - this.newStudentName = ""; - }, - - removeStudent(index) { - const newList = this.modelValue.list.filter((_, i) => i !== index); - this.updateModelValue({ - list: newList, - text: newList.join("\n"), - }); - }, - - moveStudent(index, direction) { - const newList = [...this.modelValue.list]; - let targetIndex; - - if (direction === "top") { - targetIndex = 0; - } else if (direction === "up") { - targetIndex = index - 1; - } else { - targetIndex = index + 1; - } - - if (targetIndex >= 0 && targetIndex < newList.length) { - const [student] = newList.splice(index, 1); - newList.splice(targetIndex, 0, student); - - this.updateModelValue({ - list: newList, - text: newList.join("\n"), - }); + if (name && !this.modelValue.list.some(s => s.name === name)) { + const maxId = Math.max(0, ...this.modelValue.list.map(s => s.id)); + this.modelValue.list.push({ id: maxId + 1, name }); + this.newStudentName = ""; } }, - // 文本编辑操作 - startEdit(index, name) { - this.editState = { index, name }; + startEdit(index, student) { + this.editState.index = index; + this.editState.name = student.name; }, saveEdit() { - const { index, name } = this.editState; - if (index === -1 || !name.trim()) return; + if (this.editState.index !== -1) { + const newName = this.editState.name.trim(); + if (newName && newName !== this.modelValue.list[this.editState.index].name) { + this.modelValue.list[this.editState.index].name = newName; + } + this.editState.index = -1; + this.editState.name = ""; + } + }, - const newList = [...this.modelValue.list]; - newList[index] = name.trim(); + removeStudent(index) { + if (index !== undefined) { + this.modelValue.list.splice(index, 1); + } + }, - this.updateModelValue({ - list: newList, - text: newList.join("\n"), - }); - this.editState = { index: -1, name: "" }; + moveStudent(index, direction) { + if (direction === "top") { + if (index > 0) { + const student = this.modelValue.list[index]; + this.modelValue.list.splice(index, 1); + this.modelValue.list.unshift(student); + this.modelValue.list.forEach((s, i) => s.id = i + 1); + } + } else { + const newIndex = direction === "up" ? index - 1 : index + 1; + if (newIndex >= 0 && newIndex < this.modelValue.list.length) { + [this.modelValue.list[index], this.modelValue.list[newIndex]] = [ + this.modelValue.list[newIndex], + this.modelValue.list[index], + ]; + [this.modelValue.list[index].id, this.modelValue.list[newIndex].id] = [ + this.modelValue.list[newIndex].id, + this.modelValue.list[index].id, + ]; + } + } }, handleClick(index, student) { @@ -351,35 +440,20 @@ export default { } }, - handleTextInput(value) { - const list = value - .split("\n") - .map((s) => s.trim()) - .filter((s) => s); - - this.updateModelValue({ - text: value, - list, - }); - }, - sortStudentsByPinyin() { - const newList = [...this.modelValue.list].sort((a, b) => { - const pinyinA = pinyin(a, { toneType: "none" ,mode: 'surname'}); - const pinyinB = pinyin(b, { toneType: "none",mode: 'surname' }); + const sorted = [...this.modelValue.list].sort((a, b) => { + const pinyinA = pinyin(a.name, { toneType: "none" }); + const pinyinB = pinyin(b.name, { toneType: "none" }); return pinyinA.localeCompare(pinyinB); }); - - this.updateModelValue({ - list: newList, - text: newList.join("\n"), - }); + sorted.forEach((s, i) => s.id = i + 1); + this.modelValue.list = sorted; }, }, }; - diff --git a/src/pages/settings.vue b/src/pages/settings.vue index 8ba2f6e..f2303cb 100644 --- a/src/pages/settings.vue +++ b/src/pages/settings.vue @@ -34,12 +34,13 @@ direction="vertical" > - + - Classworks 是开源免费的软件,官方没有提供任何形式的付费支持服务,源代码仓库地址在 - + { this.loadAllSettings(); }); - this.loadStudents(); }, beforeUnmount() { @@ -435,9 +429,7 @@ export default { }); }, - // 添加统一的设置处理方法 handleSettingsChange(newSettings) { - // 使用防抖来避免过多更新 if (this.settingsChangeTimeout) { clearTimeout(this.settingsChangeTimeout); } @@ -453,13 +445,12 @@ export default { this.showMessage("设置已更新", `${settingKey} 已保存`); } else { this.showError("保存失败", `${settingKey} 设置失败`); - // 回滚到原值 this.settings[section][key] = currentValue; } } }); }); - }, 100); // 添加100ms延迟 + }, 100); }, showMessage(title, content = "", type = "success") { @@ -470,89 +461,6 @@ export default { this.$message.error(title, content); }, - async loadStudents() { - this.studentsError = null; - try { - this.loading.students = true; - const classNum = getSetting("server.classNumber"); - - if (!classNum) { - throw new Error("请先设置班号"); - } - - try { - // Try to get student list from the dedicated key - const response = await dataProvider.loadData("classworks-list-main"); - - if (response.success != false && Array.isArray(response)) { - // Transform the data into a simple list of names - this.studentData.list = response.map((student) => student.name); - this.studentData.text = this.studentData.list.join("\n"); - this.lastSavedData = [...this.studentData.list]; - this.hasUnsavedChanges = false; - return; - } - } catch (error) { - console.warn( - "Failed to load student list from dedicated key, falling back to config", - error - ); - } - } catch (error) { - console.error("加载学生列表失败:", error); - this.studentsError = error.message || "加载失败,请检查设置"; - this.showError("加载失败", this.studentsError); - } finally { - this.loading.students = false; - } - }, - - async saveStudents() { - try { - const classNum = getSetting("server.classNumber"); - - if (!classNum) { - throw new Error("请先设置班号"); - } - - // Convert the list of names to the new format with IDs - const formattedStudentList = this.studentData.list.map( - (name, index) => ({ - id: index + 1, - name, - }) - ); - - // Save the student list to the dedicated key - const response = await dataProvider.saveData( - "classworks-list-main", - formattedStudentList - ); - - if (response.success == false) { - throw new Error(response.error?.message || "保存失败"); - } - - // 更新保存状态 - this.lastSavedData = [...this.studentData.list]; - this.hasUnsavedChanges = false; - this.showMessage("保存成功", "学生列表已更新"); - } catch (error) { - console.error("保存学生列表失败:", error); - this.showError("保存失败", error.message || "请重试"); - } - }, - - handleStudentDataChange(newData) { - // 仅在列表实际发生变化时更新 - if ( - JSON.stringify(newData.list) !== JSON.stringify(this.studentData.list) - ) { - this.studentData = { ...newData }; - this.hasUnsavedChanges = true; - } - }, - saveEdit() { if (this.editingIndex !== -1) { const newName = this.editingName.trim(); @@ -587,12 +495,6 @@ export default { } }, - setStudentNumber(index) { - this.studentToMove = index; - this.newPosition = String(index + 1); - this.numberDialog = true; - }, - applyNewPosition() { const newPos = parseInt(this.newPosition) - 1; if ( @@ -680,11 +582,9 @@ export default { onSettingsSaved() { this.showMessage("设置已更新", "您的设置已成功保存"); - // 如果需要,可以在这里重新加载相关数据 }, onSettingUpdate(key, value) { - // 处理设置更新 this.showMessage("设置已更新", `${key} 已保存为 ${value}`); }, },