|
@@ -104,6 +104,29 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <div v-if="visible_import" class="modal-mask" @click.self="isloading_import || (visible_import=false)" >
|
|
|
|
|
+ <div class="modal-container">
|
|
|
|
|
+ <div class="modal-body">
|
|
|
|
|
+ <div class="import-result">
|
|
|
|
|
+ <h2>{{isloading_import?"导入中...":`成功${successImport}条,失败${failedImport}条,跳过${skippedImport}条,共${totalImport}条`}}</h2>
|
|
|
|
|
+ <div v-if="failedName.length>0">
|
|
|
|
|
+ <h4>失败学生名单:</h4>
|
|
|
|
|
+ <div v-for="(name,index) in failedName" :key="index">
|
|
|
|
|
+ {{ name }},学号:{{ failedOfficialNumber[index] }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="skippedName.length>0">
|
|
|
|
|
+ <h4>跳过学生名单:</h4>
|
|
|
|
|
+ <div v-for="(name,index) in skippedName" :key="index">
|
|
|
|
|
+ {{ name }},学号:{{ skippedOfficialNumber[index] }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style="height: 15px;"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div v-if="visible_add" class="modal-mask" @click.self="isloading_add || (visible_add=false)" >
|
|
<div v-if="visible_add" class="modal-mask" @click.self="isloading_add || (visible_add=false)" >
|
|
|
<div class="modal-container">
|
|
<div class="modal-container">
|
|
|
<div class="add1" v-show="!isloading_add">
|
|
<div class="add1" v-show="!isloading_add">
|
|
@@ -112,6 +135,9 @@
|
|
|
<div class="add1" v-show="!isloading_add">
|
|
<div class="add1" v-show="!isloading_add">
|
|
|
<h2>学生学号:</h2> <input type="text" v-model.trim="addOfficalNumber" ></input>
|
|
<h2>学生学号:</h2> <input type="text" v-model.trim="addOfficalNumber" ></input>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div class="add1" v-show="!isloading_add">
|
|
|
|
|
+ <h2>电话号码:</h2> <input type="text" v-model.trim="addPhoneNumber" ></input>
|
|
|
|
|
+ </div>
|
|
|
<div class="add1" v-show="isloading_add"
|
|
<div class="add1" v-show="isloading_add"
|
|
|
:style="{'height': '66%', 'margin-left':'210px'}">
|
|
:style="{'height': '66%', 'margin-left':'210px'}">
|
|
|
<h2>上传中...</h2>
|
|
<h2>上传中...</h2>
|
|
@@ -132,6 +158,8 @@ import { useRoute } from 'vue-router';
|
|
|
import type {ClassStudentVO} from "@/types/vo";
|
|
import type {ClassStudentVO} from "@/types/vo";
|
|
|
import useApis from "@/apis";
|
|
import useApis from "@/apis";
|
|
|
import { get } from 'http';
|
|
import { get } from 'http';
|
|
|
|
|
+import { log } from 'console';
|
|
|
|
|
+import { fail } from 'assert';
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
const route = useRoute()
|
|
|
const apis = useApis()
|
|
const apis = useApis()
|
|
@@ -142,15 +170,26 @@ const currentPage = ref(1)
|
|
|
const searchInput = ref("")
|
|
const searchInput = ref("")
|
|
|
const visible_add = ref(false)
|
|
const visible_add = ref(false)
|
|
|
const visible_del = ref(false)
|
|
const visible_del = ref(false)
|
|
|
|
|
+const visible_import = ref(false)
|
|
|
const isloading = ref(false)
|
|
const isloading = ref(false)
|
|
|
|
|
+const isloading_import = ref(false)
|
|
|
const isloading_add = ref(false)
|
|
const isloading_add = ref(false)
|
|
|
const addStudentName = ref("")
|
|
const addStudentName = ref("")
|
|
|
const addOfficalNumber = ref("")
|
|
const addOfficalNumber = ref("")
|
|
|
|
|
+const addPhoneNumber = ref("")
|
|
|
const deleteId = ref(-1)
|
|
const deleteId = ref(-1)
|
|
|
const deleteIds = ref<number[]>([])
|
|
const deleteIds = ref<number[]>([])
|
|
|
const deleteName = ref("")
|
|
const deleteName = ref("")
|
|
|
const hoverStuId = ref(-1)
|
|
const hoverStuId = ref(-1)
|
|
|
const isSingleDelete = ref(true)
|
|
const isSingleDelete = ref(true)
|
|
|
|
|
+let totalImport = 0
|
|
|
|
|
+let successImport = 0
|
|
|
|
|
+let failedImport = 0
|
|
|
|
|
+let skippedImport = 0
|
|
|
|
|
+let failedName = []
|
|
|
|
|
+let failedOfficialNumber = []
|
|
|
|
|
+let skippedName = []
|
|
|
|
|
+let skippedOfficialNumber = []
|
|
|
|
|
|
|
|
const StudentsDataLoading = ref(false)
|
|
const StudentsDataLoading = ref(false)
|
|
|
|
|
|
|
@@ -164,7 +203,7 @@ const handleDelete = (sid) => {
|
|
|
}).stuName
|
|
}).stuName
|
|
|
}
|
|
}
|
|
|
const importData = async () => {
|
|
const importData = async () => {
|
|
|
- console.log("importData");
|
|
|
|
|
|
|
+ // console.log("importData");
|
|
|
const input = document.createElement('input')
|
|
const input = document.createElement('input')
|
|
|
input.type = 'file'
|
|
input.type = 'file'
|
|
|
input.accept = '.xlsx,.xls,.csv'
|
|
input.accept = '.xlsx,.xls,.csv'
|
|
@@ -177,8 +216,33 @@ const importData = async () => {
|
|
|
}
|
|
}
|
|
|
isloading_add.value = true
|
|
isloading_add.value = true
|
|
|
try {
|
|
try {
|
|
|
|
|
+ isloading_import.value = true
|
|
|
|
|
+ visible_import.value = true
|
|
|
|
|
+ failedName = []
|
|
|
|
|
+ failedOfficialNumber = []
|
|
|
|
|
+ skippedName = []
|
|
|
|
|
+ skippedOfficialNumber = []
|
|
|
const res = await apis.importStudentsOfClass(classId, selectedFile)
|
|
const res = await apis.importStudentsOfClass(classId, selectedFile)
|
|
|
|
|
+ totalImport= res.data.data.total
|
|
|
|
|
+ successImport = res.data.data.successCount
|
|
|
|
|
+ failedImport = res.data.data.failedCount
|
|
|
|
|
+ skippedImport = res.data.data.skippedCount
|
|
|
|
|
+ isloading_import.value = false
|
|
|
console.log('Import response:', res)
|
|
console.log('Import response:', res)
|
|
|
|
|
+ // res.data.data.failedCount/skippedCount/successCount/total 弹窗提示总数据:成功多少条,失败多少条,跳过多少条
|
|
|
|
|
+ // alert(`总数据:${res.data.data.total},成功${res.data.data.successCount}条,失败${res.data.data.failedCount}条,跳过${res.data.data.skippedCount}条`)
|
|
|
|
|
+ // res.data.data.details 是每个学生的导入详情,其中status为状态,FAILED为失败,SUCCESS为成功,SKIPPED为跳过
|
|
|
|
|
+ // foreach遍历,将失败的学生的姓名stuName和学号officialNumber展示到弹窗中
|
|
|
|
|
+ res.data.data.details.forEach((item) => {
|
|
|
|
|
+ if (item.status === 'FAILED') {
|
|
|
|
|
+ failedName.push(item.stuName)
|
|
|
|
|
+ failedOfficialNumber.push(item.officialNumber)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (item.status === 'SKIPPED') {
|
|
|
|
|
+ skippedName.push(item.stuName)
|
|
|
|
|
+ skippedOfficialNumber.push(item.officialNumber)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
getStudents()
|
|
getStudents()
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('Import failed:', error)
|
|
console.error('Import failed:', error)
|
|
@@ -210,10 +274,10 @@ const DeleteStudents = async () => {
|
|
|
}
|
|
}
|
|
|
const AddStudent = async () => {
|
|
const AddStudent = async () => {
|
|
|
isloading_add.value = true
|
|
isloading_add.value = true
|
|
|
- console.log(addStudentName.value)
|
|
|
|
|
- console.log(+addOfficalNumber.value)
|
|
|
|
|
|
|
+ console.log(+addOfficalNumber.value,addStudentName.value,addPhoneNumber.value)
|
|
|
console.log(classId);
|
|
console.log(classId);
|
|
|
- await apis.addStudentOfClasss(classId,+addOfficalNumber.value)
|
|
|
|
|
|
|
+ const res = await apis.addStudentOfClasss(classId,+addOfficalNumber.value,addStudentName.value,addPhoneNumber.value)
|
|
|
|
|
+ console.log('添加学生反馈',res)
|
|
|
isloading_add.value = false
|
|
isloading_add.value = false
|
|
|
visible_add.value=false
|
|
visible_add.value=false
|
|
|
addStudentName.value = ""
|
|
addStudentName.value = ""
|
|
@@ -444,6 +508,28 @@ input[type="checkbox"]:checked {
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
color:#70bbdb
|
|
color:#70bbdb
|
|
|
}
|
|
}
|
|
|
|
|
+ .modal-body {
|
|
|
|
|
+ padding: 16px 20px;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ color:#70bbdb;
|
|
|
|
|
+ .import-result {
|
|
|
|
|
+ /* 可滚动 */
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ /* 隐藏滚动条 */
|
|
|
|
|
+ -ms-overflow-style: none;
|
|
|
|
|
+ scrollbar-width: none;
|
|
|
|
|
+ /* 划到最底下但最底下的被遮盖住了一大部分 */
|
|
|
|
|
+ ::-webkit-scrollbar {
|
|
|
|
|
+ display: none;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
.modal-footer {
|
|
.modal-footer {
|
|
|
padding: 12px 20px;
|
|
padding: 12px 20px;
|
|
|
height: 50%;
|
|
height: 50%;
|