index.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <el-container>
  3. <el-header class="sa-header">
  4. <div class="sa-title sa-flex sa-row-between">
  5. <div class="label sa-flex">
  6. <span class="left">会员管理</span>
  7. <search-condition
  8. :conditionLabel="filterParams.conditionLabel"
  9. @deleteFilter="deleteFilter"
  10. ></search-condition>
  11. </div>
  12. <div>
  13. <el-button
  14. v-auth="'user.admin.user.list'"
  15. class="sa-button-refresh"
  16. icon="RefreshRight"
  17. @click="getData()"
  18. ></el-button>
  19. <el-button class="sa-button-refresh" icon="Search" @click="openFilter"></el-button>
  20. </div>
  21. </div>
  22. </el-header>
  23. <el-main class="sa-p-0" v-loading="table.loading">
  24. <el-table class="sa-table" height="100%" :data="table.data" stripe @sort-change="fieldFilter">
  25. <template #empty>
  26. <sa-empty />
  27. </template>
  28. <el-table-column sortable="custom" prop="id" label="ID" min-width="80" />
  29. <el-table-column label="用户信息" min-width="150">
  30. <template #default="scope">
  31. <sa-user-profile :user="scope.row" :id="scope.row.id" />
  32. </template>
  33. </el-table-column>
  34. <el-table-column prop="username" label="用户名" min-width="120" align="center" />
  35. <el-table-column prop="mobile" label="手机号" min-width="120" align="center" />
  36. <el-table-column
  37. sortable="custom"
  38. prop="commission"
  39. label="佣金"
  40. min-width="110"
  41. align="center"
  42. />
  43. <el-table-column
  44. sortable="custom"
  45. prop="total_consume"
  46. label="总消费"
  47. min-width="110"
  48. align="center"
  49. />
  50. <el-table-column
  51. sortable="custom"
  52. prop="score"
  53. label="积分"
  54. min-width="110"
  55. align="center"
  56. />
  57. <el-table-column
  58. sortable="custom"
  59. prop="money"
  60. label="余额"
  61. min-width="110"
  62. align="center"
  63. />
  64. <el-table-column
  65. sortable="custom"
  66. prop="create_time"
  67. label="注册时间"
  68. min-width="172"
  69. align="center"
  70. />
  71. <el-table-column
  72. sortable="custom"
  73. prop="login_time"
  74. label="上次登录"
  75. min-width="172"
  76. align="center"
  77. />
  78. <el-table-column label="操作" min-width="120" fixed="right">
  79. <template #default="scope">
  80. <el-button
  81. v-auth="'user.admin.user.detail'"
  82. class="is-link"
  83. type="primary"
  84. @click="onDetail(scope.row.id)"
  85. >查看</el-button
  86. >
  87. <el-popconfirm
  88. width="fit-content"
  89. confirm-button-text="确认"
  90. cancel-button-text="取消"
  91. title="确认删除这条记录?"
  92. @confirm="onDelete(scope.row.id)"
  93. >
  94. <template #reference>
  95. <el-button v-auth="'user.admin.user.delete'" class="is-link" type="danger">
  96. 删除
  97. </el-button>
  98. </template>
  99. </el-popconfirm>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. </el-main>
  104. <sa-view-bar>
  105. <template #right>
  106. <sa-pagination :pageData="pageData" @updateFn="getData" />
  107. </template>
  108. </sa-view-bar>
  109. </el-container>
  110. </template>
  111. <script>
  112. export default {
  113. name: 'user.admin',
  114. };
  115. </script>
  116. <script setup>
  117. import { onMounted, reactive } from 'vue';
  118. import userApi from '@/app/user/api';
  119. import { usePagination, useModal } from '@/sheep/hooks';
  120. import { useSearch } from '@/sheep/components/sa-table/sa-search/useSearch';
  121. import { composeFilter } from '@/sheep/utils';
  122. import UserDetail from './detail.vue';
  123. import { cloneDeep } from 'lodash';
  124. const filterParams = reactive({
  125. tools: {
  126. user: {
  127. type: 'tinputprepend',
  128. placeholder: '请输入查询内容',
  129. field: 'user',
  130. user: {
  131. field: 'id',
  132. value: '',
  133. },
  134. options: [
  135. {
  136. label: '用户ID',
  137. value: 'id',
  138. },
  139. {
  140. label: '用户名',
  141. value: 'username',
  142. },
  143. {
  144. label: '昵称',
  145. value: 'nickname',
  146. },
  147. {
  148. label: '手机号',
  149. value: 'mobile',
  150. },
  151. {
  152. label: '邮箱',
  153. value: 'email',
  154. },
  155. ],
  156. },
  157. create_time: {
  158. type: 'tdatetimerange',
  159. label: '注册时间',
  160. field: 'create_time',
  161. value: [],
  162. },
  163. login_time: {
  164. type: 'tdatetimerange',
  165. label: '上次登录',
  166. field: 'login_time',
  167. value: [],
  168. },
  169. },
  170. data: {
  171. user: { field: 'id', value: '' },
  172. create_time: [],
  173. login_time: [],
  174. },
  175. conditionLabel: {},
  176. });
  177. const { openFilter, deleteFilter } = useSearch({ filterParams, getData });
  178. const table = reactive({
  179. loading: false,
  180. data: [],
  181. order: '',
  182. sort: '',
  183. });
  184. const { pageData } = usePagination();
  185. async function getData(page) {
  186. table.loading = true;
  187. if (page) pageData.page = page;
  188. let tempSearch = cloneDeep(filterParams.data);
  189. let search = composeFilter(tempSearch, {
  190. username: 'like',
  191. nickname: 'like',
  192. mobile: 'like',
  193. email: 'like',
  194. create_time: 'range',
  195. login_time: 'range',
  196. });
  197. const { error, data } = await userApi.list({
  198. page: pageData.page,
  199. list_rows: pageData.list_rows,
  200. ...search,
  201. order: table.order,
  202. sort: table.sort,
  203. });
  204. if (error === 0) {
  205. table.data = data.data;
  206. pageData.page = data.current_page;
  207. pageData.list_rows = data.per_page;
  208. pageData.total = data.total;
  209. }
  210. table.loading = false;
  211. }
  212. function fieldFilter({ prop, order }) {
  213. table.order = order == 'ascending' ? 'asc' : 'desc';
  214. table.sort = prop;
  215. getData();
  216. }
  217. function onDetail(id) {
  218. useModal(UserDetail, {
  219. title: '会员详情',
  220. id,
  221. });
  222. }
  223. async function onDelete(id) {
  224. const { error } = await userApi.delete(id);
  225. error == 0 && getData();
  226. }
  227. onMounted(() => {
  228. getData();
  229. });
  230. </script>