Commit 0454f787a9ea7bde38cf2a28cf3e698f1e612a8c

Authored by 梁保满
1 parent 0ca11cc2

班级管理,班级列表修改,科目设置

package.json
... ... @@ -21,7 +21,8 @@
21 21 "vue": "^2.6.11",
22 22 "vue-i18n": "^8.4.0",
23 23 "vue-router": "^3.5.1",
24   - "vuex": "^3.6.2"
  24 + "vuex": "^3.6.2",
  25 + "vuedraggable": "^2.24.3"
25 26 },
26 27 "devDependencies": {
27 28 "@vue/cli-plugin-babel": "~4.5.0",
... ...
src/api/apis/apis.js
... ... @@ -1425,8 +1425,6 @@ export default {
1425 1425 data,
1426 1426 });
1427 1427 },
1428   -
1429   -
1430 1428 //修改密码
1431 1429 changePwd(data) {
1432 1430 return service({
... ... @@ -1435,4 +1433,39 @@ export default {
1435 1433 data,
1436 1434 });
1437 1435 },
  1436 + /**
  1437 + * v1.4
  1438 + */
  1439 + //班级管理
  1440 + classManager(data) {
  1441 + return service({
  1442 + url: setUpUrls.classManager,
  1443 + method: "POST",
  1444 + data,
  1445 + });
  1446 + },
  1447 + //班级排序
  1448 + classSort(data) {
  1449 + return service({
  1450 + url: setUpUrls.classSort,
  1451 + method: "POST",
  1452 + data,
  1453 + });
  1454 + },
  1455 + //学生分班轨迹
  1456 + studentClassLogs(data) {
  1457 + return service({
  1458 + url: setUpUrls.studentClassLogs,
  1459 + method: "POST",
  1460 + data,
  1461 + });
  1462 + },
  1463 + //修改科目
  1464 + updateSubject(data) {
  1465 + return service({
  1466 + url: setUpUrls.updateSubject,
  1467 + method: "POST",
  1468 + data,
  1469 + });
  1470 + },
1438 1471 };
... ...
src/api/urls/apis.js
... ... @@ -367,4 +367,17 @@ export default {
367 367  
368 368 // 修改密码
369 369 changePwd: "/api_html/changePwd",
  370 +
  371 +
  372 + /**
  373 + * v1.4
  374 + */
  375 + //班级管理
  376 + classManager: "/api_html/school/manager/classManager",
  377 + //班级排序
  378 + classSort: "/api_html/school/manager/classSort",
  379 + //学生分班轨迹
  380 + studentClassLogs: "/api_html/school/manager/studentClassLogs",
  381 + //修改科目
  382 + updateSubject: "/api_html/school/manager/updateSubject",
370 383 }
... ...
src/router/index.js
... ... @@ -42,6 +42,7 @@ const SetUpConglomerate = () => import("@/views/standard/setUp/conglomerate")
42 42 const SetUpSchool = () => import("@/views/standard/setUp/school")
43 43 const SetUpTeacher = () => import("@/views/standard/setUp/teacher")
44 44 const SetUpStudent = () => import("@/views/standard/setUp/student")
  45 +const SetUpClazz = () => import("@/views/standard/setUp/clazz")
