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.

1242 lines
40 KiB

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