@ -19,44 +19,76 @@
< div class = "main-content" >
<!-- 搜索和操作栏 -- >
< div class = "action-bar" >
< div class = "sidebar-header" >
< h1 class = "sidebar-title" >
< span class = "home-link" @click ="jumpToDashboard" > 首页 < / span > & nbsp ; > & nbsp ; 工程研究中心评估
< / h1 >
< / div >
< div class = "search-box" >
< input
< div class = "sidebar-header" >
< h1 class = "sidebar-title" >
< span class = "home-link" @click ="jumpToDashboard" > 首页 < / span > & nbsp ; > & nbsp ; 工程研究中心评估
< / h1 >
< / div >
< div class = "searchbox" >
<!-- 新增 : 得分比较按钮组 -- >
< div class = "score-comparison-wrapper" >
< el-button
type = "primary"
v - if = "!scoreComparisonMode"
class = "compare-score-btn"
@ click = "toggleScoreComparisonMode"
>
得分比较
< / el-button >
< template v-else >
< el-button class = "compare-score-btn close-btn" @click ="toggleScoreComparisonMode" >
关闭
< / el-button >
< el-button
class = "compare-score-btn start-compare-btn"
@ click = "openScoreComparisonDialog"
: disabled = "selectedLabs.length < 2"
: class = "{ 'disabled-btn': selectedLabs.length < 2 }"
>
开始比较 ( { { selectedLabs . length } } )
< / el-button >
< / template >
< / div >
<!-- 搜索框 -- >
< div class = "search-box" >
< input
type = "text"
placeholder = "请输入工程研究中心名称或ID号"
v - model = "searchQuery"
@ input = "handleSearch"
/ >
< button class = "search-button" >
< svg class = "search-icon" viewBox = "0 0 24 24" width = "20" height = "20" >
< path fill = "white" d = "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" / >
< / svg >
< / button >
/ >
< button class = "search-button" >
< svg class = "search-icon" viewBox = "0 0 24 24" width = "20" height = "20" >
< path fill = "white" d = "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" / >
< / svg >
< / button >
< / div >
<!-- < button class = "add-evaluation-btn" @click ="openAddEvaluationDrawer" >
新增评估
< / button > -- >
< / div >
<!-- < button class = "add-evaluation-btn" @click ="openAddEvaluationDrawer" >
新增评估
< / button > -- >
< / div >
<!-- 工程研究中心卡片列表 -- >
< div class = "lab-card-grid custom-scrollbar" >
<!-- < div v-for = "(lab, index) in filteredLabs" :key="index" class="lab-card" style="height: 440px;" > - - >
< div v-for = "(lab, index) in filteredLabs" :key="index" class="lab-card" style="height: 440px;" @click="openLabDetail(lab)" >
< div class = "card-header" >
< span class = "lab-id" > ID : { { lab . basicInformation . name1 || lab . id } } < / span >
< span class = "total-score" > 时间 : < span class = "score-value" > { { lab . basicInformation . name0 } } < / span > < / span >
< div v-for = "(lab) in filteredLabs" :key="lab.id" class="lab-card" >
<!-- 复选框 -- >
< div v-if = "scoreComparisonMode" class="card-checkbox-wrapper" >
< input
type = "checkbox"
v - model = "lab.selected"
@ change = "handleLabSelection(lab)"
/ >
< / div >
< div class = "card-content" >
<!-- < div class = "lab-image" >
< img :src = "lab.basicInformation.name5" alt = "工程研究中心图片" / >
< / div > -- >
< div class = "card- header" @click ="openLabDetail(lab)" >
< span class = "lab-id" : style = "scoreComparisonMode?'margin-left: 40px;':''" > ID : { { lab . basicInformation . name1 || lab . id } } < / span >
< span class = "total-score" > 年份 : < span class = "score-value" > { { lab . basicInformation . name0 } } < / span > < / span >
< / div >
< div class = "card-content" @click ="openLabDetail(lab)" >
< div class = "lab-info" >
< div class = "info-item" >
< span class = "info-label" > 中心名称 : < / span >
@ -64,7 +96,7 @@
< / div >
< div class = "info-item" >
< span class = "info-label" > 所属领域 : < / span >
< span class = "info-value" > { { lab . basicInformation . name3 } } < / span >
< span class = "info-value" > { { lab . basicInformation . name3 } } < / span >
< / div >
< div class = "info-item" >
< span class = "info-label" > 所属学校 : < / span >
@ -74,13 +106,14 @@
< span class = "info-label" > 主管部门 : < / span >
< span class = "info-value" > { { lab . basicInformation . name5 } } < / span >
< / div >
< / div >
< / div >
< div class = "evaluation-chart" >
< div :id = "`lab-chart-${ in dex }`" class = "radar-chart" > < / div >
< div class = "evaluation-chart" @click ="openLabDetail(lab)" >
< div :id = "`lab-chart-${ lab. id}`" class = "radar-chart" > < / div > <!-- 根据lab . id确保唯一性 -- >
< / div >
< div class = "evaluation-info" > 评估摘要 : { { lab . abstracts } } < / div >
< / div >
< / div >
< / div >
@ -95,16 +128,53 @@
/ >
< LabDrawerDetail
v - model : visible = "drawerVisible"
: is - edit = "isEditMode"
: dimensions = "dimensions"
: lab - data = "selectedLab"
@ save = "handleSaveEvaluation"
v - model : visible = "drawerVisible"
: is - edit = "isEditMode"
: dimensions = "dimensions"
: lab - data = "selectedLab"
@ save = "handleSaveEvaluation"
/ >
<!-- 得分比较弹窗 -- >
< el-dialog
v - model = "scoreComparisonDialogVisible"
title = "得分比较"
width = "70%"
center
: append - to - body = "true"
class = "score-comparison-dialog"
>
< el-table
: data = "scoreComparisonTableData"
style = "width: 100%"
border
stripe
class = "default-table score-comparison-table"
: row - class - name = "tableRowClassName"
>
< el-table-column prop = "category" label = "" width = "180" > < / el-table-column >
< el-table-column
v - for = "(header) in scoreComparisonHeaders"
: key = "header.prop"
: prop = "header.prop"
: label = "header.label"
align = "center"
>
< template # default = "{ row }" >
< span : class = " {
'max-score-in-column' : Number ( row [ header . prop ] ) === columnStats [ header . prop ] ? . max ,
'min-score-in-column' : Number ( row [ header . prop ] ) === columnStats [ header . prop ] ? . min
} " >
{ { row [ header . prop ] } }
< / span >
< / template >
< / el-table-column >
< / el-table >
< / el-dialog >
< / template >
< script setup >
import { ref , onMounted , watch , nextTick } from 'vue' ;
import { ref , onMounted , watch , nextTick , computed , onBeforeUnmount } from 'vue' ; / / 引 入 o n B e f o r e U n m o u n t
import * as echarts from 'echarts/core' ;
import { RadarChart } from 'echarts/charts' ;
import LabDrawerDetail from './LabDrawerDetail.vue' ;
@ -117,7 +187,7 @@ import {
} from 'echarts/components' ;
import { CanvasRenderer } from 'echarts/renderers' ;
import axios from 'axios' ;
import { ElMessage } from 'element-plus' ;
import { ElMessage , ElDialog , ElTable , ElTableColumn } from 'element-plus' ;
import { getApiBaseUrl } from '../config' ; / / 导 入 A P I 基 础 U R L 函 数
/ / 注 册 必 要 的 e c h a r t s 组 件
@ -135,6 +205,14 @@ const isEditMode = ref(false);
const selectedLab = ref ( null ) ;
const dimensionDrawerVisible = ref ( false ) ;
/ / 得 分 比 较 相 关 响 应 式 变 量
const scoreComparisonMode = ref ( false ) ; / / 是 否 处 于 得 分 比 较 模 式
const selectedLabs = ref ( [ ] ) ; / / 存 储 选 中 的 L a b C a r d 数 据
const scoreComparisonDialogVisible = ref ( false ) ; / / 控 制 得 分 比 较 弹 窗 显 示
/ / 存 储 E c h a r t s 实 例 , 用 于 销 毁
const chartInstances = new Map ( ) ;
/ / 打 开 添 加 评 估 抽 屉
const openAddEvaluationDrawer = ( ) => {
isEditMode . value = false ;
@ -194,11 +272,27 @@ onMounted(async () => {
await loadLabs ( ) ;
} ) ;
/ / 组 件 销 毁 前 , 销 毁 所 有 E c h a r t s 实 例 和 事 件 监 听 器
onBeforeUnmount ( ( ) => {
chartInstances . forEach ( chart => {
chart . dispose ( ) ;
} ) ;
chartInstances . clear ( ) ;
window . removeEventListener ( 'resize' , debounceResize ) ; / / 移 除 全 局 r e s i z e 监 听
} ) ;
/ / 加 载 工 程 研 究 中 心 数 据
const loadLabs = async ( ) => {
try {
const response = await axios . get ( ` ${ getApiBaseUrl ( ) } /admin-api/pg/evaluation-results/get-release ` ) ;
labs . value = response . data . data ;
/ / 为 每 个 l a b 添 加 s e l e c t e d 属 性 , 并 确 保 它 是 一 个 响 应 式 引 用
/ / 同 时 确 保 r e s u l t 数 组 中 的 数 据 是 数 字 类 型
labs . value = response . data . data . map ( lab => ( {
... lab ,
selected : false ,
result : lab . result . map ( Number ) / / 确 保 r a d a r D a t a 转 换 为 数 字
} ) ) ;
/ / 先 更 新 过 滤 的 工 程 研 究 中 心 列 表
handleSearch ( ) ;
/ / 给 一 个 短 暂 的 延 时 , 确 保 D O M 已 经 更 新
@ -210,36 +304,55 @@ const loadLabs = async () => {
}
} ;
/ / 编 辑 维 度
const editDimension = ( dim , index ) => {
/ / 打 开 维 度 设 置 抽 屉
openDimensionDrawer ( ) ;
/ / 节 流 函 数 f o r r e s i z e
const debounce = ( fn , delay ) => {
let timer = null ;
return function ( ) {
const context = this ;
const args = arguments ;
clearTimeout ( timer ) ;
timer = setTimeout ( ( ) => {
fn . apply ( context , args ) ;
} , delay ) ;
} ;
} ;
const debounceResize = debounce ( ( ) => {
chartInstances . forEach ( chart => {
chart && chart . resize ( ) ;
} ) ;
} , 300 ) ; / / 3 0 0 m s 节 流
/ / 更 新 所 有 雷 达 图
const updateAllRadarCharts = ( ) => {
nextTick ( ( ) => {
filteredLabs . value . forEach ( ( lab , index ) => {
const chartDom = document . getElementById ( ` lab-chart- ${ index } ` ) ;
/ / 先 销 毁 不 再 存 在 的 图 表 实 例
const currentLabIds = new Set ( filteredLabs . value . map ( lab => lab . id ) ) ;
chartInstances . forEach ( ( chart , id ) => {
if ( ! currentLabIds . has ( id ) ) {
chart . dispose ( ) ;
chartInstances . delete ( id ) ;
}
} ) ;
filteredLabs . value . forEach ( ( lab ) => {
const chartDom = document . getElementById ( ` lab-chart- ${ lab . id } ` ) ;
if ( ! chartDom ) return ;
/ / 先 清 空 之 前 的 图 表 实 例 , 避 免 重 复 创 建
echarts . dispose ( chartDom ) ;
const chart = echarts . init ( chartDom ) ;
let chart = chartInstances . get ( lab . id ) ;
if ( ! chart ) {
chart = echarts . init ( chartDom ) ;
chartInstances . set ( lab . id , chart ) ;
/ / 只 在 第 一 次 创 建 时 添 加 r e s i z e 监 听
window . addEventListener ( 'resize' , debounceResize ) ;
}
/ / 从 二 级 维 度 生 成 指 标
/ / c o n s t i n d i c a t o r s = l a b . d i m e n s i o n ;
const indicators = lab . dimension . map ( index => ( { name : index , max : 50 } ) ) ;
const indicators = lab . dimension . map ( name => ( { name : name , max : 50 } ) ) ; / / 假 设 最 大 值 为 5 0
/ / 准 备 雷 达 图 数 据
let radarData = lab . result ;
let radarData = lab . result ; / / 已 确 保 为 数 字 数 组
console . log ( 'radarData:' , indicators , radarData ) ;
chart . setOption ( {
/ / t o o l t i p : {
/ / t r i g g e r : ' i t e m ' , / / 触 发 类 型 为 数 据 项
/ / f o r m a t t e r : ' { b } : { c } ' / / 提 示 框 内 容 格 式 , b 为 数 据 项 名 称 , c 为 数 值
/ / } ,
radar : {
indicator : indicators ,
splitArea : {
@ -297,11 +410,6 @@ const updateAllRadarCharts = () => {
}
]
} ) ;
/ / 添 加 窗 口 大 小 变 化 时 的 图 表 调 整
window . addEventListener ( 'resize' , ( ) => {
chart && chart . resize ( ) ;
} ) ;
} ) ;
} ) ;
} ;
@ -315,7 +423,7 @@ const handleSearch = () => {
filteredLabs . value = labs . value ;
} else {
filteredLabs . value = labs . value . filter ( lab =>
lab . basicInformation . name2 && lab . basicInformation . name2 . includes ( searchQuery . value ) ||
( lab . basicInformation . name2 && lab . basicInformation . name2 . includes ( searchQuery . value ) ) ||
( lab . basicInformation . name1 && lab . basicInformation . name1 . includes ( searchQuery . value ) )
) ;
}
@ -328,19 +436,173 @@ const handleSearch = () => {
/ / 打 开 工 程 研 究 中 心 详 情 抽 屉
const openLabDetail = async ( lab ) => {
/ / co n s t r e s p o n s e = a w a i t a x i o s . g e t ( ` $ { g e t A p i B a s e U r l ( ) } / p g / e v a l u a t i o n - r e s u l t s / g e t - p r e v i e w ? i d = $ { l a b . i d } ` ) ;
/ / c o n s o l e . l o g ( ' r e s p o n s e r e s p o n s e r e s p o n s e r e s p o n s e ' , r e s p o n s e )
/ / 如果 在 比 较 模 式 , 点 击 卡 片 不 打 开 详 情
if ( scoreComparisonMode . value ) return ;
selectedLab . value = lab ;
isEditMode . value = true ;
drawerVisible . value = true ;
} ;
/ / - - - 得 分 比 较 功 能 实 现 - - -
/ / 切 换 得 分 比 较 模 式
const toggleScoreComparisonMode = ( ) => {
scoreComparisonMode . value = ! scoreComparisonMode . value ;
if ( ! scoreComparisonMode . value ) {
/ / 关 闭 模 式 时 , 清 空 所 有 选 中 状 态
filteredLabs . value . forEach ( lab => {
lab . selected = false ;
} ) ;
selectedLabs . value = [ ] ;
}
} ;
/ / 处 理 L a b C a r d 选 中 状 态 变 化
const handleLabSelection = ( lab ) => {
/ / 使 用 V u e 的 响 应 式 方 法 确 保 数 组 更 新 被 追 踪
if ( lab . selected ) {
selectedLabs . value . push ( lab ) ;
} else {
selectedLabs . value = selectedLabs . value . filter ( item => item . id !== lab . id ) ;
}
} ;
/ / 计 算 得 分 比 较 表 格 的 横 向 表 头
const scoreComparisonHeaders = computed ( ( ) => {
if ( selectedLabs . value . length === 0 ) {
return [ ] ;
}
/ / 取 第 一 个 选 中 L a b 的 d i m e n s i o n 作 为 横 向 表 头
const firstLabDimensions = selectedLabs . value [ 0 ] . dimension ;
return firstLabDimensions . map ( ( dim , index ) => ( {
prop : ` score ${ index + 1 } ` , / / 动 态 生 成 属 性 名 , 例 如 s c o r e 1 , s c o r e 2
label : dim
} ) ) ;
} ) ;
/ / 计 算 得 分 比 较 表 格 的 数 据
const scoreComparisonTableData = computed ( ( ) => {
if ( selectedLabs . value . length === 0 ) {
return [ ] ;
}
return selectedLabs . value . map ( lab => {
const row = {
category : lab . basicInformation . name2 / / 纵 向 表 头 是 中 心 名 称
} ;
/ / 将 r a d a r D a t a 映 射 到 r o w 的 动 态 属 性 上
lab . result . forEach ( ( score , index ) => {
row [ ` score ${ index + 1 } ` ] = score ;
} ) ;
return row ;
} ) ;
} ) ;
/ / 新 增 : 计 算 每 列 的 最 大 值 和 最 小 值
const columnStats = computed ( ( ) => {
const stats = { } ;
if ( scoreComparisonTableData . value . length === 0 || scoreComparisonHeaders . value . length === 0 ) {
return stats ;
}
scoreComparisonHeaders . value . forEach ( header => {
const prop = header . prop ;
/ / 确 保 在 计 算 最 大 最 小 值 时 , 所 有 值 都 是 数 字
const values = scoreComparisonTableData . value . map ( row => Number ( row [ prop ] ) ) ;
if ( values . length > 0 ) {
stats [ prop ] = {
max : Math . max ( ... values ) ,
min : Math . min ( ... values )
} ;
}
} ) ;
/ / c o n s o l e . l o g ( " C a l c u l a t e d c o l u m n S t a t s : " , s t a t s ) ; / / 调 试 输 出
return stats ;
} ) ;
/ / 表 格 行 样 式 , 用 于 隔 行 高 亮
const tableRowClassName = ( { rowIndex } ) => {
if ( rowIndex % 2 === 1 ) {
return 'striped-row' ; / / 奇 数 行 应 用 条 纹 样 式
}
return '' ;
} ;
/ / 打 开 得 分 比 较 弹 窗
const openScoreComparisonDialog = ( ) => {
if ( selectedLabs . value . length < 2 ) {
ElMessage . warning ( '请至少选择两个工程研究中心进行比较!' ) ;
return ;
}
scoreComparisonDialogVisible . value = true ;
} ;
/ / 监 听 f i l t e r e d L a b s 变 化 , 更 新 雷 达 图
/ / 这 里 不 再 需 要 深 度 监 听 , 因 为 l a b . i d 变 化 不 会 频 繁 , 内 部 数 据 的 变 化 由 E C h a r t s 自 身 处 理
watch ( filteredLabs , ( ) => {
nextTick ( ( ) => {
updateAllRadarCharts ( ) ;
} ) ;
} ) ;
< / script >
< style >
/* common.css 保持不变,用于全局样式 */
@ import './common.css' ;
< / style >
< style scoped >
. default - table {
background - color : white ; /* 表格背景色为白色 */
color : black ; /* 文字颜色为黑色 */
border - radius : 8 px ;
overflow : hidden ;
}
/* 新增:得分比较表格的特定样式 */
. score - comparison - table {
max - height : 60 vh ; /* 设置最大高度, 例如视口高度的60% */
overflow - y : auto ; /* 当内容超出最大高度时,显示垂直滚动条 */
overflow - x : hidden ;
}
. default - table th . el - table _ _cell {
background - color : # f5f7fa ! important ; /* 表头背景色浅灰 */
color : black ! important ;
font - weight : bold ;
border - right : 1 px solid # ebeef5 ! important ;
border - bottom : 1 px solid # ebeef5 ! important ;
}
. default - table td . el - table _ _cell {
background - color : white ! important ; /* 单元格背景色白色 */
color : black ! important ;
border - right : 1 px solid # ebeef5 ! important ;
border - bottom : 1 px solid # ebeef5 ! important ;
}
. default - table tr : hover > td {
background - color : # f0f2f5 ! important ; /* 行悬停背景色更浅的灰色 */
}
/* 条纹样式 */
. default - table . el - table -- striped . el - table _ _body tr . striped - row td {
background - color : # fafafa ! important ; /* 条纹行背景色,比默认单元格略深 */
}
/* 最大值和最小值高亮 */
. max - score - in - column {
color : red ; /* 红色 */
font - weight : bold ;
}
. min - score - in - column {
color : blue ; /* 蓝色 */
font - weight : bold ;
}
. evaluation - page {
position : absolute ;
top : 0 ;
@ -553,21 +815,30 @@ const openLabDetail = async (lab) => {
flex - direction : column ;
padding : 0 10 px ;
overflow : hidden ;
max - height : calc ( 100 vh - 100 px ) ; /* 限制最大高度 */
max - height : none ;
height : auto ;
}
/* 搜索和操作栏 */
. action - bar {
height : 64 px ;
display : flex ;
justify - content : space - between ;
justify - content : space - between ; /* 使得左中右元素分散对齐 */
align - items : center ;
}
/* 新增:得分比较按钮组容器,与搜索框分离 */
. score - comparison - wrapper {
display : flex ;
gap : 10 px ; /* 按钮之间的间距 */
margin - right : 20 px ; /* 与搜索框的间距 */
}
. search - box {
display : flex ;
align - items : center ;
width : 300 px ;
width : 300 px ; /* 调整宽度,不再包含得分比较按钮 */
background - color : rgba ( 255 , 255 , 255 , 0.1 ) ;
border - radius : 20 px ;
overflow : hidden ;
@ -614,26 +885,29 @@ const openLabDetail = async (lab) => {
/* 工程研究中心卡片网格 */
. lab - card - grid {
display : grid ;
grid - template - columns : repeat ( auto - fill , minmax ( 450 px , 1 fr ) ) ;
gap : 20 px ;
overflow - y : auto ; /* 允许卡片区域滚动 */
flex : 1 ;
display : flex ; /* 使用 flex 布局 */
flex - wrap : wrap ; /* 允许项目换行 */
gap : 20 px ; /* 项目间的间距 */
padding : 20 px ;
background - color : # 262 F50 ;
border - radius : 10 px ;
overflow - y : auto ;
justify - content : flex - start ;
}
. lab - card {
box - sizing : border - box ;
flex : 0 0 calc ( ( 100 % - 40 px ) / 3 ) ;
background - color : # 1 f3266 ;
border - radius : 8 px ;
overflow : hidden ;
border : 1 px solid rgba ( 73 , 134 , 255 , 0.3 ) ;
display : flex ;
flex - direction : column ;
min - height : 350 px ; /* 调整最小高度,确保雷达图有足够空间 */
min - height : 350 px ;
cursor : pointer ;
transition : transform 0.2 s , box - shadow 0.2 s ;
position : relative ;
}
. lab - card : hover {
@ -641,6 +915,31 @@ const openLabDetail = async (lab) => {
box - shadow : 0 5 px 15 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
/* 复选框容器样式 */
. card - checkbox - wrapper {
position : absolute ;
top : 4 px ; /* 距离顶部 */
left : 8 px ; /* 距离左侧 */
z - index : 10 ; /* 确保在最上层 */
background - color : rgba ( 0 , 0 , 0 , 0.3 ) ; /* 半透明黑色背景 */
border - radius : 4 px ;
padding : 4 px ;
display : flex ;
align - items : center ;
justify - content : center ;
width : 28 px ; /* 确保有足够点击区域 */
height : 28 px ;
}
. card - checkbox - wrapper input [ type = "checkbox" ] {
width : 20 px ;
height : 20 px ;
cursor : pointer ;
accent - color : # 4986 ff ; /* 改变复选框颜色 */
margin : 0 ; /* 移除默认外边距 */
}
. card - header {
display : flex ;
justify - content : space - between ;
@ -653,6 +952,7 @@ const openLabDetail = async (lab) => {
. lab - id {
font - size : 14 px ;
color : rgba ( 255 , 255 , 255 , 0.7 ) ;
/* 确保ID不被复选框遮挡, 如果复选框在左边, 这里可能需要调整padding-left或margin-left */
}
. total - score {
@ -687,14 +987,16 @@ const openLabDetail = async (lab) => {
}
. lab - info {
width : 6 0% ;
width : 10 0% ;
display : flex ;
flex - direction : column ;
flex - direction : row ; /* 修改为横向排列 */
flex - wrap : wrap ; /* 允许元素换行 */
gap : 10 px ;
}
. info - item {
margin - bottom : 5 px ;
width : calc ( 50 % - 5 px ) ; /* 每个元素占一半宽度,减去 gap 的一半 */
}
. info - label {
@ -756,6 +1058,49 @@ const openLabDetail = async (lab) => {
margin - bottom : 5 px ;
}
/* 得分比较按钮样式 */
. compare - score - btn {
background - color : rgb ( 13 , 70 , 192 ) ;
border : none ;
color : rgba ( 255 , 255 , 255 , 1 ) ;
border - radius : 10 px ;
padding : 8 px 15 px ;
font - size : 14 px ;
text - align : center ;
font - family : PingFangSC - regular ;
cursor : pointer ;
transition : background - color 0.2 s , border - color 0.2 s ;
}
. compare - score - btn : hover {
background - color : rgba ( 14 , 62 , 167 , 0.8 ) ;
}
. compare - score - btn . close - btn {
background - color : # f44336 ; /* 红色 */
border - color : # f44336 ;
}
. compare - score - btn . close - btn : hover {
background - color : # d32f2f ;
}
. compare - score - btn . start - compare - btn {
background - color : # 4 CAF50 ; /* 绿色 */
border - color : # 4 CAF50 ;
}
. compare - score - btn . start - compare - btn : hover {
background - color : # 388 E3C ;
}
. compare - score - btn . disabled - btn {
background - color : # 616161 ; /* 灰色 */
border - color : # 616161 ;
cursor : not - allowed ;
opacity : 0.7 ;
}
@ media ( max - width : 1200 px ) {
. lab - card - grid {
grid - template - columns : 1 fr ;
@ -781,4 +1126,10 @@ const openLabDetail = async (lab) => {
width : 100 % ;
}
}
. searchbox {
display : flex ;
}
. evaluation - info {
padding : 20 px 15 px ;
}
< / style >