riskLogsList.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <template>
  2. <div class="layout-container">
  3. <!-- 菜单栏 -->
  4. <From :form-items="dynamicFormItems" @formSubmitted="handleFormSubmitted" @formReset="handleFormReset" />
  5. <!-- 表格 -->
  6. <div class="layout-container">
  7. <Table @getTableData="changeTableData" v-model:page="page" ref="table" :data="tableData"
  8. @selection-change="handleSelectionChange">
  9. <el-table-column prop="appId" label="应用ID" width="150" />
  10. <el-table-column prop="appName" label="应用名称" width="150" />
  11. <el-table-column prop="nickName" label="用户昵称" width="120" />
  12. <el-table-column prop="userId" label="用户ID" width="120" />
  13. <el-table-column prop="userStatus" label="用户状态" width="90">
  14. <template #default="scope">
  15. {{ getDictionaryName('user_status',scope.row.userStatus) }}
  16. </template>
  17. </el-table-column>
  18. <el-table-column prop="bannedLimit" label="风控期限" width="90">
  19. <template #default="scope">
  20. {{ scope.row.bannedLimit }}天
  21. </template>
  22. </el-table-column>
  23. <el-table-column prop="bannedReason" label="封禁原因" width="260" />
  24. <el-table-column prop="bannedTime" label="封禁时间" width="160">
  25. <template #default="scope">
  26. {{ convertUTCToBeijing(scope.row.bannedTime) }}
  27. </template>
  28. </el-table-column>
  29. <el-table-column prop="bannedType" label="封禁类型" width="90">
  30. <template #default="scope">
  31. {{ scope.row.bannedType === 1 ? '渠道' : '平台' }}
  32. </template>
  33. </el-table-column>
  34. <el-table-column prop="channelId" label="渠道商ID" width="110" />
  35. <el-table-column prop="phoneModel" label="手机型号" width="110" />
  36. <el-table-column prop="platformId" label="平台ID" width="150" />
  37. <el-table-column prop="communicationOperator" label="IP运营商" width="120" />
  38. <el-table-column prop="ipAddr" label="IP归属地" width="200" />
  39. <el-table-column prop="lastLoginIp" label="最新登录IP" width="150" />
  40. <el-table-column prop="lastLoginTime" label="最新登录时间" width="160">
  41. <template #default="scope">
  42. {{ convertUTCToBeijing(scope.row.lastLoginTime) }}
  43. </template>
  44. </el-table-column>
  45. <el-table-column prop="operatorName" label="操作人" width="90" />
  46. <el-table-column prop="registryTime" label="注册时间" width="160">
  47. <template #default="scope">
  48. {{ convertUTCToBeijing(scope.row.registryTime) }}
  49. </template>
  50. </el-table-column>
  51. </Table>
  52. </div>
  53. <!-- 操作弹窗 -->
  54. <Layer :layer="layer" @confirm="submit(ruleForm)" @close="layer.show = false">
  55. <el-form :model="formEdit" :rules="rules" ref="ruleForm" label-width="120px" style="margin-right:30px;">
  56. <el-form-item label="解封原因:" required prop="reason">
  57. <el-input v-model="formEdit.reason" placeholder="请输入封禁原因" clearable />
  58. </el-form-item>
  59. </el-form>
  60. </Layer>
  61. </div>
  62. </template>
  63. <script setup>
  64. import { onBeforeMount, ref, reactive } from "vue";
  65. import From from "@/components/from/index.vue";
  66. import Table from "@/components/table/index.vue";
  67. import Layer from '@/components/layer/index.vue'
  68. import Card from './components/card/index.vue'
  69. import { ElMessage } from 'element-plus'
  70. import { getUserList, getStaticList, riskBannedUser, riskLockUser } from '@/api/userModule.js'
  71. import { riskBannedList, riskChangeUserStatus } from '@/api/riskModule.js'
  72. import { convertUTCToBeijing } from '@/utils/index.js'
  73. import { useGetDictList } from '@/hooks/useGetDictList.js'
  74. import { useStore } from 'vuex'
  75. const store = useStore()
  76. const { dictData, loadDictData, getOptions, getDictionaryName } = useGetDictList();
  77. const form = ref(null);
  78. const tableData = ref([]);
  79. // 分页参数, 供table使用
  80. const page = reactive({
  81. pageNum: 1,
  82. pageSize: 20,
  83. total: 0,
  84. });
  85. const formSearch = ref({
  86. userId: null,//用户ID
  87. appId: null,// 应用ID
  88. bannedReason: null, //封禁原因
  89. bannedTimeBegin: null, //封禁开始时间
  90. bannedTimeEnd: null, //封禁结束时间
  91. channelId: null,// 渠道商ID
  92. channelOrigin: null, //渠道来源
  93. channelType: null,//渠道类型
  94. limit: 20,// 当前页数量(查询量)
  95. page: 1,// 当前页码
  96. });
  97. const dynamicFormItems = ref([])
  98. onBeforeMount(() => {
  99. settingData()
  100. getList();
  101. });
  102. // 获取缓存数据设置筛选数据
  103. const settingData = () => {
  104. loadDictData().then(() => {
  105. dynamicFormItems.value = [
  106. {
  107. label: '用户ID',
  108. prop: 'userId',
  109. type: 'input',
  110. needEnterEvent: true
  111. },
  112. {
  113. label: '应用ID',
  114. prop: 'appId',
  115. type: 'input',
  116. needEnterEvent: true
  117. },
  118. {
  119. label: '封禁原因',
  120. prop: 'bannedReason',
  121. type: 'input',
  122. needEnterEvent: true
  123. },
  124. {
  125. label: '渠道来源',
  126. prop: 'channelOrigin',
  127. type: 'select',
  128. options: getOptions('channel_origin'),
  129. },
  130. { label: '封禁时间', prop: 'bannedTime', type: 'daterange' },
  131. ]
  132. })
  133. }
  134. // 分页数据
  135. const getList = async () => {
  136. let res = await riskBannedList({ ...formSearch.value });
  137. tableData.value = res.data;
  138. page.total = res.pageMeta.total;
  139. };
  140. const changeTableData = (type) => {
  141. formSearch.value.page = type ? 1 : page.pageNum;
  142. formSearch.value.limit = page.pageSize;
  143. // 分页切换
  144. getList();
  145. };
  146. // 搜索
  147. const handleFormSubmitted = (formData) => {
  148. // console.log("接收到子组件传递的数据", formData.appId);
  149. formSearch.value.page = page.pageNum;
  150. formSearch.value.limit = page.pageSize;
  151. formSearch.value.appId = formData.appId;
  152. formSearch.value.userId = formData.userId;
  153. formSearch.value.bannedReason = formData.bannedReason;
  154. formSearch.value.channelId = formData.channelId;
  155. formSearch.value.channelOrigin = formData.channelOrigin;
  156. formSearch.value.channelType = formData.channelType;
  157. // 封禁时间
  158. if (formData.bannedTime) {
  159. formSearch.value.bannedTimeBegin = convertUTCToBeijing(formData.bannedTime[0], false);
  160. formSearch.value.bannedTimeEnd = convertUTCToBeijing(formData.bannedTime[1], false);
  161. }else {
  162. formSearch.value.bannedTimeBegin = null
  163. formSearch.value.bannedTimeEnd = null
  164. }
  165. getList();
  166. };
  167. // 表单重置
  168. const handleFormReset = () => {
  169. formSearch.value = {
  170. userId: null,//用户ID
  171. appId: null,// 应用ID
  172. bannedReason: null, //封禁原因
  173. bannedTimeBegin: null, //封禁开始时间
  174. bannedTimeEnd: null, //封禁结束时间
  175. channelId: null,// 渠道商ID
  176. channelOrigin: null, //渠道来源
  177. channelType: null,//渠道类型
  178. limit: 20,// 当前页数量(查询量)
  179. page: 1,// 当前页码
  180. };
  181. page.pageNum = 1
  182. page.pageSize = 20
  183. page.total = 0
  184. getList();
  185. };
  186. // 选择监听器
  187. const handleSelectionChange = (val) => {
  188. context.emit("selection-change", val)
  189. }
  190. // 弹窗
  191. const layer = ref({
  192. show: false,
  193. title: "解封用户",
  194. showButton: true,
  195. width: '300px'
  196. })
  197. const formEdit = ref({
  198. bannedType: '',//封禁类型 1-渠道 2-平台
  199. operator: '',//操作人
  200. operatorName: '',//操作人名称
  201. reason: '',//封禁原因
  202. userId: '', //用户ID
  203. userStatus: '', //用户状态
  204. })
  205. const editUserType = (row) => {
  206. ruleForm.value?.resetFields()
  207. layer.value.show = true
  208. layer.value.title = `解封用户${row.nickName}`
  209. formEdit.value.bannedType = row.channelType
  210. formEdit.value.operator = store.state.user.info.loginName
  211. formEdit.value.operatorName = store.state.user.info.nickName
  212. formEdit.value.userId = row.userId
  213. formEdit.value.userStatus = 1 //正常
  214. }
  215. const ruleForm = ref(null);
  216. const rules = reactive({
  217. reason: [
  218. {
  219. required: true,
  220. message: "请输入解封原因",
  221. trigger: ["blur"],
  222. },
  223. ],
  224. });
  225. const submit = async (formEl) => {
  226. await formEl.validate(async (valid, fields) => {
  227. if (valid) {
  228. // 提交内容
  229. riskChangeUserStatus({ ...formEdit.value }).then((res) => {
  230. ElMessage.success('用户解封成功')
  231. getList();
  232. })
  233. } else {
  234. console.log("error submit!", fields);
  235. }
  236. })
  237. layer.value.show = false
  238. }
  239. </script>
  240. <style scoped lang="scss">
  241. .layout-container {
  242. .card {
  243. .title {
  244. margin-bottom: 10px;
  245. font-weight: 600;
  246. }
  247. display: flex;
  248. flex-direction: column;
  249. align-items: start;
  250. width: calc(100% - 60px);
  251. margin: 30px 30px 0;
  252. }
  253. .button {
  254. display: flex;
  255. flex-direction: column;
  256. .button-item {
  257. margin: 4px;
  258. }
  259. }
  260. }
  261. </style>