UserSelectDialog.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <template>
  2. <div>
  3. <el-dialog
  4. title="用户选择"
  5. width="1000px"
  6. :close-on-click-modal="false"
  7. :append-to-body="true"
  8. draggable
  9. class="userDialog"
  10. v-model="visible">
  11. <el-container style="height: 500px">
  12. <el-aside width="200px">
  13. <el-card class="org">
  14. <div slot="header" class="clearfix">
  15. <el-input
  16. placeholder="请输入组织机构过滤"
  17. size="small"
  18. v-model="filterText">
  19. </el-input>
  20. </div>
  21. <el-tree
  22. :data="officeTreeData"
  23. :props="{
  24. value: 'id', // ID字段名
  25. label: 'name', // 显示名称
  26. children: 'children' // 子级字段名
  27. }"
  28. default-expand-all
  29. highlight-current
  30. node-key="id"
  31. :render-content="renderContent"
  32. :filter-node-method="filterNode"
  33. :expand-on-click-node="false"
  34. @node-click="handleNodeClick"
  35. ref="officeTree">
  36. </el-tree>
  37. </el-card>
  38. </el-aside>
  39. <el-container>
  40. <el-header style="text-align: left; font-size: 12px;height:30px">
  41. <el-form :inline="true" ref="searchForm" :model="searchForm" @keyup.enter.native="refreshList()" @submit.native.prevent>
  42. <el-form-item prop="loginName">
  43. <el-input v-model="searchForm.loginName" placeholder="登录名" clearable></el-input>
  44. </el-form-item>
  45. <el-form-item>
  46. <el-button type="primary" @click="refreshList()" icon="el-icon-search">查询</el-button>
  47. <el-button @click="resetSearch()" icon="el-icon-refresh-right">重置</el-button>
  48. </el-form-item>
  49. </el-form>
  50. </el-header>
  51. <el-main>
  52. <el-table
  53. :data="dataList"
  54. v-loading="loading"
  55. size="small"
  56. border
  57. ref="userTable"
  58. @selection-change="selectionChangeHandle"
  59. @sort-change="sortChangeHandle"
  60. height="calc(100% - 40px)"
  61. style="width: 100%;">
  62. <el-table-column
  63. header-align="center"
  64. align="center"
  65. v-if="limit <= 1"
  66. width="50">
  67. <template #default="scope">
  68. <el-radio :label="scope.row.id" :value="dataListAllSelections[0]&&dataListAllSelections[0].id" @change.native="getTemplateRow(scope.$index,scope.row)"><span></span></el-radio>
  69. </template>
  70. </el-table-column>
  71. <el-table-column
  72. type="selection"
  73. header-align="center"
  74. v-if="limit > 1"
  75. align="center"
  76. width="50">
  77. </el-table-column>
  78. <el-table-column
  79. prop="photo"
  80. header-align="center"
  81. align="center"
  82. label="头像">
  83. <template #default="scope">
  84. <img :src="scope.row.photo === ''?'/static/img/avatar.png':scope.row.photo" style="height:35px"/>
  85. </template>
  86. </el-table-column>
  87. <el-table-column
  88. prop="loginName"
  89. header-align="center"
  90. align="center"
  91. sortable="custom"
  92. min-width="90"
  93. label="登录名">
  94. </el-table-column>
  95. <el-table-column
  96. prop="name"
  97. header-align="center"
  98. align="真实姓名"
  99. sortable="custom"
  100. min-width="90"
  101. label="用户名">
  102. </el-table-column>
  103. <el-table-column
  104. prop="companyDTO.name"
  105. header-align="center"
  106. align="center"
  107. sortable="custom"
  108. min-width="110"
  109. label="所属机构">
  110. </el-table-column>
  111. <el-table-column
  112. prop="officeDTO.name"
  113. header-align="center"
  114. align="center"
  115. sortable="custom"
  116. min-width="110"
  117. label="所属部门">
  118. </el-table-column>
  119. <el-table-column
  120. prop="loginFlag"
  121. header-align="center"
  122. align="center"
  123. min-width="100"
  124. label="状态">
  125. <template #default="scope">
  126. <el-tag v-if="scope.row.loginFlag === '1'" size="small" type="success">正常</el-tag>
  127. <el-tag v-else-if="scope.row.loginFlag === '0'" size="small" type="danger">禁用</el-tag>
  128. </template>
  129. </el-table-column>
  130. </el-table>
  131. <el-pagination
  132. @size-change="sizeChangeHandle"
  133. @current-change="currentChangeHandle"
  134. :current-page="pageNo"
  135. :page-sizes="[5, 10, 50, 100]"
  136. :page-size="pageSize"
  137. :total="total"
  138. layout="total, sizes, prev, pager, next, jumper">
  139. </el-pagination>
  140. </el-main>
  141. </el-container>
  142. <el-aside width="200px">
  143. <el-tag
  144. :key="tag.id"
  145. v-for="tag in dataListAllSelections"
  146. closable
  147. :disable-transitions="false"
  148. @close="del(tag)">
  149. {{tag.name}}
  150. </el-tag>
  151. </el-aside>
  152. </el-container>
  153. <template #footer>
  154. <span class="dialog-footer">
  155. <el-button size="small" @click="visible = false" icon="el-icon-circle-close">关闭</el-button>
  156. <el-button size="small" type="primary" icon="el-icon-circle-check" @click="doSubmit()">确定</el-button>
  157. </span>
  158. </template>
  159. </el-dialog>
  160. </div>
  161. </template>
  162. <script>
  163. export default {
  164. data () {
  165. return {
  166. searchForm: {
  167. loginName: '',
  168. companyDTO: {
  169. id: ''
  170. },
  171. officeDTO: {
  172. id: ''
  173. },
  174. name: ''
  175. },
  176. filterText: '',
  177. dataListAllSelections: [], // 所有选中的数据包含跨页数据
  178. dataListSelections: [],
  179. idKey: 'id', // 标识列表数据中每一行的唯一键的名称(需要按自己的数据改一下)
  180. dataList: [],
  181. dynamicTags: [],
  182. officeTreeData: [],
  183. pageNo: 1,
  184. pageSize: 10,
  185. total: 0,
  186. orders: [],
  187. loading: false,
  188. visible: false
  189. }
  190. },
  191. props: {
  192. selectData: {
  193. type: Array,
  194. default: () => { return [] }
  195. },
  196. limit: {
  197. type: Number,
  198. default: 999999
  199. }
  200. },
  201. watch: {
  202. filterText (val) {
  203. this.$refs.officeTree.filter(val)
  204. }
  205. },
  206. methods: {
  207. init () {
  208. this.visible = true
  209. this.$nextTick(() => {
  210. this.dataListAllSelections = JSON.parse(JSON.stringify(this.selectData))
  211. this.refreshTree()
  212. this.resetSearch()
  213. })
  214. },
  215. renderContent (h, { node, data }) {
  216. return (
  217. <span class="custom-tree-node">
  218. {
  219. data.type === '1' ? <i class="fa fa-sitemap"></i> : <i class="fa fa-users"></i>
  220. }
  221. <span class="text">{node.label}</span>
  222. </span>
  223. )
  224. },
  225. getTemplateRow (index, row) { // 获取选中数据
  226. this.dataListSelections = [row]
  227. this.$nextTick(() => {
  228. this.changePageCoreRecordData()
  229. })
  230. },
  231. // 设置选中的方法
  232. setSelectRow () {
  233. if (!this.dataListAllSelections || this.dataListAllSelections.length <= 0) {
  234. this.$refs.userTable.clearSelection()
  235. return
  236. }
  237. // 标识当前行的唯一键的名称
  238. let idKey = this.idKey
  239. let selectAllIds = []
  240. this.dataListAllSelections.forEach(row => {
  241. selectAllIds.push(row[idKey])
  242. })
  243. this.$refs.userTable.clearSelection()
  244. for (var i = 0; i < this.dataList.length; i++) {
  245. if (selectAllIds.indexOf(this.dataList[i][idKey]) >= 0) {
  246. // 设置选中,记住table组件需要使用ref="table"
  247. this.$refs.userTable.toggleRowSelection(this.dataList[i], true)
  248. }
  249. }
  250. },
  251. // 记忆选择核心方法
  252. changePageCoreRecordData () {
  253. // 标识当前行的唯一键的名称
  254. let idKey = this.idKey
  255. let that = this
  256. // 如果总记忆中还没有选择的数据,那么就直接取当前页选中的数据,不需要后面一系列计算
  257. if (this.dataListAllSelections.length <= 0) {
  258. this.dataListSelections.forEach(row => {
  259. that.dataListAllSelections.push(row)
  260. })
  261. return
  262. }
  263. // 总选择里面的key集合
  264. let selectAllIds = []
  265. this.dataListAllSelections.forEach(row => {
  266. selectAllIds.push(row[idKey])
  267. })
  268. let selectIds = []
  269. // 获取当前页选中的id
  270. this.dataListSelections.forEach(row => {
  271. selectIds.push(row[idKey])
  272. // 如果总选择里面不包含当前页选中的数据,那么就加入到总选择集合里
  273. if (selectAllIds.indexOf(row[idKey]) < 0) {
  274. that.dataListAllSelections.push(row)
  275. }
  276. })
  277. let noSelectIds = []
  278. // 得到当前页没有选中的id
  279. this.dataList.forEach(row => {
  280. if (selectIds.indexOf(row[idKey]) < 0) {
  281. noSelectIds.push(row[idKey])
  282. }
  283. })
  284. noSelectIds.forEach(id => {
  285. if (selectAllIds.indexOf(id) >= 0) {
  286. for (let i = 0; i < that.dataListAllSelections.length; i++) {
  287. if (that.dataListAllSelections[i][idKey] === id) {
  288. // 如果总选择中有未被选中的,那么就删除这条
  289. that.dataListAllSelections.splice(i, 1)
  290. break
  291. }
  292. }
  293. }
  294. })
  295. },
  296. // 得到选中的所有数据
  297. getAllSelectionData () {
  298. // 再执行一次记忆勾选数据匹配,目的是为了在当前页操作勾选后直接获取选中数据
  299. this.changePageCoreRecordData()
  300. },
  301. filterNode (value, data) {
  302. if (!value) return true
  303. return data.name.indexOf(value) !== -1
  304. },
  305. del (tag) {
  306. this.dataListAllSelections.splice(this.dataListAllSelections.indexOf(tag), 1)
  307. this.$nextTick(() => {
  308. this.setSelectRow()
  309. })
  310. },
  311. // 获取数据列表
  312. refreshList () {
  313. if (this.commonJS.isEmpty(this.searchForm.officeDTO.id) && this.commonJS.isEmpty(this.searchForm.companyDTO.id)) {
  314. this.searchForm.selectAll = 'true'
  315. }
  316. this.loading = true
  317. this.$http({
  318. url: '/system-server/sys/user/list2',
  319. method: 'get',
  320. params: {
  321. 'current': this.pageNo,
  322. 'size': this.pageSize,
  323. 'orders': this.orders,
  324. ...this.searchForm
  325. }
  326. }).then((data) => {
  327. this.dataList = data.records
  328. this.total = data.total
  329. this.pageNo = data.current
  330. this.loading = false
  331. this.$nextTick(() => {
  332. this.setSelectRow()
  333. })
  334. })
  335. },
  336. refreshTree () {
  337. this.$http({
  338. url: `/system-server/sys/office/treeData`,
  339. method: 'get'
  340. }).then((data) => {
  341. this.officeTreeData = data
  342. })
  343. },
  344. // 每页数
  345. sizeChangeHandle (val) {
  346. this.pageSize = val
  347. this.pageNo = 1
  348. this.refreshList()
  349. this.$nextTick(() => {
  350. this.changePageCoreRecordData()
  351. })
  352. },
  353. // 当前页
  354. currentChangeHandle (val) {
  355. this.pageNo = val
  356. this.refreshList()
  357. this.$nextTick(() => {
  358. this.changePageCoreRecordData()
  359. })
  360. },
  361. // 多选
  362. selectionChangeHandle (val) {
  363. this.dataListSelections = val
  364. this.$nextTick(() => {
  365. this.changePageCoreRecordData()
  366. })
  367. },
  368. // 排序
  369. sortChangeHandle (column) {
  370. if (column.prop === 'officeDTO.name') {
  371. column.prop = 'o.name'
  372. }
  373. if (column.prop === 'companyDTO.name') {
  374. column.prop = 'c.name'
  375. }
  376. this.orders = []
  377. if (column.order != null) {
  378. this.orders.push({column: this.$utils.toLine(column.prop), asc: column.order === 'ascending'})
  379. }
  380. this.refreshList()
  381. },
  382. handleNodeClick (data) {
  383. if (data.type === '1') {
  384. this.searchForm.companyDTO.id = data.id
  385. this.searchForm.officeDTO.id = ''
  386. } else {
  387. this.searchForm.companyDTO.id = ''
  388. this.searchForm.officeDTO.id = data.id
  389. }
  390. this.refreshList()
  391. },
  392. resetSearch () {
  393. this.searchForm.companyDTO.id = ''
  394. this.searchForm.officeDTO.id = ''
  395. this.$refs.officeTree.setCurrentKey(null)
  396. this.$refs.searchForm.resetFields()
  397. this.refreshList()
  398. },
  399. doSubmit () {
  400. if (this.limit < this.dataListAllSelections.length) {
  401. this.$message.error(`你最多只能选择${this.limit}个用户`)
  402. return
  403. }
  404. this.visible = false
  405. this.$emit('doSubmit', this.dataListAllSelections)
  406. }
  407. }
  408. }
  409. </script>
  410. <style lang="scss">
  411. .org {
  412. height: 100%;
  413. .el-card__header {
  414. padding: 10px;
  415. }
  416. .el-card__body {
  417. padding: 10px;
  418. max-height: 520px;
  419. overflow: auto;
  420. }
  421. }
  422. .userDialog{
  423. .el-dialog__body {
  424. padding: 10px 0px 0px 10px;
  425. color: #606266;
  426. font-size: 14px;
  427. word-break: break-all;
  428. }
  429. .el-main {
  430. padding: 20px 20px 5px 20px;
  431. .el-pagination{
  432. margin-top: 5px;
  433. }
  434. }
  435. }
  436. </style>