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.

1247 lines
42 KiB

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