mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-02 17:29:23 +00:00
1
This commit is contained in:
parent
e46f44bee2
commit
e6cbe1faea
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user