mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-07-05 11:09:29 +00:00
1
This commit is contained in:
parent
99f3f1b0ef
commit
5cfeba57ba
@ -24,7 +24,6 @@
|
|||||||
<v-menu
|
<v-menu
|
||||||
v-model="datePickerDialog"
|
v-model="datePickerDialog"
|
||||||
:close-on-content-click="false"
|
:close-on-content-click="false"
|
||||||
|
|
||||||
>
|
>
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-btn
|
<v-btn
|
||||||
@ -60,150 +59,94 @@
|
|||||||
fluid
|
fluid
|
||||||
>
|
>
|
||||||
<div v-if="showNoDataMessage && !isToday" class="no-data-message">
|
<div v-if="showNoDataMessage && !isToday" class="no-data-message">
|
||||||
<v-card class="text-center pa-4" variant="outlined">
|
<v-card class="text-center pa-4" >
|
||||||
<v-card-title class="text-h6">{{ noDataMessage }}</v-card-title>
|
<v-card-title class="text-h6">别看未来的作业了</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<div class="text-body-1">该日期未上传作业数据</div>
|
<div class="text-body-1">{{ noDataMessage }}</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="showNoDataMessage && isToday" class="no-data-message">
|
<div class="grid-masonry" ref="gridContainer">
|
||||||
<v-card class="text-center pa-4" variant="outlined">
|
<div
|
||||||
<v-card-title class="text-h6">开始今天的作业</v-card-title>
|
v-for="item in sortedItems"
|
||||||
<v-card-text>
|
:key="item.key"
|
||||||
<div class="text-body-1 mb-4">今天还没有上传作业哦~</div>
|
class="grid-item"
|
||||||
<v-btn
|
:class="{
|
||||||
color="primary"
|
'empty-card': !item.content,
|
||||||
@click="initializeAndOpenDialog"
|
[`grid-row-${item.rowSpan}`]: true
|
||||||
>
|
}"
|
||||||
开始添加作业
|
:style="{
|
||||||
</v-btn>
|
'grid-row-end': `span ${item.rowSpan}`,
|
||||||
</v-card-text>
|
order: item.order,
|
||||||
</v-card>
|
cursor: uploadLoading || downloadLoading || isPastDate ? 'not-allowed' : 'pointer',
|
||||||
|
opacity: uploadLoading || downloadLoading ? '0.7' : '1'
|
||||||
|
}"
|
||||||
|
@click="!uploadLoading && !downloadLoading && !isPastDate && openDialog(item.key)"
|
||||||
|
>
|
||||||
|
<v-card border height="100%">
|
||||||
|
<v-card-title :class="{ 'text-subtitle-1': !item.content }">
|
||||||
|
{{ item.name }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text :style="item.content ? contentStyle : null">
|
||||||
|
<template v-if="item.content">
|
||||||
|
<v-list>
|
||||||
|
<v-list-item
|
||||||
|
v-for="text in splitPoint(item.content)"
|
||||||
|
:key="text"
|
||||||
|
>
|
||||||
|
{{ text }}
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="text-center pa-2">
|
||||||
|
<v-icon size="small" color="grey">mdi-plus</v-icon>
|
||||||
|
<div class="text-caption text-grey">点击添加作业</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<!-- 空科目按钮组 -->
|
||||||
<div class="grid-masonry" ref="gridContainer">
|
<v-btn-group v-if="emptySubjectDisplay === 'button'" class="empty-subjects-container">
|
||||||
<div
|
<v-btn
|
||||||
v-for="item in sortedItems"
|
v-for="subject in emptySubjects"
|
||||||
:key="item.key"
|
:key="subject.key"
|
||||||
class="grid-item"
|
variant="tonal"
|
||||||
:class="{
|
color="primary"
|
||||||
'empty-card': !item.content,
|
@click="!uploadLoading && !downloadLoading && openDialog(subject.key)"
|
||||||
[`grid-row-${item.rowSpan}`]: true
|
:disabled="uploadLoading || downloadLoading"
|
||||||
}"
|
>
|
||||||
:style="{
|
<v-icon start>mdi-plus</v-icon>
|
||||||
'grid-row-end': `span ${item.rowSpan}`,
|
{{ subject.name }}
|
||||||
order: item.order,
|
</v-btn>
|
||||||
cursor: uploadLoading || downloadLoading ? 'not-allowed' : 'pointer',
|
</v-btn-group>
|
||||||
opacity: uploadLoading || downloadLoading ? '0.7' : '1'
|
|
||||||
}"
|
|
||||||
@click="!uploadLoading && !downloadLoading && openDialog(item.key)"
|
|
||||||
>
|
|
||||||
<v-card border height="100%">
|
|
||||||
<v-card-title :class="{ 'text-subtitle-1': !item.content }">
|
|
||||||
{{ item.name }}
|
|
||||||
</v-card-title>
|
|
||||||
<v-card-text :style="item.content ? contentStyle : null">
|
|
||||||
<template v-if="item.content">
|
|
||||||
<v-list>
|
|
||||||
<v-list-item
|
|
||||||
v-for="text in splitPoint(item.content)"
|
|
||||||
:key="text"
|
|
||||||
>
|
|
||||||
{{ text }}
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="text-center pa-2">
|
|
||||||
<v-icon size="small" color="grey">mdi-plus</v-icon>
|
|
||||||
<div class="text-caption text-grey">点击添加作业</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 空科目按钮组 -->
|
|
||||||
<div v-if="emptySubjectDisplay === 'button'" class="empty-subjects-container">
|
|
||||||
<v-btn
|
|
||||||
v-for="subject in emptySubjects"
|
|
||||||
:key="subject.key"
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
class="empty-subject-btn"
|
|
||||||
@click="!uploadLoading && !downloadLoading && openDialog(subject.key)"
|
|
||||||
:disabled="uploadLoading || downloadLoading"
|
|
||||||
>
|
|
||||||
<v-icon start>mdi-plus</v-icon>
|
|
||||||
{{ subject.name }}
|
|
||||||
</v-btn>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<!-- 出勤统计区域 -->
|
<!-- 出勤统计区域 -->
|
||||||
<v-navigation-drawer
|
<v-col
|
||||||
v-if="studentList.length > 1"
|
v-if="studentList.length"
|
||||||
location="right"
|
class="attendance-area"
|
||||||
permanent
|
cols="1"
|
||||||
width="300"
|
@click="!isPastDate ? setAttendanceArea() : null"
|
||||||
class="attendance-drawer"
|
|
||||||
>
|
>
|
||||||
<v-card
|
<h1>出勤</h1>
|
||||||
class="h-100 attendance-card"
|
<h2>应到: {{ studentList.length }}人</h2>
|
||||||
flat
|
<h2>实到: {{ studentList.length - selectedSet.size }}人</h2>
|
||||||
>
|
<h2>请假: {{ selectedSet.size }}人</h2>
|
||||||
<v-card-text class="text-center">
|
<h3 v-for="(i, index) in selectedSet" :key="'absent-' + index">
|
||||||
<div class="attendance-numbers">
|
{{ `${index + 1}. ${studentList[i]}` }}
|
||||||
<div class="total-number mb-4">
|
</h3>
|
||||||
<div class="text-h2 font-weight-bold">{{ studentList.length }}</div>
|
<h2>迟到: {{ lateSet.size }}人</h2>
|
||||||
<div class="text-overline">应到</div>
|
<h3 v-for="(i, index) in lateSet" :key="'late-' + index">
|
||||||
</div>
|
{{ `${index + 1}. ${studentList[i]}` }}
|
||||||
|
</h3>
|
||||||
<div class="d-flex justify-space-around">
|
</v-col>
|
||||||
<div class="status-number text-success">
|
|
||||||
<div class="text-h3 font-weight-bold">
|
|
||||||
{{ studentList.length - selectedSet.size - lateSet.size }}
|
|
||||||
</div>
|
|
||||||
<div class="text-overline">实到</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="status-number text-error">
|
|
||||||
<div class="text-h3 font-weight-bold">
|
|
||||||
{{ selectedSet.size }}
|
|
||||||
</div>
|
|
||||||
<div class="text-overline">请假</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="status-number text-warning">
|
|
||||||
<div class="text-h3 font-weight-bold">
|
|
||||||
{{ lateSet.size }}
|
|
||||||
</div>
|
|
||||||
<div class="text-overline">迟到</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</v-card-text>
|
|
||||||
|
|
||||||
<v-card-actions class="pa-4">
|
|
||||||
<v-btn
|
|
||||||
block
|
|
||||||
color="primary"
|
|
||||||
size="large"
|
|
||||||
prepend-icon="mdi-pencil"
|
|
||||||
@click="setAttendanceArea"
|
|
||||||
>
|
|
||||||
编辑出勤
|
|
||||||
</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
</div>
|
</div>
|
||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
<v-btn
|
<v-btn
|
||||||
@ -232,7 +175,9 @@
|
|||||||
>
|
>
|
||||||
<v-card border>
|
<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-subtitle>
|
||||||
|
{{ autoSave ? "喵?喵呜!" : "写完后点击上传谢谢喵" }}
|
||||||
|
</v-card-subtitle>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-textarea
|
<v-textarea
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
@ -420,13 +365,6 @@
|
|||||||
.empty-subjects-container {
|
.empty-subjects-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-subject-btn {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 120px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1199px) {
|
@media (max-width: 1199px) {
|
||||||
@ -440,10 +378,6 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-subject-btn {
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-card {
|
.empty-card {
|
||||||
transform: scale(0.95);
|
transform: scale(0.95);
|
||||||
}
|
}
|
||||||
@ -635,12 +569,15 @@ export default {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 根据排序模式选择不同的排序方法
|
// Sort items: prioritize non-empty content first
|
||||||
if (this.dynamicSort) {
|
return items.sort((a, b) => {
|
||||||
return this.optimizeGridLayout(items);
|
// If one item has content and the other does not, prioritize the one with content
|
||||||
} else {
|
if (a.content && !b.content) return -1;
|
||||||
return this.fixedGridLayout(items);
|
if (!a.content && b.content) return 1;
|
||||||
}
|
|
||||||
|
// If both have content or both are empty, sort by order
|
||||||
|
return a.order - b.order;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
attendanceVisible() {
|
attendanceVisible() {
|
||||||
return this.studentList.length > 0;
|
return this.studentList.length > 0;
|
||||||
@ -670,6 +607,14 @@ export default {
|
|||||||
dynamicSort() {
|
dynamicSort() {
|
||||||
return getSetting('display.dynamicSort');
|
return getSetting('display.dynamicSort');
|
||||||
},
|
},
|
||||||
|
isPastDate() {
|
||||||
|
const selectedDate = new Date(this.dateString);
|
||||||
|
const today = new Date();
|
||||||
|
// 将时间部分归零以进行比较
|
||||||
|
selectedDate.setHours(0, 0, 0, 0);
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
return selectedDate < today; // 如果选择的日期在今天之前,则返回 true
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@ -806,12 +751,29 @@ export default {
|
|||||||
|
|
||||||
this.synced = true;
|
this.synced = true;
|
||||||
} else {
|
} else {
|
||||||
// Handle the error case
|
// Handle the error case for today's date
|
||||||
this.showNoDataMessage = true;
|
if (this.isToday && res.data.status == false) {
|
||||||
this.noDataMessage = res.data.msg || '未找到数据';
|
this.showNoDataMessage = false; // Ensure we show the empty data
|
||||||
this.homeworkData = {};
|
this.homeworkData = {
|
||||||
this.selectedSet.clear();
|
"语文": { name: "语文", content: "" },
|
||||||
this.lateSet.clear();
|
"数学": { name: "数学", content: "" },
|
||||||
|
"英语": { name: "英语", content: "" },
|
||||||
|
"物理": { name: "物理", content: "" },
|
||||||
|
"化学": { name: "化学", content: "" },
|
||||||
|
"生物": { name: "生物", content: "" },
|
||||||
|
"历史": { name: "历史", content: "" },
|
||||||
|
"地理": { name: "地理", content: "" },
|
||||||
|
"政治": { name: "政治", content: "" },
|
||||||
|
};
|
||||||
|
this.noDataMessage = ''; // Clear any previous message
|
||||||
|
} else {
|
||||||
|
// Handle other error cases
|
||||||
|
this.showNoDataMessage = true;
|
||||||
|
this.noDataMessage = res.data.msg || '未找到数据';
|
||||||
|
this.homeworkData = {};
|
||||||
|
this.selectedSet.clear();
|
||||||
|
this.lateSet.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('下载数据失败:', error);
|
console.error('下载数据失败:', error);
|
||||||
@ -1076,24 +1038,6 @@ export default {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
initializeAndOpenDialog() {
|
|
||||||
// 初始化作业数据
|
|
||||||
this.initializeHomeworkData();
|
|
||||||
this.showNoDataMessage = false;
|
|
||||||
this.synced = false; // 设置为未同步状态
|
|
||||||
|
|
||||||
// 如果启用了自动保存,初始化后自动上传
|
|
||||||
if (this.autoSave) {
|
|
||||||
this.uploadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开第一个科目的对话框
|
|
||||||
const firstSubject = Object.keys(this.homeworkData)[0];
|
|
||||||
if (firstSubject) {
|
|
||||||
this.openDialog(firstSubject);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setAllPresent() {
|
setAllPresent() {
|
||||||
this.selectedSet.clear();
|
this.selectedSet.clear();
|
||||||
this.lateSet.clear();
|
this.lateSet.clear();
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app-bar elevation="1">
|
<v-app-bar elevation="1">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-btn
|
<v-btn icon="mdi-arrow-left" variant="text" @click="$router.push('/')" class="mr-2" />
|
||||||
icon="mdi-arrow-left"
|
|
||||||
variant="text"
|
|
||||||
@click="$router.push('/')"
|
|
||||||
class="mr-2"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<v-app-bar-title class="text-h6 font-weight-medium">设置</v-app-bar-title>
|
<v-app-bar-title class="text-h6 font-weight-medium">设置</v-app-bar-title>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
|
||||||
<v-container class="py-4">
|
<v-container class="py-4">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="4">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
@ -21,46 +16,26 @@
|
|||||||
</template>
|
</template>
|
||||||
<v-card-title class="text-h6">服务器设置</v-card-title>
|
<v-card-title class="text-h6">服务器设置</v-card-title>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-text-field
|
<v-text-field v-model="settings.server.domain" label="服务器域名" placeholder="例如: http://example.com"
|
||||||
v-model="settings.server.domain"
|
prepend-inner-icon="mdi-web" variant="outlined" density="comfortable" class="mb-4" required />
|
||||||
label="服务器域名"
|
<v-text-field v-model="settings.server.classNumber" label="班号" placeholder="例如: 1 或 A"
|
||||||
placeholder="例如: http://example.com"
|
prepend-inner-icon="mdi-account-group" variant="outlined" density="comfortable" required
|
||||||
prepend-inner-icon="mdi-web"
|
:rules="[v => !!v || '班号不能为空', v => /^[A-Za-z0-9]+$/.test(v) || '班号只能包含字母和数字']" />
|
||||||
variant="outlined"
|
|
||||||
density="comfortable"
|
|
||||||
class="mb-4"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<v-text-field
|
|
||||||
v-model="settings.server.classNumber"
|
|
||||||
label="班号"
|
|
||||||
placeholder="例如: 1 或 A"
|
|
||||||
prepend-inner-icon="mdi-account-group"
|
|
||||||
variant="outlined"
|
|
||||||
density="comfortable"
|
|
||||||
required
|
|
||||||
:rules="[v => !!v || '班号不能为空', v => /^[A-Za-z0-9]+$/.test(v) || '班号只能包含字母和数字']"
|
|
||||||
/>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions class="px-4 pb-4">
|
<v-card-actions class="px-4 pb-4">
|
||||||
<v-btn
|
<v-btn color="primary" prepend-icon="mdi-content-save" block @click="saveSettings('server')">
|
||||||
color="primary"
|
|
||||||
prepend-icon="mdi-content-save"
|
|
||||||
block
|
|
||||||
@click="saveSettings('server')"
|
|
||||||
>
|
|
||||||
保存设置
|
保存设置
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<v-col cols="12" md="6">
|
|
||||||
|
<v-col cols="12" md="4">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
@ -68,44 +43,25 @@
|
|||||||
</template>
|
</template>
|
||||||
<v-card-title class="text-h6">自动刷新设置(不建议启用)</v-card-title>
|
<v-card-title class="text-h6">自动刷新设置(不建议启用)</v-card-title>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-switch
|
<v-switch v-model="settings.refresh.auto" label="启用自动刷新" color="primary" hide-details class="mb-4" />
|
||||||
v-model="settings.refresh.auto"
|
<v-text-field v-model="settings.refresh.interval" type="number" label="刷新间隔" suffix="秒"
|
||||||
label="启用自动刷新"
|
:disabled="!settings.refresh.auto" variant="outlined" density="comfortable" :rules="[
|
||||||
color="primary"
|
|
||||||
hide-details
|
|
||||||
class="mb-4"
|
|
||||||
/>
|
|
||||||
<v-text-field
|
|
||||||
v-model="settings.refresh.interval"
|
|
||||||
type="number"
|
|
||||||
label="刷新间隔"
|
|
||||||
suffix="秒"
|
|
||||||
:disabled="!settings.refresh.auto"
|
|
||||||
variant="outlined"
|
|
||||||
density="comfortable"
|
|
||||||
:rules="[
|
|
||||||
v => v >= 10 || '刷新间隔不能小于10秒',
|
v => v >= 10 || '刷新间隔不能小于10秒',
|
||||||
v => v <= 3600 || '刷新间隔不能大于3600秒'
|
v => v <= 3600 || '刷新间隔不能大于3600秒'
|
||||||
]"
|
]" />
|
||||||
/>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions class="px-4 pb-4">
|
<v-card-actions class="px-4 pb-4">
|
||||||
<v-btn
|
<v-btn color="primary" prepend-icon="mdi-content-save" block @click="saveSettings('refresh')">
|
||||||
color="primary"
|
|
||||||
prepend-icon="mdi-content-save"
|
|
||||||
block
|
|
||||||
@click="saveSettings('refresh')"
|
|
||||||
>
|
|
||||||
保存设置
|
保存设置
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="4">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
@ -113,46 +69,28 @@
|
|||||||
</template>
|
</template>
|
||||||
<v-card-title class="text-h6">字体设置</v-card-title>
|
<v-card-title class="text-h6">字体设置</v-card-title>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-text-field
|
<v-text-field v-model="settings.font.size" type="number" label="字体大小" suffix="px" variant="outlined"
|
||||||
v-model="settings.font.size"
|
density="comfortable" class="mb-4" :rules="[
|
||||||
type="number"
|
|
||||||
label="字体大小"
|
|
||||||
suffix="px"
|
|
||||||
variant="outlined"
|
|
||||||
density="comfortable"
|
|
||||||
class="mb-4"
|
|
||||||
:rules="[
|
|
||||||
v => v >= 16 || '字体大小不能小于16px',
|
v => v >= 16 || '字体大小不能小于16px',
|
||||||
v => v <= 100 || '字体大小不能大于100px'
|
v => v <= 100 || '字体大小不能大于100px'
|
||||||
]"
|
]" />
|
||||||
/>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions class="px-4 pb-4">
|
<v-card-actions class="px-4 pb-4">
|
||||||
<v-btn
|
<v-btn color="error" variant="outlined" prepend-icon="mdi-refresh" class="flex-grow-1"
|
||||||
color="error"
|
@click="resetFontSize">
|
||||||
variant="outlined"
|
|
||||||
prepend-icon="mdi-refresh"
|
|
||||||
class="flex-grow-1"
|
|
||||||
@click="resetFontSize"
|
|
||||||
>
|
|
||||||
重置
|
重置
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn color="primary" prepend-icon="mdi-content-save" class="flex-grow-1" @click="saveSettings('font')">
|
||||||
color="primary"
|
|
||||||
prepend-icon="mdi-content-save"
|
|
||||||
class="flex-grow-1"
|
|
||||||
@click="saveSettings('font')"
|
|
||||||
>
|
|
||||||
保存设置
|
保存设置
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="4">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
@ -160,45 +98,24 @@
|
|||||||
</template>
|
</template>
|
||||||
<v-card-title class="text-h6">编辑设置</v-card-title>
|
<v-card-title class="text-h6">编辑设置</v-card-title>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-switch
|
<v-switch v-model="settings.edit.autoSave" label="启用自动保存" color="primary" hide-details class="mb-4">
|
||||||
v-model="settings.edit.autoSave"
|
|
||||||
label="启用自动保存"
|
|
||||||
color="primary"
|
|
||||||
hide-details
|
|
||||||
class="mb-4"
|
|
||||||
>
|
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<v-tooltip location="right">
|
<v-tooltip location="right">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-icon
|
<v-icon v-bind="props" icon="mdi-help-circle-outline" size="small" class="ml-2" />
|
||||||
v-bind="props"
|
|
||||||
icon="mdi-help-circle-outline"
|
|
||||||
size="small"
|
|
||||||
class="ml-2"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
编辑完成后自动上传到服务器
|
编辑完成后自动上传到服务器
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-switch>
|
</v-switch>
|
||||||
|
|
||||||
<v-switch
|
<v-switch v-model="settings.edit.refreshBeforeEdit" label="编辑前自动刷新" color="primary" hide-details>
|
||||||
v-model="settings.edit.refreshBeforeEdit"
|
|
||||||
label="编辑前自动刷新"
|
|
||||||
color="primary"
|
|
||||||
hide-details
|
|
||||||
>
|
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<v-tooltip location="right">
|
<v-tooltip location="right">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-icon
|
<v-icon v-bind="props" icon="mdi-help-circle-outline" size="small" class="ml-2" />
|
||||||
v-bind="props"
|
|
||||||
icon="mdi-help-circle-outline"
|
|
||||||
size="small"
|
|
||||||
class="ml-2"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
打开编辑框前自动从服务器获取最新数据
|
打开编辑框前自动从服务器获取最新数据
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
@ -207,117 +124,76 @@
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions class="px-4 pb-4">
|
<v-card-actions class="px-4 pb-4">
|
||||||
<v-btn
|
<v-btn color="primary" prepend-icon="mdi-content-save" block @click="saveSettings('edit')">
|
||||||
color="primary"
|
|
||||||
prepend-icon="mdi-content-save"
|
|
||||||
block
|
|
||||||
@click="saveSettings('edit')"
|
|
||||||
>
|
|
||||||
保存设置
|
保存设置
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col> <v-col cols="12" md="6">
|
</v-col> <v-col cols="12" md="4">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-icon icon="mdi-card-outline" size="large" class="mr-2" />
|
<v-icon icon="mdi-card-outline" size="large" class="mr-2" />
|
||||||
</template>
|
|
||||||
<v-card-title class="text-h6">显示设置</v-card-title>
|
|
||||||
</v-card-item>
|
|
||||||
|
|
||||||
<v-card-text>
|
|
||||||
<v-switch
|
|
||||||
v-model="settings.display.dynamicSort"
|
|
||||||
label="启用动态排序"
|
|
||||||
hint="动态排序会根据内容长度自动调整卡片位置以优化显示效果"
|
|
||||||
persistent-hint
|
|
||||||
class="mb-4"
|
|
||||||
@change="saveSettings('display')"
|
|
||||||
>
|
|
||||||
<template v-slot:append>
|
|
||||||
<v-tooltip location="right">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-icon
|
|
||||||
v-bind="props"
|
|
||||||
icon="mdi-help-circle-outline"
|
|
||||||
size="small"
|
|
||||||
class="ml-2"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<div>
|
|
||||||
<p>启用:根据内容长度动态调整位置</p>
|
|
||||||
<p>关闭:按语数英/物化生/政史地固定排列</p>
|
|
||||||
</div>
|
|
||||||
</v-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
</v-switch>
|
<v-card-title class="text-h6">显示设置</v-card-title>
|
||||||
|
</v-card-item>
|
||||||
|
|
||||||
<v-divider class="my-4" />
|
<v-card-text>
|
||||||
|
<v-switch v-model="settings.display.dynamicSort" label="启用动态排序" hint="动态排序会根据内容长度自动调整卡片位置以优化显示效果"
|
||||||
<v-radio-group
|
persistent-hint class="mb-4" @change="saveSettings('display')">
|
||||||
v-model="settings.display.emptySubjectDisplay"
|
<template v-slot:append>
|
||||||
label="空作业显示方式"
|
<v-tooltip location="right">
|
||||||
class="mt-4"
|
<template v-slot:activator="{ props }">
|
||||||
@change="saveSettings('display')"
|
<v-icon v-bind="props" icon="mdi-help-circle-outline" size="small" class="ml-2" />
|
||||||
>
|
</template>
|
||||||
<v-radio
|
<div>
|
||||||
value="card"
|
<p>启用:根据内容长度动态调整位置</p>
|
||||||
label="显示为空卡片"
|
<p>关闭:按语数英/物化生/政史地固定排列</p>
|
||||||
>
|
</div>
|
||||||
<template v-slot:label>
|
</v-tooltip>
|
||||||
<div class="d-flex align-center">
|
|
||||||
显示为空卡片
|
|
||||||
<v-tooltip location="right">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-icon
|
|
||||||
v-bind="props"
|
|
||||||
icon="mdi-help-circle-outline"
|
|
||||||
size="small"
|
|
||||||
class="ml-2"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
在主界面中显示为可点击的空白卡片
|
|
||||||
</v-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</v-radio>
|
</v-switch>
|
||||||
<v-radio
|
|
||||||
value="button"
|
|
||||||
label="显示为按钮组"
|
|
||||||
>
|
|
||||||
<template v-slot:label>
|
|
||||||
<div class="d-flex align-center">
|
|
||||||
显示为按钮组
|
|
||||||
<v-tooltip location="right">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-icon
|
|
||||||
v-bind="props"
|
|
||||||
icon="mdi-help-circle-outline"
|
|
||||||
size="small"
|
|
||||||
class="ml-2"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
在主界面底部显示为一组添加按钮
|
|
||||||
</v-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</v-radio>
|
|
||||||
</v-radio-group>
|
|
||||||
</v-card-text>
|
|
||||||
|
|
||||||
<v-card-actions class="px-4 pb-4">
|
<v-divider class="my-4" />
|
||||||
<v-btn
|
|
||||||
color="primary"
|
<v-radio-group v-model="settings.display.emptySubjectDisplay" label="空作业显示方式" class="mt-4"
|
||||||
prepend-icon="mdi-content-save"
|
@change="saveSettings('display')">
|
||||||
block
|
<v-radio value="card" label="显示为空卡片">
|
||||||
@click="saveSettings('display')"
|
<template v-slot:label>
|
||||||
>
|
<div class="d-flex align-center">
|
||||||
保存设置
|
显示为空卡片
|
||||||
</v-btn>
|
<v-tooltip location="right">
|
||||||
</v-card-actions>
|
<template v-slot:activator="{ props }">
|
||||||
</v-card>
|
<v-icon v-bind="props" icon="mdi-help-circle-outline" size="small" class="ml-2" />
|
||||||
</v-col>
|
</template>
|
||||||
|
在主界面中显示为可点击的空白卡片
|
||||||
|
</v-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-radio>
|
||||||
|
<v-radio value="button" label="显示为按钮组">
|
||||||
|
<template v-slot:label>
|
||||||
|
<div class="d-flex align-center">
|
||||||
|
显示为按钮组
|
||||||
|
<v-tooltip location="right">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-icon v-bind="props" icon="mdi-help-circle-outline" size="small" class="ml-2" />
|
||||||
|
</template>
|
||||||
|
在主界面底部显示为一组添加按钮
|
||||||
|
</v-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-radio>
|
||||||
|
</v-radio-group>
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
|
<v-card-actions class="px-4 pb-4">
|
||||||
|
<v-btn color="primary" prepend-icon="mdi-content-save" block @click="saveSettings('display')">
|
||||||
|
保存设置
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<v-card elevation="2" class="rounded-lg">
|
<v-card elevation="2" class="rounded-lg">
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
@ -326,32 +202,17 @@
|
|||||||
</template>
|
</template>
|
||||||
<v-card-title class="text-h6">学生列表设置</v-card-title>
|
<v-card-title class="text-h6">学生列表设置</v-card-title>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<v-btn
|
<v-btn :color="showAdvancedEdit ? 'primary' : undefined" variant="text" prepend-icon="mdi-code-braces"
|
||||||
:color="showAdvancedEdit ? 'primary' : undefined"
|
@click="showAdvancedEdit = !showAdvancedEdit">
|
||||||
variant="text"
|
|
||||||
prepend-icon="mdi-code-braces"
|
|
||||||
@click="showAdvancedEdit = !showAdvancedEdit"
|
|
||||||
>
|
|
||||||
{{ showAdvancedEdit ? '返回基础编辑' : '高级编辑' }}
|
{{ showAdvancedEdit ? '返回基础编辑' : '高级编辑' }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-progress-linear
|
<v-progress-linear v-if="studentsLoading" indeterminate color="primary" class="mb-4" />
|
||||||
v-if="studentsLoading"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
class="mb-4"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<v-alert
|
<v-alert v-if="studentsError" type="error" variant="tonal" closable class="mb-4">
|
||||||
v-if="studentsError"
|
|
||||||
type="error"
|
|
||||||
variant="tonal"
|
|
||||||
closable
|
|
||||||
class="mb-4"
|
|
||||||
>
|
|
||||||
{{ studentsError }}
|
{{ studentsError }}
|
||||||
</v-alert>
|
</v-alert>
|
||||||
|
|
||||||
@ -359,137 +220,68 @@
|
|||||||
<div v-if="!showAdvancedEdit">
|
<div v-if="!showAdvancedEdit">
|
||||||
<v-row class="mb-6">
|
<v-row class="mb-6">
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-text-field
|
<v-text-field v-model="newStudent" label="添加学生" placeholder="输入学生姓名后回车添加"
|
||||||
v-model="newStudent"
|
prepend-inner-icon="mdi-account-plus" variant="outlined" hide-details @keyup.enter="addStudent">
|
||||||
label="添加学生"
|
|
||||||
placeholder="输入学生姓名后回车添加"
|
|
||||||
prepend-inner-icon="mdi-account-plus"
|
|
||||||
variant="outlined"
|
|
||||||
hide-details
|
|
||||||
@keyup.enter="addStudent"
|
|
||||||
>
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-btn
|
<v-btn icon="mdi-plus" variant="text" color="primary" :disabled="!newStudent.trim()"
|
||||||
icon="mdi-plus"
|
@click="addStudent" />
|
||||||
variant="text"
|
|
||||||
color="primary"
|
|
||||||
:disabled="!newStudent.trim()"
|
|
||||||
@click="addStudent"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col
|
<v-col v-for="(student, index) in studentsList" :key="index" cols="12" sm="6" md="4" lg="3">
|
||||||
v-for="(student, index) in studentsList"
|
|
||||||
:key="index"
|
|
||||||
cols="12"
|
|
||||||
sm="6"
|
|
||||||
md="4"
|
|
||||||
lg="3"
|
|
||||||
>
|
|
||||||
<v-hover v-slot="{ isHovering, props }">
|
<v-hover v-slot="{ isHovering, props }">
|
||||||
<v-card
|
<v-card v-bind="props" :elevation="isMobile ? 1 : (isHovering ? 4 : 1)" :class="[
|
||||||
v-bind="props"
|
'student-card',
|
||||||
:elevation="isMobile ? 1 : (isHovering ? 4 : 1)"
|
{
|
||||||
:class="[
|
'bg-primary-subtle': isHovering && !isMobile,
|
||||||
'student-card',
|
'mobile': isMobile
|
||||||
{
|
}
|
||||||
'bg-primary-subtle': isHovering && !isMobile,
|
]" border>
|
||||||
'mobile': isMobile
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
border
|
|
||||||
>
|
|
||||||
<v-card-text class="d-flex align-center pa-3">
|
<v-card-text class="d-flex align-center pa-3">
|
||||||
<v-menu
|
<v-menu location="bottom" :open-on-hover="!isMobile" :open-on-long-press="isMobile">
|
||||||
location="bottom"
|
|
||||||
:open-on-hover="!isMobile"
|
|
||||||
:open-on-long-press="isMobile"
|
|
||||||
>
|
|
||||||
<template v-slot:activator="{ props: menuProps }">
|
<template v-slot:activator="{ props: menuProps }">
|
||||||
<v-btn
|
<v-btn variant="tonal" size="small" class="mr-3 font-weight-medium" v-bind="menuProps">
|
||||||
variant="tonal"
|
|
||||||
size="small"
|
|
||||||
class="mr-3 font-weight-medium"
|
|
||||||
v-bind="menuProps"
|
|
||||||
>
|
|
||||||
{{ index + 1 }}
|
{{ index + 1 }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-list density="compact" nav>
|
<v-list density="compact" nav>
|
||||||
<v-list-item
|
<v-list-item prepend-icon="mdi-arrow-up-bold" :disabled="index === 0"
|
||||||
prepend-icon="mdi-arrow-up-bold"
|
@click="moveToTop(index)">
|
||||||
:disabled="index === 0"
|
|
||||||
@click="moveToTop(index)"
|
|
||||||
>
|
|
||||||
置顶
|
置顶
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-list-item
|
<v-list-item prepend-icon="mdi-arrow-up" :disabled="index === 0"
|
||||||
prepend-icon="mdi-arrow-up"
|
@click="moveStudent(index, 'up')">
|
||||||
:disabled="index === 0"
|
|
||||||
@click="moveStudent(index, 'up')"
|
|
||||||
>
|
|
||||||
上移
|
上移
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item
|
<v-list-item prepend-icon="mdi-arrow-down" :disabled="index === studentsList.length - 1"
|
||||||
prepend-icon="mdi-arrow-down"
|
@click="moveStudent(index, 'down')">
|
||||||
:disabled="index === studentsList.length - 1"
|
|
||||||
@click="moveStudent(index, 'down')"
|
|
||||||
>
|
|
||||||
下移
|
下移
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-list-item
|
<v-list-item prepend-icon="mdi-format-list-numbered" @click="setStudentNumber(index)">
|
||||||
prepend-icon="mdi-format-list-numbered"
|
|
||||||
@click="setStudentNumber(index)"
|
|
||||||
>
|
|
||||||
设置序号
|
设置序号
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
|
|
||||||
<v-text-field
|
<v-text-field v-if="editingIndex === index" v-model="editingName" density="compact"
|
||||||
v-if="editingIndex === index"
|
variant="underlined" hide-details class="flex-grow-1" @keyup.enter="saveEdit"
|
||||||
v-model="editingName"
|
@blur="saveEdit" autofocus />
|
||||||
density="compact"
|
<span v-else class="text-body-1 flex-grow-1"
|
||||||
variant="underlined"
|
|
||||||
hide-details
|
|
||||||
class="flex-grow-1"
|
|
||||||
@keyup.enter="saveEdit"
|
|
||||||
@blur="saveEdit"
|
|
||||||
autofocus
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
class="text-body-1 flex-grow-1"
|
|
||||||
@click="isMobile ? startEdit(index, student) : null"
|
@click="isMobile ? startEdit(index, student) : null"
|
||||||
@dblclick="!isMobile ? startEdit(index, student) : null"
|
@dblclick="!isMobile ? startEdit(index, student) : null">
|
||||||
>
|
|
||||||
{{ student }}
|
{{ student }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div
|
<div class="d-flex gap-1 action-buttons" :class="{ 'opacity-100': isHovering || isMobile }">
|
||||||
class="d-flex gap-1 action-buttons"
|
<v-btn icon="mdi-pencil" variant="text" color="primary" size="small"
|
||||||
:class="{'opacity-100': isHovering || isMobile}"
|
@click="startEdit(index, student)" />
|
||||||
>
|
<v-btn icon="mdi-delete" variant="text" color="error" size="small"
|
||||||
<v-btn
|
@click="confirmDelete(index)" />
|
||||||
icon="mdi-pencil"
|
|
||||||
variant="text"
|
|
||||||
color="primary"
|
|
||||||
size="small"
|
|
||||||
@click="startEdit(index, student)"
|
|
||||||
/>
|
|
||||||
<v-btn
|
|
||||||
icon="mdi-delete"
|
|
||||||
variant="text"
|
|
||||||
color="error"
|
|
||||||
size="small"
|
|
||||||
@click="confirmDelete(index)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
@ -501,39 +293,19 @@
|
|||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
<div v-if="showAdvancedEdit" class="pt-2">
|
<div v-if="showAdvancedEdit" class="pt-2">
|
||||||
<v-textarea
|
<v-textarea v-model="students" label="批量编辑学生列表" placeholder="每行输入一个学生姓名" hint="使用文本编辑模式批量编辑学生名单"
|
||||||
v-model="students"
|
persistent-hint variant="outlined" rows="10" />
|
||||||
label="批量编辑学生列表"
|
|
||||||
placeholder="每行输入一个学生姓名"
|
|
||||||
hint="使用文本编辑模式批量编辑学生名单"
|
|
||||||
persistent-hint
|
|
||||||
variant="outlined"
|
|
||||||
rows="10"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</v-expand-transition>
|
</v-expand-transition>
|
||||||
|
|
||||||
<v-row class="mt-6">
|
<v-row class="mt-6">
|
||||||
<v-col cols="12" class="d-flex gap-2">
|
<v-col cols="12" class="d-flex gap-2">
|
||||||
<v-btn
|
<v-btn color="primary" prepend-icon="mdi-content-save" size="large" :loading="studentsLoading"
|
||||||
color="primary"
|
:disabled="studentsLoading" @click="saveStudents">
|
||||||
prepend-icon="mdi-content-save"
|
|
||||||
size="large"
|
|
||||||
:loading="studentsLoading"
|
|
||||||
:disabled="studentsLoading"
|
|
||||||
@click="saveStudents"
|
|
||||||
>
|
|
||||||
保存学生列表
|
保存学生列表
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn color="error" variant="outlined" prepend-icon="mdi-refresh" size="large"
|
||||||
color="error"
|
:loading="studentsLoading" :disabled="studentsLoading" @click="reloadStudentList">
|
||||||
variant="outlined"
|
|
||||||
prepend-icon="mdi-refresh"
|
|
||||||
size="large"
|
|
||||||
:loading="studentsLoading"
|
|
||||||
:disabled="studentsLoading"
|
|
||||||
@click="reloadStudentList"
|
|
||||||
>
|
|
||||||
重置列表
|
重置列表
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
@ -554,45 +326,25 @@
|
|||||||
<v-row justify="center" align="center">
|
<v-row justify="center" align="center">
|
||||||
<v-col cols="12" md="8" class="text-center">
|
<v-col cols="12" md="8" class="text-center">
|
||||||
<v-avatar size="120" class="mb-4">
|
<v-avatar size="120" class="mb-4">
|
||||||
<v-img
|
<v-img src="https://avatars.githubusercontent.com/u/88357633?v=4" alt="作者头像" />
|
||||||
src="https://avatars.githubusercontent.com/u/88357633?v=4"
|
|
||||||
alt="作者头像"
|
|
||||||
/>
|
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
<h2 class="text-h5 mb-2">HomeworkPage</h2>
|
<h2 class="text-h5 mb-2">HomeworkPage</h2>
|
||||||
<p class="text-body-1 mb-4">
|
<p class="text-body-1 mb-4">
|
||||||
由 <a
|
由 <a href="https://github.com/sunwuyuan" target="_blank"
|
||||||
href="https://github.com/sunwuyuan"
|
class="text-decoration-none font-weight-medium">Sunwuyuan</a> 开发
|
||||||
target="_blank"
|
|
||||||
class="text-decoration-none font-weight-medium"
|
|
||||||
>Sunwuyuan</a> 开发
|
|
||||||
</p>
|
</p>
|
||||||
<div class="d-flex justify-center gap-2 flex-wrap">
|
<div class="d-flex justify-center gap-2 flex-wrap">
|
||||||
<v-btn
|
<v-btn color="primary" variant="outlined" href="https://github.com/SunWuyuan/homeworkpage-frontend"
|
||||||
color="primary"
|
target="_blank" prepend-icon="mdi-github">
|
||||||
variant="outlined"
|
|
||||||
href="https://github.com/SunWuyuan/homeworkpage-frontend"
|
|
||||||
target="_blank"
|
|
||||||
prepend-icon="mdi-github"
|
|
||||||
>
|
|
||||||
前端 GitHub
|
前端 GitHub
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn color="primary" variant="outlined" href="https://github.com/SunWuyuan/homeworkpage-backend"
|
||||||
color="primary"
|
target="_blank" prepend-icon="mdi-github">
|
||||||
variant="outlined"
|
|
||||||
href="https://github.com/SunWuyuan/homeworkpage-backend"
|
|
||||||
target="_blank"
|
|
||||||
prepend-icon="mdi-github"
|
|
||||||
>
|
|
||||||
后端 GitHub
|
后端 GitHub
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn color="primary" variant="outlined"
|
||||||
color="primary"
|
href="https://github.com/SunWuyuan/homeworkpage-backend/issues" target="_blank"
|
||||||
variant="outlined"
|
prepend-icon="mdi-bug">
|
||||||
href="https://github.com/SunWuyuan/homeworkpage-backend/issues"
|
|
||||||
target="_blank"
|
|
||||||
prepend-icon="mdi-bug"
|
|
||||||
>
|
|
||||||
报告问题
|
报告问题
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
@ -622,11 +374,7 @@
|
|||||||
<v-btn color="primary" variant="text" @click="deleteDialog = false">
|
<v-btn color="primary" variant="text" @click="deleteDialog = false">
|
||||||
取消
|
取消
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn color="error" variant="text" @click="removeStudent(studentToDelete?.index)">
|
||||||
color="error"
|
|
||||||
variant="text"
|
|
||||||
@click="removeStudent(studentToDelete?.index)"
|
|
||||||
>
|
|
||||||
删除
|
删除
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -637,17 +385,11 @@
|
|||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>设置序号</v-card-title>
|
<v-card-title>设置序号</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-text-field
|
<v-text-field v-model="newPosition" type="number" label="新序号" :rules="[
|
||||||
v-model="newPosition"
|
v => !!v || '序号不能为空',
|
||||||
type="number"
|
v => v > 0 || '序号必须大于0',
|
||||||
label="新序号"
|
v => v <= studentsList.length || `序号不能大于${studentsList.length}`
|
||||||
:rules="[
|
]" @keyup.enter="applyNewPosition" />
|
||||||
v => !!v || '序号不能为空',
|
|
||||||
v => v > 0 || '序号必须大于0',
|
|
||||||
v => v <= studentsList.length || `序号不能大于${studentsList.length}`
|
|
||||||
]"
|
|
||||||
@keyup.enter="applyNewPosition"
|
|
||||||
/>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
@ -665,7 +407,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useDisplay } from 'vuetify';
|
import { useDisplay } from 'vuetify';
|
||||||
import {
|
import {
|
||||||
getSetting,
|
getSetting,
|
||||||
setSetting,
|
setSetting,
|
||||||
resetSetting,
|
resetSetting,
|
||||||
@ -720,7 +462,7 @@ export default {
|
|||||||
studentsError: null,
|
studentsError: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadAllSettings();
|
this.loadAllSettings();
|
||||||
this.unwatchSettings = watchSettings(() => {
|
this.unwatchSettings = watchSettings(() => {
|
||||||
@ -810,7 +552,7 @@ export default {
|
|||||||
|
|
||||||
const domain = getSetting('server.domain');
|
const domain = getSetting('server.domain');
|
||||||
const classNum = getSetting('server.classNumber');
|
const classNum = getSetting('server.classNumber');
|
||||||
|
|
||||||
if (!domain || !classNum) {
|
if (!domain || !classNum) {
|
||||||
throw new Error('请先设置服务器域名和班号');
|
throw new Error('请先设置服务器域名和班号');
|
||||||
}
|
}
|
||||||
@ -835,7 +577,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const domain = getSetting('server.domain');
|
const domain = getSetting('server.domain');
|
||||||
const classNum = getSetting('server.classNumber');
|
const classNum = getSetting('server.classNumber');
|
||||||
|
|
||||||
if (!domain || !classNum) {
|
if (!domain || !classNum) {
|
||||||
throw new Error('请先设置服务器域名和班号');
|
throw new Error('请先设置服务器域名和班号');
|
||||||
}
|
}
|
||||||
@ -871,7 +613,7 @@ export default {
|
|||||||
if (this.editingIndex !== -1 && this.editingIndex !== index) {
|
if (this.editingIndex !== -1 && this.editingIndex !== index) {
|
||||||
this.saveEdit();
|
this.saveEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.editingIndex = index;
|
this.editingIndex = index;
|
||||||
this.editingName = name;
|
this.editingName = name;
|
||||||
},
|
},
|
||||||
@ -901,9 +643,9 @@ export default {
|
|||||||
moveStudent(index, direction) {
|
moveStudent(index, direction) {
|
||||||
const newIndex = direction === 'up' ? index - 1 : index + 1;
|
const newIndex = direction === 'up' ? index - 1 : index + 1;
|
||||||
if (newIndex >= 0 && newIndex < this.studentsList.length) {
|
if (newIndex >= 0 && newIndex < this.studentsList.length) {
|
||||||
[this.studentsList[index], this.studentsList[newIndex]] =
|
[this.studentsList[index], this.studentsList[newIndex]] =
|
||||||
[this.studentsList[newIndex], this.studentsList[index]];
|
[this.studentsList[newIndex], this.studentsList[index]];
|
||||||
|
|
||||||
if (this.settings.edit.autoSave) {
|
if (this.settings.edit.autoSave) {
|
||||||
this.saveStudents();
|
this.saveStudents();
|
||||||
}
|
}
|
||||||
@ -939,7 +681,7 @@ export default {
|
|||||||
const student = this.studentsList[index];
|
const student = this.studentsList[index];
|
||||||
this.studentsList.splice(index, 1);
|
this.studentsList.splice(index, 1);
|
||||||
this.studentsList.unshift(student);
|
this.studentsList.unshift(student);
|
||||||
|
|
||||||
if (this.settings.edit.autoSave) {
|
if (this.settings.edit.autoSave) {
|
||||||
this.saveStudents();
|
this.saveStudents();
|
||||||
}
|
}
|
||||||
@ -1006,7 +748,7 @@ export default {
|
|||||||
.v-container {
|
.v-container {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-col {
|
.v-col {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
@ -1029,11 +771,11 @@ export default {
|
|||||||
.v-col {
|
.v-col {
|
||||||
padding: 6px !important;
|
padding: 6px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.student-card {
|
.student-card {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@ -1046,4 +788,4 @@ export default {
|
|||||||
.student-card:active {
|
.student-card:active {
|
||||||
background-color: rgb(var(--v-theme-primary), 0.05);
|
background-color: rgb(var(--v-theme-primary), 0.05);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -72,12 +72,12 @@ const settingsDefinitions = {
|
|||||||
// 编辑设置
|
// 编辑设置
|
||||||
'edit.autoSave': {
|
'edit.autoSave': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: true,
|
||||||
description: '是否启用自动保存'
|
description: '是否启用自动保存'
|
||||||
},
|
},
|
||||||
'edit.refreshBeforeEdit': {
|
'edit.refreshBeforeEdit': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: true,
|
||||||
description: '编辑前是否自动刷新'
|
description: '编辑前是否自动刷新'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user