feat(n): 第一次上传 提供测试链接

main
@0Melon0 2 years ago
commit 00c32862f1

@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

@ -0,0 +1,15 @@
module.exports = {
root: true,
env: {
node: true,
},
extends: ['plugin:vue/essential', 'eslint:recommended'],
parserOptions: {
parser: '@babel/eslint-parser',
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/multi-word-component-names': 'off',
},
};

23
.gitignore vendored

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,5 @@
# cockpit
大屏数据展示基于 `Vue2 + dataV + Echart`
[`dataV`](http://datav.jiaminghi.com)

@ -0,0 +1,12 @@
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
},
],
],
};

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

11788
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,35 @@
{
"name": "cockpit",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@jiaminghi/charts": "^0.2.18",
"@jiaminghi/data-view": "^2.10.0",
"core-js": "^3.8.3",
"dayjs": "^1.11.9",
"element-ui": "^2.15.14",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"babel-plugin-component": "^1.1.1",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"sass": "^1.32.7",
"sass-loader": "^12.0.0",
"vue-template-compiler": "^2.6.14"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -0,0 +1,72 @@
<template>
<dv-full-screen-container class="app">
<dv-loading v-show="isLoding">Loading...</dv-loading>
<comHeader></comHeader>
<main class="contentBox" @click="enterFullscreen">
<router-view></router-view>
</main>
</dv-full-screen-container>
</template>
<script>
import comHeader from '@/components/comHeader/index.vue';
export default {
data: () => {
return {
isLoding: false,
};
},
mounted() {
setTimeout(() => {
this.isLoding = false;
}, 1000);
},
methods: {
enterFullscreen() {
const element = document.documentElement;
//
if (!this.isLoding) {
if (element.webkitRequestFullscreen) {
// Chrome, Safari and Opera
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
// IE/Edge
element.msRequestFullscreen();
} else if (element.mozRequestFullScreen) {
// Firefox
element.mozRequestFullScreen();
} else if (element.requestFullscreen) {
element.requestFullscreen();
}
}
},
},
components: {
comHeader,
},
};
</script>
<style lang="scss">
* {
margin: 0;
padding: 0;
text-decoration: none;
list-style: none;
color: #fff;
}
.app {
width: 100%;
height: 100%;
background-image: url('@/assets/img/bg.png');
background-size: cover;
background-repeat: no-repeat;
.contentBox {
height: calc(100% - 100px);
display: flex;
box-sizing: border-box;
padding: 20px;
padding-top: 0px;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

@ -0,0 +1,51 @@
<template>
<dv-charts :option="option"></dv-charts>
</template>
<script>
export default {
data() {
return {
option: {
xAxis: {
type: 'category',
data: ['骨科', '心胸外科', '普通外科', '神经外科', '整形外科'],
axisLabel: {
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
yAxis: {
type: 'value',
data: 'value',
max: '1%',
axisLabel: {
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
series: [
{
type: 'bar',
data: [200, 150, 120, 80, 70],
label: {
show: true,
position: 'top',
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
],
},
};
},
};
</script>
<style></style>

@ -0,0 +1,105 @@
<template>
<Header>
<dv-decoration-8 class="left" />
<dv-decoration-5 class="center" />
<dv-decoration-8 class="right" :reverse="true" />
<div class="centerTitle">{{$route.meta.title}}</div>
<dv-decoration-7 class="dateBox"><span>{{ curTime }}</span></dv-decoration-7>
</Header>
</template>
<script>
import dayjs from 'dayjs';
export default {
data() {
return {
curTime: '',
dayOfWeekText: '',
};
},
methods: {
//
getWeek() {
const dayOfWeek = dayjs().day();
switch (dayOfWeek) {
case 0:
this.dayOfWeekText = '星期日';
break;
case 1:
this.dayOfWeekText = '星期一';
break;
case 2:
this.dayOfWeekText = '星期二';
break;
case 3:
this.dayOfWeekText = '星期三';
break;
case 4:
this.dayOfWeekText = '星期四';
break;
case 5:
this.dayOfWeekText = '星期五';
break;
case 6:
this.dayOfWeekText = '星期六';
break;
}
},
//
updateTime() {
this.curTime = dayjs().format(`YYYY-MM-DD HH:mm:ss ${this.dayOfWeekText}`);
},
},
created() {
this.getWeek();
this.updateTime();
this.timer = setInterval(this.updateTime, 1000);
},
beforeDestroy() {
clearInterval(this.timer);
},
};
</script>
<style lang="scss" scoped>
Header {
display: flex;
justify-content: space-between;
flex-shrink: 0;
height: 100px;
position: relative;
.left {
width: 25%;
height: 60px;
}
.center {
width: 40%;
height: 60px;
margin-top: 30px;
}
.right {
width: 25%;
height: 60px;
}
.centerTitle {
position: absolute;
font-size: 30px;
font-weight: 700;
left: 50%;
top: 15px;
transform: translateX(-50%);
}
.dateBox {
position: absolute;
width: 18%;
height: 60px;
font-size: 16px;
font-weight: 700;
right: 9%;
top: 27px;
span{
margin: 0 8px;
}
}
}
</style>

@ -0,0 +1,109 @@
<template>
<div class="dv-bar-chart">
<div class="bar-chart-container" ref="bar-chart" />
</div>
</template>
<script>
import Charts from '@jiaminghi/charts';
import { deepMerge } from '@jiaminghi/charts/lib/util/index';
import { deepClone } from '@jiaminghi/c-render/lib/plugin/util';
export default {
name: 'DvBarChart',
props: {
config: {
type: Object,
default: () => ({}),
},
},
data() {
return {
defaultConfig: {},
mergedConfig: null,
chart: null,
};
},
methods: {
init() {
const { initChart, mergeConfig, setBarOption } = this;
initChart();
mergeConfig();
setBarOption();
},
initChart() {
// Echart
const { $refs } = this;
this.chart = new Charts($refs['bar-chart']);
},
mergeConfig() {
//
const { defaultConfig, config } = this;
this.mergedConfig = deepMerge(deepClone(defaultConfig, true), config || {});
},
setBarOption() {
const { getBarOption, chart } = this;
// Echart
const option = getBarOption();
chart.setOption(option, true);
},
getBarOption() {
//
// const { mergedConfig } = this;
return {
xAxis: [
{
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: {
type: 'value',
data:[],
axisLabel: {
textStyle: {
color: '#333',
fontSize: 12,
},
},
splitLine: {
show: true,
lineStyle: {
color: '#ddd',
type: 'dashed',
},
},
axis: {
// axis
name: 'Y轴名称',
nameTextStyle: {
color: '#666',
fontSize: 14,
},
// axis ...
},
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
},
],
};
},
},
mounted() {
const { init } = this;
//
init();
},
};
</script>
<style lang="scss" scoped>
.bar-chart-container {
height: 100%;
}
</style>

@ -0,0 +1,50 @@
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import {
fullScreenContainer,
loading,
digitalFlop,
activeRingChart,
capsuleChart,
scrollBoard,
charts,
decoration2,
decoration4,
decoration5,
decoration8,
decoration7,
borderBox1,
borderBox2,
borderBox7,
borderBox11,
borderBox13,
} from '@jiaminghi/data-view';
Vue.use(fullScreenContainer)
.use(loading)
.use(digitalFlop)
.use(activeRingChart)
.use(capsuleChart)
.use(scrollBoard)
.use(charts)
.use(decoration2)
.use(decoration4)
.use(decoration5)
.use(decoration8)
.use(decoration7)
.use(borderBox1)
.use(borderBox2)
.use(borderBox7)
.use(borderBox11)
.use(borderBox13);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

@ -0,0 +1,47 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
redirect: '/monitor',
},
{
path: '/monitor',
name: 'monitor',
meta: { title: '运营监控' },
component: () => import('@/views/pageMonitor/index.vue'),
},
{
path: '/scheduling',
name: 'scheduling',
meta: { title: '护理人员排班' },
component: () => import('@/views/pageScheduling/index.vue'),
},
{
path: '/operation',
name: 'operation',
meta: { title: '首台率' },
component: () => import('@/views/pageOperation/index.vue'),
},
{
path: '/room',
name: 'room',
meta: { title: '手术间利用率' },
component: () => import('@/views/pageRoom/index.vue'),
},
];
const router = new VueRouter({
routes,
});
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
next();
});
export default router;

@ -0,0 +1,17 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})

@ -0,0 +1,98 @@
<template>
<div class="bottomLeft">
<dv-border-box-13>
<div class="chartsBox">
<div class="chartItem">
<p>手术等级</p>
<dv-active-ring-chart :config="config1" />
</div>
<dv-decoration-2 :reverse="true" />
<div class="chartItem">
<p>ASA分级</p>
<dv-active-ring-chart :config="config2" />
</div>
</div>
</dv-border-box-13>
</div>
</template>
<script>
export default {
data() {
return {
config1: {
data: [
{
name: '一级',
value: 300,
},
{
name: '二级',
value: 250,
},
{
name: '三级',
value: 250,
},
{
name: '四级',
value: 100,
},
{
name: '五级',
value: 80,
},
],
},
config2: {
data: [
{
name: 'I级',
value: 80,
},
{
name: 'II级',
value: 50,
},
{
name: 'III级',
value: 10,
},
{
name: 'IV级',
value: 20,
},
],
},
};
},
};
</script>
<style lang="scss" scoped>
.bottomLeft {
flex-basis: 40%;
.chartsBox {
width: 100%;
height: 100%;
display: flex;
position: relative;
padding-top: 10px;
box-sizing: border-box;
.chartItem {
width: 48%;
height: 100%;
flex-shrink: 0;
padding-top: 40px;
box-sizing: border-box;
p {
font-size: 24px;
text-align: center;
}
:deep(.dv-active-ring-chart) {
height: 90%;
}
}
}
}
</style>

@ -0,0 +1,118 @@
<template>
<div class="bottomMiddle">
<dv-border-box-13>
<div class="chartsBox">
<div class="chartItem">
<nav>
<p class="left">手术量统计</p>
<div class="right">
<p class="active"></p>
<p></p>
</div>
</nav>
<dv-capsule-chart :config="config" />
</div>
</div>
</dv-border-box-13>
</div>
</template>
<script>
export default {
data() {
return {
config: {
data: [
{
name: '择期手术',
value: 120,
},
{
name: '急诊手术',
value: 10,
},
{
name: '门诊手术',
value: 30,
},
{
name: '无痛手术',
value: 20,
},
{
name: '日间手术',
value: 25,
},
],
showValue: true,
},
};
},
};
</script>
<style lang="scss" scoped>
.bottomMiddle {
flex-basis: 28%;
.chartsBox {
width: 100%;
height: 100%;
display: flex;
position: relative;
padding-top: 10px;
box-sizing: border-box;
.chartItem {
width: 100%;
height: 100%;
flex-shrink: 0;
padding: 0 20px;
padding-top: 20px;
box-sizing: border-box;
nav {
display: flex;
justify-content: space-between;
.right {
display: flex;
.active,
p:hover {
color: #87ceeb;
}
p {
margin-right: 10px;
cursor: pointer;
}
}
p {
font-size: 24px;
}
}
:deep(.dv-capsule-chart) {
height: 90%;
transform: translateX(-10px) translateY(20px);
.label-column {
div {
font-size: 18px;
margin-top: 7px;
}
}
.capsule-container {
.capsule-item {
height: 20px;
.capsule-item-column {
height: 18px;
.capsule-item-value {
font-size: 18px;
transform: translateX(110%);
}
}
}
.unit-label {
visibility: hidden;
font-size: 20px;
}
}
}
}
}
}
</style>

@ -0,0 +1,71 @@
<template>
<div class="bottomRight">
<dv-border-box-13>
<div class="chartsBox">
<div class="chartItem">
<nav>
<p class="left">科室手术量统计(前五)</p>
<div class="right">
<p class="active"></p>
<p></p>
</div>
</nav>
<dv-bar-chart></dv-bar-chart>
</div>
</div>
</dv-border-box-13>
</div>
</template>
<script>
// import dvBarChart from '@/components/dvBarChart/index.vue';
import comBar from '@/components/comBar/index.vue';
export default {
components: {
'dv-bar-chart': comBar,
},
};
</script>
<style lang="scss" scoped>
.bottomRight {
flex-basis: 28%;
.chartsBox {
width: 100%;
height: 100%;
display: flex;
position: relative;
padding-top: 10px;
box-sizing: border-box;
.chartItem {
width: 100%;
height: 100%;
flex-shrink: 0;
padding: 0 20px;
padding-top: 20px;
box-sizing: border-box;
nav {
display: flex;
justify-content: space-between;
.right {
display: flex;
.active,
p:hover {
color: #87ceeb;
}
p {
margin-right: 10px;
cursor: pointer;
}
}
p {
font-size: 24px;
}
}
:deep(.dv-charts-container){
height: 90%;
}
}
}
}
</style>

@ -0,0 +1,51 @@
<template>
<dv-border-box-1>
<section class="monitor">
<div class="topBox">
<topLeft></topLeft>
<topRight></topRight>
</div>
<div class="bottomBox">
<bottomLeft></bottomLeft>
<bottomMiddle></bottomMiddle>
<bottomRight></bottomRight>
</div>
</section>
</dv-border-box-1>
</template>
<script>
import topLeft from './topLeft/index.vue';
import topRight from './topRight/index.vue';
import bottomLeft from './bottomLeft/index.vue';
import bottomMiddle from './bottomMiddle/index.vue';
import bottomRight from './bottomRight/index.vue';
export default {
components: {
topLeft,
topRight,
bottomLeft,
bottomMiddle,
bottomRight,
},
};
</script>
<style lang="scss" scoped>
.monitor {
width: 100%;
height: 100%;
> div {
height: 50%;
padding: 20px;
box-sizing: border-box;
}
.topBox {
display: flex;
}
.bottomBox {
display: flex;
justify-content: space-between;
}
}
</style>

@ -0,0 +1,115 @@
<template>
<div class="topLeft">
<dv-border-box-13>
<div class="box">
<dv-border-box-2 class="item">
<p>首台准点率</p>
<p>
<dv-digital-flop :config="config1" />
</p>
</dv-border-box-2>
<dv-border-box-2 class="item">
<p>手术间利用率</p>
<p>
<dv-digital-flop :config="config2" />
</p>
</dv-border-box-2>
<dv-border-box-2 class="item">
<p>总人数 <span>400</span></p>
<p>进行中 <span>180</span></p>
<p>待进行 <span>220</span></p>
</dv-border-box-2>
<dv-border-box-2 class="item">
<p>急症患者</p>
<p>
<dv-digital-flop :config="config6" />
</p>
</dv-border-box-2>
</div>
</dv-border-box-13>
</div>
</template>
<script>
export default {
data() {
return {
config1: {
number: [0],
content: '{nt} %',
animationFrame: 150,
animationCurve: 'easeOutCubic',
style: {
fontSize: 30,
},
},
config2: {
number: [0],
content: '{nt} %',
animationFrame: 150,
animationCurve: 'easeOutCubic',
style: {
fontSize: 30,
},
},
config6: {
number: [0],
content: '{nt} 个',
animationFrame: 150,
animationCurve: 'easeOutCubic',
style: {
fontSize: 30,
},
},
};
},
mounted() {
const { config1, config2, config6 } = this;
config1.number = [80];
config2.number = [86];
config6.number = [180];
this.config1 = { ...this.config1 };
this.config2 = { ...this.config2 };
this.config6 = { ...this.config6 };
},
};
</script>
<style lang="scss" scoped>
.topLeft {
flex-basis: 32%;
.box {
height: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
.item {
flex-basis: 45%;
flex-shrink: 0;
height: 40%;
box-sizing: border-box;
padding: 3%;
:deep(.border-box-content) {
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
font-size: 20px;
p {
height: 30%;
flex-shrink: 0;
display: flex;
align-items: center;
span {
margin-left: 10px;
}
.dv-digital-flop {
height: 100%;
}
}
}
}
}
}
</style>

@ -0,0 +1,71 @@
<template>
<div class="topRight">
<dv-border-box-13>
<el-carousel direction="vertical" :autoplay="false" :interval="5000">
<el-carousel-item v-for="item in 3" :key="item">
<div class="item" v-for="(item1, index) in 21" :key="item1">
<dv-border-box-2>
<p>WK{{ String(index + 1).padStart(2, '0') }}</p>
<p v-if="index % 3" style="color: #f00"></p>
<p v-else-if="index % 5" style="color: #ff0">麻醉结束</p>
<p v-else style="color: #fff">空置中</p>
</dv-border-box-2>
</div>
</el-carousel-item>
</el-carousel>
</dv-border-box-13>
</div>
</template>
<script>
import { Carousel, CarouselItem } from 'element-ui';
export default {
components: {
'el-carousel': Carousel,
'el-carousel-item': CarouselItem,
},
};
</script>
<style lang="scss" scoped>
.topRight {
flex-basis: 65%;
margin-left: 3%;
:deep(.el-carousel) {
height: 100%;
.el-carousel__container {
height: 100%;
}
.el-carousel__item {
height: 100%;
.item {
float: left;
width: 13%;
padding-top: 10%;
position: relative;
margin-left: 1%;
margin-top: 1.8%;
> div {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.border-box-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
p:first-child {
font-size: 18px;
}
p:last-child {
font-size: 22px;
}
}
}
}
}
}
}
</style>

@ -0,0 +1,46 @@
<template>
<dv-border-box-1>
<section class="operation">
<div class="leftBox">
<leftTop></leftTop>
<leftBottom></leftBottom>
</div>
<div class="rightBox">
<rightMiddle></rightMiddle>
</div>
</section>
</dv-border-box-1>
</template>
<script>
import leftTop from './leftTop/index.vue';
import leftBottom from './leftBottom/index.vue';
import rightMiddle from './rightMiddle/index.vue';
export default {
components: {
leftTop,
leftBottom,
rightMiddle,
},
};
</script>
<style lang="scss" scoped>
.operation {
width: 100%;
height: 100%;
padding: 20px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.leftBox {
flex-basis: 30%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.rightBox {
flex-basis: 69%;
}
}
</style>

@ -0,0 +1,62 @@
<template>
<div class="leftBottom">
<dv-border-box-13>
<dv-charts :option="option"></dv-charts>
</dv-border-box-13>
</div>
</template>
<script>
export default {
data() {
return {
option: {
xAxis: {
type: 'category',
data: ['3月', '4月', '5月', '6月', '7月', '8月'],
axisLabel: {
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
yAxis: {
type: 'value',
data: 'value',
max: 100,
min: 0,
axisLabel: {
formatter: '{value}%',
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
series: [
{
type: 'line',
data: [92, 89, 96, 98, 95, 95],
label: {
show: true,
position: 'top',
formatter: '{value}%',
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
],
},
};
},
};
</script>
<style lang="scss" scoped>
.leftBottom {
height: 49%;
}
</style>

@ -0,0 +1,60 @@
<template>
<div class="leftTop">
<dv-border-box-13>
<dv-border-box-2 class="item">
<p>首台准点率 <span>80%</span></p>
</dv-border-box-2>
<dv-decoration-2 />
<dv-border-box-2 class="item">
<p>总人数 <span>400</span></p>
<p>进行中 <span>180</span></p>
<p>待进行 <span>220</span></p>
</dv-border-box-2>
</dv-border-box-13>
</div>
</template>
<script>
export default {
data() {
return {};
},
};
</script>
<style lang="scss" scoped>
.leftTop {
height: 49%;
:deep(.dv-border-box-13) {
padding: 20px;
box-sizing: border-box;
> div {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
.item {
height: 45%;
.border-box-content {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
padding: 20px 0 ;
box-sizing: border-box;
p {
font-size: 20px;
span {
font-size: 24px;
color: #61bad3;
}
}
}
}
.dv-decoration-2 {
height: 2%;
}
}
}
}
</style>

@ -0,0 +1,66 @@
<template>
<div class="rightMiddle">
<dv-scroll-board :config="config" />
</div>
</template>
<script>
export default {
data() {
return {
title: '白班 手术间78 护理人员135',
titleWidth: 380,
config: {
header: ['手术间', '手术名称', '申请类型', '入手术室时间', '麻醉开始时间', '手术开始时间', '是否准点'],
data: [
['WK01', '阑尾切除术', '紧急', '2023-09-10 08:00', '2023-09-10 08:30', '2023-09-10 09:15', '准点'],
['WK02', '膝关节置换术', '择期', '2023-09-11 09:30', '2023-09-11 10:00', '2023-09-11 10:45', '不准点'],
['WK03', '白内障手术', '择期', '2023-09-12 14:45', '2023-09-12 15:15', '2023-09-12 15:45', '准点'],
['WK04', '胆囊切除术', '紧急', '2023-09-13 08:30', '2023-09-13 09:00', '2023-09-13 09:45', '准点'],
['WK05', '阑尾切除术', '紧急', '2023-09-14 07:45', '2023-09-14 08:15', '2023-09-14 08:45', '不准点'],
['WK06', '膝关节置换术', '择期', '2023-09-15 10:00', '2023-09-15 10:30', '2023-09-15 11:15', '准点'],
['WK07', '阑尾切除术', '紧急', '2023-09-16 08:15', '2023-09-16 08:45', '2023-09-16 09:30', '不准点'],
['WK08', '白内障手术', '择期', '2023-09-17 14:30', '2023-09-17 15:00', '2023-09-17 15:45', '准点'],
['WK09', '胆囊切除术', '紧急', '2023-09-18 08:45', '2023-09-18 09:15', '2023-09-18 10:00', '不准点'],
['WK10', '膝关节置换术', '择期', '2023-09-19 10:15', '2023-09-19 10:45', '2023-09-19 11:30', '准点'],
['WK11', '阑尾切除术', '紧急', '2023-09-20 08:30', '2023-09-20 09:00', '2023-09-20 09:45', '准点'],
['WK12', '白内障手术', '择期', '2023-09-21 14:15', '2023-09-21 14:45', '2023-09-21 15:30', '不准点'],
['WK13', '胆囊切除术', '紧急', '2023-09-22 08:00', '2023-09-22 08:30', '2023-09-22 09:15', '不准点'],
['WK14', '阑尾切除术', '紧急', '2023-09-23 07:30', '2023-09-23 08:00', '2023-09-23 08:45', '不准点'],
['WK15', '膝关节置换术', '择期', '2023-09-24 10:30', '2023-09-24 11:00', '2023-09-24 11:45', '准点'],
['WK16', '白内障手术', '择期', '2023-09-25 14:00', '2023-09-25 14:30', '2023-09-25 15:15', '不准点'],
['WK17', '胆囊切除术', '紧急', '2023-09-26 08:15', '2023-09-26 08:45', '2023-09-26 09:30', '不准点'],
['WK18', '阑尾切除术', '紧急', '2023-09-27 07:45', '2023-09-27 08:15', '2023-09-27 09:00', '不准点'],
['WK19', '膝关节置换术', '择期', '2023-09-28 10:45', '2023-09-28 11:15', '2023-09-28 12:00', '准点'],
['WK20', '白内障手术', '择期', '2023-09-29 13:45', '2023-09-29 14:15', '2023-09-29 14:45', '不准点'],
],
rowNum: 12,
waitTime: 10000,
carousel: 'page',
},
};
},
};
</script>
<style lang="scss" scoped>
.rightMiddle {
height: 100%;
:deep(.dv-scroll-board) {
box-sizing: border-box;
height: 100%;
.header-item {
font-size: 18px;
}
.ceil {
font-size: 18px;
white-space: nowrap;
}
.row-item {
.ceil:last-child {
color: #87ceeb;
}
}
}
}
</style>

@ -0,0 +1,41 @@
<template>
<section class="room">
<div class="leftBox">
<leftMiddle></leftMiddle>
</div>
<div class="rightBox">
<rightMiddle></rightMiddle>
</div>
</section>
</template>
<script>
import leftMiddle from './leftMiddle/index.vue';
import rightMiddle from './rightMiddle/index.vue';
export default {
components: {
leftMiddle,
rightMiddle,
},
};
</script>
<style lang="scss" scoped>
.room {
width: 100%;
height: 100%;
padding: 20px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.leftBox {
flex-basis: 18%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.rightBox {
flex-basis: 80%;
}
}
</style>

@ -0,0 +1,61 @@
<template>
<div class="leftMiddle">
<dv-border-box-13>
<dv-border-box-2 class="item">
<p>手术间数</p>
<span>80</span>
</dv-border-box-2>
<dv-decoration-2 />
<dv-border-box-2 class="item">
<p>手术间利用率</p>
<span>72%</span>
</dv-border-box-2>
<dv-decoration-2 />
<dv-border-box-2 class="item">
<p>平均接台时间</p>
<span>45分钟</span>
</dv-border-box-2>
</dv-border-box-13>
</div>
</template>
<script>
export default {};
</script>
<style lang="scss" scoped>
.leftMiddle {
height: 100%;
:deep(.dv-border-box-13) {
padding: 20px;
box-sizing: border-box;
> div {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
.item {
height: 45%;
.border-box-content {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
padding: 20px 0;
box-sizing: border-box;
p {
font-size: 24px;
}
span {
font-size: 30px;
color: #61bad3;
}
}
}
.dv-decoration-2 {
height: 2%;
}
}
}
}
</style>

@ -0,0 +1,83 @@
<template>
<div class="rightMiddle">
<dv-charts :option="option"></dv-charts>
</div>
</template>
<script>
export default {
data() {
return {
option: {
xAxis: {
type: 'category',
position: 'top',
data: 'value',
min: 0,
max: 23,
minInterval: 1,
splitNumber: 24,
axisLabel: {
style: {
stroke: '#fff',
fontSize: 14,
},
formatter: dataItem => `${String(dataItem.value).padStart(2, '0')}:00`,
},
axisLine: {
show: false,
},
},
yAxis: {
data: [],
splitLine: { show: false },
axisLabel: {
style: {
stroke: '#fff',
fontSize: 14,
},
},
},
series: [],
},
};
},
created() {
//
const num = 8;
//
for (let index = num; index >= 1; index--) {
this.option.yAxis.data.push(`手术间${String(index).padStart(2, '0')}`);
}
// 使
for (let index = 1; index <= 24; index++) {
let seriesData = {
name: `bar${String(index).padStart(2, '0')}`,
type: 'bar',
stack: 'bar',
data: [],
independentColor: true,
independentColors: [],
barWidth: 10,
};
for (let sunIndex = 0; sunIndex < num; sunIndex++) {
const isUse = Math.random() < 0.7;
seriesData.data.push(1);
if (isUse) {
seriesData.independentColors.push('#87ceeb');
} else {
seriesData.independentColors.push('rgb(128,128,128)');
}
}
this.option.series.push(seriesData);
}
},
};
</script>
<style lang="scss" scoped>
.rightMiddle {
height: 100%;
background-color: gray;
}
</style>

@ -0,0 +1,107 @@
<template>
<section class="scheduling">
<dv-border-box-11 :title="title" :titleWidth="titleWidth">
<dv-scroll-board :config="config" />
</dv-border-box-11>
</section>
</template>
<script>
export default {
data() {
return {
title: '白班 手术间78 护理人员135',
titleWidth: 380,
config: {
data: [
['WK01 郑六、小李、杨三、孙七', 'WK02 小红、小李、杨三、小刚', 'WK03 赵六、吴四、赵十五'],
['WK04 李八、吴四、王五、钟二十一', 'WK05 刘一、小丽、小明', 'WK06 小刚、黄十二、小明、周十六'],
['WK07 李四、郑六、吴十九、孙七', 'WK08 小李、吴四、李八', 'WK09 吴四、吴十九、李四、小丽、钟二十一'],
[
'WK10 李四、吴十九、王五、陈十七、杨三',
'WK11 黄十二、张三、小丽、小红、小李',
'WK12 杨十八、钟二十一、陈十七、小刚、许二十',
],
['WK13 杨三、周五、朱九', 'WK14 朱九、郑六、小刚、孙七', 'WK15 许二十、陈二、刘一'],
[
'WK16 郑六、许二十、小红、朱九、杨十八',
'WK17 郑六、刘一、吴十九、钟二十一、小李',
'WK18 钟二十一、杨三、林十一、小红、吴十九',
],
[
'WK19 小李、小明、王五、许二十',
'WK20 刘一、杨十八、小丽、赵六、陈十七',
'WK21 小刚、孙七、吴四、黄十二、钟二十一',
],
['WK22 黄十二、郑六、王十四、林十一、小明', 'WK23 刘一、小刚、小丽、赵六', 'WK24 周五、王五、黄十二、李八'],
['WK25 郑六、周十六、王五、张三', 'WK26 陈十七、吴十九、陈二、张三', 'WK27 小明、林十一、李四'],
[
'WK28 小红、赵十五、陈二、李八、朱九',
'WK29 陈十七、小丽、张三、王十四',
'WK30 陈二、王五、王十四、周五、吴十九',
],
['WK31 小红、杨十八、小丽', 'WK32 杨十八、陈二、小丽、郑六、林十一', 'WK33 张三、刘一、孙七、王五'],
['WK34 小红、小刚、林十一', 'WK35 李四、杨十八、赵十五、朱九', 'WK36 朱九、赵六、张三、赵十五、小李'],
['WK37 杨三、陈二、刘一', 'WK38 朱九、小明、吴十九、孙七', 'WK39 刘一、陈二、小刚、赵六'],
[
'WK40 王五、小红、刘十三、杨十八',
'WK41 赵十五、黄十二、周十六、张三',
'WK42 朱九、赵十五、周十六、李八、黄十二',
],
['WK43 小刚、吴十九、周五、朱九、李八', 'WK44 小李、周五、王五', 'WK45 杨十八、黄十二、李八'],
['WK46 李四、小丽、王五、吴十九', 'WK47 何十、孙七、小李', 'WK48 林十一、钟二十一、小刚、刘一'],
[
'WK49 赵十五、王五、周十六、小丽、杨十八',
'WK50 郑六、周十六、李八',
'WK51 王十四、小刚、赵十五、陈二、林十一',
],
['WK52 小刚、李四、吴十九', 'WK53 周五、李八、周十六', 'WK54 吴十九、周十六、林十一'],
['WK55 郑六、小李、王五、李八、钟二十一', 'WK56 小李、刘十三、周五', 'WK57 何十、周十六、吴四、小红、许二十'],
[
'WK58 孙七、杨十八、陈十七、王五、李八',
'WK59 赵六、杨十八、周十六',
'WK60 杨三、周十六、刘一、赵六、许二十',
],
[
'WK61 钟二十一、杨十八、刘一、杨三、黄十二',
'WK62 李八、何十、刘十三、王五、陈十七',
'WK63 李八、朱九、王十四、小丽、郑六',
],
[
'WK64 刘十三、小明、黄十二、小红',
'WK65 杨十八、陈二、黄十二、赵六、周十六',
'WK66 赵六、吴十九、小丽、刘一、张三',
],
['WK67 孙七、小刚、王五、吴四', 'WK68 刘十三、周十六、王十四、张三、杨三', 'WK69 杨十八、李八、孙七、陈十七'],
['WK70 小李、陈十七、张三', 'WK71 赵六、刘一、钟二十一、赵十五', 'WK72 杨三、钟二十一、小红、小李、王十四'],
['WK73 周十六、小刚、小李、小红、陈十七', 'WK74 吴十九、孙七、小红', 'WK75 刘一、李四、周十六'],
['WK76 杨十八、郑六、陈十七、赵六', 'WK77 李八、张三、小丽', 'WK78 王五、吴十九、刘一、孙七、何十'],
],
rowNum: 12,
waitTime: 5000,
carousel: 'page',
},
};
},
};
</script>
<style lang="scss" scoped>
.scheduling {
width: 100%;
height: 100%;
:deep(.dv-border-box-11) {
height: 100%;
.dv-scroll-board {
padding: 3% 1% 0;
box-sizing: border-box;
height: 92%;
.ceil{
font-size: 20px;
white-space: nowrap;
/* border-right: 1px dashed #fff; */
}
}
}
}
</style>

@ -0,0 +1,5 @@
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
transpileDependencies: true,
publicPath: './',
});
Loading…
Cancel
Save