index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <template>
  2. <a-card class="account-page-card">
  3. <Action
  4. :btn_text="$t('permission.account.new_user')"
  5. :btn_permission="'system:user:add'"
  6. @searchClick="searchClick"
  7. @resetClick="resetClick"
  8. @createClick="createClick"
  9. @sizeChange="tableSizeChange"
  10. @refreshClick="refreshClick"
  11. >
  12. </Action>
  13. <DataTable
  14. :data="table_data"
  15. :columns="table_columns"
  16. row-key="userId"
  17. :scroll="{
  18. x: 2000
  19. }"
  20. :size="table_size"
  21. :loading="table_loading"
  22. :pagination="pagination_props"
  23. @pageChange="handlePageChange"
  24. >
  25. <template #status="{ record }">
  26. <a-switch v-model="record.status" @change="statusChange(record)" checked-value="1" unchecked-value="0" />
  27. </template>
  28. <template #operationSlot="{ record }">
  29. <a-popconfirm :content="$t('permission.account.reset_password')" @ok="handleResetPassword(record)">
  30. <a-button v-hasPermi="'system:role:resetPassword'" type="text">{{
  31. $t('permission.account.reset_password')
  32. }}</a-button>
  33. </a-popconfirm>
  34. <a-button v-hasPermi="'system:user:edit'" type="text" @click="handleEdit(record, true)">{{
  35. $t('permission.account.edit')
  36. }}</a-button>
  37. <a-button v-hasPermi="'system:user:viewPermission'" type="text" @click="handleView(record, true)">{{
  38. $t('permission.account.view_permission')
  39. }}</a-button>
  40. <a-button v-hasPermi="'system:user:deptEdit'" type="text" @click="handleDeptConfig(record, true)">{{
  41. $t('permission.account.dept_config')
  42. }}</a-button>
  43. <a-button
  44. v-hasPermi="'system:user:delete'"
  45. @click="handleDeleteModal(record.userId, $t('permission.delete_confirm'))"
  46. type="text"
  47. status="warning"
  48. >{{ $t('permission.account.delete') }}</a-button
  49. >
  50. </template>
  51. </DataTable>
  52. </a-card>
  53. <OperateModal
  54. :visible.sync="edit_visible"
  55. @ok="modalSave"
  56. @cancel="handleEdit(null, false)"
  57. :title="is_edit_mode ? $t('permission.account.edit') : $t('permission.account.new_user')"
  58. >
  59. <AccountForm :edit_form="edit_form" :is_edit_mode="is_edit_mode" :role_list="role_list" />
  60. </OperateModal>
  61. <ViewPermission
  62. :visible.sync="view_permission_visible"
  63. @cancel="handleView(null, false)"
  64. @close="handleView(null, false)"
  65. :menu_permissions_list="menu_permissions_list"
  66. :knowledge_permissions_list="knowledge_permissions_list"
  67. :dialog_permissions_list="dialog_permissions_list"
  68. :agent_permissions_list="agent_permissions_list"
  69. />
  70. <DeptConfigModal
  71. :visible.sync="dept_config_visible"
  72. :dept_list="dept_list"
  73. :dept_detail="dept_detail"
  74. @ok="handleDeptConfigSave"
  75. @cancel="handleDeptConfig(null, false)"
  76. />
  77. </template>
  78. <script setup>
  79. import { ref, reactive, onMounted } from 'vue';
  80. import { Message, Modal } from '@arco-design/web-vue';
  81. import DataTable from '../../../views/permission/DataTable.vue';
  82. import Action from '../../../views/permission/Action.vue';
  83. import OperateModal from '../../../views/permission/Modal.vue';
  84. import AccountForm from './AccountForm.vue';
  85. import ViewPermission from './ViewPermission.vue';
  86. import DeptConfigModal from './DeptConfigModal.vue';
  87. import { hasPermission } from '../../../utils/permission';
  88. import {
  89. QueryUserList,
  90. QueryUserDeptDetail,
  91. UpdateUserDept,
  92. AddUser,
  93. UpdateUser,
  94. QueryUserPermission,
  95. UserStatusSwitch,
  96. ResetPassword,
  97. DeleteUser
  98. } from '../../../apis/permission/account';
  99. import { QueryAllRoleList, QueryDeptTree } from '../../../apis/permission/common';
  100. const keywords = ref('');
  101. // 表格相关
  102. const table_data = ref([]);
  103. const table_columns = ref([
  104. { title: '序号', width: 80, fixed: 'left', slotName: 'index' },
  105. { title: '用户名', dataIndex: 'userName', width: 150, titleSlotName: 'userName' },
  106. { title: '姓名', dataIndex: 'loginName', titleSlotName: 'loginName' },
  107. {
  108. title: '角色',
  109. dataIndex: 'roleName',
  110. width: 300,
  111. ellipsis: true,
  112. tooltip: { position: 'top' },
  113. titleSlotName: 'roleName'
  114. },
  115. {
  116. title: '所属部门',
  117. dataIndex: 'deptName',
  118. width: 400,
  119. ellipsis: true,
  120. tooltip: { position: 'top' },
  121. titleSlotName: 'deptName'
  122. },
  123. { title: '手机号', dataIndex: 'phone', width: 150, titleSlotName: 'phone' },
  124. { title: '邮箱', dataIndex: 'email', width: 150, titleSlotName: 'email' },
  125. { title: '状态', dataIndex: 'status', width: 100, slotName: 'status' },
  126. { title: '操作', dataIndex: 'operation', width: 500, fixed: 'right', slotName: 'operationSlot' }
  127. ]);
  128. const pagination_props = ref({
  129. total: 10,
  130. current: 1,
  131. pageSize: 12
  132. });
  133. const table_size = ref('medium');
  134. const table_loading = ref(false);
  135. // 编辑表单相关
  136. const edit_visible = ref(false);
  137. const is_edit_mode = ref(false);
  138. const edit_form = reactive({
  139. userName: '',
  140. userName: '',
  141. phone: '',
  142. email: '',
  143. pwd: '',
  144. roles: []
  145. });
  146. const role_list = ref([]);
  147. // 查看权限相关
  148. const view_permission_visible = ref(false);
  149. const menu_permissions_list = ref([]);
  150. const knowledge_permissions_list = ref([]);
  151. const dialog_permissions_list = ref([]);
  152. const agent_permissions_list = ref([]);
  153. // 部门配置相关
  154. const dept_config_visible = ref(false);
  155. const dept_detail = ref([]);
  156. const dept_list = ref([]);
  157. const getUserList = async () => {
  158. const params = {
  159. keyword: keywords.value,
  160. current: pagination_props.value.current,
  161. pageSize: pagination_props.value.pageSize
  162. };
  163. table_loading.value = true;
  164. const { code, data } = await QueryUserList(params);
  165. if (code === 200) {
  166. // 处理部门名称和角色名称
  167. for (const user of data.rows) {
  168. user.deptName = ''; // 初始化 deptName
  169. user.roleName = ''; // 初始化 roleName
  170. if (user.depts) {
  171. for (let i = 0; i < user.depts.length; i++) {
  172. const d = user.depts[i];
  173. user.deptName += d.deptName + (i < user.depts.length - 1 ? ', ' : '');
  174. }
  175. }
  176. if (user.roles) {
  177. for (let i = 0; i < user.roles.length; i++) {
  178. const r = user.roles[i];
  179. user.roleName += r.roleName + (i < user.roles.length - 1 ? ', ' : '');
  180. }
  181. }
  182. }
  183. pagination_props.value.total = data.total;
  184. table_data.value = data.rows;
  185. table_loading.value = false;
  186. } else {
  187. table_loading.value = false;
  188. }
  189. };
  190. const searchClick = (value) => {
  191. keywords.value = value;
  192. getUserList();
  193. };
  194. const resetClick = () => {
  195. keywords.value = '';
  196. getUserList();
  197. };
  198. const createClick = () => {
  199. edit_form.userId = '';
  200. edit_form.userName = '';
  201. edit_form.loginName = '';
  202. edit_form.phone = '';
  203. edit_form.email = '';
  204. edit_form.pwd = '';
  205. edit_form.roles = [];
  206. is_edit_mode.value = false;
  207. handleEdit(null, true);
  208. };
  209. const refreshClick = () => {
  210. console.log('刷新');
  211. };
  212. // 切换页码
  213. const handlePageChange = (current) => {
  214. pagination_props.value.current = current;
  215. getUserList();
  216. };
  217. // 用户状态切换
  218. const statusChange = async (record) => {
  219. if (record?.dept) {
  220. const params = {
  221. userId: record.userId,
  222. status: record.status
  223. };
  224. const { code } = await UserStatusSwitch(params);
  225. if (code === 200) {
  226. Message.success({
  227. title: '成功',
  228. content: '状态切换成功.'
  229. });
  230. }
  231. } else {
  232. record.status = '0';
  233. Message.warning({
  234. title: '提示',
  235. content: '如想启用用户,需进行部门配置.'
  236. });
  237. }
  238. };
  239. //重置密码
  240. const handleResetPassword = async (record) => {
  241. const { code } = await ResetPassword(record.userId);
  242. if (code === 200) {
  243. Message.success({
  244. title: '重置密码',
  245. content: '该用户密码重置为000000'
  246. });
  247. }
  248. };
  249. const handleEdit = async (record, visible) => {
  250. if (visible) {
  251. const { code, data } = await QueryAllRoleList();
  252. if (code === 200) {
  253. role_list.value = data.rows;
  254. }
  255. }
  256. if (record) {
  257. edit_form.userId = record.userId;
  258. edit_form.userName = record.userName;
  259. edit_form.loginName = record.loginName;
  260. edit_form.phone = record.phone;
  261. edit_form.email = record.email;
  262. edit_form.pwd = record.pwd;
  263. edit_form.roles = record.roles.map((role) => role.roleId);
  264. is_edit_mode.value = true;
  265. }
  266. edit_visible.value = visible;
  267. };
  268. // 查看权限
  269. const handleView = async (record, visible) => {
  270. if (record) {
  271. dialog_permissions_list.value = [];
  272. knowledge_permissions_list.value = [];
  273. menu_permissions_list.value = [];
  274. const { code, data } = await QueryUserPermission(record.userId);
  275. if (code === 200) {
  276. const { knowledge, menus, dialog } = data;
  277. if (dialog && dialog.length > 0) dialog_permissions_list.value = dialog;
  278. if (knowledge && knowledge.length > 0) knowledge_permissions_list.value = knowledge;
  279. if (menus && menus.length > 0) menu_permissions_list.value = getMenuTitles(menus);
  280. }
  281. }
  282. view_permission_visible.value = visible;
  283. };
  284. // 部门配置
  285. const handleDeptConfig = async (record, visible) => {
  286. if (record) {
  287. edit_form.userId = record.userId;
  288. const {
  289. code,
  290. data: { rows }
  291. } = await QueryUserDeptDetail(record.userId);
  292. if (code === 200) {
  293. dept_detail.value = rows;
  294. }
  295. }
  296. dept_config_visible.value = visible;
  297. };
  298. const handleDeptConfigSave = async (checked_keys) => {
  299. dept_config_visible.value = false;
  300. const data = {
  301. userId: edit_form.userId,
  302. depts: checked_keys
  303. };
  304. const { code } = await UpdateUserDept(data);
  305. if (code === 200) {
  306. Message.success({
  307. title: '部门配置',
  308. content: '部门配置成功'
  309. });
  310. getUserList();
  311. }
  312. };
  313. // 删除用户
  314. const handleDelete = async (userId) => {
  315. const { code } = await DeleteUser(userId);
  316. if (code === 200) {
  317. Message.success({
  318. title: '删除用户',
  319. content: '删除成功'
  320. });
  321. getUserList();
  322. }
  323. };
  324. const modalSave = async () => {
  325. edit_visible.value = false;
  326. const data = {
  327. userId: is_edit_mode.value ? edit_form.userId : undefined,
  328. ...edit_form
  329. };
  330. const apiCall = is_edit_mode.value ? UpdateUser : AddUser;
  331. const { code } = await apiCall(data);
  332. if (code === 200) {
  333. const action = is_edit_mode.value ? '编辑' : '新增';
  334. Message.success({
  335. title: `${action}用户`,
  336. content: `${action}成功`
  337. });
  338. getUserList();
  339. }
  340. };
  341. const tableSizeChange = (size) => {
  342. table_size.value = size;
  343. };
  344. // 铺开路由菜单title
  345. const getMenuTitles = (data, result = []) => {
  346. data.forEach((item) => {
  347. // 检查item是否有id和name属性
  348. if (item.id && item.meta.title) {
  349. result.push({ id: item.id, name: item.meta.title });
  350. }
  351. // 如果有子项,递归调用函数
  352. if (item.children && item.children.length > 0) {
  353. getMenuTitles(item.children, result);
  354. }
  355. });
  356. return result;
  357. };
  358. const getDeptTree = async () => {
  359. const {
  360. code,
  361. data: { rows }
  362. } = await QueryDeptTree();
  363. if (code == 200) {
  364. dept_list.value = rows;
  365. }
  366. };
  367. const handleDeleteModal = (id, title) => {
  368. Modal.warning({
  369. title,
  370. okText: '确定',
  371. cancelText: '取消',
  372. hideCancel: false,
  373. onOk() {
  374. handleDelete(id);
  375. }
  376. });
  377. };
  378. onMounted(() => {
  379. if (hasPermission('system:user:list')) {
  380. getUserList();
  381. getDeptTree();
  382. } else {
  383. Message.error({
  384. title: '权限不足',
  385. content: '您没有权限查看用户列表'
  386. });
  387. }
  388. });
  389. </script>
  390. <style lang="css" scoped>
  391. .account-page-card {
  392. height: calc(100% - 56px);
  393. }
  394. </style>