Bläddra i källkod

命题任务选人调整

zhangjie 2 år sedan
förälder
incheckning
b520c83cd9

+ 12 - 5
card/components/PageStructDialog.vue

@@ -47,18 +47,25 @@ export default {
       this.topics.forEach(topic => {
         if (!topic.parent) return;
         curTopicNo = topic.parent.topicNo;
+        let questionsCount = 0;
+        if (topic.type === "EXPLAIN") {
+          questionsCount = topic.parent.questionsCount;
+        } else if (topic.type === "COMPOSITION") {
+          questionsCount = 1;
+        } else {
+          questionsCount = topic.questionsCount;
+        }
+
         if (structData[curTopicNo]) {
-          if (topic.type !== "COMPOSITION" && topic.type !== "EXPLAIN") {
-            structData[curTopicNo].questionsCount += topic.questionsCount;
+          if (topic.type !== "EXPLAIN") {
+            structData[curTopicNo].questionsCount += questionsCount;
           }
         } else {
           let sd = {
             topicNo: curTopicNo,
             topicName: topic.parent.topicName,
-            questionsCount: topic.questionsCount
+            questionsCount
           };
-          if (topic.type === "EXPLAIN")
-            sd.questionsCount = topic.parent.questionsCount;
 
           structData[curTopicNo] = sd;
         }

+ 0 - 3
src/assets/styles/pages.scss

@@ -891,9 +891,6 @@
 // modify-marker-question
 .modify-marker-question {
   .el-dialog {
-    width: 900px;
-    margin: 0 auto;
-
     &__header,
     &__footer {
       display: none;

+ 141 - 105
src/modules/exam/components/ModifyExamTask.vue

@@ -1,116 +1,135 @@
 <template>
-  <el-dialog
-    class="modify-exam-task"
-    :visible.sync="modalIsShow"
-    :title="title"
-    top="10vh"
-    width="600px"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    append-to-body
-    @open="visibleChange"
-  >
-    <el-form
-      v-if="modalIsShow"
-      ref="modalFormComp"
-      label-width="120px"
-      :class="{ 'form-info': !editable }"
-      :rules="rules"
-      :model="modalForm"
+  <div>
+    <el-dialog
+      class="modify-exam-task"
+      :visible.sync="modalIsShow"
+      :title="title"
+      top="10vh"
+      width="600px"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      append-to-body
+      @open="visibleChange"
     >
-      <el-form-item prop="semesterId" label="学期:">
-        <semester-select
-          v-if="editable"
-          ref="SemesterSelect"
-          v-model="modalForm.semesterId"
-          default-select-in-used
-          class="width-full"
-        ></semester-select>
-        <span v-else>{{ modalForm.semesterName }}</span>
-      </el-form-item>
-      <el-form-item prop="examId" label="考试:">
-        <exam-select
-          v-if="editable"
-          v-model="modalForm.examId"
-          :semester-id="modalForm.semesterId"
-          class="width-full"
-        ></exam-select>
-        <span v-else>{{ modalForm.examName }}</span>
-      </el-form-item>
-      <el-form-item prop="courseCode" label="课程(代码):">
-        <course-select
-          v-if="editable"
-          ref="CourseSelect"
-          v-model.trim="modalForm.courseCode"
-          placeholder="请选择"
-          clearable
-          class="width-full"
-          :semester-id="modalForm.semesterId"
-          :exam-id="modalForm.examId"
-          @change="courseChange"
-        ></course-select>
-        <span v-else
-          >{{ modalForm.courseName }}({{ modalForm.courseCode }})</span
-        >
-      </el-form-item>
-      <el-form-item prop="paperNumber" label="试卷编号:">
-        <el-input
-          v-if="editable"
-          v-model="modalForm.paperNumber"
-          clearable
-        ></el-input>
-        <span v-else>{{ modalForm.paperNumber | defaultFieldFilter }}</span>
-      </el-form-item>
-      <el-form-item prop="startTime" label="命题时间:">
-        <el-date-picker
-          v-if="editable"
-          v-model="createTime"
-          type="datetimerange"
-          range-separator="至"
-          start-placeholder="开始时间"
-          end-placeholder="结束时间"
-          value-format="timestamp"
-          align="right"
-          unlink-panels
-          @change="dateChange"
-        >
-        </el-date-picker>
-        <span v-else>
-          <span v-if="modalForm.startTime && modalForm.endTime">
-            {{ modalForm.startTime | timestampFilter }} 至
-            {{ modalForm.endTime | timestampFilter }}
+      <el-form
+        v-if="modalIsShow"
+        ref="modalFormComp"
+        label-width="120px"
+        :class="{ 'form-info': !editable }"
+        :rules="rules"
+        :model="modalForm"
+      >
+        <el-form-item prop="semesterId" label="学期:">
+          <semester-select
+            v-if="editable"
+            ref="SemesterSelect"
+            v-model="modalForm.semesterId"
+            default-select
+            class="width-full"
+          ></semester-select>
+          <span v-else>{{ modalForm.semesterName }}</span>
+        </el-form-item>
+        <el-form-item prop="examId" label="考试:">
+          <exam-select
+            v-if="editable"
+            v-model="modalForm.examId"
+            :semester-id="modalForm.semesterId"
+            class="width-full"
+          ></exam-select>
+          <span v-else>{{ modalForm.examName }}</span>
+        </el-form-item>
+        <el-form-item prop="courseCode" label="课程(代码):">
+          <course-select
+            v-if="editable"
+            ref="CourseSelect"
+            v-model.trim="modalForm.courseCode"
+            placeholder="请选择"
+            clearable
+            class="width-full"
+            :semester-id="modalForm.semesterId"
+            :exam-id="modalForm.examId"
+            @change="courseChange"
+          ></course-select>
+          <span v-else
+            >{{ modalForm.courseName }}({{ modalForm.courseCode }})</span
+          >
+        </el-form-item>
+        <el-form-item prop="paperNumber" label="试卷编号:">
+          <el-input
+            v-if="editable"
+            v-model="modalForm.paperNumber"
+            clearable
+          ></el-input>
+          <span v-else>{{ modalForm.paperNumber | defaultFieldFilter }}</span>
+        </el-form-item>
+        <el-form-item prop="startTime" label="命题时间:">
+          <el-date-picker
+            v-if="editable"
+            v-model="createTime"
+            type="datetimerange"
+            range-separator="至"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            value-format="timestamp"
+            align="right"
+            unlink-panels
+            @change="dateChange"
+          >
+          </el-date-picker>
+          <span v-else>
+            <span v-if="modalForm.startTime && modalForm.endTime">
+              {{ modalForm.startTime | timestampFilter }} 至
+              {{ modalForm.endTime | timestampFilter }}
+            </span>
+            <span v-else>--</span>
           </span>
-          <span v-else>--</span>
-        </span>
-      </el-form-item>
-      <el-form-item label="命题老师:">
-        <question-teacher-user-select
-          v-if="editType !== 'PREVIEW' && modalIsShow"
-          ref="QuestionTeacherSelect"
-          v-model="modalForm.userId"
-          class="width-full"
-          :course-code="modalForm.courseCode"
-          placeholder="请选择"
-        ></question-teacher-user-select>
-        <span v-else>{{ modalForm.userName | defaultFieldFilter }}</span>
-      </el-form-item>
-    </el-form>
+        </el-form-item>
+        <el-form-item label="命题老师:">
+          <!-- <question-teacher-user-select
+            v-if="editType !== 'PREVIEW' && modalIsShow"
+            ref="QuestionTeacherSelect"
+            v-model="modalForm.userId"
+            class="width-full"
+            :course-code="modalForm.courseCode"
+            placeholder="请选择"
+          ></question-teacher-user-select> -->
+          <div class="box-justify">
+            <span>{{ modalForm.userName | defaultFieldFilter }}</span>
+            <el-button
+              v-if="editType !== 'PREVIEW'"
+              type="primary"
+              @click="toSelectTeacher"
+              >选择</el-button
+            >
+          </div>
+        </el-form-item>
+      </el-form>
 
-    <div slot="footer">
-      <el-button
-        v-if="editType !== 'PREVIEW'"
-        type="primary"
-        :disabled="isSubmit"
-        @click="submit"
-        >确认</el-button
-      >
-      <el-button @click="cancel">取消</el-button>
-    </div>
-  </el-dialog>
+      <div slot="footer">
+        <el-button
+          v-if="editType !== 'PREVIEW'"
+          type="primary"
+          :disabled="isSubmit"
+          @click="submit"
+          >确认</el-button
+        >
+        <el-button @click="cancel">取消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- SelectQuestionTeacher -->
+    <select-question-teacher
+      ref="SelectQuestionTeacher"
+      :users="teachers"
+      :course-code="modalForm.courseCode"
+      @modified="userSelected"
+    ></select-question-teacher>
+  </div>
 </template>
 
 <script>
 import { updateExamTask, updatExamTaskTeacher } from "../api";
+import SelectQuestionTeacher from "./SelectQuestionTeacher.vue";
 
 const initModalForm = {
   id: null,
@@ -132,6 +151,7 @@ const initModalForm = {
 
 export default {
   name: "modify-exam-task",
+  components: { SelectQuestionTeacher },
   props: {
     instance: {
       type: Object,
@@ -164,6 +184,7 @@ export default {
       isSubmit: false,
       modalForm: {},
       createTime: [],
+      teachers: [],
       rules: {
         semesterId: [
           {
@@ -247,6 +268,21 @@ export default {
     },
     courseChange(course) {
       this.modalForm.courseName = course.name;
+      this.modalForm.userId = "";
+      this.modalForm.userName = "";
+      this.teachers = [];
+    },
+    userSelected(teachers) {
+      this.teachers = teachers;
+      this.modalForm.userId = teachers[0].id;
+      this.modalForm.userName = teachers[0].name;
+    },
+    toSelectTeacher() {
+      if (!this.modalForm.courseCode) {
+        this.$message.error("请选择课程");
+        return;
+      }
+      this.$refs.SelectQuestionTeacher.open();
     },
     async submit() {
       const valid = await this.$refs.modalFormComp.validate().catch(() => {});

+ 369 - 0
src/modules/exam/components/SelectQuestionTeacher.vue

@@ -0,0 +1,369 @@
+<template>
+  <el-dialog
+    class="modify-marker-question"
+    :visible.sync="modalIsShow"
+    append-to-body
+    top="20px"
+    :width="multiple ? '900px' : '450px'"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    @opened="visibleChange"
+  >
+    <div slot="title"></div>
+
+    <el-row type="flex" :gutter="10">
+      <el-col :span="multiple ? 12 : 24">
+        <div class="marker-box">
+          <div class="user-title">人员</div>
+          <div class="user-search">
+            <el-input
+              v-model="filterLabel"
+              placeholder="请输入人员名称"
+              clearable
+              size="mini"
+              prefix-icon="el-icon-search"
+              @input="labelChange"
+            ></el-input>
+          </div>
+          <div class="user-types">
+            <div
+              :class="['user-type', { 'is-active': userType === 'org' }]"
+              @click="switchUserType('org')"
+            >
+              组织架构
+            </div>
+            <div
+              :class="['user-type', { 'is-active': userType === 'course' }]"
+              @click="switchUserType('course')"
+            >
+              课程
+            </div>
+          </div>
+          <div class="user-tree">
+            <el-tree
+              ref="UserTree"
+              :data="userTree"
+              node-key="id"
+              :default-checked-keys="selectedUserIds"
+              :props="defaultProps"
+              default-expand-all
+            >
+              <span class="custom-tree-node" slot-scope="{ node, data }">
+                <el-checkbox
+                  v-if="data.isUser"
+                  v-model="node.checked"
+                  @change="val => userChange(val, data)"
+                >
+                  {{ node.label }}
+                </el-checkbox>
+                <span v-else>{{ node.label }}</span>
+                <div v-if="multiple" title="全选" @click.stop>
+                  <el-checkbox
+                    v-if="!data.isUser && data.children.length"
+                    v-model="data.selected"
+                    @change="checked => selectNodeAll(checked, data)"
+                  ></el-checkbox>
+                </div>
+              </span>
+            </el-tree>
+          </div>
+        </div>
+      </el-col>
+      <el-col v-if="multiple" :span="12">
+        <div class="marker-box marker-box-uq">
+          <el-form
+            ref="modalFormRef"
+            :rules="rules"
+            :model="{}"
+            label-width="100px"
+            label-position="top"
+          >
+            <el-form-item prop="users" label="已选评卷员:">
+              <el-tag
+                v-for="user in selectedUsers"
+                :key="user.id"
+                closable
+                :disable-transitions="false"
+                @close="toDeleteUser(user)"
+              >
+                {{ user.name }}({{ user.orgName }})
+              </el-tag>
+            </el-form-item>
+          </el-form>
+        </div>
+      </el-col>
+    </el-row>
+
+    <div class="marker-footer">
+      <el-button type="primary" @click="confirm">确认</el-button>
+      <el-button @click="cancel">取消</el-button>
+    </div>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { deepCopy } from "../../../plugins/utils";
+import { questionTeatherUserQuery } from "../../base/api";
+
+export default {
+  name: "select-question-teacher",
+  props: {
+    users: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    courseCode: {
+      type: String,
+      default: ""
+    },
+    multiple: { type: Boolean, default: false }
+  },
+  data() {
+    const usersValidator = (rule, value, callback) => {
+      if (!this.selectedUserIds.length) {
+        callback(new Error("请选择评卷员"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      modalIsShow: false,
+      filterLabel: "",
+      userType: "course",
+      courseUsers: [],
+      orgUsers: [],
+      userTree: [],
+      userList: [],
+      selectedUsers: [],
+      selectedUserIds: [],
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      rules: {
+        users: [
+          {
+            required: true,
+            validator: usersValidator,
+            trigger: "change"
+          }
+        ]
+      }
+    };
+  },
+  watch: {
+    courseCode(val, oldval) {
+      if (val !== oldval) {
+        this.getUserData();
+      }
+    }
+  },
+  mounted() {
+    this.getUserData();
+  },
+  methods: {
+    visibleChange() {
+      this.filterLabel = "";
+      this.userType = "course";
+      this.selectedUsers = this.users.map(item => {
+        return { ...item };
+      });
+      this.selectedUserIds = this.users.map(item => item.id);
+      this.labelChange();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    // user
+    switchUserType(type) {
+      this.filterLabel = "";
+      this.userType = type;
+
+      this.userTree =
+        type === "org" ? deepCopy(this.orgUsers) : deepCopy(this.courseUsers);
+      this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
+    },
+    async getUserData() {
+      if (!this.courseCode) return;
+      let params = {
+        courseCode: this.courseCode
+      };
+      const data = await questionTeatherUserQuery(params);
+      this.parseUserData(data);
+      this.getUserList();
+    },
+    parseUserData(data) {
+      const parseUser = list => {
+        return list.map(item => {
+          // org
+          let nitem = {
+            id: item.id,
+            label: item.name,
+            isUser: false,
+            selected: false,
+            children: []
+          };
+
+          if (item["children"] && item["children"].length) {
+            nitem.children = [...nitem.children, ...parseUser(item.children)];
+          }
+          // user
+          if (item["sysUserList"] && item["sysUserList"].length) {
+            let sysUserList = item.sysUserList;
+            const users = sysUserList.map(user => {
+              const nuser = {
+                id: user.id,
+                userId: user.id,
+                label: user.realName,
+                name: user.realName,
+                orgName: item.name,
+                loginName: user.loginName,
+                selected: false,
+                isUser: true
+              };
+              return nuser;
+            });
+            nitem.children = [...nitem.children, ...users];
+          }
+
+          return nitem;
+        });
+      };
+      if (data.courseUserList && data.courseUserList.length) {
+        this.courseUsers = data.courseUserList.map(user => {
+          return {
+            id: user.id,
+            userId: user.id,
+            label: user.realName,
+            name: user.realName,
+            orgName: user.orgName,
+            loginName: user.loginName,
+            selected: false,
+            isUser: true
+          };
+        });
+      }
+      this.orgUsers = parseUser(data.blurryUserDtoList);
+      this.userTree = deepCopy(this.orgUsers);
+      this.getUserList();
+    },
+    getUserList() {
+      let userList = [];
+      const fetchUser = users => {
+        users.forEach(item => {
+          if (item["children"] && item["children"].length) {
+            fetchUser(item.children);
+          } else {
+            if (item.isUser) {
+              let nitem = { ...item };
+              nitem.label = `${nitem.name}(${nitem.orgName})`;
+              userList.push(nitem);
+            }
+          }
+        });
+      };
+      fetchUser(this.orgUsers);
+
+      this.userList = userList;
+    },
+    labelChange() {
+      if (!this.filterLabel) {
+        this.switchUserType(this.userType);
+      } else {
+        const escapeRegexpString = (value = "") =>
+          String(value).replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
+        const reg = new RegExp(escapeRegexpString(this.filterLabel), "i");
+
+        if (this.userType === "org") {
+          this.userTree = this.userList.filter(item => reg.test(item.name));
+        } else {
+          this.userTree = this.courseUsers.filter(item => reg.test(item.name));
+        }
+      }
+      this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
+    },
+    selectNodeAll(checked, data) {
+      let users = [];
+      const getUserIds = list => {
+        list.forEach(item => {
+          item.selected = checked;
+          if (item.children && item.children.length) {
+            getUserIds(item.children);
+          } else {
+            if (item.isUser) users.push(item);
+          }
+        });
+      };
+      getUserIds(data.children);
+
+      const userIds = users.map(u => u.id);
+      const selectedUserIds = this.selectedUsers.map(item => item.id);
+
+      let deleteUserIds = [];
+      userIds.forEach((userId, uindex) => {
+        const userPos = selectedUserIds.indexOf(userId);
+        const includeUser = userPos !== -1;
+        if (checked) {
+          if (!includeUser) this.selectedUsers.push(users[uindex]);
+        } else {
+          if (includeUser) {
+            deleteUserIds.push(userId);
+          }
+        }
+      });
+      this.selectedUsers = this.selectedUsers.filter(
+        u => !deleteUserIds.includes(u.id)
+      );
+      this.selectedUserIds = this.selectedUsers.map(item => item.id);
+      this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
+      this.$refs.modalFormRef.validateField("users");
+    },
+    userChange(checked, user) {
+      if (!this.multiple) {
+        this.selectedUsers = [];
+        if (checked) {
+          this.selectedUsers.push(user);
+        }
+        this.selectedUserIds = this.selectedUsers.map(item => item.id);
+        this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
+        return;
+      }
+
+      if (checked) {
+        this.selectedUsers.push(user);
+      } else {
+        this.selectedUsers = this.selectedUsers.filter(
+          item => item.id !== user.id
+        );
+      }
+      this.selectedUserIds = this.selectedUsers.map(item => item.id);
+      this.$refs.modalFormRef.validateField("users");
+    },
+    toDeleteUser(user) {
+      const pos = this.selectedUsers.findIndex(item => item.id === user.id);
+      this.selectedUsers.splice(pos, 1);
+      this.selectedUserIds = this.selectedUsers.map(item => item.id);
+      this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
+      this.$refs.modalFormRef.validateField("users");
+    },
+    // confirm
+    async confirm() {
+      if (this.multiple) {
+        const valid = await this.$refs.modalFormRef.validate().catch(() => {});
+        if (!valid) return;
+      }
+
+      this.$emit("modified", this.selectedUsers);
+      this.cancel();
+    }
+  }
+};
+</script>

+ 1 - 0
src/modules/stmms/components/SelectTypeUser.vue

@@ -4,6 +4,7 @@
     :visible.sync="modalIsShow"
     append-to-body
     top="20px"
+    width="900px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     :show-close="false"

+ 1 - 0
src/modules/stmms/components/markParam/ModifyMarkerQuestion.vue

@@ -4,6 +4,7 @@
     :visible.sync="modalIsShow"
     append-to-body
     top="20px"
+    width="900px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     :show-close="false"