优化登录页UI、新增占满布局类

This commit is contained in:
Cheng Zhou
2026-03-10 11:37:19 +08:00
parent 4c98147f3e
commit 8bec268a5b
47 changed files with 640 additions and 351 deletions
+12 -12
View File
@@ -1,7 +1,7 @@
<template>
<div class="page">
<div class="page page--flush">
<el-card shadow="never" class="main-content-card unified-shell">
<div class="main-content-flat 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">
@@ -48,11 +48,12 @@
</el-button>
</el-form>
</div>
<div class="unified-section table-section">
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table
:data="sortedItems"
v-loading="loading"
style="width: 100%"
class="shipment-table"
:row-class-name="shipmentRowClass"
@row-click="onRowClick"
>
@@ -104,7 +105,7 @@
</el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.drugShipments.empty" />
</div>
</el-card>
</div>
</div>
</template>
@@ -252,7 +253,7 @@ onMounted(async () => {
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
}
@@ -271,10 +272,10 @@ onMounted(async () => {
}
.filter-actions :deep(.el-button) {
height: 36px;
line-height: 36px;
padding: 0 18px;
border-radius: 8px;
height: 32px;
line-height: 32px;
padding: 0 12px;
border-radius: 10px;
}
.filter-select {
@@ -285,9 +286,8 @@ onMounted(async () => {
flex: 1;
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
.shipment-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.type-tag {
@@ -1,10 +1,10 @@
<template>
<div class="redirecting ctms-page-shell">
<section class="unified-action-bar">
<div class="redirecting ctms-page-shell page--flush">
<section class="unified-action-bar bar--flush">
<div class="redirecting-title">{{ TEXT.menu.fileVersionManagement }}</div>
</section>
<section class="unified-shell">
<section class="unified-section">
<section class="unified-section section--flush">
<el-empty :description="`${TEXT.common.loading}...`" />
</section>
</section>
+17 -5
View File
@@ -1,6 +1,6 @@
<template>
<div class="page">
<el-card shadow="never" class="main-content-card unified-shell">
<div class="main-content-flat 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">
@@ -70,7 +70,7 @@
</el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeContracts.empty" />
</div>
</el-card>
</div>
</div>
</template>
@@ -185,10 +185,18 @@ onMounted(async () => {
flex-direction: column;
}
.main-content-flat {
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
}
@@ -206,8 +214,12 @@ onMounted(async () => {
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
padding-top: 0;
padding-bottom: 0;
}
.ctms-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
+17 -5
View File
@@ -1,6 +1,6 @@
<template>
<div class="page">
<el-card shadow="never" class="main-content-card unified-shell">
<div class="main-content-flat 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">
@@ -80,7 +80,7 @@
</el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeSpecials.empty" />
</div>
</el-card>
</div>
</div>
</template>
@@ -194,10 +194,18 @@ onMounted(async () => {
flex-direction: column;
}
.main-content-flat {
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
}
@@ -219,8 +227,12 @@ onMounted(async () => {
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
padding-top: 0;
padding-bottom: 0;
}
:deep(.ctms-table .el-table__inner-wrapper::before) {
display: none;
}
</style>
+8 -9
View File
@@ -1,8 +1,8 @@
<template>
<div class="page">
<div class="page ctms-page-shell page--flush">
<el-card shadow="never" class="main-content-card unified-shell">
<div class="filter-container unified-action-bar">
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form">
<el-input
@@ -29,7 +29,7 @@
</el-button>
</el-form>
</div>
<div class="unified-section table-section">
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table
:data="sortedItems"
v-loading="loading"
@@ -60,7 +60,7 @@
</el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.knowledgeNotes.empty" />
</div>
</el-card>
</div>
</div>
</template>
@@ -178,7 +178,7 @@ onMounted(async () => {
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
}
@@ -195,9 +195,8 @@ onMounted(async () => {
flex: 1;
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
:deep(.ctms-table .el-table__inner-wrapper::before) {
display: none;
}
</style>
+9 -10
View File
@@ -1,7 +1,7 @@
<template>
<div class="page">
<div class="page page--flush">
<div v-if="study.currentStudy" class="unified-shell">
<section class="unified-section equipment-section">
<section class="unified-section section--flush">
<div class="filter-row">
<el-form :inline="true" :model="filters">
<el-form-item label="设备名称">
@@ -15,7 +15,7 @@
<el-button type="primary" @click="openCreate">新建</el-button>
</div>
<el-table v-loading="loading" :data="rows" class="ctms-table" style="width: 100%" table-layout="fixed">
<el-table v-loading="loading" :data="rows" class="ctms-table equipment-table" style="width: 100%" table-layout="fixed">
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="specModel" label="规格型号" />
<el-table-column prop="unit" label="单位" />
@@ -391,11 +391,6 @@ watch(
flex-direction: column;
}
.equipment-section {
padding-top: 14px;
padding-bottom: 12px;
}
.filter-row {
display: flex;
align-items: center;
@@ -593,9 +588,13 @@ watch(
padding-bottom: 4px;
}
.equipment-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
/* ========== 表格居中 ========== */
:deep(.ctms-table th.el-table__cell .cell),
:deep(.ctms-table td.el-table__cell .cell) {
.equipment-table :deep(th.el-table__cell .cell),
.equipment-table :deep(td.el-table__cell .cell) {
text-align: center;
}
</style>
+10 -11
View File
@@ -1,7 +1,7 @@
<template>
<div class="page ctms-page-shell">
<div class="page ctms-page-shell page--flush">
<div v-if="study.currentStudy" class="unified-shell ctms-table-card">
<section class="unified-action-bar">
<section class="unified-action-bar bar--flush">
<div class="card-header ctms-page-header-row">
<div>
<div class="card-title">{{ TEXT.modules.projectMilestones.listTitle }}</div>
@@ -22,7 +22,7 @@
</div>
</div>
</section>
<section class="unified-section ctms-page-content-grid">
<section class="unified-section ctms-page-content-grid section--flush-x section--flush-top section--flush-bottom">
<el-table :data="rows" v-loading="loading" class="ctms-table" style="width: 100%">
<el-table-column prop="name" :label="TEXT.modules.projectMilestones.columns.name" min-width="140" />
<el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate" min-width="170">
@@ -450,12 +450,16 @@ watch(
flex-direction: column;
}
.ctms-page-content-grid {
gap: 0;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 12px;
margin-bottom: 0;
flex-wrap: wrap;
}
@@ -657,12 +661,7 @@ watch(
background: #94a3b8;
}
:deep(.ctms-table th.el-table__cell .cell),
:deep(.ctms-table td.el-table__cell .cell) {
font-size: 11px;
padding-top: 4px;
padding-bottom: 4px;
padding-left: 6px;
padding-right: 6px;
.ctms-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style>
+1 -51
View File
@@ -1,21 +1,7 @@
<template>
<div class="page ctms-page-shell">
<div class="page ctms-page-shell page--flush">
<div v-if="study.currentStudy" class="page-body">
<div class="unified-shell ctms-table-card">
<section class="unified-section">
<div class="kpi-grid">
<KpiCard
v-for="item in kpiItems"
:key="item.key"
class="kpi"
:title="item.title"
:value="item.value"
:subtext="item.subtext"
:type="item.type"
/>
</div>
</section>
<section class="unified-section">
<div class="overview-meta-inline">
<el-tag v-if="usingDemo" effect="plain" type="info" class="demo-tag">示例数据</el-tag>
@@ -83,7 +69,6 @@ import { fetchProjectOverview } from "../../api/overview";
import { fetchSites } from "../../api/sites";
import StateEmpty from "../../components/StateEmpty.vue";
import StateLoading from "../../components/StateLoading.vue";
import KpiCard from "../../components/KpiCard.vue";
import CenterProgressRow from "./project-overview/CenterProgressRow.vue";
import EnrollmentBarChart, { type EnrollmentBarItem } from "./project-overview/EnrollmentBarChart.vue";
import { adaptProjectOverview, type CenterOverview, type ProjectOverviewViewModel } from "./project-overview/overview.adapter";
@@ -99,35 +84,6 @@ const updatedAtLabel = ref(displayDateTime(new Date()));
const preferApi = String(import.meta.env.VITE_USE_OVERVIEW_API || "").toLowerCase() === "true";
const centers = computed(() => overview.value?.centers || []);
const kpiItems = computed(() => {
const summary = overview.value?.summary;
const totalTarget = summary?.total_target ?? 0;
const totalActual = summary?.total_actual ?? 0;
const activeCenters = centers.value.filter((item) => item.is_active !== false).length;
return [
{
key: "target",
title: "总入组目标",
value: totalTarget,
subtext: "项目整体计划",
type: "primary" as const,
},
{
key: "actual",
title: "当前入组",
value: totalActual,
subtext: `达成率 ${totalTarget > 0 ? Math.round((totalActual / totalTarget) * 100) : 0}%`,
type: "success" as const,
},
{
key: "centers",
title: "活跃中心",
value: activeCenters,
subtext: `中心总数 ${centers.value.length}`,
type: "info" as const,
},
];
});
const buildFallbackCentersFromSites = (siteList: any[]): CenterOverview[] =>
siteList.map((site: any) => ({
@@ -252,12 +208,6 @@ watch(
gap: 0;
}
.kpi-grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.demo-tag {
border-color: var(--ctms-border-color);
color: var(--ctms-text-secondary);
@@ -1,8 +1,8 @@
<template>
<div class="page ctms-page-shell">
<div class="page ctms-page-shell page--flush">
<template v-if="study.currentStudy">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card">
<div class="filter-container unified-action-bar">
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<div class="filter-left">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="问题分类" class="filter-item">
@@ -47,7 +47,7 @@
</div>
</div>
<div class="unified-section table-section">
<div class="unified-section table-section section--flush">
<el-table
class="issue-table"
:data="tableRows"
@@ -113,7 +113,7 @@
/>
</div>
</div>
</el-card>
</div>
<el-drawer
v-model="formDialogVisible"
@@ -723,7 +723,6 @@ watch(
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
padding: 16px 16px 0;
}
.filter-left {
@@ -734,7 +733,7 @@ watch(
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
@@ -764,10 +763,6 @@ watch(
gap: 8px;
}
.table-section {
padding: 12px 0;
}
.issue-no {
font-weight: 600;
color: #24324a;
@@ -823,11 +818,15 @@ watch(
}
.pagination-wrap {
margin: 14px 16px 0;
margin: 10px 0 0;
display: flex;
justify-content: flex-end;
}
.issue-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.dialog-select {
width: 100%;
}
+12 -13
View File
@@ -1,7 +1,7 @@
<template>
<div class="page ctms-page-shell">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card">
<div class="filter-container unified-action-bar">
<div class="page ctms-page-shell page--flush">
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" class="filter-form">
<el-form-item class="filter-item-form">
<el-input v-model="filters.keyword" :placeholder="TEXT.common.fields.keyword" clearable class="filter-input-comp">
@@ -33,8 +33,8 @@
</el-form-item>
</el-form>
</div>
<div class="unified-section table-section">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" table-layout="fixed">
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" table-layout="fixed" class="risk-table">
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" min-width="160" show-overflow-tooltip />
<el-table-column prop="subject_no" :label="TEXT.modules.subjectManagement.screeningNo" min-width="160" show-overflow-tooltip />
<el-table-column :label="TEXT.common.fields.site" min-width="160" show-overflow-tooltip>
@@ -54,7 +54,7 @@
</el-table>
<StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssuePd.emptyDescription" />
</div>
</el-card>
</div>
</div>
</template>
@@ -162,21 +162,16 @@ onMounted(load);
flex-direction: column;
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
}
.filter-form {
display: flex;
width: 100%;
flex-wrap: wrap;
gap: 0;
gap: 8px;
}
.filter-item-form {
margin-bottom: 0;
margin-right: 12px;
margin-right: 0;
}
.filter-input-comp {
@@ -191,4 +186,8 @@ onMounted(load);
margin-bottom: 0;
margin-right: 0;
}
.risk-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style>
+12 -13
View File
@@ -1,7 +1,7 @@
<template>
<div class="page ctms-page-shell">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card">
<div class="filter-container unified-action-bar">
<div class="page ctms-page-shell page--flush">
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" class="filter-form">
<el-form-item class="filter-item-form">
<el-input v-model="filters.keyword" :placeholder="TEXT.common.fields.keyword" clearable class="filter-input-comp">
@@ -51,8 +51,8 @@
</el-form-item>
</el-form>
</div>
<div class="unified-section table-section">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%">
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" class="risk-table">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140">
<template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
</el-table-column>
@@ -82,7 +82,7 @@
</el-table>
<StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssueSae.emptyDescription" />
</div>
</el-card>
</div>
</div>
</template>
@@ -219,21 +219,16 @@ onMounted(load);
flex-direction: column;
}
.table-section {
padding-top: 12px;
padding-bottom: 12px;
}
.filter-form {
display: flex;
width: 100%;
flex-wrap: wrap;
gap: 0;
gap: 8px;
}
.filter-item-form {
margin-bottom: 0;
margin-right: 12px;
margin-right: 0;
}
.filter-input-comp {
@@ -248,4 +243,8 @@ onMounted(load);
margin-bottom: 0;
margin-right: 0;
}
.risk-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style>
@@ -1,9 +1,9 @@
<template>
<div class="page">
<el-card shadow="never" class="main-content-card unified-shell">
<div class="page ctms-page-shell page--flush">
<div class="main-content-flat unified-shell">
<el-tabs v-model="activeTab" class="ctms-tabs">
<el-tab-pane :label="TEXT.modules.startupFeasibilityEthics.feasibilityTab" name="feasibility">
<div class="ctms-tab-content">
<div class="ctms-tab-content unified-section section--flush">
<div class="ctms-section-header">
<div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.feasibilityTab }}</div>
<div class="ctms-section-actions">
@@ -63,7 +63,7 @@
</div>
</el-tab-pane>
<el-tab-pane :label="TEXT.modules.startupFeasibilityEthics.ethicsTab" name="ethics">
<div class="ctms-tab-content">
<div class="ctms-tab-content unified-section section--flush">
<div class="ctms-section-header">
<div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.ethicsTab }}</div>
<div class="ctms-section-actions">
@@ -126,7 +126,7 @@
</div>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</div>
</template>
@@ -312,7 +312,15 @@ onMounted(() => {
}
.ctms-tab-content {
padding: 12px;
gap: 0;
}
.ctms-tab-content .ctms-section-header {
margin-bottom: 0;
}
.ctms-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style>
+7 -3
View File
@@ -1,12 +1,12 @@
<template>
<div class="page">
<div class="page ctms-page-shell page--flush">
<div class="unified-shell">
<section class="unified-section">
<section class="unified-section kickoff-table-section section--flush">
<el-table
:data="kickoffRows"
v-loading="loading"
style="width: 100%"
class="ctms-table"
class="ctms-table kickoff-table"
:row-class-name="kickoffRowClass"
@row-click="onKickoffRowClick"
>
@@ -166,6 +166,10 @@ onMounted(() => {
gap: 0;
}
.kickoff-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style>
<style>
+14 -10
View File
@@ -1,7 +1,7 @@
<template>
<div class="page ctms-page-shell">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card">
<div class="filter-container unified-action-bar">
<div class="page ctms-page-shell page--flush">
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form">
<el-input
@@ -54,7 +54,7 @@
</el-button>
</el-form>
</div>
<div class="unified-section table-section">
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table
:data="pagedItems"
v-loading="loading"
@@ -118,7 +118,7 @@
</div>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.subjectManagement.empty" />
</div>
</el-card>
</div>
</div>
</template>
@@ -281,7 +281,7 @@ onMounted(async () => {
.filter-form {
display: flex;
width: 100%;
gap: 12px;
gap: 8px;
align-items: center;
}
@@ -300,9 +300,13 @@ onMounted(async () => {
}
.header-action-btn {
height: 36px;
padding: 0 20px;
border-radius: 8px;
height: 32px;
padding: 0 12px;
border-radius: 10px;
}
:deep(.ctms-table .el-table__inner-wrapper::before) {
display: none;
}
.subject-info-cell {
@@ -358,7 +362,7 @@ onMounted(async () => {
.pagination-wrap {
display: flex;
justify-content: flex-end;
margin-top: 14px;
margin-top: 10px;
}
</style>