index.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <div class="table-box">
  3. <ProTable
  4. ref="proTable"
  5. title="用户列表"
  6. highlight-current-row
  7. :columns="columns"
  8. :request-api="getUserList"
  9. :row-class-name="tableRowClassName"
  10. :span-method="objectSpanMethod"
  11. :show-summary="true"
  12. :summary-method="getSummaries"
  13. @row-click="rowClick"
  14. >
  15. <!-- 表格 header 按钮 -->
  16. <template #tableHeader="scope">
  17. <el-button type="primary" :icon="CirclePlus" @click="proTable?.element?.toggleAllSelection">全选 / 全不选</el-button>
  18. <el-button type="primary" :icon="Pointer" plain @click="setCurrent">选中第五行</el-button>
  19. <el-button type="danger" :icon="Delete" plain :disabled="!scope.isSelected" @click="batchDelete(scope.selectedListIds)">
  20. 批量删除用户
  21. </el-button>
  22. </template>
  23. <!-- Expand -->
  24. <template #expand="scope">
  25. {{ scope.row }}
  26. </template>
  27. <!-- 表格操作 -->
  28. <template #operation="scope">
  29. <el-button type="primary" link :icon="Refresh" @click="resetPass(scope.row)">重置密码</el-button>
  30. <el-button type="primary" link :icon="Delete" @click="deleteAccount(scope.row)">删除</el-button>
  31. </template>
  32. <template #append>
  33. <span style="color: var(--el-color-primary)">我是插入在表格最后的内容。若表格有合计行,该内容会位于合计行之上。</span>
  34. </template>
  35. </ProTable>
  36. </div>
  37. </template>
  38. <script setup lang="tsx" name="complexProTable">
  39. import { reactive, ref } from "vue";
  40. import { ElMessage } from "element-plus";
  41. import { User } from "@/api/interface";
  42. import { useHandleData } from "@/hooks/useHandleData";
  43. import ProTable from "@/components/ProTable/index.vue";
  44. import { CirclePlus, Pointer, Delete, Refresh } from "@element-plus/icons-vue";
  45. import type { TableColumnCtx } from "element-plus/es/components/table/src/table-column/defaults";
  46. import { ProTableInstance, ColumnProps, HeaderRenderScope } from "@/components/ProTable/interface";
  47. import { getUserList, deleteUser, resetUserPassWord, getUserStatus, getUserGender } from "@/api/modules/user";
  48. // ProTable 实例
  49. const proTable = ref<ProTableInstance>();
  50. // 自定义渲染表头(使用tsx语法)
  51. const headerRender = (scope: HeaderRenderScope<User.ResUserList>) => {
  52. return (
  53. <el-button type="primary" onClick={() => ElMessage.success("我是通过 tsx 语法渲染的表头")}>
  54. {scope.column.label}
  55. </el-button>
  56. );
  57. };
  58. // 表格配置项
  59. const columns = reactive<ColumnProps<User.ResUserList>[]>([
  60. { type: "selection", width: 80 },
  61. { type: "index", label: "#", width: 80 },
  62. { type: "expand", label: "Expand", width: 100 },
  63. {
  64. prop: "base",
  65. label: "基本信息",
  66. headerRender,
  67. _children: [
  68. { prop: "username", label: "用户姓名", width: 110 },
  69. { prop: "user.detail.age", label: "年龄", width: 100 },
  70. {
  71. prop: "gender",
  72. label: "性别",
  73. width: 100,
  74. enum: getUserGender,
  75. fieldNames: { label: "genderLabel", value: "genderValue" }
  76. },
  77. {
  78. prop: "details",
  79. label: "详细资料",
  80. _children: [
  81. { prop: "idCard", label: "身份证号" },
  82. { prop: "email", label: "邮箱" },
  83. { prop: "address", label: "居住地址" }
  84. ]
  85. }
  86. ]
  87. },
  88. {
  89. prop: "status",
  90. label: "用户状态",
  91. tag: true,
  92. enum: getUserStatus,
  93. fieldNames: { label: "userLabel", value: "userStatus" }
  94. },
  95. { prop: "createTime", label: "创建时间", width: 200 },
  96. { prop: "operation", label: "操作", fixed: "right", width: 230 }
  97. ]);
  98. // 选择行
  99. const setCurrent = () => {
  100. proTable.value?.element?.setCurrentRow(proTable.value?.tableData[4]);
  101. proTable.value?.element?.toggleRowSelection(proTable.value?.tableData[4], true);
  102. };
  103. // 表尾合计行(自行根据条件计算)
  104. interface SummaryMethodProps<T = User.ResUserList> {
  105. columns: TableColumnCtx<T>[];
  106. data: T[];
  107. }
  108. const getSummaries = (param: SummaryMethodProps) => {
  109. const { columns } = param;
  110. const sums: string[] = [];
  111. columns.forEach((column, index) => {
  112. if (index === 0) return (sums[index] = "合计");
  113. else sums[index] = "N/A";
  114. });
  115. return sums;
  116. };
  117. // 列合并
  118. interface SpanMethodProps {
  119. row: User.ResUserList;
  120. column: TableColumnCtx<User.ResUserList>;
  121. rowIndex: number;
  122. columnIndex: number;
  123. }
  124. const objectSpanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
  125. if (columnIndex === 3) {
  126. if (rowIndex % 2 === 0) return { rowspan: 2, colspan: 1 };
  127. else return { rowspan: 0, colspan: 0 };
  128. }
  129. };
  130. // 设置列样式
  131. const tableRowClassName = ({ rowIndex }: { row: User.ResUserList; rowIndex: number }) => {
  132. if (rowIndex === 2) return "warning-row";
  133. if (rowIndex === 6) return "success-row";
  134. return "";
  135. };
  136. // 单击行
  137. const rowClick = (row: User.ResUserList, column: TableColumnCtx<User.ResUserList>) => {
  138. if (column.property == "radio" || column.property == "operation") return;
  139. ElMessage.success("当前行被点击了!");
  140. };
  141. // 删除用户信息
  142. const deleteAccount = async (params: User.ResUserList) => {
  143. await useHandleData(deleteUser, { id: [params.id] }, `删除【${params.username}】用户`);
  144. proTable.value?.getTableList();
  145. };
  146. // 批量删除用户信息
  147. const batchDelete = async (id: string[]) => {
  148. await useHandleData(deleteUser, { id }, "删除所选用户信息");
  149. proTable.value?.clearSelection();
  150. proTable.value?.getTableList();
  151. };
  152. // 重置用户密码
  153. const resetPass = async (params: User.ResUserList) => {
  154. await useHandleData(resetUserPassWord, { id: params.id }, `重置【${params.username}】用户密码`);
  155. proTable.value?.getTableList();
  156. };
  157. </script>
  158. <style lang="scss">
  159. .el-table .warning-row,
  160. .el-table .warning-row .el-table-fixed-column--right,
  161. .el-table .warning-row .el-table-fixed-column--left {
  162. background-color: var(--el-color-warning-light-9);
  163. }
  164. .el-table .success-row,
  165. .el-table .success-row .el-table-fixed-column--right,
  166. .el-table .success-row .el-table-fixed-column--left {
  167. background-color: var(--el-color-success-light-9);
  168. }
  169. </style>