mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-05 11:09:29 +00:00
1
This commit is contained in:
parent
7abd0f0a15
commit
1137f44c44
@ -1,59 +1,101 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-card title="选择服务器">
|
<v-card border>
|
||||||
<v-card-text>
|
<v-card>
|
||||||
<v-form @submit.prevent="saveServerUrl">
|
<v-card-title>选择服务器</v-card-title>
|
||||||
<v-text-field v-model="serverUrl" label="后端地址" required />
|
<v-card-subtitle>没事别乱动</v-card-subtitle>
|
||||||
<v-btn type="submit" color="primary"> 保存 </v-btn>
|
<v-card-text>
|
||||||
</v-form>
|
<v-text-field v-model="serverUrl" label="后端地址" required />
|
||||||
</v-card-text>
|
<v-btn type="submit" color="primary" @click="saveServerUrl"> 保存 </v-btn>
|
||||||
</v-card>
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>设置学生列表</v-card-title>
|
||||||
|
<v-card-subtitle>没事别乱动</v-card-subtitle>
|
||||||
|
|
||||||
|
<v-card-text>
|
||||||
|
<v-textarea v-model="students" label="学生列表" required />
|
||||||
|
<v-btn type="submit" color="primary" @click="saveStudents" border>
|
||||||
|
保存
|
||||||
|
</v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card></v-card
|
||||||
|
>
|
||||||
<v-snackbar v-model="snackbar">
|
<v-snackbar v-model="snackbar">
|
||||||
{{ snackbarText }}
|
{{ snackbarText }}
|
||||||
</v-snackbar>
|
</v-snackbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
serverUrl: "",
|
serverUrl: "",
|
||||||
snackbar: false,
|
snackbar: false,
|
||||||
snackbarText: "",
|
snackbarText: "",
|
||||||
|
students: "",
|
||||||
|
studentsList: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadServerUrl();
|
this.loadServerUrl();
|
||||||
|
this.loadStudents();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
saveServerUrl() {
|
saveServerUrl() {
|
||||||
try {
|
try {
|
||||||
|
// 格式化URL,去除空格,/结尾,http://开头,使用new URL()
|
||||||
|
if (this.serverUrl == "") {
|
||||||
|
localStorage.removeItem("backendServerUrl");
|
||||||
|
this.snackbarText = "删除成功,请刷新页面。";
|
||||||
|
this.snackbar = true;
|
||||||
|
|
||||||
// 格式化URL,去除空格,/结尾,http://开头,使用new URL()
|
return;
|
||||||
if (this.serverUrl == "") {
|
}
|
||||||
localStorage.removeItem("backendServerUrl");
|
this.serverUrl =
|
||||||
this.snackbarText = "删除成功,请刷新页面。";
|
new URL(this.serverUrl).protocol +
|
||||||
|
"//" +
|
||||||
|
new URL(this.serverUrl).host;
|
||||||
|
localStorage.setItem("backendServerUrl", this.serverUrl);
|
||||||
|
this.snackbarText = "保存成功,请刷新页面。";
|
||||||
this.snackbar = true;
|
this.snackbar = true;
|
||||||
|
} catch (error) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.serverUrl =
|
|
||||||
new URL(this.serverUrl).protocol + "//" + new URL(this.serverUrl).host;
|
|
||||||
localStorage.setItem("backendServerUrl", this.serverUrl);
|
|
||||||
this.snackbarText = "保存成功,请刷新页面。";
|
|
||||||
this.snackbar = true;
|
|
||||||
}catch (error) {
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
this.snackbarText = "保存失败,请检查后端地址。";
|
this.snackbarText = "保存失败,请检查后端地址。";
|
||||||
this.snackbar = true;
|
this.snackbar = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
saveStudents() {
|
||||||
|
try {
|
||||||
|
this.studentsList = this.students.split("\n");
|
||||||
|
axios
|
||||||
|
.post(this.serverUrl + "/setstudentlist", {
|
||||||
|
studentList: this.studentsList,
|
||||||
|
id: 1,
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
});
|
||||||
|
localStorage.setItem("studentList", this.students);
|
||||||
|
this.snackbarText = "保存成功,请刷新页面。";
|
||||||
|
this.snackbar = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
this.snackbarText = "保存失败,请检查学生列表。";
|
||||||
|
this.snackbar = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
loadServerUrl() {
|
loadServerUrl() {
|
||||||
const savedUrl = localStorage.getItem("backendServerUrl");
|
const savedUrl = localStorage.getItem("backendServerUrl");
|
||||||
if (savedUrl) {
|
if (savedUrl) {
|
||||||
this.serverUrl = savedUrl;
|
this.serverUrl = savedUrl;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
loadStudents() {
|
||||||
|
if (localStorage.getItem("studentList")) {
|
||||||
|
this.students = localStorage.getItem("studentList").replace(/,/g, "\n");
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app-bar>
|
<v-app-bar>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-app-bar-nav-icon icon="mdi-home"/>
|
<v-app-bar-nav-icon icon="mdi-home" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-app-bar-title>
|
<v-app-bar-title>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
style="padding: 2px !important"
|
style="padding: 2px !important"
|
||||||
@click="openDialog(subject)"
|
@click="openDialog(subject)"
|
||||||
>
|
>
|
||||||
<v-card>
|
<v-card border>
|
||||||
<v-card-title>{{ homeworkData[subject].name }}</v-card-title>
|
<v-card-title>{{ homeworkData[subject].name }}</v-card-title>
|
||||||
<v-card-text :style="contentStyle">
|
<v-card-text :style="contentStyle">
|
||||||
<v-list>
|
<v-list>
|
||||||
@ -47,6 +47,7 @@
|
|||||||
<div />
|
<div />
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
|
||||||
<v-col
|
<v-col
|
||||||
v-if="studentList.length"
|
v-if="studentList.length"
|
||||||
class="attendance-area"
|
class="attendance-area"
|
||||||
@ -55,15 +56,21 @@
|
|||||||
>
|
>
|
||||||
<h1>出勤</h1>
|
<h1>出勤</h1>
|
||||||
<h2>应到:{{ studentList.length }}人</h2>
|
<h2>应到:{{ studentList.length }}人</h2>
|
||||||
<h2>实到:{{ studentList.length - selectedSet.size }}人</h2>
|
<h2>
|
||||||
<h2 style="margin-bottom: 5px">请假:{{ selectedSet.size }} 人</h2>
|
实到:{{ studentList.length - selectedSet.size - lateSet.size }}人
|
||||||
<h3 v-for="(i, index) in selectedSet" :key="index">
|
</h2>
|
||||||
|
<h2>请假:{{ selectedSet.size }} 人</h2>
|
||||||
|
<h3 v-for="(i, index) in selectedSet" :key="'absent-' + index">
|
||||||
|
{{ `${index + 1}. ${studentList[i]}` }}
|
||||||
|
</h3>
|
||||||
|
<h2>迟到:{{ lateSet.size }} 人</h2>
|
||||||
|
|
||||||
|
<h3 v-for="(i, index) in lateSet" :key="'late-' + index">
|
||||||
{{ `${index + 1}. ${studentList[i]}` }}
|
{{ `${index + 1}. ${studentList[i]}` }}
|
||||||
</h3>
|
</h3>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
<v-btn icon="mdi-plus" variant="text" @click="zoom('up')" />
|
<v-btn icon="mdi-plus" variant="text" @click="zoom('up')" />
|
||||||
<v-btn icon="mdi-minus" variant="text" @click="zoom('out')" />
|
<v-btn icon="mdi-minus" variant="text" @click="zoom('out')" />
|
||||||
@ -91,8 +98,9 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</v-container>
|
</v-container>
|
||||||
<v-dialog v-model="dialogVisible" width="500" @click:outside="handleClose">
|
<v-dialog v-model="dialogVisible" width="500" @click:outside="handleClose">
|
||||||
<v-card>
|
<v-card border>
|
||||||
<v-card-title>{{ dialogTitle }}</v-card-title>
|
<v-card-title>{{ dialogTitle }}</v-card-title>
|
||||||
|
<v-card-subtitle>写完后点击上传谢谢喵</v-card-subtitle>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-textarea
|
<v-textarea
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
@ -107,8 +115,8 @@
|
|||||||
|
|
||||||
<v-dialog v-model="attendDialogVisible" width="800">
|
<v-dialog v-model="attendDialogVisible" width="800">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>设置未到学生列表</v-card-title>
|
<v-card-title>设置学生出勤状态</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text><v-btn @click="cleanstudentslist">全勤</v-btn>
|
||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col
|
<v-col
|
||||||
@ -119,10 +127,16 @@
|
|||||||
md="4"
|
md="4"
|
||||||
>
|
>
|
||||||
<v-card
|
<v-card
|
||||||
:class="{ selected: selectedSet.has(i) }"
|
border
|
||||||
variant="outlined"
|
:class="{ selected: selectedSet.has(i) || lateSet.has(i) }"
|
||||||
:color="selectedSet.has(i) ? 'primary' : ''"
|
:color="
|
||||||
@click="toggleStudent(i)"
|
selectedSet.has(i)
|
||||||
|
? 'primary'
|
||||||
|
: lateSet.has(i)
|
||||||
|
? 'orange'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
@click="toggleStudentStatus(i)"
|
||||||
>
|
>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
{{ `${i + 1}. ${name}` }}
|
{{ `${i + 1}. ${name}` }}
|
||||||
@ -134,6 +148,7 @@
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
<v-dialog v-model="ServerSelectionDialog" width="500">
|
<v-dialog v-model="ServerSelectionDialog" width="500">
|
||||||
<ServerSelection />
|
<ServerSelection />
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -147,6 +162,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useDisplay } from "vuetify";
|
import { useDisplay } from "vuetify";
|
||||||
import ServerSelection from "../components/ServerSelection.vue";
|
import ServerSelection from "../components/ServerSelection.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "HomeworkBoard",
|
name: "HomeworkBoard",
|
||||||
components: { ServerSelection },
|
components: { ServerSelection },
|
||||||
@ -155,7 +171,8 @@ export default {
|
|||||||
backurl: localStorage.getItem("backendServerUrl") || "",
|
backurl: localStorage.getItem("backendServerUrl") || "",
|
||||||
currentEditSubject: null,
|
currentEditSubject: null,
|
||||||
studentList: ["加载中"],
|
studentList: ["加载中"],
|
||||||
selectedSet: new Set(),
|
selectedSet: new Set(), // Absent students
|
||||||
|
lateSet: new Set(), // Late students
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
dialogTitle: "",
|
dialogTitle: "",
|
||||||
textarea: "",
|
textarea: "",
|
||||||
@ -194,6 +211,7 @@ export default {
|
|||||||
async initializeData() {
|
async initializeData() {
|
||||||
const res = await axios.get(this.backurl + "/config.json");
|
const res = await axios.get(this.backurl + "/config.json");
|
||||||
this.studentList = res.data.studentList;
|
this.studentList = res.data.studentList;
|
||||||
|
localStorage.setItem("studentList", res.data.studentList);
|
||||||
this.homeworkArrange = res.data.homeworkArrange;
|
this.homeworkArrange = res.data.homeworkArrange;
|
||||||
|
|
||||||
this.initializeHomeworkData();
|
this.initializeHomeworkData();
|
||||||
@ -261,15 +279,24 @@ export default {
|
|||||||
this.attendDialogVisible = true;
|
this.attendDialogVisible = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleStudent(index) {
|
toggleStudentStatus(index) {
|
||||||
if (this.selectedSet.has(index)) {
|
if (this.selectedSet.has(index)) {
|
||||||
this.selectedSet.delete(index);
|
this.selectedSet.delete(index);
|
||||||
|
this.lateSet.add(index); // Toggle to late
|
||||||
|
} else if (this.lateSet.has(index)) {
|
||||||
|
this.lateSet.delete(index);
|
||||||
} else {
|
} else {
|
||||||
this.selectedSet.add(index);
|
this.selectedSet.add(index); // Toggle to late
|
||||||
}
|
}
|
||||||
this.synced = false;
|
this.synced = false;
|
||||||
},
|
},
|
||||||
|
cleanstudentslist()
|
||||||
|
{
|
||||||
|
this.selectedSet.clear();
|
||||||
|
this.lateSet.clear();
|
||||||
|
this.synced = false;
|
||||||
|
|
||||||
|
},
|
||||||
zoom(direction) {
|
zoom(direction) {
|
||||||
const step = 2;
|
const step = 2;
|
||||||
if (direction === "up" && this.fontSize < 100) {
|
if (direction === "up" && this.fontSize < 100) {
|
||||||
@ -289,6 +316,7 @@ export default {
|
|||||||
date: this.dateString,
|
date: this.dateString,
|
||||||
data: this.homeworkData,
|
data: this.homeworkData,
|
||||||
attendance: Array.from(this.selectedSet),
|
attendance: Array.from(this.selectedSet),
|
||||||
|
late: Array.from(this.lateSet), // Upload late students as well
|
||||||
});
|
});
|
||||||
this.synced = true;
|
this.synced = true;
|
||||||
this.showSyncMessage();
|
this.showSyncMessage();
|
||||||
@ -363,6 +391,7 @@ export default {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
this.selectedSet = new Set(res.data.attendance || []);
|
this.selectedSet = new Set(res.data.attendance || []);
|
||||||
|
this.lateSet = new Set(res.data.late || []); // Initialize late set
|
||||||
this.synced = true;
|
this.synced = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user