init:库尔勒妇幼项目初始化
8
.env.development
Normal file
@@ -0,0 +1,8 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 妇幼小程序拓展
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 妇幼小程序拓展/开发环境
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
11
.env.production
Normal file
@@ -0,0 +1,11 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 妇幼小程序拓展
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
|
||||
# 妇幼小程序拓展/生产环境
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
11
.env.staging
Normal file
@@ -0,0 +1,11 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 妇幼小程序拓展
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
# 妇幼小程序拓展/生产环境
|
||||
VITE_APP_BASE_API = '/stage-api'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Vue 3 + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
|
||||
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/star.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>mini-expand</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
5129
package-lock.json
generated
Normal file
29
package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "miniexpand",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"axios": "^1.7.7",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts": "^5.5.1",
|
||||
"element-plus": "^2.8.3",
|
||||
"moment": "^2.30.1",
|
||||
"pinia": "^2.3.1",
|
||||
"sass": "^1.78.0",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vue": "^3.4.37",
|
||||
"vue-router": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.1.2",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"vite": "^5.4.1"
|
||||
}
|
||||
}
|
||||
1
public/star.svg
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
18
src/App.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<script setup>
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/zh-cn";
|
||||
dayjs.locale("zh-cn");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<router-view/>
|
||||
</el-config-provider>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
24
src/api/auth.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
|
||||
export function getAuther(req) {
|
||||
return request({
|
||||
url: '/countAutho/getAuther',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getPerm(req) {
|
||||
return request({
|
||||
url: '/countAutho/getPerm',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getDeptPerm(req) {
|
||||
return request({
|
||||
url: '/countAutho/getDeptPerm',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
10
src/api/dept.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
//收入数值统计
|
||||
export function getDeptData(req) {
|
||||
return request({
|
||||
url: '/his/getUniqueLb25Data',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
66
src/api/hospitalization.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
//测试接口
|
||||
export function getHosData(req) {
|
||||
return request({
|
||||
url: '/his/countData',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB21Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB21Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB24Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB24Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB23Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB24Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB22Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB22Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB20Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB20Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export function getLB19Options(req) {
|
||||
return request({
|
||||
url: '/his/getLB19Options',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
63
src/api/outpatient.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
//测试接口
|
||||
export function getOutPatientData(req) {
|
||||
return request({
|
||||
url: '/his/countData',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
export function getSpecialData(req) {
|
||||
return request({
|
||||
url: '/his/specialSingleCount',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
export function getSingleDeptCount(req) {
|
||||
return request({
|
||||
url: '/his/getSingleDeptCount',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
export function getChildSpecialSingleCount(req) {
|
||||
return request({
|
||||
url: '/his/getChildSpecialSingleCount',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getChildSingleBudget(req) {
|
||||
return request({
|
||||
url: '/his/getChildSingleBudget',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getTMB(req) {
|
||||
return request({
|
||||
url: '/his/getTMB',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getCDB(req) {
|
||||
return request({
|
||||
url: '/his/getCDB',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
export function getEMDB(req) {
|
||||
return request({
|
||||
url: '/his/getEMDB',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
19
src/api/synthesis.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
//收入数值统计
|
||||
export function getCountData(req) {
|
||||
return request({
|
||||
url: '/his/countData',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
//收入饼图统计
|
||||
export function getSynPieCountData(req) {
|
||||
return request({
|
||||
url: '/his/synPieCountData',
|
||||
method: 'get',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
BIN
src/assets/401_images/401.gif
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
src/assets/404_images/404.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
src/assets/404_images/404_cloud.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
src/assets/gesture_images/down.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/icons/svg/bug.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/icons/svg/statistics.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1733301290071" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5121" width="48" height="48"><path d="M1008.64 993.28h-117.76v-460.8c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v460.8h-150.016v-209.92c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v209.92h-150.016v-250.88c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v250.88H349.696v-296.96c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v296.96H168.96v-174.08c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v174.08H30.72V107.52c0-8.704-6.656-15.36-15.36-15.36s-15.36 6.656-15.36 15.36v901.12c0 8.192 6.656 15.36 15.36 15.36h993.28c8.704 0 15.36-7.168 15.36-15.36 0-8.704-6.656-15.36-15.36-15.36z" p-id="5122" fill="#1296db"></path><path d="M153.6 450.56c3.584 0 7.168-1.536 10.24-4.096l169.984-155.136 168.96 125.44c2.56 2.048 5.12 3.072 8.192 3.072l184.32 10.24c5.12 0.512 10.24-2.048 13.312-6.656l179.2-256c5.12-7.168 3.072-16.384-3.584-21.504-7.168-5.12-16.384-3.072-21.504 3.584l-174.08 248.832-171.008-9.728-175.616-129.536c-6.144-4.608-14.336-4.096-19.456 1.024l-179.2 163.84c-6.144 5.632-6.656 15.36-1.024 21.504 3.072 3.584 7.168 5.12 11.264 5.12z" p-id="5123" fill="#1296db"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
99
src/assets/styles/btn.scss
Normal file
@@ -0,0 +1,99 @@
|
||||
@import './variables.module.scss';
|
||||
|
||||
@mixin colorBtn($color) {
|
||||
background: $color;
|
||||
|
||||
&:hover {
|
||||
color: $color;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
background: $color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.blue-btn {
|
||||
@include colorBtn($blue)
|
||||
}
|
||||
|
||||
.light-blue-btn {
|
||||
@include colorBtn($light-blue)
|
||||
}
|
||||
|
||||
.red-btn {
|
||||
@include colorBtn($red)
|
||||
}
|
||||
|
||||
.pink-btn {
|
||||
@include colorBtn($pink)
|
||||
}
|
||||
|
||||
.green-btn {
|
||||
@include colorBtn($green)
|
||||
}
|
||||
|
||||
.tiffany-btn {
|
||||
@include colorBtn($tiffany)
|
||||
}
|
||||
|
||||
.yellow-btn {
|
||||
@include colorBtn($yellow)
|
||||
}
|
||||
|
||||
.pan-btn {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
padding: 14px 36px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
outline: none;
|
||||
transition: 600ms ease all;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
width: 100%;
|
||||
transition: 600ms ease all;
|
||||
}
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
width: 0;
|
||||
transition: 400ms ease all;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: inherit;
|
||||
top: inherit;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-button {
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
background: #fff;
|
||||
color: #fff;
|
||||
-webkit-appearance: none;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
padding: 10px 15px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
109
src/assets/styles/element-ui.scss
Normal file
@@ -0,0 +1,109 @@
|
||||
// cover some element-ui styles
|
||||
|
||||
.el-breadcrumb__inner,
|
||||
.el-breadcrumb__inner a {
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.el-upload {
|
||||
input[type="file"] {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-upload__input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cell {
|
||||
.el-tag {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.small-padding {
|
||||
.cell {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.fixed-width {
|
||||
.el-button--mini {
|
||||
padding: 7px 10px;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.status-col {
|
||||
.cell {
|
||||
padding: 0 10px;
|
||||
text-align: center;
|
||||
|
||||
.el-tag {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// refine element ui upload
|
||||
.upload-container {
|
||||
.el-upload {
|
||||
width: 100%;
|
||||
|
||||
.el-upload-dragger {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dropdown
|
||||
.el-dropdown-menu {
|
||||
a {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
|
||||
// fix date-picker ui bug in filter-item
|
||||
.el-range-editor.el-input__inner {
|
||||
display: inline-flex !important;
|
||||
}
|
||||
|
||||
// to fix el-date-picker css style
|
||||
.el-range-separator {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.el-menu--collapse
|
||||
> div
|
||||
> .el-submenu
|
||||
> .el-submenu__title
|
||||
.el-submenu__icon-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-dropdown .el-dropdown-link{
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
//.el-dialog {
|
||||
// display: flex !important;
|
||||
// flex-direction: column !important;
|
||||
// margin: 0 !important;
|
||||
// position: absolute !important;
|
||||
// top: 50% !important;
|
||||
// left: 50% !important;
|
||||
// transform: translate(-50%, -50%) !important;
|
||||
// overflow-y: scroll !important;
|
||||
// max-height: 100vh !important;
|
||||
//}
|
||||
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||
.el-dialog {
|
||||
transform: none;
|
||||
left: 0;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
184
src/assets/styles/index.scss
Normal file
@@ -0,0 +1,184 @@
|
||||
@import './variables.module.scss';
|
||||
@import './mixin.scss';
|
||||
@import './transition.scss';
|
||||
@import './element-ui.scss';
|
||||
@import './sidebar.scss';
|
||||
@import './btn.scss';
|
||||
@import './ruoyi.scss';
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.padding-content {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
a:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a,
|
||||
a:focus,
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.fr {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.pr-5 {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.pl-5 {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineBlock {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
&:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
aside {
|
||||
background: #eef1f6;
|
||||
padding: 8px 24px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
color: #2c3e50;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
a {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//main-container全局样式
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.components-container {
|
||||
margin: 30px 50px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.sub-navbar {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding-right: 20px;
|
||||
transition: 600ms ease position;
|
||||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
||||
|
||||
.subtitle {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.draft {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
|
||||
&.deleted {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
}
|
||||
|
||||
.link-type,
|
||||
.link-type:focus {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
padding-bottom: 10px;
|
||||
|
||||
.filter-item {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
66
src/assets/styles/mixin.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
@mixin clearfix {
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrollBar {
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin relative {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@mixin pct($pct) {
|
||||
width: #{$pct};
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@mixin triangle($width, $height, $color, $direction) {
|
||||
$width: $width/2;
|
||||
$color-border-style: $height solid $color;
|
||||
$transparent-border-style: $width solid transparent;
|
||||
height: 0;
|
||||
width: 0;
|
||||
|
||||
@if $direction==up {
|
||||
border-bottom: $color-border-style;
|
||||
border-left: $transparent-border-style;
|
||||
border-right: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==right {
|
||||
border-left: $color-border-style;
|
||||
border-top: $transparent-border-style;
|
||||
border-bottom: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==down {
|
||||
border-top: $color-border-style;
|
||||
border-left: $transparent-border-style;
|
||||
border-right: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==left {
|
||||
border-right: $color-border-style;
|
||||
border-top: $transparent-border-style;
|
||||
border-bottom: $transparent-border-style;
|
||||
}
|
||||
}
|
||||
281
src/assets/styles/ruoyi.scss
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* 通用css样式布局处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
/** 基础通用 **/
|
||||
.pt5 {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.el-form .el-form-item__label {
|
||||
font-weight: 700;
|
||||
}
|
||||
.el-dialog:not(.is-fullscreen) {
|
||||
margin-top: 6vh !important;
|
||||
}
|
||||
|
||||
.el-dialog.scrollbar .el-dialog__body {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 10px 20px 0;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9 !important;
|
||||
color: #515a6e;
|
||||
height: 15px !important;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*="el-icon-"] + span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 表单布局 **/
|
||||
.form-header {
|
||||
font-size:15px;
|
||||
color:#6379bb;
|
||||
border-bottom:1px solid #ddd;
|
||||
margin:8px 10px 25px 10px;
|
||||
padding-bottom:5px
|
||||
}
|
||||
|
||||
/** 表格布局 **/
|
||||
.pagination-container {
|
||||
position: relative;
|
||||
height: 25px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px !important;
|
||||
}
|
||||
|
||||
.el-dialog .pagination-container {
|
||||
position: static !important;
|
||||
}
|
||||
|
||||
/* tree border */
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border-radius:4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media ( max-width : 768px) {
|
||||
.pagination-container .el-pagination > .el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table .fixed-width .el-button--small {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
/** 表格更多操作下拉样式 */
|
||||
.el-table .el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-tree-node__content > .el-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.list-group-striped > .list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.el-card__header {
|
||||
padding: 14px 15px 7px !important;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.el-card__body {
|
||||
padding: 15px 20px 20px 20px !important;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1c84c6;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #23c6c8;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #f8ac59;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #ed5565;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
/* image */
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 拖拽列样式 */
|
||||
.sortable-ghost{
|
||||
opacity: .8;
|
||||
color: #fff!important;
|
||||
background: #42b983!important;
|
||||
}
|
||||
|
||||
/* 表格右侧工具栏样式 */
|
||||
.top-right-btn {
|
||||
margin-left: auto;
|
||||
}
|
||||
238
src/assets/styles/sidebar.scss
Normal file
@@ -0,0 +1,238 @@
|
||||
#app {
|
||||
|
||||
.main-container {
|
||||
height: 100%;
|
||||
transition: margin-left .28s;
|
||||
margin-left: $base-sidebar-width;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebarHide {
|
||||
margin-left: 0!important;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
-webkit-transition: width .28s;
|
||||
transition: width 0.28s;
|
||||
width: $base-sidebar-width !important;
|
||||
background-color: $base-menu-background;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
font-size: 0px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||
box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||
|
||||
// reset element-ui css
|
||||
.horizontal-collapse-transition {
|
||||
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
||||
}
|
||||
|
||||
.scrollbar-wrapper {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar.is-vertical {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.el-scrollbar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.has-logo {
|
||||
.el-scrollbar {
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
}
|
||||
|
||||
.is-horizontal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.el-menu {
|
||||
border: none;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.el-menu-item, .menu-title {
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
.el-menu-item .el-menu-tooltip__trigger {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
// menu hover
|
||||
.sub-menu-title-noDropdown,
|
||||
.el-sub-menu__title {
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
& .theme-dark .is-active > .el-sub-menu__title {
|
||||
color: $base-menu-color-active !important;
|
||||
}
|
||||
|
||||
& .nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||
& .el-sub-menu .el-menu-item {
|
||||
min-width: $base-sidebar-width !important;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
& .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||
& .theme-dark .el-sub-menu .el-menu-item {
|
||||
background-color: $base-sub-menu-background !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $base-sub-menu-hover !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hideSidebar {
|
||||
.sidebar-container {
|
||||
width: 54px !important;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-left: 54px;
|
||||
}
|
||||
|
||||
.sub-menu-title-noDropdown {
|
||||
padding: 0 !important;
|
||||
position: relative;
|
||||
|
||||
.el-tooltip {
|
||||
padding: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-sub-menu {
|
||||
overflow: hidden;
|
||||
|
||||
&>.el-sub-menu__title {
|
||||
padding: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu--collapse {
|
||||
.el-sub-menu {
|
||||
&>.el-sub-menu__title {
|
||||
&>span {
|
||||
height: 0;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
}
|
||||
&>i {
|
||||
height: 0;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu--collapse .el-menu .el-sub-menu {
|
||||
min-width: $base-sidebar-width !important;
|
||||
}
|
||||
|
||||
// mobile responsive
|
||||
.mobile {
|
||||
.main-container {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
transition: transform .28s;
|
||||
width: $base-sidebar-width !important;
|
||||
}
|
||||
|
||||
&.hideSidebar {
|
||||
.sidebar-container {
|
||||
pointer-events: none;
|
||||
transition-duration: 0.3s;
|
||||
transform: translate3d(-$base-sidebar-width, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.withoutAnimation {
|
||||
|
||||
.main-container,
|
||||
.sidebar-container {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// when menu collapsed
|
||||
.el-menu--vertical {
|
||||
&>.el-menu {
|
||||
.svg-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||
.el-menu-item {
|
||||
&:hover {
|
||||
// you can use $sub-menuHover
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// the scroll bar appears when the sub-menu is too long
|
||||
>.el-menu--popup {
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/assets/styles/transition.scss
Normal file
@@ -0,0 +1,49 @@
|
||||
// global transition css
|
||||
|
||||
/* fade */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.28s;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* fade-transform */
|
||||
.fade-transform--move,
|
||||
.fade-transform-leave-active,
|
||||
.fade-transform-enter-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.fade-transform-enter {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
|
||||
.fade-transform-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
/* breadcrumb transition */
|
||||
.breadcrumb-enter-active,
|
||||
.breadcrumb-leave-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.breadcrumb-enter,
|
||||
.breadcrumb-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.breadcrumb-move {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.breadcrumb-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
65
src/assets/styles/variables.module.scss
Normal file
@@ -0,0 +1,65 @@
|
||||
// base color
|
||||
$blue: #324157;
|
||||
$light-blue: #3A71A8;
|
||||
$red: #C03639;
|
||||
$pink: #E65D6E;
|
||||
$green: #30B08F;
|
||||
$tiffany: #4AB7BD;
|
||||
$yellow: #FEC171;
|
||||
$panGreen: #30B08F;
|
||||
|
||||
// 默认菜单主题风格
|
||||
$base-menu-color: #bfcbd9;
|
||||
$base-menu-color-active: #f4f4f5;
|
||||
$base-menu-background: #304156;
|
||||
$base-logo-title-color: #ffffff;
|
||||
|
||||
$base-menu-light-color: rgba(0, 0, 0, 0.7);
|
||||
$base-menu-light-background: #ffffff;
|
||||
$base-logo-light-title-color: #001529;
|
||||
|
||||
$base-sub-menu-background: #1f2d3d;
|
||||
$base-sub-menu-hover: #001528;
|
||||
|
||||
// 自定义暗色菜单风格
|
||||
/**
|
||||
$base-menu-color:hsla(0,0%,100%,.65);
|
||||
$base-menu-color-active:#fff;
|
||||
$base-menu-background:#001529;
|
||||
$base-logo-title-color: #ffffff;
|
||||
|
||||
$base-menu-light-color:rgba(0,0,0,.70);
|
||||
$base-menu-light-background:#ffffff;
|
||||
$base-logo-light-title-color: #001529;
|
||||
|
||||
$base-sub-menu-background:#000c17;
|
||||
$base-sub-menu-hover:#001528;
|
||||
*/
|
||||
|
||||
$--color-primary: #409EFF;
|
||||
$--color-success: #67C23A;
|
||||
$--color-warning: #E6A23C;
|
||||
$--color-danger: #F56C6C;
|
||||
$--color-info: #909399;
|
||||
|
||||
$base-sidebar-width: 200px;
|
||||
|
||||
// the :export directive is the magic sauce for webpack
|
||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
||||
:export {
|
||||
menuColor: $base-menu-color;
|
||||
menuLightColor: $base-menu-light-color;
|
||||
menuColorActive: $base-menu-color-active;
|
||||
menuBackground: $base-menu-background;
|
||||
menuLightBackground: $base-menu-light-background;
|
||||
subMenuBackground: $base-sub-menu-background;
|
||||
subMenuHover: $base-sub-menu-hover;
|
||||
sideBarWidth: $base-sidebar-width;
|
||||
logoTitleColor: $base-logo-title-color;
|
||||
logoLightTitleColor: $base-logo-light-title-color;
|
||||
primaryColor: $--color-primary;
|
||||
successColor: $--color-success;
|
||||
dangerColor: $--color-danger;
|
||||
infoColor: $--color-info;
|
||||
warningColor: $--color-warning;
|
||||
}
|
||||
53
src/components/SvgIcon/index.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<svg :class="svgClass" aria-hidden="true">
|
||||
<use :xlink:href="iconName" :fill="color" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default defineComponent({
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
return {
|
||||
iconName: computed(() => `#icon-${props.iconClass}`),
|
||||
svgClass: computed(() => {
|
||||
if (props.className) {
|
||||
return `svg-icon ${props.className}`
|
||||
}
|
||||
return 'svg-icon'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scope lang="scss">
|
||||
.sub-el-icon,
|
||||
.nav-icon {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
margin-right: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
fill: currentColor;
|
||||
vertical-align: -2px;
|
||||
}
|
||||
</style>
|
||||
10
src/components/SvgIcon/svgicon.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import * as components from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
install: (app) => {
|
||||
for (const key in components) {
|
||||
const componentConfig = components[key];
|
||||
app.component(componentConfig.name, componentConfig);
|
||||
}
|
||||
},
|
||||
};
|
||||
5
src/directive/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import hasPermi from './permission/hasPermi'
|
||||
|
||||
export default function directive(app){
|
||||
app.directive('hasPermi', hasPermi)
|
||||
}
|
||||
51
src/directive/permission/hasPermi.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* v-hasPermi 操作权限处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
export default {
|
||||
|
||||
mounted(el, binding, vnode) {
|
||||
const {value} = binding
|
||||
const all_permission = "*:*:*";
|
||||
const permissions = useUserStore().permissions
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const permissionFlag = value
|
||||
const hasPermissions = permissions.some(permission => {
|
||||
return all_permission === permission || permissionFlag.includes(permission)
|
||||
})
|
||||
|
||||
if (!hasPermissions) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`请设置操作权限标签值`)
|
||||
}
|
||||
}
|
||||
// mounted(el, binding, vnode) {
|
||||
// const {value} = binding
|
||||
// const all_permission = "*:*:*";
|
||||
// setTimeout(()=>{
|
||||
//
|
||||
// const permissions = useUserStore().permissions
|
||||
//
|
||||
// if (value && value instanceof Array && value.length > 0) {
|
||||
// const permissionFlag = value
|
||||
// const hasPermissions = permissions.some(permission => {
|
||||
// console.log("permission", permission)
|
||||
// return all_permission === permission || permissionFlag.includes(permission)
|
||||
// })
|
||||
//
|
||||
// if (!hasPermissions) {
|
||||
// console.log("mei")
|
||||
// el.parentNode && el.parentNode.removeChild(el)
|
||||
// }
|
||||
// } else {
|
||||
// throw new Error(`请设置操作权限标签值`)
|
||||
// }
|
||||
// },1000)
|
||||
//
|
||||
// }
|
||||
}
|
||||
27
src/main.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import {createApp} from 'vue'
|
||||
import '@/assets/styles/index.scss' // global css
|
||||
import App from './App.vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import router from './router'
|
||||
import directive from './directive' // directive
|
||||
|
||||
|
||||
// svg图标
|
||||
import 'virtual:svg-icons-register'
|
||||
import SvgIcon from '@/components/SvgIcon'
|
||||
import elementIcons from '@/components/SvgIcon/svgicon'
|
||||
import store from './store'
|
||||
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
// 使用element-plus 并且设置全局的大小
|
||||
app.use(ElementPlus)
|
||||
app.use(store)
|
||||
app.use(elementIcons)
|
||||
app.component('svg-icon', SvgIcon)
|
||||
directive(app)
|
||||
|
||||
app.mount('#app')
|
||||
70
src/router/index.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
|
||||
import {getAuther, getPerm} from "@/api/auth.js";
|
||||
import useUserStore from "@/store/modules/user.js";
|
||||
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/synthesis',
|
||||
component: () => import('@/views/synthesis/index.vue'),
|
||||
meta: {title: '综合统计'}
|
||||
},
|
||||
{
|
||||
path: '/integrative',
|
||||
component: () => import('@/views/integrative/index.vue'),
|
||||
meta: {title: '全院综合统计'}
|
||||
},
|
||||
{
|
||||
path: '/hospitalization',
|
||||
component: () => import('@/views/hospitalization/index.vue'),
|
||||
meta: {title: '住院统计'}
|
||||
}, {
|
||||
path: '/inhos',
|
||||
component: () => import('@/views/inhos/index.vue'),
|
||||
meta: {title: '住院统计'}
|
||||
},
|
||||
{
|
||||
path: '/outpatient',
|
||||
component: () => import('@/views/outpatient/index.vue'),
|
||||
meta: {title: '门诊统计'}
|
||||
},
|
||||
{
|
||||
path: '/opd',
|
||||
component: () => import('@/views/opd/index.vue'),
|
||||
meta: {title: '门诊统计'}
|
||||
},
|
||||
{
|
||||
path: '/dept',
|
||||
component: () => import('@/views/dept/index.vue'),
|
||||
meta: {title: '科室统计'}
|
||||
},
|
||||
{
|
||||
path: '/401',
|
||||
component: () => import('@/views/error/401.vue'),
|
||||
},
|
||||
|
||||
]
|
||||
const router = createRouter(
|
||||
{
|
||||
history: createWebHashHistory(),
|
||||
routes: constantRoutes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
return {top: 0}
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
await useUserStore().getInfo(to)
|
||||
if (to.meta.title) {
|
||||
document.title = to.meta.title
|
||||
}
|
||||
next()
|
||||
|
||||
})
|
||||
|
||||
export default router;
|
||||
3
src/store/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const store = createPinia()
|
||||
|
||||
export default store
|
||||
34
src/store/modules/user.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import {getPerm} from "@/api/auth.js";
|
||||
|
||||
const useUserStore = defineStore(
|
||||
'user',
|
||||
{
|
||||
state: () => ({
|
||||
id: '',
|
||||
name: '',
|
||||
avatar: '',
|
||||
roles: [],
|
||||
permissions: [],
|
||||
}),
|
||||
actions: {
|
||||
async getInfo(to) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const a = to.fullPath
|
||||
var strings = a.split('=');
|
||||
if (strings[1] === '' || strings[1] === null || strings[1] === undefined) {
|
||||
reject("没有openid")
|
||||
}
|
||||
let req = {
|
||||
'openid': strings[1]
|
||||
}
|
||||
getPerm(req).then(res => {
|
||||
this.permissions = res.data
|
||||
resolve(res)
|
||||
})
|
||||
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
export default useUserStore
|
||||
6
src/utils/errorCode.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'401': '认证失败,无法访问系统资源',
|
||||
'403': '当前操作没有权限',
|
||||
'404': '访问资源不存在',
|
||||
'default': '系统未知错误,请反馈给管理员'
|
||||
}
|
||||
67
src/utils/request.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import axios from 'axios'
|
||||
import errorCode from '@/utils/errorCode'
|
||||
import {tansParams} from '@/utils/ruoyi'
|
||||
import {ElNotification, ElMessage} from 'element-plus'
|
||||
|
||||
const service = axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
// 超时
|
||||
timeout: 30000
|
||||
})
|
||||
// request拦截器
|
||||
service.interceptors.request.use(config => {
|
||||
// get请求映射params参数
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = config.url + '?' + tansParams(config.params);
|
||||
url = url.slice(0, -1);
|
||||
config.params = {};
|
||||
config.url = url;
|
||||
}
|
||||
return config
|
||||
}, error => {
|
||||
console.log(error)
|
||||
Promise.reject(error)
|
||||
})
|
||||
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(res => {
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = res.data.code || 20000;
|
||||
// 获取错误信息
|
||||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
||||
|
||||
if (code === 401) {
|
||||
//提示校验失败,openid不对,重定向
|
||||
ElMessage({message: msg, type: 'error'})
|
||||
return Promise.reject('无效的会话,请确认身份!')
|
||||
} else if (code === 500) {
|
||||
ElMessage({message: msg, type: 'error'})
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code === 601) {
|
||||
ElMessage({message: msg, type: 'warning'})
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code !== 20000) {
|
||||
ElNotification.error({title: msg})
|
||||
return Promise.reject('error')
|
||||
} else {
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log('err' + error)
|
||||
let {message} = error;
|
||||
if (message == "Network Error") {
|
||||
message = "后端接口连接异常";
|
||||
} else if (message.includes("timeout")) {
|
||||
message = "系统接口请求超时";
|
||||
} else if (message.includes("Request failed with status code")) {
|
||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||
}
|
||||
ElMessage({message: message, type: 'error', duration: 5 * 1000})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
||||
246
src/utils/ruoyi.js
Normal file
@@ -0,0 +1,246 @@
|
||||
|
||||
|
||||
/**
|
||||
* 通用js方法封装处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
// 日期格式化
|
||||
export function parseTime(time, pattern) {
|
||||
if (arguments.length === 0 || !time) {
|
||||
return null
|
||||
}
|
||||
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||
let date
|
||||
if (typeof time === 'object') {
|
||||
date = time
|
||||
} else {
|
||||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||
time = parseInt(time)
|
||||
} else if (typeof time === 'string') {
|
||||
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
|
||||
}
|
||||
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||
time = time * 1000
|
||||
}
|
||||
date = new Date(time)
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay()
|
||||
}
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key]
|
||||
// Note: getDay() returns 0 on Sunday
|
||||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = '0' + value
|
||||
}
|
||||
return value || 0
|
||||
})
|
||||
return time_str
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
export function resetForm(refName) {
|
||||
if (this.$refs[refName]) {
|
||||
this.$refs[refName].resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加日期范围
|
||||
export function addDateRange(params, dateRange, propName) {
|
||||
let search = params;
|
||||
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
|
||||
dateRange = Array.isArray(dateRange) ? dateRange : [];
|
||||
if (typeof (propName) === 'undefined') {
|
||||
search.params['beginTime'] = dateRange[0];
|
||||
search.params['endTime'] = dateRange[1];
|
||||
} else {
|
||||
search.params['begin' + propName] = dateRange[0];
|
||||
search.params['end' + propName] = dateRange[1];
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
// 回显数据字典
|
||||
export function selectDictLabel(datas, value) {
|
||||
if (value === undefined) {
|
||||
return "";
|
||||
}
|
||||
var actions = [];
|
||||
Object.keys(datas).some((key) => {
|
||||
if (datas[key].value == ('' + value)) {
|
||||
actions.push(datas[key].label);
|
||||
return true;
|
||||
}
|
||||
})
|
||||
if (actions.length === 0) {
|
||||
actions.push(value);
|
||||
}
|
||||
return actions.join('');
|
||||
}
|
||||
|
||||
// 回显数据字典(字符串数组)
|
||||
export function selectDictLabels(datas, value, separator) {
|
||||
if (value === undefined || value.length ===0) {
|
||||
return "";
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
value = value.join(",");
|
||||
}
|
||||
var actions = [];
|
||||
var currentSeparator = undefined === separator ? "," : separator;
|
||||
var temp = value.split(currentSeparator);
|
||||
Object.keys(value.split(currentSeparator)).some((val) => {
|
||||
var match = false;
|
||||
Object.keys(datas).some((key) => {
|
||||
if (datas[key].value == ('' + temp[val])) {
|
||||
actions.push(datas[key].label + currentSeparator);
|
||||
match = true;
|
||||
}
|
||||
})
|
||||
if (!match) {
|
||||
actions.push(temp[val] + currentSeparator);
|
||||
}
|
||||
})
|
||||
return actions.join('').substring(0, actions.join('').length - 1);
|
||||
}
|
||||
|
||||
// 字符串格式化(%s )
|
||||
export function sprintf(str) {
|
||||
var args = arguments, flag = true, i = 1;
|
||||
str = str.replace(/%s/g, function () {
|
||||
var arg = args[i++];
|
||||
if (typeof arg === 'undefined') {
|
||||
flag = false;
|
||||
return '';
|
||||
}
|
||||
return arg;
|
||||
});
|
||||
return flag ? str : '';
|
||||
}
|
||||
|
||||
// 转换字符串,undefined,null等转化为""
|
||||
export function parseStrEmpty(str) {
|
||||
if (!str || str == "undefined" || str == "null") {
|
||||
return "";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// 数据合并
|
||||
export function mergeRecursive(source, target) {
|
||||
for (var p in target) {
|
||||
try {
|
||||
if (target[p].constructor == Object) {
|
||||
source[p] = mergeRecursive(source[p], target[p]);
|
||||
} else {
|
||||
source[p] = target[p];
|
||||
}
|
||||
} catch (e) {
|
||||
source[p] = target[p];
|
||||
}
|
||||
}
|
||||
return source;
|
||||
};
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
*/
|
||||
export function handleTree(data, id, parentId, children) {
|
||||
let config = {
|
||||
id: id || 'id',
|
||||
parentId: parentId || 'parentId',
|
||||
childrenList: children || 'children'
|
||||
};
|
||||
|
||||
var childrenListMap = {};
|
||||
var nodeIds = {};
|
||||
var tree = [];
|
||||
|
||||
for (let d of data) {
|
||||
let parentId = d[config.parentId];
|
||||
if (childrenListMap[parentId] == null) {
|
||||
childrenListMap[parentId] = [];
|
||||
}
|
||||
nodeIds[d[config.id]] = d;
|
||||
childrenListMap[parentId].push(d);
|
||||
}
|
||||
|
||||
for (let d of data) {
|
||||
let parentId = d[config.parentId];
|
||||
if (nodeIds[parentId] == null) {
|
||||
tree.push(d);
|
||||
}
|
||||
}
|
||||
|
||||
for (let t of tree) {
|
||||
adaptToChildrenList(t);
|
||||
}
|
||||
|
||||
function adaptToChildrenList(o) {
|
||||
if (childrenListMap[o[config.id]] !== null) {
|
||||
o[config.childrenList] = childrenListMap[o[config.id]];
|
||||
}
|
||||
if (o[config.childrenList]) {
|
||||
for (let c of o[config.childrenList]) {
|
||||
adaptToChildrenList(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数处理
|
||||
* @param {*} params 参数
|
||||
*/
|
||||
export function tansParams(params) {
|
||||
let result = ''
|
||||
for (const propName of Object.keys(params)) {
|
||||
const value = params[propName];
|
||||
var part = encodeURIComponent(propName) + "=";
|
||||
if (value !== null && value !== "" && typeof (value) !== "undefined") {
|
||||
if (typeof value === 'object') {
|
||||
for (const key of Object.keys(value)) {
|
||||
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
|
||||
let params = propName + '[' + key + ']';
|
||||
var subPart = encodeURIComponent(params) + "=";
|
||||
result += subPart + encodeURIComponent(value[key]) + "&";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += part + encodeURIComponent(value) + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
// 返回项目路径
|
||||
export function getNormalPath(p) {
|
||||
if (p.length === 0 || !p || p == 'undefined') {
|
||||
return p
|
||||
};
|
||||
let res = p.replace('//', '/')
|
||||
if (res[res.length - 1] === '/') {
|
||||
return res.slice(0, res.length - 1)
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 验证是否为blob格式
|
||||
export function blobValidate(data) {
|
||||
return data.type !== 'application/json'
|
||||
}
|
||||
39
src/utils/vertify.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import CryptoJS from 'crypto-js';
|
||||
|
||||
const aecConfig = {
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
|
||||
var key = 'hqe0nb384oyjwnprd386jmslvoyt2io1'
|
||||
var iv = 'udfe1j8woobdmy51xbz7j4814aw9atdx'
|
||||
key = CryptoJS.enc.Utf8.parse(key)
|
||||
iv = CryptoJS.enc.Utf8.parse(iv)
|
||||
|
||||
//加密方法
|
||||
function AES_EN(text) {
|
||||
|
||||
const encrypted = CryptoJS.AES.encrypt(text, key, {
|
||||
iv,
|
||||
...aecConfig
|
||||
})
|
||||
return encrypted.ciphertext.toString()
|
||||
}
|
||||
|
||||
//解密方法
|
||||
function AES_DE(text) {
|
||||
text = CryptoJS.enc.Hex.parse(text)
|
||||
const decrypt = CryptoJS.AES.decrypt({
|
||||
ciphertext: text
|
||||
}, key, {
|
||||
iv,
|
||||
...aecConfig
|
||||
})
|
||||
const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
|
||||
return decryptedStr.toString()
|
||||
}
|
||||
|
||||
export {
|
||||
AES_EN,
|
||||
AES_DE
|
||||
}
|
||||
125
src/views/dept/index.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import moment from "moment/moment.js";
|
||||
import {getDeptData} from "@/api/dept.js";
|
||||
import {getDeptPerm} from "@/api/auth.js";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {AES_DE} from "@/utils/vertify.js";
|
||||
|
||||
onMounted(() => {
|
||||
deptPermList()
|
||||
})
|
||||
// 设置初始时间
|
||||
let today = new Date();
|
||||
today = moment(today).format("YYYYMMDD");
|
||||
const value1 = ref([today, today]);
|
||||
const showData = ref({
|
||||
depts: "",
|
||||
deptTableData: [],
|
||||
})
|
||||
|
||||
function deptPermList() {
|
||||
// 优先查询该openid的权限包含哪些科室
|
||||
var route = useRoute();
|
||||
var openid = route.query.openid;//从链接中获取openid
|
||||
if (typeof (openid) != "undefined" && openid != null && openid != '') {
|
||||
let req = {
|
||||
openid: openid
|
||||
}
|
||||
getDeptPerm(req).then(res => {
|
||||
// console.log(res)
|
||||
showData.value.depts = res.data
|
||||
tableInit()
|
||||
})
|
||||
} else {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
}
|
||||
|
||||
function tableInit() {
|
||||
|
||||
let req = {
|
||||
startTime: value1.value[0].toString(),
|
||||
endTime: value1.value[1].toString(),
|
||||
lb: "25",
|
||||
Dept: showData.value.depts
|
||||
}
|
||||
getDeptData(req).then(res => {
|
||||
// console.log(res)
|
||||
showData.value.deptTableData = res.data
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--日期选择器-->
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value1"
|
||||
type="daterange"
|
||||
style="width: 50vw"
|
||||
value-format="YYYYMMDD"
|
||||
range-separator="-"
|
||||
start-placeholder="起始日期"
|
||||
end-placeholder="结束日期"
|
||||
size="small"
|
||||
@change="tableInit"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder"></div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- 科室统计-->
|
||||
<span class="table-title">科室统计</span>
|
||||
<el-table :data="showData.deptTableData" size="small" flexible
|
||||
style="width: 100%; margin-top: 20px;font-size: 10px" stripe border>
|
||||
<el-table-column label="项目名称" prop="dxmmc" fixed align="center"></el-table-column>
|
||||
<el-table-column label="项目数量" prop="sl" align="center"></el-table-column>
|
||||
<el-table-column label="合计金额" prop="zje" align="center"></el-table-column>
|
||||
</el-table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dateChoose {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
margin-bottom: 1vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dateText {
|
||||
width: 15vw;
|
||||
}
|
||||
|
||||
.dateWrap {
|
||||
width: 15vw;
|
||||
}
|
||||
|
||||
.placeHolder {
|
||||
width: 42vw;
|
||||
}
|
||||
|
||||
.placeHolder2 {
|
||||
width: 25vw;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin-top: 1vh;
|
||||
margin-bottom: 1vh;
|
||||
opacity: 0.7 !important;
|
||||
}
|
||||
</style>
|
||||
82
src/views/error/401.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="errPage-container">
|
||||
<el-button icon="arrow-left" class="pan-back-btn" @click="back">
|
||||
返回
|
||||
</el-button>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<h1 class="text-jumbo text-ginormous">
|
||||
401错误!
|
||||
</h1>
|
||||
<h2>您没有访问权限!</h2>
|
||||
<h6>对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li class="link-type">
|
||||
<router-link to="/">
|
||||
回首页
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import errImage from "@/assets/401_images/401.gif";
|
||||
|
||||
let { proxy } = getCurrentInstance();
|
||||
|
||||
const errGif = ref(errImage + "?" + +new Date());
|
||||
|
||||
function back() {
|
||||
if (proxy.$route.query.noGoBack) {
|
||||
proxy.$router.push({ path: "/" });
|
||||
} else {
|
||||
proxy.$router.go(-1);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.errPage-container {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
margin: 100px auto;
|
||||
.pan-back-btn {
|
||||
background: #008489;
|
||||
color: #fff;
|
||||
border: none !important;
|
||||
}
|
||||
.pan-gif {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
.pan-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
.text-jumbo {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
color: #484848;
|
||||
}
|
||||
.list-unstyled {
|
||||
font-size: 14px;
|
||||
li {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
a {
|
||||
color: #008489;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
227
src/views/error/404.vue
Normal file
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">
|
||||
404错误!
|
||||
</div>
|
||||
<div class="bullshit__headline">
|
||||
{{ message }}
|
||||
</div>
|
||||
<div class="bullshit__info">
|
||||
对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
|
||||
</div>
|
||||
<router-link to="/index" class="bullshit__return-home">
|
||||
返回首页
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let message = computed(() => {
|
||||
return '找不到网页!'
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
603
src/views/hospitalization/index.vue
Normal file
@@ -0,0 +1,603 @@
|
||||
<script setup>
|
||||
import * as echarts from 'echarts';
|
||||
import {onMounted, ref} from "vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {AES_DE} from "@/utils/vertify.js";
|
||||
import moment from "moment/moment.js";
|
||||
import {getHosData} from '@/api/hospitalization.js'
|
||||
|
||||
onMounted(() => {
|
||||
generateLine()
|
||||
generateNowBar()
|
||||
generateTodayBar()
|
||||
changeHosHeaderDate()
|
||||
getNowData()
|
||||
changeHosBottomDate()
|
||||
verifyOpenid();
|
||||
})
|
||||
//设置展示的数据
|
||||
const showData = ref({
|
||||
outpatients:"",
|
||||
daysAvg:"",
|
||||
cwsyl:"",
|
||||
inpatients:"",
|
||||
badpatients:"",
|
||||
inhospatients:"",
|
||||
outhospatients:"",
|
||||
lastOuthospatients:"",
|
||||
lastInhospatients:"",
|
||||
|
||||
deptOptions:[],
|
||||
inHosOptions:[],
|
||||
outHosOptions:[]
|
||||
|
||||
});
|
||||
// 设置初始时间
|
||||
let today = new Date();
|
||||
today= moment(today).format("YYYYMMDD");
|
||||
const value1 = ref([today+"00:00:00",today+"23:59:59"]);
|
||||
const value2 = ref(today);
|
||||
//设置可以访问的人员
|
||||
const releaseUser = ref(['o-ZxO47Otvo5Rsq7kN-4PHvZIOt8', 'o-ZxO4-oIddDT0ecgxNEkvApJ-N0','o-ZxO4xd9dV7Dd6OOMKD6ukomD8c','o-ZxO47fz4FjMvL5ESLKcl0YqVJ8','o-ZxO49keb-3wV3CLAuFDpvrx-LQ',
|
||||
'o-ZxO47o9FYvO-Eor_JPCwzXS3ig','o-ZxO49XU81BKOSnDzKVGWrAZXGg']);
|
||||
|
||||
function verifyOpenid() {
|
||||
var route = useRoute();
|
||||
var openid = route.query.openid;//从链接中获取openid
|
||||
if (typeof (openid) != "undefined" && openid != null && openid != '') {
|
||||
var de = AES_DE(openid);//解密
|
||||
if (!releaseUser.value.includes(de)) {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
} else {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function changeHosHeaderDate(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "15"
|
||||
}
|
||||
for (let i = 15; i < 23; i++) {
|
||||
switch (i) {
|
||||
case 15:
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.outpatients = res.data.outpatients
|
||||
})
|
||||
break;
|
||||
case 16:
|
||||
req.lb="16"
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.daysAvg = res.data
|
||||
})
|
||||
break;
|
||||
case 17:
|
||||
req.lb="17"
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.cwsyl = res.data
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
getEachDeptInHos()
|
||||
}
|
||||
|
||||
var eachDeptOption = {
|
||||
title: {
|
||||
text: '各科入院概况',
|
||||
top: '10%',
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
left: 'right',
|
||||
data: ['出院', '入院'],
|
||||
top: "10%"
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right:
|
||||
'4%',
|
||||
bottom:
|
||||
'3%',
|
||||
containLabel:
|
||||
true
|
||||
}
|
||||
,
|
||||
xAxis: [
|
||||
{
|
||||
type: 'value'
|
||||
}
|
||||
],
|
||||
yAxis:
|
||||
[
|
||||
{
|
||||
type: 'category',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
data: [],
|
||||
}
|
||||
],
|
||||
series:
|
||||
[
|
||||
{
|
||||
name: '入院',
|
||||
type: 'bar',
|
||||
stack: 'Total',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside'
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: '出院',
|
||||
type: 'bar',
|
||||
stack: 'Total',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside'
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
data: []
|
||||
}
|
||||
]
|
||||
}
|
||||
const ec_today_bar = ref(null)
|
||||
var ecTodayBar = {}
|
||||
function generateTodayBar() {
|
||||
ecTodayBar = echarts.init(ec_today_bar.value)
|
||||
|
||||
}
|
||||
function getEachDeptInHos(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "22"
|
||||
}
|
||||
getHosData(req).then(res=>{
|
||||
let inDeptMap = res.inPatients
|
||||
var deptArray = []
|
||||
var inHosArray = []
|
||||
var outHosArray = []
|
||||
for (const Key in inDeptMap) {
|
||||
deptArray.push(Key)
|
||||
inHosArray.push(inDeptMap[Key])
|
||||
}
|
||||
let OUTDeptMap = res.outPatients
|
||||
for (const Key in OUTDeptMap) {
|
||||
outHosArray.push(-OUTDeptMap[Key])
|
||||
}
|
||||
eachDeptOption.yAxis[0].data=deptArray
|
||||
eachDeptOption.series[0].data= inHosArray
|
||||
eachDeptOption.series[1].data= outHosArray
|
||||
eachDeptOption && ecTodayBar.setOption(eachDeptOption)
|
||||
})
|
||||
}
|
||||
function getNowData(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "18"
|
||||
}
|
||||
for (let i = 18; i <=19; i++) {
|
||||
switch (i) {
|
||||
case 18:
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.inpatients = res.data.inpatients
|
||||
})
|
||||
break;
|
||||
case 19:
|
||||
req.lb= "19"
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.badpatients = res.data.badpatients
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getNowInHosData();
|
||||
getNowAndYesInHosData();
|
||||
}
|
||||
function getNowAndYesInHosData(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "21"
|
||||
}
|
||||
getHosData(req).then(res=>{
|
||||
console.log(res)
|
||||
showData.value.inhospatients= res.data.inhospatients
|
||||
showData.value.outhospatients= res.data.outhospatients
|
||||
})
|
||||
req.startTime= moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"00:00:00"
|
||||
req.endTime = moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"23:59:59"
|
||||
getHosData(req).then(res=>{
|
||||
showData.value.lastInhospatients= res.data.inhospatients
|
||||
showData.value.lastOuthospatients= res.data.outhospatients
|
||||
})
|
||||
}
|
||||
var nowInHosOption = {
|
||||
title: {
|
||||
text: '当前在院人数',
|
||||
top: '10%',
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01],
|
||||
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: ['孕产保健部', '妇女保健部', '儿童保健部统计'],
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '人次',
|
||||
type: 'bar',
|
||||
data: [2, 18, 10]
|
||||
},
|
||||
]
|
||||
};
|
||||
const ec_now_bar = ref(null)
|
||||
var ecNowBar ={}
|
||||
function generateNowBar() {
|
||||
ecNowBar = echarts.init(ec_now_bar.value)
|
||||
}
|
||||
function getNowInHosData(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "20"
|
||||
}
|
||||
getHosData(req).then(res=>{
|
||||
let tempArray = res.data
|
||||
var deptArray = []
|
||||
var inHosArray = []
|
||||
for (const key in tempArray) {
|
||||
deptArray.push(key)
|
||||
inHosArray.push(tempArray[key])
|
||||
}
|
||||
nowInHosOption.yAxis.data = deptArray
|
||||
nowInHosOption.series[0].data = inHosArray
|
||||
nowInHosOption && ecNowBar.setOption(nowInHosOption)
|
||||
})
|
||||
}
|
||||
var inAndOutHosMonthOption = {
|
||||
title: {
|
||||
show: true,
|
||||
text: '出入院人数变化情况(近12月)',
|
||||
left: 'center',
|
||||
top: "3%",
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
left: 'right',
|
||||
top: "12%"
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "入院",
|
||||
data: [],
|
||||
type: 'line',
|
||||
smooth: true
|
||||
},
|
||||
{
|
||||
name: "出院",
|
||||
data: [],
|
||||
type: 'line',
|
||||
smooth: true
|
||||
}
|
||||
]
|
||||
};
|
||||
const ec_month_line = ref(null)
|
||||
var ecMonthLine = {}
|
||||
function generateLine() {
|
||||
ecMonthLine = echarts.init(ec_month_line.value);
|
||||
}
|
||||
function changeHosBottomDate(){
|
||||
let startDate = moment(value2.value).subtract(11,'month').format("YYYYMMDD")+"00:00:00"
|
||||
let endDate = value2.value.toString()+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "23"
|
||||
}
|
||||
getHosData(req).then(res=>{
|
||||
let tempInHosMap = res.inPatients
|
||||
let tempOutHosMap = res.outPatients
|
||||
let dateArray = []
|
||||
let inHosArray = []
|
||||
let outHosArrray = []
|
||||
for (const key in tempInHosMap) {
|
||||
dateArray.push(key)
|
||||
inHosArray.push(tempInHosMap[key])
|
||||
}
|
||||
for (const key in tempOutHosMap) {
|
||||
outHosArrray.push(tempOutHosMap[key])
|
||||
}
|
||||
inAndOutHosMonthOption.xAxis.data = dateArray
|
||||
inAndOutHosMonthOption.series[0].data = inHosArray
|
||||
inAndOutHosMonthOption.series[1].data = outHosArrray
|
||||
inAndOutHosMonthOption && ecMonthLine.setOption(inAndOutHosMonthOption);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div class="app-container">
|
||||
<!--日期选择器-->
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value1"
|
||||
type="daterange"
|
||||
style="width: 50vw"
|
||||
value-format="YYYYMMDD00:00:00"
|
||||
range-separator="-"
|
||||
start-placeholder="起始日期"
|
||||
end-placeholder="结束日期"
|
||||
size="small"
|
||||
@change="changeHosHeaderDate"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder"></div>
|
||||
</div>
|
||||
|
||||
<!--数值-->
|
||||
<div class="number-group">
|
||||
<div>
|
||||
<div>出院人次</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.outpatients }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>平均住院日</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{showData.daysAvg}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>病床使用率</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{showData.cwsyl}}%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_today_bar"></div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<!--数值-->
|
||||
<div class="number-group">
|
||||
<div>
|
||||
<div>当前在院</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.inpatients }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>当前危重</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.badpatients }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_now_bar"></div>
|
||||
</div>
|
||||
<div class="dynamic">
|
||||
<div>住院动态</div>
|
||||
</div>
|
||||
<!--数值,人次-->
|
||||
<div class="person-times-group">
|
||||
<div class="person-times-item">
|
||||
<div class="person-times">
|
||||
<div>入院人次:</div>
|
||||
<div>{{ showData.inhospatients }}</div>
|
||||
</div>
|
||||
<div class="person-times-yes">
|
||||
<div>昨日:</div>
|
||||
<div>{{ showData.lastInhospatients }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="person-times-item">
|
||||
<div class="person-times">
|
||||
<div>出院人次:</div>
|
||||
<div>{{ showData.outhospatients }}</div>
|
||||
</div>
|
||||
<div class="person-times-yes">
|
||||
<div>昨日:</div>
|
||||
<div>{{ showData.lastOuthospatients }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
</div>
|
||||
<div class="dateChoose1">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
style="width: 35vw"
|
||||
value-format="YYYYMMDD"
|
||||
placeholder="时间节点"
|
||||
size="small"
|
||||
@change="changeHosBottomDate"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder2"></div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_month_line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.person-times-group {
|
||||
width: 98vw;
|
||||
height: 7vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 1.5vh;
|
||||
}
|
||||
|
||||
.person-times-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.person-times {
|
||||
width: 58vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.person-times-yes {
|
||||
width: 40vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.number-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 3vh;
|
||||
font-size: xx-small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.place-holder {
|
||||
height: 1vh;
|
||||
}
|
||||
|
||||
.dynamic {
|
||||
width: 92vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: small;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dateChoose {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
.dateChoose1 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
margin-top: 3vh;
|
||||
}
|
||||
.dateText{
|
||||
width: 15vw;
|
||||
}
|
||||
.dateWrap{
|
||||
width: 15vw;
|
||||
}
|
||||
.placeHolder{
|
||||
width: 42vw;
|
||||
}
|
||||
.placeHolder2{
|
||||
width:25vw ;
|
||||
}
|
||||
.ec-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.ec_class {
|
||||
width: 95vw;
|
||||
height: 40vh;
|
||||
}
|
||||
</style>
|
||||
1424
src/views/inhos/index.vue
Normal file
743
src/views/integrative/index.vue
Normal file
@@ -0,0 +1,743 @@
|
||||
<script setup>
|
||||
import moment from "moment/moment.js";
|
||||
import * as echarts from 'echarts';
|
||||
import {onMounted, ref} from "vue";
|
||||
import {getOutPatientData, getSpecialData} from "@/api/outpatient.js"
|
||||
|
||||
onMounted(() => {
|
||||
generateEachMonthLine()
|
||||
generateThreeYearLine()
|
||||
generateMTMonthLine()
|
||||
generateSPMTLineLine()
|
||||
|
||||
initData()
|
||||
|
||||
})
|
||||
|
||||
// 设置初始时间
|
||||
let today = new Date();
|
||||
today = moment(today).format("YYYYMMDD");
|
||||
const value2 = ref(today);
|
||||
|
||||
const showData = ref({
|
||||
completenessData: [],
|
||||
integrativeData: [],
|
||||
threeYearsData: [],
|
||||
threeYearsTableHeader: [],
|
||||
|
||||
MTNumHeader: [],
|
||||
MTNumData: [],
|
||||
MTWorkHeader: [],
|
||||
MTWorkData: [],
|
||||
MTWorkTableData: [],
|
||||
})
|
||||
|
||||
function getMTWorkCount() {
|
||||
let startDate = moment(value2.value).subtract(11, 'month').format("YYYYMMDD") + "00:00:00"
|
||||
let endDate = value2.value.toString() + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "7"
|
||||
}
|
||||
ecMTMonthLine.showLoading()
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.MTWorkHeader = res.data.tableHeader
|
||||
showData.value.MTWorkData = res.data.tableData
|
||||
MTMonthOption.legend.data = res.data.legendList
|
||||
MTMonthOption.xAxis.data = res.data.lineX
|
||||
let tempObject = res.data.lineData
|
||||
for (let key in tempObject) {
|
||||
var tempSeries = {
|
||||
name: key,
|
||||
// stack: 'Total',
|
||||
type: 'line',
|
||||
data: tempObject[key]
|
||||
}
|
||||
MTMonthOption.series.push(tempSeries)
|
||||
}
|
||||
MTMonthOption && ecMTMonthLine.setOption(MTMonthOption)
|
||||
ecMTMonthLine.hideLoading()
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function getCompletenessData() {
|
||||
let startDate = value2.value.toString() + "00:00:00"
|
||||
let endDate = startDate.substring(0, 8) + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "1"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.completenessData = res.completeness;
|
||||
})
|
||||
}
|
||||
|
||||
function getIntegrativeData() {
|
||||
let startDate = moment(value2.value).subtract(11, 'month').format("YYYYMMDD") + "00:00:00"
|
||||
let endDate = value2.value.toString() + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "2"
|
||||
}
|
||||
ecMonthLine.showLoading()
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.integrativeData = res.data.integrative;
|
||||
eachMonthOption.xAxis.data = res.data.dates
|
||||
eachMonthOption.series[0].data = res.data.mzwces
|
||||
eachMonthOption.series[1].data = res.data.zywce
|
||||
eachMonthOption.series[2].data = res.data.zwces
|
||||
ecMonthLine.hideLoading()
|
||||
eachMonthOption && ecMonthLine.setOption(eachMonthOption);
|
||||
})
|
||||
}
|
||||
|
||||
function getThreeYearsData() {
|
||||
let startDate = moment(value2.value).subtract(2, 'year').format("YYYYMMDD") + "00:00:00"
|
||||
let endDate = value2.value.toString() + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "3"
|
||||
}
|
||||
ecYearLine.showLoading()
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.threeYearsData = res.data.tableData
|
||||
showData.value.threeYearsTableHeader = res.data.tableHeader
|
||||
threeYearOption.legend.data = res.data.legend
|
||||
threeYearOption.xAxis.data = res.data.xAxis
|
||||
let tempObject = res.data.seriesData
|
||||
for (let key in tempObject) {
|
||||
var tempSeries = {
|
||||
name: key,
|
||||
type: 'line',
|
||||
data: tempObject[key]
|
||||
}
|
||||
threeYearOption.series.push(tempSeries)
|
||||
}
|
||||
ecYearLine.hideLoading()
|
||||
threeYearOption && ecYearLine.setOption(threeYearOption);
|
||||
})
|
||||
}
|
||||
|
||||
var ec_month_line = ref(null);
|
||||
var ec_year_line = ref(null);
|
||||
const ec_MTMonth_line = ref(null);
|
||||
const ec_spmt_line = ref(null);
|
||||
var ecSPMTLine = {};
|
||||
var ecMonthLine = {};
|
||||
var ecYearLine = {};
|
||||
var ecMTMonthLine = {};
|
||||
|
||||
var MTMonthOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: function (point, params, dom, rect, size) {
|
||||
// 鼠标坐标和提示框位置的参考坐标系是:以外层div的左上角那一点为原点,x轴向右,y轴向下
|
||||
// 提示框位置
|
||||
var x = 0; // x坐标位置
|
||||
var y = 0; // y坐标位置
|
||||
|
||||
// 当前鼠标位置
|
||||
var pointX = point[0];
|
||||
var pointY = point[1];
|
||||
|
||||
// 外层div大小
|
||||
// var viewWidth = size.viewSize[0];
|
||||
// var viewHeight = size.viewSize[1];
|
||||
|
||||
// 提示框大小
|
||||
var boxWidth = size.contentSize[0];
|
||||
var boxHeight = size.contentSize[1];
|
||||
|
||||
// boxWidth > pointX 说明鼠标左边放不下提示框
|
||||
if (boxWidth > pointX) {
|
||||
x = 5;
|
||||
} else { // 左边放的下
|
||||
x = pointX - boxWidth;
|
||||
}
|
||||
|
||||
// boxHeight > pointY 说明鼠标上边放不下提示框
|
||||
if (boxHeight > pointY) {
|
||||
y = 5;
|
||||
} else { // 上边放得下
|
||||
y = pointY - boxHeight;
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 20,
|
||||
data: []
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
y: 80,
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: [],
|
||||
axisLabel: {
|
||||
//x轴文字的配置
|
||||
show: true,
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: []
|
||||
}
|
||||
|
||||
|
||||
var eachMonthOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: function (point, params, dom, rect, size) {
|
||||
// 鼠标坐标和提示框位置的参考坐标系是:以外层div的左上角那一点为原点,x轴向右,y轴向下
|
||||
// 提示框位置
|
||||
var x = 0; // x坐标位置
|
||||
var y = 0; // y坐标位置
|
||||
|
||||
// 当前鼠标位置
|
||||
var pointX = point[0];
|
||||
var pointY = point[1];
|
||||
|
||||
// 外层div大小
|
||||
// var viewWidth = size.viewSize[0];
|
||||
// var viewHeight = size.viewSize[1];
|
||||
|
||||
// 提示框大小
|
||||
var boxWidth = size.contentSize[0];
|
||||
var boxHeight = size.contentSize[1];
|
||||
|
||||
// boxWidth > pointX 说明鼠标左边放不下提示框
|
||||
if (boxWidth > pointX) {
|
||||
x = 5;
|
||||
} else { // 左边放的下
|
||||
x = pointX - boxWidth;
|
||||
}
|
||||
|
||||
// boxHeight > pointY 说明鼠标上边放不下提示框
|
||||
if (boxHeight > pointY) {
|
||||
y = 5;
|
||||
} else { // 上边放得下
|
||||
y = pointY - boxHeight;
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 20,
|
||||
data: ['门诊', '住院', '合计',]
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: [],
|
||||
axisLabel: {
|
||||
//x轴文字的配置
|
||||
show: true,
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '门诊',
|
||||
type: 'line',
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: '住院',
|
||||
type: 'line',
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: '合计',
|
||||
type: 'line',
|
||||
data: []
|
||||
},
|
||||
]
|
||||
}
|
||||
var threeYearOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: function (point, params, dom, rect, size) {
|
||||
// 鼠标坐标和提示框位置的参考坐标系是:以外层div的左上角那一点为原点,x轴向右,y轴向下
|
||||
// 提示框位置
|
||||
var x = 0; // x坐标位置
|
||||
var y = 0; // y坐标位置
|
||||
|
||||
// 当前鼠标位置
|
||||
var pointX = point[0];
|
||||
var pointY = point[1];
|
||||
|
||||
// 外层div大小
|
||||
// var viewWidth = size.viewSize[0];
|
||||
// var viewHeight = size.viewSize[1];
|
||||
|
||||
// 提示框大小
|
||||
var boxWidth = size.contentSize[0];
|
||||
var boxHeight = size.contentSize[1];
|
||||
|
||||
// boxWidth > pointX 说明鼠标左边放不下提示框
|
||||
if (boxWidth > pointX) {
|
||||
x = 5;
|
||||
} else { // 左边放的下
|
||||
x = pointX - boxWidth;
|
||||
}
|
||||
|
||||
// boxHeight > pointY 说明鼠标上边放不下提示框
|
||||
if (boxHeight > pointY) {
|
||||
y = 5;
|
||||
} else { // 上边放得下
|
||||
y = pointY - boxHeight;
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 20,
|
||||
data: []
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: [],
|
||||
axisLabel: {
|
||||
//x轴文字的配置
|
||||
show: true,
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: []
|
||||
}
|
||||
var SPMTOption = {
|
||||
title: {
|
||||
show: true,
|
||||
text: '',
|
||||
left: 'center',
|
||||
top: "3%",
|
||||
textStyle: {
|
||||
fontSize: 15,
|
||||
opacity: 0.7
|
||||
},
|
||||
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: function (point, params, dom, rect, size) {
|
||||
// 鼠标坐标和提示框位置的参考坐标系是:以外层div的左上角那一点为原点,x轴向右,y轴向下
|
||||
// 提示框位置
|
||||
var x = 0; // x坐标位置
|
||||
var y = 0; // y坐标位置
|
||||
|
||||
// 当前鼠标位置
|
||||
var pointX = point[0];
|
||||
var pointY = point[1];
|
||||
|
||||
// 外层div大小
|
||||
// var viewWidth = size.viewSize[0];
|
||||
// var viewHeight = size.viewSize[1];
|
||||
|
||||
// 提示框大小
|
||||
var boxWidth = size.contentSize[0];
|
||||
var boxHeight = size.contentSize[1];
|
||||
|
||||
// boxWidth > pointX 说明鼠标左边放不下提示框
|
||||
if (boxWidth > pointX) {
|
||||
x = 5;
|
||||
} else { // 左边放的下
|
||||
x = pointX - boxWidth;
|
||||
}
|
||||
|
||||
// boxHeight > pointY 说明鼠标上边放不下提示框
|
||||
if (boxHeight > pointY) {
|
||||
y = 5;
|
||||
} else { // 上边放得下
|
||||
y = pointY - boxHeight;
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 40,
|
||||
data: []
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
y: 80,
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
axisLabel: {
|
||||
//x轴文字的配置
|
||||
show: true,
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: []
|
||||
}
|
||||
|
||||
const objectSpanMethod = ({
|
||||
row,
|
||||
column,
|
||||
rowIndex,
|
||||
columnIndex,
|
||||
}) => {
|
||||
if (columnIndex === 0) {
|
||||
|
||||
if (rowIndex % 3 === 0) {
|
||||
return {
|
||||
rowspan: 3,
|
||||
colspan: 1,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
rowspan: 0,
|
||||
colspan: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMTWorkTableData() {
|
||||
let startDate = moment(value2.value).subtract(2, 'year').format("YYYYMMDD") + "00:00:00"
|
||||
let endDate = value2.value.toString() + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "9"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.MTWorkTableData = res.data
|
||||
})
|
||||
}
|
||||
|
||||
function clickMTCell(e) {
|
||||
let startDate = moment(value2.value).subtract(2, 'year').format("YYYYMMDD") + "00:00:00"
|
||||
let endDate = value2.value.toString() + "23:59:59"
|
||||
var req = {}
|
||||
if (e) {
|
||||
SPMTOption.title.text = e.ks
|
||||
req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "9",
|
||||
Dept: e.ks
|
||||
}
|
||||
} else {
|
||||
SPMTOption.title.text = '医学影像科'
|
||||
req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "9",
|
||||
Dept: '医学影像科'
|
||||
}
|
||||
}
|
||||
ecSPMTLine.showLoading()
|
||||
getSpecialData(req).then(res => {
|
||||
SPMTOption.legend.data = res.data.legend
|
||||
let tempObj = res.data.seriesDatas
|
||||
SPMTOption.series = []
|
||||
for (let key in tempObj) {
|
||||
var tempSeries = {
|
||||
name: key,
|
||||
// stack: 'Total',
|
||||
type: 'line',
|
||||
data: tempObj[key]
|
||||
}
|
||||
SPMTOption.series.push(tempSeries)
|
||||
}
|
||||
ecSPMTLine.hideLoading()
|
||||
SPMTOption && ecSPMTLine.setOption(SPMTOption)
|
||||
})
|
||||
}
|
||||
|
||||
function getMTNums() {
|
||||
// let startDate = moment().startOf('month').format('YYYYMMDD') + "00:00:00"
|
||||
let startDate = value2.value.toString() + "00:00:00"
|
||||
let endDate = startDate.substring(0, 8) + "23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "5"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.MTNumHeader = res.data.tableHeader
|
||||
showData.value.MTNumData = res.data.tableData
|
||||
})
|
||||
}
|
||||
|
||||
function generateEachMonthLine() {
|
||||
ecMonthLine = echarts.init(ec_month_line.value);
|
||||
}
|
||||
|
||||
function generateThreeYearLine() {
|
||||
ecYearLine = echarts.init(ec_year_line.value);
|
||||
}
|
||||
|
||||
function generateMTMonthLine() {
|
||||
ecMTMonthLine = echarts.init(ec_MTMonth_line.value)
|
||||
}
|
||||
|
||||
function generateSPMTLineLine() {
|
||||
ecSPMTLine = echarts.init(ec_spmt_line.value)
|
||||
}
|
||||
|
||||
function initData() {
|
||||
getIntegrativeData()
|
||||
getThreeYearsData()
|
||||
getCompletenessData()
|
||||
|
||||
|
||||
clickMTCell()
|
||||
|
||||
getMTNums()
|
||||
getMTNums()
|
||||
getMTWorkTableData()
|
||||
getMTWorkCount()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 日期选择框-->
|
||||
<div class="app-container">
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">今日日期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
style="width: 35vw"
|
||||
value-format="YYYYMMDD"
|
||||
placeholder="时间节点"
|
||||
size="small"
|
||||
@change="initData"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder2"></div>
|
||||
</div>
|
||||
<!-- 表格1-->
|
||||
<div v-hasPermi="['inte:completeness']">
|
||||
<el-table :data="showData.completenessData" size="small" style="width: 100%; margin-top: 20px;font-size: 10px"
|
||||
border stripe>
|
||||
<el-table-column align="center" prop="lb" fixed/>
|
||||
<el-table-column align="center" prop="mzwcd" label="门诊"/>
|
||||
<el-table-column align="center" prop="zywcd" label="住院"/>
|
||||
<el-table-column align="center" prop="zwcd" label="合计"/>
|
||||
</el-table>
|
||||
<el-divider/>
|
||||
</div>
|
||||
<!-- 表格二-->
|
||||
<div v-hasPermi="['inte:integrative']">
|
||||
<span class="table-title">近12个月每月预算完成额对比</span>
|
||||
<el-table :data="showData.integrativeData" size="small" style="width: 100%; margin-top: 20px;font-size: 10px"
|
||||
border height="230">
|
||||
<el-table-column align="center" prop="ny"/>
|
||||
<el-table-column align="center" prop="mzwce" label="门诊"/>
|
||||
<el-table-column align="center" prop="zywce" label="住院"/>
|
||||
<el-table-column align="center" prop="zwce" label="合计"/>
|
||||
</el-table>
|
||||
<!-- 折线图-->
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_month_line"></div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
</div>
|
||||
|
||||
<!-- 表格三-->
|
||||
<div v-hasPermi="['inte:threeYears']">
|
||||
<span class="table-title">近三年每月总预算完成额对比</span>
|
||||
<el-table :data="showData.threeYearsData" border size="small"
|
||||
style="width: 100%; margin-top: 20px;font-size: 10px" height="250" stripe>
|
||||
<el-table-column fixed="left" label="年" show-overflow-tooltip width="40" align="right">
|
||||
<el-table-column fixed="left" prop="月" label="月" show-overflow-tooltip width="40"
|
||||
align="center">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column :label="item" :prop="item"
|
||||
v-for="item in showData.threeYearsTableHeader" align="center"></el-table-column>
|
||||
</el-table>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_year_line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-hasPermi="['opd:MTNum']">
|
||||
<span class="table-title">医技科室工作量</span>
|
||||
<!-- <el-table :data="showData.MTNumData" size="small" height="200"-->
|
||||
<!-- style="width: 100%; margin-top: 20px;font-size: 10px" stripe border>-->
|
||||
<!-- <el-table-column label="分类" prop="分类" fixed align="center"></el-table-column>-->
|
||||
<!-- <el-table-column :label="item" :prop="item"-->
|
||||
<!-- v-for="item in showData.MTNumHeader" align="center"></el-table-column>-->
|
||||
<!-- </el-table> -->
|
||||
|
||||
<el-table :data="showData.MTNumData" size="small" height="200"
|
||||
style="width: 100%; margin-top: 20px;font-size: 10px" stripe border>
|
||||
<el-table-column prop="lb" fixed align="center"></el-table-column>
|
||||
<el-table-column prop="yxyxk" label="医学影像科" align="center"></el-table-column>
|
||||
<el-table-column prop="yxjyk" label="医学检验科" align="center"></el-table-column>
|
||||
<el-table-column prop="kfyxk" label="康复医学科" align="center"></el-table-column>
|
||||
<el-table-column prop="hj" label="合计" align="center"></el-table-column>
|
||||
|
||||
|
||||
<!-- <el-table-column :label="item" :prop="item"-->
|
||||
<!-- v-for="item in showData.MTNumHeader" align="center"></el-table-column>-->
|
||||
</el-table>
|
||||
<el-divider/>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-hasPermi="['opd:MTWork']">
|
||||
<span class="table-title">近12个月医技科室每月工作量</span>
|
||||
<el-table :data="showData.MTWorkData" size="small" height="275"
|
||||
style="width: 100%; margin-top: 20px;font-size: 10px" stripe border>
|
||||
<el-table-column fixed label="科室" align="right">
|
||||
<el-table-column fixed prop="日期" label="日期" show-overflow-tooltip
|
||||
align="center">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column :label="item" :prop="item"
|
||||
v-for="item in showData.MTWorkHeader" align="center"></el-table-column>
|
||||
</el-table>
|
||||
<div>
|
||||
<div class="ec-group">
|
||||
<div class="ec-mt-class" ref="ec_MTMonth_line"></div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
</div>
|
||||
|
||||
<div v-hasPermi="['opd:MTWorkTable']">
|
||||
<span class="table-title">近三年医技科室每月总工作量</span>
|
||||
<el-table
|
||||
:data="showData.MTWorkTableData"
|
||||
:span-method="objectSpanMethod"
|
||||
@cell-click="clickMTCell"
|
||||
border
|
||||
size="small"
|
||||
style="width: 100%; margin-top: 20px;font-size: 10px"
|
||||
height="220"
|
||||
>
|
||||
<el-table-column prop="ks" align="center" label="科室" width="70" fixed>
|
||||
</el-table-column>
|
||||
<el-table-column prop="nf" fixed align="center" label="年" width="50"/>
|
||||
<el-table-column prop="one" align="center" label="1月" width="50"/>
|
||||
<el-table-column prop="two" align="center" label="2月" width="50"/>
|
||||
<el-table-column prop="three" align="center" label="3月" width="50"/>
|
||||
<el-table-column prop="four" align="center" label="4月" width="50"/>
|
||||
<el-table-column prop="five" align="center" label="5月" width="50"/>
|
||||
<el-table-column prop="six" align="center" label="6月" width="50"/>
|
||||
<el-table-column prop="seven" align="center" label="7月" width="50"/>
|
||||
<el-table-column prop="eight" align="center" label="8月" width="50"/>
|
||||
<el-table-column prop="nine" align="center" label="9月" width="50"/>
|
||||
<el-table-column prop="ten" align="center" label="10月" width="50"/>
|
||||
<el-table-column prop="eleven" align="center" label="11月" width="50"/>
|
||||
<el-table-column prop="twelve" align="center" label="12月" width="50"/>
|
||||
</el-table>
|
||||
<div class="ec-group">
|
||||
<div class="ec-special-mt" ref="ec_spmt_line"></div>
|
||||
</div>
|
||||
<!-- <el-divider/>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.table-title {
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin-top: 1vh;
|
||||
margin-bottom: 1vh;
|
||||
opacity: 0.7 !important;
|
||||
}
|
||||
|
||||
.dateChoose {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
margin-bottom: 1vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dateText {
|
||||
width: 30vw;
|
||||
}
|
||||
|
||||
.dateWrap {
|
||||
width: 30vw;
|
||||
}
|
||||
|
||||
.placeHolder2 {
|
||||
width: 5vw;
|
||||
}
|
||||
|
||||
.ec-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ec_class {
|
||||
width: 90vw;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.ec-special-mt {
|
||||
width: 90vw;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.ec-mt-class {
|
||||
width: 90vw;
|
||||
height: 50vh;
|
||||
}
|
||||
</style>
|
||||
2001
src/views/opd/index.vue
Normal file
540
src/views/outpatient/index.vue
Normal file
@@ -0,0 +1,540 @@
|
||||
<script setup>
|
||||
import * as echarts from 'echarts';
|
||||
import {onMounted, ref} from "vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {AES_DE} from "@/utils/vertify.js";
|
||||
import {getOutPatientData} from "@/api/outpatient.js"
|
||||
import moment from "moment/moment.js";
|
||||
import {ElLoading} from "element-plus";
|
||||
|
||||
onMounted(() => {
|
||||
generateMonthLine();
|
||||
generateDayLine();
|
||||
generateDayBar();
|
||||
outPatientDateChange();
|
||||
getVisitsNumber();
|
||||
getEmergencyVisitsNumber();
|
||||
changeDate2();
|
||||
verifyOpenid();
|
||||
})
|
||||
|
||||
//设置可以访问的人员
|
||||
const releaseUser = ref(['o-ZxO47Otvo5Rsq7kN-4PHvZIOt8', 'o-ZxO4-oIddDT0ecgxNEkvApJ-N0','o-ZxO4xd9dV7Dd6OOMKD6ukomD8c','o-ZxO47fz4FjMvL5ESLKcl0YqVJ8','o-ZxO49keb-3wV3CLAuFDpvrx-LQ',
|
||||
'o-ZxO47o9FYvO-Eor_JPCwzXS3ig','o-ZxO49XU81BKOSnDzKVGWrAZXGg']);
|
||||
|
||||
// 设置初始时间
|
||||
let today = new Date();
|
||||
// let yesterday = new Date(today.getTime()-24*60*60*1000);
|
||||
today= moment(today).format("YYYYMMDD");
|
||||
// yesterday=moment(yesterday).format("YYYYMMDD");
|
||||
const value1 = ref([today+"00:00:00",today+"23:59:59"]);
|
||||
const value2 = ref(today);
|
||||
// const value1 = ref([yesterday+"00:00:00",today+"00:00:00"]);
|
||||
|
||||
//设置展示的数据
|
||||
const showData = ref({
|
||||
numberPeopleOutp:'',
|
||||
medfeeAvg: '',
|
||||
outMedfeeAvg: '',
|
||||
visitsNumber: '',
|
||||
lastVisitsNumber: '',
|
||||
emergencyVisitsNumber: '',
|
||||
lastEmergencyVisitsNumber: '',
|
||||
monthOptions:[],
|
||||
monthDataOptions:[],
|
||||
weekOptions:[],
|
||||
weekDataOptions:[],
|
||||
eachDeptOptions:[],
|
||||
eachDeptDataOptions:[],
|
||||
});
|
||||
//定义获取dom,准备dom初始化容器
|
||||
const ec_month_line= ref(null) //ref标签获取dom
|
||||
const ec_day_bar = ref(null)
|
||||
const ec_day_line = ref(null)
|
||||
var ecDayLine = {}
|
||||
var ecMonthLine = {}
|
||||
var ecDayBar = {}
|
||||
// 图形的options
|
||||
var eachDeptOption = {
|
||||
title: {
|
||||
text: '各科门诊人次',
|
||||
top: '10%',
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01],
|
||||
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 40, // 标题倾斜
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '人次',
|
||||
type: 'bar',
|
||||
data: []
|
||||
},
|
||||
]
|
||||
};
|
||||
var weekOption = {
|
||||
title: {
|
||||
show: true,
|
||||
text: '七日门诊变化情况',
|
||||
left: 'center',
|
||||
top: "10%",
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [],
|
||||
type: 'line',
|
||||
smooth: true
|
||||
}
|
||||
]
|
||||
};
|
||||
var twelveMonthOption = {
|
||||
title: {
|
||||
show: true,
|
||||
text: '门诊人次变化情况(近12月)',
|
||||
left: 'center',
|
||||
top: "10%",
|
||||
textStyle: {
|
||||
fontSize: 13,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 38, // 标题倾斜
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
interval: 0, // 设置数据间隔
|
||||
rotate: 48, // 标题倾斜
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [],
|
||||
type: 'line',
|
||||
smooth: true
|
||||
}
|
||||
]
|
||||
}
|
||||
// 临时展示测试数据
|
||||
const workloadData = ref([])
|
||||
function verifyOpenid() {
|
||||
var route = useRoute();
|
||||
var openid = route.query.openid;//从链接中获取openid
|
||||
if (typeof (openid) != "undefined" && openid != null && openid != '') {
|
||||
var de = AES_DE(openid);//解密
|
||||
if (!releaseUser.value.includes(de)) {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
} else {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
}
|
||||
// 初始化echarts
|
||||
function generateDayBar() {
|
||||
ecDayBar = echarts.init(ec_day_bar.value);
|
||||
}
|
||||
function generateDayLine() {
|
||||
ecDayLine = echarts.init(ec_day_line.value);
|
||||
}
|
||||
function generateMonthLine() {
|
||||
ecMonthLine = echarts.init(ec_month_line.value);
|
||||
}
|
||||
function outPatientDateChange() {
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "7"
|
||||
}
|
||||
for (var i = 7; i <= 14; i++) {
|
||||
if (i === 7) {
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.numberPeopleOutp = res.data.numberPeopleOutp
|
||||
})
|
||||
}
|
||||
if (i === 12) {
|
||||
req.lb = "12"
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.medfeeAvg = res.data.medfeeAvg
|
||||
})
|
||||
}
|
||||
if (i === 13) {
|
||||
req.lb="13"
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.outMedfeeAvg=res.data.outMedfeeAvg
|
||||
})
|
||||
}
|
||||
}
|
||||
changeMonthLine()
|
||||
changeWeekLine()
|
||||
changeEachDeptBar()
|
||||
}
|
||||
function changeMonthLine(){
|
||||
let startDate = moment(value2.value).subtract(11,'month').format("YYYYMMDD")+"00:00:00"
|
||||
let endDate = value2.value.toString()+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "14"
|
||||
}
|
||||
var loadIngOptions={lock: true,
|
||||
text: '数据加载中',
|
||||
background: 'rgba(0, 0, 0, 0.1)'}
|
||||
const loadingInstance=ElLoading.service(loadIngOptions)
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.monthOptions = []
|
||||
showData.value.monthDataOptions = []
|
||||
var map = res.data
|
||||
for (let key in map) {
|
||||
showData.value.monthOptions.push(key)
|
||||
showData.value.monthDataOptions.push(map[key])
|
||||
}
|
||||
twelveMonthOption.xAxis.data = showData.value.monthOptions
|
||||
twelveMonthOption.series[0].data = showData.value.monthDataOptions
|
||||
twelveMonthOption && ecMonthLine.setOption(twelveMonthOption);
|
||||
loadingInstance.close()
|
||||
})
|
||||
}
|
||||
function changeWeekLine(){
|
||||
let startDate = moment(value2.value).subtract(6,"days").format("YYYYMMDD")+"00:00:00"
|
||||
let endDate = value2.value.toString()+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "10"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.weekOptions = []
|
||||
showData.value.weekDataOptions = []
|
||||
var map = res.data
|
||||
for (let key in map) {
|
||||
showData.value.weekOptions.push(key)
|
||||
showData.value.weekDataOptions.push(map[key])
|
||||
}
|
||||
weekOption.xAxis.data = showData.value.weekOptions
|
||||
weekOption.series[0].data = showData.value.weekDataOptions
|
||||
weekOption && ecDayLine.setOption(weekOption);
|
||||
})
|
||||
}
|
||||
function changeEachDeptBar(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "11"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.eachDeptOptions = []
|
||||
showData.value.eachDeptDataOptions = []
|
||||
var map = res.data
|
||||
for (let key in map) {
|
||||
showData.value.eachDeptOptions.push(key)
|
||||
showData.value.eachDeptDataOptions.push(map[key])
|
||||
}
|
||||
eachDeptOption.yAxis.data = showData.value.eachDeptOptions
|
||||
eachDeptOption.series[0].data = showData.value.eachDeptDataOptions
|
||||
eachDeptOption && ecDayBar.setOption(eachDeptOption)
|
||||
})
|
||||
}
|
||||
function getVisitsNumber(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = startDate.substring(0,8)+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "7"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.visitsNumber = res.data.numberPeopleOutp
|
||||
})
|
||||
|
||||
let lastStartDate = moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"00:00:00"
|
||||
let lastEndDate = moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"23:59:59"
|
||||
let lastReq = {
|
||||
startTime: lastStartDate,
|
||||
endTime: lastEndDate,
|
||||
lb: "7"
|
||||
}
|
||||
getOutPatientData(lastReq).then(res => {
|
||||
showData.value.lastVisitsNumber = res.data.numberPeopleOutp
|
||||
})
|
||||
}
|
||||
function getEmergencyVisitsNumber(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = startDate.substring(0,8)+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "8"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
showData.value.emergencyVisitsNumber = res.data.numberPeopleOutp
|
||||
})
|
||||
let lastStartDate = moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"00:00:00"
|
||||
let lastEndDate = moment(value1.value[0].toString().substring(0,8)).subtract(1,'days').format('YYYYMMDD')+"23:59:59"
|
||||
let lastReq = {
|
||||
startTime: lastStartDate,
|
||||
endTime: lastEndDate,
|
||||
lb: "8"
|
||||
}
|
||||
getOutPatientData(lastReq).then(res => {
|
||||
showData.value.lastEmergencyVisitsNumber = res.data.numberPeopleOutp
|
||||
})
|
||||
}
|
||||
function changeDate2(){
|
||||
changeWeekLine()
|
||||
changeMonthLine()
|
||||
getTableData()
|
||||
}
|
||||
function getTableData(){
|
||||
let startDate = value2.value.toString()+"00:00:00"
|
||||
let endDate = startDate.substring(0,8)+"23:59:59"
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "24"
|
||||
}
|
||||
getOutPatientData(req).then(res => {
|
||||
workloadData.value=res.workDetails
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--日期选择器-->
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value1"
|
||||
type="daterange"
|
||||
style="width: 50vw"
|
||||
value-format="YYYYMMDD00:00:00"
|
||||
range-separator="-"
|
||||
start-placeholder="起始日期"
|
||||
end-placeholder="结束日期"
|
||||
size="small"
|
||||
@change="outPatientDateChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder"></div>
|
||||
</div>
|
||||
|
||||
<!--数值-->
|
||||
<div class="number-group">
|
||||
<div>
|
||||
<div>门诊人次</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{showData.numberPeopleOutp}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>门诊次均费用</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{showData.medfeeAvg}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>门诊次均药费</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{showData.outMedfeeAvg}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_day_bar"></div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<!--数值,人次-->
|
||||
<div class="person-times-group">
|
||||
<div class="person-times-item">
|
||||
<div class="person-times">
|
||||
<div>门诊人次:</div>
|
||||
<div>{{showData.visitsNumber}}</div>
|
||||
</div>
|
||||
<div class="person-times-yes">
|
||||
<div>昨日:</div>
|
||||
<div>{{ showData.lastVisitsNumber }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="person-times-item">
|
||||
<div class="person-times">
|
||||
<div>急诊人次:</div>
|
||||
<div>{{showData.emergencyVisitsNumber}}</div>
|
||||
</div>
|
||||
<div class="person-times-yes">
|
||||
<div>昨日:</div>
|
||||
<div>{{showData.lastEmergencyVisitsNumber}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider />
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
style="width: 35vw"
|
||||
value-format="YYYYMMDD"
|
||||
placeholder="时间节点"
|
||||
size="small"
|
||||
@change="changeDate2"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder2"></div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_day_line"></div>
|
||||
</div>
|
||||
<div class="ec-group">
|
||||
<div class="ec_class" ref="ec_month_line"></div>
|
||||
</div>
|
||||
|
||||
<el-table :data="workloadData" style="width: 100%">
|
||||
<el-table-column align="center" label="门诊工作量明细统计(儿童保健部)">
|
||||
<el-table-column fixed prop="tjlb" label="分类"/>
|
||||
<el-table-column fixed prop="ettjxyss" label="儿童体检(≤3岁)"/>
|
||||
<el-table-column prop="ettjdyss" label="儿童体检(>3岁)"/>
|
||||
<el-table-column prop="etrttj" label="儿童入托体检"/>
|
||||
<el-table-column fixed="right" prop="hj" label="合计"/>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.person-times-group {
|
||||
width: 98vw;
|
||||
height: 6vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 3vh;
|
||||
}
|
||||
|
||||
.person-times-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.person-times {
|
||||
width: 58vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.person-times-yes {
|
||||
width: 40vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.dateChoose {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
.dateText{
|
||||
width: 15vw;
|
||||
}
|
||||
.dateWrap{
|
||||
width: 15vw;
|
||||
}
|
||||
.placeHolder{
|
||||
width: 42vw;
|
||||
}
|
||||
.placeHolder2{
|
||||
width:25vw ;
|
||||
}
|
||||
.place-holder {
|
||||
height: 1vh;
|
||||
}
|
||||
|
||||
.number-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 3vh;
|
||||
font-size: xx-small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ec-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ec_class {
|
||||
width: 89vw;
|
||||
height: 48vh;
|
||||
}
|
||||
</style>
|
||||
241
src/views/synthesis/index.vue
Normal file
@@ -0,0 +1,241 @@
|
||||
<script setup>
|
||||
import * as echarts from 'echarts';
|
||||
import {ref, onMounted} from "vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {AES_DE} from "../../utils/vertify.js";
|
||||
import {toRaw} from "vue";
|
||||
import {getCountData, getSynPieCountData} from "@/api/synthesis.js"
|
||||
import moment from 'moment';
|
||||
|
||||
onMounted(() => {
|
||||
generateMediclPie();
|
||||
synthesisDateChange();
|
||||
verifyOpenid();
|
||||
})
|
||||
|
||||
let today = new Date();
|
||||
today= moment(today).format("YYYYMMDD");
|
||||
const value1 = ref([today+"00:00:00",today+"23:59:59"]);
|
||||
//设置可以访问的人员
|
||||
const releaseUser = ref(['o-ZxO47Otvo5Rsq7kN-4PHvZIOt8', 'o-ZxO4-oIddDT0ecgxNEkvApJ-N0','o-ZxO4xd9dV7Dd6OOMKD6ukomD8c','o-ZxO47fz4FjMvL5ESLKcl0YqVJ8','o-ZxO49keb-3wV3CLAuFDpvrx-LQ',
|
||||
'o-ZxO47o9FYvO-Eor_JPCwzXS3ig','o-ZxO49XU81BKOSnDzKVGWrAZXGg']);
|
||||
const showData = ref({
|
||||
totalIncome: '',
|
||||
outpatientBudget: '',
|
||||
inpMedfee: '',
|
||||
pieData: [],
|
||||
});
|
||||
const medical_pie= ref(null) //ref标签获取dom
|
||||
var option = {
|
||||
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
bottom: '0.01',
|
||||
textStyle: {
|
||||
fontSize: 10,
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
center: ['50%', '40%'],
|
||||
radius: '35%',
|
||||
data:[],
|
||||
label: {
|
||||
formatter: function (data) {
|
||||
return `${data.name}:${data.value}%`
|
||||
},
|
||||
overflow: "break"
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
var medicalPie={}
|
||||
|
||||
function verifyOpenid() {
|
||||
var route = useRoute();
|
||||
var openid = route.query.openid;//从链接中获取openid
|
||||
if (typeof (openid) != "undefined" && openid != null && openid != '') {
|
||||
var de = AES_DE(openid);//解密
|
||||
if (!releaseUser.value.includes(de)) {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
} else {
|
||||
//跳转到错误页面
|
||||
var router = useRouter();
|
||||
router.replace({path: "/401"})
|
||||
}
|
||||
}
|
||||
function generateMediclPie() {
|
||||
medicalPie = echarts.init(medical_pie.value);
|
||||
}
|
||||
function synthesisDateChange() {
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
lb: "1"
|
||||
}
|
||||
for (var i = 1; i <= 6; i++) {
|
||||
if (i === 1) {
|
||||
getCountData(req).then(res => {
|
||||
showData.value.totalIncome = res.data.totalIncome;
|
||||
})
|
||||
}
|
||||
if (i === 2) {
|
||||
req.lb = "2"
|
||||
getCountData(req).then(res => {
|
||||
showData.value.outpatientBudget = res.data.outpatientBudget;
|
||||
})
|
||||
}
|
||||
if (i === 3) {
|
||||
req.lb = "3"
|
||||
getCountData(req).then(res => {
|
||||
showData.value.inpMedfee = res.data.inpMedfee;
|
||||
})
|
||||
}
|
||||
}
|
||||
changePie()
|
||||
|
||||
}
|
||||
function changePie(){
|
||||
let startDate = value1.value[0].toString()
|
||||
let endDate = value1.value[1].toString()
|
||||
let req = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
}
|
||||
getSynPieCountData(req).then(res=>{
|
||||
showData.value.pieData=[]
|
||||
showData.value.pieData.push({
|
||||
name:'药类占比',
|
||||
value:res.data.yzb
|
||||
})
|
||||
showData.value.pieData.push({
|
||||
name:'百元耗占比',
|
||||
value:res.data.byhczb
|
||||
})
|
||||
showData.value.pieData.push({
|
||||
name:'医务预算完成度占比',
|
||||
value:res.data.ywsrzb
|
||||
})
|
||||
option.series[0].data=toRaw(showData.value.pieData)
|
||||
option && medicalPie.setOption(option,true);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--日期选择器-->
|
||||
<div class="dateChoose">
|
||||
<div class="dateText">周期:</div>
|
||||
<div class="dateWrap">
|
||||
<el-date-picker
|
||||
v-model="value1"
|
||||
type="daterange"
|
||||
style="width: 50vw"
|
||||
value-format="YYYYMMDD00:00:00"
|
||||
range-separator="-"
|
||||
start-placeholder="起始日期"
|
||||
end-placeholder="结束日期"
|
||||
size="small"
|
||||
@change="synthesisDateChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="placeHolder"></div>
|
||||
</div>
|
||||
|
||||
<!--数值-->
|
||||
<div class="number-group">
|
||||
<div>
|
||||
<div>总预算完成度</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.totalIncome }} 万</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>门诊预算完成度</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.outpatientBudget }} 万</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>住院预算完成度</div>
|
||||
<div class="place-holder"></div>
|
||||
<div>{{ showData.inpMedfee}}万</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--三个饼图 金额占比-->
|
||||
<div>
|
||||
<div class="ec-group">
|
||||
<div ref="medical_pie" class="ec_class"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dateChoose {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.5vh;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
.dateText{
|
||||
width: 20vw;
|
||||
}
|
||||
.dateWrap{
|
||||
width: 15vw;
|
||||
}
|
||||
.placeHolder{
|
||||
width: 42vw;
|
||||
}
|
||||
|
||||
.place-holder {
|
||||
height: 1vh;
|
||||
}
|
||||
|
||||
.number-group {
|
||||
width: 80vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 3vh;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.ec-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 3vh;
|
||||
}
|
||||
|
||||
.ec_class {
|
||||
width: 80vw;
|
||||
height: 25vh;
|
||||
}
|
||||
|
||||
</style>
|
||||
62
vite.config.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import {defineConfig, loadEnv} from 'vite'
|
||||
import path from 'path'
|
||||
import createVitePlugins from './vite/plugins'
|
||||
|
||||
export default defineConfig(({mode, command}) => {
|
||||
const env = loadEnv(mode, process.cwd())
|
||||
const {VITE_APP_ENV} = env
|
||||
return {
|
||||
base: VITE_APP_ENV === 'production' ? '/' : '/',
|
||||
plugins: createVitePlugins(env, command === 'build'),
|
||||
resolve: {
|
||||
// https://cn.vitejs.dev/config/#resolve-alias
|
||||
alias: {
|
||||
// 设置路径
|
||||
'~':
|
||||
path.resolve(__dirname, './'),
|
||||
// 设置别名
|
||||
'@':
|
||||
path.resolve(__dirname, './src')
|
||||
}
|
||||
,
|
||||
// https://cn.vitejs.dev/config/#resolve-extensions
|
||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
|
||||
}
|
||||
,
|
||||
// vite 相关配置
|
||||
server: {
|
||||
hmr: true,
|
||||
port:
|
||||
8099,
|
||||
host:
|
||||
true,
|
||||
open:
|
||||
true,
|
||||
proxy:
|
||||
{
|
||||
// https://cn.vitejs.dev/config/#server-proxy
|
||||
'/dev-api':
|
||||
{
|
||||
target: 'http://localhost:8083',
|
||||
// target: 'http://110.153.1.138:8081',
|
||||
changeOrigin:
|
||||
true,
|
||||
rewrite:
|
||||
(p) => p.replace(/^\/dev-api/, ''),
|
||||
}
|
||||
,
|
||||
'/prod-api':
|
||||
{
|
||||
target: 'http://110.153.1.138:8081',
|
||||
changeOrigin:
|
||||
true,
|
||||
rewrite:
|
||||
(p) => p.replace(/^\/prod-api/, '/prod-api/'),
|
||||
}
|
||||
}
|
||||
}
|
||||
,
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
12
vite/plugins/auto-import.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import autoImport from 'unplugin-auto-import/vite'
|
||||
|
||||
export default function createAutoImport() {
|
||||
return autoImport({
|
||||
imports: [
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia'
|
||||
],
|
||||
dts: false
|
||||
})
|
||||
}
|
||||
10
vite/plugins/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import createAutoImport from './auto-import.js'
|
||||
import createSvgIcon from './svg-icon'
|
||||
|
||||
export default function createVitePlugins(viteEnv, isBuild) {
|
||||
const vitePlugins = [vue()]
|
||||
vitePlugins.push(createAutoImport())
|
||||
vitePlugins.push(createSvgIcon(isBuild))
|
||||
return vitePlugins
|
||||
}
|
||||
10
vite/plugins/svg-icon.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
import path from 'path'
|
||||
|
||||
export default function createSvgIcon(isBuild) {
|
||||
return createSvgIconsPlugin({
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')],
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
svgoOptions: isBuild
|
||||
})
|
||||
}
|
||||