| | |
| | | <template> |
| | | <div> |
| | | <div v-loading="isloading" style="padding: 10px"> |
| | | <div> |
| | | <el-image |
| | | style="width: 100%; height: 72px" |
| | | :src="img.head" |
| | | fit="contain" |
| | | ></el-image> |
| | | <div v-loading="loading" class="cockpit"> |
| | | <!-- 顶部标题栏 --> |
| | | <header class="cockpit-header"> |
| | | <div class="header-left"> |
| | | <span class="header-logo"></span> |
| | | <h1 class="header-title">青岛大学附属医院 · OPO 器官捐献管理驾驶舱</h1> |
| | | </div> |
| | | <div class="header-right"> |
| | | <span class="header-clock">{{ now }}</span> |
| | | <el-button type="text" class="header-logout" @click="handleLogout" |
| | | >退出</el-button |
| | | > |
| | | </div> |
| | | </header> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6"> |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">占比统计</div> |
| | | |
| | | <div style="padding: 0 2rem"> |
| | | <div class="iwc-box-a" :style="'height:' + heightA + 'px'"> |
| | | <div class="iwc-box-a-1"> |
| | | <span |
| | | class="iwc-before-o" |
| | | style="border-color: #38a5f8" |
| | | ></span |
| | | >性别占比:{{ |
| | | currentZb.sex == -1 ? "" : arrZb.sex[currentZb.sex].label |
| | | }} |
| | | </div> |
| | | <el-progress |
| | | :text-inside="true" |
| | | :stroke-width="15" |
| | | :percentage=" |
| | | currentZb.sex == -1 |
| | | ? 0 |
| | | : Number( |
| | | (arrZb.sex[currentZb.sex].value * 100).toFixed(0) |
| | | ) |
| | | " |
| | | :color="'#38a5f8'" |
| | | ></el-progress> |
| | | </div> |
| | | <div class="iwc-box-a" :style="'height:' + heightA + 'px'"> |
| | | <div class="iwc-box-a-1"> |
| | | <span |
| | | class="iwc-before-o" |
| | | style="border-color: #9078e5" |
| | | ></span |
| | | >年龄占比:{{ |
| | | currentZb.age == -1 ? "" : arrZb.age[currentZb.age].label |
| | | }} |
| | | </div> |
| | | <el-progress |
| | | :text-inside="true" |
| | | :stroke-width="15" |
| | | :percentage=" |
| | | currentZb.age == -1 |
| | | ? 0 |
| | | : Number( |
| | | (arrZb.age[currentZb.age].value * 100).toFixed(0) |
| | | ) |
| | | " |
| | | :color="'#9078e5'" |
| | | ></el-progress> |
| | | </div> |
| | | <div class="iwc-box-a" :style="'height:' + heightA + 'px'"> |
| | | <div class="iwc-box-a-1"> |
| | | <span |
| | | class="iwc-before-o" |
| | | style="border-color: #3fc529" |
| | | ></span |
| | | >捐献分类占比:{{ |
| | | currentZb.type == -1 |
| | | ? "" |
| | | : arrZb.type[currentZb.type].label |
| | | }} |
| | | </div> |
| | | <el-progress |
| | | :text-inside="true" |
| | | :stroke-width="15" |
| | | :percentage=" |
| | | currentZb.type == -1 |
| | | ? 0 |
| | | : Number( |
| | | (arrZb.type[currentZb.type].value * 100).toFixed(0) |
| | | ) |
| | | " |
| | | :color="'#3fc529'" |
| | | ></el-progress> |
| | | </div> |
| | | <div class="iwc-box-a" :style="'height:' + heightA + 'px'"> |
| | | <div class="iwc-box-a-1"> |
| | | <span |
| | | class="iwc-before-o" |
| | | style="border-color: #2a65b5" |
| | | ></span |
| | | >疾病占比:{{ |
| | | currentZb.d == -1 ? "" : arrZb.d[currentZb.d].label |
| | | }} |
| | | </div> |
| | | <el-progress |
| | | :text-inside="true" |
| | | :stroke-width="15" |
| | | :percentage=" |
| | | currentZb.d == -1 |
| | | ? 0 |
| | | : Number((arrZb.d[currentZb.d].value * 100).toFixed(0)) |
| | | " |
| | | :color="'#2a65b5'" |
| | | ></el-progress> |
| | | </div> |
| | | <div class="iwc-box-a" :style="'height:' + heightA + 'px'"> |
| | | <div class="iwc-box-a-1"> |
| | | <span |
| | | class="iwc-before-o" |
| | | style="border-color: #fbc329" |
| | | ></span |
| | | >血型占比:{{ |
| | | currentZb.x == -1 ? "" : arrZb.x[currentZb.x].label |
| | | }} |
| | | </div> |
| | | <el-progress |
| | | :text-inside="true" |
| | | :stroke-width="15" |
| | | :percentage=" |
| | | currentZb.x == -1 |
| | | ? 0 |
| | | : Number((arrZb.x[currentZb.x].value * 100).toFixed(0)) |
| | | " |
| | | :color="'#fbc329'" |
| | | ></el-progress> |
| | | </div> |
| | | </div> |
| | | </dv-border-box-7> |
| | | </div> |
| | | |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">机构捐献统计</div> |
| | | |
| | | <div |
| | | style="padding: 0 2rem" |
| | | :style="'height:' + (height * 0.35 - 54) + 'px'" |
| | | > |
| | | <dv-scroll-board |
| | | :config="tableConfig" |
| | | style="width: 100%" |
| | | class="iwc-h-rb-table" |
| | | :style="'height:' + (height * 0.35 - 54) + 'px'" |
| | | /> |
| | | </div> |
| | | </dv-border-box-7> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="iwc-box-d" style="height: 125px"> |
| | | <div class="iwc-box-d-1"> |
| | | <div class="iwc-box-d-img"> |
| | | <el-image |
| | | style="width: 100%; height: 100%" |
| | | :src="img.btn1" |
| | | fit="cover" |
| | | ></el-image> |
| | | </div> |
| | | <div class="iwc-box-d-f"> |
| | | <div class="iwc-box-d-f1">{{ leijishuju.processOrgans }}</div> |
| | | <div class="iwc-box-d-f2">捐献案例累计</div> |
| | | </div> |
| | | </div> |
| | | <div class="iwc-box-d-1"> |
| | | <div class="iwc-box-d-img"> |
| | | <el-image |
| | | style="width: 100%; height: 100%" |
| | | :src="img.btn2" |
| | | fit="cover" |
| | | ></el-image> |
| | | </div> |
| | | <div class="iwc-box-d-f"> |
| | | <div class="iwc-box-d-f1">{{ leijishuju.finishedOrgans }}</div> |
| | | <div class="iwc-box-d-f2">捐献完成累计</div> |
| | | </div> |
| | | </div> |
| | | <div class="iwc-box-d-1"> |
| | | <div class="iwc-box-d-img"> |
| | | <el-image |
| | | style="width: 100%; height: 100%" |
| | | :src="img.btn3" |
| | | fit="cover" |
| | | ></el-image> |
| | | </div> |
| | | <div class="iwc-box-d-f"> |
| | | <div class="iwc-box-d-f1">{{ leijishuju.Organsnum }}</div> |
| | | <div class="iwc-box-d-f2">捐献器官累计</div> |
| | | </div> |
| | | </div> |
| | | <div class="iwc-box-d-1" style="flex: 1.4"> |
| | | <div class="iwc-box-d-img"> |
| | | <el-image |
| | | style="width: 100%; height: 100%" |
| | | :src="img.btn4" |
| | | fit="cover" |
| | | ></el-image> |
| | | </div> |
| | | <div class="iwc-box-d-f"> |
| | | <div class="iwc-box-d-f1">{{ leijishuju.PMP }}</div> |
| | | <div class="iwc-box-d-f2">每百万人口器官捐献率(PMP)</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="iwc-box-e" style="margin-bottom: 10px; padding-left: 12%"> |
| | | <el-col :span="17"> |
| | | <MapChart |
| | | :cdata="cdata" |
| | | :height="height * 0.72 - 128 + 'px'" |
| | | @click="mapClick" |
| | | :chartType="chartType" |
| | | <!-- KPI 指标卡 --> |
| | | <section class="kpi-row"> |
| | | <div v-for="kpi in kpiCards" :key="kpi.label" class="kpi-card"> |
| | | <div class="kpi-icon" :style="{ background: kpi.gradient }"> |
| | | <i :class="kpi.icon"></i> |
| | | </div> |
| | | <div class="kpi-body"> |
| | | <div class="kpi-label">{{ kpi.label }}</div> |
| | | <div class="kpi-value"> |
| | | <count-to |
| | | :start-val="0" |
| | | :end-val="kpi.value" |
| | | :duration="1400" |
| | | :decimals="kpi.decimals || 0" |
| | | separator="," |
| | | /> |
| | | </el-col> |
| | | <el-col :span="7" > |
| | | <div style="backgroun-color:black; margin:bottom:5px;height:100%;padding-top:50px;"> |
| | | <el-row> |
| | | <div style="color:white;font-size:15px;text-align:center">当前各地市潜在捐献案例</div> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12" style="color:white;font-size:14px;text-align:center;margin-top:10px" |
| | | v-for="(item, index) in cityDonoateCaseArr" |
| | | :key="index"> |
| | | {{item.cityName}}<br> <span style="color:#ffd200">{{item.donoateNum}}</span>例 |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | </el-col> |
| | | <span class="kpi-unit">{{ kpi.unit }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">器官获取统计</div> |
| | | </div> |
| | | </div> |
| | | </section> |
| | | |
| | | <el-row |
| | | style="padding: 0 2rem" |
| | | :style="'height:' + (height * 0.35 - 54) + 'px'" |
| | | > |
| | | <el-col |
| | | :span="8" |
| | | v-for="(item, index) in organSumData" |
| | | :key="index" |
| | | > |
| | | <div |
| | | style=" |
| | | color: #fff; |
| | | padding-bottom: 10px; |
| | | " |
| | | > |
| | | {{ item.name }}:<span style="font-size: 18px">{{ |
| | | item.value |
| | | }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </dv-border-box-7> |
| | | <!-- 仪表盘指标 --> |
| | | <section class="gauge-row"> |
| | | <div v-for="g in gaugeCharts" :key="g.name" class="panel"> |
| | | <div class="panel-title">{{ g.name }}</div> |
| | | <G2PlotChart type="gauge" :options="g.options" :height="150" /> |
| | | </div> |
| | | </section> |
| | | |
| | | <!-- 主区:地图居中,其他图环绕 --> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="6"> |
| | | <div class="col-stack"> |
| | | <div class="panel"> |
| | | <div class="panel-title">案例月度趋势</div> |
| | | <G2PlotChart type="area" :options="trendOptions" :height="205" /> |
| | | </div> |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">机构接受器官统计</div> |
| | | |
| | | <el-row |
| | | style="padding: 0 1rem" |
| | | :style="'height:' + (height * 0.35 - 54) + 'px'" |
| | | > |
| | | <dv-scroll-board |
| | | v-if="configHosOrgan.data.length > 0" |
| | | :config="configHosOrgan" |
| | | class="iwc-box-b-table" |
| | | style="width: 100%" |
| | | :style="'height:' + (height * 0.35 - 54) + 'px'" |
| | | /> |
| | | </el-row> |
| | | </dv-border-box-7> |
| | | <div class="panel"> |
| | | <div class="panel-title">器官获取 / 移植趋势</div> |
| | | <G2PlotChart type="line" :options="organMoonOptions" :height="205" /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6"> |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">历年捐献数据</div> |
| | | |
| | | <el-row |
| | | style="padding: 0 1rem" |
| | | :style="'height:' + (height * 0.28 - 80) + 'px'" |
| | | > |
| | | <BarChartH |
| | | :cdata="cdataYear" |
| | | :organData="organYearData" |
| | | :height="height * 0.28 - 80 + 'px'" |
| | | /> |
| | | </el-row> |
| | | </dv-border-box-7> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="panel panel--map"> |
| | | <div class="panel-title">地区分布</div> |
| | | <MapChart |
| | | :cdata="raw.mapData" |
| | | :height="'480px'" |
| | | :zoom="1.4" |
| | | left="center" |
| | | top="middle" |
| | | label-mode="name" |
| | | dark |
| | | :roam="true" |
| | | @click="mapClick" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <div class="col-stack"> |
| | | <div class="panel"> |
| | | <div class="panel-title">地区捐献对比</div> |
| | | <G2PlotChart type="column" :options="areaOptions" :height="205" /> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <div class="iwc-dv-box" style="margin-bottom: 0.5rem"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">捐献案例月度统计</div> |
| | | |
| | | <div style="padding: 0 2rem"> |
| | | <LineChart |
| | | :cdata="anlidata" |
| | | :height="height * 0.28 - 80 + 'px'" |
| | | <div class="panel panel--carousel"> |
| | | <div class="panel-title">{{ currentCarousel.title }}</div> |
| | | <transition name="fade" mode="out-in"> |
| | | <div :key="carouselIndex" class="carousel-body"> |
| | | <G2PlotChart |
| | | :type="currentCarousel.type" |
| | | :options="currentCarousel.options" |
| | | :height="205" |
| | | /> |
| | | </div> |
| | | </dv-border-box-7> |
| | | </transition> |
| | | <div class="carousel-dots"> |
| | | <span |
| | | v-for="(item, i) in carouselItems" |
| | | :key="i" |
| | | class="dot" |
| | | :class="{ active: i === carouselIndex }" |
| | | @click="carouselIndex = i" |
| | | ></span> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <div class="iwc-dv-box"> |
| | | <dv-border-box-7 |
| | | :color="['#0a336e', '#1a7ade']" |
| | | :backgroundColor="'#030e40'" |
| | | > |
| | | <div class="iwc-box-head">质控指标</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div |
| | | style="padding: 0 2rem" |
| | | :style="'height:' + (height * 0.28 - 80) + 'px'" |
| | | > |
| | | <div class="iwc-box-c"> |
| | | <div class="iwc-box-c1" style="color: #fac738"> |
| | | <div class="iwc-box-c1-o"> |
| | | {{ |
| | | leijishuju.donateTransferRate |
| | | ? leijishuju.donateTransferRate.toFixed(2) |
| | | : "" |
| | | }} |
| | | </div> |
| | | <div class="iwc-box-c1-l" style="font-size:0.8rem">器官捐献转化率</div> |
| | | </div> |
| | | <div class="iwc-box-c1" style="color: #34bc1d"> |
| | | <div class="iwc-box-c1-o"> |
| | | {{ |
| | | leijishuju.organProductionRate |
| | | ? leijishuju.organProductionRate.toFixed(2) |
| | | : "" |
| | | }} |
| | | </div> |
| | | <div class="iwc-box-c1-l" style="font-size:0.8rem">平均器官产出率</div> |
| | | </div> |
| | | <div class="iwc-box-c1" style="color: #2f9ef4"> |
| | | <div class="iwc-box-c1-o"> |
| | | {{ |
| | | leijishuju.organUsedRate |
| | | ? leijishuju.organUsedRate.toFixed(2) |
| | | : "" |
| | | }} |
| | | </div> |
| | | <div class="iwc-box-c1-l" style="font-size:0.8rem">获取器官利用率</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </dv-border-box-7> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <el-row v-if="0" class="c-home" :gutter="10"> |
| | | <el-col :span="8"> |
| | | <div style="padding-top: 25px; padding-bottom: 10px"> |
| | | <dv-border-box-2 :color="['#1b88a3']"> |
| | | <div class="box-title" style="position: absolute; top: -8px"> |
| | | <span><b>对比分析</b></span> |
| | | </div> |
| | | <div style="padding: 40px 10px"> |
| | | <div |
| | | class="c-table-title light" |
| | | v-if="0" |
| | | style="height: 50px; line-height: 50px" |
| | | > |
| | | 器官统计 |
| | | </div> |
| | | <LineChart :cdata="anlidata" :height="height / 7 + 'px'" /> |
| | | <Line2Chart :cdata="yiyuan" :height="height / 7 + 'px'" /> |
| | | <Line1Chart :cdata="organsum" :height="height / 7 + 'px'" /> |
| | | <BarChart :cdata="organData" :height="height / 7 + 'px'" /> |
| | | |
| | | <BarChart2 |
| | | :cdata="hosGetData" |
| | | :height="(height / 7) * 2 + 'px'" |
| | | /> |
| | | |
| | | <BarChart3 |
| | | :cdata="organSumData" |
| | | :height="(height - 10) / 7 + 'px'" |
| | | /> |
| | | </div> |
| | | </dv-border-box-2> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8" style="margin-top: 28px"> |
| | | <dv-border-box-12 :color="['#1b88a3']" style="padding: -20px"> |
| | | <div class="box-title" style="position: absolute; top: -8px"> |
| | | <span><b>全省概况</b></span> |
| | | </div> |
| | | <div style="padding: 30px 20px 30px; margin: 0 auto"> |
| | | <el-row> |
| | | <el-col :span="8" class="box-num"> |
| | | <div class="box-num-main" style="text-align: center"> |
| | | <p>潜在捐献累计</p> |
| | | <span class="box-num-main-n">{{ |
| | | leijishuju.processOrgans |
| | | }}</span> |
| | | </div> |
| | | <div class="box-num-ex"> |
| | | <span></span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8" class="box-num"> |
| | | <div class="box-num-main" style="text-align: center"> |
| | | <p>捐献完成累计</p> |
| | | <span class="box-num-main-n">{{ |
| | | leijishuju.finishedOrgans |
| | | }}</span> |
| | | </div> |
| | | <div style="height: 20px"></div> |
| | | <div class="box-num-ex"> |
| | | <span></span> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="8" class="box-num"> |
| | | <div class="box-num-main" style="text-align: center"> |
| | | <p>捐献器官累计</p> |
| | | <span class="box-num-main-n">{{ |
| | | leijishuju.Organsnum |
| | | }}</span> |
| | | </div> |
| | | <div class="box-num-ex"> |
| | | <span></span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row style="margin-bottom: 10px"> |
| | | <el-col :span="12" class="box-num"> |
| | | <div class="box-num-main" style="text-align: center"> |
| | | <p>每百万人口器官捐献率(PMP)</p> |
| | | <span class="box-num-main-n">{{ leijishuju.PMP }}</span> |
| | | </div> |
| | | <div class="box-num-ex"> |
| | | <span></span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12" class="box-num"> |
| | | <div class="box-num-main" style="text-align: center"> |
| | | <p>潜献转化率/器官产出率/器官利用率</p> |
| | | <span class="box-num-main-n"> |
| | | {{ leijishuju.donateTransferRate.toFixed(2) }}/{{ |
| | | leijishuju.organProductionRate.toFixed(2) |
| | | }}/{{ leijishuju.organUsedRate.toFixed(2) }}</span |
| | | > |
| | | </div> |
| | | <div class="box-num-ex"> |
| | | <span></span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </dv-border-box-12> |
| | | <dv-border-box-7 :color="['#fff']"> |
| | | <dv-border-box-8> |
| | | <div style="padding: 40px 20px"> |
| | | <div style="padding-top: 12px"></div> |
| | | <MapChart |
| | | :cdata="cdata" |
| | | :height="height - 220 + 'px'" |
| | | @click="mapClick" |
| | | :chartType="chartType" |
| | | /></div></dv-border-box-8 |
| | | ></dv-border-box-7> |
| | | </el-col> |
| | | <el-col :span="8" v-loading="tableLoading" style="padding-top: 28px"> |
| | | <dv-border-box-6 :color="['#1b88a3']"> |
| | | <div class="box-title" style="position: absolute; top: -8px"> |
| | | <span><b>占比统计</b></span> |
| | | </div> |
| | | <div |
| | | class="iwc-ring" |
| | | v-if="1" |
| | | style=" |
| | | padding: 30px 10px 20px; |
| | | min-height: 280px; |
| | | text-align: center; |
| | | " |
| | | > |
| | | <el-row |
| | | ><el-col :span="8"> |
| | | <dv-active-ring-chart |
| | | v-if="configSex.data.length > 0" |
| | | :config="configSex" |
| | | style="width: 100%; height: 100px" |
| | | /> |
| | | <div>性别占比</div></el-col |
| | | ><el-col :span="8"> |
| | | <dv-active-ring-chart |
| | | v-if="configAge.data.length > 0" |
| | | :config="configAge" |
| | | style="width: 100%; height: 100px" |
| | | /> |
| | | <div>年龄占比</div></el-col |
| | | ><el-col :span="8"> |
| | | <dv-active-ring-chart |
| | | v-if="configDd.data.length > 0" |
| | | :config="configDd" |
| | | style="width: 100%; height: 100px" |
| | | /> |
| | | <div>捐献分类占比</div></el-col |
| | | ></el-row |
| | | > |
| | | <el-row |
| | | ><el-col :span="12"> |
| | | <dv-active-ring-chart |
| | | v-if="configD.data.length > 0" |
| | | :config="configD" |
| | | style="width: 100%; height: 100px" |
| | | /> |
| | | <div>疾病占比</div></el-col |
| | | ><el-col :span="12"> |
| | | <dv-active-ring-chart |
| | | v-if="configX.data.length > 0" |
| | | :config="configX" |
| | | style="width: 100%; height: 100px" |
| | | /> |
| | | 血型占比</el-col |
| | | ></el-row |
| | | > |
| | | </div> |
| | | <div v-if="0" style="padding: 30px 10px 20px; min-height: 280px"> |
| | | <el-row style="margin-bottom: 10px"> |
| | | <el-col :span="7" style="text-align: right">男女占比</el-col> |
| | | <el-col :span="17"> |
| | | <div style="display: flex; text-align: center"> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">男</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.manRate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">女</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.womanRate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row style="margin-bottom: 10px"> |
| | | <el-col :span="7" style="text-align: right" |
| | | >捐献分类占比</el-col |
| | | > |
| | | <el-col :span="17"> |
| | | <div style="display: flex; text-align: center"> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">DBD</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.dbdrate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">DCD</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.dcdrate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">DBCD</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.dbcdrate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row style="margin-bottom: 10px"> |
| | | <el-col :span="7" style="text-align: right">年龄占比</el-col> |
| | | <el-col :span="17"> |
| | | <div style="display: flex; text-align: center"> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">1-17岁</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.a1Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">18-49岁</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.a2Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">49-69岁</span> <span |
| | | class="fc-sp" |
| | | >{{ (objZb.a3Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row style="margin-bottom: 10px"> |
| | | <el-col |
| | | :span="24" |
| | | style="margin-bottom: 10px; text-align: center" |
| | | >血型占比</el-col |
| | | > |
| | | <el-col :span="24"> |
| | | <div style="display: flex; text-align: center"> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">A型</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.xarate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">B型</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.xbrate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">AB型</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.xabrate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">O型</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.xorate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col |
| | | :span="24" |
| | | style="margin-bottom: 10px; text-align: center" |
| | | >病因占比</el-col |
| | | > |
| | | <el-col :span="24"> |
| | | <div style="display: flex; text-align: center"> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">脑血管意外</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.d0Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">脑外伤</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.d1Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">缺血缺氧性脑病</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.d2Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">脑肿瘤</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.d3Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | <div style="flex: 1"> |
| | | <span class="fc-white">心血管疾病</span><br /><span |
| | | class="fc-sp" |
| | | >{{ (objZb.d4Rate * 100).toFixed(2) + "%" }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </dv-border-box-6> |
| | | |
| | | <dv-border-box-6 :color="['#1b88a3']" style="margin-top: 30px"> |
| | | <div class="box-title" style="position: absolute; top: -8px"> |
| | | <span><b>机构统计</b></span> |
| | | </div> |
| | | <div style="padding: 20px"> |
| | | <el-row class="c-table-title"> |
| | | <el-col :span="18" :class="isAll ? 'active' : ''"> |
| | | <el-divider content-position="left" |
| | | ><span>浙江省</span></el-divider |
| | | ></el-col |
| | | > |
| | | <el-col :span="6"><el-divider></el-divider></el-col> |
| | | </el-row> |
| | | <dv-scroll-board |
| | | :config="tableConfig" |
| | | style="width: 100%; border: 1px solid #142984" |
| | | class="iwc-h-rb-table" |
| | | :style="{ height: height - 310 + 'px' }" |
| | | /> |
| | | </div> |
| | | </dv-border-box-6> |
| | | </el-col> |
| | | </el-row> --> |
| | | </div> |
| | | <!-- 登录弹窗 --> |
| | | <el-dialog |
| | | title="登录" |
| | | :visible.sync="dialogVisible" |
| | | width="380px" |
| | | :close-on-click-modal="false" |
| | | :show-close="false" |
| | | append-to-body |
| | | custom-class="login-dialog" |
| | | > |
| | | <el-form :model="form" @submit.native.prevent> |
| | | <el-form-item label="账号" label-width="60px"> |
| | | <el-input |
| | | v-model="defaultAccount" |
| | | autocomplete="off" |
| | | placeholder="请输入账号" |
| | | @keyup.enter.native="loginFn" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="密码" label-width="60px"> |
| | | <el-input |
| | | v-model="defaultPassword" |
| | | show-password |
| | | autocomplete="off" |
| | | placeholder="请输入密码" |
| | | @keyup.enter.native="loginFn" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | <el-button type="primary" :loading="loginLoading" @click="loginFn" |
| | | >登 录</el-button |
| | | > |
| | | </span> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import { |
| | | getNumberOfOrgan, |
| | | getOrgansOfHospital, |
| | | getAllOrganInfo, |
| | | countDonateorgan, |
| | | countDonateHostipal, |
| | | countorganHostipal, |
| | | getDonateNumber, |
| | | getdonateBaseInfoByMonth, |
| | | getdonatePeopleByMonth, |
| | | getdonateNumberByMonth, |
| | | getdonateHospitalByMonth, |
| | | getacceptHospitalByMonths, |
| | | getOrgansOfHospitalByMonth, |
| | | getDonateorganPMP, |
| | | getDonateorganQuality, |
| | | getDonationwitnessStats, |
| | | getTransplantHospitalNum, |
| | | getDonateorganSum, |
| | | getDonateorganDistrictDonateCalculate, |
| | | } from "@/api/project/donateorgan"; |
| | | import { listData } from "@/api/system/dict/data"; |
| | | import { login, logout, getInfo } from "@/api/login"; |
| | | import { listDonatebaseinfo } from "@/api/project/donatebaseinfo"; |
| | | import { getToken, setToken, removeToken } from "@/utils/auth"; |
| | | import MapChart from "./components/MapChart"; |
| | | import BarChart from "./components/BarChart"; |
| | | import BarChart2 from "./components/BarChart2"; |
| | | import BarChart3 from "./components/BarChart3"; |
| | | import BarChartH from "./components/BarChartH"; |
| | | import LineChart from "./components/lineChart"; |
| | | import Line1Chart from "./components/line1Chart"; |
| | | import Line2Chart from "./components/line2Chart"; |
| | | |
| | | const DEF_TABLE_CONFIG = { |
| | | header: ["区域", "机构", "捐献登记", "捐献完成"], |
| | | data: [], |
| | | headerBGC: "#0a3073", |
| | | oddRowBGC: "", |
| | | evenRowBGC: "", |
| | | rowNum: 6, |
| | | <script> |
| | | import CountTo from 'vue-count-to'; |
| | | import G2PlotChart from '@/components/charts/G2PlotChart.vue'; |
| | | import MapChart from './components/MapChart'; |
| | | import { login } from '@/api/login'; |
| | | import { encrypts } from '@/utils/crypto'; |
| | | import { setToken, removeToken } from '@/utils/auth'; |
| | | import { xAxis, yAxis, legend, tooltip } from '@/utils/g2Dark'; |
| | | import { toMonth, toNum } from '@/utils/totals'; |
| | | import { mockCockpitData } from './cockpitMock'; |
| | | |
| | | const AGE_LABELS = { |
| | | '1': '≤17岁', |
| | | '2': '18-49岁', |
| | | '3': '50-69岁', |
| | | '4': '≥70岁', |
| | | '0-17': '≤17岁', |
| | | '18-49': '18-49岁', |
| | | '50-69': '50-69岁', |
| | | '70-100': '≥70岁' |
| | | }; |
| | | |
| | | export default { |
| | | name: "home", |
| | | props: {}, |
| | | components: { |
| | | MapChart, |
| | | BarChart, |
| | | BarChart2, |
| | | BarChart3, |
| | | BarChartH, |
| | | LineChart, |
| | | Line1Chart, |
| | | Line2Chart, |
| | | }, |
| | | name: 'home', |
| | | components: { CountTo, G2PlotChart, MapChart }, |
| | | data() { |
| | | return { |
| | | img: { |
| | | head: require("../../assets/images/dv-head.png"), |
| | | btn1: require("../../assets/images/dv-btn-1.png"), |
| | | btn2: require("../../assets/images/dv-btn-2.png"), |
| | | btn3: require("../../assets/images/dv-btn-3.png"), |
| | | btn4: require("../../assets/images/dv-btn-4.png"), |
| | | }, |
| | | leijishuju: {}, |
| | | arrrrr: [], |
| | | hospitallist: [], |
| | | year: "", |
| | | isloading: false, |
| | | tableLoading: false, |
| | | showTable: false, |
| | | currentArea: null, |
| | | tableList: [], |
| | | pageData: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | | total: 0, |
| | | height: 1080, |
| | | width: 1920, |
| | | isAll: true, |
| | | chartType: "map", |
| | | tableConfig: { ...DEF_TABLE_CONFIG }, |
| | | totalCount: 0, |
| | | allInfo: { |
| | | finishedOrgans: 0, |
| | | processOrgans: 4, |
| | | Organsnum: 0, |
| | | }, |
| | | anlidata: [ |
| | | { |
| | | name: "1月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "2月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "3月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "4月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "5月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "6月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "7月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "8月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "9月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "10月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "11月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "12月", |
| | | value: 0, |
| | | }, |
| | | ], |
| | | |
| | | organsum: [ |
| | | { |
| | | name: "一月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "二月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "三月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "四月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "五月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "六月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "七月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "八月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "九月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十一月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十二月", |
| | | value: 0, |
| | | }, |
| | | ], |
| | | |
| | | yiyuan: [ |
| | | { |
| | | name: "一月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "二月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "三月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "四月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "五月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "六月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "七月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "八月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "九月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十一月", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "十二月", |
| | | value: 0, |
| | | }, |
| | | ], |
| | | organData: [ |
| | | { |
| | | key: "heart", |
| | | name: "心脏", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "fullLiver", |
| | | name: "全肝", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "leftLiver", |
| | | name: "左肝", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "rightLiver", |
| | | name: "右肝", |
| | | value: 0, |
| | | }, |
| | | |
| | | { |
| | | key: "leftRenal", |
| | | name: "左肾", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "rightRenal", |
| | | name: "右肾", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "fullLung", |
| | | name: "全肺", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "leftLung", |
| | | name: "左肺", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "rightLung", |
| | | name: "右肺", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "leftEye", |
| | | name: "左眼膜", |
| | | value: 0, |
| | | }, |
| | | { |
| | | key: "rightEye", |
| | | name: "右眼膜", |
| | | value: 0, |
| | | }, |
| | | // 遗体换成全肝了 |
| | | ], |
| | | |
| | | hosGetData: [], |
| | | configHosOrgan: { |
| | | data: [], |
| | | oddRowBGC: "", |
| | | evenRowBGC: "", |
| | | rowNum: 6, |
| | | }, |
| | | organSumData: [], |
| | | cdata: [ |
| | | { |
| | | // 名字需要与 “common/map/zhejiang.js” 地图数据文件里面定义的一一对应,不能是 “福州” 或者 “闽” 之类的缩写 |
| | | name: "杭州市", |
| | | district: "1", |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | district: "2", |
| | | name: "宁波市", |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | district: "3", |
| | | name: "温州市", |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "嘉兴市", |
| | | district: "4", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "湖州市", |
| | | district: "5", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "绍兴市", |
| | | district: "6", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "金华市", |
| | | district: "7", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "衢州市", |
| | | district: "8", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "舟山市", |
| | | district: "9", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "台州市", |
| | | district: "A", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | { |
| | | name: "丽水市", |
| | | district: "B", |
| | | |
| | | value: 0, |
| | | elseData: { |
| | | value2: 0, |
| | | value3: 0, |
| | | }, |
| | | }, |
| | | ], |
| | | hospitalarr: [], |
| | | objZb: {}, //占比 |
| | | arrZb: {}, |
| | | currentZb: { |
| | | sex: -1, |
| | | age: -1, |
| | | type: -1, |
| | | d: -1, |
| | | x: -1, |
| | | }, |
| | | loopShowZb: null, |
| | | cdataYear: [], |
| | | organYearData: [], |
| | | configSex: { |
| | | data: [], |
| | | lineWidth: 6, |
| | | digitalFlopStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | configAge: { |
| | | data: [], |
| | | lineWidth: 6, |
| | | digitalFlopStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | configDd: { |
| | | data: [], |
| | | lineWidth: 6, |
| | | digitalFlopStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | configD: { |
| | | data: [], |
| | | lineWidth: 6, |
| | | digitalFlopStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | configX: { |
| | | data: [], |
| | | lineWidth: 6, |
| | | digitalFlopStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | cityDonoateCaseArr: [], |
| | | now: '', |
| | | clockTimer: null, |
| | | carouselTimer: null, |
| | | loading: false, |
| | | loginLoading: false, |
| | | dialogVisible: true, |
| | | defaultAccount: '', |
| | | defaultPassword: '', |
| | | form: {}, |
| | | carouselIndex: 0, |
| | | raw: { |
| | | mapData: [], |
| | | gauges: [], |
| | | caseTrend: [], |
| | | organMoon: [], |
| | | caseBloodType: [], |
| | | caseSex: [], |
| | | organType: [], |
| | | organDiscard: [], |
| | | caseTrendArea: [], |
| | | totals: [], |
| | | caseAvgAge: [] |
| | | } |
| | | }; |
| | | }, |
| | | computed: { |
| | | kpiCards() { |
| | | const t = this.raw.totals[0] || {}; |
| | | const potential = toNum(t.totalPotential); |
| | | const completed = toNum(t.totalCompletion); |
| | | const age = toNum((this.raw.caseAvgAge[0] || {}).avgAge); |
| | | const getTotal = this.raw.organMoon.reduce( |
| | | (s, i) => s + toNum(i.getCount), |
| | | 0 |
| | | ); |
| | | const useTotal = this.raw.organMoon.reduce( |
| | | (s, i) => s + toNum(i.useCount), |
| | | 0 |
| | | ); |
| | | return [ |
| | | { |
| | | label: '总潜在捐献案例', |
| | | value: potential, |
| | | unit: '例', |
| | | icon: 'el-icon-s-flag', |
| | | gradient: 'linear-gradient(135deg,#1d4ed8,#38bdf8)' |
| | | }, |
| | | { |
| | | label: '总完成捐献', |
| | | value: completed, |
| | | unit: '例', |
| | | icon: 'el-icon-circle-check', |
| | | gradient: 'linear-gradient(135deg,#059669,#34d399)' |
| | | }, |
| | | { |
| | | label: '平均年龄', |
| | | value: age, |
| | | unit: '岁', |
| | | icon: 'el-icon-user', |
| | | decimals: 1, |
| | | gradient: 'linear-gradient(135deg,#7c3aed,#a78bfa)' |
| | | }, |
| | | { |
| | | label: '器官获取总数', |
| | | value: getTotal, |
| | | unit: '个', |
| | | icon: 'el-icon-box', |
| | | gradient: 'linear-gradient(135deg,#0e7490,#22d3ee)' |
| | | }, |
| | | { |
| | | label: '器官移植总数', |
| | | value: useTotal, |
| | | unit: '个', |
| | | icon: 'el-icon-s-help', |
| | | gradient: 'linear-gradient(135deg,#d97706,#fbbf24)' |
| | | } |
| | | ]; |
| | | }, |
| | | gaugeCharts() { |
| | | return this.raw.gauges.map(g => ({ name: g.name, options: this.buildGauge(g) })); |
| | | }, |
| | | trendOptions() { |
| | | const data = []; |
| | | this.raw.caseTrend.forEach(d => { |
| | | data.push({ |
| | | time: this.fmtMonth(d.donateTime), |
| | | type: '潜在捐献', |
| | | value: toNum(d.potentialCount) |
| | | }); |
| | | data.push({ |
| | | time: this.fmtMonth(d.donateTime), |
| | | type: '完成捐献', |
| | | value: toNum(d.completeCount) |
| | | }); |
| | | }); |
| | | return { |
| | | data, |
| | | xField: 'time', |
| | | yField: 'value', |
| | | seriesField: 'type', |
| | | smooth: true, |
| | | color: ['#38a5f8', '#34d399'], |
| | | legend: legend(), |
| | | xAxis: xAxis(), |
| | | yAxis: yAxis(), |
| | | tooltip: tooltip(), |
| | | line: { size: 3 }, |
| | | areaStyle: { fillOpacity: 0.16 } |
| | | }; |
| | | }, |
| | | organMoonOptions() { |
| | | const data = []; |
| | | this.raw.organMoon.forEach(d => { |
| | | data.push({ |
| | | time: this.fmtMonth(d.donateTime), |
| | | type: '获取', |
| | | value: toNum(d.getCount) |
| | | }); |
| | | data.push({ |
| | | time: this.fmtMonth(d.donateTime), |
| | | type: '移植', |
| | | value: toNum(d.useCount) |
| | | }); |
| | | }); |
| | | return { |
| | | data, |
| | | xField: 'time', |
| | | yField: 'value', |
| | | seriesField: 'type', |
| | | smooth: true, |
| | | color: ['#22d3ee', '#fbbf24'], |
| | | lineStyle: { lineWidth: 3 }, |
| | | point: { size: 4, shape: 'circle' }, |
| | | legend: legend(), |
| | | xAxis: xAxis(), |
| | | yAxis: yAxis(), |
| | | tooltip: tooltip() |
| | | }; |
| | | }, |
| | | // 男女比例(按年龄段汇总为总体男女) |
| | | sexRatioOptions() { |
| | | let man = 0; |
| | | let woman = 0; |
| | | this.raw.caseSex.forEach(d => { |
| | | man += toNum(d.manCount); |
| | | woman += toNum(d.womanCount); |
| | | }); |
| | | const data = [ |
| | | { type: '男', value: man }, |
| | | { type: '女', value: woman } |
| | | ]; |
| | | return { |
| | | data, |
| | | angleField: 'value', |
| | | colorField: 'type', |
| | | radius: 0.85, |
| | | innerRadius: 0.62, |
| | | color: ['#38a5f8', '#fb7185'], |
| | | label: { |
| | | type: 'spider', |
| | | content: '{percentage}', |
| | | style: { fill: '#c3cde4' } |
| | | }, |
| | | legend: legend({ position: 'bottom' }), |
| | | tooltip: tooltip({ showTitle: false }) |
| | | }; |
| | | }, |
| | | // 年龄与性别分布 |
| | | ageSexOptions() { |
| | | const data = []; |
| | | this.raw.caseSex.forEach(d => { |
| | | const g = AGE_LABELS[d.ageGroup] || d.ageGroup; |
| | | data.push({ age: g, type: '男', value: toNum(d.manCount) }); |
| | | data.push({ age: g, type: '女', value: toNum(d.womanCount) }); |
| | | }); |
| | | return { |
| | | data, |
| | | xField: 'age', |
| | | yField: 'value', |
| | | seriesField: 'type', |
| | | isGroup: true, |
| | | columnWidthRatio: 0.4, |
| | | color: ['#38a5f8', '#fb7185'], |
| | | legend: legend(), |
| | | xAxis: xAxis(), |
| | | yAxis: yAxis(), |
| | | tooltip: tooltip() |
| | | }; |
| | | }, |
| | | organTypeOptions() { |
| | | const data = []; |
| | | this.raw.organType.forEach(d => { |
| | | data.push({ organ: d.organName, type: '获取', value: toNum(d.getCount) }); |
| | | data.push({ organ: d.organName, type: '移植', value: toNum(d.useCount) }); |
| | | }); |
| | | return { |
| | | data, |
| | | xField: 'value', |
| | | yField: 'organ', |
| | | seriesField: 'type', |
| | | isGroup: true, |
| | | barWidthRatio: 0.6, |
| | | color: ['#22d3ee', '#fbbf24'], |
| | | legend: legend(), |
| | | xAxis: yAxis(), |
| | | yAxis: xAxis(), |
| | | tooltip: tooltip() |
| | | }; |
| | | }, |
| | | // 器官弃用情况 |
| | | discardOptions() { |
| | | const data = this.raw.organDiscard.map(d => ({ |
| | | organ: d.organName, |
| | | value: toNum(d.discardCount) |
| | | })); |
| | | return { |
| | | data, |
| | | xField: 'organ', |
| | | yField: 'value', |
| | | columnWidthRatio: 0.5, |
| | | color: '#fb7185', |
| | | legend: false, |
| | | xAxis: xAxis({ label: { autoRotate: true } }), |
| | | yAxis: yAxis(), |
| | | tooltip: tooltip() |
| | | }; |
| | | }, |
| | | areaOptions() { |
| | | const data = []; |
| | | this.raw.caseTrendArea.forEach(d => { |
| | | const name = String(d.area || '').replace('地区', ''); |
| | | data.push({ |
| | | area: name, |
| | | type: '潜在捐献', |
| | | value: toNum(d.potentialCount) |
| | | }); |
| | | data.push({ |
| | | area: name, |
| | | type: '完成捐献', |
| | | value: toNum(d.completeCount) |
| | | }); |
| | | }); |
| | | return { |
| | | data, |
| | | xField: 'area', |
| | | yField: 'value', |
| | | seriesField: 'type', |
| | | isGroup: true, |
| | | columnWidthRatio: 0.45, |
| | | color: ['#38a5f8', '#34d399'], |
| | | legend: legend(), |
| | | xAxis: xAxis({ label: { autoRotate: true } }), |
| | | yAxis: yAxis(), |
| | | tooltip: tooltip() |
| | | }; |
| | | }, |
| | | carouselItems() { |
| | | return [ |
| | | { title: '男女比例', type: 'ring', options: this.sexRatioOptions }, |
| | | { title: '器官类型分布', type: 'bar', options: this.organTypeOptions }, |
| | | { title: '器官弃用情况', type: 'column', options: this.discardOptions }, |
| | | { title: '年龄与性别分布', type: 'column', options: this.ageSexOptions } |
| | | ]; |
| | | }, |
| | | currentCarousel() { |
| | | return this.carouselItems[this.carouselIndex] || this.carouselItems[0]; |
| | | } |
| | | }, |
| | | created() { |
| | | this.height = window.innerHeight - 72; |
| | | //this.getinfos(); |
| | | //this.getOrgansOfHospitalByMonthss(); |
| | | this.startClock(); |
| | | }, |
| | | mounted() { |
| | | removeToken(); |
| | | let defaultAccount = "cockpit"; |
| | | let defaultPassword = "Admin@123"; |
| | | let code; |
| | | let uuid; |
| | | login(defaultAccount, defaultPassword, code, uuid) |
| | | .then(async (res) => { |
| | | debugger |
| | | setToken(res.token); |
| | | await this.getDictData(); |
| | | this.getinfos(); |
| | | this.getData(); |
| | | // this.getList(); |
| | | this.getAllInfo(); |
| | | this.getdonatecount(); |
| | | this.getorgancount(); |
| | | this.getDonateNumbers(); |
| | | this.get(); |
| | | this.getcountDonateHostipal(); |
| | | //按月度统计的器官数 折线图 |
| | | //this.getcurrentmonthorgan(); |
| | | // this.getcurrentPeopleBymonth(); |
| | | this.getOrgansOfHospitalByMonths(); |
| | | //this.getOrgansOfHospitalByMonthss(); |
| | | //resolve() |
| | | }) |
| | | .catch((error) => { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | beforeDestroy() { |
| | | if (this.clockTimer) clearInterval(this.clockTimer); |
| | | if (this.carouselTimer) clearInterval(this.carouselTimer); |
| | | }, |
| | | methods: { |
| | | getOrgansOfHospitalByMonthss() { |
| | | var date = new Date(); |
| | | var year = date.getFullYear(); |
| | | var month = date.getMonth(); |
| | | month = Number(month) + 1; |
| | | if (month < 10) { |
| | | month = "0" + month; |
| | | } |
| | | var data = date.getDate(); |
| | | if (data < 10) { |
| | | data = "0" + data; |
| | | } |
| | | var hours = date.getHours(); |
| | | var minute = date.getMinutes(); |
| | | var second = date.getSeconds(); |
| | | var time = |
| | | year + |
| | | "-" + |
| | | month + |
| | | "-" + |
| | | data + |
| | | " " + |
| | | hours + |
| | | ":" + |
| | | minute + |
| | | ":" + |
| | | second; |
| | | let params = { |
| | | starttime: "1998-01-01 00:00:00", |
| | | endtime: time, |
| | | }; |
| | | getOrgansOfHospitalByMonth(params).then((res) => { |
| | | let hospitalarr = res.data; |
| | | // this.hospitalarr = hospitalarr |
| | | let shi = [ |
| | | { name: "省本级", value: "0" }, |
| | | { name: "杭州市", value: "1" }, |
| | | { name: "宁波市", value: "2" }, |
| | | { name: "温州市", value: "3" }, |
| | | { name: "嘉兴市", value: "4" }, |
| | | { name: "湖州市", value: "5" }, |
| | | { name: "绍兴市", value: "6" }, |
| | | { name: "金华市", value: "7" }, |
| | | { name: "衢州市", value: "8" }, |
| | | { name: "舟山市", value: "9" }, |
| | | { name: "台州市", value: "A" }, |
| | | { name: "丽水市", value: "B" }, |
| | | ]; |
| | | |
| | | for (let i = 0; i < hospitalarr.length; i++) { |
| | | for (let j = 0; j < shi.length; j++) { |
| | | if (hospitalarr[i].regionLevel == shi[j].value) { |
| | | hospitalarr[i].regionLevel = shi[j].name; |
| | | fmtMonth(value) { |
| | | const m = toMonth(value); |
| | | if (!m) return ''; |
| | | const mm = Number(m.split('-')[1]); |
| | | return mm ? `${mm}月` : m; |
| | | }, |
| | | buildGauge(g) { |
| | | const pct = g.max ? Math.min(Math.max(g.value / g.max, 0), 1) : 0; |
| | | const suffix = g.max === 100 ? '%' : ''; |
| | | return { |
| | | percent: pct, |
| | | startAngle: Math.PI, |
| | | endAngle: Math.PI * 2, |
| | | radius: 0.85, |
| | | innerRadius: 0.72, |
| | | range: { color: [g.color, '#1c2a4d'], width: 10 }, |
| | | axis: { |
| | | label: null, |
| | | tickLine: { style: { stroke: '#2a3a63' } } |
| | | }, |
| | | indicator: { |
| | | pointer: { style: { stroke: '#e6edff', lineWidth: 2 } }, |
| | | pin: { style: { stroke: '#e6edff', lineWidth: 2, r: 4 } } |
| | | }, |
| | | statistic: { |
| | | content: { |
| | | content: `${g.value}${suffix}`, |
| | | style: { |
| | | color: '#ffffff', |
| | | fontSize: 30, |
| | | fontWeight: 700, |
| | | lineHeight: 1, |
| | | opacity: 1 |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | getOrgansOfHospitalByMonths() { |
| | | let curYear = this.$moment().year(); |
| | | let params = { |
| | | starttime: this.$moment().format(curYear + "-01-01 00:00:00"), |
| | | endtime: this.$moment().format("YYYY-MM-DD 00:00:00"), |
| | | }; |
| | | getOrgansOfHospitalByMonth(params).then((res) => { |
| | | let arr = []; |
| | | arr = res.data; |
| | | let shi = [ |
| | | { name: "省本级", value: "0" }, |
| | | { name: "杭州市", value: "1" }, |
| | | { name: "宁波市", value: "2" }, |
| | | { name: "温州市", value: "3" }, |
| | | { name: "嘉兴市", value: "4" }, |
| | | { name: "湖州市", value: "5" }, |
| | | { name: "绍兴市", value: "6" }, |
| | | { name: "金华市", value: "7" }, |
| | | { name: "衢州市", value: "8" }, |
| | | { name: "舟山市", value: "9" }, |
| | | { name: "台州市", value: "A" }, |
| | | { name: "丽水市", value: "B" }, |
| | | ]; |
| | | let newConfig = { |
| | | ...DEF_TABLE_CONFIG, |
| | | }; |
| | | let arrr = []; |
| | | for (let i = 0; i < arr.length; i++) { |
| | | for (let j = 0; j < shi.length; j++) { |
| | | if (arr[i].regionLevel == shi[j].value) { |
| | | arr[i].regionLevel = shi[j].name; |
| | | } |
| | | } |
| | | arrr.push({ |
| | | regionLevel: arr[i].regionLevel, |
| | | hospitalName: arr[i].hospitalName, |
| | | donateNumber: arr[i].baseInfoCount, |
| | | acceptNumber: arr[i].completionCount, |
| | | }); |
| | | } |
| | | this.arrrrr = arrr; |
| | | newConfig.data = arrr; |
| | | this.tableConfig = newConfig; |
| | | }); |
| | | }, |
| | | refresh() { |
| | | if (this.showTable) { |
| | | this.getList(); |
| | | } else { |
| | | this.getData(); |
| | | startClock() { |
| | | const tick = () => { |
| | | this.now = this.$moment().format('YYYY-MM-DD HH:mm:ss'); |
| | | }; |
| | | tick(); |
| | | this.clockTimer = setInterval(tick, 1000); |
| | | }, |
| | | startCarousel() { |
| | | if (this.carouselTimer) clearInterval(this.carouselTimer); |
| | | this.carouselTimer = setInterval(() => { |
| | | this.carouselIndex = |
| | | (this.carouselIndex + 1) % this.carouselItems.length; |
| | | }, 5000); |
| | | }, |
| | | loginFn() { |
| | | if (!this.defaultAccount || !this.defaultPassword) { |
| | | this.$message.warning('请输入账号和密码'); |
| | | return; |
| | | } |
| | | }, |
| | | //柱状图数据 |
| | | getinfos() {}, |
| | | |
| | | //当前年份按月度统计的捐献器官数 |
| | | getcurrentmonthorgan() { |
| | | let nowYear = this.$moment().year(); |
| | | let params = { |
| | | starttime: this.$moment(nowYear + "-01-01").format("YYYY-01-01 00:00:00"), |
| | | endtime: this.$moment().format("YYYY-MM-DD 00:00:00"), |
| | | }; |
| | | getdonateNumberByMonth(params).then((res) => { |
| | | let donateorgans = res.data; |
| | | let arr1 = []; |
| | | let num = 0; |
| | | for (let i = 0; i < donateorgans.length; i++) { |
| | | num = donateorgans[i].donatemonth.substring(0, 4); |
| | | // if (this.year == num) { |
| | | arr1.push(donateorgans[i]); |
| | | for (let i = 0; i < arr1.length; i++) { |
| | | let month = arr1[i].donatemonth; |
| | | month = month.substring(month.length - 2, month.length); |
| | | let donatecount = arr1[i].donatecount; |
| | | this.organsum[month - 1].value = donatecount; |
| | | } |
| | | // } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | getcountDonateHostipal() { |
| | | let nowYear = this.$moment().year(); |
| | | let a = { |
| | | // starttime: "2020-01-01 00:00:00", |
| | | // endtime: "2022-02-01 00:00:00", //???? |
| | | starttime: this.$moment(nowYear + "-01-01").format("YYYY-01-01 00:00:00"), |
| | | endtime: this.$moment().format("YYYY-MM-DD 00:00:00"), |
| | | }; |
| | | countDonateHostipal(a).then((res) => { |
| | | let donateorgans = res.data; |
| | | let arr3 = []; |
| | | let num = 0; |
| | | for (let i = 0; i < donateorgans.length; i++) { |
| | | num = donateorgans[i].donatemonth.substring(0, 4); |
| | | arr3.push(donateorgans[i]); |
| | | for (let i = 0; i < arr3.length; i++) { |
| | | let month = arr3[i].donatemonth; |
| | | month = month.substring(month.length - 2, month.length); |
| | | let donatecount = arr3[i].donatecount; |
| | | this.yiyuan[month - 1].value = donatecount; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | get() {}, |
| | | //捐献累计信息 |
| | | getDonateNumbers() { |
| | | let paramStartTime = null; |
| | | let nowDateYear = this.$moment().year(); |
| | | paramStartTime = this.$moment(nowDateYear + "-01-01").format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ); |
| | | let a = { |
| | | starttime: paramStartTime, |
| | | endtime: this.$moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | |
| | | getDonateorganDistrictDonateCalculate(a).then((res) => { |
| | | let cityCaseArr = []; |
| | | let data = res.data; |
| | | for (let i = 0; i < data.length; i++) { |
| | | let ii = this.cdata.findIndex( |
| | | (item) => item.district == data[i].district |
| | | ); |
| | | if (ii > -1) { |
| | | this.cdata[ii].value = data[i].donateCount; |
| | | this.cdata[ii].elseData.value2 = data[i].completeCount; |
| | | this.cdata[ii].elseData.value3 = data[i].totalOrganCount; |
| | | cityCaseArr.push({ |
| | | cityName: this.cdata[ii].name, |
| | | donoateNum: data[i].donateCount, |
| | | }); |
| | | } |
| | | } |
| | | this.cityDonoateCaseArr = cityCaseArr; |
| | | }); |
| | | getDonateNumber(a).then((res) => { |
| | | console.log("捐献累计信息", res); |
| | | this.leijishuju.processOrgans = res.data.numberOfDonate; |
| | | this.leijishuju.finishedOrgans = res.data.numberOfCompletion; |
| | | this.leijishuju.Organsnum = res.data.numberOfOrgans; |
| | | }); |
| | | |
| | | getDonateorganPMP(a).then((res) => { |
| | | console.log("PMP", res); |
| | | let data = res.data; |
| | | this.leijishuju.PMP = ((data.pmprate * 100) / 64).toFixed(2); |
| | | }); |
| | | |
| | | getDonateorganQuality(a).then((res) => { |
| | | let data = res.data; |
| | | this.leijishuju.donateTransferRate = data.donateTransferRate; |
| | | this.leijishuju.organProductionRate = data.organProductionRate; |
| | | this.leijishuju.organUsedRate = data.organUsedRate; |
| | | this.$forceUpdate(); |
| | | }); |
| | | getDonationwitnessStats(a).then((res) => { |
| | | |
| | | console.log("各种占比", res); |
| | | let data = res.data; |
| | | |
| | | this.objZb = { ...data }; |
| | | this.arrZb = { |
| | | sex: [ |
| | | { label: "男", value: data.manRate }, |
| | | { label: "女", value: data.womanRate }, |
| | | ], |
| | | age: [ |
| | | { label: "1-17岁", value: data.a1Rate }, |
| | | { label: "18-48岁", value: data.a2Rate }, |
| | | { label: "49-69岁", value: data.a2Rate }, |
| | | ], |
| | | type: [ |
| | | { label: "DBD", value: data.dbdrate }, |
| | | { label: "DCD", value: data.dcdrate }, |
| | | { label: "DBCD", value: data.dbcdrate }, |
| | | ], |
| | | d: [ |
| | | { label: "脑血管意外", value: data.d0Rate }, |
| | | { label: "脑外伤", value: data.d1Rate }, |
| | | { label: "缺血缺氧性脑病", value: data.d2Rate }, |
| | | { label: "脑肿瘤", value: data.d3Rate }, |
| | | { label: "心血管疾病", value: data.d4Rate }, |
| | | ], |
| | | x: [ |
| | | { label: "A型", value: data.xarate }, |
| | | { label: "B型", value: data.xbrate }, |
| | | { label: "AB型", value: data.xabrate }, |
| | | { label: "O型", value: data.xorate }, |
| | | ], |
| | | }; |
| | | |
| | | window.clearInterval(this.loopShowZb); |
| | | this.loopShowZb = setInterval(() => { |
| | | if (this.currentZb.sex < this.arrZb.sex.length - 1) { |
| | | this.currentZb.sex += 1; |
| | | this.loginLoading = true; |
| | | login(encrypts(this.defaultAccount), encrypts(this.defaultPassword)) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | setToken(res.token); |
| | | this.dialogVisible = false; |
| | | this.$message.success('登录成功'); |
| | | this.loadData(); |
| | | } else { |
| | | this.currentZb.sex = 0; |
| | | } |
| | | if (this.currentZb.age < this.arrZb.age.length - 1) { |
| | | this.currentZb.age += 1; |
| | | } else { |
| | | this.currentZb.age = 0; |
| | | } |
| | | if (this.currentZb.type < this.arrZb.type.length - 1) { |
| | | this.currentZb.type += 1; |
| | | } else { |
| | | this.currentZb.type = 0; |
| | | } |
| | | if (this.currentZb.d < this.arrZb.d.length - 1) { |
| | | this.currentZb.d += 1; |
| | | } else { |
| | | this.currentZb.d = 0; |
| | | } |
| | | if (this.currentZb.x < this.arrZb.x.length - 1) { |
| | | this.currentZb.x += 1; |
| | | } else { |
| | | this.currentZb.x = 0; |
| | | } |
| | | }, 3000); |
| | | }); |
| | | |
| | | getTransplantHospitalNum(a).then((res) => { |
| | | console.log("每家移植医院获取的器官总数", res); |
| | | let data = res.data; |
| | | let list = data.map((item) => { |
| | | return [item.orgName, item.organCount]; |
| | | }); |
| | | list = list.filter((item) => !item[0].includes("眼")); |
| | | this.configHosOrgan.data = list; |
| | | this.hosGetData = data.map((item) => { |
| | | return { |
| | | name: item.orgName, |
| | | value: item.organCount, |
| | | }; |
| | | }); |
| | | }); |
| | | |
| | | getDonateorganSum(a).then((res) => { |
| | | console.log("各种器官的获取总数", res); |
| | | let data = res.data; |
| | | let list = this.organSumData.map((item) => item); |
| | | for (let i = 0; i < data.length; i++) { |
| | | let k = data[i].organNo; |
| | | let ii = this.organSumData.findIndex((item) => item.key == k); |
| | | if (ii > -1) { |
| | | this.organSumData[ii].value = data[i].count; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | //历年数据 |
| | | let startTime = "2019-01-01 00:00:00"; |
| | | let endTime = this.$moment().format("YYYY-01-01 00:00:00"); |
| | | endTime = this.$moment(endTime) |
| | | .add(1, "years") |
| | | .format("YYYY-01-01 00:00:00"); |
| | | let dYear = this.$moment(endTime).diff(this.$moment(startTime), "years"); |
| | | |
| | | if (dYear > 5) { |
| | | startTime == |
| | | this.$moment(endtime).add(-5, "year").format("YYYY-01-01 00:00:00"); |
| | | } |
| | | |
| | | let arrYear = []; |
| | | for (let i = 0; i < 6; i++) { |
| | | let year = this.$moment(startTime).add(i, "year").format("YYYY"); |
| | | if (i >= dYear) { |
| | | year = ""; |
| | | continue; |
| | | } |
| | | arrYear.push({ |
| | | year: year, |
| | | num: year ? 0 : "", |
| | | }); |
| | | } |
| | | let params = { |
| | | starttime: startTime, |
| | | endtime: endTime, |
| | | }; |
| | | // getdonateNumberByMonth ???//带注释 |
| | | getdonatePeopleByMonth(params).then((res) => { |
| | | let data = res.data; |
| | | for (let i = 0; i < data.length; i++) { |
| | | let year = this.$moment(data[i].donatemonth).format("YYYY"); |
| | | |
| | | let ii = arrYear.findIndex((item) => item.year == year); |
| | | if (ii > -1) { |
| | | arrYear[ii].num += data[i].donatecount; |
| | | } |
| | | } |
| | | this.cdataYear = arrYear; |
| | | console.log("cdataYear:" + JSON.stringify(this.cdataYear)); |
| | | }); |
| | | }, |
| | | |
| | | async getDictData() { |
| | | try { |
| | | let res = await listData({ |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | dictType: "sys_Organ", |
| | | }); |
| | | let list = res.rows.map((item) => { |
| | | return { |
| | | key: item.dictValue, |
| | | name: item.dictLabel, |
| | | value: 0, |
| | | }; |
| | | }); |
| | | this.organSumData = list.filter( |
| | | (it) => it.key != "C00" |
| | | ); |
| | | } catch (e) {} |
| | | }, |
| | | |
| | | async getdonatecount() { |
| | | let nowDateYear = this.$moment().year(); |
| | | let nowDateMonth = this.$moment().month() + 1; |
| | | let startTime; |
| | | let endTime = this.$moment().add(1, "month").format("YYYY-MM-01"); |
| | | if (nowDateMonth <= 5) { |
| | | startTime = this.$moment().add(-6, "month").format("YYYY-MM-01"); |
| | | } else { |
| | | startTime = this.$moment().format(nowDateYear + "-01-01"); |
| | | } |
| | | |
| | | let donateorgans = []; |
| | | let organList = []; |
| | | |
| | | let params = { |
| | | starttime: startTime, |
| | | endtime: endTime, |
| | | }; |
| | | |
| | | try { |
| | | let res = await countDonateorgan(params); |
| | | donateorgans = res.data; |
| | | console.log("donateorgans:" + JSON.stringify(donateorgans)) |
| | | } catch (e) {} |
| | | debugger |
| | | try { |
| | | let res = await getdonateNumberByMonth(params); |
| | | organList = res.data; |
| | | console.log("organList:" + JSON.stringify(organList)) |
| | | } catch (e) {} |
| | | debugger |
| | | console.log(donateorgans); |
| | | let arr = []; |
| | | for (let i = 0; i < 12; i++) { |
| | | //统计捐献案例月度统计数据 |
| | | let mm = this.$moment(startTime).add(i, "month").format("YYYY-MM"); |
| | | let num = ""; |
| | | let num2 = ""; |
| | | let ii = donateorgans.findIndex((item) => item.donatemonth == mm); |
| | | if (ii > -1) { |
| | | num = donateorgans[ii].donatecount; |
| | | } |
| | | let oi = organList.findIndex((item) => item.donatemonth == mm); |
| | | if (oi > -1) { |
| | | num2 = organList[oi].donatecount; |
| | | } |
| | | arr.push({ |
| | | name: this.$moment(mm).format("M月"), |
| | | value: num, |
| | | value2: num2, |
| | | }); |
| | | } |
| | | |
| | | let organYearArr = []; |
| | | this.anlidata = arr; |
| | | |
| | | for (let k = 0; k < organList.length; k++) { |
| | | let yearNo = this.$moment(organList[k].donatemonth + "-01").format( |
| | | "YYYY" |
| | | ); |
| | | let organNum = organList[k].donatecount; |
| | | //判断当前年份是否在数组中 |
| | | let yearIndex = organYearArr.findIndex((item) => item.year == yearNo); |
| | | if (yearIndex > -1) { |
| | | organYearArr[yearIndex].num += organNum; |
| | | } else { |
| | | organYearArr.push({ year: yearNo, num: organNum }); |
| | | } |
| | | } |
| | | this.organYearData = organYearArr; |
| | | }, |
| | | getorgancount() {}, |
| | | |
| | | getData() {}, |
| | | |
| | | getAllInfo() { |
| | | let params = { |
| | | starttime: "2022-01-01 00:00:00", |
| | | endtime: this.$moment().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | getAllOrganInfo(params) |
| | | .then((response) => { |
| | | if (response.data) { |
| | | this.allInfo = response.data; |
| | | let list = this.organData.map((item) => item); |
| | | for (let i = 0; i < list.length; i++) { |
| | | let k = list[i].key; |
| | | if (this.allInfo[k]) { |
| | | list.value = this.allInfo[k]; |
| | | this.organData[i].value = list.value; |
| | | } |
| | | } |
| | | this.organData = list; |
| | | let organsums = 0; |
| | | this.$message.error(res.msg || '登录失败'); |
| | | } |
| | | }) |
| | | .catch((erroe) => {}) |
| | | .finally(() => {}); |
| | | .catch(() => { |
| | | // 请求失败由 request 拦截器统一提示 |
| | | }) |
| | | .finally(() => { |
| | | this.loginLoading = false; |
| | | }); |
| | | }, |
| | | async getTempList() { |
| | | let total = 0; |
| | | let pageIndex = 1; |
| | | let list = []; |
| | | handleLogout() { |
| | | removeToken(); |
| | | this.dialogVisible = true; |
| | | this.$message.info('已退出登录'); |
| | | }, |
| | | mapClick() { |
| | | // 区县点击可在此扩展下钻 |
| | | }, |
| | | async loadData() { |
| | | this.loading = true; |
| | | try { |
| | | let searchInfo = { |
| | | pageNum: 1, |
| | | pageSize: 1, |
| | | }; |
| | | let response = await listDonatebaseinfo(searchInfo); |
| | | this.totalCount = response.total; |
| | | } catch (error) {} |
| | | }, |
| | | mapClick(data) { |
| | | let newConfig = { |
| | | ...DEF_TABLE_CONFIG, |
| | | }; |
| | | let arr = []; |
| | | for (let i = 0; i < this.arrrrr.length; i++) { |
| | | if (data.name == this.arrrrr[i].regionLevel) { |
| | | arr.push(this.arrrrr[i]); |
| | | } |
| | | // 后端接口就绪后,将下面模拟数据替换为真实接口: |
| | | // 趋势/性别/器官/地区/KPI → /opo/totals/*(@/api/businessApi/statistics.js) |
| | | // 区县地图 → getDonateorganDistrictDonateCalculate; |
| | | // 仪表盘 → getDonateorganQuality / getDonateorganPMP; |
| | | // 器官弃用 → 统计模块器官弃用相关接口(@/api/businessApi/statistics.js) |
| | | const m = mockCockpitData(); |
| | | this.raw.mapData = m.mapData; |
| | | this.raw.gauges = m.gauges; |
| | | this.raw.caseTrend = m.caseTrend; |
| | | this.raw.organMoon = m.organMoon; |
| | | this.raw.caseBloodType = m.caseBloodType; |
| | | this.raw.caseSex = m.caseSex; |
| | | this.raw.organType = m.organType; |
| | | this.raw.organDiscard = m.organDiscard; |
| | | this.raw.caseTrendArea = m.caseTrendArea; |
| | | this.raw.totals = m.totals; |
| | | this.raw.caseAvgAge = m.caseAvgAge; |
| | | this.startCarousel(); |
| | | } catch (e) { |
| | | console.error('驾驶舱数据加载失败', e); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | newConfig.data = arr; |
| | | this.tableConfig = newConfig; |
| | | // let name = data.name; |
| | | // let arr = []; |
| | | |
| | | // for(let i=0;i<this.arrrrr.length;i++){ |
| | | // if(this.arrrr[i].regionLevel == name){ |
| | | // arr.push({ |
| | | // regionLevel : this.arrrrr[i].regionLevel, |
| | | // hospitalName : this.arrrrr[i].hospitalName, |
| | | // donateNumber : this.arrrrr[i].baseInfoCount, |
| | | // acceptNumber : this.arrrrr[i].completionCount |
| | | // }) |
| | | // } |
| | | // } |
| | | // this.arrrr = arr; |
| | | // this.currentArea = { ...data }; |
| | | // this.tableList = []; |
| | | // this.total = 0; |
| | | // this.pageData.pageNum = 1; |
| | | // this.showTable = true; |
| | | // this.getList(data.name); |
| | | }, |
| | | getRanNum() { |
| | | return Math.round(Math.random() * 40); |
| | | }, |
| | | }, |
| | | computed: { |
| | | heightA() { |
| | | let h = (this.height * 0.36 - 54) / 5; |
| | | return h; |
| | | }, |
| | | totalValue() { |
| | | let sum = 0; |
| | | for (let i = 0; i < this.cdata.length; i++) { |
| | | sum += this.cdata[i].value; |
| | | } |
| | | return sum; |
| | | }, |
| | | totalValue2() { |
| | | let sum = 0; |
| | | for (let i = 0; i < this.cdata.length; i++) { |
| | | sum += this.cdata[i].elseData.value2; |
| | | } |
| | | return sum; |
| | | }, |
| | | totalValue3() { |
| | | let sum = 0; |
| | | for (let i = 0; i < this.cdata.length; i++) { |
| | | sum += this.cdata[i].elseData.value3; |
| | | } |
| | | return sum; |
| | | }, |
| | | }, |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | #app { |
| | | overflow: hidden; |
| | | .cockpit { |
| | | min-height: 100vh; |
| | | padding: 14px 16px 20px; |
| | | box-sizing: border-box; |
| | | color: #e6edff; |
| | | background: radial-gradient( |
| | | 1200px 640px at 18% -10%, |
| | | #12275a 0%, |
| | | rgba(18, 39, 90, 0) 60% |
| | | ), |
| | | radial-gradient(1000px 600px at 110% 10%, #0c2a52 0%, rgba(12, 42, 82, 0) 55%), |
| | | linear-gradient(180deg, #0a1226 0%, #070c1c 60%, #050812 100%); |
| | | } |
| | | .iwc-dv-box { |
| | | .iwc-box-head { |
| | | text-align: center; |
| | | font-size: 18px; |
| | | padding: 7px 0 25px; |
| | | color: #fff; |
| | | background-image: url("../../assets/images/dv-box-title.png"); |
| | | background-size: 100% 150%; |
| | | height: 54px; |
| | | } |
| | | .iwc-box-a { |
| | | font-size: 13px; |
| | | .iwc-box-a-1 { |
| | | color: #5ba2ff; |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | .iwc-before-o { |
| | | display: inline-block; |
| | | width: 11px; |
| | | height: 10px; |
| | | border-radius: 50%; |
| | | border: 0.15rem solid; |
| | | margin-right: 0.5rem; |
| | | } |
| | | .iwc-box-c { |
| | | display: flex; |
| | | padding: 1rem 0; |
| | | .iwc-box-c1 { |
| | | flex: 1; |
| | | font-size: 1rem; |
| | | text-align: center; |
| | | .iwc-box-c1-o { |
| | | display: inline-block; |
| | | width: 3.6rem; |
| | | height: 3.6rem; |
| | | line-height: 3.6rem; |
| | | margin: 0 auto; |
| | | border: 0.2rem solid; |
| | | border-radius: 50%; |
| | | } |
| | | .iwc-box-c1-l { |
| | | padding: 1rem 0; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep .el-loading-mask { |
| | | background-color: rgba(5, 8, 18, 0.75); |
| | | } |
| | | .iwc-box-d { |
| | | display: flex; |
| | | padding-top: 2rem; |
| | | .iwc-box-d-1 { |
| | | flex: 1; |
| | | position: relative; |
| | | .iwc-box-d-img { |
| | | width: 3.6rem; |
| | | height: 3.6rem; |
| | | position: absolute; |
| | | } |
| | | } |
| | | .iwc-box-d-f { |
| | | padding-left: 4rem; |
| | | padding-top: 0.5rem; |
| | | .iwc-box-d-f1 { |
| | | font-size: 1.4rem; |
| | | color: #07dbff; |
| | | height: 2rem; |
| | | } |
| | | .iwc-box-d-f2 { |
| | | color: #fff; |
| | | font-size: 0.75rem; |
| | | } |
| | | } |
| | | } |
| | | .c-home { |
| | | .fc-white { |
| | | color: #fff; |
| | | } |
| | | .fc-sp { |
| | | color: #409eff; |
| | | } |
| | | .box-title { |
| | | width: 100%; |
| | | span { |
| | | display: block; |
| | | width: 130px; |
| | | height: 25px; |
| | | -webkit-transform: skew(20deg); |
| | | -moz-transform: skew(20deg); |
| | | -o-transform: skew(20deg); |
| | | background: #1356a1; |
| | | line-height: 25px; |
| | | align-self: center; |
| | | border: 1px transparent solid; |
| | | border-image: linear-gradient(#070a17, #7be6fc) 10 10; |
| | | border-image: linear-gradient(#070a17, #7be6fc) 10 10; |
| | | border-image: linear-gradient(#070a17, #7be6fc) 10 10; |
| | | margin: 0 auto; |
| | | } |
| | | b { |
| | | display: block; |
| | | color: #fff; |
| | | text-align: center; |
| | | transform: skewY(-20deg); |
| | | transform: skewX(-20deg); |
| | | } |
| | | } |
| | | .box-num { |
| | | position: relative; |
| | | .box-num-main { |
| | | p { |
| | | margin: 0 0 10px; |
| | | } |
| | | text-align: right; |
| | | .box-num-main-n { |
| | | color: #409eff; |
| | | font-size: 25px; |
| | | } |
| | | } |
| | | .box-num-ex { |
| | | position: absolute; |
| | | bottom: 5px; |
| | | right: 10px; |
| | | width: 45px; |
| | | |
| | | span { |
| | | color: #409eff; |
| | | font-size: 12px; |
| | | } |
| | | /* 顶部标题栏 */ |
| | | .cockpit-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 6px 4px 14px; |
| | | .header-left { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .header-logo { |
| | | width: 10px; |
| | | height: 26px; |
| | | border-radius: 3px; |
| | | margin-right: 12px; |
| | | background: linear-gradient(180deg, #38a5f8, #22d3ee); |
| | | box-shadow: 0 0 12px rgba(56, 165, 248, 0.7); |
| | | } |
| | | .header-title { |
| | | margin: 0; |
| | | font-size: 22px; |
| | | font-weight: 700; |
| | | letter-spacing: 2px; |
| | | background: linear-gradient(90deg, #eaf2ff, #6db8ff); |
| | | -webkit-background-clip: text; |
| | | background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | } |
| | | .header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .header-clock { |
| | | color: #9aa7c7; |
| | | font-size: 14px; |
| | | font-variant-numeric: tabular-nums; |
| | | letter-spacing: 1px; |
| | | margin-right: 16px; |
| | | } |
| | | .header-logout { |
| | | color: #9aa7c7; |
| | | &:hover { |
| | | color: #38a5f8; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep .c-table-title { |
| | | .el-divider.el-divider--horizontal { |
| | | background-color: #95a1ec; |
| | | .el-divider__text.is-left { |
| | | color: #303133; |
| | | background: #fafafa; |
| | | } |
| | | } |
| | | .active { |
| | | .el-divider.el-divider--horizontal { |
| | | .el-divider__text.is-left { |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* KPI 指标卡 */ |
| | | .kpi-row { |
| | | display: grid; |
| | | grid-template-columns: repeat(5, 1fr); |
| | | gap: 16px; |
| | | margin-bottom: 16px; |
| | | } |
| | | ::v-deep .iwc-ring { |
| | | .dv-active-ring-chart .active-ring-info .active-ring-name { |
| | | .kpi-card { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 12px 16px; |
| | | border-radius: 12px; |
| | | border: 1px solid rgba(90, 120, 190, 0.28); |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(40, 52, 96, 0.72), |
| | | rgba(16, 24, 52, 0.9) |
| | | ); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); |
| | | } |
| | | .kpi-icon { |
| | | width: 44px; |
| | | height: 44px; |
| | | flex-shrink: 0; |
| | | border-radius: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 22px; |
| | | color: #fff; |
| | | margin-right: 12px; |
| | | box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); |
| | | } |
| | | .kpi-body { |
| | | min-width: 0; |
| | | } |
| | | .kpi-label { |
| | | font-size: 13px; |
| | | color: #8aa0c8; |
| | | margin-bottom: 2px; |
| | | } |
| | | .kpi-value { |
| | | font-size: 24px; |
| | | font-weight: 700; |
| | | color: #fff; |
| | | line-height: 1.2; |
| | | } |
| | | .kpi-unit { |
| | | font-size: 13px; |
| | | font-weight: 400; |
| | | color: #8aa0c8; |
| | | margin-left: 4px; |
| | | } |
| | | |
| | | /* 仪表盘行 */ |
| | | .gauge-row { |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | gap: 16px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* 面板 */ |
| | | .panel { |
| | | height: 100%; |
| | | padding: 14px 16px; |
| | | border-radius: 12px; |
| | | border: 1px solid rgba(80, 110, 180, 0.25); |
| | | background: linear-gradient( |
| | | 180deg, |
| | | rgba(25, 35, 70, 0.82), |
| | | rgba(13, 20, 43, 0.82) |
| | | ); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); |
| | | box-sizing: border-box; |
| | | } |
| | | .panel-title { |
| | | position: relative; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: #dbe4ff; |
| | | margin-bottom: 10px; |
| | | padding-left: 12px; |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 82px; |
| | | left: 0; |
| | | top: 2px; |
| | | bottom: 2px; |
| | | width: 4px; |
| | | border-radius: 2px; |
| | | background: linear-gradient(180deg, #38a5f8, #22d3ee); |
| | | } |
| | | } |
| | | ::v-deep .iwc-box-b-table.dv-scroll-board { |
| | | .rows { |
| | | .row-item:nth-child(2) { |
| | | border: 1px solid #02406e; |
| | | background-color: rgba(19, 187, 206, 0.13); |
| | | background-blend-mode: multiply; |
| | | //filter: drop-shadow(3px 3px 4px #07dbff); |
| | | box-shadow: 0 0 10px rgb(0, 153, 184) inset; |
| | | } |
| | | .ceil:nth-child(1) { |
| | | flex: 1; |
| | | } |
| | | .ceil:nth-child(2) { |
| | | width: 70px !important; |
| | | } |
| | | |
| | | /* 左右两列堆叠 */ |
| | | .col-stack { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | height: 100%; |
| | | .panel { |
| | | flex: 1; |
| | | } |
| | | } |
| | | ::v-deep .iwc-h-rb-table.dv-scroll-board { |
| | | .header { |
| | | color: #07dbff; |
| | | .header-item:nth-child(1) { |
| | | width: 70px !important; |
| | | } |
| | | .header-item:nth-child(2) { |
| | | flex: 1; |
| | | } |
| | | .header-item:nth-child(3) { |
| | | width: 80px !important; |
| | | } |
| | | .header-item:nth-child(4) { |
| | | width: 80px !important; |
| | | } |
| | | } |
| | | .rows { |
| | | .row-item { |
| | | border-bottom: 1px solid #036492; |
| | | } |
| | | .row-item:nth-child(2) { |
| | | border: 1px solid #07dbff; |
| | | background-color: rgba(19, 187, 206, 0.13); |
| | | background-blend-mode: multiply; |
| | | box-shadow: 0 0 10px rgb(0, 153, 184) inset; |
| | | //filter: drop-shadow(3px 3px 4px #07dbff); |
| | | } |
| | | .ceil:nth-child(1) { |
| | | width: 70px; |
| | | } |
| | | .ceil:nth-child(2) { |
| | | flex: 1; |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | } |
| | | .ceil:nth-child(3) { |
| | | width: 80px; |
| | | text-align: center; |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | } |
| | | .ceil:nth-child(4) { |
| | | width: 80px; |
| | | text-align: center; |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | } |
| | | |
| | | /* 轮播 */ |
| | | .panel--carousel { |
| | | position: relative; |
| | | } |
| | | .carousel-body { |
| | | height: 205px; |
| | | } |
| | | .carousel-dots { |
| | | position: absolute; |
| | | right: 16px; |
| | | top: 16px; |
| | | display: flex; |
| | | gap: 6px; |
| | | } |
| | | .dot { |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background: rgba(120, 140, 190, 0.35); |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | &.active { |
| | | width: 20px; |
| | | border-radius: 4px; |
| | | background: #38a5f8; |
| | | } |
| | | } |
| | | ::v-deep .iwc-box-a { |
| | | .el-progress-bar__outer { |
| | | background-color: #29345c; |
| | | .fade-enter-active, |
| | | .fade-leave-active { |
| | | transition: opacity 0.4s; |
| | | } |
| | | .fade-enter, |
| | | .fade-leave-to { |
| | | opacity: 0; |
| | | } |
| | | </style> |
| | | |
| | | <!-- 登录弹窗通过 append-to-body 挂到 body 下,scoped 样式无法命中,故用全局样式 --> |
| | | <style lang="scss"> |
| | | .el-dialog.login-dialog { |
| | | background: linear-gradient(180deg, rgba(28, 40, 78, 0.97), rgba(13, 20, 43, 0.99)); |
| | | border: 1px solid rgba(74, 120, 200, 0.45); |
| | | border-radius: 14px; |
| | | box-shadow: 0 0 0 1px rgba(56, 165, 248, 0.12), 0 0 44px rgba(56, 165, 248, 0.28), |
| | | 0 24px 60px rgba(0, 0, 0, 0.55); |
| | | overflow: hidden; |
| | | |
| | | .el-dialog__header { |
| | | padding: 22px 26px 14px; |
| | | border-bottom: 1px solid rgba(74, 120, 200, 0.22); |
| | | } |
| | | .el-progress-bar__innerText { |
| | | margin-right: -27px; |
| | | .el-dialog__title { |
| | | color: #eaf2ff; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | letter-spacing: 2px; |
| | | &::before { |
| | | content: ''; |
| | | display: inline-block; |
| | | width: 4px; |
| | | height: 16px; |
| | | margin-right: 10px; |
| | | border-radius: 2px; |
| | | background: linear-gradient(180deg, #38a5f8, #22d3ee); |
| | | box-shadow: 0 0 8px rgba(56, 165, 248, 0.8); |
| | | vertical-align: -2px; |
| | | } |
| | | } |
| | | .el-dialog__body { |
| | | padding: 26px 26px 8px; |
| | | color: #c3cde4; |
| | | } |
| | | .el-dialog__footer { |
| | | padding: 8px 26px 24px; |
| | | text-align: right; |
| | | } |
| | | |
| | | .el-form-item__label { |
| | | color: #aab6d4; |
| | | font-weight: 500; |
| | | letter-spacing: 1px; |
| | | } |
| | | .el-input__inner { |
| | | background: rgba(8, 15, 34, 0.9); |
| | | border: 1px solid rgba(90, 124, 200, 0.35); |
| | | border-radius: 6px; |
| | | color: #e6edff; |
| | | transition: border-color 0.25s, box-shadow 0.25s; |
| | | &::placeholder { |
| | | color: rgba(154, 167, 199, 0.6); |
| | | } |
| | | &:hover { |
| | | border-color: rgba(90, 124, 200, 0.55); |
| | | } |
| | | &:focus { |
| | | border-color: #38a5f8; |
| | | box-shadow: 0 0 0 3px rgba(56, 165, 248, 0.18); |
| | | } |
| | | } |
| | | |
| | | .el-button { |
| | | background: rgba(24, 36, 68, 0.9); |
| | | border: 1px solid rgba(90, 124, 200, 0.4); |
| | | color: #c3cde4; |
| | | &:hover { |
| | | border-color: #38a5f8; |
| | | color: #eaf2ff; |
| | | } |
| | | } |
| | | .el-button--primary { |
| | | background: linear-gradient(135deg, #2563eb, #22d3ee); |
| | | border: none; |
| | | color: #fff; |
| | | box-shadow: 0 4px 14px rgba(56, 165, 248, 0.4); |
| | | &:hover, |
| | | &:focus { |
| | | background: linear-gradient(135deg, #2f6ff0, #2fd8f2); |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | </style> |