立项配置页初步优化
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<el-card shadow="never" class="main-content-card">
|
||||
<div class="filter-container">
|
||||
<el-card shadow="never" class="main-content-card unified-shell">
|
||||
<div class="filter-container unified-action-bar">
|
||||
<el-form :inline="true" :model="filters" class="filter-form">
|
||||
<el-form-item label="" class="filter-item-form">
|
||||
<el-select v-model="filters.entityType" clearable :placeholder="TEXT.modules.adminAuditLogs.filterEntityType" @change="loadLogs" class="filter-select-comp">
|
||||
<el-option v-for="opt in entityTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="" class="filter-item-form">
|
||||
<el-select v-model="filters.eventType" clearable :placeholder="TEXT.modules.adminAuditLogs.filterEvent" @change="loadLogs" class="filter-select-comp">
|
||||
<el-option v-for="opt in eventTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
@@ -43,53 +48,55 @@
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="logs" v-loading="loading" style="width: 100%" stripe>
|
||||
<el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<span class="text-gray-500">{{ displayDateTime(scope.row.timestamp) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="actorName" :label="TEXT.modules.adminAuditLogs.columns.actor" width="140" />
|
||||
<el-table-column prop="actorRoleLabel" :label="TEXT.common.labels.role" width="120" />
|
||||
<el-table-column prop="eventLabel" :label="TEXT.modules.adminAuditLogs.columns.event" width="160">
|
||||
<template #default="scope">
|
||||
<el-tag effect="plain">{{ scope.row.eventLabel }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="actionText" :label="TEXT.modules.adminAuditLogs.columns.action" min-width="180" />
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.target" min-width="180">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.targetTypeLabel">
|
||||
<strong>{{ scope.row.targetTypeLabel }}</strong>
|
||||
<span class="text-gray-500" v-if="scope.row.targetName">({{ scope.row.targetName }})</span>
|
||||
</span>
|
||||
<span v-else>{{ TEXT.common.fallback }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.diff" min-width="260">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.diffText?.length" class="diff-container">
|
||||
<div v-for="(line, idx) in scope.row.diffText" :key="idx" class="diff-line">{{ line }}</div>
|
||||
</div>
|
||||
<span v-else class="text-gray-400">{{ TEXT.audit.emptyValue }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.result" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.result === 'SUCCESS' ? 'success' : 'danger'" effect="dark" size="small">
|
||||
{{ scope.row.resultLabel }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
layout="prev, pager, next"
|
||||
:page-size="pageSize"
|
||||
:current-page="page"
|
||||
:total="total"
|
||||
@current-change="onPageChange"
|
||||
/>
|
||||
<div class="unified-section table-section">
|
||||
<el-table :data="logs" v-loading="loading" style="width: 100%" stripe>
|
||||
<el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<span class="text-gray-500">{{ displayDateTime(scope.row.timestamp) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="actorName" :label="TEXT.modules.adminAuditLogs.columns.actor" width="140" />
|
||||
<el-table-column prop="actorRoleLabel" :label="TEXT.common.labels.role" width="120" />
|
||||
<el-table-column prop="eventLabel" :label="TEXT.modules.adminAuditLogs.columns.event" width="160">
|
||||
<template #default="scope">
|
||||
<el-tag effect="plain">{{ scope.row.eventLabel }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="actionText" :label="TEXT.modules.adminAuditLogs.columns.action" min-width="180" />
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.target" min-width="180">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.targetTypeLabel">
|
||||
<strong>{{ scope.row.targetTypeLabel }}</strong>
|
||||
<span class="text-gray-500" v-if="scope.row.targetName">({{ scope.row.targetName }})</span>
|
||||
</span>
|
||||
<span v-else>{{ TEXT.common.fallback }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.diff" min-width="260">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.diffText?.length" class="diff-container">
|
||||
<div v-for="(line, idx) in scope.row.diffText" :key="idx" class="diff-line">{{ line }}</div>
|
||||
</div>
|
||||
<span v-else class="text-gray-400">{{ TEXT.audit.emptyValue }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.result" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.result === 'SUCCESS' ? 'success' : 'danger'" effect="dark" size="small">
|
||||
{{ scope.row.resultLabel }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
layout="prev, pager, next"
|
||||
:page-size="pageSize"
|
||||
:current-page="page"
|
||||
:total="total"
|
||||
@current-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
@@ -141,6 +148,7 @@ const pageSize = 20;
|
||||
const total = ref(0);
|
||||
|
||||
const filters = ref({
|
||||
entityType: "",
|
||||
eventType: "",
|
||||
operatorId: "",
|
||||
result: "",
|
||||
@@ -151,6 +159,15 @@ const eventTypeOptions = Object.entries(auditDict).map(([value, cfg]) => ({
|
||||
value,
|
||||
label: cfg.label,
|
||||
}));
|
||||
const entityTypeOptions = [
|
||||
{ value: "study_setup_config", label: "立项配置" },
|
||||
{ value: "study", label: "项目" },
|
||||
{ value: "subject", label: "参与者" },
|
||||
{ value: "site", label: "中心" },
|
||||
{ value: "finance", label: "费用" },
|
||||
{ value: "drug_shipment", label: "药品流向" },
|
||||
{ value: "audit_log", label: "审计日志" },
|
||||
];
|
||||
const userOptions = computed(() => users.value.map((u: any) => ({ label: u.username, value: u.id })));
|
||||
const isAdmin = computed(() => auth.user?.role === "ADMIN");
|
||||
const canProjectExport = computed(() => !!study.currentStudy && auth.user?.role === "ADMIN");
|
||||
@@ -188,6 +205,7 @@ const loadLogs = async () => {
|
||||
const params: Record<string, any> = {
|
||||
skip: (page.value - 1) * pageSize,
|
||||
limit: pageSize,
|
||||
entity_type: filters.value.entityType || undefined,
|
||||
action: filters.value.eventType || undefined,
|
||||
operator_id: filters.value.operatorId || undefined,
|
||||
};
|
||||
@@ -258,6 +276,7 @@ const fetchAllForExport = async () => {
|
||||
const params: Record<string, any> = {
|
||||
skip: 0,
|
||||
limit: 2000,
|
||||
entity_type: filters.value.entityType || undefined,
|
||||
action: filters.value.eventType || undefined,
|
||||
operator_id: filters.value.operatorId || undefined,
|
||||
};
|
||||
@@ -327,12 +346,9 @@ onMounted(async () => {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content-card :deep(.el-card__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
margin-bottom: 20px;
|
||||
.table-section {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
|
||||
Reference in New Issue
Block a user