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-15 13:42:13 +08:00
parent e46f44bee2
commit e6cbe1faea
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
2 changed files with 35 additions and 132 deletions

View File

@ -1,8 +1,8 @@
<template> <template>
<v-card <v-card
border border
:color="hasChanges ? 'warning-subtle' : undefined" :color="unsavedChanges ? 'warning-subtle' : undefined"
:class="{ 'unsaved-changes': hasChanges }" :class="{ 'unsaved-changes': unsavedChanges }"
> >
<v-card-item> <v-card-item>
<template #prepend> <template #prepend>
@ -11,7 +11,7 @@
<v-card-title class="text-h6">学生列表</v-card-title> <v-card-title class="text-h6">学生列表</v-card-title>
<template #append> <template #append>
<unsaved-warning <unsaved-warning
:show="hasChanges" :show="unsavedChanges"
message="有未保存的更改" message="有未保存的更改"
/> />
<v-btn <v-btn
@ -190,8 +190,8 @@
prepend-icon="mdi-content-save" prepend-icon="mdi-content-save"
size="large" size="large"
:loading="loading" :loading="loading"
:disabled="loading || !hasChanges" :disabled="loading || !unsavedChanges"
@click="handleSave" @click="$emit('save')"
> >
保存名单 保存名单
</v-btn> </v-btn>
@ -201,7 +201,7 @@
prepend-icon="mdi-refresh" prepend-icon="mdi-refresh"
size="large" size="large"
:loading="loading" :loading="loading"
:disabled="loading || !hasChanges" :disabled="loading || !unsavedChanges"
@click="$emit('reload')" @click="$emit('reload')"
> >
重载名单 重载名单
@ -234,51 +234,16 @@ export default {
loading: Boolean, loading: Boolean,
error: String, error: String,
isMobile: Boolean, isMobile: Boolean,
originalList: { unsavedChanges: Boolean
type: Array,
default: () => []
}
}, },
data() { data() {
return { return {
newStudentName: '', // newStudentName: '',
editState: { editState: {
index: -1, index: -1,
name: '' name: ''
}, }
savedState: null // null
}
},
created() {
this.initializeSavedState()
},
mounted() {
this.$nextTick(() => {
this.initializeSavedState()
})
},
watch: {
originalList: {
handler(newList) {
//
if (this.modelValue.list.length === 0) {
const newState = {
list: [...newList],
text: newList.join('\n')
};
//
this.savedState = { ...newState };
this.updateModelValue({
...this.modelValue,
...newState
});
}
},
immediate: true
} }
}, },
@ -292,29 +257,11 @@ export default {
set(value) { set(value) {
this.handleTextInput(value); this.handleTextInput(value);
} }
},
hasChanges() {
return this.savedState && this.isStateChanged();
} }
}, },
methods: { methods: {
// // UI
initializeSavedState() {
const currentList = this.modelValue.list || []
this.savedState = {
list: [...currentList],
text: currentList.join('\n')
}
},
//
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;
this.updateModelValue({ this.updateModelValue({
@ -324,7 +271,6 @@ export default {
}); });
}, },
//
updateModelValue(newData) { updateModelValue(newData) {
this.$emit('update:modelValue', { this.$emit('update:modelValue', {
...this.modelValue, ...this.modelValue,
@ -332,16 +278,7 @@ export default {
}); });
}, },
// //
updateSavedState() {
const currentList = this.modelValue.list || []
this.savedState = {
list: [...currentList],
text: currentList.join('\n')
}
},
//
addStudent() { addStudent() {
const name = this.newStudentName.trim(); const name = this.newStudentName.trim();
if (!name || this.modelValue.list.includes(name)) return; if (!name || this.modelValue.list.includes(name)) return;
@ -385,7 +322,7 @@ export default {
} }
}, },
// //
startEdit(index, name) { startEdit(index, name) {
this.editState = { index, name }; this.editState = { index, name };
}, },
@ -405,23 +342,11 @@ export default {
}, },
handleClick(index, student) { handleClick(index, student) {
//
if (this.isMobile) { if (this.isMobile) {
this.startEdit(index, student); this.startEdit(index, student);
} }
}, },
//
async handleSave() {
try {
await this.$emit('save')
this.updateSavedState()
} catch (error) {
console.error('保存失败:', error);
throw error;
}
},
handleTextInput(value) { handleTextInput(value) {
const list = value const list = value
.split('\n') .split('\n')
@ -432,31 +357,6 @@ export default {
text: value, text: value,
list list
}); });
},
//
isStateChanged() {
if (!this.savedState) return false
const currentList = this.modelValue.list || []
const savedList = this.savedState.list || []
//
if (currentList.length !== savedList.length) return true
//
for (let i = 0; i < currentList.length; i++) {
if (currentList[i] !== savedList[i]) return true
}
//
if (this.modelValue.advanced) {
const currentText = this.modelValue.text || ''
const savedText = this.savedState.text || ''
if (currentText !== savedText) return true
}
return false
} }
} }
} }

View File

