修复显示异常与筛选功能UI

This commit is contained in:
Cheng Zhou
2025-12-23 22:02:57 +08:00
parent 9e9404d273
commit 148fa6ad9a
5 changed files with 127 additions and 81 deletions
+2 -2
View File
@@ -4,8 +4,8 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CTMS</title> <title>CTMS</title>
<script type="module" crossorigin src="/assets/index-Cs6sO1fk.js"></script> <script type="module" crossorigin src="/assets/index-BLuwzAdI.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BX8Ho7fh.css"> <link rel="stylesheet" crossorigin href="/assets/index-DrrS234a.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
+27
View File
@@ -156,3 +156,30 @@ body {
.el-tag--success { background-color: #f6ffed; color: var(--ctms-success); border: 1px solid #b7eb8f; } .el-tag--success { background-color: #f6ffed; color: var(--ctms-success); border: 1px solid #b7eb8f; }
.el-tag--warning { background-color: #fffbe6; color: var(--ctms-warning); border: 1px solid #ffe58f; } .el-tag--warning { background-color: #fffbe6; color: var(--ctms-warning); border: 1px solid #ffe58f; }
.el-tag--danger { background-color: #fff1f0; color: var(--ctms-danger); border: 1px solid #ffa39e; } .el-tag--danger { background-color: #fff1f0; color: var(--ctms-danger); border: 1px solid #ffa39e; }
/* 列表整合工具栏 (Table Toolbar) */
.ctms-table-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
gap: 16px;
flex-wrap: wrap;
}
.ctms-filter-group {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.ctms-filter-item {
width: 160px;
}
.ctms-action-group {
display: flex;
gap: 12px;
align-items: center;
}
+7 -2
View File
@@ -121,12 +121,17 @@ const siteName = (row: any) => {
const ownerName = (ownerId: string) => { const ownerName = (ownerId: string) => {
const memberMap = members.value.reduce<Record<string, string>>((acc, cur) => { const memberMap = members.value.reduce<Record<string, string>>((acc, cur) => {
const username = cur?.user?.display_name || cur?.user?.username || cur?.username; const username = cur?.user?.display_name || cur?.user?.full_name || cur?.user?.username || cur?.username;
if (cur?.user_id) acc[cur.user_id] = username || cur.user_id; if (cur?.user_id) acc[cur.user_id] = username || cur.user_id;
if (cur?.id) acc[cur.id] = username || cur.id;
return acc; return acc;
}, {}); }, {});
const owner = milestone.value?.owner; const owner = milestone.value?.owner;
return owner?.display_name || owner?.username || displayUser(ownerId, { members: memberMap }); const nameFromObject = owner?.display_name || owner?.full_name || owner?.username;
if (nameFromObject) return nameFromObject;
return memberMap[ownerId] || ownerId || "—";
}; };
onMounted(async () => { onMounted(async () => {
+44 -26
View File
@@ -1,31 +1,34 @@
<template> <template>
<div class="page"> <div class="page">
<el-card class="mb-12"> <el-card>
<div class="filters"> <div class="table-toolbar">
<el-select v-model="filters.level" placeholder="核查层级" clearable @change="load"> <div class="filter-group">
<el-option label="SDV 核查" value="SDV" /> <el-select v-model="filters.level" placeholder="核查层级" clearable @change="load" class="filter-item">
<el-option label="SDR 核查" value="SDR" /> <el-option label="SDV 核查" value="SDV" />
</el-select> <el-option label="SDR 核查" value="SDR" />
<SiteSelect </el-select>
v-model="filters.site_id" <SiteSelect
:study-id="study.currentStudy?.id || null" v-model="filters.site_id"
placeholder="中心" :study-id="study.currentStudy?.id || null"
style="width: 220px" placeholder="中心"
@change="load" class="filter-item site-selector"
/> @change="load"
<div class="spacer" /> />
<el-button v-if="canEdit" type="primary" @click="openCreate">新增核查进度</el-button> </div>
<div class="action-group">
<el-button v-if="canEdit" type="primary" @click="openCreate">新增核查进度</el-button>
</div>
</div> </div>
</el-card>
<VerificationTable <VerificationTable
:verifications="verifications" :verifications="verifications"
:can-edit="canEdit" :can-edit="canEdit"
:loading="loading" :loading="loading"
:subject-map="subjectMap" :subject-map="subjectMap"
:verifier-map="verifierMap" :verifier-map="verifierMap"
@edit="openEdit" @edit="openEdit"
/> />
</el-card>
<el-dialog :title="editForm.id ? '更新核查进度' : '新增核查进度'" v-model="showEdit" width="520px"> <el-dialog :title="editForm.id ? '更新核查进度' : '新增核查进度'" v-model="showEdit" width="520px">
<el-form :model="editForm" label-width="120px"> <el-form :model="editForm" label-width="120px">
@@ -205,10 +208,25 @@ onMounted(async () => {
.page { .page {
padding: 16px; padding: 16px;
} }
.filters { .table-toolbar {
display: flex; display: flex;
gap: 8px; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 20px;
gap: 16px;
flex-wrap: wrap;
}
.filter-group {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.filter-item {
width: 160px;
}
.site-selector {
width: 220px;
} }
.spacer { .spacer {
flex: 1; flex: 1;
+47 -51
View File
@@ -1,48 +1,54 @@
<template> <template>
<div class="page"> <div class="page">
<el-card> <el-card>
<div class="filters"> <div class="ctms-table-toolbar">
<el-select v-model="filters.eventType" clearable placeholder="操作类型" @change="loadLogs"> <div class="ctms-filter-group">
<el-option v-for="opt in eventTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> <el-select v-model="filters.eventType" clearable placeholder="操作类型" @change="loadLogs" class="ctms-filter-item">
</el-select> <el-option v-for="opt in eventTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
<el-select v-model="filters.operatorId" clearable placeholder="操作人" filterable @change="loadLogs"> </el-select>
<el-option v-for="u in userOptions" :key="u.value" :label="u.label" :value="u.value" /> <el-select v-model="filters.operatorId" clearable placeholder="操作人" filterable @change="loadLogs" class="ctms-filter-item">
</el-select> <el-option v-for="u in userOptions" :key="u.value" :label="u.label" :value="u.value" />
<el-select v-model="filters.result" clearable placeholder="结果" @change="loadLogs"> </el-select>
<el-option label="成功" value="SUCCESS" /> <el-select v-model="filters.result" clearable placeholder="结果" @change="loadLogs" style="width: 100px">
<el-option label="失败" value="FAIL" /> <el-option label="成功" value="SUCCESS" />
</el-select> <el-option label="失败" value="FAIL" />
<el-date-picker </el-select>
v-model="filters.range" <el-date-picker
type="daterange" v-model="filters.range"
unlink-panels type="daterange"
start-placeholder="开始日期" unlink-panels
end-placeholder="结束日期" start-placeholder="开始"
format="YYYY-MM-DD" end-placeholder="结束"
value-format="YYYY-MM-DD" format="YYYY-MM-DD"
@change="loadLogs" value-format="YYYY-MM-DD"
/> style="width: 240px"
<div class="spacer" /> @change="loadLogs"
<el-button type="primary" @click="loadLogs">查询</el-button> />
<el-button </div>
v-if="isAdmin" <div class="ctms-action-group">
type="warning" <el-button
plain v-if="isAdmin"
:loading="exportLoading" type="warning"
@click="confirmExport('system')" plain
> size="small"
导出系统审计 :loading="exportLoading"
</el-button> @click="confirmExport('system')"
<el-button >
v-if="canProjectExport" 导出系统审计
type="warning" </el-button>
plain <el-button
:loading="exportLoading" v-if="canProjectExport"
@click="confirmExport('project')" type="warning"
> plain
导出项目审计 size="small"
</el-button> :loading="exportLoading"
@click="confirmExport('project')"
>
导出项目审计
</el-button>
</div>
</div> </div>
<el-table :data="logs" v-loading="loading" style="width: 100%"> <el-table :data="logs" v-loading="loading" style="width: 100%">
<el-table-column prop="timestamp" label="时间" width="180"> <el-table-column prop="timestamp" label="时间" width="180">
<template #default="scope">{{ displayDateTime(scope.row.timestamp) }}</template> <template #default="scope">{{ displayDateTime(scope.row.timestamp) }}</template>
@@ -318,16 +324,6 @@ onMounted(async () => {
.page { .page {
padding: 16px; padding: 16px;
} }
.filters {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 12px;
flex-wrap: wrap;
}
.spacer {
flex: 1;
}
.pagination { .pagination {
margin-top: 12px; margin-top: 12px;
text-align: right; text-align: right;