front/src/views/system/dataPerm/audit/index.vue
zzh cf4d2c4a3f feat: 新增 9610 申报页与批量清单/报关单操作
同步 SPA 回退、权限目录、拣货绑定组件及相关系统页调整。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 17:46:04 +08:00

176 lines
6.6 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 class="data-perm-audit-container">
<div class="data-perm-audit-card">
<a-tabs v-model:active-key="activeTab">
<a-tab-pane key="change" title="配置变更日志">
<div class="table-toolbar">
<a-space wrap>
<a-select v-model="changeQuery.targetType" placeholder="目标类型" allow-clear style="width: 120px">
<a-option value="user">用户</a-option>
<a-option value="role">角色</a-option>
<a-option value="template">模板</a-option>
</a-select>
<a-input v-model="changeQuery.targetId" placeholder="目标 ID" allow-clear style="width: 200px" />
<a-range-picker v-model="changeQuery.timeRange" show-time style="width: 360px" />
<a-button class="app-btn-search" @click="loadChangeLog">{{ t('common.search') }}</a-button>
</a-space>
<PaginationPro
:total-count="changePagination.total"
v-model:current-page="changePagination.current"
v-model:page-size="changePagination.pageSize"
@page-change="(p) => { changePagination.current = p; loadChangeLog() }"
@page-size-change="(s) => { changePagination.pageSize = s; changePagination.current = 1; loadChangeLog() }"
/>
</div>
<a-table :data="changeLogs" :loading="changeLoading" :pagination="false" row-key="id" size="small">
<template #columns>
<a-table-column title="时间" data-index="createTime" :width="180" />
<a-table-column title="目标" :width="100">
<template #cell="{ record }">{{ record.targetType }}</template>
</a-table-column>
<a-table-column title="目标 ID" data-index="targetId" ellipsis />
<a-table-column title="动作" data-index="action" :width="100" />
<a-table-column title="操作人 mapId" data-index="operatorMapId" :width="110" />
</template>
</a-table>
</a-tab-pane>
<a-tab-pane key="access" title="数据访问日志">
<a-alert type="info" style="margin-bottom: 12px">
P1 后端暂不自动写入访问日志;本页为预留查询界面,待内审需求启用后再对接。
</a-alert>
<div class="table-toolbar">
<a-space wrap>
<a-input v-model="accessQuery.userId" placeholder="用户 GUID" allow-clear style="width: 220px" />
<a-select
v-model="accessQuery.dataResourceCode"
placeholder="模块"
allow-clear
style="width: 140px"
:options="[
{ value: 'Order', label: '订单' },
{ value: 'Customer', label: '客户' },
]"
/>
<a-range-picker v-model="accessQuery.timeRange" show-time style="width: 360px" />
<a-button class="app-btn-search" @click="loadAccessLog">{{ t('common.search') }}</a-button>
</a-space>
<PaginationPro
:total-count="accessPagination.total"
v-model:current-page="accessPagination.current"
v-model:page-size="accessPagination.pageSize"
@page-change="(p) => { accessPagination.current = p; loadAccessLog() }"
@page-size-change="(s) => { accessPagination.pageSize = s; accessPagination.current = 1; loadAccessLog() }"
/>
</div>
<a-table :data="accessLogs" :loading="accessLoading" :pagination="false" row-key="id" size="small">
<template #columns>
<a-table-column title="时间" data-index="createTime" :width="180" />
<a-table-column title="模块" data-index="dataResourceCode" :width="100" />
<a-table-column title="接口" data-index="apiPath" ellipsis />
<a-table-column title="行数" data-index="rowCount" :width="80" align="center" />
</template>
</a-table>
</a-tab-pane>
</a-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import PaginationPro from '@/components/PaginationPro/index.vue'
import { getAccessLogList, getChangeLogList, type AccessLogItem, type ChangeLogItem } from '@/api/rbac/data-perm'
import { handleApiError } from '@/utils/rbac-error-handler'
const { t } = useI18n()
const activeTab = ref('change')
const changeLoading = ref(false)
const changeLogs = ref<ChangeLogItem[]>([])
const changeQuery = reactive({
targetType: '',
targetId: '',
timeRange: [] as string[],
})
const changePagination = reactive({ current: 1, pageSize: 30, total: 0 })
const accessLoading = ref(false)
const accessLogs = ref<AccessLogItem[]>([])
const accessQuery = reactive({
userId: '',
dataResourceCode: '',
timeRange: [] as string[],
})
const accessPagination = reactive({ current: 1, pageSize: 30, total: 0 })
function buildTimeParams(range: string[]) {
if (!range?.length || range.length < 2) return {}
return { startTime: range[0], endTime: range[1] }
}
async function loadChangeLog() {
changeLoading.value = true
try {
const res = await getChangeLogList({
targetType: changeQuery.targetType || undefined,
targetId: changeQuery.targetId || undefined,
page: changePagination.current,
pageSize: changePagination.pageSize,
...buildTimeParams(changeQuery.timeRange),
})
changeLogs.value = res.items || []
changePagination.total = res.total || 0
} catch (e) {
changeLogs.value = []
handleApiError(e)
} finally {
changeLoading.value = false
}
}
async function loadAccessLog() {
accessLoading.value = true
try {
const res = await getAccessLogList({
userId: accessQuery.userId || undefined,
dataResourceCode: accessQuery.dataResourceCode || undefined,
page: accessPagination.current,
pageSize: accessPagination.pageSize,
...buildTimeParams(accessQuery.timeRange),
})
accessLogs.value = res.items || []
accessPagination.total = res.total || 0
} catch (e) {
accessLogs.value = []
handleApiError(e)
} finally {
accessLoading.value = false
}
}
loadChangeLog()
</script>
<style scoped>
.data-perm-audit-container {
padding: 16px;
background: var(--app-page-bg);
flex: 1;
}
.data-perm-audit-card {
background: var(--app-card-bg);
border-radius: 8px;
padding: 16px;
}
.table-toolbar {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 12px;
}
</style>