permissionList.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <template>
  2. <div v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" class="permissionList">
  3. <div class="permissionList_tree">
  4. <div class="permissionList_tree_head flex">
  5. <div class="permissionList_tree_head_list">名称</div>
  6. <div class="permissionList_tree_head_list">类型</div>
  7. <div class="permissionList_tree_head_list">行权限</div>
  8. <div class="permissionList_tree_head_list">操作</div>
  9. </div>
  10. <div class="permissionList_tree_body">
  11. <el-scrollbar style="height: 100%" :horizontal="false">
  12. <el-tree ref="tree" :data="data" show-checkbox node-key="pageconfigurationid" default-expand-all :expand-on-click-node="false" @check="checkChange">
  13. <template slot-scope="{node,data}">
  14. <div class="custom-tree-node flex">
  15. <div class="custom-tree-node-list">{{data.pagename}}</div>
  16. <div class="custom-tree-node-list">{{data.pagetype}}</div>
  17. <div class="custom-tree-node-list">
  18. <el-tooltip class="item" effect="dark" :content="data.selectcolumnlist" placement="top">
  19. <div class="tmsg">{{ data.selectcolumnlist }}</div>
  20. </el-tooltip>
  21. </div>
  22. <div class="custom-tree-node-list">
  23. <template v-if="data.pagetype == 'table'">
  24. <el-button size="mini" type="text" @click="details(node, data)">行权限</el-button>
  25. </template>
  26. </div>
  27. </div>
  28. </template>
  29. </el-tree>
  30. </el-scrollbar>
  31. </div>
  32. </div>
  33. <div class="permissionList_dialog">
  34. <!--高级查询-->
  35. <PublicPageDialog dialog-title="行权限" dialogSize="600px" :dialog-drawer="advancedDrawer" @handleClose="advancedDrawer = false" @handleSubmit="advancedTable('advancedDialogForm')">
  36. <AdvancedQuery ref="advancedDialogForm" :select-options="selectOptions" :ad-list="false" :ad-dep="adDep" @getAdvancedQueryData="getAdvancedQueryData" />
  37. </PublicPageDialog>
  38. </div>
  39. </div>
  40. </template>
  41. <script>
  42. import PublicPageDialog from '@/components/PublicPageDialog'
  43. import AdvancedQuery from '@/components/AdvancedQuery'
  44. import { mapGetters } from 'vuex'
  45. import { listToTree } from '@/utils/validate'
  46. import { Query, newData, modifyData, moveData, getAuthorization, authorization } from "@/api/webApi"
  47. import { formatChange } from '@/utils/validate'
  48. export default {
  49. name: 'Permissionlist',
  50. props: {
  51. listMap: {
  52. type: Object,
  53. default: () => new Object()
  54. },
  55. treeMap: {
  56. type: Object,
  57. default: () => new Object()
  58. }
  59. },
  60. components: { PublicPageDialog, AdvancedQuery },
  61. data () {
  62. return {
  63. advancedDrawer: false,
  64. loading: false,
  65. ischeck: false,
  66. data: [],
  67. defaultProps: {
  68. children: 'children',
  69. label: 'pagename'
  70. },
  71. defaultKeys: [],
  72. nodeKey: 'pageconfigurationid',
  73. adDep: 1,
  74. dataKey: 'pagename',
  75. checkDatas: [],
  76. queryItem: {},
  77. tableKey: '',
  78. rowData: {},
  79. selectOptions: [],
  80. queryId: 6,
  81. allAuthData: [],
  82. }
  83. },
  84. watch: {
  85. listMap: {
  86. handler (row) {
  87. if (Object.keys(row).length) {
  88. const queryItem = _.cloneDeep(row)
  89. if (queryItem.children) delete queryItem.children
  90. this.ischeck = true
  91. this.checkDatas = []
  92. this.queryItem = queryItem
  93. this.$refs.tree.setCheckedKeys([])
  94. this.queryTreeData(queryItem, '权限')
  95. }
  96. },
  97. deep: true,
  98. immediate: true
  99. },
  100. treeMap: {
  101. handler (obj) {
  102. if (Object.keys(obj).length) {
  103. const { serviceid, pagename } = obj
  104. this.queryAllAuthData(serviceid, pagename)
  105. }
  106. },
  107. deep: true,
  108. immediate: true
  109. }
  110. },
  111. computed: {
  112. ...mapGetters(['authArrs'])
  113. },
  114. methods: {
  115. async queryAllAuthData (serviceid, pagename) {
  116. this.loading = true;
  117. const datacontent = { filter: { 1: 1 } }
  118. try {
  119. const { code, returnData } = await Query({
  120. serviceid,
  121. datacontent,
  122. event: '0'
  123. });
  124. if (code == 0 && returnData?.length) {
  125. this.allAuthData = _.cloneDeep(returnData)
  126. this.setAuthData([], returnData)
  127. } else {
  128. this.$message.error(`获取${pagename}数据失败`);
  129. }
  130. } catch (error) {
  131. this.$message.error(`获取${pagename}数据失败`);
  132. }
  133. this.loading = false;
  134. },
  135. disableTreeData (arr = []) {
  136. if (!arr.length) return
  137. const alldata = _.cloneDeep(arr)
  138. const isdata = _.cloneDeep(this.authArrs)
  139. const nodata = this.findRepetData(alldata, isdata)
  140. if (nodata?.length) {
  141. alldata.map(item => {
  142. nodata.map(ci => {
  143. if (item.pageconfigurationid == ci.pageconfigurationid) {
  144. item.disabled = true
  145. }
  146. })
  147. })
  148. }
  149. return alldata
  150. },
  151. restDataRow () {
  152. this.ischeck = true
  153. this.checkDatas = []
  154. this.$refs.tree.setCheckedKeys([])
  155. this.queryTreeData(this.queryItem, '权限')
  156. },
  157. //高级查询-提交
  158. advancedTable (refName) {
  159. this.$refs[refName].advancedQueryHandler()
  160. },
  161. getAdvancedQueryData (dataRules) {
  162. const ndata = this.checkDatas?.at(-1)
  163. const nitem = ndata.filter(item => item.pageconfigurationid == this.rowData.pageconfigurationid)
  164. const { id, supergroupid, type } = this.queryItem
  165. const { pageconfigurationid, serviceid, selectcolumnlist = '', insetcolumnlist = '', updatecolumnlist = '', filterset = '' } = nitem[0]
  166. const rowData = {
  167. pageconfigurationid,
  168. serviceid,
  169. selectcolumnlist,
  170. insetcolumnlist,
  171. updatecolumnlist,
  172. filterset
  173. }
  174. rowData.selectcolumnlist = JSON.stringify(dataRules)
  175. if (type == 1) {
  176. rowData.userid = id
  177. this.queryId = 7
  178. } else {
  179. rowData.usergroupid = id
  180. this.queryId = 6
  181. }
  182. this.sendCheckData('edit', [rowData])
  183. // this.$nextTick(() => {
  184. // this.restDataRow()
  185. // })
  186. this.advancedDrawer = false
  187. },
  188. formatRowAuth (nstr, arr) {
  189. if (!nstr || !arr) return []
  190. const nitem = JSON.parse(nstr)
  191. const tableValues = [...arr]
  192. if (nitem?.length && tableValues?.length) {
  193. const htmls = []
  194. const ndatas = [...nitem]
  195. tableValues.map(({ pagename, pagecode }) => {
  196. ndatas.map(({ column, comparator, connector, value }) => {
  197. if (pagecode == column) {
  198. const comparatorfh = comparator == '=' ? '等于' : '不等于'
  199. const connectorfh = connector == 'and' ? '并且' : connector == 'or' ? '或者' : ''
  200. const str = pagename + comparatorfh + value + connectorfh
  201. htmls.push(str)
  202. }
  203. })
  204. })
  205. return htmls
  206. }
  207. },
  208. //打开行权限
  209. details (node, data) {
  210. if (!this.ischeck) {
  211. this.$message.error('请先选中左边的权限树后再操作')
  212. this.$refs.tree.setCheckedKeys([])
  213. return
  214. }
  215. if (!this.checkDatas.length) {
  216. this.$message.error('请先勾选权限后再操作')
  217. return
  218. }
  219. const ndata = _.cloneDeep(data)
  220. const { pageconfigurationid } = ndata
  221. const nitem = this.checkDatas?.at(-1).filter(item => item.pageconfigurationid == pageconfigurationid)
  222. if (!nitem.length) {
  223. this.$message.error('请先勾选权限后再操作')
  224. return
  225. }
  226. this.adDep = Math.random()
  227. this.rowData = ndata
  228. sessionStorage.setItem('tableColumns', JSON.stringify({ tableKey: pageconfigurationid, tableValues: ndata.children }))
  229. this.$store.dispatch('auth/changeAuthMsg', ndata.children)
  230. if (data.selectcolumnmsg) {
  231. this.selectOptions = JSON.parse(data.selectcolumnmsg)
  232. }
  233. this.advancedDrawer = true
  234. },
  235. //初始化数据
  236. setAuthData (arrs = [], returnData = []) {
  237. const narrs = _.cloneDeep(arrs)
  238. const ndata = _.cloneDeep(returnData)
  239. if (narrs.length) {
  240. ndata.map(item => {
  241. narrs.map(ci => {
  242. if (item.pageconfigurationid == ci.pageconfigurationid && ci.selectcolumnlist) {
  243. const tableColumnArrs = ndata.filter(item => item['superiorid'] == ci.pageconfigurationid && item['pagetype'] == 'column')
  244. const htmls = this.formatRowAuth(ci.selectcolumnlist, tableColumnArrs)
  245. item.selectcolumnmsg = ci.selectcolumnlist
  246. item.selectcolumnlist = htmls.join('')
  247. }
  248. })
  249. })
  250. }
  251. const alldata = this.disableTreeData(ndata)
  252. const treeMenu = listToTree([...alldata], 'superiorid', 'pageconfigurationid')
  253. this.data = treeMenu
  254. },
  255. //勾选已有权限
  256. checkAuthData (ndata) {
  257. const returnData = _.cloneDeep(ndata)
  258. if (ndata?.length) {
  259. const ids = []
  260. ndata.map(({ pageconfigurationid }) => {
  261. ids.push(pageconfigurationid)
  262. })
  263. this.$refs.tree.setCheckedKeys(ids)
  264. const treeDatas = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes())
  265. const res = this.findRepetData(treeDatas, returnData)
  266. if (res?.length) {
  267. res.map((item) => {
  268. if (item.pageconfigurationid) {
  269. this.$refs.tree.setChecked(item.pageconfigurationid, false, false);
  270. }
  271. })
  272. }
  273. this.checkDatas.push(ndata)
  274. }
  275. },
  276. //获取当前用户组/用户已有权限
  277. async queryTreeData (dataContent, pagename) {
  278. this.loading = true;
  279. try {
  280. const { code, returnData } = await getAuthorization({ datacontent: dataContent });
  281. if (code == 0) {
  282. const ndata = _.cloneDeep(returnData)
  283. this.setAuthData(ndata, this.allAuthData)
  284. this.$nextTick(() => {
  285. this.checkAuthData(ndata)
  286. })
  287. } else {
  288. this.$message.error(`获取${pagename}数据失败`);
  289. }
  290. } catch (error) {
  291. this.$message.error(`获取${pagename}数据失败`);
  292. }
  293. this.loading = false;
  294. },
  295. checkChange () {
  296. if (!this.ischeck) {
  297. this.$message.error('请先选中左边的权限树后再操作')
  298. this.$refs.tree.setCheckedKeys([])
  299. return
  300. }
  301. const checks = this.$refs.tree.getCheckedNodes() //选中
  302. const halfchecks = this.$refs.tree.getHalfCheckedNodes() //半选中
  303. const allchecks = [...checks, ...halfchecks]
  304. this.checkDatas.push(allchecks)
  305. this.isAddorDel()
  306. },
  307. isAddorDel () {
  308. const ndatas = _.cloneDeep(this.checkDatas)
  309. if (ndatas.length == 1) {
  310. this.sendCheckData('add', ndatas[0])
  311. } else {
  312. const [nitems1, nitems2] = [ndatas.at(-1), ndatas.at(-2)]
  313. if (nitems1.length > nitems2.length) {
  314. const res = this.findRepetData(nitems1, nitems2)
  315. this.sendCheckData('add', res)
  316. } else {
  317. const res = this.findRepetData(nitems1, nitems2)
  318. this.sendCheckData('del', res)
  319. }
  320. }
  321. },
  322. findRepetData (nitems1, nitems2) {
  323. const key = 'pageconfigurationid'
  324. const res = [...nitems1, ...nitems2].filter(
  325. (item) =>
  326. !(
  327. nitems1.some((p) => item[key] == p[key]) &&
  328. nitems2.some((c) => item[key] == c[key])
  329. )
  330. )
  331. return res
  332. },
  333. //发送新增编辑删除数据
  334. sendCheckData (types, data) {
  335. const event = types == 'add' ? 1 : types == 'edit' ? 2 : 3
  336. const querys = []
  337. const items = _.cloneDeep(data)
  338. const { id, type } = this.queryItem
  339. if (types == 'edit') {
  340. items.map(item => {
  341. if (item.children) delete item.children
  342. })
  343. const params = {
  344. serviceid: this.queryId,
  345. datacontent: [
  346. {
  347. filter: {
  348. pageconfigurationid: items[0].pageconfigurationid
  349. },
  350. value: items[0]
  351. }
  352. ],
  353. event,
  354. }
  355. type == 1 ? params.datacontent[0].filter.userid = items[0].userid : params.datacontent[0].filter.usergroupid = items[0].usergroupid
  356. querys.push(modifyData(params))
  357. } else {
  358. const ids = []
  359. items.map(item => {
  360. if (item.children) delete item.children
  361. ids.push(item.pageconfigurationid)
  362. })
  363. const params = {
  364. id,
  365. type,
  366. datacontent: ids,
  367. event
  368. }
  369. querys.push(authorization(params))
  370. }
  371. this.getAnscyData(querys)
  372. },
  373. //获取异步数据
  374. async getAnscyData (allResult) {
  375. if (!allResult.length) return
  376. this.loading = true
  377. const results = await Promise.allSettled(allResult)
  378. results.map((item) => {
  379. const { status, value } = item
  380. if (status == 'fulfilled') {
  381. const { code } = value
  382. if (code == 0) {
  383. this.$message.success('操作成功')
  384. } else {
  385. this.$message.error('操作失败')
  386. }
  387. } else {
  388. this.$message.error('网络错误')
  389. }
  390. })
  391. this.loading = false
  392. }
  393. }
  394. }
  395. </script>
  396. <style lang="scss" scoped>
  397. .permissionList {
  398. height: 100%;
  399. &_tree {
  400. height: 100%;
  401. &_head {
  402. height: 42px;
  403. line-height: 42px;
  404. background-color: #f0f6ff;
  405. font-size: 16px;
  406. font-size: 600;
  407. &_list {
  408. padding: 0 20px;
  409. width: 25%;
  410. }
  411. }
  412. ::v-deep &_body {
  413. height: calc(100% - 52px);
  414. .el-scrollbar__wrap {
  415. overflow-x: hidden;
  416. }
  417. .is-horizontal {
  418. display: none;
  419. }
  420. .el-tree-node {
  421. &__content {
  422. height: 49px;
  423. border-top: 1px solid #d6d4d4;
  424. }
  425. }
  426. .custom-tree-node {
  427. width: 100%;
  428. line-height: 28px;
  429. &-list {
  430. padding-right: 20px;
  431. width: 25%;
  432. &:last-child {
  433. padding-right: 0;
  434. }
  435. }
  436. .tmsg {
  437. white-space: nowrap;
  438. text-overflow: ellipsis;
  439. overflow: hidden;
  440. }
  441. }
  442. }
  443. }
  444. }
  445. </style>