Files
olons_admin/web/src/views/app-member/login-log/index.vue
T

64 lines
4.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<div class="n-layout-page-header"><n-card :bordered="false" title="会员登录日志">记录C端会员每次登录成功或失败,敏感信息均脱敏展示。</n-card></div>
<n-card :bordered="false" class="proCard">
<BasicForm ref="searchFormRef" @register="register" @submit="reloadTable" @reset="reloadTable" />
<BasicTable ref="actionRef" :columns="columns" :request="loadDataTable" :row-key="row => row.id" :action-column="actionColumn" :scroll-x="scrollX" :resize-height-offset="-10000">
<template #tableTitle><n-button v-if="hasPermission(['/appMemberLoginLog/export'])" type="primary" @click="exportRows">导出</n-button></template>
</BasicTable>
</n-card>
<n-modal v-model:show="showDetail" preset="card" title="登录日志详情" class="detail-modal">
<n-spin :show="detailLoading">
<n-descriptions v-if="detail.id" bordered :column="2" label-placement="left">
<n-descriptions-item label="日志ID">{{ detail.id }}</n-descriptions-item>
<n-descriptions-item label="请求ID">{{ detail.reqId }}</n-descriptions-item>
<n-descriptions-item label="会员编号">{{ detail.memberNo || '-' }}</n-descriptions-item>
<n-descriptions-item label="用户名">{{ detail.username || '-' }}</n-descriptions-item>
<n-descriptions-item label="手机号">{{ detail.mobileMask || '-' }}</n-descriptions-item>
<n-descriptions-item label="登录方式">{{ dict.getLabel('appMemberLoginTypeOptions', detail.loginType) }}</n-descriptions-item>
<n-descriptions-item label="登录状态">{{ dict.getLabel('sys_login_status', detail.status) }}</n-descriptions-item>
<n-descriptions-item label="登录时间">{{ detail.loginAt }}</n-descriptions-item>
<n-descriptions-item label="登录IP">{{ detail.loginIpMask || '-' }}</n-descriptions-item>
<n-descriptions-item label="登录地区">{{ detail.loginRegion || '-' }}</n-descriptions-item>
<n-descriptions-item label="登录域名">{{ detail.loginDomain || '-' }}</n-descriptions-item>
<n-descriptions-item label="操作系统">{{ detail.os }}</n-descriptions-item>
<n-descriptions-item label="浏览器">{{ detail.browser }}</n-descriptions-item>
<n-descriptions-item label="失败原因">{{ detail.errMsg || '-' }}</n-descriptions-item>
<n-descriptions-item label="User-Agent" :span="2">{{ detail.userAgent || '-' }}</n-descriptions-item>
</n-descriptions>
</n-spin>
</n-modal>
</div>
</template>
<script lang="ts" setup>
import { computed, h, onMounted, reactive, ref } from 'vue';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form';
import { usePermission } from '@/hooks/web/usePermission';
import { useDictStore } from '@/store/modules/dict';
import { adaTableScrollX } from '@/utils/hotgo';
import { List, View, Export } from '@/api/appMemberLoginLog';
import { columns, schemas, loadOptions } from './model';
const dict = useDictStore();
const { hasPermission } = usePermission();
const actionRef = ref();
const searchFormRef = ref<any>({});
const showDetail = ref(false);
const detailLoading = ref(false);
const detail = reactive<any>({});
const [register] = useForm({ gridProps: { cols: '1 s:1 m:2 l:3' }, labelWidth: 80, schemas });
const loadDataTable = (res) => List({ ...searchFormRef.value?.formModel, ...res });
const reloadTable = () => actionRef.value?.reload();
const actionColumn = reactive({ width: 100, title: '操作', key: 'action', fixed: 'right', render: (row) => h(TableAction as any, { style: 'button', actions: [{ label: '详情', onClick: () => openDetail(row), auth: ['/appMemberLoginLog/view'] }] }) });
const scrollX = computed(() => adaTableScrollX(columns, actionColumn.width));
async function openDetail(row) { showDetail.value = true; detailLoading.value = true; try { Object.assign(detail, await View({ id: row.id })); } finally { detailLoading.value = false; } }
function exportRows() { Export({ ...searchFormRef.value?.formModel }); }
onMounted(loadOptions);
</script>
<style lang="less" scoped>
:deep(.detail-modal) { width: min(900px, 94vw); }
</style>