index.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <script setup lang="ts">
  2. import { reactive, onMounted, ref, nextTick } from "vue";
  3. import { getAdminUserList, removeAdminUser } from "@/api/admin";
  4. import { useRenderIcon } from "@/components/ReIcon/src/hooks";
  5. import { ExtDLabel, ExtDSelect } from "@/components/ExtForm";
  6. import { ElMessage, ElMessageBox } from "element-plus";
  7. import AccountDialog from "./dialog.vue";
  8. defineOptions({ name: "AdminAccount" });
  9. const queryRef = ref();
  10. const dialogRef = ref();
  11. interface ColumnItem {
  12. label: string;
  13. prop: string;
  14. width?: number;
  15. }
  16. const state = reactive({
  17. formQuery: {
  18. username: "",
  19. nickname: "",
  20. mobilePhone: "",
  21. status: ""
  22. },
  23. pageQuery: {
  24. pageNum: 1,
  25. pageSize: 10,
  26. total: 0
  27. },
  28. tableData: {
  29. height: 500,
  30. data: [] as Array<any>,
  31. loading: false,
  32. columns: [
  33. { label: "用户名", prop: "username", width: 120 },
  34. { label: "昵称", prop: "nickname", width: 180 },
  35. { label: "手机号", prop: "mobilePhone", width: 130 },
  36. { label: "状态", prop: "status", width: 100 },
  37. { label: "最后登录时间", prop: "lastLoginTime", width: 180 },
  38. { label: "创建时间", prop: "createTime", width: 180 }
  39. ] as ColumnItem[]
  40. }
  41. });
  42. onMounted(() => {
  43. loadData();
  44. nextTick(() => {
  45. const bodyHeight = document.body.clientHeight;
  46. const queryHeight = queryRef.value?.$el?.clientHeight || 0;
  47. state.tableData.height = bodyHeight - queryHeight - 280;
  48. });
  49. });
  50. const loadData = (refresh: boolean = false) => {
  51. if (refresh) {
  52. state.pageQuery.pageNum = 1;
  53. }
  54. state.tableData.loading = true;
  55. getAdminUserList({ ...state.formQuery, ...state.pageQuery })
  56. .then((res: any) => {
  57. const { list, total } = res || {};
  58. state.tableData.data = list || [];
  59. state.pageQuery.total = total || 0;
  60. })
  61. .catch(() => {
  62. state.tableData.data = [];
  63. })
  64. .finally(() => {
  65. state.tableData.loading = false;
  66. });
  67. };
  68. const handleSizeChange = (size: number) => {
  69. state.pageQuery.pageSize = size;
  70. loadData(true);
  71. };
  72. const handleCurrentChange = (page: number) => {
  73. state.pageQuery.pageNum = page;
  74. loadData();
  75. };
  76. const handleSearch = () => {
  77. loadData(true);
  78. };
  79. const handleReset = () => {
  80. state.formQuery = {
  81. username: "",
  82. nickname: "",
  83. mobilePhone: "",
  84. status: ""
  85. };
  86. loadData(true);
  87. };
  88. const handleAdd = () => dialogRef.value?.open("add");
  89. const handleEdit = (row: any) => dialogRef.value?.open("edit", row);
  90. const handleDelete = (row: any) => {
  91. ElMessageBox.confirm(`确定要删除用户『${row.username}』吗?`, "提示", {
  92. confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
  93. }).then(() => {
  94. removeAdminUser(row.id).then(() => {
  95. ElMessage.success("删除成功");
  96. loadData(true);
  97. });
  98. }).catch(() => {});
  99. };
  100. </script>
  101. <template>
  102. <div class="page-container">
  103. <el-card shadow="hover">
  104. <el-form ref="queryRef" :model="state.formQuery" inline class="search-form">
  105. <el-form-item label="用户名">
  106. <el-input v-model="state.formQuery.username" placeholder="请输入用户名" clearable @keyup.enter="handleSearch" />
  107. </el-form-item>
  108. <el-form-item label="昵称">
  109. <el-input v-model="state.formQuery.nickname" placeholder="请输入昵称" clearable @keyup.enter="handleSearch" />
  110. </el-form-item>
  111. <el-form-item label="手机号">
  112. <el-input v-model="state.formQuery.mobilePhone" placeholder="请输入手机号" clearable @keyup.enter="handleSearch" />
  113. </el-form-item>
  114. <el-form-item label="状态">
  115. <ExtDSelect
  116. v-model="state.formQuery.status"
  117. type="AdminUser.status"
  118. placeholder="请选择状态"
  119. @on-change="handleSearch"
  120. />
  121. </el-form-item>
  122. <el-form-item>
  123. <el-button
  124. type="primary"
  125. :icon="useRenderIcon('ri/search-line')"
  126. @click="handleSearch"
  127. >
  128. 查询
  129. </el-button>
  130. <el-button
  131. :icon="useRenderIcon('ri/refresh-line')"
  132. @click="handleReset"
  133. >
  134. 重置
  135. </el-button>
  136. <el-button
  137. type="success"
  138. :icon="useRenderIcon('ri/add-line')"
  139. @click="handleAdd"
  140. >
  141. 新增
  142. </el-button>
  143. </el-form-item>
  144. </el-form>
  145. <el-table
  146. v-loading="state.tableData.loading"
  147. :data="state.tableData.data"
  148. :height="state.tableData.height"
  149. border
  150. stripe
  151. >
  152. <template #empty>
  153. <el-empty description="暂无数据" />
  154. </template>
  155. <el-table-column
  156. v-for="col in state.tableData.columns"
  157. :key="col.prop"
  158. :prop="col.prop"
  159. :label="col.label"
  160. :width="col.width"
  161. show-overflow-tooltip
  162. >
  163. <template #default="{ row }">
  164. <template v-if="col.prop === 'status'">
  165. <ExtDLabel type="AdminUser.status" :model-value="row.status" />
  166. </template>
  167. <template v-else>
  168. {{ row[col.prop] }}
  169. </template>
  170. </template>
  171. </el-table-column>
  172. <el-table-column label="操作" width="150" fixed="right">
  173. <template #default="{ row }">
  174. <el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
  175. <el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
  176. </template>
  177. </el-table-column>
  178. </el-table>
  179. <div class="pagination-container">
  180. <el-pagination
  181. v-model:current-page="state.pageQuery.pageNum"
  182. v-model:page-size="state.pageQuery.pageSize"
  183. :total="state.pageQuery.total"
  184. :page-sizes="[10, 20, 50, 100]"
  185. layout="total, sizes, prev, pager, next, jumper"
  186. @size-change="handleSizeChange"
  187. @current-change="handleCurrentChange"
  188. />
  189. </div>
  190. </el-card>
  191. <AccountDialog ref="dialogRef" @refresh="loadData" />
  192. </div>
  193. </template>
  194. <style scoped lang="scss">
  195. .page-container {
  196. padding: 15px;
  197. }
  198. .search-form {
  199. margin-bottom: 15px;
  200. }
  201. .pagination-container {
  202. display: flex;
  203. justify-content: flex-end;
  204. margin-top: 15px;
  205. }
  206. </style>