|
@@ -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>
|