45 46 const ArchivedClazz = () => import("@/views/standard/setUp/archivedClazz")
46 47  
47 48 const PersonalAsk = () => import("@/views/personal/ask/index")
... ... @@ -295,6 +296,13 @@ let addrouters = [
295 296 children: []
296 297 },
297 298 {
  299 + path: "/setUpClazz",
  300 + iconCls: "fa fa-sitemap",
  301 + name: '班级管理',
  302 + component: SetUpClazz,
  303 + children: []
  304 + },
  305 + {
298 306 path: "/setUpTeacher",
299 307 iconCls: "fa fa-male",
300 308 name: '教师管理',
... ...
src/views/standard/setUp/clazz.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <back-box>
  4 + <template slot="title">
  5 + <span>班级管理</span>
  6 + </template>
  7 + <template slot="btns" v-if="!code">
  8 + <el-tooltip effect="dark" content="导入班级名单" placement="bottom">
  9 + <el-button
  10 + type="primary"
  11 + icon="el-icon-upload2"
  12 + size="mini"
  13 + plain
  14 + circle
  15 + @click="diaUp = true"
  16 + ></el-button>
  17 + </el-tooltip>
  18 + <el-tooltip effect="dark" content="导出班级名单" placement="bottom">
  19 + <el-button
  20 + type="primary"
  21 + icon="el-icon-download"
  22 + size="mini"
  23 + plain
  24 + circle
  25 + @click="exportTeacherExl"
  26 + ></el-button>
  27 + </el-tooltip>
  28 + </template>
  29 + </back-box>
  30 + <div class="page-content">
  31 + <div class="grade-box">
  32 + <div class="grade-item" v-for="(item, index) in dataList">
  33 + <p class="h-title">
  34 + <span>{{ item.gradeName }}</span>
  35 + <el-button
  36 + class="sub-btn"
  37 + type="info"
  38 + size="mini"
  39 + round
  40 + plain
  41 + @click="openSubject(item)"
  42 + >科目管理({{ item.subjectNames.length }})</el-button
  43 + >
  44 + <span class="txt" v-if="index == 0">拖动班级进行排序</span>
  45 + </p>
  46 + <draggable
  47 + tag="ul"
  48 + class="grade-info"
  49 + v-model="item.classList"
  50 + @start="start"
  51 + @end="end(item)"
  52 + v-bind="{
  53 + animation: 300,
  54 + }"
  55 + >
  56 + <li class="clazz-li" v-for="clazz in item.classList" :key="item.id">
  57 + <div class="clazz-item">
  58 + <p class="clazz-name">
  59 + {{ clazz.className }}
  60 + <i
  61 + class="el-icon-edit"
  62 + @click.stop="setClass(clazz, item.gradeName)"
  63 + ></i>
  64 + </p>
  65 + <div class="clazz-class">
  66 + <span>学生:{{ clazz.studentCount }}个</span>
  67 + <span>教师:{{ clazz.studentCount }}个</span>
  68 + </div>
  69 + </div>
  70 + </li>
  71 + </draggable>
  72 + </div>
  73 + </div>
  74 + </div>
  75 + <el-dialog title="导入班级名单" :visible.sync="diaUp" width="600">
  76 + <up-load
  77 + id="downTeacher"
  78 + :url="url"
  79 + @upSuccess="upSuccess"
  80 + fileName="班级名单"
  81 + >
  82 + <p class="down-txt" slot="down">
  83 + 通过Excel名单导入班级名单,点击
  84 + <el-link type="danger" @click="downExcel">模板下载</el-link> 。
  85 + </p>
  86 + </up-load>
  87 + <div class="dialog-footer" slot="footer">
  88 + <el-button @click="diaUp = false">取 消</el-button>
  89 + </div>
  90 + </el-dialog>
  91 + <el-dialog title="修改班级" :visible.sync="diaClass" width="400">
  92 + <el-form
  93 + ref="formClass"
  94 + :model="formClass"
  95 + :rules="rulesClass"
  96 + label-width="160px"
  97 + >
  98 + <el-form-item label="所在年级:">
  99 + <span>{{ formClass.gradeName }}</span>
  100 + </el-form-item>
  101 + <el-form-item label="班级名称:" prop="studentName">
  102 + <el-col :span="10">
  103 + <el-input maxlength="30" v-model.trim="formClass.className" />
  104 + </el-col>
  105 + </el-form-item>
  106 + <el-form-item label="班级编码:">
  107 + <el-col :span="10">
  108 + <el-input maxlength="30" v-model.trim="formClass.classCode" />
  109 + </el-col>
  110 + </el-form-item>
  111 + <el-form-item label="入学年份:">
  112 + <el-col :span="10">
  113 + <el-date-picker
  114 + v-model="formClass.intoSchoolYear"
  115 + type="year"
  116 + placeholder="选择年"
  117 + >
  118 + </el-date-picker>
  119 + </el-col>
  120 + </el-form-item>
  121 + </el-form>
  122 + <div class="dialog-footer" slot="footer">
  123 + <el-button @click="_SaveClass" type="primary">确 定</el-button>
  124 + <el-button @click="diaClass = false">取 消</el-button>
  125 + <el-popconfirm title="确定删除该班级吗?" @confirm="_RemoveClass">
  126 + <el-button class="el-button-del" slot="reference" type="danger" plain
  127 + >删 除</el-button
  128 + >
  129 + </el-popconfirm>
  130 + </div>
  131 + </el-dialog>
  132 + <el-dialog :visible.sync="diaSubject" width="400">
  133 + <p slot="title" class="dia-tit">
  134 + {{ formClass.gradeName }}
  135 + <span class="tips">(默认科目和已经有任课老师的提示不能删除)</span>
  136 + </p>
  137 + <el-form class="form-box" label-width="80px" v-loading="loadingSub">
  138 + <el-form-item label="科目:">
  139 + <div class="subject-box">
  140 + <el-checkbox-group v-model="subjectNames">
  141 + <p
  142 + class="p1"
  143 + v-for="(item, index) in subjectList"
  144 + :key="item.default"
  145 + >
  146 + <el-checkbox v-if="!item.checked" :label="item.value">{{
  147 + item.value
  148 + }}</el-checkbox>
  149 + <el-input
  150 + class="sub-ipt"
  151 + v-else
  152 + v-model="item.value"
  153 + @keyup.enter.native="_EditSub(item)"
  154 + ></el-input>
  155 + <i
  156 + class="el-icon el-icon-edit"
  157 + v-show="!item.checked"
  158 + @click="item.checked = true"
  159 + ></i>
  160 + <i
  161 + class="el-icon el-icon-check"
  162 + v-show="item.checked"
  163 + @click="_EditSub(item)"
  164 + ></i>
  165 + <i
  166 + class="el-icon el-icon-close"
  167 + v-show="item.checked"
  168 + @click="resetSub(item)"
  169 + ></i>
  170 + <i
  171 + v-show="!item.checked"
  172 + class="el-icon el-icon-delete"
  173 + @click="_DelSubject(item, index)"
  174 + ></i>
  175 + </p>
  176 + </el-checkbox-group>
  177 + </div>
  178 + <el-col :span="8">
  179 + <el-input
  180 + placeholder="添加科目"
  181 + v-model.trim="subjectName"
  182 + maxlength="30"
  183 + >
  184 + <i
  185 + slot="suffix"
  186 + class="el-input__icon el-icon-plus"
  187 + @click="addSubjectName"
  188 + ></i>
  189 + </el-input>
  190 + </el-col>
  191 + </el-form-item>
  192 + </el-form>
  193 + <div class="dialog-footer" slot="footer">
  194 + <el-button @click="_SaveSubject" type="primary">确 定</el-button>
  195 + <el-button @click="diaSubject = false">取 消</el-button>
  196 + </div>
  197 + </el-dialog>
  198 + </div>
  199 +</template>
  200 +
  201 +<script>
  202 +import { downloadFile } from "@/utils";
  203 +import draggable from "vuedraggable";
  204 +export default {
  205 + components: {
  206 + draggable,
  207 + },
  208 + data() {
  209 + return {
  210 + code: "",
  211 + loading: false,
  212 + loadingDown: false,
  213 + loadingSub: false,
  214 + diaUp: false,
  215 + diaClass: false,
  216 + diaSubject: false,
  217 + subjectLoading: false,
  218 + url: "/api_html/school/manager/importClazzClicker",
  219 + formClass: {
  220 + //修改班级信息
  221 + gradeName: "",
  222 + className: "",
  223 + classCode: "",
  224 + intoSchoolYear: "",
  225 + },
  226 + rulesClass: {
  227 + className: [
  228 + { required: true, message: "请输入班级名称", trigger: "blur" },
  229 + ],
  230 + },
  231 + subjects: [], //科目列表(只有科目)
  232 + subjectList: [], //科目列表
  233 + subjectNames: [], //已有科目
  234 + subjectName: "", //要添加的科目
  235 + dataList: [],
  236 + };
  237 + },
  238 + async created() {
  239 + this.code = localStorage.getItem("csCode") || "";
  240 + this._QueryData();
  241 + this._QuerySubject();
  242 + },
  243 + methods: {
  244 + openSubject(obj) {
  245 + this.formClass.gradeName = obj.gradeName;
  246 + this.subjectNames = [...obj.subjectNames];
  247 + this.diaSubject = true;
  248 + },
  249 + start(e) {
  250 + console.log(e);
  251 + },
  252 + end(obj) {
  253 + let classListIds = obj.classList.map((item) => {
  254 + return item.id;
  255 + });
  256 + this._SaveComponents(classListIds);
  257 + },
  258 + upSuccess(res) {
  259 + //导入成功
  260 + this.$message.closeAll();
  261 + this.$message({
  262 + showClose: true,
  263 + message: `成功(${res.data.success})`,
  264 + type: "success",
  265 + duration: 5000,
  266 + });
  267 + this.diaUp = false;
  268 + this._QueryData();
  269 + },
  270 + setClass(obj, gradeName) {
  271 + this.formClass.gradeName = gradeName;
  272 + this.formClass.classId = obj.id;
  273 + this.formClass.className = obj.className;
  274 + this.formClass.classCode = obj.classCode || "";
  275 + this.formClass.intoSchoolYear = obj.intoSchoolYear
  276 + ? obj.intoSchoolYear + ""
  277 + : "";
  278 + this.diaClass = true;
  279 + },
  280 + _RemoveClass() {
  281 + this.$refs.formClass.validate(async (valid) => {
  282 + if (valid) {
  283 + const { data, status, info } = await this.$request.removeClass({
  284 + classId: this.formClass.classId,
  285 + });
  286 + if (status === 0) {
  287 + this.$message.success("修改成功");
  288 + this.diaClass = false;
  289 + this._QueryData();
  290 + } else {
  291 + this.$message.error(info);
  292 + }
  293 + } else {
  294 + this.$message.warning("输入有误请检查!");
  295 + return false;
  296 + }
  297 + });
  298 + },
  299 + _SaveClass() {
  300 + this.$refs.formClass.validate(async (valid) => {
  301 + if (valid) {
  302 + const { data, status, info } = await this.$request.updateClass({
  303 + classId: this.formClass.classId,
  304 + className: this.formClass.className,
  305 + intoSchoolYear: this.formClass.intoSchoolYear,
  306 + });
  307 + if (status === 0) {
  308 + this.$message.success("修改成功");
  309 + this.diaClass = false;
  310 + this._QueryData();
  311 + } else {
  312 + this.$message.error(info);
  313 + }
  314 + } else {
  315 + this.$message.warning("输入有误请检查!");
  316 + return false;
  317 + }
  318 + });
  319 + },
  320 + addSubjectName() {
  321 + //添加科目
  322 + if (!this.subjectName) {
  323 + this.$message.warning("请填写科目名称");
  324 + return;
  325 + } else if (this.subjects.includes(this.subjectName)) {
  326 + this.$message.warning("科目已存在,请重新填写~");
  327 + return;
  328 + }
  329 + this.subjectList.push({
  330 + default: this.subjectName,
  331 + value: this.subjectName,
  332 + checked: false,
  333 + });
  334 + this.subjectNames.push(this.subjectName);
  335 + this.subjectName = "";
  336 + },
  337 + resetSub(item) {
  338 + item.value = item.default;
  339 + item.checked = false;
  340 + },
  341 + async _EditSub(item) {
  342 + if (this.subjects.includes(item.value)) {
  343 + this.$message.warning("科目已存在,请重新填写~");
  344 + return;
  345 + }
  346 + item.checked = false;
  347 + const { status, info } = await this.$request.updateSubject({
  348 + subjectName: item.value,
  349 + oldSubjectName: item.default,
  350 + });
  351 + if (status === 0) {
  352 + this.$message.success(info);
  353 + let idx = this.subjectNames.findIndex(sub => item==sub)
  354 + this.subjectNames.splice(idx, 1, item.value);
  355 + item.default = item.value;
  356 + } else {
  357 + item.checked = true;
  358 + this.$message.error(info);
  359 + }
  360 + },
  361 + async _DelSubject(obj, index) {
  362 + if (this.subjectLoading) return;
  363 + this.subjectLoading = true;
  364 + const { status, info } = await this.$request.delSubject({
  365 + subjectName: obj.default,
  366 + });
  367 + this.subjectLoading = false;
  368 + if (status === 0) {
  369 + this.$message.success(info);
  370 + this.subjectList.splice(index, 1);
  371 + this._QueryData();
  372 + } else {
  373 + this.$message.error(info);
  374 + }
  375 + },
  376 + async _SaveSubject() {
  377 + //保存修改年级信息
  378 + if (!this.subjectNames.length) {
  379 + this.$message.error("请选择科目!");
  380 + return;
  381 + }
  382 + this.loadingSub = true;
  383 + const { status, info } = await this.$request.updateGrade({
  384 + gradeName: this.formClass.gradeName,
  385 + subjectNames: this.subjectNames,
  386 + });
  387 + this.loadingSub = false;
  388 + if (status === 0) {
  389 + this.$message.success("修改成功~");
  390 + this.diaSubject = false;
  391 + this._QueryData();
  392 + this._QuerySubject();
  393 + } else {
  394 + this.$message.error(info);
  395 + }
  396 + },
  397 + async _SaveComponents(classListIds) {
  398 + this.loading = true;
  399 + let { status, info } = await this.$request.classSort({
  400 + classIds: [...classListIds],
  401 + });
  402 + this.loading = false;
  403 + if (status === 0) {
  404 + this.$message.success("调整成功!");
  405 + } else {
  406 + this.$message.error(info);
  407 + }
  408 + },
  409 + async _QueryData() {
  410 + this.loading = true;
  411 + let { data, status, info } = await this.$request.classManager();
  412 + this.loading = false;
  413 + if (status === 0) {
  414 + this.dataList = [...data.list] || [];
  415 + } else {
  416 + this.$message.error(info);
  417 + }
  418 + },
  419 + async _QuerySubject() {
  420 + const { data, status, info } = await this.$request.subjectList();
  421 + if (status === 0) {
  422 + this.subjects = [...data?.subjectNames] || [];
  423 + this.subjectList =
  424 + data?.subjectNames.map((item) => {
  425 + return {
  426 + default: item,
  427 + value: item,
  428 + checked: false,
  429 + };
  430 + }) || [];
  431 + } else {
  432 + this.$message.error(info);
  433 + }
  434 + },
  435 + async downExcel() {
  436 + let data = await this.$request.teacherTemplate();
  437 + if (data && !data.code) {
  438 + let blob = new Blob([data], {
  439 + type: "application/vnd.ms-excel;charset=utf-8",
  440 + });
  441 + downloadFile(`班级名单模版.xlsx`, blob);
  442 + } else {
  443 + this.$message.error(data.info);
  444 + }
  445 + },
  446 + async exportTeacherExl() {
  447 + this.loadingDown = true;
  448 + let data = await this.$request.exportTeacher();
  449 + this.loadingDown = false;
  450 + if (data) {
  451 + let blob = new Blob([data], {
  452 + type: "application/vnd.ms-excel;charset=utf-8",
  453 + });
  454 + downloadFile(`班级名单.xlsx`, blob);
  455 + } else {
  456 + this.$message.error("下载失败");
  457 + }
  458 + },
  459 + },
  460 +};
  461 +</script>
  462 +
  463 +<style lang="scss" scoped>
  464 +.page-tit {
  465 + margin-bottom: 20px;
  466 +}
  467 +.page-content {
  468 + padding: 20px;
  469 +}
  470 +.grade-box {
  471 + background: #f8f8f8;
  472 + padding: 12px 0;
  473 +}
  474 +.el-button-del {
  475 + margin-left: 10px;
  476 +}
  477 +.h-title {
  478 + display: flex;
  479 + align-items: center;
  480 + .sub-btn {
  481 + margin-left: 30px;
  482 + }
  483 + .txt {
  484 + margin-left: 30px;
  485 + font-size: 13px;
  486 + color: #666;
  487 + }
  488 +}
  489 +.dia-tit {
  490 + .tips {
  491 + font-size: 12px;
  492 + }
  493 +}
  494 +.grade-item {
  495 + .grade-info {
  496 + display: flex;
  497 + flex-wrap: wrap;
  498 + padding: 20px 20px 0;
  499 + .clazz-li {
  500 + margin-right: 30px;
  501 + margin-bottom: 20px;
  502 + position: relative;
  503 + background: #fff;
  504 + .el-icon-edit {
  505 + cursor: pointer;
  506 + display: none;
  507 + &:hover {
  508 + color: #667ffd;
  509 + }
  510 + }
  511 + &:hover {
  512 + .el-icon-edit {
  513 + display: inline;
  514 + }
  515 + }
  516 + }
  517 +
  518 + .clazz-item {
  519 + width: 220px;
  520 + box-sizing: border-box;
  521 + padding: 16px;
  522 + border-radius: 10px;
  523 + box-shadow: 1px 1px 3px #888;
  524 + }
  525 + .clazz-name {
  526 + font-size: 16px;
  527 + font-weight: bold;
  528 + line-height: 18px;
  529 + padding-bottom: 12px;
  530 + }
  531 + .clazz-class {
  532 + display: flex;
  533 + justify-content: space-between;
  534 + font-size: 15px;
  535 + }
  536 + }
  537 +}
  538 +.subject-box {
  539 + overflow: hidden;
  540 + position: relative;
  541 + .p1 {
  542 + line-height: 20px;
  543 + margin-bottom: 10px;
  544 + }
  545 +}
  546 +:deep(.el-checkbox-group) {
  547 + display: flex;
  548 + flex-wrap: wrap;
  549 + .p1 {
  550 + padding-right: 50px;
  551 + position: relative;
  552 + &:hover {
  553 + .el-icon {
  554 + display: block;
  555 + &:hover {
  556 + color: #667ffd;
  557 + }
  558 + }
  559 + .is-checked ~ .el-icon-delete {
  560 + display: none;
  561 + }
  562 + }
  563 + }
  564 + .el-icon {
  565 + font-size: 14px;
  566 + color: #999;
  567 + position: absolute;
  568 + right: 10px;
  569 + top: 3px;
  570 + cursor: pointer;
  571 + display: none;
  572 + }
  573 + .el-icon-check,
  574 + .el-icon-close {
  575 + display: block;
  576 + }
  577 + .el-icon-edit,
  578 + .el-icon-check {
  579 + right: 28px;
  580 + }
  581 +}
  582 +.sub-ipt {
  583 + :deep(.el-input__inner) {
  584 + height: 24px;
  585 + line-height: 24px;
  586 + }
  587 +}
  588 +.form-box {
  589 + :deep(.el-form-item__label) {
  590 + line-height: 28px;
  591 + }
  592 + .el-icon-plus {
  593 + cursor: pointer;
  594 + &:hover {
  595 + color: #667ffd;
  596 + }
  597 + }
  598 +}
  599 +</style>