@ -313,8 +313,10 @@
:loading="loading.students" :loading="loading.students"
:error="studentsError" :error="studentsError"
:is-mobile="isMobile" :is-mobile="isMobile"
:unsaved-changes="hasUnsavedChanges"
@save="saveStudents" @save="saveStudents"
@reload="loadStudentList" @reload="loadStudentList"
@update:modelValue="handleStudentDataChange"
/> />
</v-col> </v-col>
@ -420,12 +422,13 @@ export default {
loading: { loading: {
server: false, server: false,
students: false students: false
} },
hasUnsavedChanges: false,
lastSavedData: null
} }
}, },
watch: { watch: {
//
'settings': { 'settings': {
handler(newSettings) { handler(newSettings) {
this.handleSettingsChange(newSettings); this.handleSettingsChange(newSettings);
@ -434,10 +437,12 @@ export default {
}, },
'studentData': { 'studentData': {
handler(newData) { handler(newData) {
// //
if (JSON.stringify(newData.list) !== JSON.stringify(this.studentData.list)) { if (this.lastSavedData) {
this.studentData.text = newData.list.join('\n'); this.hasUnsavedChanges = JSON.stringify(newData.list) !== JSON.stringify(this.lastSavedData);
} }
//
this.studentData.text = newData.list.join('\n');
}, },
deep: true deep: true
} }
@ -531,6 +536,8 @@ export default {
if (res.data && Array.isArray(res.data.studentList)) { if (res.data && Array.isArray(res.data.studentList)) {
this.studentData.list = res.data.studentList; this.studentData.list = res.data.studentList;
this.studentData.text = res.data.studentList.join('\n'); this.studentData.text = res.data.studentList.join('\n');
this.lastSavedData = [...res.data.studentList];
this.hasUnsavedChanges = false;
} }
} catch (error) { } catch (error) {
console.error('加载学生列表失败:', error); console.error('加载学生列表失败:', error);
@ -554,13 +561,15 @@ export default {
const key = provider === 'server' ? `${domain}/${classNum}` : classNum; const key = provider === 'server' ? `${domain}/${classNum}` : classNum;
const res = await dataProvider.saveConfig(provider, key, { const res = await dataProvider.saveConfig(provider, key, {
studentList: this.studentData.list, studentList: this.studentData.list,
//
}); });
if (!res.success) { if (!res.success) {
throw new Error(res.error.message); throw new Error(res.error.message);
} }
//
this.lastSavedData = [...this.studentData.list];
this.hasUnsavedChanges = false;
this.showMessage('保存成功', '学生列表已更新'); this.showMessage('保存成功', '学生列表已更新');
} catch (error) { } catch (error) {
console.error('保存学生列表失败:', error); console.error('保存学生列表失败:', error);
@ -568,14 +577,19 @@ export default {
} }
}, },
handleStudentDataChange(newData) {
//
if (JSON.stringify(newData.list) !== JSON.stringify(this.studentData.list)) {
this.studentData = { ...newData };
this.hasUnsavedChanges = true;
}
},
saveEdit() { saveEdit() {
if (this.editingIndex !== -1) { if (this.editingIndex !== -1) {
const newName = this.editingName.trim(); const newName = this.editingName.trim();
if (newName && newName !== this.studentData.list[this.editingIndex]) { if (newName && newName !== this.studentData.list[this.editingIndex]) {
this.studentData.list[this.editingIndex] = newName; this.studentData.list[this.editingIndex] = newName;
if (this.settings.edit.autoSave) {
this.saveStudents();
}
} }
this.editingIndex = -1; this.editingIndex = -1;
this.editingName = ''; this.editingName = '';
@ -599,9 +613,6 @@ export default {
const newIndex = direction === 'up' ? index - 1 : index + 1; const newIndex = direction === 'up' ? index - 1 : index + 1;
if (newIndex >= 0 && newIndex < this.studentData.list.length) { if (newIndex >= 0 && newIndex < this.studentData.list.length) {
[this.studentData.list[index], this.studentData.list[newIndex]] = [this.studentData.list[newIndex], this.studentData.list[index]]; [this.studentData.list[index], this.studentData.list[newIndex]] = [this.studentData.list[newIndex], this.studentData.list[index]];
if (this.settings.edit.autoSave) {
this.saveStudents();
}
} }
}, },
@ -622,7 +633,6 @@ export default {
const student = this.studentData.list[this.studentToMove]; const student = this.studentData.list[this.studentToMove];
this.studentData.list.splice(this.studentToMove, 1); this.studentData.list.splice(this.studentToMove, 1);
this.studentData.list.splice(newPos, 0, student); this.studentData.list.splice(newPos, 0, student);
if (this.settings.edit.autoSave) this.saveStudents();
} }
this.numberDialog = false; this.numberDialog = false;
this.studentToMove = null; this.studentToMove = null;
@ -634,9 +644,6 @@ export default {
const student = this.studentData.list[index]; const student = this.studentData.list[index];
this.studentData.list.splice(index, 1); this.studentData.list.splice(index, 1);
this.studentData.list.unshift(student); this.studentData.list.unshift(student);
if (this.settings.edit.autoSave) {
this.saveStudents();
}
} }
}, },
@ -645,9 +652,6 @@ export default {
if (student && !this.studentData.list.includes(student)) { if (student && !this.studentData.list.includes(student)) {
this.studentData.list.push(student); this.studentData.list.push(student);
this.newStudent = ''; this.newStudent = '';
if (this.settings.edit.autoSave) {
this.saveStudents();
}
} }
}, },
@ -656,7 +660,6 @@ export default {
this.studentData.list.splice(index, 1); this.studentData.list.splice(index, 1);
this.deleteDialog = false; this.deleteDialog = false;
this.studentToDelete = null; this.studentToDelete = null;
if (this.settings.edit.autoSave) this.saveStudents();
} }
}, },