UserSelectDialog.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. <template>
  2. <el-dialog
  3. v-model="dialogVisible"
  4. title="人员选择"
  5. :width="type == 1 ? 680 : 460"
  6. destroy-on-close
  7. append-to-body
  8. @closed="$emit('closed')"
  9. draggable
  10. >
  11. <template v-if="type == 1">
  12. <div class="user-select">
  13. <div class="user-select__left">
  14. <div class="user-select__search">
  15. <el-input
  16. v-model="searchForm.name"
  17. prefix-icon="search"
  18. placeholder="搜索成员"
  19. >
  20. <template #append>
  21. <el-button
  22. icon="search"
  23. @click="search"
  24. ></el-button>
  25. </template>
  26. </el-input>
  27. </div>
  28. <div class="user-select__select">
  29. <div
  30. class="user-select__tree"
  31. v-loading="showGrouploading"
  32. >
  33. <el-scrollbar>
  34. <el-tree
  35. class="menu"
  36. ref="groupTree"
  37. :data="group"
  38. node-key="id"
  39. :props="{
  40. label: 'name',
  41. children: 'children',
  42. }"
  43. highlight-current
  44. :expand-on-click-node="false"
  45. :current-node-key="groupId"
  46. @node-click="groupClick"
  47. >
  48. <template #default="{ node, data }">
  49. <span
  50. class="custom-tree-node el-tree-node__label"
  51. >
  52. <span class="label">
  53. <el-icon
  54. :size="16"
  55. class="m-r-5"
  56. >
  57. <qiye
  58. v-if="data.type === '1'"
  59. :style="{
  60. color:
  61. $TOOL.data.get(
  62. 'IS_PRIMARY_TENANT'
  63. ) &&
  64. data.tenantDTO &&
  65. $utils.getTenantColorById(
  66. data
  67. .tenantDTO
  68. .id
  69. ),
  70. }"
  71. ></qiye>
  72. <bumen
  73. v-else
  74. :style="{
  75. color:
  76. $TOOL.data.get(
  77. 'IS_PRIMARY_TENANT'
  78. ) &&
  79. data.tenantDTO &&
  80. $utils.getTenantColorById(
  81. data
  82. .tenantDTO
  83. .id
  84. ),
  85. }"
  86. ></bumen>
  87. </el-icon>
  88. {{ node.label }}
  89. </span>
  90. </span>
  91. </template>
  92. </el-tree>
  93. </el-scrollbar>
  94. </div>
  95. <div
  96. class="user-select__user"
  97. v-loading="showUserloading"
  98. >
  99. <div class="user-select__user__list">
  100. <el-scrollbar ref="userScrollbar">
  101. <el-tree
  102. class="menu"
  103. ref="userTree"
  104. :data="user"
  105. node-key="id"
  106. highlight-current
  107. :props="{
  108. key: 'id',
  109. label: 'name',
  110. children: 'children',
  111. }"
  112. :default-checked-keys="selectedIds"
  113. :show-checkbox="limit > 1"
  114. check-on-click-node
  115. @check-change="userClick"
  116. ></el-tree>
  117. </el-scrollbar>
  118. </div>
  119. <footer>
  120. <el-pagination
  121. background
  122. layout="prev,next"
  123. small
  124. :total="total"
  125. :page-size="pageSize"
  126. v-model:currentPage="currentPage"
  127. @current-change="paginationChange"
  128. ></el-pagination>
  129. </footer>
  130. </div>
  131. </div>
  132. </div>
  133. <div class="user-select__toicon">
  134. <el-icon><arrow-right /></el-icon>
  135. </div>
  136. <div class="user-select__selected">
  137. <header>已选 ({{ selected.length }})</header>
  138. <ul>
  139. <el-scrollbar>
  140. <li
  141. v-for="(item, index) in selected"
  142. :key="item.id"
  143. >
  144. <span class="name">
  145. <el-avatar
  146. v-if="
  147. $TOOL.data.get('IS_PRIMARY_TENANT')
  148. "
  149. :size="30"
  150. :style="{
  151. background:
  152. $utils.getTenantColorById(
  153. item.tenantId
  154. ) + '!important',
  155. }"
  156. >{{
  157. item.name.substring(0, 1)
  158. }}</el-avatar
  159. >
  160. <el-avatar v-else>{{
  161. item.name.substring(0, 1)
  162. }}</el-avatar>
  163. <label>{{ item.name }}</label>
  164. </span>
  165. <span class="delete">
  166. <el-button
  167. text
  168. type="primary"
  169. icon="del-filled"
  170. circle
  171. size="small"
  172. @click="deleteSelected(index)"
  173. ></el-button>
  174. </span>
  175. </li>
  176. </el-scrollbar>
  177. </ul>
  178. </div>
  179. </div>
  180. </template>
  181. <template #footer>
  182. <el-button @click="dialogVisible = false">取 消</el-button>
  183. <el-button type="primary" @click="save">确 认</el-button>
  184. </template>
  185. </el-dialog>
  186. </template>
  187. <script>
  188. import userService from "@/api/sys/userService";
  189. import officeService from "@/api/sys/officeService";
  190. export default {
  191. props: {
  192. tenantId: { type: String, default: null },
  193. limit: {
  194. type: Number,
  195. default: 999999,
  196. },
  197. },
  198. data() {
  199. return {
  200. searchForm: {
  201. loginName: "",
  202. companyDTO: {
  203. id: "",
  204. },
  205. officeDTO: {
  206. id: "",
  207. },
  208. name: "",
  209. },
  210. dialogVisible: false,
  211. showGrouploading: false,
  212. showUserloading: false,
  213. groupId: "",
  214. pageSize: 10,
  215. total: 0,
  216. currentPage: 1,
  217. group: [],
  218. user: [],
  219. role: [],
  220. type: 1,
  221. selected: [],
  222. value: [],
  223. };
  224. },
  225. computed: {
  226. selectedIds() {
  227. return this.selected.map((t) => t.id);
  228. },
  229. },
  230. methods: {
  231. //打开赋值
  232. open(data) {
  233. this.value = data || [];
  234. this.selected = JSON.parse(JSON.stringify(data || []));
  235. this.dialogVisible = true;
  236. this.getGroup();
  237. this.getUser();
  238. },
  239. //获取组织
  240. async getGroup() {
  241. this.showGrouploading = true;
  242. // officeService.treeData().then((data) => {
  243. // this.officeTreeData = data
  244. // this.showGrouploading = false;
  245. // })
  246. var res = await officeService.treeData({ tenantId: this.tenantId });
  247. this.showGrouploading = false;
  248. var allNode = { id: "", type: "1", name: "所有" };
  249. res.unshift(allNode);
  250. this.group = res;
  251. },
  252. //获取用户
  253. async getUser() {
  254. this.showUserloading = true;
  255. userService
  256. .list({
  257. current: this.currentPage,
  258. size: this.pageSize,
  259. ...this.searchForm,
  260. "tenantDTO.id": this.tenantId,
  261. })
  262. .then((data) => {
  263. this.user = data.records;
  264. this.total = data.total;
  265. // this.pageNo = data.current
  266. this.showUserloading = false;
  267. this.$refs.userScrollbar.setScrollTop(0);
  268. });
  269. },
  270. //组织点击
  271. groupClick(data) {
  272. if (data.type === "1") {
  273. this.searchForm.companyDTO.id = data.id;
  274. this.searchForm.officeDTO.id = "";
  275. } else {
  276. this.searchForm.companyDTO.id = "";
  277. this.searchForm.officeDTO.id = data.id;
  278. }
  279. this.currentPage = 1;
  280. this.groupId = data.id;
  281. this.getUser();
  282. },
  283. //用户点击
  284. userClick(data, checked) {
  285. if (checked) {
  286. if (this.limit === 1) {
  287. this.selected = [
  288. {
  289. id: data.id,
  290. name: data.name,
  291. tenantId: data.tenantDTO?.id,
  292. },
  293. ];
  294. } else {
  295. this.selected.push({
  296. id: data.id,
  297. name: data.name,
  298. tenantId: data.tenantDTO?.id,
  299. });
  300. }
  301. } else {
  302. this.selected = this.selected.filter(
  303. (item) => item.id != data.id
  304. );
  305. }
  306. },
  307. //用户分页点击
  308. paginationChange() {
  309. this.getUser();
  310. },
  311. //用户搜索
  312. search() {
  313. // this.groupId = ''
  314. // this.$refs.groupTree.setCurrentKey(this.groupId)
  315. this.currentPage = 1;
  316. this.getUser();
  317. },
  318. //删除已选
  319. deleteSelected(index) {
  320. this.selected.splice(index, 1);
  321. console.log(this.selected);
  322. if (this.type == 1) {
  323. this.$refs.userTree.setCheckedKeys(this.selectedIds);
  324. } else if (this.type == 2) {
  325. this.$refs.groupTree.setCheckedKeys(this.selectedIds);
  326. }
  327. },
  328. //提交保存
  329. save() {
  330. this.value.splice(0, this.value.length);
  331. this.selected.map((item) => {
  332. this.value.push(item);
  333. });
  334. if (this.limit < this.value.length) {
  335. this.$message.error(`你最多只能选择${this.limit}个用户`);
  336. return;
  337. }
  338. this.$emit("doSubmit", this.value);
  339. this.dialogVisible = false;
  340. },
  341. },
  342. };
  343. </script>
  344. <style scoped>
  345. .user-select {
  346. display: flex;
  347. }
  348. .user-select__left {
  349. width: 400px;
  350. }
  351. .user-select__right {
  352. flex: 1;
  353. }
  354. .user-select__selected li .name .el-avatar {
  355. margin-right: 2px;
  356. height: 10;
  357. width: 25px;
  358. height: 25px;
  359. }
  360. .user-select__search {
  361. padding-bottom: 10px;
  362. }
  363. .user-select__select {
  364. display: flex;
  365. border: 1px solid var(--el-border-color-light);
  366. background: var(--el-color-white);
  367. }
  368. .user-select__tree {
  369. width: 200px;
  370. height: 300px;
  371. border-right: 1px solid var(--el-border-color-light);
  372. }
  373. .user-select__user {
  374. width: 200px;
  375. height: 300px;
  376. display: flex;
  377. flex-direction: column;
  378. }
  379. .user-select__user__list {
  380. flex: 1;
  381. overflow: auto;
  382. }
  383. .user-select__user footer {
  384. height: 36px;
  385. padding-top: 5px;
  386. border-top: 1px solid var(--el-border-color-light);
  387. }
  388. .user-select__toicon {
  389. display: flex;
  390. justify-content: center;
  391. align-items: center;
  392. margin: 0 10px;
  393. }
  394. .user-select__toicon i {
  395. display: flex;
  396. justify-content: center;
  397. align-items: center;
  398. background: #ccc;
  399. width: 20px;
  400. height: 20px;
  401. text-align: center;
  402. line-height: 20px;
  403. border-radius: 50%;
  404. color: #fff;
  405. }
  406. .user-select__selected {
  407. height: 345px;
  408. width: 200px;
  409. border: 1px solid var(--el-border-color-light);
  410. background: var(--el-color-white);
  411. }
  412. .user-select__selected header {
  413. height: 43px;
  414. line-height: 43px;
  415. border-bottom: 1px solid var(--el-border-color-light);
  416. padding: 0 15px;
  417. font-size: 16px;
  418. }
  419. .user-select__selected ul {
  420. height: 300px;
  421. overflow: auto;
  422. }
  423. .user-select__selected li {
  424. display: flex;
  425. align-items: center;
  426. justify-content: space-between;
  427. padding: 5px 5px 5px 15px;
  428. height: 38px;
  429. }
  430. .user-select__selected li .name {
  431. display: flex;
  432. align-items: center;
  433. }
  434. .user-select__selected li .name .el-avatar {
  435. margin-right: 10px;
  436. }
  437. .user-select__selected li .delete {
  438. display: none;
  439. }
  440. .user-select__selected li:hover {
  441. background: var(--el-color-primary-light-9);
  442. }
  443. .user-select__selected li:hover .delete {
  444. display: inline-block;
  445. }
  446. .user-select-role .user-select__left {
  447. width: 200px;
  448. }
  449. .user-select-role .user-select__tree {
  450. border: none;
  451. height: 343px;
  452. }
  453. </style>