优化登录页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
+1
View File
@@ -18,6 +18,7 @@ const session = useSessionStore();
<style scoped> <style scoped>
.app-shell { .app-shell {
min-height: 100vh; min-height: 100vh;
min-height: 100dvh;
} }
.app-locked { .app-locked {
+10 -4
View File
@@ -1,5 +1,5 @@
<template> <template>
<el-card class="panel"> <div class="panel unified-shell">
<div class="header"> <div class="header">
<span>{{ TEXT.common.labels.category }}</span> <span>{{ TEXT.common.labels.category }}</span>
<div v-if="canMaintain"> <div v-if="canMaintain">
@@ -23,7 +23,7 @@
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
<FaqCategoryForm v-model="showForm" :category="editing" :is-admin="isAdmin" @success="emit('refresh')" /> <FaqCategoryForm v-model="showForm" :category="editing" :is-admin="isAdmin" @success="emit('refresh')" />
</el-card> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -94,18 +94,24 @@ const onDelete = async (cat: FaqCategory) => {
<style scoped> <style scoped>
.panel { .panel {
padding: 0; border: 0;
border-radius: 0;
box-shadow: none;
overflow: hidden;
} }
.header { .header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 12px; padding: 0 0 12px;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;
} }
.menu { .menu {
max-height: calc(100vh - 240px); max-height: calc(100vh - 240px);
overflow: auto; overflow: auto;
border-right: 0;
} }
.actions { .actions {
margin-left: auto; margin-left: auto;
+5 -1
View File
@@ -1,5 +1,5 @@
<template> <template>
<el-table :data="items" v-loading="loading" style="width: 100%" @row-click="onRowClick"> <el-table :data="items" v-loading="loading" style="width: 100%" class="faq-table" @row-click="onRowClick">
<el-table-column prop="question" :label="TEXT.common.fields.question" min-width="200"> <el-table-column prop="question" :label="TEXT.common.fields.question" min-width="200">
<template #default="scope"> <template #default="scope">
<el-link type="primary" :underline="false" class="question-link"> <el-link type="primary" :underline="false" class="question-link">
@@ -131,6 +131,10 @@ const remove = async (row: FaqItem) => {
</script> </script>
<style scoped> <style scoped>
.faq-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.danger { .danger {
color: #f56c6c; color: #f56c6c;
} }
+6 -2
View File
@@ -195,8 +195,8 @@
<div class="content-wrapper"> <div class="content-wrapper">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<transition name="fade-transform" mode="out-in"> <transition name="fade-transform" mode="out-in">
<div class="ctms-route-shell"> <div :key="route.fullPath" class="ctms-route-shell">
<component :is="Component" /> <component :is="Component" :key="route.fullPath" />
</div> </div>
</transition> </transition>
</router-view> </router-view>
@@ -435,6 +435,9 @@ const onCommand = (cmd: string) => {
<style scoped> <style scoped>
.layout-container { .layout-container {
height: 100vh; height: 100vh;
height: 100dvh;
min-height: 100vh;
min-height: 100dvh;
background-color: transparent; background-color: transparent;
} }
@@ -703,6 +706,7 @@ const onCommand = (cmd: string) => {
.content-wrapper { .content-wrapper {
padding: 6px 8px; padding: 6px 8px;
min-height: calc(100vh - 52px); min-height: calc(100vh - 52px);
min-height: calc(100dvh - 52px);
background: #f7f8fb; background: #f7f8fb;
} }
+9 -13
View File
@@ -1,13 +1,14 @@
<template> <template>
<div class="module-page"> <div class="module-page ctms-page-shell page--flush">
<div class="module-header"> <div class="unified-shell">
<div class="module-header unified-action-bar bar--flush">
<div> <div>
<h1 class="module-title">{{ title }}</h1> <h1 class="module-title">{{ title }}</h1>
<p v-if="subtitle" class="module-subtitle">{{ subtitle }}</p> <p v-if="subtitle" class="module-subtitle">{{ subtitle }}</p>
</div> </div>
<slot name="actions" /> <slot name="actions" />
</div> </div>
<div class="module-content"> <div class="module-content unified-section section--flush">
<div class="module-list"> <div class="module-list">
<div class="module-list-header"> <div class="module-list-header">
<span class="list-title">{{ listTitle }}</span> <span class="list-title">{{ listTitle }}</span>
@@ -17,6 +18,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -44,13 +46,7 @@ withDefaults(
.module-page { .module-page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 0;
}
.module-header {
display: flex;
justify-content: space-between;
align-items: baseline;
} }
.module-title { .module-title {
@@ -68,9 +64,9 @@ withDefaults(
.module-list { .module-list {
background-color: #fff; background-color: #fff;
border: 1px solid var(--ctms-border-color); border: 0;
border-radius: var(--ctms-radius); border-radius: 0;
padding: 20px; padding: 0;
} }
.module-list-header { .module-list-header {
@@ -1,5 +1,5 @@
<template> <template>
<el-card> <div class="attachment-list-panel unified-shell">
<div class="header"> <div class="header">
<span>{{ headerTitle }}</span> <span>{{ headerTitle }}</span>
<AttachmentUploader <AttachmentUploader
@@ -10,7 +10,7 @@
@uploaded="load" @uploaded="load"
/> />
</div> </div>
<el-table :data="attachments" v-loading="loading" style="width: 100%"> <el-table :data="attachments" v-loading="loading" style="width: 100%" class="attachment-table">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="200" /> <el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="200" />
<el-table-column :label="TEXT.common.labels.size" width="120"> <el-table-column :label="TEXT.common.labels.size" width="120">
<template #default="scope">{{ formatFileSize(scope.row.file_size ?? scope.row.size) }}</template> <template #default="scope">{{ formatFileSize(scope.row.file_size ?? scope.row.size) }}</template>
@@ -43,7 +43,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-card> </div>
<el-dialog append-to=".layout-main .content-wrapper" v-model="previewVisible" :title="previewTitle" width="720px" :close-on-click-modal="false"> <el-dialog append-to=".layout-main .content-wrapper" v-model="previewVisible" :title="previewTitle" width="720px" :close-on-click-modal="false">
<div v-if="previewError" class="preview-error"> <div v-if="previewError" class="preview-error">
@@ -236,11 +236,23 @@ watch(previewVisible, (visible) => {
</script> </script>
<style scoped> <style scoped>
.attachment-list-panel {
background: #ffffff;
border: 0;
border-radius: 0;
box-shadow: none;
}
.header { .header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 8px; padding: 10px 16px;
border-bottom: 1px solid #eaf0f8;
}
.attachment-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
.preview-frame { .preview-frame {
@@ -1,6 +1,6 @@
<template> <template>
<div class="fee-attachments"> <div class="fee-attachments">
<el-card v-for="group in groups" :key="group.key" class="group-card"> <div v-for="group in groups" :key="group.key" class="group-card unified-shell">
<div class="group-header"> <div class="group-header">
<div> <div>
<div class="group-title">{{ group.label }}</div> <div class="group-title">{{ group.label }}</div>
@@ -28,7 +28,7 @@
<div v-if="(grouped[group.key] || []).length === 0" class="group-empty"> <div v-if="(grouped[group.key] || []).length === 0" class="group-empty">
<StateEmpty :description="group.emptyText" /> <StateEmpty :description="group.emptyText" />
</div> </div>
<el-table v-else :data="grouped[group.key]" style="width: 100%"> <el-table v-else :data="grouped[group.key]" style="width: 100%" class="group-table">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="160" /> <el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="160" />
<el-table-column :label="TEXT.common.labels.size" width="110"> <el-table-column :label="TEXT.common.labels.size" width="110">
<template #default="scope">{{ formatFileSize(scope.row.size || scope.row.file_size) }}</template> <template #default="scope">{{ formatFileSize(scope.row.size || scope.row.file_size) }}</template>
@@ -59,7 +59,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
</el-card> </div>
</div> </div>
<el-dialog append-to=".layout-main .content-wrapper" v-model="previewVisible" :title="previewTitle" width="720px" :close-on-click-modal="false"> <el-dialog append-to=".layout-main .content-wrapper" v-model="previewVisible" :title="previewTitle" width="720px" :close-on-click-modal="false">
@@ -315,14 +315,21 @@ watch(previewVisible, (visible) => {
gap: 12px; gap: 12px;
} }
.group-card {
background: #ffffff;
border: 0;
border-radius: 0;
box-shadow: none;
overflow: hidden;
}
.group-header { .group-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
margin-bottom: 8px;
gap: 8px; gap: 8px;
padding: 10px 16px;
border-bottom: 1px solid #eaf0f8;
} }
.group-title { .group-title {
@@ -338,7 +345,11 @@ watch(previewVisible, (visible) => {
} }
.group-empty { .group-empty {
padding: 0; padding: 12px 16px 0;
}
.group-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
/* Compact Empty State Override */ /* Compact Empty State Override */
+18 -4
View File
@@ -90,6 +90,12 @@
} }
/* 全局重置 */ /* 全局重置 */
html,
body,
#app {
min-height: 100%;
}
body { body {
margin: 0; margin: 0;
font-family: "Manrope", "Segoe UI", sans-serif; font-family: "Manrope", "Segoe UI", sans-serif;
@@ -345,15 +351,15 @@ body {
.ctms-filter-row { .ctms-filter-row {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
gap: 20px; gap: 12px;
flex-wrap: wrap; flex-wrap: wrap;
} }
.ctms-filter-item { .ctms-filter-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 4px;
min-width: 160px; min-width: 144px;
} }
.ctms-filter-label { .ctms-filter-label {
@@ -368,6 +374,14 @@ body {
.ctms-table-card { .ctms-table-card {
margin-bottom: 0; margin-bottom: 0;
border: 0;
border-radius: 0;
box-shadow: none !important;
background: transparent;
}
.ctms-table-card > .el-card__body {
padding: 0;
} }
.ctms-table .el-table__row { .ctms-table .el-table__row {
@@ -375,7 +389,7 @@ body {
} }
.ctms-pagination { .ctms-pagination {
margin-top: 16px; margin-top: 10px;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
} }
+50 -6
View File
@@ -3,8 +3,8 @@
--unified-shell-border: #d8e2ef; --unified-shell-border: #d8e2ef;
--unified-shell-divider: #eaf0f8; --unified-shell-divider: #eaf0f8;
--unified-shell-radius: 16px; --unified-shell-radius: 16px;
--unified-shell-padding-x: 20px; --unified-shell-padding-x: 16px;
--unified-shell-padding-y: 14px; --unified-shell-padding-y: 10px;
--unified-title-color: #0f2345; --unified-title-color: #0f2345;
--unified-muted-color: #6f84a8; --unified-muted-color: #6f84a8;
} }
@@ -13,6 +13,11 @@
padding: 16px 20px 20px; padding: 16px 20px 20px;
} }
.ctms-page-shell.page--flush,
.page.page--flush {
padding: 0 !important;
}
.ctms-page-header-row { .ctms-page-header-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -33,6 +38,23 @@
box-shadow: none; box-shadow: none;
} }
.page--flush > .unified-shell,
.page--flush > .main-content-flat.unified-shell,
.page--flush .page-body > .unified-shell,
.page--flush .page-body > .main-content-flat.unified-shell {
margin: 0;
width: 100%;
border-radius: 0;
}
.main-content-flat {
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.el-card.unified-shell { .el-card.unified-shell {
margin-bottom: 0; margin-bottom: 0;
border: 0 !important; border: 0 !important;
@@ -54,6 +76,11 @@
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
.unified-action-bar.bar--flush {
padding-left: 0 !important;
padding-right: 0 !important;
}
.ctms-page > .ctms-page-header.unified-action-bar, .ctms-page > .ctms-page-header.unified-action-bar,
.page > .page-header.unified-action-bar { .page > .page-header.unified-action-bar {
border: 0; border: 0;
@@ -67,6 +94,23 @@
border-bottom: 1px solid var(--unified-shell-divider); border-bottom: 1px solid var(--unified-shell-divider);
} }
.unified-section.section--flush-x {
padding-left: 0 !important;
padding-right: 0 !important;
}
.unified-section.section--flush-top {
padding-top: 0 !important;
}
.unified-section.section--flush-bottom {
padding-bottom: 0 !important;
}
.unified-section.section--flush {
padding: 0 !important;
}
.unified-section:last-child { .unified-section:last-child {
border-bottom: 0; border-bottom: 0;
} }
@@ -112,16 +156,16 @@
} }
.unified-shell .el-table th.el-table__cell { .unified-shell .el-table th.el-table__cell {
background-color: #f8fbff; background-color: #f7f9fc;
color: #35527d; color: #34506f;
font-weight: 600; font-weight: 600;
height: 42px; height: 40px;
font-size: 13px; font-size: 13px;
} }
.unified-shell .el-table td.el-table__cell { .unified-shell .el-table td.el-table__cell {
border-bottom-color: #edf2f8; border-bottom-color: #edf2f8;
padding: 8px 0; padding: 7px 0;
} }
.unified-shell .el-button, .unified-shell .el-button,
+7 -7
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell page--flush">
<el-row :gutter="12"> <el-row :gutter="12">
<el-col :span="5"> <el-col :span="5">
<FaqCategoryPanel <FaqCategoryPanel
@@ -154,25 +154,25 @@ onMounted(async () => {
<style scoped> <style scoped>
.page { .page {
padding: 16px; padding: 0;
} }
.faq-main { .faq-main {
background: #fff; background: #fff;
border: 1px solid var(--ctms-border-color); border: 0;
border-radius: 10px; border-radius: 0;
padding: 16px; padding: 0;
overflow: hidden;
} }
.filters { .filters {
display: flex; display: flex;
gap: 8px; gap: 8px;
align-items: center; align-items: center;
margin-bottom: 16px;
} }
.spacer { .spacer {
flex: 1; flex: 1;
} }
.pagination-wrap { .pagination-wrap {
margin-top: 14px; padding: 10px 16px 0;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
} }
+23 -6
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <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"> <div class="filter-container unified-action-bar">
<div class="filter-form"> <div class="filter-form">
<el-tag type="info" effect="plain" class="filter-label-tag">{{ TEXT.common.fields.status }}</el-tag> <el-tag type="info" effect="plain" class="filter-label-tag">{{ TEXT.common.fields.status }}</el-tag>
@@ -14,7 +14,7 @@
</div> </div>
</div> </div>
<div class="unified-section approval-table-section"> <div class="unified-section approval-table-section">
<el-table :data="users" v-loading="loading" style="width: 100%"> <el-table :data="users" v-loading="loading" class="approval-table" style="width: 100%">
<el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" /> <el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" /> <el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" />
<el-table-column prop="role" :label="TEXT.common.labels.role" width="120"> <el-table-column prop="role" :label="TEXT.common.labels.role" width="120">
@@ -54,7 +54,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -124,12 +124,26 @@ onMounted(() => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0;
}
.main-content-flat {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.main-content-flat :deep(.el-card__body) {
padding: 0;
} }
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 10px;
align-items: center; align-items: center;
} }
@@ -146,7 +160,10 @@ onMounted(() => {
} }
.approval-table-section { .approval-table-section {
padding-top: 12px; padding: 0;
padding-bottom: 12px; }
.approval-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
</style> </style>
+30 -11
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <div class="page">
<el-card shadow="never" class="main-content-card unified-shell"> <div class="main-content-flat unified-shell">
<div class="audit-toolbar"> <div class="audit-toolbar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
@@ -60,7 +60,7 @@
</el-form> </el-form>
</div> </div>
<div class="unified-section table-section"> <div class="unified-section table-section">
<el-table :data="logs" v-loading="loading" style="width: 100%" stripe> <el-table :data="logs" v-loading="loading" class="audit-table" style="width: 100%" stripe>
<el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" width="180" align="center"> <el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" width="180" align="center">
<template #default="scope"> <template #default="scope">
<span class="text-gray-500">{{ displayDateTime(scope.row.timestamp) }}</span> <span class="text-gray-500">{{ displayDateTime(scope.row.timestamp) }}</span>
@@ -115,7 +115,7 @@
/> />
</div> </div>
</div> </div>
</el-card> </div>
<el-drawer <el-drawer
v-model="detailVisible" v-model="detailVisible"
@@ -425,21 +425,35 @@ onMounted(async () => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0;
}
.main-content-flat {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.main-content-flat :deep(.el-card__body) {
padding: 0;
} }
.table-section { .table-section {
padding-top: 12px; padding: 0;
padding-bottom: 12px;
} }
.audit-toolbar { .audit-toolbar {
padding: 12px 16px; padding: 10px 16px;
border-bottom: 1px solid var(--unified-shell-divider);
} }
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 10px; gap: 8px;
align-items: center; align-items: center;
flex-wrap: nowrap; flex-wrap: nowrap;
} }
@@ -451,15 +465,15 @@ onMounted(async () => {
} }
.filter-select-comp { .filter-select-comp {
width: 140px; width: 132px;
} }
.filter-select-result { .filter-select-result {
width: 100px; width: 96px;
} }
.date-range-picker-comp { .date-range-picker-comp {
width: 260px !important; width: 248px !important;
} }
.filter-spacer { .filter-spacer {
@@ -509,9 +523,14 @@ onMounted(async () => {
} }
.pagination-wrap { .pagination-wrap {
margin-top: 14px; margin-top: 10px;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
padding: 0 0 6px;
}
.audit-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
.drawer-header { .drawer-header {
+31 -14
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="ctms-page setup-page ctms-page-shell"> <div class="ctms-page setup-page ctms-page-shell page--flush">
<div class="setup-shell unified-shell"> <div class="setup-shell unified-shell">
<div class="setup-header unified-action-bar"> <div class="setup-header unified-action-bar">
<div class="setup-flow"> <div class="setup-flow">
@@ -537,7 +537,7 @@
<StateLoading v-else :rows="4" /> <StateLoading v-else :rows="4" />
</section> </section>
<section v-show="activeStep === 1" class="setup-section"> <section v-show="activeStep === 1" class="setup-section setup-section--table">
<el-table :data="currentSetupDraft.projectMilestones" class="ctms-table setup-milestone-table"> <el-table :data="currentSetupDraft.projectMilestones" class="ctms-table setup-milestone-table">
<el-table-column label="里程碑" min-width="180"> <el-table-column label="里程碑" min-width="180">
<template #default="scope"> <template #default="scope">
@@ -668,7 +668,7 @@
</el-table> </el-table>
</section> </section>
<section v-show="activeStep === 2" class="setup-section enrollment-plan-section"> <section v-show="activeStep === 2" class="setup-section setup-section--table enrollment-plan-section">
<div class="enrollment-plan-toolbar"> <div class="enrollment-plan-toolbar">
<div class="enrollment-inline-group"> <div class="enrollment-inline-group">
<span class="enrollment-inline-label required">计划入组日期</span> <span class="enrollment-inline-label required">计划入组日期</span>
@@ -886,7 +886,7 @@
</el-table> </el-table>
</section> </section>
<section v-show="activeStep === 3" class="setup-section"> <section v-show="activeStep === 3" class="setup-section setup-section--table">
<el-table :data="currentSetupDraft.siteMilestones" class="ctms-table"> <el-table :data="currentSetupDraft.siteMilestones" class="ctms-table">
<el-table-column label="里程碑" min-width="220"> <el-table-column label="里程碑" min-width="220">
<template #default="scope"> <template #default="scope">
@@ -979,7 +979,7 @@
</el-table> </el-table>
</section> </section>
<section v-show="activeStep === 4" class="setup-section enrollment-plan-section"> <section v-show="activeStep === 4" class="setup-section setup-section--table enrollment-plan-section">
<div class="enrollment-plan-toolbar"> <div class="enrollment-plan-toolbar">
<div class="site-plan-selector"> <div class="site-plan-selector">
<span class="enrollment-inline-label">中心</span> <span class="enrollment-inline-label">中心</span>
@@ -1226,7 +1226,7 @@
</div> </div>
</section> </section>
<section v-show="activeStep === 5" class="setup-section"> <section v-show="activeStep === 5" class="setup-section setup-section--table">
<el-table :data="currentSetupDraft.monitoringStrategies" class="ctms-table"> <el-table :data="currentSetupDraft.monitoringStrategies" class="ctms-table">
<el-table-column label="监查类型" min-width="180"> <el-table-column label="监查类型" min-width="180">
<template #default="scope"> <template #default="scope">
@@ -1303,7 +1303,7 @@
</el-table> </el-table>
</section> </section>
<section v-show="activeStep === 6" class="setup-section"> <section v-show="activeStep === 6" class="setup-section setup-section--table">
<el-table :data="centerConfirmDisplayRows" class="ctms-table"> <el-table :data="centerConfirmDisplayRows" class="ctms-table">
<el-table-column label="中心" min-width="180"> <el-table-column label="中心" min-width="180">
<template #default="scope"> <template #default="scope">
@@ -6045,11 +6045,10 @@ onBeforeUnmount(() => {
} }
.setup-shell { .setup-shell {
border: 1px solid #d8e2ef; border: 0;
border-radius: 16px;
background: #ffffff; background: #ffffff;
overflow: hidden; overflow: hidden;
box-shadow: 0 6px 20px rgba(17, 42, 88, 0.05); box-shadow: none;
} }
.setup-header { .setup-header {
@@ -6977,6 +6976,12 @@ onBeforeUnmount(() => {
background: #ffffff; background: #ffffff;
} }
.setup-section--table {
padding-left: 0;
padding-right: 0;
padding-top: 0;
}
.enrollment-plan-section { .enrollment-plan-section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -7207,13 +7212,16 @@ onBeforeUnmount(() => {
.setup-content { .setup-content {
position: relative; position: relative;
padding-left: 0 !important;
padding-right: 0 !important;
padding-bottom: 0 !important;
} }
.setup-content-step-title { .setup-content-step-title {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
padding: 10px 12px; padding: 9px 12px;
font-size: 18px; font-size: 18px;
font-weight: 700; font-weight: 700;
color: #162f57; color: #162f57;
@@ -7473,6 +7481,12 @@ onBeforeUnmount(() => {
margin-bottom: 10px; margin-bottom: 10px;
} }
.setup-section--table .setup-section-header {
margin-bottom: 0;
padding-left: 12px;
padding-right: 12px;
}
.setup-content.setup-content-drawer .setup-section-header { .setup-content.setup-content-drawer .setup-section-header {
padding-bottom: 0; padding-bottom: 0;
margin-bottom: 0; margin-bottom: 0;
@@ -7698,9 +7712,10 @@ onBeforeUnmount(() => {
} }
.setup-section :deep(.el-table th.el-table__cell) { .setup-section :deep(.el-table th.el-table__cell) {
background: #f8fafc !important; background: #f7f9fc !important;
color: #64748b !important; color: #34506f !important;
font-weight: 500 !important; font-weight: 600 !important;
height: 40px;
border-bottom: 1px solid #e2e8f0 !important; border-bottom: 1px solid #e2e8f0 !important;
border-right: none !important; border-right: none !important;
border-left: none !important; border-left: none !important;
@@ -7711,6 +7726,8 @@ onBeforeUnmount(() => {
border-right: none !important; border-right: none !important;
border-left: none !important; border-left: none !important;
background: transparent !important; background: transparent !important;
padding-top: 7px;
padding-bottom: 7px;
} }
/* 覆盖悬停状态颜色,保持极简高级 */ /* 覆盖悬停状态颜色,保持极简高级 */
+22 -5
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <div class="page">
<el-card shadow="never" class="main-content-card unified-shell"> <div class="main-content-flat unified-shell">
<div class="unified-action-bar actions-only-bar"> <div class="unified-action-bar actions-only-bar">
<div class="filter-spacer"></div> <div class="filter-spacer"></div>
<el-button type="primary" @click="openAdd"> <el-button type="primary" @click="openAdd">
@@ -8,7 +8,7 @@
</el-button> </el-button>
</div> </div>
<div class="unified-section member-table-section"> <div class="unified-section member-table-section">
<el-table :data="memberRows" v-loading="loading" stripe> <el-table :data="memberRows" v-loading="loading" stripe class="member-table">
<el-table-column prop="full_name" :label="TEXT.modules.adminProjectMembers.username" min-width="160" /> <el-table-column prop="full_name" :label="TEXT.modules.adminProjectMembers.username" min-width="160" />
<el-table-column prop="role_in_study" :label="TEXT.modules.adminProjectMembers.projectRole" min-width="140"> <el-table-column prop="role_in_study" :label="TEXT.modules.adminProjectMembers.projectRole" min-width="140">
<template #default="scope"> <template #default="scope">
@@ -62,7 +62,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</el-card> </div>
<el-dialog append-to=".layout-main .content-wrapper" :title="TEXT.modules.adminProjectMembers.newTitle" width="520px" v-model="addVisible" :close-on-click-modal="false"> <el-dialog append-to=".layout-main .content-wrapper" :title="TEXT.modules.adminProjectMembers.newTitle" width="520px" v-model="addVisible" :close-on-click-modal="false">
<el-form :model="newMember" label-width="120px" ref="addFormRef" :rules="addRules"> <el-form :model="newMember" label-width="120px" ref="addFormRef" :rules="addRules">
@@ -301,6 +301,20 @@ onMounted(async () => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0;
}
.main-content-flat {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.main-content-flat :deep(.el-card__body) {
padding: 0;
} }
.actions-only-bar { .actions-only-bar {
@@ -310,8 +324,11 @@ onMounted(async () => {
} }
.member-table-section { .member-table-section {
padding-top: 12px; padding: 0;
padding-bottom: 12px; }
.member-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
.hint { .hint {
+24 -7
View File
@@ -1,14 +1,14 @@
<template> <template>
<div class="page"> <div class="page">
<el-card shadow="never" class="main-content-card unified-shell"> <div class="main-content-flat unified-shell">
<div class="unified-action-bar actions-only-bar"> <div class="unified-action-bar actions-only-bar">
<div class="filter-spacer"></div> <div class="filter-spacer"></div>
<el-button type="primary" @click="openCreate"> <el-button type="primary" @click="openCreate">
{{ TEXT.common.actions.add }}{{ TEXT.modules.adminProjects.projectLabel }} {{ TEXT.common.actions.add }}{{ TEXT.modules.adminProjects.projectLabel }}
</el-button> </el-button>
</div> </div>
<div class="unified-section"> <div class="unified-section project-table-section">
<el-table :data="projects" v-loading="loading" stripe> <el-table :data="projects" v-loading="loading" stripe class="project-table">
<el-table-column prop="name" :label="TEXT.common.fields.projectName" min-width="300"> <el-table-column prop="name" :label="TEXT.common.fields.projectName" min-width="300">
<template #default="scope"> <template #default="scope">
<el-link type="primary" @click="goDetail(scope.row)" class="font-medium">{{ scope.row.name }}</el-link> <el-link type="primary" @click="goDetail(scope.row)" class="font-medium">{{ scope.row.name }}</el-link>
@@ -57,7 +57,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</el-card> </div>
<ProjectForm v-model:visible="formVisible" :project="editingProject" @saved="loadProjects" /> <ProjectForm v-model:visible="formVisible" :project="editingProject" @saved="loadProjects" />
</div> </div>
</template> </template>
@@ -219,6 +219,20 @@ onMounted(() => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0;
}
.main-content-flat {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.main-content-flat :deep(.el-card__body) {
padding: 0;
} }
.actions-only-bar { .actions-only-bar {
@@ -227,9 +241,12 @@ onMounted(() => {
align-items: center; align-items: center;
} }
.unified-section { .project-table-section {
padding-top: 12px; padding: 0;
padding-bottom: 12px; }
.project-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
.action-btn { .action-btn {
+7 -8
View File
@@ -1,14 +1,14 @@
<template> <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="unified-action-bar actions-only-bar"> <div class="unified-action-bar actions-only-bar">
<div class="filter-spacer"></div> <div class="filter-spacer"></div>
<el-button type="primary" @click="openCreate"> <el-button type="primary" @click="openCreate">
{{ TEXT.common.actions.add }}{{ TEXT.modules.adminSites.siteLabel }} {{ TEXT.common.actions.add }}{{ TEXT.modules.adminSites.siteLabel }}
</el-button> </el-button>
</div> </div>
<div class="unified-section site-table-section"> <div class="unified-section site-table-section section--flush-x section--flush-top section--flush-bottom">
<el-table :data="displaySites" v-loading="loading" stripe :row-class-name="siteRowClass" style="width: 100%"> <el-table :data="displaySites" v-loading="loading" stripe :row-class-name="siteRowClass" style="width: 100%" class="site-table">
<el-table-column prop="name" :label="TEXT.common.fields.siteName" min-width="220"> <el-table-column prop="name" :label="TEXT.common.fields.siteName" min-width="220">
<template #default="scope"> <template #default="scope">
<div class="site-name-cell"> <div class="site-name-cell">
@@ -61,7 +61,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</el-card> </div>
<SiteForm <SiteForm
v-if="projectId" v-if="projectId"
v-model:visible="formVisible" v-model:visible="formVisible"
@@ -278,9 +278,8 @@ onMounted(async () => {
align-items: center; align-items: center;
} }
.site-table-section { .site-table :deep(.el-table__inner-wrapper::before) {
padding-top: 12px; display: none;
padding-bottom: 12px;
} }
.site-name-cell { .site-name-cell {
+38 -6
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <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"> <div class="filter-container unified-action-bar">
<div class="filter-form"> <div class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
@@ -28,7 +28,7 @@
</div> </div>
<div class="unified-section user-table-section"> <div class="unified-section user-table-section">
<el-table :data="users" stripe v-loading="loading" style="width: 100%"> <el-table :data="users" stripe v-loading="loading" class="user-table" style="width: 100%">
<el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" /> <el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" /> <el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" />
<el-table-column prop="department" :label="TEXT.common.fields.department" min-width="140" /> <el-table-column prop="department" :label="TEXT.common.fields.department" min-width="140" />
@@ -84,7 +84,7 @@
/> />
</div> </div>
</div> </div>
</el-card> </div>
<UserForm v-model:visible="formVisible" :user="editingUser" :admin-count="activeAdminCount" @saved="loadUsers" /> <UserForm v-model:visible="formVisible" :user="editingUser" :admin-count="activeAdminCount" @saved="loadUsers" />
<UserResetPassword v-model:visible="resetVisible" :user="resetUser" @reset="loadUsers" /> <UserResetPassword v-model:visible="resetVisible" :user="resetUser" @reset="loadUsers" />
</div> </div>
@@ -291,12 +291,26 @@ onMounted(() => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0;
}
.main-content-flat {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.main-content-flat :deep(.el-card__body) {
padding: 0;
} }
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 10px;
align-items: center; align-items: center;
} }
@@ -306,7 +320,7 @@ onMounted(() => {
} }
.filter-input-comp { .filter-input-comp {
width: 200px; width: 190px;
} }
.filter-spacer { .filter-spacer {
@@ -314,13 +328,31 @@ onMounted(() => {
} }
.user-table-section { .user-table-section {
padding: 0;
}
.user-table {
margin-top: 0;
}
.user-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.user-table :deep(th.el-table__cell) {
padding-top: 10px;
padding-bottom: 10px;
}
.user-table :deep(td.el-table__cell) {
padding-top: 12px; padding-top: 12px;
padding-bottom: 12px; padding-bottom: 12px;
} }
.pagination-wrap { .pagination-wrap {
margin-top: 14px; margin-top: 10px;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
padding: 0 0 6px;
} }
</style> </style>
@@ -1,7 +1,7 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell page--flush">
<div class="unified-shell"> <div class="unified-shell">
<section class="unified-section" v-loading="loading"> <section class="unified-section section--flush-x" v-loading="loading">
<div class="unified-section-header"> <div class="unified-section-header">
<div> <div>
<div class="ctms-section-title"> <div class="ctms-section-title">
@@ -37,7 +37,7 @@
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section section--flush-x section--flush-bottom">
<el-tabs v-model="activeTab" @tab-change="handleTabChange" class="ctms-tabs"> <el-tabs v-model="activeTab" @tab-change="handleTabChange" class="ctms-tabs">
<el-tab-pane :label="TEXT.modules.fileVersionManagement.tabs.versions" name="versions"> <el-tab-pane :label="TEXT.modules.fileVersionManagement.tabs.versions" name="versions">
<div class="ctms-section-header"> <div class="ctms-section-header">
@@ -49,7 +49,7 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<el-card class="ctms-table-card unified-shell"> <div class="ctms-table-panel">
<el-table :data="detail.version_timeline" v-loading="versionLoading" class="ctms-table"> <el-table :data="detail.version_timeline" v-loading="versionLoading" class="ctms-table">
<el-table-column prop="version_no" :label="TEXT.modules.fileVersionManagement.fields.versionNo" width="120"> <el-table-column prop="version_no" :label="TEXT.modules.fileVersionManagement.fields.versionNo" width="120">
<template #default="{ row }"> <template #default="{ row }">
@@ -94,7 +94,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-card> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="TEXT.modules.fileVersionManagement.tabs.distributions" name="distributions"> <el-tab-pane :label="TEXT.modules.fileVersionManagement.tabs.distributions" name="distributions">
@@ -107,7 +107,7 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<el-card class="ctms-table-card unified-shell"> <div class="ctms-table-panel">
<el-table :data="distributions" v-loading="distributionLoading" class="ctms-table"> <el-table :data="distributions" v-loading="distributionLoading" class="ctms-table">
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.targetType" width="120"> <el-table-column :label="TEXT.modules.fileVersionManagement.fields.targetType" width="120">
<template #default="{ row }"> <template #default="{ row }">
@@ -125,7 +125,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-card> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@@ -680,6 +680,18 @@ watch(
gap: 0; gap: 0;
} }
.ctms-table-panel {
padding: 0;
}
.ctms-section-header {
margin-bottom: 0;
}
.ctms-table-panel :deep(.el-table__inner-wrapper::before) {
display: none;
}
.doc-meta-row { .doc-meta-row {
display: flex; display: flex;
align-items: center; align-items: center;
+10 -14
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell 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"> <div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
<el-select v-model="filters.scope_type" :placeholder="TEXT.modules.fileVersionManagement.filters.scope" clearable class="filter-select-comp"> <el-select v-model="filters.scope_type" :placeholder="TEXT.modules.fileVersionManagement.filters.scope" clearable class="filter-select-comp">
@@ -28,7 +28,7 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<section class="unified-section"> <section class="unified-section document-table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="sortedItems" :data="sortedItems"
v-loading="loading" v-loading="loading"
@@ -84,7 +84,7 @@
</template> </template>
</el-table> </el-table>
</section> </section>
</el-card> </div>
<el-dialog append-to=".layout-main .content-wrapper" v-model="createVisible" :title="TEXT.modules.fileVersionManagement.dialog.createTitle" width="520px" destroy-on-close class="ctms-dialog"> <el-dialog append-to=".layout-main .content-wrapper" v-model="createVisible" :title="TEXT.modules.fileVersionManagement.dialog.createTitle" width="520px" destroy-on-close class="ctms-dialog">
<el-form ref="createFormRef" :model="createForm" :rules="createRules" label-width="100px" class="ctms-form"> <el-form ref="createFormRef" :model="createForm" :rules="createRules" label-width="100px" class="ctms-form">
@@ -346,18 +346,10 @@ watch(
gap: 0; gap: 0;
} }
.main-content-card :deep(.el-card__body) {
padding: 0;
}
.filter-container {
margin-bottom: 0;
}
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -370,6 +362,10 @@ watch(
width: 132px; width: 132px;
} }
.ctms-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.filter-spacer { .filter-spacer {
flex: 1; flex: 1;
} }
+5 -1
View File
@@ -36,7 +36,7 @@
<el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item> <el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section attachment-section">
<AttachmentList <AttachmentList
v-if="shipmentId" v-if="shipmentId"
:study-id="studyId" :study-id="studyId"
@@ -109,6 +109,10 @@ onMounted(load);
gap: 0; gap: 0;
} }
.attachment-section {
padding: 0;
}
.section-title-row { .section-title-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -251,6 +251,10 @@ onMounted(async () => {
overflow: hidden; overflow: hidden;
} }
.section-card :deep(.el-card__body) {
padding: 0;
}
.card-header { .card-header {
padding: 4px 0; padding: 4px 0;
} }
+5 -1
View File
@@ -88,7 +88,7 @@
</el-row> </el-row>
</el-card> </el-card>
<el-card class="form-card section-margin unified-shell" shadow="never"> <el-card class="form-card section-margin attachment-card unified-shell" shadow="never">
<template #header> <template #header>
<div class="card-header actions-header"> <div class="card-header actions-header">
<span class="header-title">{{ TEXT.modules.feeContracts.paymentTitle }}</span> <span class="header-title">{{ TEXT.modules.feeContracts.paymentTitle }}</span>
@@ -517,6 +517,10 @@ onMounted(async () => {
margin-top: 24px; margin-top: 24px;
} }
.attachment-card :deep(.el-card__body) {
padding: 0;
}
.card-header { .card-header {
padding: 4px 0; padding: 4px 0;
} }
+10 -16
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<div class="overview"> <div class="overview">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="6"> <el-col :xs="24" :sm="12" :md="6">
@@ -53,7 +53,7 @@
<StateLoading v-else-if="loading" :rows="6" /> <StateLoading v-else-if="loading" :rows="6" />
<el-card shadow="never" class="main-content-card unified-shell" v-else> <div class="main-content-flat unified-shell" v-else>
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item"> <el-form-item label="" class="filter-item">
@@ -86,13 +86,13 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<section class="unified-section"> <section class="unified-section contract-table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="sortedContracts" :data="sortedContracts"
style="width: 100%" style="width: 100%"
@row-click="onRowClick" @row-click="onRowClick"
:row-class-name="contractRowClass" :row-class-name="contractRowClass"
:header-cell-style="{ background: '#f8f9fb' }" class="contract-table"
> >
<el-table-column prop="center_name" :label="TEXT.common.fields.site" min-width="160"> <el-table-column prop="center_name" :label="TEXT.common.fields.site" min-width="160">
<template #default="scope"> <template #default="scope">
@@ -167,7 +167,7 @@
</el-table> </el-table>
<StateEmpty v-if="sortedContracts.length === 0" :description="TEXT.modules.feeContracts.empty" /> <StateEmpty v-if="sortedContracts.length === 0" :description="TEXT.modules.feeContracts.empty" />
</section> </section>
</el-card> </div>
</div> </div>
</template> </template>
@@ -350,18 +350,14 @@ onMounted(async () => {
gap: 0; gap: 0;
} }
.main-content-card :deep(.el-card__body) { .overview {
padding: 0; margin: 0;
}
.filter-container {
margin-bottom: 0;
} }
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -383,10 +379,8 @@ onMounted(async () => {
flex: 1; flex: 1;
} }
.table-card { .contract-table :deep(.el-table__inner-wrapper::before) {
border-radius: 12px; display: none;
border: 1px solid var(--ctms-border-color);
overflow: hidden;
} }
.site-cell { .site-cell {
@@ -233,6 +233,10 @@ onMounted(async () => {
overflow: hidden; overflow: hidden;
} }
.section-card :deep(.el-card__body) {
padding: 0;
}
.card-header { .card-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -56,7 +56,7 @@
</el-row> </el-row>
</el-card> </el-card>
<el-card class="form-card section-margin unified-shell" shadow="never"> <el-card class="form-card section-margin attachment-card unified-shell" shadow="never">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span class="header-title">{{ TEXT.common.fields.status }}</span> <span class="header-title">{{ TEXT.common.fields.status }}</span>
@@ -394,6 +394,10 @@ onMounted(async () => {
margin-top: 24px; margin-top: 24px;
} }
.attachment-card :deep(.el-card__body) {
padding: 0;
}
.card-header { .card-header {
padding: 4px 0; padding: 4px 0;
} }
+10 -16
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<div class="overview"> <div class="overview">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="6"> <el-col :xs="24" :sm="12" :md="6">
@@ -52,7 +52,7 @@
<StateLoading v-else-if="loading" :rows="6" /> <StateLoading v-else-if="loading" :rows="6" />
<el-card shadow="never" class="main-content-card unified-shell" v-else> <div class="main-content-flat unified-shell" v-else>
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item"> <el-form-item label="" class="filter-item">
@@ -97,13 +97,13 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<section class="unified-section"> <section class="unified-section special-expense-table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="sortedExpenses" :data="sortedExpenses"
style="width: 100%" style="width: 100%"
@row-click="onRowClick" @row-click="onRowClick"
:header-cell-style="{ background: '#f8f9fb' }"
:row-class-name="expenseRowClass" :row-class-name="expenseRowClass"
class="special-expense-table"
> >
<el-table-column :label="TEXT.common.fields.occurDate" width="140"> <el-table-column :label="TEXT.common.fields.occurDate" width="140">
<template #default="scope"> <template #default="scope">
@@ -166,7 +166,7 @@
</el-table> </el-table>
<StateEmpty v-if="sortedExpenses.length === 0" :description="TEXT.modules.feeSpecials.empty" /> <StateEmpty v-if="sortedExpenses.length === 0" :description="TEXT.modules.feeSpecials.empty" />
</section> </section>
</el-card> </div>
</div> </div>
</template> </template>
@@ -355,18 +355,14 @@ onMounted(async () => {
gap: 0; gap: 0;
} }
.main-content-card :deep(.el-card__body) { .overview {
padding: 0; margin: 0;
}
.filter-container {
margin-bottom: 0;
} }
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -391,10 +387,8 @@ onMounted(async () => {
flex: 1; flex: 1;
} }
.table-card { .special-expense-table :deep(.el-table__inner-wrapper::before) {
border-radius: 12px; display: none;
border: 1px solid var(--ctms-border-color);
overflow: hidden;
} }
.date-text { .date-text {
@@ -19,7 +19,7 @@
<el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item> <el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section attachment-section">
<AttachmentList <AttachmentList
v-if="contractId" v-if="contractId"
:study-id="studyId" :study-id="studyId"
@@ -113,4 +113,8 @@ onMounted(async () => {
flex-direction: column; flex-direction: column;
gap: 0; gap: 0;
} }
.attachment-section {
padding: 0;
}
</style> </style>
+5 -1
View File
@@ -18,7 +18,7 @@
<el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item> <el-descriptions-item :label="TEXT.common.fields.remark" :span="2">{{ detail.remark || TEXT.common.fallback }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section attachment-section">
<AttachmentList <AttachmentList
v-if="specialId" v-if="specialId"
:study-id="studyId" :study-id="studyId"
@@ -112,4 +112,8 @@ onMounted(async () => {
flex-direction: column; flex-direction: column;
gap: 0; gap: 0;
} }
.attachment-section {
padding: 0;
}
</style> </style>
+12 -12
View File
@@ -1,7 +1,7 @@
<template> <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"> <div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item"> <el-form-item label="" class="filter-item">
@@ -48,11 +48,12 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<div class="unified-section table-section"> <div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="sortedItems" :data="sortedItems"
v-loading="loading" v-loading="loading"
style="width: 100%" style="width: 100%"
class="shipment-table"
:row-class-name="shipmentRowClass" :row-class-name="shipmentRowClass"
@row-click="onRowClick" @row-click="onRowClick"
> >
@@ -104,7 +105,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.drugShipments.empty" /> <StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.drugShipments.empty" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -252,7 +253,7 @@ onMounted(async () => {
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -271,10 +272,10 @@ onMounted(async () => {
} }
.filter-actions :deep(.el-button) { .filter-actions :deep(.el-button) {
height: 36px; height: 32px;
line-height: 36px; line-height: 32px;
padding: 0 18px; padding: 0 12px;
border-radius: 8px; border-radius: 10px;
} }
.filter-select { .filter-select {
@@ -285,9 +286,8 @@ onMounted(async () => {
flex: 1; flex: 1;
} }
.table-section { .shipment-table :deep(.el-table__inner-wrapper::before) {
padding-top: 12px; display: none;
padding-bottom: 12px;
} }
.type-tag { .type-tag {
@@ -1,10 +1,10 @@
<template> <template>
<div class="redirecting ctms-page-shell"> <div class="redirecting ctms-page-shell page--flush">
<section class="unified-action-bar"> <section class="unified-action-bar bar--flush">
<div class="redirecting-title">{{ TEXT.menu.fileVersionManagement }}</div> <div class="redirecting-title">{{ TEXT.menu.fileVersionManagement }}</div>
</section> </section>
<section class="unified-shell"> <section class="unified-shell">
<section class="unified-section"> <section class="unified-section section--flush">
<el-empty :description="`${TEXT.common.loading}...`" /> <el-empty :description="`${TEXT.common.loading}...`" />
</section> </section>
</section> </section>
+17 -5
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <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"> <div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
@@ -70,7 +70,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeContracts.empty" /> <StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeContracts.empty" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -185,10 +185,18 @@ onMounted(async () => {
flex-direction: column; flex-direction: column;
} }
.main-content-flat {
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -206,8 +214,12 @@ onMounted(async () => {
} }
.table-section { .table-section {
padding-top: 12px; padding-top: 0;
padding-bottom: 12px; padding-bottom: 0;
}
.ctms-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
+17 -5
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <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"> <div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
@@ -80,7 +80,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeSpecials.empty" /> <StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.financeSpecials.empty" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -194,10 +194,18 @@ onMounted(async () => {
flex-direction: column; flex-direction: column;
} }
.main-content-flat {
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
padding: 0;
}
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -219,8 +227,12 @@ onMounted(async () => {
} }
.table-section { .table-section {
padding-top: 12px; padding-top: 0;
padding-bottom: 12px; padding-bottom: 0;
}
:deep(.ctms-table .el-table__inner-wrapper::before) {
display: none;
} }
</style> </style>
+8 -9
View File
@@ -1,8 +1,8 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell 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"> <div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
<el-input <el-input
@@ -29,7 +29,7 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<div class="unified-section table-section"> <div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="sortedItems" :data="sortedItems"
v-loading="loading" v-loading="loading"
@@ -60,7 +60,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.knowledgeNotes.empty" /> <StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.knowledgeNotes.empty" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -178,7 +178,7 @@ onMounted(async () => {
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -195,9 +195,8 @@ onMounted(async () => {
flex: 1; flex: 1;
} }
.table-section { :deep(.ctms-table .el-table__inner-wrapper::before) {
padding-top: 12px; display: none;
padding-bottom: 12px;
} }
</style> </style>
+9 -10
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="page"> <div class="page page--flush">
<div v-if="study.currentStudy" class="unified-shell"> <div v-if="study.currentStudy" class="unified-shell">
<section class="unified-section equipment-section"> <section class="unified-section section--flush">
<div class="filter-row"> <div class="filter-row">
<el-form :inline="true" :model="filters"> <el-form :inline="true" :model="filters">
<el-form-item label="设备名称"> <el-form-item label="设备名称">
@@ -15,7 +15,7 @@
<el-button type="primary" @click="openCreate">新建</el-button> <el-button type="primary" @click="openCreate">新建</el-button>
</div> </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="name" label="设备名称" />
<el-table-column prop="specModel" label="规格型号" /> <el-table-column prop="specModel" label="规格型号" />
<el-table-column prop="unit" label="单位" /> <el-table-column prop="unit" label="单位" />
@@ -391,11 +391,6 @@ watch(
flex-direction: column; flex-direction: column;
} }
.equipment-section {
padding-top: 14px;
padding-bottom: 12px;
}
.filter-row { .filter-row {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -593,9 +588,13 @@ watch(
padding-bottom: 4px; padding-bottom: 4px;
} }
.equipment-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
/* ========== 表格居中 ========== */ /* ========== 表格居中 ========== */
:deep(.ctms-table th.el-table__cell .cell), .equipment-table :deep(th.el-table__cell .cell),
:deep(.ctms-table td.el-table__cell .cell) { .equipment-table :deep(td.el-table__cell .cell) {
text-align: center; text-align: center;
} }
</style> </style>
+10 -11
View File
@@ -1,7 +1,7 @@
<template> <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"> <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 class="card-header ctms-page-header-row">
<div> <div>
<div class="card-title">{{ TEXT.modules.projectMilestones.listTitle }}</div> <div class="card-title">{{ TEXT.modules.projectMilestones.listTitle }}</div>
@@ -22,7 +22,7 @@
</div> </div>
</div> </div>
</section> </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 :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="name" :label="TEXT.modules.projectMilestones.columns.name" min-width="140" />
<el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate" min-width="170"> <el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate" min-width="170">
@@ -450,12 +450,16 @@ watch(
flex-direction: column; flex-direction: column;
} }
.ctms-page-content-grid {
gap: 0;
}
.card-header { .card-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 12px; gap: 12px;
margin-bottom: 12px; margin-bottom: 0;
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -657,12 +661,7 @@ watch(
background: #94a3b8; background: #94a3b8;
} }
:deep(.ctms-table th.el-table__cell .cell), .ctms-table :deep(.el-table__inner-wrapper::before) {
:deep(.ctms-table td.el-table__cell .cell) { display: none;
font-size: 11px;
padding-top: 4px;
padding-bottom: 4px;
padding-left: 6px;
padding-right: 6px;
} }
</style> </style>
+1 -51
View File
@@ -1,21 +1,7 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<div v-if="study.currentStudy" class="page-body"> <div v-if="study.currentStudy" class="page-body">
<div class="unified-shell ctms-table-card"> <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"> <section class="unified-section">
<div class="overview-meta-inline"> <div class="overview-meta-inline">
<el-tag v-if="usingDemo" effect="plain" type="info" class="demo-tag">示例数据</el-tag> <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 { fetchSites } from "../../api/sites";
import StateEmpty from "../../components/StateEmpty.vue"; import StateEmpty from "../../components/StateEmpty.vue";
import StateLoading from "../../components/StateLoading.vue"; import StateLoading from "../../components/StateLoading.vue";
import KpiCard from "../../components/KpiCard.vue";
import CenterProgressRow from "./project-overview/CenterProgressRow.vue"; import CenterProgressRow from "./project-overview/CenterProgressRow.vue";
import EnrollmentBarChart, { type EnrollmentBarItem } from "./project-overview/EnrollmentBarChart.vue"; import EnrollmentBarChart, { type EnrollmentBarItem } from "./project-overview/EnrollmentBarChart.vue";
import { adaptProjectOverview, type CenterOverview, type ProjectOverviewViewModel } from "./project-overview/overview.adapter"; 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 preferApi = String(import.meta.env.VITE_USE_OVERVIEW_API || "").toLowerCase() === "true";
const centers = computed(() => overview.value?.centers || []); 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[] => const buildFallbackCentersFromSites = (siteList: any[]): CenterOverview[] =>
siteList.map((site: any) => ({ siteList.map((site: any) => ({
@@ -252,12 +208,6 @@ watch(
gap: 0; gap: 0;
} }
.kpi-grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.demo-tag { .demo-tag {
border-color: var(--ctms-border-color); border-color: var(--ctms-border-color);
color: var(--ctms-text-secondary); color: var(--ctms-text-secondary);
@@ -1,8 +1,8 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<template v-if="study.currentStudy"> <template v-if="study.currentStudy">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card"> <div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar bar--flush">
<div class="filter-left"> <div class="filter-left">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="问题分类" class="filter-item"> <el-form-item label="问题分类" class="filter-item">
@@ -47,7 +47,7 @@
</div> </div>
</div> </div>
<div class="unified-section table-section"> <div class="unified-section table-section section--flush">
<el-table <el-table
class="issue-table" class="issue-table"
:data="tableRows" :data="tableRows"
@@ -113,7 +113,7 @@
/> />
</div> </div>
</div> </div>
</el-card> </div>
<el-drawer <el-drawer
v-model="formDialogVisible" v-model="formDialogVisible"
@@ -723,7 +723,6 @@ watch(
justify-content: space-between; justify-content: space-between;
gap: 16px; gap: 16px;
flex-wrap: wrap; flex-wrap: wrap;
padding: 16px 16px 0;
} }
.filter-left { .filter-left {
@@ -734,7 +733,7 @@ watch(
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -764,10 +763,6 @@ watch(
gap: 8px; gap: 8px;
} }
.table-section {
padding: 12px 0;
}
.issue-no { .issue-no {
font-weight: 600; font-weight: 600;
color: #24324a; color: #24324a;
@@ -823,11 +818,15 @@ watch(
} }
.pagination-wrap { .pagination-wrap {
margin: 14px 16px 0; margin: 10px 0 0;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
} }
.issue-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.dialog-select { .dialog-select {
width: 100%; width: 100%;
} }
+12 -13
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card"> <div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" class="filter-form"> <el-form :inline="true" class="filter-form">
<el-form-item class="filter-item-form"> <el-form-item class="filter-item-form">
<el-input v-model="filters.keyword" :placeholder="TEXT.common.fields.keyword" clearable class="filter-input-comp"> <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-item>
</el-form> </el-form>
</div> </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="filteredItems" v-loading="loading" style="width: 100%" table-layout="fixed"> <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="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 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> <el-table-column :label="TEXT.common.fields.site" min-width="160" show-overflow-tooltip>
@@ -54,7 +54,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssuePd.emptyDescription" /> <StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssuePd.emptyDescription" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -162,21 +162,16 @@ onMounted(load);
flex-direction: column; flex-direction: column;
} }
.table-section {
padding-top: 12px;
padding-bottom: 12px;
}
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
flex-wrap: wrap; flex-wrap: wrap;
gap: 0; gap: 8px;
} }
.filter-item-form { .filter-item-form {
margin-bottom: 0; margin-bottom: 0;
margin-right: 12px; margin-right: 0;
} }
.filter-input-comp { .filter-input-comp {
@@ -191,4 +186,8 @@ onMounted(load);
margin-bottom: 0; margin-bottom: 0;
margin-right: 0; margin-right: 0;
} }
.risk-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style> </style>
+12 -13
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card"> <div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" class="filter-form"> <el-form :inline="true" class="filter-form">
<el-form-item class="filter-item-form"> <el-form-item class="filter-item-form">
<el-input v-model="filters.keyword" :placeholder="TEXT.common.fields.keyword" clearable class="filter-input-comp"> <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-item>
</el-form> </el-form>
</div> </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="filteredItems" v-loading="loading" style="width: 100%"> <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"> <el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140">
<template #default="scope">{{ displayDate(scope.row.onset_date) }}</template> <template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
</el-table-column> </el-table-column>
@@ -82,7 +82,7 @@
</el-table> </el-table>
<StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssueSae.emptyDescription" /> <StateEmpty v-if="!loading && filteredItems.length === 0" :description="TEXT.modules.riskIssueSae.emptyDescription" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -219,21 +219,16 @@ onMounted(load);
flex-direction: column; flex-direction: column;
} }
.table-section {
padding-top: 12px;
padding-bottom: 12px;
}
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
flex-wrap: wrap; flex-wrap: wrap;
gap: 0; gap: 8px;
} }
.filter-item-form { .filter-item-form {
margin-bottom: 0; margin-bottom: 0;
margin-right: 12px; margin-right: 0;
} }
.filter-input-comp { .filter-input-comp {
@@ -248,4 +243,8 @@ onMounted(load);
margin-bottom: 0; margin-bottom: 0;
margin-right: 0; margin-right: 0;
} }
.risk-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style> </style>
@@ -1,9 +1,9 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell page--flush">
<el-card shadow="never" class="main-content-card unified-shell"> <div class="main-content-flat unified-shell">
<el-tabs v-model="activeTab" class="ctms-tabs"> <el-tabs v-model="activeTab" class="ctms-tabs">
<el-tab-pane :label="TEXT.modules.startupFeasibilityEthics.feasibilityTab" name="feasibility"> <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-header">
<div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.feasibilityTab }}</div> <div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.feasibilityTab }}</div>
<div class="ctms-section-actions"> <div class="ctms-section-actions">
@@ -63,7 +63,7 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="TEXT.modules.startupFeasibilityEthics.ethicsTab" name="ethics"> <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-header">
<div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.ethicsTab }}</div> <div class="ctms-section-title">{{ TEXT.modules.startupFeasibilityEthics.ethicsTab }}</div>
<div class="ctms-section-actions"> <div class="ctms-section-actions">
@@ -126,7 +126,7 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-card> </div>
</div> </div>
</template> </template>
@@ -312,7 +312,15 @@ onMounted(() => {
} }
.ctms-tab-content { .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> </style>
+7 -3
View File
@@ -1,12 +1,12 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell page--flush">
<div class="unified-shell"> <div class="unified-shell">
<section class="unified-section"> <section class="unified-section kickoff-table-section section--flush">
<el-table <el-table
:data="kickoffRows" :data="kickoffRows"
v-loading="loading" v-loading="loading"
style="width: 100%" style="width: 100%"
class="ctms-table" class="ctms-table kickoff-table"
:row-class-name="kickoffRowClass" :row-class-name="kickoffRowClass"
@row-click="onKickoffRowClick" @row-click="onKickoffRowClick"
> >
@@ -166,6 +166,10 @@ onMounted(() => {
gap: 0; gap: 0;
} }
.kickoff-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
</style> </style>
<style> <style>
+14 -10
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="page ctms-page-shell"> <div class="page ctms-page-shell page--flush">
<el-card shadow="never" class="main-content-card unified-shell ctms-table-card"> <div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar"> <div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form"> <el-form :inline="true" :model="filters" class="filter-form">
<el-form-item label="" class="filter-item-form"> <el-form-item label="" class="filter-item-form">
<el-input <el-input
@@ -54,7 +54,7 @@
</el-button> </el-button>
</el-form> </el-form>
</div> </div>
<div class="unified-section table-section"> <div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table <el-table
:data="pagedItems" :data="pagedItems"
v-loading="loading" v-loading="loading"
@@ -118,7 +118,7 @@
</div> </div>
<StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.subjectManagement.empty" /> <StateEmpty v-if="!loading && sortedItems.length === 0" :description="TEXT.modules.subjectManagement.empty" />
</div> </div>
</el-card> </div>
</div> </div>
</template> </template>
@@ -281,7 +281,7 @@ onMounted(async () => {
.filter-form { .filter-form {
display: flex; display: flex;
width: 100%; width: 100%;
gap: 12px; gap: 8px;
align-items: center; align-items: center;
} }
@@ -300,9 +300,13 @@ onMounted(async () => {
} }
.header-action-btn { .header-action-btn {
height: 36px; height: 32px;
padding: 0 20px; padding: 0 12px;
border-radius: 8px; border-radius: 10px;
}
:deep(.ctms-table .el-table__inner-wrapper::before) {
display: none;
} }
.subject-info-cell { .subject-info-cell {
@@ -358,7 +362,7 @@ onMounted(async () => {
.pagination-wrap { .pagination-wrap {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-top: 14px; margin-top: 10px;
} }
</style> </style>
+13 -1
View File
@@ -26,7 +26,7 @@
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section attachment-section">
<AttachmentList <AttachmentList
v-if="recordId" v-if="recordId"
:study-id="studyId" :study-id="studyId"
@@ -156,6 +156,18 @@ onMounted(() => {
}); });
</script> </script>
<style scoped>
.page {
display: flex;
flex-direction: column;
gap: 0;
}
.attachment-section {
padding: 0;
}
</style>
<style scoped> <style scoped>
.page { .page {
display: flex; display: flex;
@@ -25,7 +25,7 @@
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section attachment-section">
<AttachmentList <AttachmentList
v-if="recordId" v-if="recordId"
:study-id="studyId" :study-id="studyId"
@@ -154,6 +154,18 @@ onMounted(() => {
}); });
</script> </script>
<style scoped>
.page {
display: flex;
flex-direction: column;
gap: 0;
}
.attachment-section {
padding: 0;
}
</style>
<style scoped> <style scoped>
.page { .page {
display: flex; display: flex;
+12 -2
View File
@@ -41,7 +41,7 @@
</el-descriptions> </el-descriptions>
</section> </section>
<section class="unified-section"> <section class="unified-section training-section">
<div class="training-header"> <div class="training-header">
<div class="training-title">{{ TEXT.modules.startupMeetingAuth.trainingTab }}</div> <div class="training-title">{{ TEXT.modules.startupMeetingAuth.trainingTab }}</div>
</div> </div>
@@ -126,7 +126,7 @@
/> />
</section> </section>
<section v-if="meetingId" class="unified-section"> <section v-if="meetingId" class="unified-section attachment-section">
<div class="attachment-grid"> <div class="attachment-grid">
<AttachmentList <AttachmentList
v-for="group in kickoffAttachmentGroups" v-for="group in kickoffAttachmentGroups"
@@ -448,6 +448,16 @@ onMounted(async () => {
gap: 0; gap: 0;
} }
.training-section,
.attachment-section {
padding-left: 0;
padding-right: 0;
}
.training-section {
padding-top: 0;
}
.training-header { .training-header {
display: flex; display: flex;
align-items: center; align-items: center;
+24 -10
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <div class="page ctms-page-shell page--flush">
<div class="page-header unified-action-bar"> <div class="page-header unified-action-bar bar--flush">
<div> <div>
<h1 class="page-title">{{ detail.subject_no || TEXT.modules.subjectManagement.screeningNo }}</h1> <h1 class="page-title">{{ detail.subject_no || TEXT.modules.subjectManagement.screeningNo }}</h1>
<p class="page-subtitle">{{ TEXT.modules.subjectManagement.screeningNo }}</p> <p class="page-subtitle">{{ TEXT.modules.subjectManagement.screeningNo }}</p>
@@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<el-card class="unified-shell" v-loading="loading"> <el-card class="unified-shell subject-shell" v-loading="loading">
<el-descriptions :column="2" border> <el-descriptions :column="2" border>
<el-descriptions-item :label="TEXT.modules.subjectManagement.screeningNo">{{ detail.subject_no || TEXT.common.fallback }}</el-descriptions-item> <el-descriptions-item :label="TEXT.modules.subjectManagement.screeningNo">{{ detail.subject_no || TEXT.common.fallback }}</el-descriptions-item>
<el-descriptions-item :label="TEXT.common.fields.site">{{ siteMap[detail.site_id] || TEXT.common.fallback }}</el-descriptions-item> <el-descriptions-item :label="TEXT.common.fields.site">{{ siteMap[detail.site_id] || TEXT.common.fallback }}</el-descriptions-item>
@@ -76,7 +76,7 @@
</el-descriptions> </el-descriptions>
</el-card> </el-card>
<el-card class="unified-shell"> <el-card class="unified-shell subject-shell">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">
<el-tab-pane :label="TEXT.modules.subjectDetail.tabs.history" name="history"> <el-tab-pane :label="TEXT.modules.subjectDetail.tabs.history" name="history">
<div class="tab-actions"> <div class="tab-actions">
@@ -84,7 +84,7 @@
{{ TEXT.common.actions.newHistory }} {{ TEXT.common.actions.newHistory }}
</el-button> </el-button>
</div> </div>
<el-table :data="historyItems" v-loading="loadingHistory" style="width: 100%"> <el-table :data="historyItems" v-loading="loadingHistory" style="width: 100%" class="subject-detail-table">
<el-table-column prop="record_date" :label="TEXT.common.fields.recordDate" width="140"> <el-table-column prop="record_date" :label="TEXT.common.fields.recordDate" width="140">
<template #default="scope">{{ displayDate(scope.row.record_date) }}</template> <template #default="scope">{{ displayDate(scope.row.record_date) }}</template>
</el-table-column> </el-table-column>
@@ -121,7 +121,7 @@
{{ TEXT.common.actions.newVisit }} {{ TEXT.common.actions.newVisit }}
</el-button> </el-button>
</div> </div>
<el-table :data="visitItems" v-loading="loadingVisits" style="width: 100%"> <el-table :data="visitItems" v-loading="loadingVisits" style="width: 100%" class="subject-detail-table">
<el-table-column prop="visit_code" :label="TEXT.common.fields.visitCode" width="120" /> <el-table-column prop="visit_code" :label="TEXT.common.fields.visitCode" width="120" />
<el-table-column prop="planned_date" :label="TEXT.common.fields.plannedDate" min-width="180"> <el-table-column prop="planned_date" :label="TEXT.common.fields.plannedDate" min-width="180">
<template #default="scope">{{ displayDate(scope.row.planned_date) }}</template> <template #default="scope">{{ displayDate(scope.row.planned_date) }}</template>
@@ -202,7 +202,7 @@
{{ TEXT.common.actions.newAe }} {{ TEXT.common.actions.newAe }}
</el-button> </el-button>
</div> </div>
<el-table :data="aeItems" v-loading="loadingAes" style="width: 100%"> <el-table :data="aeItems" v-loading="loadingAes" style="width: 100%" class="subject-detail-table">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140"> <el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140">
<template #default="scope">{{ displayDate(scope.row.onset_date) }}</template> <template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
</el-table-column> </el-table-column>
@@ -258,7 +258,7 @@
{{ TEXT.modules.subjectDetail.newPd }} {{ TEXT.modules.subjectDetail.newPd }}
</el-button> </el-button>
</div> </div>
<el-table :data="pdItems" v-loading="loadingPds" style="width: 100%"> <el-table :data="pdItems" v-loading="loadingPds" style="width: 100%" class="subject-detail-table">
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" width="130" /> <el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" width="130" />
<el-table-column prop="pd_type" :label="TEXT.common.fields.pdType" min-width="140" /> <el-table-column prop="pd_type" :label="TEXT.common.fields.pdType" min-width="140" />
<el-table-column prop="pd_level" :label="TEXT.common.fields.pdLevel" min-width="120"> <el-table-column prop="pd_level" :label="TEXT.common.fields.pdLevel" min-width="120">
@@ -1097,7 +1097,7 @@ onMounted(async () => {
.page { .page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 0;
} }
.page-header { .page-header {
@@ -1106,6 +1106,16 @@ onMounted(async () => {
align-items: flex-end; align-items: flex-end;
} }
.subject-shell {
border: 0;
border-radius: 0;
box-shadow: none;
}
.subject-shell :deep(.el-card__body) {
padding: 0;
}
.page-title { .page-title {
margin: 0; margin: 0;
font-size: 22px; font-size: 22px;
@@ -1126,7 +1136,11 @@ onMounted(async () => {
.tab-actions { .tab-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-bottom: 12px; margin-bottom: 10px;
}
.subject-detail-table :deep(.el-table__inner-wrapper::before) {
display: none;
} }
.ae-type-tag { .ae-type-tag {
@@ -10,7 +10,7 @@
style="width: 100%" style="width: 100%"
v-loading="loading" v-loading="loading"
empty-text="暂无数据" empty-text="暂无数据"
class="custom-table" class="custom-table center-summary-table"
> >
<el-table-column prop="name" label="管理中心" min-width="180"> <el-table-column prop="name" label="管理中心" min-width="180">
<template #default="{ row }"> <template #default="{ row }">
@@ -65,6 +65,29 @@ const getStageType = (status?: string) => {
margin-bottom: 24px; margin-bottom: 24px;
} }
.summary-table-container {
overflow: hidden;
}
.center-summary-table :deep(.el-table__inner-wrapper::before) {
display: none;
}
.summary-table-container :deep(.el-table th.el-table__cell) {
background: #f7f9fc;
}
.summary-table-container :deep(.el-table td.el-table__cell),
.summary-table-container :deep(.el-table th.el-table__cell) {
padding-left: 0;
padding-right: 0;
}
.summary-table-container :deep(.el-table td.el-table__cell) {
padding-top: 7px;
padding-bottom: 7px;
}
.box-header { .box-header {
margin-bottom: 16px; margin-bottom: 16px;
} }