index.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <template>
  2. <ele-page flex-table>
  3. <page-search @search="reload" />
  4. <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns">
  5. <template #toolbar>
  6. <el-button
  7. type="success"
  8. plain
  9. v-permission="'customer:list:export'"
  10. @click="handleExportExcel"
  11. :icon="DownloadOutlined"
  12. >
  13. 导出EXCEL
  14. </el-button>
  15. </template>
  16. <template #nickName="{ row }">
  17. <div class="flex flex-col items-center">
  18. <el-avatar :src="row.imgPath" />
  19. <ele-text class="mt-1">{{ row.nickName }}</ele-text>
  20. </div>
  21. </template>
  22. <template #status="{ row }">
  23. <dict-data
  24. code="user_info_status"
  25. type="tag"
  26. :model-value="row.status"
  27. />
  28. </template>
  29. <template #action="{ row }">
  30. <div>
  31. <el-button
  32. type="success"
  33. link
  34. v-permission="'customer:list:detail'"
  35. @click="handleDetail(row)"
  36. >
  37. [用户详情]
  38. </el-button>
  39. <el-button
  40. type="warning"
  41. link
  42. v-permission="'customer:list:userTag'"
  43. @click="handleBindTag(row)"
  44. >
  45. [用户标签]
  46. </el-button>
  47. <el-button
  48. type="warning"
  49. link
  50. v-permission="'customer:list:accountDetail'"
  51. @click="handleDetail(row, 'accountChange')"
  52. >
  53. [账户明细]
  54. </el-button>
  55. <el-button
  56. type="danger"
  57. link
  58. v-permission="'customer:list:reduceUserAccount'"
  59. @click="handleReduceAccount(row)"
  60. >
  61. [扣减余额]
  62. </el-button>
  63. <el-button
  64. type="success"
  65. link
  66. v-permission="'customer:list:blacklistHistory'"
  67. @click="handleBlacklistHistory(row)"
  68. >
  69. [拉黑历史]
  70. </el-button>
  71. <el-button
  72. v-if="row.status == 1"
  73. type="danger"
  74. link
  75. v-permission="'customer:list:blacklist'"
  76. @click="handleAddBlacklist(row)"
  77. >
  78. [加入黑名单]
  79. </el-button>
  80. <el-button
  81. v-else
  82. type="danger"
  83. link
  84. v-permission="'customer:list:blacklist'"
  85. @click="handleRemoveBlacklist(row)"
  86. >
  87. [移除黑名单]
  88. </el-button>
  89. <el-button
  90. v-if="row.status != 3"
  91. type="danger"
  92. link
  93. v-permission="'customer:list:cancel'"
  94. @click="handleCancel(row)"
  95. >
  96. [注销]
  97. </el-button>
  98. </div>
  99. </template>
  100. </common-table>
  101. <blacklist-history ref="historyRef" />
  102. <customer-detail ref="detailRef" />
  103. <user-bind-tag ref="tagRef" />
  104. </ele-page>
  105. </template>
  106. <script setup>
  107. import { ref, reactive } from 'vue';
  108. import { ElMessageBox } from 'element-plus/es';
  109. import { EleMessage } from 'ele-admin-plus/es';
  110. import { DownloadOutlined } from '@/components/icons';
  111. import CommonTable from '@/components/CommonPage/CommonTable.vue';
  112. import pageSearch from './components/page-search.vue';
  113. import blacklistHistory from '@/views/customer/list/components/blacklist-history.vue';
  114. import customerDetail from '@/views/customer/list/components/customer-detail.vue';
  115. import userBindTag from '@/views/recycleOrder/components/user-bind-tag.vue';
  116. import request from '@/utils/request';
  117. defineOptions({ name: 'CustomerList' });
  118. /** 表格列配置 */
  119. const columns = ref([
  120. {
  121. label: '用户昵称',
  122. prop: 'nickName',
  123. align: 'center',
  124. slot: 'nickName'
  125. },
  126. { label: '用户ID', prop: 'id', align: 'center' },
  127. { label: '用户OpenId', prop: 'openId', align: 'center' },
  128. { label: '手机号', prop: 'mobile', align: 'center' },
  129. { label: '用户类型', prop: 'platName', align: 'center' },
  130. { label: '用户标签', prop: 'userTagStr', align: 'center' },
  131. { label: '状态', prop: 'statusName', align: 'center', slot: 'status' },
  132. { label: '创建时间', prop: 'createTime', align: 'center', width: 160 },
  133. {
  134. columnKey: 'action',
  135. label: '操作',
  136. width: 200,
  137. align: 'center',
  138. slot: 'action'
  139. }
  140. ]);
  141. /** 页面组件实例 */
  142. const pageRef = ref(null);
  143. const pageConfig = reactive({
  144. pageUrl: '/user/userInfo/pagelist',
  145. exportUrl: '/user/userInfo/export',
  146. fileName: '客户列表',
  147. cacheKey: 'customerListTable'
  148. });
  149. //刷新表格
  150. function reload(where) {
  151. pageRef.value?.reload(where);
  152. }
  153. //批量删除
  154. function handleBatchDelete(row) {
  155. let selections = row ? [row] : pageRef.value?.getSelections();
  156. let ids = selections.map((item) => item.id).join(',');
  157. let url = `/baseinfo/schoolInfo/removeById/${ids}`;
  158. pageRef.value?.operatBatch({
  159. title: '确认删除?',
  160. method: 'post',
  161. url,
  162. row
  163. });
  164. }
  165. //导出excel
  166. function handleExportExcel() {
  167. pageRef.value?.exportData('用户列表');
  168. }
  169. //加入黑名单
  170. function handleAddBlacklist(row) {
  171. ElMessageBox.confirm('确认加入黑名单?', '提示', {
  172. confirmButtonText: '确定',
  173. canceledButtonText: '关闭',
  174. showInput: true,
  175. inputPlaceholder: '请输入拉黑原因'
  176. }).then(({ value }) => {
  177. request
  178. .post('/user/black/add', { userId: row.id, reason: value })
  179. .then((res) => {
  180. if (res.data.code == 200) {
  181. ElMessage({
  182. type: 'success',
  183. message: '操作成功'
  184. });
  185. reload();
  186. } else {
  187. ElMessage({
  188. type: 'error',
  189. message: res.data.msg
  190. });
  191. }
  192. });
  193. });
  194. }
  195. //移除黑名单
  196. function handleRemoveBlacklist(row) {
  197. pageRef.value?.messageBoxConfirm({
  198. message: '确认移出黑名单?',
  199. fetch: () => request.post('/user/black/delete', { userId: row.id })
  200. });
  201. }
  202. //扣减余额
  203. function handleReduceAccount(row) {
  204. ElMessageBox.prompt(
  205. `请输入用户"${row.nickName}"(ID: ${row.id})的扣减金额`,
  206. '扣减余额',
  207. {
  208. confirmButtonText: '确定',
  209. cancelButtonText: '取消',
  210. inputPlaceholder: '请输入扣减金额',
  211. inputPattern: /^(?!0+(\.0+)?$)([1-9]\d*|0)(\.\d{1,2})?$/,
  212. inputErrorMessage: '金额必须大于0,且最多两位小数(例如:1.23 或 0.5)',
  213. draggable: true
  214. }
  215. ).then(({ value }) => {
  216. request
  217. .post('/user/userAccountInfo/reduceUserAccount', {
  218. userId: row.id,
  219. reduceMoney: Number(value).toFixed(2)
  220. })
  221. .then((res) => {
  222. if (res.data.code == 200) {
  223. EleMessage.success('操作成功');
  224. reload();
  225. } else {
  226. EleMessage.error(res.data.msg);
  227. }
  228. });
  229. });
  230. }
  231. //编辑页面
  232. const editRef = ref(null);
  233. function handleUpdate(row) {
  234. editRef.value?.handleOpen(row);
  235. }
  236. //详情页面
  237. const detailRef = ref(null);
  238. function handleDetail(row, type) {
  239. detailRef.value?.handleOpen(row, type);
  240. }
  241. //拉黑历史
  242. const historyRef = ref(null);
  243. function handleBlacklistHistory(row) {
  244. historyRef.value?.handleOpen(row);
  245. }
  246. //用户标签
  247. const tagRef = ref(null);
  248. function handleBindTag(row) {
  249. row.userId = row.id;
  250. tagRef.value?.handleOpen(row);
  251. }
  252. //注销用户
  253. function handleCancel(row) {
  254. ElMessageBox.confirm(
  255. `确认注销用户"${row.nickName}"?注销后不可恢复!`,
  256. '提示',
  257. {
  258. confirmButtonText: '确定',
  259. cancelButtonText: '取消',
  260. type: 'warning'
  261. }
  262. ).then(() => {
  263. request.post(`/user/userInfo/cancel/${row.id}`).then((res) => {
  264. if (res.data.code == 200) {
  265. EleMessage.success('操作成功');
  266. reload();
  267. } else {
  268. EleMessage.error(res.data.msg);
  269. }
  270. });
  271. });
  272. }
  273. </script>