mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 00:57:13 +08:00 
			
		
		
		
	重构:重构在线用户前端代码
This commit is contained in:
		| @@ -1,5 +1,7 @@ | |||||||
| import axios from 'axios'; | import axios from "axios"; | ||||||
| import qs from 'query-string'; | import qs from "query-string"; | ||||||
|  |  | ||||||
|  | const BASE_URL = "/monitor/online/user"; | ||||||
|  |  | ||||||
| export interface OnlineUserRecord { | export interface OnlineUserRecord { | ||||||
|   token: string; |   token: string; | ||||||
| @@ -11,25 +13,26 @@ export interface OnlineUserRecord { | |||||||
|   loginTime: string; |   loginTime: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface OnlineUserParams extends Partial<OnlineUserRecord> { | export interface OnlineUserParam extends Partial<OnlineUserRecord> { | ||||||
|   page: number; |   page: number; | ||||||
|   size: number; |   size: number; | ||||||
|   sort: Array<string>; |   sort: Array<string>; | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface OnlineUserListRes { | export interface OnlineUserListRes { | ||||||
|   list: OnlineUserRecord[]; |   list: OnlineUserRecord[]; | ||||||
|   total: number; |   total: number; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function getOnlineUserList(params: OnlineUserParams) { | export function listOnlineUser(params: OnlineUserParam) { | ||||||
|   return axios.get<OnlineUserListRes>('/monitor/online/user', { |   return axios.get<OnlineUserListRes>(BASE_URL, { | ||||||
|     params, |     params, | ||||||
|     paramsSerializer: (obj) => { |     paramsSerializer: (obj) => { | ||||||
|       return qs.stringify(obj); |       return qs.stringify(obj); | ||||||
|     }, |     } | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function kickout(token: string) { | export function kickout(token: string) { | ||||||
|   return axios.delete(`/monitor/online/user/${token}`); |   return axios.delete(`${BASE_URL}/${token}`); | ||||||
| } | } | ||||||
| @@ -1,11 +1,10 @@ | |||||||
| <template> | <template> | ||||||
|   <a-range-picker |   <a-range-picker | ||||||
|     style="width: 100%" |     :placeholder="placeholder" | ||||||
|     :shortcuts="shortcuts" |  | ||||||
|     shortcuts-position="left" |  | ||||||
|     :format="format" |     :format="format" | ||||||
|     :show-time="showTime" |     :show-time="showTime" | ||||||
|     :placeholder="placeholder" |     :shortcuts="shortcuts" | ||||||
|  |     shortcuts-position="left" | ||||||
|   /> |   /> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,65 +2,85 @@ | |||||||
|   <div class="container"> |   <div class="container"> | ||||||
|     <Breadcrumb :items="['menu.monitor', 'menu.online.user.list']" /> |     <Breadcrumb :items="['menu.monitor', 'menu.online.user.list']" /> | ||||||
|     <a-card class="general-card" :title="$t('menu.online.user.list')"> |     <a-card class="general-card" :title="$t('menu.online.user.list')"> | ||||||
|       <a-row style="margin-bottom: 15px"> |       <!-- 头部区域 --> | ||||||
|         <a-col :span="24"> |       <div class="head-container"> | ||||||
|           <a-form ref="queryFormRef" :model="queryFormData" layout="inline"> |         <!-- 搜索栏 --> | ||||||
|  |         <div class="query-container"> | ||||||
|  |           <a-form ref="queryRef" :model="queryParams" layout="inline"> | ||||||
|             <a-form-item field="nickname" hide-label> |             <a-form-item field="nickname" hide-label> | ||||||
|               <a-input |               <a-input | ||||||
|                 v-model="queryFormData.nickname" |                 v-model="queryParams.nickname" | ||||||
|                 placeholder="输入用户昵称搜索" |                 placeholder="输入用户昵称搜索" | ||||||
|                 allow-clear |                 allow-clear | ||||||
|                 style="width: 150px;" |                 style="width: 150px;" | ||||||
|                 @press-enter="toQuery" |                 @press-enter="handleQuery" | ||||||
|               /> |               /> | ||||||
|             </a-form-item> |             </a-form-item> | ||||||
|             <a-form-item field="loginTime" hide-label> |             <a-form-item field="loginTime" hide-label> | ||||||
|               <date-range-picker v-model="queryFormData.loginTime" /> |               <date-range-picker v-model="queryParams.loginTime" /> | ||||||
|  |             </a-form-item> | ||||||
|  |             <a-form-item hide-label> | ||||||
|  |               <a-space> | ||||||
|  |                 <a-button type="primary" @click="handleQuery"> | ||||||
|  |                   <template #icon><icon-search /></template>查询 | ||||||
|  |                 </a-button> | ||||||
|  |                 <a-button @click="resetQuery"> | ||||||
|  |                   <template #icon><icon-refresh /></template>重置 | ||||||
|  |                 </a-button> | ||||||
|  |               </a-space> | ||||||
|             </a-form-item> |             </a-form-item> | ||||||
|             <a-button type="primary" @click="toQuery"> |  | ||||||
|               <template #icon> |  | ||||||
|                 <icon-search /> |  | ||||||
|               </template> |  | ||||||
|               查询 |  | ||||||
|             </a-button> |  | ||||||
|             <a-button @click="resetQuery"> |  | ||||||
|               <template #icon> |  | ||||||
|                 <icon-refresh /> |  | ||||||
|               </template> |  | ||||||
|               重置 |  | ||||||
|             </a-button> |  | ||||||
|           </a-form> |           </a-form> | ||||||
|         </a-col> |         </div> | ||||||
|       </a-row> |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 列表区域 --> | ||||||
|       <a-table |       <a-table | ||||||
|         :columns="columns" |         ref="tableRef" | ||||||
|         :data="renderData" |         row-key="token" | ||||||
|         :pagination="paginationProps" |         :loading="loading" | ||||||
|         row-key="logId" |         :pagination="{ | ||||||
|  |           showTotal: true, | ||||||
|  |           showPageSize: true, | ||||||
|  |           total: total, | ||||||
|  |           current: queryParams.page, | ||||||
|  |         }" | ||||||
|  |         :data="onlineUserList" | ||||||
|         :bordered="false" |         :bordered="false" | ||||||
|         :stripe="true" |         :stripe="true" | ||||||
|         :loading="loading" |  | ||||||
|         size="large" |         size="large" | ||||||
|         @page-change="handlePageChange" |         @page-change="handlePageChange" | ||||||
|         @page-size-change="handlePageSizeChange" |         @page-size-change="handlePageSizeChange" | ||||||
|       > |       > | ||||||
|         <template #index="{ rowIndex }"> |         <template #columns> | ||||||
|           {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} |           <a-table-column title="序号"> | ||||||
|         </template> |             <template #cell="{ rowIndex }"> | ||||||
|         <template #nickname="{ record }"> |               {{ rowIndex + 1 + (queryParams.page - 1) * queryParams.size }} | ||||||
|           {{ record.nickname }}({{record.username}}) |             </template> | ||||||
|         </template> |           </a-table-column> | ||||||
|         <template #operations="{ record }"> |           <a-table-column title="用户昵称"> | ||||||
|           <a-button |             <template #cell="{ record }"> | ||||||
|             v-permission="['admin']" |               {{ record.nickname }}({{record.username}}) | ||||||
|             type="text" |             </template> | ||||||
|             size="small" |           </a-table-column> | ||||||
|             :title="currentToken === record.token ? '不能强退当前登录' : ''" |           <a-table-column title="登录 IP" data-index="clientIp" /> | ||||||
|             :disabled="currentToken === record.token" |           <a-table-column title="登录地点" data-index="location" /> | ||||||
|             @click="handleClick(record.token)" |           <a-table-column title="浏览器" data-index="browser" /> | ||||||
|           > |           <a-table-column title="登录时间" data-index="loginTime" /> | ||||||
|             强退 |           <a-table-column title="操作" align="center"> | ||||||
|           </a-button> |             <template #cell="{ record }"> | ||||||
|  |               <a-popconfirm content="确定要强退该用户吗?" type="warning" @ok="handleKickout(record.token)"> | ||||||
|  |                 <a-button | ||||||
|  |                   v-permission="['admin']" | ||||||
|  |                   type="text" | ||||||
|  |                   size="small" | ||||||
|  |                   :disabled="currentToken === record.token" | ||||||
|  |                   :title="currentToken === record.token ? '不能强退当前登录用户' : ''" | ||||||
|  |                 > | ||||||
|  |                   <template #icon><icon-delete /></template>强退 | ||||||
|  |                 </a-button> | ||||||
|  |               </a-popconfirm> | ||||||
|  |             </template> | ||||||
|  |           </a-table-column> | ||||||
|         </template> |         </template> | ||||||
|       </a-table> |       </a-table> | ||||||
|     </a-card> |     </a-card> | ||||||
| @@ -68,116 +88,94 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
|   import { computed, ref, reactive } from 'vue'; |   import { getCurrentInstance, ref, toRefs, reactive } from 'vue'; | ||||||
|   import useLoading from '@/hooks/loading'; |   import { | ||||||
|   import { Message } from '@arco-design/web-vue'; |     listOnlineUser, | ||||||
|   import { getOnlineUserList, OnlineUserRecord, OnlineUserParams, kickout } from '@/api/monitor/online'; |     OnlineUserRecord, | ||||||
|   import { Pagination } from '@/types/global'; |     OnlineUserParam, | ||||||
|   import { PaginationProps } from '@arco-design/web-vue'; |     kickout | ||||||
|   import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; |   } from '@/api/monitor/online'; | ||||||
|   import { FormInstance } from '@arco-design/web-vue/es/form'; |  | ||||||
|   import { getToken } from '@/utils/auth'; |   import { getToken } from '@/utils/auth'; | ||||||
|  |  | ||||||
|   const { loading, setLoading } = useLoading(true); |   const { proxy } = getCurrentInstance() as any; | ||||||
|   const currentToken = computed(() => getToken()); |  | ||||||
|   const queryFormRef = ref<FormInstance>(); |  | ||||||
|   const queryFormData = ref({ |  | ||||||
|     nickname: '', |  | ||||||
|     loginTime: [], |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   // 查询 |   const onlineUserList = ref<OnlineUserRecord[]>([]); | ||||||
|   const toQuery = () => { |   const total = ref(0); | ||||||
|     fetchData({ |   const loading = ref(false); | ||||||
|       page: pagination.current, |   const currentToken = getToken(); | ||||||
|       size: pagination.pageSize, |  | ||||||
|  |   const data = reactive({ | ||||||
|  |     // 查询参数 | ||||||
|  |     queryParams: { | ||||||
|  |       nickname: undefined, | ||||||
|  |       loginTime: undefined, | ||||||
|  |       page: 1, | ||||||
|  |       size: 10, | ||||||
|       sort: ['createTime,desc'], |       sort: ['createTime,desc'], | ||||||
|       ...queryFormData.value, |     }, | ||||||
|     } as unknown as OnlineUserParams); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   // 重置 |  | ||||||
|   const resetQuery = async () => { |  | ||||||
|     await queryFormRef.value?.resetFields(); |  | ||||||
|     await fetchData(); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   const renderData = ref<OnlineUserRecord[]>([]); |  | ||||||
|   const basePagination: Pagination = { |  | ||||||
|     current: 1, |  | ||||||
|     pageSize: 10, |  | ||||||
|   }; |  | ||||||
|   const pagination = reactive({ |  | ||||||
|     ...basePagination, |  | ||||||
|   }); |   }); | ||||||
|   const paginationProps = computed((): PaginationProps => { |   const { queryParams } = toRefs(data); | ||||||
|     return { |  | ||||||
|       showTotal: true, |  | ||||||
|       showPageSize: true, |  | ||||||
|       total: pagination.total, |  | ||||||
|       current: pagination.current, |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
|   const columns = computed<TableColumnData[]>(() => [ |  | ||||||
|     { |  | ||||||
|       title: '序号', |  | ||||||
|       dataIndex: 'index', |  | ||||||
|       slotName: 'index', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '用户昵称', |  | ||||||
|       dataIndex: 'nickname', |  | ||||||
|       slotName: 'nickname', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '登录 IP', |  | ||||||
|       dataIndex: 'clientIp', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '登录地点', |  | ||||||
|       dataIndex: 'location', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '浏览器', |  | ||||||
|       dataIndex: 'browser', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '登录时间', |  | ||||||
|       dataIndex: 'loginTime', |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       title: '操作', |  | ||||||
|       slotName: 'operations', |  | ||||||
|       align: 'center', |  | ||||||
|     }, |  | ||||||
|   ]); |  | ||||||
|  |  | ||||||
|   // 分页查询列表 |   /** | ||||||
|   const fetchData = async ( |    * 查询列表 | ||||||
|     params: OnlineUserParams = { page: 1, size: 10, sort: ['createTime,desc'] } |    * | ||||||
|   ) => { |    * @param params 查询参数 | ||||||
|     setLoading(true); |    */ | ||||||
|     try { |   const getList = (params: OnlineUserParam = { ...queryParams.value }) => { | ||||||
|       const { data } = await getOnlineUserList(params); |     loading.value = true; | ||||||
|       renderData.value = data.list; |     listOnlineUser(params).then((res) => { | ||||||
|       pagination.current = params.page; |       onlineUserList.value = res.data.list; | ||||||
|       pagination.total = data.total; |       total.value = res.data.total; | ||||||
|     } finally { |       loading.value = false; | ||||||
|       setLoading(false); |     }); | ||||||
|     } |  | ||||||
|   }; |   }; | ||||||
|  |   getList(); | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 强退 | ||||||
|  |    * | ||||||
|  |    * @param token Token | ||||||
|  |    */ | ||||||
|  |   const handleKickout = (token: string) => { | ||||||
|  |     kickout(token).then((res) => { | ||||||
|  |       getList(); | ||||||
|  |       proxy.$message.success(res.msg); | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 查询 | ||||||
|  |    */ | ||||||
|  |   const handleQuery = () => { | ||||||
|  |     getList(); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 重置 | ||||||
|  |    */ | ||||||
|  |   const resetQuery = () => { | ||||||
|  |     proxy.$refs.queryRef.resetFields(); | ||||||
|  |     handleQuery(); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 切换页码 | ||||||
|  |    * | ||||||
|  |    * @param current 页码 | ||||||
|  |    */ | ||||||
|   const handlePageChange = (current: number) => { |   const handlePageChange = (current: number) => { | ||||||
|     fetchData({ page: current, size: pagination.pageSize, sort: ['createTime,desc'] }); |     queryParams.value.page = current; | ||||||
|  |     getList(); | ||||||
|   }; |   }; | ||||||
|   const handlePageSizeChange = (pageSize: number) => { |  | ||||||
|     fetchData({ page: pagination.current, size: pageSize, sort: ['createTime,desc'] }); |  | ||||||
|   }; |  | ||||||
|   fetchData(); |  | ||||||
|  |  | ||||||
|   // 强退 |   /** | ||||||
|   const handleClick = async (token: string) => { |    * 切换每页条数 | ||||||
|     const res = await kickout(token); |    * | ||||||
|     if (res.success) Message.success(res.msg); |    * @param pageSize 每页条数 | ||||||
|  |    */ | ||||||
|  |   const handlePageSizeChange = (pageSize: number) => { | ||||||
|  |     queryParams.value.size = pageSize; | ||||||
|  |     getList(); | ||||||
|   }; |   }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| @@ -190,6 +188,9 @@ | |||||||
| <style scoped lang="less"> | <style scoped lang="less"> | ||||||
|   .container { |   .container { | ||||||
|     padding: 0 20px 20px 20px; |     padding: 0 20px 20px 20px; | ||||||
|  |     .head-container { | ||||||
|  |       margin-bottom: 16px | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   :deep(.arco-table-th) { |   :deep(.arco-table-th) { | ||||||
|     &:last-child { |     &:last-child { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user