index.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <el-container class="is-vertical">
  3. <sc-page-header @add="table_add"></sc-page-header>
  4. <el-container class="user-container">
  5. <el-aside width="310px">
  6. <el-header>
  7. <el-input v-model="filterText" clearable placeholder="输入关键字进行过滤"></el-input>
  8. <el-button title="重置部门" circle @click="dept_unset">
  9. <template #icon><sc-iconify icon="iconoir:remove-link"></sc-iconify></template>
  10. </el-button>
  11. </el-header>
  12. <el-main class="nopadding">
  13. <el-scrollbar>
  14. <el-tree ref="treeRef" node-key="id" :data="deptTree" :expand-on-click-node="false" highlight-current check-strictly :filter-node-method="filterNode" @node-click="data => nodeClick(data)">
  15. <template #default="{ data }">
  16. <vxe-text-ellipsis :id="data.id" :title="data.name" class="custom-tree-node" :content="data.name"></vxe-text-ellipsis>
  17. </template>
  18. </el-tree>
  19. </el-scrollbar>
  20. </el-main>
  21. </el-aside>
  22. <scTable ref="xGridTable" :apiObj="$API.auth.user" :formConfig="formConfig" :paramsColums="paramsColums" :toolbarConfig="toolbarConfig" :columns="columns">
  23. <template #action="{ row }">
  24. <el-button type="primary" link @click="password_rest(row)">
  25. <template #icon><sc-iconify icon="material-symbols:arrow-split"></sc-iconify></template>重置密码
  26. </el-button>
  27. <el-button type="primary" link @click="table_edit(row)">
  28. <template #icon><sc-iconify icon="ant-design:edit-outlined"></sc-iconify></template>修改
  29. </el-button>
  30. <el-button type="primary" link @click="table_del(row)">
  31. <template #icon><sc-iconify icon="ant-design:delete-outlined"></sc-iconify></template>删除
  32. </el-button>
  33. </template>
  34. </scTable>
  35. </el-container>
  36. </el-container>
  37. <user-detail v-if="dialog" ref="userRef" :deptTree="deptTree" @success="refreshTable" @closed="dialog = false"></user-detail>
  38. </template>
  39. <script setup>
  40. import XEUtils from "xe-utils";
  41. import API from "@/api";
  42. import { mapFormItemInput } from "@/components/scTable/helper";
  43. import userDetail from "./detail";
  44. const filterText = ref("");
  45. const deptTree = ref([]);
  46. const treeRef = ref();
  47. watch(() => filterText.value, value => treeRef.value.filter(value));
  48. const filterNode = (value, data) => {
  49. if (!value) return true;
  50. return data.name.includes(value);
  51. }
  52. const nodeClick = data => {
  53. XEUtils.set(formConfig.data, "deptId", data.id);
  54. refreshTable();
  55. }
  56. const dept_unset = () => {
  57. treeRef.value.setCurrentKey();
  58. XEUtils.set(formConfig.data, "deptId", null);
  59. refreshTable();
  60. }
  61. const toolbarConfig = reactive({
  62. enabled: true,
  63. export: true
  64. });
  65. const formConfig = reactive({
  66. data: {},
  67. items: [
  68. mapFormItemInput("usernameLike", "用户名"),
  69. mapFormItemInput("nickNameLike", "用户昵称"),
  70. mapFormItemInput("phoneLike", "手机号")
  71. ]
  72. });
  73. const paramsColums = reactive([
  74. { column: "orderBy", defaultValue: "id_desc" },
  75. { column: "deptId" },
  76. { column: "usernameLike" },
  77. { column: "nickNameLike" },
  78. { column: "phoneLike" }
  79. ]);
  80. const columns = reactive([
  81. { type: "seq", width: 60 },
  82. { type: "html", field: "username", title: "用户名", minWidth: 160, sortable: true },
  83. { type: "html", field: "nickName", title: "用户昵称", minWidth: 160, sortable: true },
  84. { type: "html", field: "dept.name", title: "所属部门", minWidth: 160, sortable: true },
  85. { type: "html", field: "gender", title: "性别", minWidth: 100, sortable: true },
  86. { type: "html", field: "phone", title: "手机号", minWidth: 120, sortable: true },
  87. { type: "html", field: "email", title: "邮箱", minWidth: 160, sortable: true },
  88. { visible: false, type: "html", field: "idcard", title: "身份证号", minWidth: 160, sortable: true, formatter: ({ cellValue, row }) => cellValue || XEUtils.get(XEUtils.toStringJSON(row.features), "idcard") },
  89. { title: "操作", fixed: "right", width: 220, align: "center", slots: { default: "action" } }
  90. ]);
  91. // 显示隐藏 筛选表单
  92. const xGridTable = ref();
  93. const refreshTable = (mode = "add") => xGridTable.value.searchData(mode);
  94. const userRef = ref();
  95. const dialog = ref(false);
  96. const table_add = () => {
  97. dialog.value = true;
  98. nextTick(() => userRef.value?.open());
  99. }
  100. const table_edit = row => {
  101. dialog.value = true;
  102. nextTick(() => userRef.value?.setData(row));
  103. }
  104. const table_del = ({ id }) => {
  105. ElMessageBox.confirm("是否确认删除该用户?", "删除警告", {
  106. type: "warning",
  107. confirmButtonText: "确定",
  108. cancelButtonText: "取消"
  109. }).then(() => {
  110. API.auth.user.del(({ id })).then(() => {
  111. ElMessage.success("操作成功");
  112. refreshTable();
  113. });
  114. }).catch(() => {});
  115. }
  116. const password_rest = ({ id, username }) => {
  117. ElMessageBox.confirm(`是否确认重置"${username}"密码?`, "重置密码", {
  118. type: "warning",
  119. confirmButtonText: "确定",
  120. cancelButtonText: "取消"
  121. }).then(() => {
  122. API.auth.user.resetPass(({ id })).then(() => {
  123. ElNotification.success({
  124. title: "提示",
  125. message: `密码已重置,密码为:123456`,
  126. duration: 1500
  127. });
  128. });
  129. }).catch(() => {});
  130. }
  131. const fetchDept = () => API.system.dept.get({ orderBy: "deptSort_asc" }).then(res => deptTree.value = XEUtils.toArrayTree(res, { parentKey: "pid" })).catch(() => deptTree.value = []);
  132. fetchDept();
  133. </script>
  134. <style lang="scss" scoped>
  135. .user-container {border-top: 1px solid var(--el-border-color-light);}
  136. .user-container .el-aside {display: flex;flex-direction: column;}
  137. .user-container .el-aside .el-header .el-button {margin-left: 10px;}
  138. .user-container .el-aside .el-main {padding-top: 15px;padding-left: 15px;}
  139. .user-container .el-aside + .el-main {padding-top: 15px;}
  140. @media (max-width: 992px) {
  141. .aminui-main > .el-container > .el-container.user-container {display: block;margin-top: 0;border: none;}
  142. .user-container .el-aside {width: 100%;}
  143. .user-container .el-aside .el-main {padding-bottom: 15px;}
  144. .user-container .el-aside + .el-main {margin-top: 15px;}
  145. }
  146. </style>