SelectUserDialog.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <template>
  2. <el-dialog
  3. class="select-user-dialog"
  4. :visible.sync="modalIsShow"
  5. title="添加用户"
  6. top="10px"
  7. width="600px"
  8. :close-on-click-modal="false"
  9. :close-on-press-escape="false"
  10. append-to-body
  11. @opened="visibleChange"
  12. >
  13. <el-row type="flex" :gutter="10">
  14. <el-col :span="12">
  15. <div class="user-search">
  16. <el-input
  17. v-model="filterLabel"
  18. placeholder="请输入角色名称"
  19. clearable
  20. size="mini"
  21. prefix-icon="el-icon-search"
  22. @input="labelChange"
  23. ></el-input>
  24. </div>
  25. <div class="user-types">
  26. <div
  27. :class="['user-type', { 'is-active': userType === 'org' }]"
  28. @click="switchUserType('org')"
  29. >
  30. 组织架构
  31. </div>
  32. <div
  33. :class="['user-type', { 'is-active': userType === 'role' }]"
  34. @click="switchUserType('role')"
  35. >
  36. 角色
  37. </div>
  38. </div>
  39. <div class="user-tree">
  40. <el-tree
  41. ref="UserTree"
  42. :data="userTree"
  43. node-key="id"
  44. :default-checked-keys="selectedUserIds"
  45. :props="defaultProps"
  46. >
  47. <span class="custom-tree-node" slot-scope="{ node, data }">
  48. <el-checkbox
  49. v-if="data.isUser"
  50. v-model="node.checked"
  51. @change="(checked) => userChange(checked, data)"
  52. >
  53. {{ node.label }}
  54. </el-checkbox>
  55. <span v-else>{{ node.label }}</span>
  56. <el-checkbox
  57. v-if="!data.isUser && canSelectAll && data.children.length"
  58. v-model="data.selected"
  59. @change="(checked) => selectNodeAll(checked, data)"
  60. ></el-checkbox>
  61. </span>
  62. </el-tree>
  63. </div>
  64. </el-col>
  65. <el-col :span="12">
  66. <div class="user-part-title">已选范围</div>
  67. <div class="user-list">
  68. <div v-for="user in selectedUsers" :key="user.id" class="user-item">
  69. <p class="user-cont">
  70. <span>{{ user.label }}</span>
  71. </p>
  72. <el-button
  73. class="user-delete"
  74. type="text"
  75. icon="el-icon-remove"
  76. @click="toDeleteUser(user)"
  77. ></el-button>
  78. </div>
  79. </div>
  80. </el-col>
  81. </el-row>
  82. <p v-show="!selectValid" class="tips-info tips-error">
  83. 选择用户数不能超过{{ userLimitCount }}
  84. </p>
  85. <div slot="footer">
  86. <el-button type="primary" :disabled="!selectValid" @click="submit"
  87. >确认</el-button
  88. >
  89. <el-button @click="cancel">取消</el-button>
  90. </div>
  91. </el-dialog>
  92. </template>
  93. <script>
  94. import { organizationList } from "../api";
  95. export default {
  96. name: "select-user-dialog",
  97. props: {
  98. users: {
  99. type: Array,
  100. default() {
  101. return [];
  102. },
  103. },
  104. userLimitCount: {
  105. type: Number,
  106. default: 5,
  107. },
  108. canSelectAll: {
  109. type: Boolean,
  110. default: false,
  111. },
  112. filterRoles: {
  113. type: Array,
  114. default() {
  115. // id 数组
  116. return [];
  117. },
  118. },
  119. },
  120. data() {
  121. return {
  122. modalIsShow: false,
  123. filterLabel: "",
  124. userType: "org",
  125. orgData: [],
  126. orgUsers: [],
  127. roleUsers: [],
  128. userTree: [],
  129. userList: [],
  130. selectedUsers: [],
  131. selectedRoleUserIds: [],
  132. selectedUserIds: [],
  133. selectValid: true,
  134. defaultProps: {
  135. children: "children",
  136. label: "label",
  137. },
  138. };
  139. },
  140. methods: {
  141. async getOrgData() {
  142. const data = await organizationList();
  143. this.orgData = data;
  144. },
  145. parseUserData(data) {
  146. let roleUserMap = {};
  147. const parseUser = (list) => {
  148. return list.map((item) => {
  149. // org
  150. let nitem = {
  151. id: item.id,
  152. label: item.name,
  153. isUser: false,
  154. selected: false,
  155. children: [],
  156. };
  157. if (item["children"] && item["children"].length) {
  158. nitem.children = [...nitem.children, ...parseUser(item.children)];
  159. }
  160. // user
  161. if (item["sysUserList"] && item["sysUserList"].length) {
  162. let sysUserList = item.sysUserList;
  163. // 过滤符合需求角色的用户
  164. if (this.filterRoles.length) {
  165. sysUserList = sysUserList.filter(
  166. (user) =>
  167. user.roleResultList &&
  168. user.roleResultList.some((role) =>
  169. this.filterRoles.includes(role.roleId)
  170. )
  171. );
  172. }
  173. const users = sysUserList.map((user) => {
  174. const nuser = {
  175. id: user.id,
  176. userId: user.id,
  177. label: user.realName,
  178. name: user.realName,
  179. orgName: item.name,
  180. selected: false,
  181. isUser: true,
  182. };
  183. if (user.roleResultList && user.roleResultList.length) {
  184. user.roleResultList.forEach((urole) => {
  185. if (!roleUserMap[urole.roleId]) {
  186. roleUserMap[urole.roleId] = {
  187. id: urole.roleId,
  188. label: urole.roleName,
  189. selected: false,
  190. isUser: false,
  191. children: [],
  192. };
  193. }
  194. let ruser = { ...nuser };
  195. ruser.id = `${ruser.id}_${this.$randomCode()}`;
  196. ruser.label = `${ruser.name}(${ruser.orgName})`;
  197. roleUserMap[urole.roleId].children.push(ruser);
  198. });
  199. }
  200. return nuser;
  201. });
  202. nitem.children = [...nitem.children, ...users];
  203. }
  204. return nitem;
  205. });
  206. };
  207. this.orgUsers = parseUser(data);
  208. this.roleUsers = Object.values(roleUserMap);
  209. this.userTree = this.orgUsers;
  210. this.getUserList();
  211. },
  212. getUserList() {
  213. let userList = [];
  214. const fetchUser = (users) => {
  215. users.forEach((item) => {
  216. if (item["children"] && item["children"].length) {
  217. fetchUser(item.children);
  218. } else {
  219. if (item.isUser) {
  220. let nitem = { ...item };
  221. nitem.label = `${nitem.name}(${nitem.orgName})`;
  222. userList.push(nitem);
  223. }
  224. }
  225. });
  226. };
  227. fetchUser(this.orgUsers);
  228. this.userList = userList;
  229. },
  230. labelChange() {
  231. if (!this.filterLabel) {
  232. this.switchUserType(this.userType);
  233. } else {
  234. const escapeRegexpString = (value = "") =>
  235. String(value).replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
  236. const reg = new RegExp(escapeRegexpString(this.filterLabel), "i");
  237. this.userTree = this.userList.filter((item) => reg.test(item.name));
  238. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  239. }
  240. },
  241. checkValid() {
  242. this.selectValid =
  243. !this.userLimitCount ||
  244. this.selectedUsers.length <= this.userLimitCount;
  245. },
  246. async visibleChange() {
  247. if (!this.orgUsers.length) await this.getOrgData();
  248. this.parseUserData(this.orgData);
  249. this.filterLabel = "";
  250. this.userType = "org";
  251. this.userTree = this.orgUsers;
  252. this.selectedUsers = this.users.map((user) => {
  253. const luser = this.userList.find((item) => item.id === user.id);
  254. return {
  255. id: user.id,
  256. name: user.name,
  257. label: `${user.name}(${luser.orgName})`,
  258. };
  259. });
  260. this.selectedUserIds = this.users.map((item) => item.id);
  261. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  262. this.checkValid();
  263. },
  264. cancel() {
  265. this.modalIsShow = false;
  266. },
  267. open() {
  268. this.modalIsShow = true;
  269. },
  270. selectNodeAll(checked, data) {
  271. let userIds = [];
  272. const getUserIds = (list) => {
  273. list.forEach((item) => {
  274. item.selected = checked;
  275. if (item.children && item.children.length) {
  276. getUserIds(item.children);
  277. } else {
  278. if (item.isUser) userIds.push(item.userId);
  279. }
  280. });
  281. };
  282. getUserIds(data.children);
  283. userIds.forEach((userId) => {
  284. const userPos = this.selectedUserIds.indexOf(userId);
  285. const includeUser = userPos !== -1;
  286. if (checked) {
  287. if (!includeUser) this.selectedUserIds.push(userId);
  288. } else {
  289. if (includeUser) {
  290. this.selectedUserIds.splice(userPos, 1);
  291. }
  292. }
  293. });
  294. if (this.userType === "role") {
  295. this.updateSelectRoleUserIds();
  296. } else {
  297. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  298. }
  299. this.updateSelectedUsersFromUserIds();
  300. },
  301. switchUserType(type) {
  302. this.userType = type;
  303. this.userTree = type === "org" ? this.orgUsers : this.roleUsers;
  304. if (type === "role") {
  305. this.updateSelectRoleUserIds();
  306. }
  307. },
  308. updateSelectRoleUserIds() {
  309. let selectedRoleUserIds = [];
  310. this.roleUsers.forEach((role) => {
  311. role.children.forEach((user) => {
  312. if (this.selectedUserIds.includes(user.userId))
  313. selectedRoleUserIds.push(user.id);
  314. });
  315. });
  316. this.selectedRoleUserIds = selectedRoleUserIds;
  317. this.$refs.UserTree.setCheckedKeys(selectedRoleUserIds);
  318. },
  319. updateSelectedUsersFromUserIds() {
  320. this.selectedUsers = this.userList.filter((user) =>
  321. this.selectedUserIds.includes(user.id)
  322. );
  323. },
  324. userChange(checked, curUser) {
  325. if (this.filterLabel) {
  326. let prevSelectUserIds = this.selectedUsers.map((item) => item.id);
  327. const prevUserListSelectUserIds = this.userTree
  328. .filter((user) => prevSelectUserIds.includes(user.id))
  329. .map((user) => user.id);
  330. const selectedUsers = this.$refs.UserTree.getCheckedNodes(true);
  331. const sIds = selectedUsers.map((user) => user.id);
  332. const prevDeletedUserIds = prevUserListSelectUserIds.filter(
  333. (uid) => !sIds.includes(uid)
  334. );
  335. this.selectedUsers = this.selectedUsers.filter(
  336. (user) => !prevDeletedUserIds.includes(user.id)
  337. );
  338. prevSelectUserIds = this.selectedUsers.map((item) => item.id);
  339. selectedUsers.forEach((user) => {
  340. if (prevSelectUserIds.includes(user.id)) return;
  341. const nuser = {
  342. id: user.id,
  343. name: user.name,
  344. label: `${user.name}(${user.orgName})`,
  345. };
  346. this.selectedUsers.push(nuser);
  347. });
  348. this.selectedUserIds = this.selectedUsers.map((item) => item.id);
  349. this.checkValid();
  350. return;
  351. }
  352. if (this.userType === "org") {
  353. const selectedUsers = this.$refs.UserTree.getCheckedNodes(true);
  354. this.selectedUsers = selectedUsers.map((user) => {
  355. const nuser = {
  356. id: user.id,
  357. name: user.name,
  358. label: `${user.name}(${user.orgName})`,
  359. };
  360. return nuser;
  361. });
  362. this.selectedUserIds = this.selectedUsers.map((item) => item.id);
  363. this.checkValid();
  364. return;
  365. }
  366. if (this.userType === "role") {
  367. if (checked) {
  368. if (!this.selectedUserIds.includes(curUser.userId))
  369. this.selectedUserIds.push(curUser.userId);
  370. } else {
  371. this.selectedUserIds = this.selectedUserIds.filter(
  372. (userid) => userid !== curUser.userId
  373. );
  374. }
  375. this.updateSelectRoleUserIds();
  376. this.updateSelectedUsersFromUserIds();
  377. this.checkValid();
  378. }
  379. },
  380. toDeleteUser(user) {
  381. const pos = this.selectedUsers.findIndex((item) => item.id === user.id);
  382. this.selectedUsers.splice(pos, 1);
  383. this.selectedUserIds = this.selectedUsers.map((item) => item.id);
  384. if (this.userType === "role") {
  385. this.updateSelectRoleUserIds();
  386. } else {
  387. this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
  388. }
  389. this.checkValid();
  390. },
  391. submit() {
  392. if (!this.selectValid) return;
  393. this.$emit(
  394. "modified",
  395. this.selectedUsers.map((item) => {
  396. return {
  397. id: item.id,
  398. name: item.name,
  399. };
  400. })
  401. );
  402. this.cancel();
  403. },
  404. },
  405. };
  406. </script>