0 600 \ No newline at end of file
... ...
src/views/standard/setUp/school.vue
... ... @@ -72,7 +72,6 @@
72 72 class="grade-item"
73 73 v-for="item in tableData"
74 74 :key="item.grade"
75   - @click="setGrade(item)"
76 75 >
77 76 <p class="grade-name">{{ item.gradeName }}</p>
78 77 <div class="grade-class">
... ... @@ -113,55 +112,6 @@
113 112 <el-button @click="diaUp = false">取 消</el-button>
114 113 </div>
115 114 </el-dialog>
116   - <el-dialog title="修改年级信息" :visible.sync="diaGrade" width="800px">
117   - <el-form
118   - class="form-box"
119   - :model="formGrade"
120   - :rules="rulesGrade"
121   - label-width="160px"
122   - >
123   - <el-form-item label="科目:" prop="subjectNames">
124   - <div class="subject-box" v-loading="subjectLoading" :class="showAll ? 'active' : ''">
125   - <span
126   - v-show="subjectList.length > 12"
127   - class="showAll"
128   - @click="showAll = !showAll"
129   - >{{ showAll ? "收起" : "更多..." }}</span
130   - >
131   - <el-checkbox-group v-model="formGrade.subjectNames">
132   - <p class="p1" v-for="(item, index) in subjectList" :key="item">
133   - <el-checkbox :label="item">{{ item }}</el-checkbox>
134   - <i class="el-icon-delete" @click="_DelSubject(item, index)"></i>
135   - </p>
136   - </el-checkbox-group>
137   - </div>
138   - <el-col :span="8">
139   - <el-input
140   - placeholder="添加科目"
141   - v-model.trim="subjectName"
142   - maxlength="30"
143   - >
144   - <i
145   - slot="suffix"
146   - class="el-input__icon el-icon-plus"
147   - @click="addSubjectName"
148   - ></i>
149   - </el-input>
150   - </el-col>
151   - </el-form-item>
152   - <el-form-item label="班级:">
153   - <span v-for="(item, index) in formGrade.classList" :key="item.id">{{
154   - `${item.className}${
155   - index == formGrade.classList.length - 1 ? "" : "、"
156   - }`
157   - }}</span>
158   - </el-form-item>
159   - </el-form>
160   - <div class="dialog-footer" slot="footer">
161   - <el-button @click="editGrade">确 定</el-button>
162   - <el-button @click="diaGrade = false">取 消</el-button>
163   - </div>
164   - </el-dialog>
165 115 <el-dialog title="修改学校信息" :visible.sync="diaSchool" width="400">
166 116 <el-form
167 117 ref="formSchool"
... ... @@ -246,8 +196,6 @@ export default {
246 196 url: "/api_html/school/manager/importClassAndStudent",
247 197 diaUp: false,
248 198 diaSchool: false,
249   - diaGrade: false,
250   - showAll: false, //修改年级科目显示
251 199 school: {
252 200 schoolName: "",
253 201 managePwd: "",
... ... @@ -286,21 +234,8 @@ export default {
286 234 },
287 235 ],
288 236 },
289   - formGrade: {
290   - //修改年级
291   - gradeName: "",
292   - subjectNames: [],
293   - classList: [],
294   - },
295   - rulesGrade: {
296   - subjectNames: [
297   - { required: true, message: "请选择科目", trigger: "blur" },
298   - ],
299   - },
300 237 subjectName: "",
301 238 sectionsList: [],
302   - subjectLoading:false,
303   - subjectList: [],
304 239 diaUpgradeGrade: false, //班级升级
305 240 defaultSections: [],
306 241 };
... ... @@ -321,7 +256,6 @@ export default {
321 256 this.code = localStorage.getItem("csCode") || "";
322 257 this._QueryDataSchool();
323 258 this._QueryDataGrade();
324   - this._QuerySubject();
325 259 this._QuerySectionList();
326 260 },
327 261 methods: {
... ... @@ -338,27 +272,6 @@ export default {
338 272 this._QueryDataSchool();
339 273 this._QueryDataGrade();
340 274 },
341   - setGrade(obj) {
342   - //打开年级设置
343   - this.formGrade.subjectNames = obj.subjectNames;
344   - this.formGrade.classList = obj.classList;
345   - this.formGrade.gradeName = obj.gradeName;
346   - this.showAll = false;
347   - this.diaGrade = true;
348   - },
349   - addSubjectName() {
350   - //添加科目
351   - if (!this.subjectName) {
352   - this.$message.warning("请填写科目名称");
353   - return;
354   - } else if (this.subjectList.includes(this.subjectName)) {
355   - this.$message.warning("科目已存在,请重新填写~");
356   - return;
357   - }
358   - this.subjectList.push(this.subjectName);
359   - this.formGrade.subjectNames.push(this.subjectName);
360   - this.subjectName = "";
361   - },
362 275 editSchool() {
363 276 //保存修改学校信息
364 277 if (!this.formSchool.sections.length) {
... ... @@ -398,20 +311,7 @@ export default {
398 311 }
399 312 });
400 313 },
401   - async _DelSubject(subject, index) {
402   - if(this.subjectLoading)return
403   - this.subjectLoading = true
404   - const { status, info } = await this.$request.delSubject({
405   - subjectName: subject,
406   - });
407   - this.subjectLoading = false
408   - if (status === 0) {
409   - this.$message.success(info);
410   - this.subjectList.splice(index, 1);
411   - } else {
412   - this.$message.error(info);
413   - }
414   - },
  314 +
