ModifyMarkerQuestion.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <el-dialog
  3. class="modify-marker-question"
  4. :visible.sync="modalIsShow"
  5. append-to-body
  6. top="20px"
  7. :close-on-click-modal="false"
  8. :close-on-press-escape="false"
  9. :show-close="false"
  10. @opened="visibleChange"
  11. >
  12. <div slot="title"></div>
  13. <el-row type="flex" :gutter="10">
  14. <el-col :span="12">
  15. <div class="marker-box">
  16. <div class="user-title">评卷员</div>
  17. <div class="user-search">
  18. <el-input
  19. v-model="filterLabel"
  20. placeholder="请输入评卷员名称"
  21. clearable
  22. size="mini"
  23. prefix-icon="el-icon-search"
  24. @input="labelChange"
  25. ></el-input>
  26. </div>
  27. <div class="user-tree">
  28. <el-tree
  29. ref="UserTree"
  30. :data="userTree"
  31. node-key="id"
  32. :default-checked-keys="selectedUserIds"
  33. :props="defaultProps"
  34. default-expand-all
  35. >
  36. <span class="custom-tree-node" slot-scope="{ node, data }">
  37. <el-checkbox
  38. v-if="data.isUser"
  39. v-model="node.checked"
  40. @change="userChange"
  41. >
  42. {{ node.label }}
  43. </el-checkbox>
  44. <span v-else>{{ node.label }}</span>
  45. <div title="全选" @click.stop>
  46. <el-checkbox
  47. v-if="!data.isUser && data.children.length"
  48. v-model="data.selected"
  49. @change="checked => selectNodeAll(checked, data)"
  50. ></el-checkbox>
  51. </div>
  52. </span>
  53. </el-tree>
  54. </div>
  55. </div>
  56. </el-col>
  57. <el-col :span="12">
  58. <div class="marker-box marker-box-uq">
  59. <el-form
  60. ref="modalFormRef"
  61. :rules="rules"
  62. :model="{}"
  63. label-width="100px"
  64. label-position="top"
  65. >
  66. <el-form-item prop="users" label="已选评卷员:">
  67. <el-tag
  68. v-for="user in selectedUsers"
  69. :key="user.id"
  70. closable
  71. :disable-transitions="false"
  72. @close="toDeleteUser(user)"
  73. >
  74. {{ user.label }}
  75. </el-tag>
  76. </el-form-item>
  77. <el-form-item prop="questions" label="选择评卷题目:">
  78. <div class="marker-paper-struct">
  79. <div
  80. v-for="mainItem in paperStructs"
  81. :key="mainItem.mainId"
  82. class="struct-item"
  83. >
  84. <div class="struct-header box-justify">
  85. <h4>{{ mainItem.mainNumber }}、{{ mainItem.mainTitle }}</h4>
  86. <el-checkbox
  87. v-model="mainItem.selected"
  88. title="全选"
  89. @change="checked => selectQuestionAll(checked, mainItem)"
  90. ></el-checkbox>
  91. </div>
  92. <div class="struct-questions">
  93. <el-checkbox
  94. v-for="question in mainItem.children"
  95. :key="question.id"
  96. v-model="question.selected"
  97. :disabled="question.disabled"
  98. @change="questionChange"
  99. >
  100. {{ question.subNumber }}
  101. </el-checkbox>
  102. </div>
  103. </div>
  104. </div>
  105. </el-form-item>
  106. </el-form>
  107. </div>
  108. </el-col>
  109. </el-row>
  110. <div class="marker-footer">
  111. <el-button type="primary" @click="confirm">确认</el-button>
  112. <el-button @click="cancel">取消</el-button>
  113. </div>
  114. <div slot="footer"></div>
  115. </el-dialog>
  116. </template>
  117. <script>
  118. import { deepCopy } from "../../../../plugins/utils";
  119. import { organizationList } from "../../../base/api";
  120. export default {
  121. name: "modify-marker-question",
  122. props: {
  123. instance: {
  124. type: Object,
  125. default() {
  126. return {};
  127. }
  128. },
  129. disabledQuestionIds: {
  130. type: Array,
  131. default() {
  132. return [];
  133. }
  134. },
  135. paperStructure: {
  136. type: Array,
  137. default() {
  138. return [];
  139. }
  140. }
  141. },
  142. data() {
  143. const usersValidator = (rule, value, callback) => {
  144. if (!this.selectedUserIds.length) {
  145. callback(new Error("请选择评卷员"));
  146. } else {
  147. callback();
  148. }
  149. };
  150. const questionsValidator = (rule, value, callback) => {
  151. if (!this.selectedQuestionIds.length) {
  152. callback(new Error("请选择试题"));
  153. } else {
  154. callback();
  155. }
  156. };
  157. return {
  158. modalIsShow: false,
  159. filterLabel: "",
  160. orgUsers: [],
  161. userTree: [],
  162. userList: [],
  163. selectedUsers: [],
  164. selectedUserIds: [],
  165. selectedQuestions: [],
  166. selectedQuestionIds: [],
  167. paperStructs: [],
  168. defaultProps: {
  169. children: "children",
  170. label: "label"
  171. },
  172. rules: {
  173. users: [
  174. {
  175. required: true,
  176. validator: usersValidator,
  177. trigger: "change"
  178. }
  179. ],
  180. questions: [
  181. {
  182. required: true,
  183. validator: questionsValidator,
  184. trigger: "change"
  185. }
  186. ]
  187. }
  188. };
  189. },
  190. mounted() {
  191. this.getOrgData();
  192. },
  193. methods: {
  194. visibleChange() {
  195. this.parseStructs();
  196. this.filterLabel = "";
  197. this.selectedQuestions = this.instance.questions;
  198. this.selectedQuestionIds = this.selectedQuestions.map(item => item.id);
  199. this.selectedUserIds = this.instance.markerList.map(item => item.id);
  200. this.updateSelectedUsersFromUserIds();
  201. this.labelChange();
  202. },
  203. cancel() {
  204. this.modalIsShow = false;
  205. },
  206. open() {
  207. this.modalIsShow = true;
  208. },
  209. // user
  210. async getOrgData() {
  211. const data = await organizationList({ specialPrivilege: "MARKER" });
  212. this.parseUserData(data);
  213. this.getUserList();
  214. },
  215. parseUserData(data) {
  216. const parseUser = list => {
  217. return list.map(item => {
  218. // org
  219. let nitem = {
  220. id: item.id,
  221. label: item.name,
  222. isUser: false,
  223. selected: false,
  224. children: []
  225. };
  226. if (item["children"] && item["children"].length) {
  227. nitem.children = [...nitem.children, ...parseUser(item.children)];
  228. }
  229. // user
  230. if (item["sysUserList"] && item["sysUserList"].length) {
  231. let sysUserList = item.sysUserList;
  232. const users = sysUserList.map(user => {
  233. const nuser = {
  234. id: user.id,
  235. userId: user.id,
  236. label: user.realName,
  237. name: user.realName,
  238. orgName: item.name,
  239. loginName: user.loginName,
  240. selected: false,
  241. isUser: true
  242. };
  243. return nuser;
  244. });
  245. nitem.children = [...nitem.children, ...users];
  246. }
  247. return nitem;
  248. });
  249. };
  250. this.orgUsers = parseUser(data);
  251. this.userTree = deepCopy(this.orgUsers);
  252. this.getUserList();
  253. },
  254. getUserList() {
  255. let userList = [];
  256. const fetchUser = users => {
  257. users.forEach(item => {
  258. if (item["children"] && item["children"].length) {
  259. fetchUser(item.children);
  260. } else {
  261. if (item.isUser) {
  262. let nitem = { ...item };
  263. nitem.label = `${nitem.name}(${nitem.orgName})`;
  264. userList.push(nitem);
  265. }
  266. }
  267. });
  268. };
  269. fetchUser(this.orgUsers);
  270. this.userList = userList;
  271. },
  272. labelChange() {
  273. if (!this.filterLabel) {
  274. this.userTree = deepCopy(this.orgUsers);
  275. } else {
  276. const escapeRegexpString = (value = "") =>
  277. String(value).replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
  278. const reg = new RegExp(escapeRegexpString(this.filterLabel), "i");
  279. this.userTree = this.userList.filter(item => reg.test(item.name));
  280. }
  281. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  282. },
  283. selectNodeAll(checked, data) {
  284. let userIds = [];
  285. const getUserIds = list => {
  286. list.forEach(item => {
  287. item.selected = checked;
  288. if (item.children && item.children.length) {
  289. getUserIds(item.children);
  290. } else {
  291. if (item.isUser) userIds.push(item.userId);
  292. }
  293. });
  294. };
  295. getUserIds(data.children);
  296. userIds.forEach(userId => {
  297. const userPos = this.selectedUserIds.indexOf(userId);
  298. const includeUser = userPos !== -1;
  299. if (checked) {
  300. if (!includeUser) this.selectedUserIds.push(userId);
  301. } else {
  302. if (includeUser) {
  303. this.selectedUserIds.splice(userPos, 1);
  304. }
  305. }
  306. });
  307. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  308. this.updateSelectedUsersFromUserIds();
  309. this.$refs.modalFormRef.validateField("users");
  310. },
  311. updateSelectedUsersFromUserIds() {
  312. this.selectedUsers = this.userList.filter(user =>
  313. this.selectedUserIds.includes(user.id)
  314. );
  315. },
  316. userChange() {
  317. if (this.filterLabel) {
  318. let prevSelectUserIds = this.selectedUsers.map(item => item.id);
  319. const prevUserListSelectUserIds = this.userTree
  320. .filter(user => prevSelectUserIds.includes(user.id))
  321. .map(user => user.id);
  322. const selectedUsers = this.$refs.UserTree.getCheckedNodes(true);
  323. const sIds = selectedUsers.map(user => user.id);
  324. const prevDeletedUserIds = prevUserListSelectUserIds.filter(
  325. uid => !sIds.includes(uid)
  326. );
  327. this.selectedUsers = this.selectedUsers.filter(
  328. user => !prevDeletedUserIds.includes(user.id)
  329. );
  330. prevSelectUserIds = this.selectedUsers.map(item => item.id);
  331. selectedUsers.forEach(user => {
  332. if (prevSelectUserIds.includes(user.id)) return;
  333. const nuser = {
  334. id: user.id,
  335. name: user.name,
  336. label: `${user.name}(${user.orgName})`
  337. };
  338. this.selectedUsers.push(nuser);
  339. });
  340. this.selectedUserIds = this.selectedUsers.map(item => item.id);
  341. } else {
  342. const selectedUsers = this.$refs.UserTree.getCheckedNodes(true);
  343. this.selectedUsers = selectedUsers.map(user => {
  344. const nuser = {
  345. id: user.id,
  346. name: user.name,
  347. label: `${user.name}(${user.orgName})`
  348. };
  349. return nuser;
  350. });
  351. this.selectedUserIds = this.selectedUsers.map(item => item.id);
  352. }
  353. this.updateSelectedUsersFromUserIds();
  354. },
  355. toDeleteUser(user) {
  356. const pos = this.selectedUsers.findIndex(item => item.id === user.id);
  357. this.selectedUsers.splice(pos, 1);
  358. this.selectedUserIds = this.selectedUsers.map(item => item.id);
  359. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  360. this.$refs.modalFormRef.validateField("users");
  361. },
  362. // question
  363. parseStructs() {
  364. this.selectedQuestionIds = this.instance.questions.map(q => q.id);
  365. let paperStructs = [];
  366. let struct = null;
  367. this.paperStructure.forEach(item => {
  368. if (item.mainFirstSub) {
  369. if (struct) paperStructs.push(struct);
  370. struct = {
  371. mainId: item.mainId,
  372. mainTitle: item.mainTitle,
  373. mainNumber: item.mainNumber,
  374. selected: false,
  375. children: []
  376. };
  377. }
  378. struct.children.push({
  379. ...item,
  380. disabled: this.disabledQuestionIds.includes(item.id),
  381. selected: this.selectedQuestionIds.includes(item.id)
  382. });
  383. });
  384. if (struct) paperStructs.push(struct);
  385. this.paperStructs = paperStructs;
  386. },
  387. selectQuestionAll(checked, mainItem) {
  388. mainItem.children.forEach(q => {
  389. if (!q.disabled) q.selected = checked;
  390. });
  391. this.questionChange();
  392. },
  393. updateSelectedQuestions() {
  394. let selectedQuestions = [];
  395. let selectedQuestionIds = [];
  396. this.paperStructs.forEach(s => {
  397. s.children.forEach(q => {
  398. if (q.selected && !q.disabled) {
  399. selectedQuestions.push(q);
  400. selectedQuestionIds.push(q.id);
  401. }
  402. });
  403. });
  404. this.selectedQuestions = selectedQuestions;
  405. this.selectedQuestionIds = selectedQuestionIds;
  406. },
  407. questionChange() {
  408. this.updateSelectedQuestions();
  409. this.$refs.modalFormRef.validateField("questions");
  410. },
  411. // confirm
  412. async confirm() {
  413. const valid = await this.$refs.modalFormRef.validate().catch(() => {});
  414. if (!valid) return;
  415. let datas = { ...this.instance };
  416. datas.markerList = this.selectedUsers.map(item => {
  417. return {
  418. id: item.id,
  419. name: item.name,
  420. loginName: item.loginName,
  421. label: item.label
  422. };
  423. });
  424. datas.questions = this.selectedQuestions.map(item => {
  425. let nitem = { ...item };
  426. delete nitem.disabled;
  427. delete nitem.selected;
  428. return nitem;
  429. });
  430. this.$emit("modified", datas);
  431. this.cancel();
  432. }
  433. }
  434. };
  435. </script>