style: 手术间利用率

main
@0Melon0 1 year ago
parent 96454b33ef
commit 649b48a532

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="557.455078125" height="352" viewBox="0 0 557.455078125 352"><defs><filter id="master_svg0_555_25475" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="0" y="0" width="554" height="349"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="25"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 0.49803921580314636 0 0 0 0 0.33725491166114807 0 0 0 0 0.8509804010391235 0 0 0 0.5 0"/><feBlend mode="normal" in2="shape" result="effect1_innerShadow"/></filter><linearGradient x1="0.012568394653499126" y1="0.2873583436012268" x2="0.9811341762542725" y2="1" id="master_svg1_201_02516"><stop offset="0%" stop-color="#8C64E2" stop-opacity="1"/><stop offset="10.360609740018845%" stop-color="#8C64E2" stop-opacity="0"/><stop offset="47.14285731315613%" stop-color="#8C64E2" stop-opacity="0"/><stop offset="73.57142567634583%" stop-color="#8C64E2" stop-opacity="0.699999988079071"/><stop offset="85.00000238418579%" stop-color="#8C64E2" stop-opacity="0.2199999988079071"/><stop offset="100%" stop-color="#8C64E2" stop-opacity="0"/></linearGradient><linearGradient x1="6.661338147750939e-16" y1="0.5" x2="1.017080545425415" y2="0.5000399947166443" id="master_svg2_555_29651"><stop offset="0%" stop-color="#5D49AF" stop-opacity="1"/><stop offset="100%" stop-color="#7E65E5" stop-opacity="0"/></linearGradient><linearGradient x1="6.661338147750939e-16" y1="0.5" x2="1.017080545425415" y2="0.5000399947166443" id="master_svg3_555_29651"><stop offset="0%" stop-color="#5D49AF" stop-opacity="1"/><stop offset="100%" stop-color="#7E65E5" stop-opacity="0"/></linearGradient></defs><g><g filter="url(#master_svg0_555_25475)"><path d="M1.5,350.5L555.5,350.5L555.5,11.5L241.5,11.5L233.5,1.5L1.5,1.5L1.5,350.5Z" fill="#01152A" fill-opacity="0.4000000059604645"/><path d="M242.221,10L557,10L557,352L0,352L0,0L234.221,0L242.221,10ZM232.779,3L240.329,12.437L240.779,13L554,13L554,349L3,349L3,3L232.779,3Z" fill-rule="evenodd" fill="url(#master_svg1_201_02516)" fill-opacity="1"/></g><g><g><path d="M242.5,1.5L457.485,1.5L460.586,5.33186L245.60075,5.33186L242.5,1.5Z" fill="url(#master_svg2_555_29651)" fill-opacity="1"/></g><g><path d="M466.5,1.5L554.3545,1.5L557.4552,5.33186L469.60075,5.33186L466.5,1.5Z" fill="url(#master_svg3_555_29651)" fill-opacity="1"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="557.455078125" height="530" viewBox="0 0 557.455078125 530"><defs><filter id="master_svg0_555_25455" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="0" y="0" width="554" height="527"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="25"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 0.49803921580314636 0 0 0 0 0.33725491166114807 0 0 0 0 0.8509804010391235 0 0 0 0.5 0"/><feBlend mode="normal" in2="shape" result="effect1_innerShadow"/></filter><linearGradient x1="0.012568394653499126" y1="0.2873583436012268" x2="0.9811341762542725" y2="1" id="master_svg1_201_02516"><stop offset="0%" stop-color="#8C64E2" stop-opacity="1"/><stop offset="10.360609740018845%" stop-color="#8C64E2" stop-opacity="0"/><stop offset="47.14285731315613%" stop-color="#8C64E2" stop-opacity="0"/><stop offset="73.57142567634583%" stop-color="#8C64E2" stop-opacity="0.699999988079071"/><stop offset="85.00000238418579%" stop-color="#8C64E2" stop-opacity="0.2199999988079071"/><stop offset="100%" stop-color="#8C64E2" stop-opacity="0"/></linearGradient><linearGradient x1="6.661338147750939e-16" y1="0.5" x2="1.017080545425415" y2="0.5000399947166443" id="master_svg2_555_29651"><stop offset="0%" stop-color="#5D49AF" stop-opacity="1"/><stop offset="100%" stop-color="#7E65E5" stop-opacity="0"/></linearGradient><linearGradient x1="6.661338147750939e-16" y1="0.5" x2="1.017080545425415" y2="0.5000399947166443" id="master_svg3_555_29651"><stop offset="0%" stop-color="#5D49AF" stop-opacity="1"/><stop offset="100%" stop-color="#7E65E5" stop-opacity="0"/></linearGradient></defs><g><g><g filter="url(#master_svg0_555_25455)"><path d="M1.5,528.5L555.5,528.5L555.5,11.5L241.5,11.5L233.5,1.5L1.5,1.5L1.5,528.5Z" fill="#01152A" fill-opacity="0.4000000059604645"/><path d="M242.221,10L557,10L557,530L0,530L0,0L234.221,0L242.221,10ZM232.779,3L240.329,12.437L240.779,13L554,13L554,527L3,527L3,3L232.779,3Z" fill-rule="evenodd" fill="url(#master_svg1_201_02516)" fill-opacity="1"/></g><g><g><path d="M242.5,1.5L457.485,1.5L460.586,5.33186L245.60075,5.33186L242.5,1.5Z" fill="url(#master_svg2_555_29651)" fill-opacity="1"/></g><g><path d="M466.5,1.5L554.3545,1.5L557.4552,5.33186L469.60075,5.33186L466.5,1.5Z" fill="url(#master_svg3_555_29651)" fill-opacity="1"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="412" height="70" viewBox="0 0 412 70"><g><g><path d="M3.11589,66.3191234375L5.76581,69.4990234375L411.5,69.4990234375L411.5,20.7919234375L401.207,10.4990234375L356.223,10.4990234375L347.223,0.4990234375L0.5,0.4990234375L0.5,63.1800234375L3.11589,66.3191234375ZM6.23419,68.4990234375L3.88411,65.6789234375L1.5,62.8180234375L1.5,1.4990234375L346.777,1.4990234375L355.777,11.4990234375L400.793,11.4990234375L410.5,21.2061234375L410.5,68.4990234375L6.23419,68.4990234375Z" fill-rule="evenodd" fill="#2D126F" fill-opacity="1"/></g><g><g><path d="M357,1C357,1,362,1,362,1C362,1,369,8.15967,369,8.15967C369,8.15967,364,8.15967,364,8.15967C364,8.15967,357,1,357,1Z" fill="#5D49AF" fill-opacity="1"/></g><g><path d="M366,1C366,1,371,1,371,1C371,1,378,8.15967,378,8.15967C378,8.15967,373,8.15967,373,8.15967C373,8.15967,366,1,366,1Z" fill="#5D49AF" fill-opacity="1"/></g><g><path d="M384,1C384,1,389,1,389,1C389,1,396,8.15967,396,8.15967C396,8.15967,391,8.15967,391,8.15967C391,8.15967,384,1,384,1Z" fill="#5D49AF" fill-opacity="1"/></g><g><path d="M375,1C375,1,380,1,380,1C380,1,387,8.15967,387,8.15967C387,8.15967,382,8.15967,382,8.15967" fill="#5D49AF" fill-opacity="1"/></g></g><g><path d="M6.08579,70L14.5,70L14.5,68L6.91421,68L2,63.08579L2,55L0,55L0,63.91421L6.08579,70Z" fill-rule="evenodd" fill="#5D49AF" fill-opacity="1"/></g><g><path d="M2,2L11,2L11,0L0,0L0,11L2,11L2,2Z" fill-rule="evenodd" fill="#5D49AF" fill-opacity="1"/></g><g transform="matrix(-1,0,0,-1,822,138)"><path d="M412,70L421,70L421,68L410,68L410,79L412,79L412,70Z" fill-rule="evenodd" fill="#5D49AF" fill-opacity="1"/></g><g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="18" height="20" viewBox="0 0 18 20"><defs><linearGradient x1="0.02499999664723873" y1="0.04545453190803528" x2="0.9749999642372131" y2="0.9999999403953552" id="master_svg0_185_23806"><stop offset="0%" stop-color="#FFA5D6" stop-opacity="1"/><stop offset="100%" stop-color="#F3DDFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.02499999664723873" y1="0.04545453563332558" x2="0.875" y2="1" id="master_svg1_185_26888"><stop offset="0%" stop-color="#582641" stop-opacity="1"/><stop offset="100%" stop-color="#DFA7FF" stop-opacity="1"/></linearGradient></defs><g><g><path d="M0,0C0,0,18,10,18,10C18,10,6.3,10,6.3,10C6.3,10,0,0,0,0C0,0,0,0,0,0Z" fill="url(#master_svg0_185_23806)" fill-opacity="0.800000011920929"/></g><g transform="matrix(1,0,0,-1,0,40)"><path d="M0,20C0,20,18,30,18,30C18,30,6.3,30,6.3,30C6.3,30,0,20,0,20C0,20,0,20,0,20Z" fill="url(#master_svg1_185_26888)" fill-opacity="0.800000011920929"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.3 KiB

