|
@@ -1,99 +1,365 @@
|
|
|
<template>
|
|
|
<el-dialog
|
|
|
+ class="modify-marker-bind modify-marker-question"
|
|
|
:visible.sync="modalIsShow"
|
|
|
+ append-to-body
|
|
|
+ top="10px"
|
|
|
+ width="900px"
|
|
|
title="绑定评卷员"
|
|
|
- top="10vh"
|
|
|
- width="448px"
|
|
|
:close-on-click-modal="false"
|
|
|
:close-on-press-escape="false"
|
|
|
- append-to-body
|
|
|
+ :show-close="false"
|
|
|
@opened="visibleChange"
|
|
|
>
|
|
|
- <el-form ref="modalFormComp" :model="modalForm" :rules="rules">
|
|
|
- <el-form-item prop="userIds" label="评卷员:">
|
|
|
- <el-select
|
|
|
- v-model="modalForm.userIds"
|
|
|
- placeholder="评卷员"
|
|
|
- multiple
|
|
|
- clearable
|
|
|
- >
|
|
|
- <el-option v-for="user in userList" :key="user.id" :value="user.id">{{
|
|
|
- user.name
|
|
|
- }}</el-option>
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <div slot="footer">
|
|
|
- <el-button type="primary" :loading="isSubmit" @click="submit"
|
|
|
- >确认</el-button
|
|
|
- >
|
|
|
+ <el-row type="flex" :gutter="10">
|
|
|
+ <el-col :span="12">
|
|
|
+ <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 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 :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 { markMarkerBind } from "../../api";
|
|
|
+import { deepCopy } from "@/plugins/utils";
|
|
|
+import { organizationList } from "../../../base/api";
|
|
|
|
|
|
export default {
|
|
|
- name: "modify-marker-bind",
|
|
|
+ name: "modify-mark-group",
|
|
|
props: {
|
|
|
- data: {
|
|
|
+ instance: {
|
|
|
type: Object,
|
|
|
default() {
|
|
|
return {};
|
|
|
},
|
|
|
},
|
|
|
+ courseCode: {
|
|
|
+ type: String,
|
|
|
+ default: "",
|
|
|
+ },
|
|
|
},
|
|
|
data() {
|
|
|
+ const usersValidator = (rule, value, callback) => {
|
|
|
+ if (!this.selectedUserIds.length) {
|
|
|
+ callback(new Error("请选择评卷员"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return {
|
|
|
- isSubmit: false,
|
|
|
modalIsShow: false,
|
|
|
- modalForm: { userIds: [] },
|
|
|
+ filterLabel: "",
|
|
|
+ userType: "course",
|
|
|
+ courseUsers: [],
|
|
|
+ orgUsers: [],
|
|
|
+ userTree: [],
|
|
|
userList: [],
|
|
|
+ selectedUsers: [],
|
|
|
+ selectedUserIds: [],
|
|
|
+ defaultProps: {
|
|
|
+ children: "children",
|
|
|
+ label: "label",
|
|
|
+ },
|
|
|
rules: {
|
|
|
- userIds: [
|
|
|
+ users: [
|
|
|
{
|
|
|
required: true,
|
|
|
- validator: (rule, value, callback) => {
|
|
|
- if (!value || !value.length) {
|
|
|
- return callback(new Error(`请选择评卷员`));
|
|
|
- }
|
|
|
- callback();
|
|
|
- },
|
|
|
+ validator: usersValidator,
|
|
|
trigger: "change",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
};
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ this.getOrgData();
|
|
|
+ },
|
|
|
methods: {
|
|
|
visibleChange() {
|
|
|
- this.modalForm = { userIds: [] };
|
|
|
- this.$nextTick(() => {
|
|
|
- this.$refs.modalFormComp.clearValidate();
|
|
|
- });
|
|
|
+ this.filterLabel = "";
|
|
|
+ this.userType = "course";
|
|
|
+ this.selectedUsers = [];
|
|
|
+ this.selectedUserIds = [];
|
|
|
+ this.labelChange();
|
|
|
},
|
|
|
cancel() {
|
|
|
this.modalIsShow = false;
|
|
|
+ this.$emit("cancel");
|
|
|
},
|
|
|
open() {
|
|
|
this.modalIsShow = true;
|
|
|
},
|
|
|
- async submit() {
|
|
|
- const valid = await this.$refs.modalFormComp.validate().catch(() => {});
|
|
|
- if (!valid) return;
|
|
|
+ // user
|
|
|
+ switchUserType(type) {
|
|
|
+ this.filterLabel = "";
|
|
|
+ this.userType = type;
|
|
|
|
|
|
- if (this.isSubmit) return;
|
|
|
- this.isSubmit = true;
|
|
|
+ this.userTree =
|
|
|
+ type === "org" ? deepCopy(this.orgUsers) : deepCopy(this.courseUsers);
|
|
|
+ this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
|
|
|
+ },
|
|
|
+ async getOrgData() {
|
|
|
+ let params = {
|
|
|
+ specialPrivilege: "MARKER",
|
|
|
+ };
|
|
|
+ if (this.courseCode) params.courseCode = this.courseCode;
|
|
|
+ const data = await organizationList(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];
|
|
|
+ }
|
|
|
|
|
|
- const datas = { ...this.modalForm, ...this.data };
|
|
|
- const res = await markMarkerBind(datas).catch(() => {});
|
|
|
- this.isSubmit = false;
|
|
|
- if (!res) return;
|
|
|
- this.$message.success("绑定成功!");
|
|
|
- this.cancel();
|
|
|
- this.$emit("modified");
|
|
|
+ if (item["courseUserList"] && item["courseUserList"].length) {
|
|
|
+ nitem.courseUserList = item.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,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return nitem;
|
|
|
+ });
|
|
|
+ };
|
|
|
+ this.orgUsers = parseUser(data);
|
|
|
+ this.userTree = deepCopy(this.orgUsers);
|
|
|
+ if (this.courseCode && this.orgUsers[0].courseUserList) {
|
|
|
+ this.courseUsers = deepCopy(this.orgUsers[0].courseUserList);
|
|
|
+ }
|
|
|
+ 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");
|
|
|
+ },
|
|
|
+ updateSelectedUsersFromUserIds() {
|
|
|
+ this.selectedUsers = this.userList.filter((user) =>
|
|
|
+ this.selectedUserIds.includes(user.id)
|
|
|
+ );
|
|
|
+ },
|
|
|
+ userChange(checked, user) {
|
|
|
+ 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() {
|
|
|
+ const valid = await this.$refs.modalFormRef.validate().catch(() => {});
|
|
|
+ if (!valid) return;
|
|
|
+
|
|
|
+ this.$emit(
|
|
|
+ "modified",
|
|
|
+ this.selectedUsers.map((item) => {
|
|
|
+ return {
|
|
|
+ id: item.id,
|
|
|
+ name: item.name,
|
|
|
+ };
|
|
|
+ })
|
|
|
+ );
|
|
|
+ this.modalIsShow = false;
|
|
|
},
|
|
|
},
|
|
|
};
|