authority.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <template>
  2. <div class="authority">
  3. <warning-bar title="注:右上角头像下拉可切换角色" />
  4. <div class="gva-table-box">
  5. <div class="gva-btn-list">
  6. <el-button
  7. type="primary"
  8. icon="plus"
  9. @click="addAuthority(0)"
  10. >新增角色</el-button>
  11. </div>
  12. <el-table
  13. :data="tableData"
  14. :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  15. row-key="authorityId"
  16. style="width: 100%"
  17. >
  18. <el-table-column
  19. label="角色ID"
  20. min-width="180"
  21. prop="authorityId"
  22. />
  23. <el-table-column
  24. align="left"
  25. label="角色名称"
  26. min-width="180"
  27. prop="authorityName"
  28. />
  29. <el-table-column
  30. align="left"
  31. label="操作"
  32. width="460"
  33. >
  34. <template #default="scope">
  35. <el-button
  36. icon="setting"
  37. type="primary"
  38. link
  39. @click="openDrawer(scope.row)"
  40. >设置权限</el-button>
  41. <el-button
  42. icon="plus"
  43. type="primary"
  44. link
  45. @click="addAuthority(scope.row.authorityId)"
  46. >新增子角色</el-button>
  47. <el-button
  48. icon="copy-document"
  49. type="primary"
  50. link
  51. @click="copyAuthorityFunc(scope.row)"
  52. >拷贝</el-button>
  53. <el-button
  54. icon="edit"
  55. type="primary"
  56. link
  57. @click="editAuthority(scope.row)"
  58. >编辑</el-button>
  59. <el-button
  60. icon="delete"
  61. type="primary"
  62. link
  63. @click="deleteAuth(scope.row)"
  64. >删除</el-button>
  65. </template>
  66. </el-table-column>
  67. </el-table>
  68. </div>
  69. <!-- 新增角色弹窗 -->
  70. <el-dialog
  71. v-model="dialogFormVisible"
  72. :title="dialogTitle"
  73. >
  74. <el-form
  75. ref="authorityForm"
  76. :model="form"
  77. :rules="rules"
  78. label-width="80px"
  79. >
  80. <el-form-item
  81. label="父级角色"
  82. prop="parentId"
  83. >
  84. <el-cascader
  85. v-model="form.parentId"
  86. style="width:100%"
  87. :disabled="dialogType==='add'"
  88. :options="AuthorityOption"
  89. :props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
  90. :show-all-levels="false"
  91. filterable
  92. />
  93. </el-form-item>
  94. <el-form-item
  95. label="角色ID"
  96. prop="authorityId"
  97. >
  98. <el-input
  99. v-model="form.authorityId"
  100. :disabled="dialogType==='edit'"
  101. autocomplete="off"
  102. maxlength="15"
  103. />
  104. </el-form-item>
  105. <el-form-item
  106. label="角色姓名"
  107. prop="authorityName"
  108. >
  109. <el-input
  110. v-model="form.authorityName"
  111. autocomplete="off"
  112. />
  113. </el-form-item>
  114. </el-form>
  115. <template #footer>
  116. <div class="dialog-footer">
  117. <el-button @click="closeDialog">取 消</el-button>
  118. <el-button
  119. type="primary"
  120. @click="enterDialog"
  121. >确 定</el-button>
  122. </div>
  123. </template>
  124. </el-dialog>
  125. <el-drawer
  126. v-if="drawer"
  127. v-model="drawer"
  128. :with-header="false"
  129. size="40%"
  130. title="角色配置"
  131. >
  132. <el-tabs
  133. :before-leave="autoEnter"
  134. type="border-card"
  135. >
  136. <el-tab-pane label="角色菜单">
  137. <Menus
  138. ref="menus"
  139. :row="activeRow"
  140. @changeRow="changeRow"
  141. />
  142. </el-tab-pane>
  143. <el-tab-pane label="角色api">
  144. <Apis
  145. ref="apis"
  146. :row="activeRow"
  147. @changeRow="changeRow"
  148. />
  149. </el-tab-pane>
  150. <el-tab-pane label="资源权限">
  151. <Datas
  152. ref="datas"
  153. :authority="tableData"
  154. :row="activeRow"
  155. @changeRow="changeRow"
  156. />
  157. </el-tab-pane>
  158. </el-tabs>
  159. </el-drawer>
  160. </div>
  161. </template>
  162. <script setup>
  163. import {
  164. getAuthorityList,
  165. deleteAuthority,
  166. createAuthority,
  167. updateAuthority,
  168. copyAuthority
  169. } from '@/api/authority'
  170. import Menus from '@/view/superAdmin/authority/components/menus.vue'
  171. import Apis from '@/view/superAdmin/authority/components/apis.vue'
  172. import Datas from '@/view/superAdmin/authority/components/datas.vue'
  173. import WarningBar from '@/components/warningBar/warningBar.vue'
  174. import { ref } from 'vue'
  175. import { ElMessage, ElMessageBox } from 'element-plus'
  176. import { toDoc } from '@/utils/doc'
  177. import { VideoCameraFilled } from '@element-plus/icons-vue'
  178. defineOptions({
  179. name: 'Authority'
  180. })
  181. const mustUint = (rule, value, callback) => {
  182. if (!/^[0-9]*[1-9][0-9]*$/.test(value)) {
  183. return callback(new Error('请输入正整数'))
  184. }
  185. return callback()
  186. }
  187. const AuthorityOption = ref([
  188. {
  189. authorityId: 0,
  190. authorityName: '根角色'
  191. }
  192. ])
  193. const drawer = ref(false)
  194. const dialogType = ref('add')
  195. const activeRow = ref({})
  196. const dialogTitle = ref('新增角色')
  197. const dialogFormVisible = ref(false)
  198. const apiDialogFlag = ref(false)
  199. const copyForm = ref({})
  200. const form = ref({
  201. authorityId: 0,
  202. authorityName: '',
  203. parentId: 0
  204. })
  205. const rules = ref({
  206. authorityId: [
  207. { required: true, message: '请输入角色ID', trigger: 'blur' },
  208. { validator: mustUint, trigger: 'blur', message: '必须为正整数' }
  209. ],
  210. authorityName: [
  211. { required: true, message: '请输入角色名', trigger: 'blur' }
  212. ],
  213. parentId: [
  214. { required: true, message: '请选择父角色', trigger: 'blur' },
  215. ]
  216. })
  217. const page = ref(1)
  218. const total = ref(0)
  219. const pageSize = ref(999)
  220. const tableData = ref([])
  221. const searchInfo = ref({})
  222. // 查询
  223. const getTableData = async() => {
  224. const table = await getAuthorityList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
  225. if (table.code === 0) {
  226. tableData.value = table.data.list
  227. total.value = table.data.total
  228. page.value = table.data.page
  229. pageSize.value = table.data.pageSize
  230. }
  231. }
  232. getTableData()
  233. const changeRow = (key, value) => {
  234. activeRow.value[key] = value
  235. }
  236. const menus = ref(null)
  237. const apis = ref(null)
  238. const datas = ref(null)
  239. const autoEnter = (activeName, oldActiveName) => {
  240. const paneArr = [menus, apis, datas]
  241. if (oldActiveName) {
  242. if (paneArr[oldActiveName].value.needConfirm) {
  243. paneArr[oldActiveName].value.enterAndNext()
  244. paneArr[oldActiveName].value.needConfirm = false
  245. }
  246. }
  247. }
  248. // 拷贝角色
  249. const copyAuthorityFunc = (row) => {
  250. setOptions()
  251. dialogTitle.value = '拷贝角色'
  252. dialogType.value = 'copy'
  253. for (const k in form.value) {
  254. form.value[k] = row[k]
  255. }
  256. copyForm.value = row
  257. dialogFormVisible.value = true
  258. }
  259. const openDrawer = (row) => {
  260. drawer.value = true
  261. activeRow.value = row
  262. }
  263. // 删除角色
  264. const deleteAuth = (row) => {
  265. ElMessageBox.confirm('此操作将永久删除该角色, 是否继续?', '提示', {
  266. confirmButtonText: '确定',
  267. cancelButtonText: '取消',
  268. type: 'warning'
  269. })
  270. .then(async() => {
  271. const res = await deleteAuthority({ authorityId: row.authorityId })
  272. if (res.code === 0) {
  273. ElMessage({
  274. type: 'success',
  275. message: '删除成功!'
  276. })
  277. if (tableData.value.length === 1 && page.value > 1) {
  278. page.value--
  279. }
  280. getTableData()
  281. }
  282. })
  283. .catch(() => {
  284. ElMessage({
  285. type: 'info',
  286. message: '已取消删除'
  287. })
  288. })
  289. }
  290. // 初始化表单
  291. const authorityForm = ref(null)
  292. const initForm = () => {
  293. if (authorityForm.value) {
  294. authorityForm.value.resetFields()
  295. }
  296. form.value = {
  297. authorityId: 0,
  298. authorityName: '',
  299. parentId: 0
  300. }
  301. }
  302. // 关闭窗口
  303. const closeDialog = () => {
  304. initForm()
  305. dialogFormVisible.value = false
  306. apiDialogFlag.value = false
  307. }
  308. // 确定弹窗
  309. const enterDialog = () => {
  310. authorityForm.value.validate(async valid => {
  311. if (valid) {
  312. form.value.authorityId = Number(form.value.authorityId)
  313. switch (dialogType.value) {
  314. case 'add':
  315. {
  316. const res = await createAuthority(form.value)
  317. if (res.code === 0) {
  318. ElMessage({
  319. type: 'success',
  320. message: '添加成功!'
  321. })
  322. getTableData()
  323. closeDialog()
  324. }
  325. }
  326. break
  327. case 'edit':
  328. {
  329. const res = await updateAuthority(form.value)
  330. if (res.code === 0) {
  331. ElMessage({
  332. type: 'success',
  333. message: '添加成功!'
  334. })
  335. getTableData()
  336. closeDialog()
  337. }
  338. }
  339. break
  340. case 'copy': {
  341. const data = {
  342. authority: {
  343. authorityId: 0,
  344. authorityName: '',
  345. datauthorityId: [],
  346. parentId: 0
  347. },
  348. oldAuthorityId: 0
  349. }
  350. data.authority.authorityId = form.value.authorityId
  351. data.authority.authorityName = form.value.authorityName
  352. data.authority.parentId = form.value.parentId
  353. data.authority.dataAuthorityId = copyForm.value.dataAuthorityId
  354. data.oldAuthorityId = copyForm.value.authorityId
  355. const res = await copyAuthority(data)
  356. if (res.code === 0) {
  357. ElMessage({
  358. type: 'success',
  359. message: '复制成功!'
  360. })
  361. getTableData()
  362. }
  363. }
  364. }
  365. initForm()
  366. dialogFormVisible.value = false
  367. }
  368. })
  369. }
  370. const setOptions = () => {
  371. AuthorityOption.value = [
  372. {
  373. authorityId: 0,
  374. authorityName: '根角色'
  375. }
  376. ]
  377. setAuthorityOptions(tableData.value, AuthorityOption.value, false)
  378. }
  379. const setAuthorityOptions = (AuthorityData, optionsData, disabled) => {
  380. AuthorityData &&
  381. AuthorityData.forEach(item => {
  382. if (item.children && item.children.length) {
  383. const option = {
  384. authorityId: item.authorityId,
  385. authorityName: item.authorityName,
  386. disabled: disabled || item.authorityId === form.value.authorityId,
  387. children: []
  388. }
  389. setAuthorityOptions(
  390. item.children,
  391. option.children,
  392. disabled || item.authorityId === form.value.authorityId
  393. )
  394. optionsData.push(option)
  395. } else {
  396. const option = {
  397. authorityId: item.authorityId,
  398. authorityName: item.authorityName,
  399. disabled: disabled || item.authorityId === form.value.authorityId
  400. }
  401. optionsData.push(option)
  402. }
  403. })
  404. }
  405. // 增加角色
  406. const addAuthority = (parentId) => {
  407. initForm()
  408. dialogTitle.value = '新增角色'
  409. dialogType.value = 'add'
  410. form.value.parentId = parentId
  411. setOptions()
  412. dialogFormVisible.value = true
  413. }
  414. // 编辑角色
  415. const editAuthority = (row) => {
  416. setOptions()
  417. dialogTitle.value = '编辑角色'
  418. dialogType.value = 'edit'
  419. for (const key in form.value) {
  420. form.value[key] = row[key]
  421. }
  422. setOptions()
  423. dialogFormVisible.value = true
  424. }
  425. </script>
  426. <style lang="scss">
  427. .authority {
  428. .el-input-number {
  429. margin-left: 15px;
  430. span {
  431. display: none;
  432. }
  433. }
  434. }
  435. .tree-content{
  436. margin-top: 10px;
  437. height: calc(100vh - 158px);
  438. overflow: auto;
  439. }
  440. </style>