You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

856 lines
28 KiB

3 months ago
3 months ago
3 months ago
3 months ago
4 weeks ago
2 months ago
3 months ago
3 months ago
3 months ago
4 weeks ago
2 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
4 weeks ago
3 months ago
3 months ago
4 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
4 weeks ago
2 months ago
3 months ago
3 months ago
4 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <script setup>
  2. import { nextTick, onMounted, reactive, ref } from 'vue'
  3. import { ElMessage } from 'element-plus'
  4. import _ from 'lodash'
  5. import request from '@/util/http'
  6. import API from '@/util/http'
  7. import { useAdminStore } from "@/store/index.js"
  8. import { storeToRefs } from "pinia"
  9. const adminStore = useAdminStore();
  10. const { adminData, menuTree } = storeToRefs(adminStore);
  11. import { permissionMapping, findMenuById } from "@/utils/menuTreePermission.js"
  12. import { tr } from 'element-plus/es/locales.mjs'
  13. // 表单验证ref
  14. const Ref = ref(null)
  15. const roleData = ref([])
  16. const roleTotal = ref(100)
  17. const treeRef = ref(null)
  18. const admin = ref({
  19. account: '',
  20. market: '',
  21. postiton: ''
  22. })
  23. const role = ref({
  24. name: ''
  25. })
  26. const getRoleObj = ref({
  27. pageNum: 1,
  28. pageSize: 10
  29. })
  30. const permissionAddVisible = ref(false)
  31. const addRole = ref({
  32. roleName: '',
  33. parentId: null,
  34. checkedKeys: [],
  35. market: ''
  36. })
  37. const addRoleMarket = ref([])
  38. const channelList = ref(['全部'])
  39. const getRoleList = async function (val) {
  40. if (!findMenuById(menuTree.value, permissionMapping.view_role_information)) {
  41. ElMessage.error('无此权限')
  42. return
  43. }
  44. try {
  45. if (typeof val === 'number') {
  46. getRoleObj.value.pageNum = val
  47. }
  48. console.log('搜索参数', getRoleObj.value, role.value)
  49. const result = await request({
  50. url: '/role/selectBy',
  51. data: {
  52. ...getRoleObj.value,
  53. roleVo: {
  54. roleName: role.value.name
  55. }
  56. }
  57. })
  58. roleData.value = result.data.list
  59. console.log('roleData', roleData.value)
  60. roleTotal.value = result.data.total
  61. } catch (error) {
  62. console.log('请求失败', error)
  63. }
  64. }
  65. // 试试D老师的方法
  66. const formatPermissions = (tree) => {
  67. if (!tree || tree.length === 0) return '';
  68. return tree.map(menu => {
  69. const mainMenu = menu.menuName;
  70. const subMenus = menu.children?.map(child => child.menuName) || [];
  71. // 如果有子菜单,显示前2个子菜单名称
  72. if (subMenus.length > 0) {
  73. const maxSub = Math.min(2, subMenus.length);
  74. const subText = subMenus.slice(0, maxSub).join('、');
  75. const moreText = subMenus.length > maxSub ? '...' : '';
  76. return `${mainMenu}+${subText}${moreText}`;
  77. }
  78. // 没有子菜单时只显示主菜单
  79. return mainMenu;
  80. }).join('+');
  81. };
  82. const trimJwCode = () => {
  83. if (admin.value.account) {
  84. admin.value.account = admin.value.account.replace(/\s/g, '');
  85. }
  86. }
  87. const searchRole = function () {
  88. trimJwCode();
  89. getRoleObj.value.pageNum = 1
  90. getRoleList()
  91. }
  92. // 重置
  93. const reset = function () {
  94. admin.value = {}
  95. role.value.name = ''
  96. // 重置页码
  97. getRoleObj.value.pageNum = 1
  98. getRoleList()
  99. }
  100. const RoleArea = ref([])
  101. const getRoleArea = async function () {
  102. try {
  103. const result = await request({
  104. url: '/general/allRoleMarket',
  105. data: {}
  106. })
  107. RoleArea.value = result.data
  108. } catch (error) {
  109. console.log('请求失败', error)
  110. }
  111. }
  112. // 新增角色弹窗
  113. const openPermissionAddVisible = function () {
  114. permissionAddVisible.value = true
  115. getRoles()
  116. getLists()
  117. }
  118. const closePermissionAddVisible = function () {
  119. permissionAddVisible.value = false
  120. Ref.value.resetFields();
  121. getRoleList()
  122. }
  123. // 新增角色初始化
  124. const permissionAddInit = function () {
  125. openPermissionAddVisible()
  126. }
  127. const handleDialogClose = function () {
  128. closePermissionAddVisible()
  129. console.log('hhh');
  130. }
  131. // 权限类别
  132. const permissionList = ref([])
  133. const getRoles = async function () {
  134. try {
  135. const res = await API({ url: '/role/selectAll' })
  136. permissionList.value = res.data.map(item => ({
  137. label: item.roleName,
  138. value: item.id
  139. }))
  140. console.log('权限列表:', permissionList.value)
  141. } catch (error) {
  142. console.error('获取权限列表失败:', error)
  143. }
  144. }
  145. const collectIds = (tree) => {
  146. let ids = [];
  147. tree.forEach((node) => {
  148. ids.push(node.id);
  149. if (node.children && node.children.length > 0) {
  150. ids = ids.concat(collectIds(node.children));
  151. }
  152. });
  153. return ids;
  154. }
  155. //给data数据加上disabled属性,控制是否禁用
  156. function processTreeData(data) {
  157. return data.map(item => ({
  158. ...item,
  159. disabled: item.id != null || item.menuName.includes("敏感权限"), //控制权限显示的条件
  160. children: item.children ? processTreeData(item.children) : []
  161. }));
  162. }
  163. const handleAddRole = async function () {
  164. if (!findMenuById(menuTree.value, permissionMapping.add_role_information)) {
  165. ElMessage.error('无此权限')
  166. return
  167. }
  168. try {
  169. await new Promise((resolve, reject) => {
  170. Ref.value.validate((valid) => {
  171. if (valid) {
  172. resolve(); // 验证通过,继续执行后续代码
  173. } else {
  174. reject(new Error('请检查并完善表单信息')); // 验证失败,抛出错误
  175. }
  176. });
  177. });
  178. addRole.value.roleName = addRole.value.roleName.replace(/\s+/g, '');
  179. console.log('去除角色名空格:', addRole.value.roleName);
  180. // 确保提交时包含所有选中的权限ID(包括父节点)
  181. const finalCheckedKeys = addRole.value.checkedKeys || [];
  182. const res = await API({
  183. url: '/role/add',
  184. data: {
  185. "roleName": addRole.value.roleName,
  186. "menuIds": finalCheckedKeys,
  187. "fatherId": addRole.value.parentId,
  188. "market": addRole.value.market,
  189. channel: addRole.value.channel
  190. }
  191. })
  192. if (res.code === 200) {
  193. ElMessage.success('角色' + addRole.value.roleName + '添加成功')
  194. console.log('成功了,看看addRole', addRole.value)
  195. console.log('提交的权限ID列表:', finalCheckedKeys)
  196. closePermissionAddVisible()
  197. } else {
  198. ElMessage.error(res.msg)
  199. }
  200. } catch (error) {
  201. console.log('请求失败', error)
  202. console.log('失败,看看addRole', addRole.value)
  203. }
  204. }
  205. const handleRolePageSizeChange = (val) => {
  206. getRoleObj.value.pageSize = val
  207. getRoleList() // 调用角色管理的查询
  208. }
  209. // 角色管理分页 - 当前页变化
  210. const handleRoleCurrentChange = (val) => {
  211. getRoleObj.value.pageNum = val
  212. getRoleList() // 调用角色管理的查询
  213. }
  214. const data = ref([])
  215. const getLists = async function () {
  216. try {
  217. console.log('addRole.value.roleId', addRole.value.roleId);
  218. let roleId = addRole.value.parentId
  219. if (addRole.value.parentId === null || addRole.value.parentId === undefined) {
  220. roleId = 2
  221. }
  222. const res = await API({
  223. url: '/menu/tree',
  224. data: { id: roleId }
  225. })
  226. data.value = res.data
  227. data.value = filterPermission(data.value)
  228. console.log('看看data', data.value)
  229. console.log('parentID:', addRole.value.parentId, 'roleId:', roleId)
  230. if (addRole.value.parentId && addRole.value.parentId !== 2) {
  231. const result = await API({
  232. url: '/general/roleMarket',
  233. data: { id: addRole.value.parentId }
  234. })
  235. if (result.code === 200) {
  236. if (typeof result.data === 'string' && result.data) {
  237. addRoleMarket.value = result.data.split(',')
  238. addRole.value.market = ''
  239. } else if (Array.isArray(result.data)) {
  240. addRoleMarket.value = result.data
  241. addRole.value.market = ''
  242. } else {
  243. addRoleMarket.value = []
  244. addRole.value.market = ''
  245. }
  246. } else {
  247. ElMessage.error('该上级角色无归属地区')
  248. console.log('该上级角色无归属地区')
  249. }
  250. console.log('addRoleMarket.value', addRoleMarket.value)
  251. } else {
  252. addRoleMarket.value = RoleArea.value
  253. console.log('elseRoleArea', RoleArea);
  254. }
  255. } catch (error) {
  256. console.log('请求失败', error)
  257. }
  258. }
  259. //获取频道列表
  260. const getChannelList = async () => {
  261. try {
  262. const res = await API({
  263. url: '/role/getChannel',
  264. })
  265. console.log('res', res);
  266. if (res.code == 200) {
  267. channelList.value = [...channelList.value, ...res.data]
  268. } else {
  269. console.log('获取频道列表', res.msg);
  270. }
  271. } catch (err) {
  272. console.log('获取频道列表出错', err);
  273. }
  274. }
  275. //金豆过滤
  276. const goldenBeanMenuIds = new Set([
  277. permissionMapping.gold_bean_audit,
  278. permissionMapping.gold_bean_recharge,
  279. permissionMapping.gold_bean_consumption,
  280. permissionMapping.gold_bean_customer_details
  281. ])
  282. // 15,43,44,45,46,47,// 金豆审核
  283. // 18,52,53,54,// 金豆充值
  284. // 20,57,58,59,60,// 金豆消耗
  285. // 23// 金豆客户账户明细
  286. const filterGoldenBeanMenus = (tree) => {
  287. return tree
  288. .filter(item => {
  289. // 排除金豆相关的顶层菜单
  290. if (goldenBeanMenuIds.has(item.id)) {
  291. return false
  292. }
  293. // 递归处理子菜单
  294. if (item.children && item.children.length > 0) {
  295. item.children = filterGoldenBeanMenus(item.children)
  296. }
  297. return true
  298. })
  299. }
  300. // 过滤权限模块(????????)俺不会
  301. const filterPermission = (tree) => {
  302. return tree.filter(item => {
  303. if (item.id === permissionMapping.permission_management) {
  304. return false
  305. }
  306. else if (item.children && item.children.length > 0) {
  307. item.children = filterPermission(item.children)
  308. }
  309. return true
  310. })
  311. }
  312. // 处理编辑角色权限时的勾选事件
  313. const handleEditRolePermissionCheck = (checkedNodes, checkedInfo) => {
  314. const { checkedKeys, checkedNodes: allCheckedNodes } = checkedInfo
  315. // 判断是否有选中的节点
  316. if (allCheckedNodes.length === 0) {
  317. permissionEditRoleObj.value.checkedKeys = []
  318. ifHasChannel.value = false
  319. return
  320. }
  321. // 由于设置了 check-strictly="false",Element Plus 会自动处理父子节点联动
  322. // 我们只需要使用 checkedKeys,它已经包含了所有必要的节点ID
  323. permissionEditRoleObj.value.checkedKeys = checkedKeys
  324. console.log('编辑角色选中的权限ID:', checkedKeys)
  325. console.log('选中的节点数量:', allCheckedNodes.length)
  326. if (checkedKeys.includes(124) || checkedKeys.includes(125) || checkedKeys.includes(126) || checkedKeys.includes(127)) {
  327. ifHasChannel.value = true
  328. } else {
  329. ifHasChannel.value = false
  330. }
  331. };
  332. //用于标记是否勾选频道管理
  333. const ifHasChannel = ref(false)
  334. const handleCheckChange = async (checkedNodes, checkedInfo) => {
  335. const { checkedKeys, checkedNodes: allCheckedNodes } = checkedInfo
  336. // 判断是否有选中的节点
  337. if (allCheckedNodes.length === 0) {
  338. addRole.value.checkedKeys = []
  339. ifHasChannel.value = false
  340. return
  341. }
  342. // 创建一个Set存储所有需要选中的ID(包括父级)
  343. const allKeys = new Set(checkedKeys)
  344. // 遍历所有选中的节点,为每个节点添加其父级
  345. allCheckedNodes.forEach(node => {
  346. // 为每个选中的节点单独查找父级
  347. selectParentNodes(data.value, node.id, allKeys)
  348. });
  349. // 将Set转换为数组并更新
  350. addRole.value.checkedKeys = Array.from(allKeys)
  351. console.log('新增角色包含所有父级的选中项:', addRole.value.checkedKeys)
  352. if (addRole.value.checkedKeys.includes(124)) {
  353. ifHasChannel.value = true
  354. console.log('勾选了频道');
  355. } else {
  356. ifHasChannel.value = false
  357. }
  358. }
  359. const selectParentNodes = (treeData, nodeId, checkedKeys) => {
  360. if (!Array.isArray(treeData)) return false
  361. for (const item of treeData) {
  362. // 先检查子节点
  363. if (item.children && item.children.length > 0) {
  364. const foundInChildren = selectParentNodes(item.children, nodeId, checkedKeys);
  365. if (foundInChildren) {
  366. // 找到子节点后添加当前节点(父节点)
  367. checkedKeys.add(item.id);
  368. return true
  369. }
  370. }
  371. // 检查当前节点是否为目标节点
  372. if (item.id === nodeId) {
  373. return true
  374. }
  375. }
  376. return false
  377. };
  378. //点击角色权限菜单树点击展示逻辑
  379. const menuTreeVisible = ref(false)
  380. const currentRoleMenuTree = ref([])
  381. const currentRoleName = ref('')
  382. const Rolecheckedkeys = ref([])
  383. const showMenuTree = (treeData, roleName) => {
  384. currentRoleMenuTree.value = processTreeData(treeData) || [];
  385. console.log('currentRoleMenuTree.value', currentRoleMenuTree.value)
  386. Rolecheckedkeys.value = collectIds(treeData)
  387. console.log('Rolecheckedkeys', Rolecheckedkeys.value)
  388. currentRoleName.value = roleName || '权限详情'
  389. menuTreeVisible.value = true;
  390. }
  391. // 编辑角色对象
  392. const permissionEditRoleObj = ref({
  393. id: null,
  394. roleName: '',
  395. market: '',
  396. parentId: null,
  397. parentName: '',
  398. checkedKeys: [],
  399. channel:''
  400. })
  401. // 编辑角色弹窗
  402. const permissionEditRoleVisible = ref(false)
  403. const collectIds2 = (tree) => {
  404. let ids = []
  405. tree.forEach((node) => {
  406. // 如果当前节点没有 children 或 children 为空,说明是叶子节点
  407. if (!node.children || node.children.length === 0) {
  408. ids.push(node.id)
  409. } else {
  410. // 如果有 children,递归收集子节点的叶子节点
  411. ids = ids.concat(collectIds2(node.children))
  412. }
  413. })
  414. return ids
  415. }
  416. const collectIdsAll = (tree) => {
  417. let ids = []
  418. tree.forEach((node) => {
  419. ids.push(node.id)
  420. // 如果当前节点没有 children 或 children 为空,说明是叶子节点
  421. if (node.children || node.children.length === 0) {
  422. ids = ids.concat(collectIdsAll(node.children))
  423. }
  424. })
  425. return ids
  426. }
  427. // 编辑角色初始化
  428. const permissionEditRoleInit = async function (row) {
  429. console.log('row', row)
  430. console.log('row.tree', row.tree)
  431. let EditIds = collectIdsAll(row.tree)
  432. console.log(EditIds);
  433. permissionEditRoleObj.value = {}
  434. permissionEditRoleObj.value.id = row.id
  435. permissionEditRoleObj.value.roleName = row.roleName
  436. permissionEditRoleObj.value.market = row.market
  437. permissionEditRoleObj.value.parentId = row.fatherId
  438. permissionEditRoleObj.value.parentName = row.fatherName
  439. permissionEditRoleObj.value.channel = row.channel
  440. console.log('permissionEditRoleObj.value',permissionEditRoleObj.value);
  441. if (EditIds.includes(124)) {
  442. ifHasChannel.value = true
  443. } else {
  444. ifHasChannel.value = false
  445. }
  446. try {
  447. let roleId = permissionEditRoleObj.value.parentId;
  448. // 如果没有上级角色,设置为管理员的id
  449. if (permissionEditRoleObj.value.parentId === null || permissionEditRoleObj.value.parentId === undefined) {
  450. roleId = 2;
  451. }
  452. // 调用 /tree 接口,使用上级角色 ID 获取权限列表
  453. const res = await API({
  454. url: '/menu/tree',
  455. data: { id: roleId }
  456. });
  457. data.value = res.data;
  458. data.value = filterPermission(data.value)
  459. //data.value = filterGoldenBeanMenus(data.value);
  460. // 收集当前行权限树的叶子节点id(只收集实际选中的叶子节点)
  461. if (row.tree && row.tree.length > 0) {
  462. const leafIds = collectIds2(row.tree);
  463. permissionEditRoleObj.value.checkedKeys = leafIds;
  464. console.log('编辑角色初始化时的权限列表', permissionEditRoleObj.value.checkedKeys);
  465. } else {
  466. permissionEditRoleObj.value.checkedKeys = [];
  467. }
  468. } catch (error) {
  469. console.log('根据上级角色获取权限列表失败', error);
  470. data.value = [];
  471. permissionEditRoleObj.value.checkedKeys = [];
  472. }
  473. console.log('编辑角色', permissionEditRoleObj.value);
  474. permissionEditRoleVisible.value = true;
  475. // 等待DOM更新后手动设置树的选中状态
  476. await nextTick();
  477. if (treeRef.value && permissionEditRoleObj.value.checkedKeys.length > 0) {
  478. treeRef.value.setCheckedKeys(permissionEditRoleObj.value.checkedKeys);
  479. console.log('手动设置树的选中状态:', permissionEditRoleObj.value.checkedKeys);
  480. }
  481. };
  482. // 编辑角色提交
  483. const permissionEditRole = async function () {
  484. if (!findMenuById(menuTree.value, permissionMapping.edit_role_information)) {
  485. ElMessage.error('无此权限')
  486. return
  487. }
  488. try {
  489. await new Promise((resolve, reject) => {
  490. Ref.value.validate((valid) => {
  491. if (valid) {
  492. resolve();
  493. } else {
  494. reject(new Error('请检查并完善表单信息'));
  495. }
  496. });
  497. });
  498. // 确保提交时包含所有选中的权限ID(包括父节点)
  499. let finalCheckedKeys = permissionEditRoleObj.value.checkedKeys || [];
  500. // 为所有选中的节点添加其父节点ID
  501. const allKeys = new Set(finalCheckedKeys);
  502. finalCheckedKeys.forEach(nodeId => {
  503. selectParentNodesForSubmit(data.value, nodeId, allKeys);
  504. });
  505. finalCheckedKeys = Array.from(allKeys);
  506. const res = await API({
  507. url: '/menu/update',
  508. data: {
  509. ...permissionEditRoleObj.value,
  510. menuIds: finalCheckedKeys
  511. }
  512. });
  513. if (res.code === 200) {
  514. console.log('编辑角色成功', permissionEditRoleObj.value);
  515. console.log('提交的权限ID列表:', finalCheckedKeys);
  516. permissionEditRoleVisible.value = false;
  517. getRoleList();
  518. ElMessage.success('编辑角色成功');
  519. } else if (res.code === 0) {
  520. console.log('角色名重复', permissionEditRoleObj.value);
  521. ElMessage.error('角色名重复');
  522. } else {
  523. console.log('编辑角色失败', res);
  524. ElMessage.error('编辑角色失败');
  525. }
  526. } catch (error) {
  527. console.log('编辑角色失败', error);
  528. console.log('失败,看看permissionEditRoleObj', permissionEditRoleObj.value);
  529. }
  530. };
  531. // 为提交时查找父节点的辅助函数
  532. const selectParentNodesForSubmit = (treeData, nodeId, checkedKeys) => {
  533. if (!Array.isArray(treeData)) return false;
  534. for (const item of treeData) {
  535. // 先检查子节点
  536. if (item.children && item.children.length > 0) {
  537. const foundInChildren = selectParentNodesForSubmit(item.children, nodeId, checkedKeys);
  538. if (foundInChildren) {
  539. // 找到子节点后添加当前节点(父节点)
  540. checkedKeys.add(item.id);
  541. return true;
  542. }
  543. }
  544. // 检查当前节点是否为目标节点
  545. if (item.id === nodeId) {
  546. return true;
  547. }
  548. }
  549. return false;
  550. };
  551. const Rolerules = reactive({
  552. roleName: [
  553. { required: true, message: '请输入角色名称', trigger: 'blur' },
  554. { min: 2, max: 20, message: '角色名称长度应在2-20个字符之间', trigger: 'blur' }
  555. ],
  556. market: [
  557. { required: true, message: '请选择归属地区', trigger: 'change' }
  558. ],
  559. checkedKeys: [
  560. {
  561. required: true,
  562. message: '请选择权限列表',
  563. trigger: 'change', // 选框变化或提交时触发,可根据实际调整
  564. validator: (rule, value, callback) => {
  565. if (value && value.length > 0) {
  566. callback(); // 有选中项,校验通过
  567. } else {
  568. callback(new Error('请选择权限列表')); // 未选中,抛出错误提示
  569. }
  570. }
  571. }
  572. ]
  573. });
  574. const throttledHandleAddRole = _.throttle(handleAddRole, 5000, {
  575. trailing: false
  576. })
  577. const canLook = findMenuById(menuTree.value, permissionMapping.view_role_information)
  578. const canAdd = findMenuById(menuTree.value, permissionMapping.add_role_information)
  579. const canEdit = findMenuById(menuTree.value, permissionMapping.edit_role_information)
  580. // 挂载
  581. onMounted(async function () {
  582. await getRoleList()
  583. await getRoleArea()
  584. await getChannelList()
  585. })
  586. </script>
  587. <template>
  588. <div>
  589. <el-card class="card1" style="margin-bottom: 1vh;">
  590. <div style="display: flex;">
  591. <el-text size="large">角色名称</el-text>
  592. <el-input v-model="role.name" style="width: 240px" placeholder="请输入角色名称" clearable />
  593. <div style="margin-left: auto;">
  594. <el-button type="primary" @click="searchRole()" :disabled="!canLook" v-if="canLook">查询</el-button>
  595. <el-button type="success" @click="reset()">重置</el-button>
  596. </div>
  597. </div>
  598. </el-card>
  599. <el-card class="card2">
  600. <div class="add-item">
  601. <el-button style="color: #048efb; border: 1px solid #048efb" @click="permissionAddInit()" :disabled="!canAdd"
  602. v-if="canAdd">新增角色</el-button>
  603. </div>
  604. <div>
  605. <el-table :data="roleData" style="width: 82vw;height:71.3vh" show-overflow-tooltip
  606. :row-style="{ height: '56px' }">
  607. <el-table-column type="index" label="序号" width="100px" fixed="left">
  608. <template #default="scope">
  609. <span>{{
  610. scope.$index + 1 + (getRoleObj.pageNum - 1) * getRoleObj.pageSize
  611. }}</span>
  612. </template>
  613. </el-table-column>
  614. <el-table-column prop="roleName" label="角色名称" />
  615. <el-table-column prop="fatherName" label="上级角色">
  616. <template #default="scope">
  617. {{ scope.row.fatherName || '-' }}
  618. </template>
  619. </el-table-column>
  620. <el-table-column label="权限范围" show-overflow-tooltip>
  621. <template #default="scope">
  622. <div class="permission-cell" @click="showMenuTree(scope.row.tree, scope.row.roleName)">
  623. {{ formatPermissions(scope.row.tree) }}
  624. </div>
  625. </template>
  626. </el-table-column>
  627. <el-table-column prop="operation" label="操作" width="200px">
  628. <template #default="scope">
  629. <el-button type="warning" text @click="permissionEditRoleInit(scope.row)"
  630. :disabled="(scope.row.id === 2) || (scope.row.id === 1) || !canEdit" v-if="canEdit">
  631. 编辑
  632. </el-button>
  633. </template>
  634. </el-table-column>
  635. </el-table>
  636. </div>
  637. <div style="margin-top: 20px;display: flex;">
  638. <el-pagination background :current-page="getRoleObj.pageNum" :page-size="getRoleObj.pageSize"
  639. :page-sizes="[5, 10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="roleTotal"
  640. @size-change="handleRolePageSizeChange" @current-change="handleRoleCurrentChange"></el-pagination>
  641. </div>
  642. </el-card>
  643. </div>
  644. <!-- 角色菜单树展示 -->
  645. <el-dialog v-model="menuTreeVisible" :title='`权限详情:${currentRoleName}`' width="600px">
  646. <el-tree :data="currentRoleMenuTree" node-key="id" :props="{ label: 'menuName', children: 'children' }"
  647. show-checkbox check-strictly :expand-on-click-node="false"
  648. :default-expanded-keys="currentRoleMenuTree.map(item => item.id)" :default-checked-keys="Rolecheckedkeys" />
  649. <template #footer>
  650. <el-button @click="menuTreeVisible = false" type="primary">关闭</el-button>
  651. </template>
  652. </el-dialog>
  653. <!-- 新增角色 -->
  654. <el-dialog v-model="permissionAddVisible" title="新增角色" width="800px" :close-on-click-modal="false"
  655. @close="handleDialogClose">
  656. <template #footer>
  657. <el-form ref="Ref" :rules="Rolerules" :model="addRole" label-width="auto"
  658. style="max-width: 600px; align-items: center">
  659. <el-form-item prop="roleName" label="角色名称:" required>
  660. <el-input v-model="addRole.roleName" placeholder="请输入角色名称" style="width: 220px" />
  661. </el-form-item>
  662. <el-form-item prop="parentName" label="上级角色:">
  663. <el-select v-model="addRole.parentId" placeholder="请选择上级角色" style="width: 220px" @change="getLists" clearable>
  664. <el-option v-for="item in permissionList" :key="item.value" :label="item.label"
  665. :value="item.value"></el-option>
  666. </el-select>
  667. </el-form-item>
  668. <el-form-item prop="market" label="归属地区:" required>
  669. <el-select v-model="addRole.market" placeholder="请选择归属地区" style="width: 220px" clearable>
  670. <el-option v-for="item in addRoleMarket" :key="item" :label="item" :value="item" />
  671. </el-select>
  672. <text>(此地区无实际意义仅用于各分部负责人查看其地区角色)</text>
  673. </el-form-item>
  674. <el-form-item prop="checkedKeys" label="权限列表:" required>
  675. <el-tree v-if="data.length > 0" :data="data" show-checkbox node-key="id"
  676. :props="{ label: 'menuName', children: 'children' }" :checked-keys="addRole.checkedKeys"
  677. :check-strictly="false" @check="handleCheckChange">
  678. <template #default="{ node }">
  679. <span>{{ node.label }}</span>
  680. </template>
  681. </el-tree>
  682. <div v-else style="display: flex; align-items: center; gap: 8px;">
  683. <span style="color: #999;">暂无数据</span>
  684. </div>
  685. </el-form-item>
  686. <el-form-item v-show="ifHasChannel" prop="channel" label="频道名称:" required>
  687. <el-select v-model="addRole.channel" placeholder="请选择频道" style="width: 220px" filterable clearable>
  688. <el-option v-for="item in channelList" :key="item" :label="item" :value="item" />
  689. </el-select>
  690. </el-form-item>
  691. </el-form>
  692. <div>
  693. <el-button @click="closePermissionAddVisible()">取消</el-button>
  694. <el-button type="primary" @click="throttledHandleAddRole">
  695. 提交
  696. </el-button>
  697. </div>
  698. </template>
  699. </el-dialog>
  700. <!-- 編輯角色彈窗 -->
  701. <el-dialog v-model="permissionEditRoleVisible" title="编辑角色" width="800px" :close-on-click-modal="false">
  702. <template #footer>
  703. <el-form ref="Ref" :rules="Rolerules" :model="permissionEditRoleObj" label-width="auto"
  704. style="max-width: 600px; align-items: center">
  705. <el-form-item prop="roleName" label="角色名称:" required>
  706. <el-input v-model="permissionEditRoleObj.roleName" placeholder="请输入角色名称" style="width: 220px" />
  707. </el-form-item>
  708. <el-form-item prop="parentName" label="上级角色:">
  709. <el-input v-model="permissionEditRoleObj.parentName" placeholder="无上级角色" disabled style="width: 220px">
  710. <el-option v-for="item in permissionList" :key="item.value" :label="item.label"
  711. :value="item.value"></el-option>
  712. </el-input>
  713. </el-form-item>
  714. <el-form-item prop="market" label="归属地区" required>
  715. <el-input v-model="permissionEditRoleObj.market" placeholder="请输入归属地区" style="width: 220px" disabled />
  716. <text>(此地区无实际意义仅用于各分部负责人查看其地区角色)</text>
  717. </el-form-item>
  718. <el-form-item prop="checkedKeys" label="权限列表:" required>
  719. <el-tree v-if="data.length > 0" :data="data" show-checkbox node-key="id" ref="treeRef"
  720. :props="{ label: 'menuName', children: 'children' }"
  721. :default-checked-keys="permissionEditRoleObj.checkedKeys" :check-strictly="false"
  722. @check="handleEditRolePermissionCheck">
  723. <!-- <template #default="{ node, data }"> data删掉了不影响功能 -->
  724. <template #default="{ node }">
  725. <span>{{ node.label }}</span>
  726. </template>
  727. </el-tree>
  728. <div v-else style="display: flex; align-items: center; gap: 8px;">
  729. <span style="color: #999;">暂无数据</span>
  730. </div>
  731. </el-form-item>
  732. <el-form-item v-show="ifHasChannel" prop="channel" label="频道名称:" required>
  733. <el-select v-model="permissionEditRoleObj.channel" placeholder="请选择频道" style="width: 220px" clearable>
  734. <el-option v-for="item in channelList" :key="item" :label="item" :value="item" />
  735. </el-select>
  736. </el-form-item>
  737. </el-form>
  738. <div>
  739. <el-button @click="permissionEditRoleVisible = false">取消</el-button>
  740. <el-button type="primary" @click="permissionEditRole">
  741. 提交
  742. </el-button>
  743. </div>
  744. </template>
  745. </el-dialog>
  746. </template>
  747. <style scoped lang="scss">
  748. // 新增用户按钮
  749. .add-item {
  750. margin-bottom: 1vh;
  751. }
  752. // 搜索的卡片样式
  753. .card1 {
  754. background: #F3FAFE;
  755. }
  756. // 表单的卡片样式
  757. .card2 {
  758. background: #E7F4FD;
  759. }
  760. // 表头背景等
  761. :deep(.el-table__header-wrapper),
  762. :deep(.el-table__body-wrapper),
  763. :deep(.el-table__cell),
  764. /* 表格 */
  765. :deep(.el-table__body td) {
  766. background-color: #F3FAFE !important;
  767. }
  768. /* 表头 */
  769. :deep(.el-table__header th) {
  770. background-color: #F3FAFE !important;
  771. }
  772. /* 鼠标悬停 */
  773. :deep(.el-table__row:hover > .el-table__cell) {
  774. background-color: #E5EBFE !important;
  775. }
  776. .head-card {
  777. display: flex;
  778. }
  779. .permission-cell {
  780. cursor: pointer;
  781. color: #409eff;
  782. /* 蓝色文字,提示可点击 */
  783. }
  784. </style>