415 315 async _UpgradeGrade() {
416 316 this.loading = true;
417 317 const { data, status, info } = await this.$request.upgradeGrade();
... ... @@ -420,34 +320,11 @@ export default {
420 320 this.$message.success("升级成功~");
421 321 this.diaUpgradeGrade = false;
422 322 this._QueryDataGrade();
423   - this._QuerySubject();
424   - } else {
425   - this.$message.error(info);
426   - }
427   - },
428   - async editGrade() {
429   - //保存修改年级信息
430   - if (!this.formGrade.subjectNames.length) {
431   - this.$message.error("请选择科目!");
432   - return;
433   - }
434   - if (this.loading) {
435   - return;
436   - }
437   - this.loading = true;
438   - const { data, status, info } = await this.$request.updateGrade({
439   - gradeName: this.formGrade.gradeName,
440   - subjectNames: this.formGrade.subjectNames,
441   - });
442   - this.loading = false;
443   - if (status === 0) {
444   - this.$message.success("修改成功~");
445   - this.diaGrade = false;
446   - this._QueryDataGrade();
447 323 } else {
448 324 this.$message.error(info);
449 325 }
450 326 },
  327 +
451 328 async _QuerySectionList() {
452 329 //学校学段
453 330 const { data, status, info } = await this.$request.sectionList();
... ... @@ -491,14 +368,7 @@ export default {
491 368 this.$message.error(info);
492 369 }
493 370 },
494   - async _QuerySubject() {
495   - const { data, status, info } = await this.$request.subjectList();
496   - if (status === 0) {
497   - this.subjectList = [...data.subjectNames] || [];
498   - } else {
499   - this.$message.error(info);
500   - }
501   - },
  371 +