@ -7,7 +7,7 @@ const routes = [
{ {
path: '/', path: '/',
name: 'home', name: 'home',
redirect: '/scheduling', redirect: '/room',
}, },
{ {
path: '/monitor', path: '/monitor',
@ -30,7 +30,7 @@ const routes = [
{ {
path: '/room', path: '/room',
name: 'room', name: 'room',
meta: { title: '手术间利用率' }, meta: { title: '手术间利用率数据可视化' },
component: () => import('@/views/pageRoom/index.vue'), component: () => import('@/views/pageRoom/index.vue'),
}, },
]; ];

@ -1,9 +1,24 @@
<template> <template>
<div></div> <div class="w-[171.29vh] flex justify-between mx-auto">
<div class="w-[51.48vh]">
<leftTop></leftTop>
<leftBottom></leftBottom>
</div>
<rightMid></rightMid>
</div>
</template> </template>
<script> <script>
export default {}; import leftTop from './leftTop/index.vue';
import leftBottom from './leftBottom/index.vue';
import rightMid from './rightMid/index.vue';
export default {
components: {
leftTop,
leftBottom,
rightMid,
},
};
</script> </script>
<style></style> <style></style>

@ -0,0 +1,102 @@
<template>
<div class="h-[32.31vh] mt-[2.77vh] pt-[4vh] bgLeftBottomBox">
<div class="h-[20vh]" ref="echartsContainer"></div>
<section class="w-[37.96vh] h-[5.18vh] leading-[5.18vh] text-center border border-[#2D126F] mx-auto">
<span class="text-[1.85vh] youshe">平均接台时间</span>
</section>
</div>
</template>
<script>
import * as echarts from 'echarts';
export default {
data() {
return {
chartOptions: {
series: [
{
type: 'gauge',
radius: '100%',
max: 120,
axisLabel: {
show: false,
},
axisLine: {
lineStyle: {
width: 20,
color: [[1, 'rgba(126, 130, 137, 0.3)']],
},
},
progress: {
show: true,
width: 20,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: '#03c2fd' },
{ offset: 0.5, color: '#1ed3e5' },
{ offset: 1, color: '#2fded6' },
],
},
},
},
pointer: {
icon: 'rect',
width: 3,
offsetCenter: ['0%', '-40%'],
itemStyle: {
color: 'rgba(139, 230, 253, 1)',
},
},
data: [
{
name: 'itemA',
value: 45,
title: { show: false },
detail: {
offsetCenter: [0, '20%'],
formatter: function (value) {
return '{a|' + value + '}{b|min}';
},
rich: {
a: {
fontSize: 40,
color: '#4AC9FF',
fontFamily: 'DIN-Bold,Microsoft YaHei',
},
b: {
fontSize: 20,
color: '#4AC9FF',
fontFamily: 'DIN-Bold,Microsoft YaHei',
verticalAlign: 'bottom',
},
},
},
},
],
},
],
},
};
},
mounted() {
const chartContainer = this.$refs.echartsContainer;
const chart = echarts.init(chartContainer);
chart.setOption(this.chartOptions);
},
};
</script>
<style>
.bgLeftBottomBox {
background-image: url('@/assets/svg/Room/LeftBottom/Box.svg');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
</style>

@ -0,0 +1,134 @@
<template>
<div class="h-[48.79vh] bgLeftTopBox p-[1.85vh]">
<div class="w-[22vh] h-[22vh] mx-auto mt-[4.6vh]" ref="echartsContainer"></div>
<div class="w-[37.96vh] h-[6.29vh] mx-auto mt-[8.6vh] px-[4.96vh] flex justify-between items-center bgTopLeftItemBox">
<div class="flex">
<img src="@/assets/svg/Room/LeftTop/TrianglePurple.svg" />
<span class="text-[1.85vh] youshe ml-[1.4vh]">手术间数</span>
</div>
<p class="text-[2.96vh] text-[#733FF3] youshe">100</p>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts';
export default {
data() {
return {
chartOptions: {
series: [
{
type: 'gauge',
startAngle: 90,
endAngle: -270,
pointer: {
show: false,
},
max: 100,
radius: '100%',
center: ['50%', '50%'],
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#9C85FA',
},
{
offset: 1,
color: '#5531E7',
},
],
global: false,
},
},
},
axisLine: {
lineStyle: {
color: [[1, '#4F518C']],
opacity: 0.7,
width: 30,
},
},
splitLine: {
show: false,
distance: 0,
length: 10,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
distance: 50,
},
data: [
{
value: 86,
name: '首台准点率',
title: {
offsetCenter: ['0%', '20%'],
fontSize: 22,
fontFamily: 'Microsoft YaHei',
color: '#fff',
overflow: 'break',
lineHeight: 20,
},
detail: {
valueAnimation: true,
offsetCenter: ['0%', '-15%'],
fontSize: 40,
fontFamily: 'DIN-Bold,Microsoft YaHei',
color: '#03FFFF',
formatter: `{value}%`,
},
},
],
},
],
},
peopleData: [
{
itemName: '进行中',
itemVal: '50',
},
{
itemName: '待进行',
itemVal: '300',
},
],
};
},
mounted() {
const chartContainer = this.$refs.echartsContainer;
const chart = echarts.init(chartContainer);
chart.setOption(this.chartOptions);
},
};
</script>
<style>
.bgLeftTopBox {
background-image: url('@/assets/svg/Room/LeftTop/Box.svg');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.bgTopLeftItemBox {
background-image: url('@/assets/svg/Room/LeftTop/ItemBox.svg');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
</style>

@ -0,0 +1,237 @@
<template>
<div class="w-[116.94vh] h-[85.51vh] bgRightMidBox">
<section class="h-full" ref="echartsContainer"></section>
</div>
</template>
<script>
import * as echarts from 'echarts';
import dayjs from 'dayjs';
export default {
data() {
return {
isLoding: false,
chartOptions: {
grid: {
width: '86%',
height: '80%',
top: '14%',
},
legend: {
data: [
{
name: '入手术室',
icon: 'rect',
itemStyle: {
color: '#92CC76',
},
},
{
name: '开始手术',
icon: 'rect',
itemStyle: {
color: '#EF6666',
},
},
{
name: '手术结束',
icon: 'rect',
itemStyle: {
color: '#FAC858',
},
},
{
name: '出手术室',
icon: 'rect',
itemStyle: {
color: '#5470C6',
},
},
],
selectedMode: 'none',
top: "6%",
right: "4%",
textStyle: {
color: '#fff',
fontSize: 14,
fontFamily: 'DIN-Bold,Microsoft YaHei',
},
},
xAxis: {
type: 'time',
position: 'top',
splitNumber: 24,
axisLabel: {
color: '#B7BDBF',
fontSize: 12,
margin: 16,
formatter: function (value) {
var date = new Date(value);
var hours = date.getHours();
var minutes = date.getMinutes();
if (hours === 0 && minutes === 0) {
return '00:00';
} else {
return (hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes;
}
},
},
},
yAxis: {
type: 'category',
data: [],
axisLabel: {
color: '#B7BDBF',
fontSize: 12,
margin: 16,
fontFamily: 'DIN-Bold,Microsoft YaHei',
},
},
series: [],
},
};
},
methods: {
initData() {
//
const currentDate = dayjs().format('YYYY-MM-DD');
const hours = new Date().getHours();
const detailMin = dayjs().subtract(1, 'minute').format('HH:mm:00');
const sevenMinutesAgo = dayjs().subtract(8, 'minute').format('HH:mm:00');
this.chartOptions.xAxis.min = `${currentDate} 08:00:00`;
this.chartOptions.xAxis.max = `${dayjs().add(1, 'day').format('YYYY-MM-DD')} 07:00:00`;
//
const num = 20;
//
const timeArr = [];
//
for (let index = num; index >= 1; index--) {
this.chartOptions.yAxis.data.push(`手术间${String(index).padStart(3, '0')}`);
const isUseArr = this.getUseTime();
for (let j = 1; j < isUseArr.length; j += 2) {
if (isUseArr[j] <= hours) {
timeArr.push({
startTime: `${currentDate} ${isUseArr[j - 1]}:00:00`,
endTime: `${currentDate} ${isUseArr[j]}:00:00`,
yValue: index - 1,
color: '#5470C6',
diff: dayjs(`${currentDate} ${isUseArr[j]}:00:00`).diff(dayjs(`${currentDate} ${isUseArr[j - 1]}:00:00`), 'minute'),
name: '出手术室',
});
} else if (isUseArr[j] > hours && isUseArr[j - 1] < hours) {
if (Math.random() > 0.5) {
timeArr.push({
startTime: `${currentDate} ${isUseArr[j - 1]}:00:00`,
endTime: `${currentDate} ${detailMin}`,
yValue: index - 1,
color: '#EF6666',
diff: dayjs(`${currentDate} ${detailMin}`).diff(dayjs(`${currentDate} ${isUseArr[j - 1]}:00:00`), 'minute'),
name: '开始手术',
});
} else {
timeArr.push({
startTime: `${currentDate} ${isUseArr[j - 1]}:00:00`,
endTime: `${currentDate} ${detailMin}`,
yValue: index - 1,
color: '#FAC858',
diff: dayjs(`${currentDate} ${detailMin}`).diff(dayjs(`${currentDate} ${isUseArr[j - 1]}:00:00`), 'minute'),
name: '手术结束',
});
}
} else if (isUseArr[j] > hours && isUseArr[j - 1] == hours) {
timeArr.push({
startTime: `${currentDate} ${sevenMinutesAgo}`,
endTime: `${currentDate} ${detailMin}`,
yValue: index - 1,
color: '#92CC76',
diff: '7',
name: '入手术室',
});
}
}
}
// series
this.chartOptions.series = this.seriesData(timeArr);
},
seriesData(data) {
// const obj = {};
const res = data.map(function (item) {
// obj[item.name] = item.color;
return {
type: 'custom',
name: item.name,
renderItem: function (params, api) {
var xStart = api.coord([item.startTime, item.yValue]);
var xEnd = api.coord([item.endTime, item.yValue]);
var textX = (xStart[0] + xEnd[0]) / 2;
var textY = xStart[1] - 20;
return {
type: 'group',
children: [
{
type: 'line',
shape: {
x1: xStart[0],
y1: xStart[1],
x2: xEnd[0],
y2: xEnd[1],
},
style: {
stroke: item.color,
lineWidth: 8,
},
},
{
type: 'text',
position: [textX, textY],
style: {
text: `${item.diff} min`,
fill: '#B7BDBF',
textSize: '12px',
textAlign: 'center',
},
},
],
};
},
data: [item],
};
});
// console.log(obj);
// console.log(JSON.stringify(res));
return res;
},
getUseTime() {
// 使
function getRandomUniqueValues(min, max, count) {
const values = new Set();
while (values.size < count) {
values.add(Math.floor(Math.random() * (max - min + 1)) + min);
}
return Array.from(values);
}
const numValues = Math.floor(Math.random() * 3) + 8;
const randomValues = getRandomUniqueValues(8, 24, numValues % 2 ? numValues + 1 : numValues);
return randomValues.sort((a, b) => {
return a - b;
});
},
},
mounted() {
const chartContainer = this.$refs.echartsContainer;
const chart = echarts.init(chartContainer);
this.initData();
chart.setOption(this.chartOptions);
},
};
</script>
<style>
.bgRightMidBox {
background-image: url('@/assets/svg/Room/RightMid/Box.svg');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
</style>
Loading…
Cancel
Save