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.

1243 lines
40 KiB

2 months ago
2 months ago
3 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 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
4 weeks ago
2 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
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 { computed, onMounted, ref } from 'vue'
  3. import { ElMessage, ElMessageBox } from 'element-plus'
  4. import { InfoFilled } from '@element-plus/icons-vue'
  5. import _ from 'lodash'
  6. import request from '@/util/http'
  7. import API from '@/util/http'
  8. import { useAdminStore } from "@/store/index.js"
  9. import { storeToRefs } from "pinia"
  10. import { findMenuById, permissionMapping } from "@/utils/menuTreePermission.js"
  11. import BackGroundSvg from '@/assets/SvgIcons/背景.svg'
  12. const adminStore = useAdminStore()
  13. const { adminData, menuTree } = storeToRefs(adminStore)
  14. // 表格数据
  15. const tableData = ref([])
  16. const total = ref(100)
  17. const handleDialogClose = function () {
  18. closeUserAddVisible()
  19. console.log('hhh');
  20. }
  21. const propsAdduser = {
  22. multiple: true, // 多选
  23. }
  24. // 搜索admin
  25. const admin = ref({
  26. account: '',
  27. market: '',
  28. postiton: ''
  29. })
  30. // 搜索对象
  31. const getObj = ref({
  32. pageNum: 1,
  33. pageSize: 10
  34. })
  35. // 修改状态确认
  36. const ackVisible = ref(false)
  37. const currentStatusRow = ref(null)
  38. const statusLoading = ref({})
  39. const showStatusConfirm = (row, targetStatus) => {
  40. currentStatusRow.value = {
  41. ...row,// 当前行数据
  42. targetStatus// 目标状态
  43. }
  44. ackVisible.value = true
  45. }
  46. // 规则
  47. const addUserRules = {
  48. account: [
  49. { required: true, message: '请输入OA号', trigger: 'blur' },
  50. { pattern: /^\d+$/, message: 'OA号必须为数字', trigger: 'blur' },
  51. { max: 20, message: '长度不能超过20位', trigger: 'blur' }
  52. ],
  53. name: [
  54. { required: true, message: '请输入用户名', trigger: 'blur' },
  55. { max: 20, message: '长度不能超过20位', trigger: 'blur' }
  56. ],
  57. market: [
  58. { required: true, message: '请选择所属地区', trigger: 'change' }
  59. ],
  60. permission: [
  61. { required: true, message: '请选择角色名称', trigger: 'change' }
  62. ],
  63. postiton: [
  64. { required: true, message: '请输入职位', trigger: 'blur' },
  65. { max: 20, message: '长度不能超过20位', trigger: 'blur' }
  66. ],
  67. machineIds: [
  68. {
  69. required: true,
  70. message: '请至少输入一个机器码',
  71. trigger: 'change',
  72. validator: (rule, value, callback) => {
  73. // 检查是否有非空的机器码
  74. const hasValid = value.some(item => item.trim() !== '');
  75. if (!hasValid) {
  76. callback(new Error('请至少输入一个机器码'));
  77. } else {
  78. callback();
  79. }
  80. }
  81. }
  82. ]
  83. };
  84. // 新增用户权限弹窗
  85. const userAddVisible = ref(false)
  86. // 编辑用户权限弹窗
  87. const userEditVisible = ref(false)
  88. //选地区
  89. const market = ref([])
  90. // 选部门
  91. const postiton = ref([])
  92. // 新增用户对象
  93. const userAddObj = ref({})
  94. // 新增用户权限对象,机器码要实现存储多个,addMachineIdInput方法实现
  95. const addAdmin = ref({
  96. account: '',
  97. name: '',
  98. market: [],
  99. permission: '',
  100. postiton: '',
  101. machineIds: [''], // 动态添加的机器码输入框
  102. machineId: '',
  103. remark: ''
  104. })
  105. // 编辑用户权限对象
  106. const permissionEditObj = ref({
  107. checkedKeys: [],
  108. machineIds: [''],
  109. machineId: '',
  110. password: '',
  111. postiton: ''
  112. })
  113. const addMachineIdInput = function () {
  114. if (addAdmin.value.machineIds.length >= 2) {
  115. ElMessage.warning('设备数量已达上限')
  116. return
  117. }
  118. addAdmin.value.machineIds.push('')
  119. }
  120. const UseraddMachineIdInput = function () {
  121. if (permissionEditObj.value.machineIds.length >= 2) {
  122. ElMessage.warning('设备数量已达上限')
  123. return
  124. }
  125. permissionEditObj.value.machineIds.push('')
  126. }
  127. // 删除权限对象
  128. const delObj = ref({})
  129. const getPermission = async function (val) {
  130. try {
  131. if (typeof val === 'number') {
  132. getObj.value.pageNum = val
  133. }
  134. console.log('搜索参数', getObj.value, admin.value)
  135. // if (admin.value.market === '总部' || admin.value.market === '研发部') {
  136. // admin.value.market = '';
  137. // }
  138. if (admin.value.account) {
  139. // 纯数字
  140. const numberRegex = /^\d{1,20}$/;
  141. // 检查是否不是数字
  142. if (!numberRegex.test(admin.value.account)) {
  143. ElMessage.error('请检查OA号格式')
  144. // 上面提示过了
  145. return
  146. }
  147. }
  148. const result = await request({
  149. url: '/permission/getPermission',
  150. data: {
  151. ...getObj.value,
  152. permission: {
  153. ...admin.value
  154. }
  155. }
  156. })
  157. tableData.value = result.data.list
  158. console.log('tableData', tableData.value)
  159. total.value = result.data.total
  160. } catch (error) {
  161. console.log('请求失败', error)
  162. }
  163. }
  164. const trimJwCode = () => {
  165. if (admin.value.account) {
  166. admin.value.account = admin.value.account.replace(/\s/g, '');
  167. }
  168. }
  169. const search = function () {
  170. trimJwCode();
  171. getObj.value.pageNum = 1
  172. getPermission()
  173. }
  174. // 重置
  175. const reset = function () {
  176. admin.value = {}
  177. // 重置页码
  178. getObj.value.pageNum = 1
  179. getPermission()
  180. }
  181. const RoleArea = ref([])
  182. const getRoleArea = async function () {
  183. try {
  184. const result = await request({
  185. url: '/general/allRoleMarket',
  186. data: {}
  187. })
  188. RoleArea.value = result.data
  189. } catch (error) {
  190. console.log('请求失败', error)
  191. }
  192. }
  193. // 获取地区树
  194. const marketsTree = ref([])
  195. const getArea = async function () {
  196. try {
  197. // 发送POST请求
  198. const result = await API({
  199. url: '/market/selectMarket',
  200. });
  201. // 将响应结果存储到响应式数据中
  202. console.log('请求成功', result)
  203. // 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
  204. const transformTree = (nodes) => {
  205. // 直接处理第一级节点的子节点
  206. const allChildren = nodes.flatMap(node => node.children || []);
  207. return allChildren.map(child => {
  208. const grandchildren = child.children && child.children.length
  209. ? transformTree([child]) // 递归处理子节点
  210. : null;
  211. return {
  212. value: child.name,
  213. label: child.name,
  214. children: grandchildren
  215. };
  216. });
  217. };
  218. // 存储地区信息
  219. marketsTree.value = transformTree(result.data)
  220. console.log('转换后的地区树==============', marketsTree.value)
  221. } catch (error) {
  222. console.log('请求失败', error)
  223. }
  224. }
  225. // 获取部门
  226. const getStore = async function () {
  227. try {
  228. const result = await request({
  229. url: '/permission/getposition',
  230. data: {}
  231. })
  232. postiton.value = result.data
  233. } catch (error) {
  234. console.log('请求失败', error)
  235. }
  236. }
  237. // 打开新增用户权限弹窗
  238. const openUserAddVisible = function () {
  239. userAddVisible.value = true
  240. }
  241. // 关闭新增用户权限弹窗,并刷新表单
  242. const closeUserAddVisible = function () {
  243. userAddVisible.value = false;
  244. // 清除表单验证状态
  245. Ref.value.resetFields();
  246. }
  247. // 新增用户权限初始化
  248. const userAddInit = function () {
  249. userAddObj.value = {}
  250. openUserAddVisible()
  251. }
  252. //新增用户
  253. const permissionAdd = async function () {
  254. if (!canLook) {
  255. ElMessage.error('无此权限')
  256. return
  257. }
  258. try {
  259. await new Promise((resolve, reject) => {
  260. Ref.value.validate((valid) => {
  261. if (valid) {
  262. resolve(); // 验证通过,继续执行后续代码
  263. } else {
  264. reject(new Error('请检查并完善表单信息')); // 验证失败,抛出错误
  265. }
  266. });
  267. });
  268. addAdmin.value.adminFlag = 1
  269. addAdmin.value.status1 = 1
  270. if (addAdmin.value.postiton === '管理员') {
  271. addAdmin.value.postiton === 1
  272. }
  273. const params = {
  274. "account": addAdmin.value.account,//OA号
  275. "adminName": addAdmin.value.name,//姓名
  276. "market": addAdmin.value.market,//地区
  277. "roleId": addAdmin.value.permission,//权限ID
  278. "postiton": addAdmin.value.postiton,//职位
  279. "machineId": addAdmin.value.machineIds[0],//机器码
  280. "remark": addAdmin.value.remark//备注
  281. }
  282. console.log('提交前addAdmin market', addAdmin.value.market)
  283. const result = await request({
  284. url: '/permission/addPermission',
  285. data: params
  286. })
  287. console.log(addAdmin.value)
  288. if (result.code === 200) {
  289. ElMessage.success('添加成功')
  290. } else {
  291. ElMessage.error(result.msg)
  292. }
  293. addAdmin.value = {}
  294. getPermission()
  295. closeUserAddVisible()
  296. } catch (error) {
  297. console.log('新增用户权限失败', error)
  298. ElMessage.error('新增用户权限失败')
  299. }
  300. }
  301. // 表单验证ref
  302. const Ref = ref(null)
  303. // 权限类别
  304. const permissionList = ref([])
  305. const getRoles = async function () {
  306. try {
  307. const res = await API({ url: '/role/selectAll' })
  308. permissionList.value = res.data.map(item => ({
  309. label: item.roleName,
  310. value: item.id
  311. }))
  312. console.log('权限列表:', permissionList.value)
  313. } catch (error) {
  314. console.error('获取权限列表失败:', error)
  315. }
  316. }
  317. // 打开编辑用户权限弹窗
  318. const openUserEditVisible = function () {
  319. userEditVisible.value = true
  320. }
  321. // 关闭编辑用户权限弹窗
  322. const closeUserEditVisible = function () {
  323. userEditVisible.value = false
  324. data.value = []
  325. }
  326. // 编辑用户权限初始化
  327. const permissionEditInit = async function (row) {
  328. console.log('row', row)
  329. permissionEditObj.value = {}
  330. permissionEditObj.value.id = row.id
  331. permissionEditObj.value.account = row.account
  332. permissionEditObj.value.adminName = row.name
  333. permissionEditObj.value.remark = row.remark
  334. permissionEditObj.value.market = row.market
  335. permissionEditObj.value.password = ''
  336. // 将字符串形式的 market 转换为数组
  337. if (typeof row.market === 'string' && row.market) {
  338. permissionEditObj.value.market = row.market.split(',');
  339. } else {
  340. // 处理空值或非字符串情况
  341. permissionEditObj.value.market = [];
  342. }
  343. permissionEditObj.value.postiton = row.postiton || ''
  344. if (permissionEditObj.value.postiton === ' ') {
  345. permissionEditObj.value.postiton = ''
  346. }
  347. permissionEditObj.value.roleId = row.roleId
  348. const result = await request({
  349. url: '/role/selectFather',
  350. data: {
  351. id: row.roleId
  352. }
  353. })
  354. console.log('初始查上级权限', result)
  355. permissionEditObj.value.parentId = result.data?.fatherId
  356. permissionEditObj.value.parentName = result.data?.fatherName
  357. console.log('get前', permissionEditObj.value.roleId);
  358. permissionEditObj.value.roleName = row.roleName
  359. if (permissionEditObj.value.roleId === 0) {
  360. permissionEditObj.value.roleId = ''
  361. }
  362. getUserLists(row.roleId)
  363. let machineIdsRef = await request({
  364. url: '/permission/getPermission',
  365. data: {
  366. "pageNum": 1,//页码数
  367. "pageSize": 1,//页条数
  368. "permission": {
  369. account: row.account,//OA号
  370. }
  371. }
  372. })
  373. if (machineIdsRef.data.list[0].machineIds == null || machineIdsRef.data.list[0].machineIds.length === 0) {
  374. permissionEditObj.value.machineIds = ['']
  375. } else {
  376. permissionEditObj.value.machineIds = machineIdsRef.data.list[0].machineIds
  377. }
  378. permissionEditObj.value.machineId = permissionEditObj.value.machineIds[0]
  379. //permissionEditObj.value.permission = row.permission
  380. console.log('编辑用户权限', permissionEditObj.value)
  381. console.log('11111111111111', permissionEditObj.value.machineId)
  382. openUserEditVisible()
  383. }
  384. const collectIds = (tree) => {
  385. let ids = [];
  386. tree.forEach((node) => {
  387. ids.push(node.id);
  388. if (node.children && node.children.length > 0) {
  389. ids = ids.concat(collectIds(node.children));
  390. }
  391. });
  392. return ids;
  393. };
  394. // 定义上级角色提示变量
  395. const parentRoleTip = ref('');
  396. //给data数据加上disabled属性,控制是否禁用
  397. function processTreeData(data) {
  398. return data.map(item => ({
  399. ...item,
  400. disabled: item.id != null || item.menuName.includes("敏感权限"), //控制权限显示的条件
  401. children: item.children ? processTreeData(item.children) : []
  402. }));
  403. }
  404. //根据上级角色控制权限列表,选择角色调整上级角色
  405. const getUserLists = async function (selectedRoleId) {
  406. try {
  407. console.log('permissionEditObj.value.roleId:', permissionEditObj.value.roleId)
  408. console.log('selectedRoleId', selectedRoleId);
  409. permissionEditObj.value.parentId = null;
  410. permissionEditObj.value.parentName = '';
  411. permissionEditObj.value.checkedKeys = [];
  412. parentRoleTip.value = '';
  413. const parentRes = await request({
  414. url: '/role/selectFather',
  415. data: { id: selectedRoleId } // 用选中的角色ID请求
  416. });
  417. const parentId = parentRes.data.fatherId;
  418. const parentName = parentRes.data.parentName;
  419. permissionEditObj.value.parentId = parentId;
  420. permissionEditObj.value.parentName = parentName;
  421. if (parentId == null) {
  422. // 无上级角色:显示提示
  423. parentRoleTip.value = '该角色无上级角色';
  424. }
  425. let roleId = permissionEditObj.value.roleId
  426. // if (permissionEditObj.value.parentId === null || permissionEditObj.value.parentId === undefined) {
  427. // roleId = 2
  428. // }
  429. const res = await API({
  430. url: '/menu/tree',
  431. data: { id: roleId }
  432. })
  433. data.value = processTreeData(res.data)
  434. permissionEditObj.value.checkedKeys = collectIds(res.data) || [];
  435. console.log('看看data', data.value)
  436. console.log('看checkedKeys', permissionEditObj.value.checkedKeys)
  437. console.log('parentID:', permissionEditObj.value.parentId, 'roleId:', roleId)
  438. console.log('permissionEditObj.value.roleId:', permissionEditObj.value.roleId)
  439. } catch (error) {
  440. console.log('请求失败', error)
  441. }
  442. }
  443. //编辑用户表单校验
  444. const editAdminRules = {
  445. market: [
  446. { required: true, message: '请选择所属地区', trigger: 'change' }
  447. ],
  448. postiton: [
  449. { required: true, message: '请输入职位', trigger: ['blur', 'change'] },
  450. { max: 20, message: '长度不能超过20位', trigger: ['blur', 'change'] }
  451. ],
  452. machineIds: [
  453. {
  454. required: true,
  455. message: '请至少输入一个机器码',
  456. trigger: 'change',
  457. validator: (rule, value, callback) => {
  458. // 检查是否有非空的机器码
  459. const hasValid = value.some(item => item.trim() !== '');
  460. if (!hasValid) {
  461. callback(new Error('请至少输入一个机器码'));
  462. } else {
  463. callback();
  464. }
  465. }
  466. }
  467. ]
  468. };
  469. // 编辑用户权限提交
  470. const permissionEdit = async function () {
  471. if (!canEdit) {
  472. ElMessage.error('无此权限')
  473. return
  474. }
  475. let { adminName: userName, roleName: oldRole, roleId: newRoleId } = permissionEditObj.value;
  476. if (oldRole == null) {
  477. oldRole = '暂未分配角色'
  478. }
  479. const newRole = permissionList.value.find(item => item.value === newRoleId)?.label || '未知角色';
  480. try {
  481. await new Promise((resolve, reject) => {
  482. Ref.value.validate((valid) => {
  483. if (valid) {
  484. resolve(); // 验证通过,继续执行后续代码
  485. } else {
  486. reject(new Error('请检查并完善表单信息')); // 验证失败,抛出错误
  487. }
  488. });
  489. });
  490. await ElMessageBox.confirm(
  491. `确认修改权限角色?<br>您正在将【${userName}】的权限角色从【${oldRole}】修改为【${newRole}】<br>变更后,该用户的可操作权限将同步更新为新角色配置,涉及数据访问、功能操作等权限变化,请谨慎确认。`,
  492. '警告',
  493. {
  494. confirmButtonText: '确认',
  495. cancelButtonText: '取消',
  496. type: "warning",
  497. lockScroll: false,
  498. dangerouslyUseHTMLString: true //允许解析 HTML 标签
  499. }
  500. )
  501. const result = await request({
  502. url: '/permission/updateAdmin',
  503. data: {
  504. account: permissionEditObj.value.account,//OA号
  505. adminName: permissionEditObj.value.adminName,//姓名
  506. market: permissionEditObj.value.market,//地区
  507. postiton: permissionEditObj.value.postiton,//职位
  508. roleId: permissionEditObj.value.roleId,//角色id
  509. machineId: permissionEditObj.value.machineIds[0],//机器码
  510. machineIds: permissionEditObj.value.machineIds[1],//机器码
  511. password: permissionEditObj.value.password,//
  512. remark: permissionEditObj.value.remark//备注
  513. }
  514. });
  515. console.log('编辑最后提交数据', permissionEditObj.value);
  516. if (result.code === 200) {
  517. await ElMessageBox.alert(
  518. `用户${userName}的权限角色已更改为【${newRole}`,
  519. '成功',
  520. {
  521. confirmButtonText: '确定',
  522. type: 'success' // 设置为 success 类型
  523. }
  524. );
  525. getPermission();
  526. closeUserEditVisible();
  527. } else {
  528. ElMessage.error(result.msg)
  529. }
  530. } catch (error) {
  531. console.log('编辑用户权限失败', error)
  532. ElMessage.error('编辑用户权限失败')
  533. }
  534. }
  535. // 删除初始化
  536. const del = function (row) {
  537. delObj.value = {}
  538. console.log(row, '删除初始化')
  539. delObj.value.account = row.account
  540. delObj.value.id = row.id
  541. }
  542. // 删除权限
  543. const delConfirm = async function () {
  544. if (!canDel) {
  545. ElMessage.error('无此权限')
  546. return
  547. }
  548. try {
  549. const result = await request({
  550. url: '/permission/deleteAdmin',
  551. data: delObj.value
  552. })
  553. console.log('看看删除对象', delObj.value)
  554. console.log('请求成功1', result)
  555. ElMessage.success('删除权限成功')
  556. delObj.value = {}
  557. getPermission()
  558. } catch (error) {
  559. console.log('删除权限失败', error)
  560. ElMessage.error('删除权限失败')
  561. }
  562. }
  563. // 禁用启用用户权限
  564. const editStatus = async function (row) {
  565. if (!change) {
  566. ElMessage.error('无此权限')
  567. return
  568. }
  569. const { id, account, targetStatus, ...restRow } = currentStatusRow.value
  570. try {
  571. statusLoading.value[id] = true
  572. console.log(row)
  573. permissionEditObj.value = {}
  574. permissionEditObj.value.id = id
  575. permissionEditObj.value.account = account
  576. permissionEditObj.value.adminStatus = targetStatus
  577. console.log('修改用户权限状态', permissionEditObj.value)
  578. const result = await request({
  579. url: '/permission/upadatePermission',
  580. data: permissionEditObj.value
  581. })
  582. console.log('请求成功2', result)
  583. if (result.code === 200) {
  584. ElMessage.success(
  585. permissionEditObj.value.adminStatus === 1 ? '启用成功' : '禁用成功'
  586. )
  587. statusLoading.value[id] = false
  588. }
  589. permissionEditObj.value = {}
  590. getPermission()
  591. } catch (error) {
  592. console.log('修改用户权限失败', error)
  593. }
  594. }
  595. const handlePageSizeChange = function (val) {
  596. getObj.value.pageSize = val
  597. getPermission()
  598. }
  599. const handleCurrentChange = function (val) {
  600. getObj.value.pageNum = val
  601. getPermission()
  602. }
  603. const data = ref([])
  604. // todo 处理地区选择变化
  605. /*const handleMarketChange = (values) => {
  606. console.log('values的类型:', typeof values);
  607. console.log('values的值:', values);
  608. //判断是否选择了总部
  609. const hasHeadquarters = values.includes('总部');
  610. if (hasHeadquarters) {
  611. // 如果选择了总部,只保留总部
  612. addAdmin.value.market = ['总部'];
  613. }
  614. console.log('看看现在的地区', addAdmin.value.market);
  615. };*/
  616. // 存储地区选择变化
  617. const selectedMarketPath = ref("")
  618. // 这个不转id
  619. const handleMarketChange = (value) => {
  620. if (value && value.length > 0) {
  621. admin.value.market = value[value.length - 1]
  622. } else {
  623. admin.value.market = ''
  624. }
  625. }
  626. // 修改地区选择处理函数
  627. const handleMarketChangeAddUser = (value) => {
  628. if (Array.isArray(value) && value.length > 0) {
  629. // 提取所有选中项的最后一级
  630. const selectedMarkets = value
  631. .map(path => Array.isArray(path) && path.length > 0 ? path[path.length - 1] : null)
  632. .filter(Boolean);
  633. // 检查是否包含总部
  634. const hasHeadquarters = selectedMarkets.includes('总部');
  635. if (hasHeadquarters) {
  636. // 如果包含总部,只保留总部
  637. addAdmin.value.market = ['总部'];
  638. } else {
  639. // 不包含总部,保留所有选择
  640. addAdmin.value.market = selectedMarkets;
  641. }
  642. } else {
  643. // 未选择任何地区
  644. addAdmin.value.market = [];
  645. }
  646. };
  647. // 修改地区选择处理函数
  648. const handleMarketChangeEditUser = (value) => {
  649. if (Array.isArray(value) && value.length > 0) {
  650. // 提取所有选中项的最后一级
  651. const selectedMarkets = value
  652. .map(path => Array.isArray(path) && path.length > 0 ? path[path.length - 1] : null)
  653. .filter(Boolean);
  654. // 检查是否包含总部
  655. const hasHeadquarters = selectedMarkets.includes('总部');
  656. if (hasHeadquarters) {
  657. // 如果包含总部,只保留总部
  658. permissionEditObj.value.market = ['总部'];
  659. } else {
  660. // 不包含总部,保留所有选择
  661. permissionEditObj.value.market = selectedMarkets;
  662. }
  663. } else {
  664. // 未选择任何地区
  665. permissionEditObj.value.market = [];
  666. }
  667. };
  668. const addUserProps = {
  669. multiple: true,
  670. }
  671. /*// 计算属性控制级联选择器的选项禁用状态
  672. const addUserProps = computed(() => {
  673. // 判断是否已选择总部
  674. const hasHeadquarters = addAdmin.value.market.includes('总部');
  675. return {
  676. multiple: true, // 保留多选功能
  677. // 选项禁用逻辑:如果已选择总部,则禁用非总部的选项
  678. disabled: (data) => {
  679. return hasHeadquarters && data.label !== '总部';
  680. }
  681. };
  682. });*/
  683. const editUserProps = {
  684. multiple: true,
  685. }
  686. /*// 计算属性控制级联选择器的选项禁用状态
  687. const editUserProps = computed(() => {
  688. // 判断是否已选择总部
  689. const hasHeadquarters = permissionEditObj.value.market.includes('总部');
  690. return {
  691. multiple: true, // 保留多选功能
  692. // 选项禁用逻辑:如果已选择总部,则禁用非总部的选项
  693. disabled: (data) => {
  694. return hasHeadquarters && data.label !== '总部';
  695. }
  696. };
  697. });*/
  698. const selectParentNodes = (treeData, nodeId, checkedKeys) => {
  699. if (!Array.isArray(treeData)) return false;
  700. for (const item of treeData) {
  701. // 先检查子节点
  702. if (item.children && item.children.length > 0) {
  703. const foundInChildren = selectParentNodes(item.children, nodeId, checkedKeys);
  704. if (foundInChildren) {
  705. // 找到子节点后添加当前节点(父节点)
  706. checkedKeys.add(item.id);
  707. return true;
  708. }
  709. }
  710. // 检查当前节点是否为目标节点
  711. if (item.id === nodeId) {
  712. return true;
  713. }
  714. }
  715. return false;
  716. };
  717. // 重置密码弹窗状态
  718. const resetConfirmVisible = ref(false)
  719. // 当前选中的行数据
  720. const currentRow = ref(null)
  721. // 重置密码
  722. const resetPassword = function (row) {
  723. // 显示确认弹窗
  724. currentRow.value = row
  725. resetConfirmVisible.value = true
  726. }
  727. // 确认重置密码
  728. const confirmResetPassword = async function () {
  729. if (!canEdit) {
  730. ElMessage.error('无此权限')
  731. return
  732. }
  733. console.log('adminData', adminData.value)
  734. // 处理markets数据
  735. if (typeof adminData.value.markets === 'string' && adminData.value.markets) {
  736. adminData.value.markets = adminData.value.markets.split(',');
  737. } else if (Array.isArray(adminData.value.markets)) {
  738. // 不处理
  739. } else {
  740. adminData.value.markets = [];
  741. }
  742. console.log('重置密码markets2', adminData.value.markets)
  743. // 权限检查
  744. if (adminData.value.markets.includes(currentRow.value.market) || adminData.value.markets[0] === '总部' || adminData.value.markets[0] === '研发部') {
  745. console.log('符合条件,可以操作', adminData.value.markets.includes(currentRow.value.market) || adminData.value.markets[0] === '总部' || adminData.value.markets[0] === '研发部');
  746. const params = {
  747. account: currentRow.value.account,
  748. }
  749. console.log(params);
  750. // 发送请求
  751. try {
  752. const result = await request({
  753. url: '/admin/reset',
  754. method: 'post',
  755. data: params // 直接传递params对象
  756. });
  757. if (result.code === 200) { // 使用严格相等运算符
  758. ElMessage.success('重置密码成功');
  759. resetConfirmVisible.value = false; // 关闭弹窗
  760. await getPermission()
  761. } else {
  762. ElMessage.error(result.message || '重置密码失败');
  763. }
  764. } catch (error) {
  765. ElMessage.error('重置密码失败');
  766. console.error('请求错误:', error);
  767. }
  768. } else {
  769. // console.log("为什么不能重置",adminData.value.markets)
  770. ElMessage.error('您没有修改' + currentRow.value.market + '地区的用户密码的权限');
  771. resetConfirmVisible.value = false; // 关闭弹窗
  772. }
  773. }
  774. // 取消重置密码
  775. const cancelResetPassword = function () {
  776. resetConfirmVisible.value = false
  777. const collectIds2 = (tree) => {
  778. let ids = [];
  779. tree.forEach((node) => {
  780. // 如果当前节点没有 children 或 children 为空,说明是叶子节点
  781. if (!node.children || node.children.length === 0) {
  782. ids.push(node.id);
  783. } else {
  784. // 如果有 children,递归收集子节点的叶子节点
  785. ids = ids.concat(collectIds2(node.children));
  786. }
  787. });
  788. return ids;
  789. };
  790. }
  791. // 为提交时查找父节点的辅助函数
  792. const selectParentNodesForSubmit = (treeData, nodeId, checkedKeys) => {
  793. if (!Array.isArray(treeData)) return false;
  794. for (const item of treeData) {
  795. // 先检查子节点
  796. if (item.children && item.children.length > 0) {
  797. const foundInChildren = selectParentNodesForSubmit(item.children, nodeId, checkedKeys);
  798. if (foundInChildren) {
  799. // 找到子节点后添加当前节点(父节点)
  800. checkedKeys.add(item.id);
  801. return true;
  802. }
  803. }
  804. // 检查当前节点是否为目标节点
  805. if (item.id === nodeId) {
  806. return true;
  807. }
  808. }
  809. return false;
  810. };
  811. const throttledPermissionEdit = _.throttle(permissionEdit, 5000, {
  812. trailing: false
  813. })
  814. // 使用 _.throttle 并设置 trailing 为 false 实现严格节流,只执行一次
  815. const throttledPermissionAdd = _.throttle(permissionAdd, 5000, {
  816. trailing: false
  817. })
  818. const canLook = findMenuById(menuTree.value, permissionMapping.display_user_management)// 我真是服啦,查询也做嘛
  819. const canAdd = findMenuById(menuTree.value, permissionMapping.add_user_information)
  820. const canEdit = findMenuById(menuTree.value, permissionMapping.edit_user_information)
  821. const canReset = findMenuById(menuTree.value, permissionMapping.reset_user_password)
  822. const canDel = findMenuById(menuTree.value, permissionMapping.delete_user_information)
  823. const change = findMenuById(menuTree.value, permissionMapping.enable_disable_user)
  824. // 挂载
  825. onMounted(async function () {
  826. await getPermission()
  827. await getArea()
  828. await getStore()
  829. await getRoles()
  830. await getRoleArea()
  831. console.log('看看权限', canAdd, canEdit, canReset, canDel, change)
  832. })
  833. </script>
  834. <template>
  835. <div>
  836. <el-card class="card1" style="margin-bottom: 1vh;">
  837. <div class="head-card">
  838. <div class="head-card-element">
  839. <el-text class="mx-1" size="large">OA号</el-text>
  840. <el-input v-model="admin.account" style="width: 240px" placeholder="请输入OA号" clearable />
  841. </div>
  842. <div class="head-card-element" style="margin-left: 50px">
  843. <el-text class="mx-1" size="large">所属地区</el-text>
  844. <el-cascader v-model="admin.market" :options="marketsTree" placeholder="请选择所属地区" clearable style="width:180px"
  845. @change="handleMarketChange" />
  846. </div>
  847. <div class="head-card-element" style="margin-left: 50px">
  848. <el-text class="mx-1" size="large">职位名称</el-text>
  849. <el-select v-model="admin.postiton" placeholder="请选择职位名称" style="width: 240px" clearable>
  850. <el-option v-for="item in postiton" :key="item" :label="item" :value="item" />
  851. </el-select>
  852. </div>
  853. <div class="head-card-btn">
  854. <el-button type="primary" @click="search()" v-if="canLook">查询</el-button>
  855. <el-button type="success" @click="reset()">重置</el-button>
  856. </div>
  857. </div>
  858. </el-card>
  859. <el-card class="card2">
  860. <!-- 展示表单 -->
  861. <div class="add-item">
  862. <el-button style="color: #048efb; border: 1px solid #048efb" :disabled="!canAdd" v-if="canAdd"
  863. @click="userAddInit()">新增用户
  864. </el-button>
  865. </div>
  866. <div>
  867. <el-table :data="tableData" style="width: 82vw;height:63.3vh" show-overflow-tooltip
  868. >
  869. <el-table-column type="index" label="序号" width="100px" fixed="left">
  870. <template #default="scope">
  871. <span>{{
  872. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  873. }}</span>
  874. </template>
  875. </el-table-column>
  876. <el-table-column prop="account" label="OA号" />
  877. <el-table-column prop="name" label="姓名" />
  878. <el-table-column prop="market" label="所属地区" />
  879. <el-table-column prop="postiton" label="职位" />
  880. <el-table-column prop="roleName" label="部门权限">
  881. </el-table-column>
  882. <el-table-column prop="remark" label="备注" />
  883. <el-table-column prop="operation" label="操作" width="280px">
  884. <template #default="scope">
  885. <el-button type="warning" text :disabled="!canReset" @click="resetPassword(scope.row)" v-if="canReset">
  886. 重置密码
  887. </el-button>
  888. <el-button type="primary" text @click="permissionEditInit(scope.row)" v-if="canEdit"
  889. :disabled="!canEdit || scope.row.adminStatus === 0 || scope.row.account === adminData.account">
  890. 修改权限
  891. </el-button>
  892. <el-popconfirm title="确定将此用户删除吗?" @confirm="delConfirm">
  893. <template #reference>
  894. <el-button type="danger" text @click="del(scope.row)" v-if="canDel"
  895. :disabled="!canDel || scope.row.adminStatus === 0 || scope.row.account === adminData.account">
  896. 删除
  897. </el-button>
  898. </template>
  899. <template #actions="{ confirm, cancel }">
  900. <el-button size="small" @click="cancel">取消</el-button>
  901. <el-button type="primary" size="small" @click="confirm">
  902. 确定
  903. </el-button>
  904. </template>
  905. </el-popconfirm>
  906. </template>
  907. </el-table-column>
  908. <el-table-column prop="adminStatus" label="状态">
  909. <template #default="scope">
  910. <el-switch :model-value="scope.row.adminStatus" :active-value="1" :inactive-value="0" size="large"
  911. v-if="change"
  912. :disabled="!change || scope.row.account === adminData.account || statusLoading[scope.row.id]"
  913. @change="(targetStatus) => showStatusConfirm(scope.row, targetStatus)" style="
  914. --el-switch-on-color: #13ce66;
  915. --el-switch-off-color: #ff4949;
  916. " active-text="启用" inactive-text="禁用" inline-prompt />
  917. </template>
  918. </el-table-column>
  919. </el-table>
  920. <div class="pagination" style="margin-top: 1vh;">
  921. <el-pagination background :current-page="getObj.pageNum" :page-size="getObj.pageSize" :page-sizes="[5, 10, 20, 50, 100]"
  922. layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handlePageSizeChange"
  923. @current-change="handleCurrentChange"></el-pagination>
  924. </div>
  925. </div>
  926. </el-card>
  927. </div>
  928. <!-- 新增用户权限 -->
  929. <el-dialog v-model="userAddVisible" title="新增用户权限" width="800px" :close-on-click-modal="false"
  930. @close="handleDialogClose">
  931. <template #footer>
  932. <el-form ref="Ref" :rules="addUserRules" :model="addAdmin" label-width="auto"
  933. style="max-width: 600px; align-items: center">
  934. <el-form-item prop="account" label="OA号:" required clearable>
  935. <el-input v-model="addAdmin.account" placeholder="请输入OA号" style="width: 220px" />
  936. </el-form-item>
  937. <el-form-item prop="name" label="用户名:" required clearable>
  938. <el-input v-model="addAdmin.name" placeholder="请输入用户名" style="width: 220px" />
  939. </el-form-item>
  940. <el-form-item prop="market" label="所属地区:" required clearable>
  941. <el-cascader v-model="addAdmin.market" :options="marketsTree" placeholder="请选择所属地区" clearable collapse-tags
  942. collapse-tags-tooltip style="width:220px" @change="handleMarketChangeAddUser" :max-collapse-tags="2"
  943. :props="addUserProps" />
  944. </el-form-item>
  945. <el-form-item prop="permission" label="角色名称:" required>
  946. <el-select v-model="addAdmin.permission" placeholder="请选择角色名称" style="width: 220px" clearable>
  947. <el-option v-for="item in permissionList" :key="item.value" :label="item.label"
  948. :value="item.value"></el-option>
  949. </el-select>
  950. </el-form-item>
  951. <el-form-item prop="postiton" label="职位:" required>
  952. <el-input v-model="addAdmin.postiton" placeholder="请输入职位" style="width: 220px" clearable />
  953. </el-form-item>
  954. <el-form-item prop="machineIds" label="机器码:" required>
  955. <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px;">
  956. <!-- 动态添加的机器码输入框 -->
  957. <div v-for="(item, index) in addAdmin.machineIds" :key="index">
  958. <el-input v-model="addAdmin.machineIds[index]" placeholder="请输入机器码"
  959. style="width: 220px; margin-right: 10px;" />
  960. </div>
  961. <el-button type="primary" @click="addMachineIdInput">添加</el-button>
  962. </div>
  963. </el-form-item>
  964. <el-form-item prop="remark" label="备注">
  965. <el-input v-model="addAdmin.remark" style="width: 300px" :rows="2" maxlength="100" show-word-limit
  966. type="textarea" />
  967. </el-form-item>
  968. </el-form>
  969. <div>
  970. <el-button @click="closeUserAddVisible()">取消</el-button>
  971. <el-button type="primary" @click="throttledPermissionAdd()">
  972. 提交
  973. </el-button>
  974. </div>
  975. </template>
  976. </el-dialog>
  977. <!-- 这是编辑用户权限弹窗 -->
  978. <el-dialog v-model="userEditVisible" title="编辑用户权限" width="800px" :close-on-click-modal="false">
  979. <el-form ref="Ref" :rules="editAdminRules" :model="permissionEditObj" label-width="auto"
  980. style="max-width: 600px; align-items: center">
  981. <el-form-item prop="account" label="用户账号:" clearable>
  982. <el-input v-model="permissionEditObj.account" placeholder="请输入OA号" style="width: 220px" disabled />
  983. </el-form-item>
  984. <el-form-item prop="name" label="用户名称:">
  985. <el-input v-model="permissionEditObj.adminName" placeholder="请输入用户名" style="width: 220px" disabled />
  986. </el-form-item>
  987. <el-form-item prop="market" label="所属地区:" clearable>
  988. <el-cascader v-model="permissionEditObj.market" :options="marketsTree" placeholder="请选择所属地区" clearable
  989. collapse-tags collapse-tags-tooltip style="width:220px" @change="handleMarketChangeEditUser"
  990. :max-collapse-tags="2" :props="editUserProps" />
  991. </el-form-item>
  992. <el-form-item prop="postiton" label="职位:">
  993. <el-input v-model="permissionEditObj.postiton" placeholder="请输入职位" style="width: 220px" clearable />
  994. </el-form-item>
  995. <el-form-item prop="roleName" label="角色名称:">
  996. <el-select v-model="permissionEditObj.roleId" placeholder="请选择角色" style="width: 220px" @change="getUserLists">
  997. <el-option v-for="item in permissionList" :key="item.value" :label="item.label"
  998. :value="item.value"></el-option>
  999. </el-select>
  1000. </el-form-item>
  1001. <el-form-item prop="parentName" label="上级角色:">
  1002. <el-select v-model="permissionEditObj.parentId" placeholder="无上级角色" :disabled="!!parentRoleTip"
  1003. style="width: 220px">
  1004. <el-option v-if="parentRoleTip" :key="0" :label="parentRoleTip" :value="null" disabled />
  1005. <el-option v-else v-for="item in permissionList" :key="item.value" :label="item.label" disabled
  1006. :value="item.value"></el-option>
  1007. </el-select>
  1008. </el-form-item>
  1009. <el-form-item prop="permissionSelect" label="权限列表:">
  1010. <el-tree v-if="data.length > 0" :data="data" :disabled="true" show-checkbox node-key="id"
  1011. :props="{ label: 'menuName', children: 'children' }" :default-checked-keys="permissionEditObj.checkedKeys">
  1012. </el-tree>
  1013. <div v-else style="display: flex; align-items: center; gap: 8px;">
  1014. <span style="color: #999;">暂无数据</span>
  1015. </div>
  1016. </el-form-item>
  1017. <el-form-item prop="machineIds" label="机器码:">
  1018. <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px;">
  1019. <!-- 动态添加的机器码输入框 -->
  1020. <div v-for="(item, index) in permissionEditObj.machineIds" :key="index">
  1021. <el-input v-model="permissionEditObj.machineIds[index]" placeholder=""
  1022. style="width: 220px; margin-right: 10px;" />
  1023. </div>
  1024. <el-button type="primary" @click="UseraddMachineIdInput">添加</el-button>
  1025. </div>
  1026. </el-form-item>
  1027. </el-form>
  1028. <div>
  1029. </div>
  1030. <template #footer>
  1031. <div>
  1032. <el-button @click="closeUserEditVisible()">取消</el-button>
  1033. <el-button type="primary" @click="throttledPermissionEdit">
  1034. 提交
  1035. </el-button>
  1036. </div>
  1037. </template>
  1038. </el-dialog>
  1039. <!-- 重置密码确认弹窗 -->
  1040. <el-dialog v-model="resetConfirmVisible" width="500px" :close-on-click-modal="false"
  1041. :before-close="cancelResetPassword">
  1042. <el-row>
  1043. <el-col :span="4" style="margin-top: 20px">
  1044. <el-icon class="dialog-icon" color="#10AEFF" size="50">
  1045. <InfoFilled />
  1046. </el-icon>
  1047. </el-col>
  1048. <el-col :span="20">
  1049. <h3>提示</h3>
  1050. <p class="dialog-title">确认重置该账号密码</p>
  1051. <p class="dialog-desc">重置后密码为: 123456请通知用户及时修改</p>
  1052. </el-col>
  1053. </el-row>
  1054. <template #footer>
  1055. <div style="display: flex; justify-content: center; gap: 30px">
  1056. <el-button @click="cancelResetPassword">取消</el-button>
  1057. <el-button type="primary" @click="confirmResetPassword">确定</el-button>
  1058. </div>
  1059. </template>
  1060. </el-dialog>
  1061. <el-dialog v-model="ackVisible" width="700px" :close-on-click-modal="false" :style="{
  1062. backgroundImage: `url(${BackGroundSvg})`,
  1063. backgroundSize: 'cover',
  1064. backgroundPosition: 'center',
  1065. height: '400px'
  1066. }"
  1067. @close="() => { if (currentStatusRow) currentStatusRow.adminStatus = currentStatusRow.adminStatus === 1 ? 0 : 1 }">
  1068. <div class="status-confirm-content">
  1069. 将要{{ currentStatusRow?.adminStatus === 1 ? '禁用' : '启用' }}该用户
  1070. <br>
  1071. </div>
  1072. <template #footer>
  1073. <div style="display: flex; justify-content: center; gap: 10px;">
  1074. <el-button round size="large" @click="() => {
  1075. currentStatusRow.adminStatus = currentStatusRow.adminStatus === 1 ? 0 : 1
  1076. ackVisible = false
  1077. }">
  1078. 取消
  1079. </el-button>
  1080. <el-button round size="large" type="primary" @click="() => {
  1081. editStatus(currentStatusRow)
  1082. ackVisible = false
  1083. }">
  1084. 确认
  1085. </el-button>
  1086. </div>
  1087. </template>
  1088. </el-dialog>
  1089. </template>
  1090. <style scoped lang="scss">
  1091. // 新增用户按钮
  1092. .add-item {
  1093. margin-bottom: 1vh;
  1094. }
  1095. // 搜索的卡片样式
  1096. .card1 {
  1097. background: #F3FAFE;
  1098. }
  1099. // 表单的卡片样式
  1100. .card2 {
  1101. background: #E7F4FD;
  1102. }
  1103. // 表头背景等
  1104. :deep(.el-table__header-wrapper),
  1105. :deep(.el-table__body-wrapper),
  1106. :deep(.el-table__cell),
  1107. /* 表格 */
  1108. :deep(.el-table__body td) {
  1109. background-color: #F3FAFE !important;
  1110. }
  1111. /* 表头 */
  1112. :deep(.el-table__header th) {
  1113. background-color: #F3FAFE !important;
  1114. }
  1115. /* 鼠标悬停 */
  1116. :deep(.el-table__row:hover > .el-table__cell) {
  1117. background-color: #E5EBFE !important;
  1118. }
  1119. .pagination {
  1120. display: flex;
  1121. }
  1122. .head-card {
  1123. display: flex;
  1124. }
  1125. .head-card-element {
  1126. margin-right: 20px;
  1127. }
  1128. .head-card-btn {
  1129. margin-left: auto;
  1130. }
  1131. .status-confirm-content {
  1132. text-align: center;
  1133. margin-top: 160px;
  1134. margin-bottom: 30px;
  1135. font-size: 48px;
  1136. }
  1137. </style>