502 372 async downExcel() {
503 373 let data = await this.$request.classAndStudentTemplate();
504 374 if (data && !data.code) {
... ... @@ -598,7 +468,6 @@ export default {
598 468 padding: 12px 16px;
599 469 border-radius: 10px;
600 470 box-shadow: 1px 1px 3px #888;
601   - cursor: pointer;
602 471 transition: all 0.5s;
603 472 &:hover {
604 473 transform: translate(-2px, -5px);
... ... @@ -633,27 +502,6 @@ export default {
633 502 }
634 503 .form-box {
635 504 margin: 0 20px;
636   - .subject-box {
637   - height: 90px;
638   - overflow: hidden;
639   - position: relative;
640   - &.active {
641   - height: auto;
642   - overflow: auto;
643   - }
644   - .showAll {
645   - position: absolute;
646   - bottom: 0;
647   - right: 10px;
648   - font-size: 12px;
649   - color: #7f7f7f;
650   - cursor: pointer;
651   - padding: 2px;
652   - &:hover {
653   - color: #667ffd;
654   - }
655   - }
656   - }
657 505 }
658 506 .el-icon-plus {
659 507 cursor: pointer;
... ...
src/views/standard/setUp/student.vue
... ... @@ -34,6 +34,23 @@
34 34 </back-box>
35 35 <div class="answer-header">
36 36 <div class="sel-box">
  37 + <el-select
  38 + class="sel"
  39 + v-model="query.gradeName"
  40 + placeholder="选择年级"
  41 + @change="changeGrade"
  42 + >
  43 + <el-option disabled label="全部" value=""></el-option>
  44 + <el-option
  45 + v-for="item in gradeList"
  46 + :key="item.value"
  47 + :label="item.label"
  48 + :value="item.value"
  49 + >
  50 + </el-option>
  51 + <el-option label="未分配" :value="80"></el-option>
  52 + <el-option label="已毕业" :value="81"></el-option>
  53 + </el-select>
37 54 <el-input
38 55 placeholder="请输入学生姓名"
39 56 v-model="query.studentName"
... ... @@ -61,30 +78,14 @@
61 78 </div>
62 79 </div>
63 80 <div class="page-content">
64   - <!-- <template v-if="!code && role !== 'ROLE_PERSONAL'">
65   - <p class="tips" v-show="archivedTotal">
66   - <span>另有{{ archivedTotal }}个班级已经归档,</span>
67   - <router-link to="/archivedClazz">点击查看&gt;&gt;</router-link>
68   - </p>
69   - </template> -->
70 81 <div class="stu-box">
71   - <div class="stu-list">
72   - <div class="h-title">
73   - <el-select
74   - class="sel"
75   - v-model="query.gradeName"
76   - placeholder="选择年级"
77   - @change="changeGrade"
78   - >
79   - <el-option
80   - v-for="item in gradeList"
81   - :key="item.value"
82   - :label="item.label"
83   - :value="item.value"
84   - >
85   - </el-option>
86   - </el-select>
87   - </div>
  82 + <div
  83 + class="stu-list"
  84 + v-show="
  85 + query.gradeName != 80 && query.gradeName != 81 && query.gradeName
  86 + "
  87 + >
  88 + <div class="h-title">班级列表</div>
88 89 <ul class="stu-ul">
89 90 <li
90 91 class="stu-item"
... ... @@ -93,33 +94,19 @@
93 94 :class="query.classId == item.id ? 'active' : ''"
94 95 @click="classDetail(item)"
95 96 >
96   - <template v-if="!code && role !== 'ROLE_PERSONAL'">
97   - <!-- <el-tooltip effect="dark" content="班级归档" placement="top">
98   - <div class="popconfirm-box">
99   - <i
100   - slot="reference"
101   - class="fa fa-file-archive-o"
102   - @click.stop="openArchivingDia(item, index)"
103   - ></i>
104   - </div>
105   - </el-tooltip> -->
106   - <el-tooltip effect="dark" content="修改班级" placement="top">
107   - <i
108   - class="el-icon-edit-outline"
109   - @click.stop="setClass(item)"
110   - ></i>
111   - </el-tooltip>
112   - </template>
113 97 {{ item.className }}({{ item.studentCount }})
114 98 </li>
115 99 </ul>
116 100 </div>
117 101 <div class="stu-detail">
118   - <div class="clazz-detail" v-if="clazzDetail.stationSn">
  102 + <p class="total" v-if="studentList.length">
  103 + 共筛选出{{ studentList.length }}名学生。
  104 + </p>
  105 + <!-- <div class="clazz-detail" v-if="clazzDetail.stationSn">
119 106 <p>基站SN:{{ clazzDetail.stationSn }}</p>
120 107 <p>配对码:{{ clazzDetail.pairingCode }}</p>
121 108 <p>频点:{{ clazzDetail.frequency }}</p>
122   - </div>
  109 + </div> -->
123 110  
124 111 <ul class="s-ul" v-loading="loading">
125 112 <li
... ... @@ -130,24 +117,26 @@
130 117 <el-popconfirm
131 118 v-if="!code"
132 119 title="确定删除吗?"
133   - @confirm="removeStu(item, index)"
  120 + @confirm="removeStu(item, index, $event)"
134 121 >
135 122 <i class="el-icon-delete" slot="reference"></i>
136 123 </el-popconfirm>
137 124 <i
138 125 class="el-icon-user-solid"
139 126 v-if="!code"
140   - @click="openChangeClazz(item)"
  127 + @click.stop="openChangeClazz(item)"
141 128 ></i>
142   - <p class="name">
143   - {{ item.studentName }}
144   - </p>
145   - <p class="p2" v-if="!query.classId">
146   - {{ item.gradeName }}﹒{{ item.className }}
147   - </p>
148   - <p class="p1">答题器:{{ item.clickerSn || "--" }}</p>
149   - <p class="p1">长学号:{{ item.studentCode }}</p>
150   - <p class="p1">短学号:{{ item.shortNumber || "--" }}</p>
  129 + <div class="s-li-box" @click="sayChange(item)">
  130 + <p class="name">
  131 + {{ item.studentName }}
  132 + </p>
  133 + <p class="p2" v-if="!query.classId">
  134 + {{ item.gradeName }}﹒{{ item.className }}
  135 + </p>
  136 + <p class="p1">答题器:{{ item.clickerSn || "--" }}</p>
  137 + <p class="p1">长学号:{{ item.studentCode }}</p>
  138 + <p class="p1">短学号:{{ item.shortNumber || "--" }}</p>
  139 + </div>
151 140 </li>
152 141 </ul>
153 142 <el-empty
... ... @@ -204,6 +193,25 @@
204 193 <el-button @click="diaChangeClass = false">取 消</el-button>
205 194 </div>
206 195 </el-dialog>
  196 + <el-dialog title="调班轨迹" :visible.sync="diaChangeClassTrack" width="400">
  197 + <el-form
  198 + :model="formClassTrack"
  199 + label-width="160px"
  200 + v-loading="loadingClassLogs"
  201 + >
  202 + <el-form-item label="学生姓名:">
  203 + <span>{{ formClassTrack.studentName }}</span>
  204 + </el-form-item>
  205 + <el-form-item label="当前班级:">
  206 + <p v-for="item in formClassTrack.classList">
  207 + {{ `${item.grade}-${item.className}(${item.createdTime})` }}
  208 + </p>
  209 + </el-form-item>
  210 + </el-form>
  211 + <div class="dialog-footer" slot="footer">
  212 + <el-button @click="diaChangeClassTrack = false">关 闭</el-button>
  213 + </div>
  214 + </el-dialog>
207 215 <el-dialog title="添加学生" :visible.sync="diaStu" width="400">
208 216 <el-form
209 217 ref="formBox"
... ... @@ -255,39 +263,6 @@
255 263 <el-button @click="diaStu = false">取 消</el-button>
256 264 </div>
257 265 </el-dialog>
258   - <el-dialog title="修改班级" :visible.sync="diaClass" width="400">
259   - <el-form
260   - class="form-box"
261   - ref="formClass"
262   - :model="formClass"
263   - :rules="rulesClass"
264   - label-width="160px"
265   - >
266   - <el-form-item label="所在年级:">
267   - <span>{{ formClass.gradeName }}</span>
268   - </el-form-item>
269   - <el-form-item label="班级名称:" prop="studentName">
270   - <el-col :span="10">
271   - <el-input maxlength="30" v-model.trim="formClass.className" />
272   - </el-col>
273   - </el-form-item>
274   - <el-form-item label="入学年份:" prop="studentCode">
275   - <el-col :span="10">
276   - <el-date-picker
277   - v-model="formClass.intoSchoolYear"
278   - type="year"
279   - value-format="yyyy"
280   - placeholder="选择年"
281   - >
282   - </el-date-picker>
283   - </el-col>
284   - </el-form-item>
285   - </el-form>
286   - <div class="dialog-footer" slot="footer">
287   - <el-button @click="saveClass">确 定</el-button>
288   - <el-button @click="diaClass = false">取 消</el-button>
289   - </div>
290   - </el-dialog>
291 266 <el-dialog title="学生答题器绑定" :visible.sync="diaUp" width="600">
292 267 <up-load
293 268 id="downTeacher"
... ... @@ -304,17 +279,6 @@
304 279 <el-button @click="diaUp = false">取 消</el-button>
305 280 </div>
306 281 </el-dialog>
307   - <el-dialog title="班级归档" :visible.sync="diaArchiving" width="400">
308   - <p>
309   - 注意班级归档后,学生解除班级关系且相关老师任课信息将不存在,确认要将班级归档吗?
310   - </p>
311   - <div class="dialog-footer" slot="footer">
312   - <el-button type="danger" @click="archivingClass">确认归档</el-button>
313   - <el-button type="primary" @click="diaArchiving = false"
314   - >取 消</el-button
315   - >
316   - </div>
317   - </el-dialog>
318 282 </div>
319 283 </template>
320 284  
... ... @@ -326,11 +290,18 @@ export default {
326 290 return {
327 291 code: "",
328 292 role: "",
  293 + loading: false,
  294 + loadingDown: false,
  295 + loadingClassLogs: false,
329 296 diaUp: false,
330 297 url: "/api_html/school/manager/importStudentClicker",
331 298 diaStu: false,
332   - diaClass: false,
333 299 diaChangeClass: false,
  300 + diaChangeClassTrack: false,
  301 + formClassTrack: {
  302 + studentName: "",
  303 + classList: [],
  304 + },
334 305 clazzDetail: { stationSn: "", pairingCode: "", frequency: "" },
335 306 query: {
336 307 gradeName: "",
... ... @@ -354,16 +325,6 @@ export default {
354 325 { required: true, message: "请输入学生长学号", trigger: "blur" },
355 326 ],
356 327 },
357   - formClass: {
358   - gradeName: "",
359   - className: "",
360   - intoSchoolYear: "",
361   - },
362   - rulesClass: {
363   - className: [
364   - { required: true, message: "请输入班级名称", trigger: "blur" },
365   - ],
366   - },
367 328 formStuCla: {
368 329 studentName: "",
369 330 studentId: "",
... ... @@ -393,10 +354,6 @@ export default {
393 354 teacherCourseList: [],
394 355 teacherGradeList: [],
395 356 },
396   - diaArchiving: false,
397   - archivedTotal: 0, //已归档班级
398   - archivingObj: {}, //即将归档班级信息
399   - archivingIndex: 0, //即将归档班级下标
400 357 };
401 358 },
402 359 async created() {
... ... @@ -404,7 +361,6 @@ export default {
404 361 this.role =
405 362 this.$store.getters.info.showRole ||
406 363 this.$store.getters.info.permissions[0].role;
407   - this._QueryArchivedNum();
408 364 await this._QueryDataGrade();
409 365 await this._QueryClass();
410 366 this._QueryData(3);
... ... @@ -435,34 +391,6 @@ export default {
435 391 this._QueryData(3);
436 392 },
437 393  
438   - setClass(obj) {
439   - this.formClass.gradeName = obj.gradeName;
440   - this.formClass.classId = obj.id;
441   - this.formClass.className = obj.className;
442   - this.formClass.intoSchoolYear = obj.intoSchoolYear + "";
443   - this.diaClass = true;
444   - },
445   - saveClass() {
446   - this.$refs.formClass.validate(async (valid) => {
447   - if (valid) {
448   - const { data, status, info } = await this.$request.updateClass({
449   - classId: this.formClass.classId,
450   - className: this.formClass.className,
451   - intoSchoolYear: this.formClass.intoSchoolYear,
452   - });
453   - if (status === 0) {
454   - this.$message.success("修改成功");
455   - this.diaClass = false;
456   - this._QueryClass();
457   - } else {
458   - this.$message.error(info);
459   - }
460   - } else {
461   - this.$message.warning("输入有误请检查!");
462   - return false;
463   - }
464   - });
465   - },
466 394 upSuccess(res) {
467 395 this.$message.closeAll();
468 396 this.$message({
... ... @@ -513,6 +441,11 @@ export default {
513 441 }
514 442 });
515 443 },
  444 + //学生调班轨迹
  445 + sayChange(obj) {
  446 + this._StudentClassLogs(obj);
  447 + this.diaChangeClassTrack = true;
  448 + },
516 449 //学生调班弹窗
517 450 openChangeClazz(obj) {
518 451 this.formStuCla.studentId = obj.id;
... ... @@ -551,32 +484,21 @@ export default {
551 484 { leading: true, trailing: false }
552 485 ),
553 486  
554   - openArchivingDia(obj, index) {
555   - this.archivingObj = { ...obj };
556   - this.archivingIndex = index;
557   - this.diaArchiving = true;
558   - },
559   - //班级归档
560   - async archivingClass() {
561   - const { data, status, info } = await this.$request.classArchiving({
562   - classId: this.archivingObj.id,
  487 + //学生调班轨迹
  488 + async _StudentClassLogs(obj) {
  489 + this.loadingClassLogs = true;
  490 + let { data, info, status } = await this.$request.studentClassLogs({
  491 + studentId: obj.id,
563 492 });
564   - this.diaArchiving = false;
565   - if (status === 0) {
566   - this.$message.success("归档成功");
567   - this.classList.splice(this.archivingIndex, 1);
568   - if (this.archivingIndex == this.classList.length) {
569   - this.classDetail(this.classList[this.archivingIndex - 1]);
570   - } else {
571   - this.classDetail(this.classList[this.archivingIndex]);
572   - }
573   - this._QueryArchivedNum();
574   - this._QueryData(3);
  493 + this.loadingClassLogs = false;
  494 + if (status == 0) {
  495 + this.formClassTrack.studentName = obj.studentName;
  496 + this.formClassTrack.classList = (data.list && [...data.list]) || [];
575 497 } else {
576 498 this.$message.error(info);
577 499 }
578 500 },
579   - async removeStu(obj, index) {
  501 + async removeStu(obj, index, $event) {
580 502 const { data, status, info } = await this.$request.delStudent({
581 503 studentId: obj.id,
582 504 });
... ... @@ -589,28 +511,33 @@ export default {
589 511 }
590 512 },
591 513 async changeGrade(val) {
  514 + if (!val) return;
592 515 this.query.classId = "";
  516 + this.query.studentName = "";
  517 + this.query.studentCode = "";
593 518 await this._QueryClass(val);
594 519 this._QueryData(3);
595 520 },
596   - async _QueryArchivedNum() {
597   - const { data, status, info } = await this.$request.archivingClassList();
598   - if (status === 0) {
599   - this.archivedTotal = data?.count || 0;
600   - } else {
601   - this.$message.error(info);
602   - }
603   - },
604 521 async _QueryData(type) {
605 522 let query = {};
606 523 if (type == 1) {
  524 + if (!this.query.studentName) {
  525 + this.$message.warning("输入学生姓名~");
  526 + return;
  527 + }
607 528 this.query.classId = "";
608 529 query.studentName = this.query.studentName;
609 530 this.query.studentCode = "";
  531 + this.query.gradeName = "";
610 532 } else if (type == 2) {
  533 + if (!this.query.studentName) {
  534 + this.$message.warning("输入学生学号~");
  535 + return;
  536 + }
611 537 this.query.classId = "";
612 538 query.studentCode = this.query.studentCode;
613 539 this.query.studentName = "";
  540 + this.query.gradeName = "";
614 541 } else if (type == 3) {
615 542 this.query.studentName = "";
616 543 this.query.studentCode = "";
... ... @@ -619,6 +546,15 @@ export default {
619 546 } else {
620 547 query = this.query;
621 548 }
  549 + if (query.gradeName == 80) {
  550 + query.status = 1;
  551 + delete query.gradeName;
  552 + } else if (query.gradeName == 81) {
  553 + query.status = 2;
  554 + delete query.gradeName;
  555 + } else {
  556 + query.status = 0;
  557 + }
622 558 this.loading = true;
623 559 const { data, status, info } = await this.$request.studentList({
624 560 ...query,
... ... @@ -702,6 +638,7 @@ export default {
702 638 padding-top: 10px;
703 639 }
704 640 .stu-list {
  641 + min-width: 200px;
705 642 max-height: 80vh;
706 643 .h-title {
707 644 height: 40px;
... ... @@ -766,18 +703,26 @@ export default {
766 703 .stu-detail {
767 704 flex: 1;
768 705 border-left: 0.5px solid #eee;
  706 + .total {
  707 + padding: 15px 12px;
  708 + font-size: 14px;
  709 + color: #666;
  710 + }
769 711 .s-ul {
770 712 display: flex;
771 713 flex-wrap: wrap;
772 714 padding-left: 20px;
773 715 .s-li {
774   - width: 180px;
775   - min-height: 120px;
  716 + position: relative;
776 717 box-shadow: 2px 2px 5px #7f7f7f;
777   - border-radius: 10px;
778 718 margin: 0 20px 20px 0;
779   - padding: 0 12px 5px;
780   - position: relative;
  719 + .s-li-box {
  720 + width: 180px;
  721 + border-radius: 10px;
  722 + min-height: 120px;
  723 + padding: 0 12px 5px;
  724 + cursor: pointer;
  725 + }
781 726 .el-icon-user-solid {
782 727 position: absolute;
783 728 top: 8px;
... ...