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.

860 lines
28 KiB

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