Browse Source

回退版本

master
aBin 4 years ago
commit
4d0b263545
  1. 3
      .browserslistrc
  2. 8
      .editorconfig
  3. 3
      .env
  4. 11
      .env.development
  5. 3
      .env.mock
  6. 10
      .env.production
  7. 47
      .eslintrc.js
  8. 23
      .gitignore
  9. 13
      .prettierrc
  10. 24
      README.md
  11. 13
      babel.config.js
  12. 1
      commitlint.config.js
  13. 30196
      package-lock.json
  14. 53
      package.json
  15. BIN
      public/favicon.ico
  16. BIN
      public/img/icons/Chevron left-Outlined_好压看图.png
  17. BIN
      public/img/icons/android-chrome-192x192.png
  18. BIN
      public/img/icons/android-chrome-512x512.png
  19. BIN
      public/img/icons/android-chrome-maskable-192x192.png
  20. BIN
      public/img/icons/android-chrome-maskable-512x512.png
  21. BIN
      public/img/icons/apple-touch-icon-120x120.png
  22. BIN
      public/img/icons/apple-touch-icon-152x152.png
  23. BIN
      public/img/icons/apple-touch-icon-180x180.png
  24. BIN
      public/img/icons/apple-touch-icon-60x60.png
  25. BIN
      public/img/icons/apple-touch-icon-76x76.png
  26. BIN
      public/img/icons/apple-touch-icon.png
  27. BIN
      public/img/icons/favicon-16x16.png
  28. BIN
      public/img/icons/favicon-32x32.png
  29. BIN
      public/img/icons/msapplication-icon-144x144.png
  30. BIN
      public/img/icons/mstile-150x150.png
  31. 3
      public/img/icons/safari-pinned-tab.svg
  32. 19
      public/index.html
  33. 2
      public/robots.txt
  34. 99
      public/sdk.js
  35. 15
      rest/http-client.env.json
  36. 55
      rest/project.http
  37. 78
      src/App.vue
  38. BIN
      src/assets/fixed.png
  39. BIN
      src/assets/pingche.png
  40. BIN
      src/assets/yan.png
  41. 486
      src/common/portrait.styl
  42. 47
      src/components/BtnCon/BtnCon.vue
  43. 154
      src/components/Content/Content.vue
  44. 186
      src/components/NumKey/NumKey.vue
  45. BIN
      src/components/NumKey/photo/del.png
  46. 80
      src/components/TestModel/TestModel.vue
  47. 302
      src/components/TimeSelect/TimeSelect.vue
  48. 124
      src/components/Title/Title.vue
  49. 20
      src/config/api-user.js
  50. 110
      src/config/api.js
  51. 30
      src/config/setting.js
  52. 19
      src/config/user.js
  53. 33
      src/main.js
  54. 95
      src/plugins/ant-design-vue.js
  55. 84
      src/plugins/axios.js
  56. 3
      src/plugins/vue-quill-editor.js
  57. 34
      src/registerServiceWorker.js
  58. 202
      src/router/index.js
  59. 7
      src/store/index.js
  60. 85
      src/store/modules/home/actions.js
  61. 26
      src/store/modules/home/getters.js
  62. 6
      src/store/modules/home/index.js
  63. 91
      src/store/modules/home/mutations.js
  64. 24
      src/store/modules/home/state.js
  65. 283
      src/views/AddPatient/AddPatient.vue
  66. 117
      src/views/AddPatient/config.js
  67. 307
      src/views/Assess/Assess.vue
  68. 19
      src/views/Assess/config.js
  69. 296
      src/views/Choice/Choice.vue
  70. 106
      src/views/Choice/Patient.vue
  71. 244
      src/views/Control/Control.vue
  72. 38
      src/views/Control/components/Table.vue
  73. 79
      src/views/Control/components/TimeLine.vue
  74. 58
      src/views/Currency/Currency.vue
  75. 156
      src/views/Diagnosis/Diagnosis.vue
  76. BIN
      src/views/Diagnosis/png/duty.png
  77. BIN
      src/views/Diagnosis/png/tel.png
  78. 51
      src/views/Establish/Assessment.vue
  79. 331
      src/views/Establish/Establish.vue
  80. 120
      src/views/GroupNotes/GroupNotes.vue
  81. 82
      src/views/Index/Index.vue
  82. 138
      src/views/Index/components/Analysis.vue
  83. 101
      src/views/Index/components/DataTable.vue
  84. 110
      src/views/Index/components/Process.vue
  85. 26
      src/views/InfoReport/InfoReport.vue
  86. 102
      src/views/Information/Information.vue
  87. 345
      src/views/MedicalSkill/MedicalSkill.vue
  88. 18
      src/views/MedicalSkill/config.js
  89. 134
      src/views/PatientList/PatientList.vue
  90. 140
      src/views/PatientList/components/List.vue
  91. 22
      src/views/Quarter/Courtyard/BeOnDuty.vue
  92. 10
      src/views/Quarter/Courtyard/ControlCore.vue
  93. 22
      src/views/Quarter/Courtyard/Details.vue
  94. 10
      src/views/Quarter/Courtyard/DetailsCore.vue
  95. 22
      src/views/Quarter/Courtyard/Infor.vue
  96. 22
      src/views/Quarter/Courtyard/Operation.vue
  97. 22
      src/views/Quarter/Courtyard/QualityControl.vue
  98. 22
      src/views/Quarter/Province/Details.vue
  99. 22
      src/views/Quarter/Province/Quarter.vue
  100. 22
      src/views/Quarter/Province/Year.vue

3
.browserslistrc

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

8
.editorconfig

@ -0,0 +1,8 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 140
root = true

3
.env

@ -0,0 +1,3 @@
VUE_APP_MODE=production
VUE_APP_PREVIEW=false
VUE_APP_URL=https://www.tall.wiki/

11
.env.development

@ -0,0 +1,11 @@
VUE_APP_MODE=development
VUE_APP_NODE_ENV=development
VUE_APP_SCENE=flat-car
VUE_APP_BASE_URL=https://www.tall.wiki/
VUE_APP_BASE_URL=https://www.tall.wiki
VUE_APP_API_URL=https://www.tall.wiki
VUE_APP_PROXY_URL=
VUE_APP_PUBLIC_PATH=/qc
VUE_APP_MSG_URL=wss://www.tall.wiki/websocket/message/v4.0/ws
VUE_APP_TITLE=智慧平车
VUE_APP_DESCRIPTION=智慧平车

3
.env.mock

@ -0,0 +1,3 @@
VUE_APP_BASE_URL=http://127.0.0.1:3000
VUE_APP_API_URL=http://127.0.0.1:3000
VUE_APP_PROXY_URL=

10
.env.production

@ -0,0 +1,10 @@
VUE_APP_MODE=production
VUE_APP_NODE_ENV=production
VUE_APP_SCENE=flat-car
VUE_APP_BASE_URL=https://www.tall.wiki/
VUE_APP_API_URL=https://www.tall.wiki
VUE_APP_PROXY_URL=
VUE_APP_PUBLIC_PATH=/qc
VUE_APP_MSG_URL=wss://www.tall.wiki/websocket/message/v4.0/ws
VUE_APP_TITLE=智慧平车
VUE_APP_DESCRIPTION=智慧平车

47
.eslintrc.js

@ -0,0 +1,47 @@
/*
* Copyright (c) 2019.
* author: wally
* email: 18603454788@163.com
*/
module.exports = {
root: true,
env: { browser: true, node: true },
extends: ['plugin:vue/recommended', 'plugin:vue/essential'],
rules: {
'vue/html-self-closing': 'off',
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['state'] }],
'max-len': ['error', { code: 140, tabWidth: 2 }],
'object-curly-newline': ['error', { multiline: true }],
'arrow-parens': ['error', 'as-needed'],
'linebreak-style': 'off',
'vue/attributes-order': 'off',
'no-param-reassign': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/html-indent': 'off',
},
parserOptions: { parser: 'babel-eslint' },
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)'],
env: { jest: true },
},
],
globals: {
Vue: true,
VueRouter: true,
Vuex: true,
axios: true,
_: true,
Vuetify: true,
vuetify: true,
},
};

23
.gitignore

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

13
.prettierrc

@ -0,0 +1,13 @@
{
"printWidth": 140,
"singleQuote": true,
"semi": true,
"trailingComma": "all",
"arrowParens": "avoid",
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"jsxBracketSameLine": false,
"proseWrap": "always",
"endOfLine": "lf"
}

24
README.md

@ -0,0 +1,24 @@
# 中医药大学课题数据库
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

13
babel.config.js

@ -0,0 +1,13 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
plugins: [
[
"import",
{
libraryName: "ant-design-vue",
libraryDirectory: "es",
style: true
}
]
]
};

1
commitlint.config.js

@ -0,0 +1 @@
module.exports = {extends: ['./node_modules/vue-cli-plugin-commitlint/lib/lint']};

30196
package-lock.json

File diff suppressed because it is too large

53
package.json

@ -0,0 +1,53 @@
{
"name": "wisdom-mobile",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"serve-mock": "vue-cli-service serve --mode mock",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"ant-design-vue": "^1.2.4",
"compression-webpack-plugin": "^6.1.1",
"core-js": "^3.6.5",
"echarts": "^4.9.0",
"echarts-gl": "^1.1.1",
"moment": "^2.29.1",
"register-service-worker": "^1.7.1",
"stylus": "^0.54.8",
"vue": "^2.6.11",
"vue-dompurify-html": "^2.3.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-pwa": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-prettier": "^6.0.0",
"axios": "^0.18.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.11.0",
"css-loader": "^5.0.1",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^6.2.2",
"less": "^2.7.3",
"less-loader": "^4.1.0",
"prettier": "^1.19.1",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"svg-sprite-loader": "^5.0.0",
"vue-cli-plugin-ant-design": "^1.0.1",
"vue-cli-plugin-axios": "^0.0.4",
"vue-template-compiler": "^2.6.11"
}
}

BIN
public/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/img/icons/Chevron left-Outlined_好压看图.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
public/img/icons/android-chrome-192x192.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
public/img/icons/android-chrome-512x512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
public/img/icons/android-chrome-maskable-192x192.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
public/img/icons/android-chrome-maskable-512x512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
public/img/icons/apple-touch-icon-120x120.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
public/img/icons/apple-touch-icon-152x152.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/icons/apple-touch-icon-180x180.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
public/img/icons/apple-touch-icon-60x60.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/img/icons/apple-touch-icon-76x76.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/img/icons/apple-touch-icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
public/img/icons/favicon-16x16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/icons/favicon-32x32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/icons/msapplication-icon-144x144.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/icons/mstile-150x150.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

3
public/img/icons/safari-pinned-tab.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 215 B

19
public/index.html

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

2
public/robots.txt

@ -0,0 +1,2 @@
User-agent: *
Disallow:

99
public/sdk.js

@ -0,0 +1,99 @@
/*
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-04-19 10:23:19
* @LastEditors: aBin
* @LastEditTime: 2021-06-09 09:50:31
*/
/**
* ccsens tall sdk.js
* v1.0.0
* 父组件调用 TallPlugin.init()即可
* 监听message消息, 如果是created消息 就把tall的参数传递过来
*/
(function(window) {
// 单例局部变量
var _instance = null;
// 对外暴露TallPlugin类
window.TallPlugin = function(config) {
this.config = config;
this.props = null;
this.parent = '*';
};
// 初始化并保证是单例
TallPlugin.init = function(callback, config) {
if (!_instance) {
_instance = new TallPlugin(config);
_instance.config = config;
_instance.parent = window.parent.origin;
// DOM加载完成
window.addEventListener('DOMContentLoaded', _instance.mounted, false);
// window onload
window.addEventListener('load', _instance.loaded, false);
// destroy
window.addEventListener('unload', _instance.destroy, false);
// error
window.addEventListener('error', _instance.error, false);
_instance.onMessage(callback);
}
return _instance;
};
TallPlugin.prototype.onMessage = function(callback) {
var _this = this;
window.addEventListener(
'message',
function(event) {
try {
if (_this.parent === event.origin) {
// 是父窗体传来的消息
console.log('event.data:', event.data);
var data = JSON.parse(event.data);
_this.props = data || null;
callback && typeof callback === 'function' && callback.call(_this, data);
} else {
_this.props = null;
}
} catch (e) {
// console.error(`TallPlugin warn: ${e}`)
_this.props = null;
}
},
false,
);
return this;
};
// DOMContentLoaded DOM加载完成触发
TallPlugin.prototype.mounted = function(callback) {
var _this = this;
window.postMessage('created', _this.parent);
callback && typeof callback === 'function' && callback.call(this);
return this;
};
// load window onload触发
TallPlugin.prototype.loaded = function(callback) {
var _this = this;
window.postMessage('loaded', _this.parent);
callback && typeof callback === 'function' && callback.call(this);
return this;
};
// 子窗体销毁触发
TallPlugin.prototype.destroy = function(callback) {
var _this = this;
window.postMessage('destroy', _this.parent);
callback && typeof callback === 'function' && callback.call(this);
return this;
};
// error触发
TallPlugin.prototype.error = function(callback) {
var _this = this;
window.postMessage('error', _this.parent);
callback && typeof callback === 'function' && callback.call(this);
return this;
};
})(window);

15
rest/http-client.env.json

@ -0,0 +1,15 @@
{
"$shared": {
"version": "v1",
"identifier": "wally",
"credential": "111111"
},
"dev": {
"name": "dev",
"url": "http://192.168.31.13/gateway"
},
"local": {
"version": "v2",
"url": "http://192.168.31.13/gateway"
}
}

55
rest/project.http

@ -0,0 +1,55 @@
# @tall = {{url}}/tall/v1.0
@tall = https://test.tall.wiki/gateway/tall/v1.0
@tcm = https://test.tall.wiki/gateway/tcm
@type = content-type: application/json;charset=utf-8
### login
# @name login
POST {{tall}}/users/signin
{{type}}
{
"client": 1,
"type": 3,
"data": {
"identifier": "song",
"credential": "999999"
}
}
### send code
GET {{tall}}/users/smscode?phone=16603418748
### phone login
# @name phonelogin
POST {{tall}}/users/signin
{{type}}
{
"client": 1,
"type": 1,
"data": {
"identifier": "16603418748",
"credential": "1111"
}
}
### 根据团队id查看研发团队相关信息
POST {{tcm}}/patient/selSearchCriteriaList
{{type}}
Authorization: Bearer {{login.response.body.$.data.token}}
# {
# "param": {
# "company": "",
# "researchDirection": "",
# "teamId": 0,
# "teamIntroduce": "",
# "teamLeaderName": "",
# "teamName": ""
# }
# }

78
src/App.vue

@ -0,0 +1,78 @@
<template>
<a-config-provider :locale="zh_CN">
<!-- <div v-if="anyringToken && ptProps.userId" class="d-flex flex-column flex-wrap" id="app"> -->
<div class="d-flex flex-column flex-wrap" id="app">
<btn-con class="btn-box fill-width" />
<Title></Title>
<router-view style="margin-top: 48px; padding-bottom: 50px" class="flex-1 bg fill-width"></router-view>
</div>
</a-config-provider>
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
import zh_CN from 'ant-design-vue/lib/locale-provider/zh_CN';
import BtnCon from 'components/BtnCon/BtnCon.vue';
import Title from 'components/Title/Title.vue';
export default {
name: 'App',
components: { Title,BtnCon },
data() {
return { zh_CN };
},
computed: mapState('home', ['anyringToken', 'ptProps']),
// created() {
//
async created() {
const userId = '1217647686598135808';
const params = { userId };
await this.getUserId(params);
await this.getToken();
//
// this.getProps();
},
methods: {
...mapActions('home', ['getUserId']),
...mapMutations('home', ['setPtProps', 'getToken']),
async getProps() {
var query = window.location.search.substring(1);
var vars = query.split('&');
const obj = {};
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
obj[pair[0]] = pair[1];
}
this.setPtProps(obj);
if (obj && obj.userId) {
const params = { userId: obj.userId };
await this.getUserId(params);
await this.getToken();
}
},
},
};
</script>
<style>
html,
body,
#app {
min-height: 100%;
}
#app {
background: transparent;
}
body::-webkit-scrollbar {
width: 0;
}
</style>
<style lang="stylus">
@import './common/portrait.styl';
</style>

BIN
src/assets/fixed.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/assets/pingche.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
src/assets/yan.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

486
src/common/portrait.styl

@ -0,0 +1,486 @@
// padding
.pa-3 {
padding: 12px;
}
.pl-1{
padding-left: 4px;
}
.pl-2{
padding-left: 8px;
}
.pl-3{
padding-left: 12px;
}
.pl-4{
padding-left: 16px;
}
.pl-5{
padding-left: 20px;
}
.pr-1{
padding-right: 4px;
}
.pr-2{
padding-right: 8px;
}
.pr-3{
padding-right: 12px;
}
.pr-4{
padding-right: 16px;
}
.pr-5{
padding-right: 20px;
}
.px-1{
padding-left: 4px;
padding-right: 4px;
}
.px-2{
padding-left: 8px;
padding-right: 8px;
}
.px-3{
padding-left: 12px;
padding-right: 12px;
}
.px-10{
padding-left: 30px;
padding-right: 30px;
}
.py-1{
padding-top: 4px;
padding-bottom: 4px;
}
.py-2{
padding-top: 8px;
padding-bottom: 8px;
}
.py-3{
padding-top: 12px;
padding-bottom: 12px;
}
.pt-3 {
padding-top: 12px;
}
.pb-3 {
padding-bottom: 12px;
}
.pb-4 {
padding-bottom: 16px;
}
.pb-5 {
padding-bottom: 20px;
}
.pb-10 {
padding-bottom: 40px;
}
// margin
.ma-2 {
margin: 8px;
}
.ma-3 {
margin: 12px;
}
.mx-2{
margin-left: 8px;
margin-right: 8px;
}
.mx-3{
margin-left: 12px;
margin-right: 12px;
}
.my-0{
margin-top: 0px;
margin-bottom: 0px;
}
.my-1{
margin-top: 4px;
margin-bottom: 4px;
}
.my-2{
margin-top: 8px;
margin-bottom: 8px;
}
.my-3{
margin-top: 12px;
margin-bottom: 12px;
}
.my-4{
margin-top: 16px;
margin-bottom: 16px;
}
.mt-1{
margin-top: 4px;
}
.mt-2{
margin-top: 8px;
}
.mt-3{
margin-top: 12px;
}
.mt-4{
margin-top: 16px;
}
.mb-0{
margin-bottom: 0px;
}
.mb-1{
margin-bottom: 4px;
}
.mb-2{
margin-bottom: 8px;
}
.mb-3{
margin-bottom: 12px;
}
.mb-4{
margin-bottom: 16px;
}
.mb-10{
margin-bottom: 40px;
}
.ml-1{
margin-left: 4px;
}
.ml-2{
margin-left: 8px;
}
.ml-3{
margin-left: 12px;
}
.ml-4{
margin-left: 16px;
}
.ml-5{
margin-left: 20px;
}
.ml-6{
margin-left: 24px;
}
.ml-7{
margin-left: 28px;
}
.ml-8{
margin-left: 32px;
}
.ml-9{
margin-left: 36px;
}
.ml-10{
margin-left: 40px;
}
.mr-1{
margin-right: 4px;
}
.mr-2{
margin-right: 8px;
}
.mr-3{
margin-right: 12px;
}
.mr-4{
margin-right: 16px;
}
.mr-5{
margin-right: 20px;
}
.mr-6{
margin-right: 24px;
}
// background
.white {
background: white;
}
.green{
background: #4CAF50;
}
.blue{
background: #1890ff;
}
.gray{
background: #CCCCCC;
}
.white--text{
color: #fff;
width: 100px;
margin: 0 auto
}
.bot-right-btn{
position: fixed;
height: 40px;
right: 6px;
bottom: 20px;
}
.bot-right-tips {
position: fixed;
height: 40px;
font-size: 14px;
right: 18px;
top: 0;
}
// flex
.d-flex{
display: flex;
}
.flex-wrap{
flex-wrap: wrap;
}
.flex-nowrap{
flex-wrap: nowrap;
}
.flex-column{
flex-direction: column;
}
.flex-column-reverse{
flex-direction: column-reverse;
}
.flex-row{
flex-direction: row;
}
.flex-row-reverse{
flex-direction: row-reverse;
}
.justify-center{
justify-content: center;
}
.justify-space-between{
justify-content: space-between;
}
.align-center{
align-items: center;
}
.align-left{
align-items: start;
}
.flex-1{
display: flex;
flex: 1;
}
.flex-2{
display: flex;
flex: 2;
}
// other
.pointer{
cursor:pointer;
}
.pointerEdit {
font-size: 16px;
margin-right: 20px;
}
.fill-height{
height:100%;
}
// font
.font-bold{
font-weight: bold;
}
.font-bold-24{
font-size: 24px;
font-weight: bold;
}
.font-24{
font-size: 24px;
}
.font-bold-18{
font-size: 18px;
font-weight: bold;
}
.font-18{
font-size: 18px;
}
.font-bold-16{
font-size: 16px;
font-weight: bold;
}
.font-16{
font-size: 16px;
}
.font-bold-14{
font-size: 14px;
font-weight: bold;
}
.font-14{
font-size: 14px;
}
.font-12{
font-size: 12px;
}
.icon-size{
font-size: 20px;
}
h2{
font-size: 24px;
font-weight: bold;
color: rgba(0,0,0,.85)
}
.textColor{
color: rgba(0,0,0,.65)
}
.text-white{
color: #fff
}
.text-red{
color: #EB3527
}
.gray-text{
color: #bbb
}
.baseColor{
color: #1890ff
}
.bg{
background: #F5F5F5
}
.fill-width{
width:100%;
}
.fill-height{
height:100%;
}
// .ant-form-item-label {
// text-align: left;
// }
// .ant-form-item-control {
// width:100%
// }
.ant-form-item-children(:only-child) {
display: flex;
flex-wrap: nowrap;
}
.ant-card-head-title {
font-weight: 600 !important;
font-size: 18px !important;
}
.ant-card-bordered {
border-radius: 10px;
}
// .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
// position: fixed;
// top: 50%;
// left: 50%;
// margin: -10px;
// }
.ant-list-bordered {
border: none;
border-radius: 4px
}
.ant-collapse {
background-color: none;
border: none
}
.w-screen{
width: 100vw;
}
.h-screen{
height: 100vh;
}
.text-center{
text-align: center;
}

47
src/components/BtnCon/BtnCon.vue

@ -0,0 +1,47 @@
<!--
* @Author: your name
* @Date: 2021-07-28 17:06:37
* @LastEditTime: 2021-07-29 10:24:56
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \wisdomcar_mobile\src\components\BtnCon\BtnCon.vue
-->
<template>
<div class="d-flex flex-wrap" style="margin-top:44px">
<a-button type="primary" @click="jump('/')" class="mx-2 my-2">首页</a-button>
<a-button type="primary" @click="jump('/establish')" class="mx-2 my-2">创建病例</a-button>
<a-button type="primary" @click="jump('/choice')" class="mx-2 my-2">选择平车</a-button>
<a-button type="primary" @click="jump('/groupNotes')" class="mx-2 my-2">团注</a-button>
<a-button type="primary" @click="jump('/currency')" class="mx-2 my-2">通用界面</a-button>
<a-button type="primary" @click="jump('/video')" class="mx-2 my-2">视频谈话</a-button>
<a-button type="primary" @click="jump('/patient')" class="mx-2 my-2">患者表格</a-button>
<a-button type="primary" @click="jump('/information')" class="mx-2 my-2">到场信息</a-button>
<a-button type="primary" @click="jump('/assess')" class="mx-2 my-2">入院评估</a-button>
<a-button type="primary" @click="jump('/medicalSkill')" class="mx-2 my-2">医技结论</a-button>
<a-button type="primary" @click="jump('/treatmentPlan')" class="mx-2 my-2">治疗方案</a-button>
<a-button type="primary" @click="jump('/control')" class="mx-2 my-2">质控</a-button>
<a-button type="primary" @click="jump('/patientList')" class="mx-2 my-2">急救绿色通道列表</a-button>
<a-button type="primary" @click="jump('/report')" class="mx-2 my-2">1月质控报告</a-button>
<a-button type="primary" @click="jump('/vein')" class="mx-2 my-2">静脉溶栓插件</a-button>
<a-button type="primary" @click="jump('/therapy')" class="mx-2 my-2">介入治疗插件</a-button>
<a-button type="primary" @click="jump('/treatment')" class="mx-2 my-2">知情谈话</a-button>
<a-button type="primary" @click="jump('/diagnosis')" class="mx-2 my-2">会诊</a-button>
<a-button type="primary" @click="jump('/infoReport')" class="mx-2 my-2">信息直报</a-button>
</div>
</template>
<script>
export default {
name: 'BtnCon',
data() {
return {};
},
methods: {
jump(url) {
this.$router.push(url);
},
},
};
</script>
<style lang="stylus" scoped></style>

154
src/components/Content/Content.vue

@ -0,0 +1,154 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 09:37:50
* @LastEditors: aBin
* @LastEditTime: 2021-06-11 15:29:01
-->
<template>
<div class="mt-1">
<a-card class="fill-width">
<div slot="title" style="color: rgba(76, 115, 177, 0.9)">详情</div>
<a-upload
name="files"
:headers="headers"
:default-file-list="fileList"
:multiple="true"
:action="action"
list-type="picture-card"
@change="handleChange"
>
<div>
<a-icon type="plus" />
<div class="ant-upload-text">添加图片</div>
</div>
</a-upload>
<a-textarea v-model="value" placeholder="描述..." :auto-size="{ minRows: 3, maxRows: 10 }" />
<a-button class="mt-2 mb-4" style="height: 40px" type="primary" block @click="setData"> 提交 </a-button>
<div style="color: rgba(76, 115, 177, 0.9)">历史记录</div>
<a-list item-layout="horizontal" :data-source="oldData">
<a-list-item slot="renderItem" slot-scope="item, index">
<a-upload
class="fill-width"
style="overflow: hidden"
v-if="item.type === 0"
list-type="picture"
:default-file-list="getFileList(item, index)"
>
</a-upload>
<span v-else-if="item.type === 1">{{ item.comment }}</span>
</a-list-item>
</a-list>
</a-card>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { upload, otherUpload, otherQuery } from 'config/api';
export default {
name: 'Content',
props: {
time: {
type: Number,
default: Date.parse(new Date()),
},
},
data() {
return {
fileList: [],
value: '',
action: upload,
oldData: [],
};
},
computed: {
...mapState('home', ['ptProps']),
//
headers() {
const token = sessionStorage.getItem('anyringToken');
return { Authorization: `Bearer ${token}` };
},
},
created() {
this.getData();
},
methods: {
handleChange(info) {
const status = info.file.status;
if (status === 'done') {
const file = info.file;
const obj = {
uid: file.uid,
name: file.response.data[0].name,
status: status,
url: file.response.data[0].visitUrl,
};
this.fileList.push(obj);
}
},
//
async setData() {
try {
const { value, fileList } = this;
let pictures = [];
if (fileList.length) {
pictures = fileList.map(item => {
return item.url;
});
}
const params = {
param: {
id: this.ptProps.id,
pictures,
records: value,
startTime: this.time,
},
};
const res = await otherUpload(params);
const { code } = res.data;
if (code === 200) {
this.$message.success('提交成功');
} else {
this.$message.error('提交失败');
}
} catch (error) {
console.error(error);
}
},
//
async getData() {
try {
const params = { param: { id: this.ptProps.id } };
const res = await otherQuery(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.oldData = data;
} else {
}
} catch (error) {}
},
//
getFileList(item, index) {
const name = item.comment.split('/')[item.comment.split('/').length - 1];
let obj = {
uid: index,
name: name.length > 20 ? name.substring(name.length - 20, name.length) : name,
status: 'done',
url: item.comment,
};
return [obj];
},
},
};
</script>
<style lang="stylus" scoped>
/deep/ .ant-list-item {
justify-content: left;
}
/deep/ .ant-upload-list-item-card-actions.picture {
display: none;
}
</style>

186
src/components/NumKey/NumKey.vue

@ -0,0 +1,186 @@
<template>
<div class="num-box">
<div class="num-key d-flex flex-column">
<div class="num-title d-flex flex-row justify-space-between">
<span class="gray-text" @click="$emit('closeNumModel')">取消</span>
<div>
{{ title }}
<span class="px-2 baseColor" style="border-bottom: 1px solid #333">{{ num === '0' ? numValue : num }}</span>
{{ unit }}
</div>
<div style="width: 24px"></div>
</div>
<div class="flex-1 fill-width key-box">
<a-button
:class="item === '确定' ? 'num-btn-btn' : 'num-btn'"
:disabled="(disable && item === '.') || (future && item === '未评')"
v-for="item in btnList"
:key="item"
@click="entering(item)"
>
<img v-if="item === 'img'" style="width: 28px" src="./photo/del.png" />
<span v-else>{{ item }}</span>
</a-button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: '',
},
type: {
type: String,
default: '',
},
unit: {
type: String,
default: '',
},
numValue: {
type: String,
default: '0',
},
},
data() {
return {
num: '0',
btnList: ['1', '2', '3', 'img', '4', '5', '6', '确定', '7', '8', '9', '.', '0', '未评'],
disable: false,
future: false,
};
},
methods: {
submit() {
this.$emit('changeValue', this.num, this.type);
},
entering(e) {
console.log('e: ', e);
let num = this.num;
/**
* 判断是否为删除按钮
* 1. 先判断字符串是否存在
* 2. 如果字符串存在,再判断字符串当前是否为 未评 ,如果是 未评 ,则直接给num 赋值为 0
* 3. 如果字符串不是 未评 ,且倒数第二位是否为 . ,如果是则一次删除两位,否则一次删除一位
* 4. 如果删除了 . ,回复 . 按钮的点击状态
* 5. 如果num不存在时,给num赋值为0
*/
if (e === 'img') {
if (num.length) {
console.log('num[num.length-1]', num[num.length - 1]);
if (num === '未评') {
num = 0;
this.future = false;
} else if (num[num.length - 1] === '.') {
num = num.slice(0, num.length - 1);
this.disable = false;
} else {
num = num.slice(0, num.length - 1);
}
if (!num) {
num = 0;
}
}
}
/**
* 判断是否为 .
* 如果是则拼到字符串中,并且修改 . 按钮的点击状态为不可用
*/
if (e === '.') {
if (num !== '未评') {
num += e;
this.disable = true;
}
}
/**
* 判断是否为 未评
* 如果是则覆盖原来字符串,且删除时需要直接删掉 两个字,并且重新赋值为0
* 当点击过一次 未评 ,不可再点,除非删除掉 未评
*/
if (e === '未评') {
num = e;
this.future = true;
this.disable = false;
}
if (e === '确定') {
this.future = true;
this.disable = false;
this.submit();
}
/**
* 数字输入框
* 首先 e img 确定 未评 ,不需要处理,
* num = 0,所点的数值直接覆盖num
* num = 0, . 不能覆盖,只能拼接
* num = 未评 ,直接覆盖num
*/
// ,NaN
if (typeof (e - 0) === 'number' && !isNaN(e - 0)) {
if ((num === 0 || num === '0' || num === '未评') && e !== '.') {
this.future = false;
num = e;
} else {
num += e;
}
}
this.num = num;
},
},
};
</script>
<style scoped>
.num-box {
height: 100vh;
width: 100vw;
background: rgba(0, 0, 0, 0.35);
position: fixed;
top: 0;
left: 0;
}
.num-key {
height: 300px;
width: 100%;
position: absolute;
bottom: 0;
background: #fff;
border-radius: 8px 8px 0 0;
}
.num-title {
height: 56px;
width: 100%;
padding: 16px;
border-bottom: 1px solid #ccc;
}
.key-box {
background: #f7f7f7;
display: grid;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-column-start: 4;
grid-gap: 8px 8px;
padding: 8px;
}
.num-btn {
background: #fff;
grid-row: span 1 / span 1;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
.num-btn-btn {
background: #4b8aff;
color: #fff;
grid-row: span 3 / span 3;
height: 100%;
font-size: 20px;
}
</style>

BIN
src/components/NumKey/photo/del.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

80
src/components/TestModel/TestModel.vue

@ -0,0 +1,80 @@
<template>
<div>
<div class="w-screen h-screen box"></div>
<div class="d-flex flex-column fill-width white absolute">
<div class="d-flex flex-row justify-space-between pa-3">
<span class="gray-text" @click="$emit('closeModel')">取消</span>
<span class="font-bold">洼田饮水试验</span>
<span class="baseColor" @click="submit">确定</span>
</div>
<a-divider class="my-0" />
<div class="d-flex flex-column">
<div
class="py-2 fill-width text-center"
:class="current === index ? 'blue text-white' : ''"
v-for="(list, index) in lists"
:key="index"
@click="changeItem(index)"
>
{{ list }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
lists: {
type: Array,
default: () => [],
},
currentValue: {
type: String,
default: '',
},
},
data() {
return { current: 5 };
},
mounted() {
const i = this.lists.findIndex(item => item === this.currentValue);
if (i) {
this.current = i;
}
},
methods: {
changeItem(index) {
this.current = index;
},
submit() {
this.$emit('closeModel', this.current);
},
},
};
</script>
<style scoped>
.box {
/* display: none; */
position: fixed;
top: 0;
left: 0;
background: #000;
opacity: 50%;
}
.absolute {
position: fixed;
bottom: 0;
z-index: 99;
background: #fff;
opacity: 100%;
border-radius: 5px 5px 0 0;
}
</style>

302
src/components/TimeSelect/TimeSelect.vue

@ -0,0 +1,302 @@
<template>
<div class="select-box">
<div class="select-key d-flex flex-column" :style="{ height: showIpt ? '344px' : '300px' }">
<div class="title-box d-flex justify-space-between">
<div class="gray-text" @click="$emit('closeTimeSelect')">取消</div>
<div>{{ title }}</div>
<div class="baseColor" @click="chooseTime">确定</div>
</div>
<div v-if="showIpt" class="ipt-box d-flex justify-center align-center">
<div class="ipt-bg">
<input class="ml-2 ipt" placeholder="请输入姓名" v-model="value" />
</div>
</div>
<div class="d-flex flex-1 items-center overflow-hidden">
<template v-for="(item, itemIndex) in list">
<div class="time-box d-flex flex-row" :key="itemIndex">
<div class="time-div">
<div class="time-time">
<div class="time-content" v-for="(time, index) in item.time" :key="index">
{{ time }}
</div>
</div>
</div>
</div>
<div class="d-flex align-center" :key="item.unit">{{ item.unit }}</div>
</template>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'TimeSelect',
props: {
title: {
// title
type: String,
default: '时间',
},
showIpt: {
//
type: Boolean,
default: false,
},
iptTitle: {
//
type: String,
default: '姓名',
},
iptValue: {
//
type: String,
default: '',
},
timeValue: {
//
//
type: Number,
default: new Date().valueOf(),
},
firstIndex: {
//
type: Number,
default: 0,
},
secondIndex: {
//
type: Number,
default: 0,
},
},
data() {
return {
list: [
{
time: [],
scrollTop: 0,
unit: '年',
},
{
time: [],
scrollTop: 0,
unit: '月',
},
{
time: [],
scrollTop: 0,
unit: '日',
},
{
time: [],
scrollTop: 0,
unit: '时',
},
{
time: [],
scrollTop: 0,
unit: '分',
},
],
selectTime: '',
value: '',
};
},
mounted() {
this.setTimeData();
setTimeout(() => {
this.setScroll();
}, 10);
},
created() {
this.value = this.iptValue;
},
methods: {
/**
* 获取当前
* 然后获取需要滚动的距离
* 然后将所有值存储到 this.list
*/
setTimeData() {
// list: [ ]
var nowMonth = new Date(this.timeValue).getMonth();
var nowDay = new Date(this.timeValue).getDate() - 1;
var nowHour = new Date(this.timeValue).getHours();
var nowMin = new Date(this.timeValue).getMinutes();
/* 生成年数组 */
var my = new Date();
var endYear = my.getFullYear(); //
for (var i = endYear; i > 2018; i--) {
this.list[0].time.push(i);
}
/* 生成月数组 */
for (var i = 1; i < 13; i++) {
this.list[1].time.push(i);
if (nowMonth === i) {
this.list[1].scrollTop = i * 26;
}
}
/* 生成日数组 */
for (var i = 1; i < 32; i++) {
this.list[2].time.push(i);
if (nowDay === i) {
this.list[2].scrollTop = i * 26;
}
}
/* 生成小时数组 */
for (let i = 0; i < 24; i++) {
this.list[3].time.push(i);
if (nowHour === i) {
this.list[3].scrollTop = i * 26;
}
}
/* 生成分钟数组 */
for (let i = 0; i < 60; i++) {
this.list[4].time.push(i);
if (nowMin === i) {
this.list[4].scrollTop = i * 26;
}
}
},
/**
* list渲染到界面上之后
* list 每一项中的 scrollTop 赋值给对应的div的 scrollTop
*/
setScroll() {
// list: [ ]
let dom = document.querySelectorAll('.time-time');
dom[1].scrollTop = this.list[1].scrollTop;
dom[2].scrollTop = this.list[2].scrollTop;
dom[3].scrollTop = this.list[3].scrollTop;
dom[4].scrollTop = this.list[4].scrollTop;
console.log(dom[1].scrollTop);
},
/**
* 点击确定是,获取到每个时间字段的滚动距离
* 然后判断当前滚动位置,最中间的 字段值 (四舍五入)
* 然后判断是否小于10 以及 判断月份的最大天数
* 最后返回 一个 date 类型的数据
* 使用moment 转换成时间戳
*/
async chooseTime() {
// list: [ ]
let dom = document.querySelectorAll('.time-time');
var year = 2021 - Math.round(dom[0].scrollTop / 26);
let month = Math.round(dom[1].scrollTop / 26) + 1;
let day = Math.round(dom[2].scrollTop / 26) + 1;
let hour = Math.round(dom[3].scrollTop / 26);
let min = Math.round(dom[4].scrollTop / 26);
if (month === 2) {
if ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0 && year % 4000 !== 0)) {
if (day > 29) {
day = 29;
}
} else {
if (day > 28) {
day = 28;
}
}
} else {
if (month === 2 || month === 4 || month === 6 || month === 9 || month === 11) {
if (day > 30) {
day = 30;
}
} else {
if (day > 31) {
day = 31;
}
}
}
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
if (hour < 10) {
hour = '0' + hour;
}
if (min < 10) {
min = '0' + min;
}
this.selectTime = `${year}-${month}-${day} ${hour}:${min}:00`;
this.$emit('chooseTime', this.$moment(this.selectTime).valueOf(), this.firstIndex, this.secondIndex, this.value);
},
},
};
</script>
<style scoped>
.ipt {
width: 64%;
margin: 10px 18%;
padding: 6px 0 6px 10px;
border: 1px solid #333;
font-size: 14px;
}
.ipt-box {
padding: 0.5rem;
height: 44px;
position: relative;
}
.ipt-bg {
width: 100%;
background: #fff;
position: absolute;
top: 0;
z-index: 99;
}
.title-box {
padding: 0.5rem;
border-bottom: 2px solid rgba(229, 231, 235, 1);
height: 44px;
}
.time-box {
height: 100%;
width: 16.66%;
text-align: center;
overflow-x: hidden;
position: relative;
}
.select-box {
height: 100vh;
width: 100vw;
background: rgba(0, 0, 0, 0.35);
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.select-key {
height: 300px;
width: 100%;
position: absolute;
bottom: 0;
background: #fff;
border-radius: 8px 8px 0 0;
}
.overflow-hidden {
overflow: hidden;
padding: 0 16px;
}
.time-div {
height: 100%;
width: 100%;
margin: 0 auto;
position: absolute;
right: -8px;
}
.time-time {
height: 100%;
width: 100%;
margin: 0 auto;
overflow-y: scroll;
padding: 116px 16px 116px 0;
}
.time-content {
height: 26px;
line-height: 26px;
font-size: 16px;
width: 100%;
}
</style>

124
src/components/Title/Title.vue

@ -0,0 +1,124 @@
<template>
<div class="d-flex flex-column">
<div class="title d-flex flex-row">
<div class="iconleft">
<img @click="backPage" src="../../../public/img/icons/Chevron left-Outlined_好压看图.png" />
</div>
<div class="titles">{{ title }}</div>
<div v-if="list && list.length" class="iconright">
<div v-for="(item, index) in list" :key="index">
<a-icon v-if="item.type === 1" :type="item.icon" @click="openPage(item.path)" />
<img v-if="item.type === 2" :src="item.icon" @click="openPage(item.path)" />
<span v-if="item.type === 3" @click="changeYan" class="font-14" :class="valueType === 1 ? 'baseColor' : 'gray-text'">
{{
item.icon
}}
</span>
<a-icon v-if="item.type === 4" :type="item.icon" @click="show = true" />
</div>
</div>
</div>
<div class="divide"></div>
<time-select @chooseTime="chooseTime" v-if="show" title="开始静脉溶栓" :show="show" @closeTimeSelect="show = false" :show-ipt="true" />
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import TimeSelect from 'components/TimeSelect/TimeSelect.vue';
import { addArriveWorker } from 'config/api';
export default {
components: { TimeSelect },
data() {
return { show: false };
},
computed: mapState('home', ['title', 'list', 'valueType', 'ptProps', 'addNum']),
methods: {
...mapMutations('home', ['setValueType', 'setAddNum']),
openPage(path) {
this.$router.push(path);
},
backPage() {
window.history.go(-1);
},
changeYan() {
if (this.valueType === 1) {
this.setValueType(0);
} else {
this.setValueType(1);
}
},
//
chooseTime(time, firstIndex, secondIndex, name) {
console.log(time, firstIndex, secondIndex, name);
const info = {
name,
time,
};
this.addDoc(info);
this.show = false;
},
async addDoc(info) {
try {
const { projectId } = this.ptProps;
let num = this.addNum;
const params = {
param: {
projectId,
workerInfoList: [info],
},
};
const res = await addArriveWorker(params);
const { code, data, msg } = res.data;
if (code === 200) {
this.$message.success('添加成功');
this.setAddNum(num + 1);
}
} catch (error) {}
},
},
};
</script>
<style lang="stylus" scoped>
.title {
height: 48px;
padding: auto 10px;
background: #F5F5F5;
position: fixed;
top: 0;
width: 100%;
line-height: 48px;
z-index: 99;
}
.titles {
display: flex;
justify-content: center;
flex: 1;
}
.iconleft {
position: absolute;
left: 10px;
height: 100%;
}
.iconleft img {
height: 25px;
width: 25px;
}
.divide {
width: 100%;
height: 1px;
background: #ddd;
}
.iconright {
position: absolute;
right: 10px;
font-size: 18px;
height: 100%;
text-align: center;
}
</style>

20
src/config/api-user.js

@ -0,0 +1,20 @@
/*
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-05-31 17:25:39
* @LastEditors: aBin
* @LastEditTime: 2021-06-02 15:27:56
*/
/*
* Copyright (c) 2020.
* author: wally
* email: 18603454788@163.com
*/
import axios from 'axios';
let { proxyUrl } = require('@/config/setting');
const tall = `${proxyUrl}/gateway/tall/v1.0`;
const users = `${tall}/users`;
// 查找用户详细信息
export const getUserId = params => axios.get(`${users}/userId`, params);

110
src/config/api.js

@ -0,0 +1,110 @@
import axios from 'axios';
let { proxyUrl } = require('@/config/setting');
console.log('proxyUrl: ', proxyUrl);
const wisdomcar = `${proxyUrl}/gateway/wisdomcar`;
const qcp = `${proxyUrl}/gateway/qcp/v3.0`;
const filedeal = `${proxyUrl}/filedeal`;
const car = `${qcp}/car`; // 平车相关接口
// const project = `${wisdomcar}/project`; // 页面相关接口
const otherRecords = `${wisdomcar}/otherRecords`; // 通用界面
const patientAndFamily = `${wisdomcar}/patientAndFamily`; // 患者相关接口
const step = `${wisdomcar}/step`; // 首页节点相关接口
const worker = `${qcp}/worker`; // 人员相关接口
const statistics = `${qcp}/statistical`; // 统计相关接口
const project = `${qcp}/project`; // 项目相关接口
const patient = `${qcp}/patient`; // 患者相关接口
// 上传文件
export const upload = `${filedeal}/file/upload/multiple`;
// 查询到场人员
export const queryArriveWorker = params => axios.post(`${worker}/queryArriveWorker`, params);
// 添加到场人员
export const addArriveWorker = params => axios.post(`${worker}/addArriveWorker`, params);
// 查询所有平车
export const queryAllCar = params => axios.post(`${car}/query`, params);
// 查询空闲平车
export const carFree = params => axios.post(`${car}/free`, params);
// 绑定平车
export const bindingCar = params => axios.post(`${car}/bind`, params);
// 查询绑定的平车
export const queryBindingCar = params => axios.post(`${car}/queryBind`, params);
// 创建病例
// export const createCase = params => axios.post(`${car}/createCase`, params);
// 查询体重和团注剂量
export const getWeight = params => axios.post(`${project}/weight`, params);
// 点击开始
export const setProStart = params => axios.post(`${project}/start`, params);
// 选择历史患者切换项目
export const switchProject = params => axios.post(`${project}/switchProject`, params);
// 上传身份证图像识别
export const identifyWords = `${project}/identifyWords`;
// 获取开始时间
export const getStartTime = params => axios.post(`${project}/getStartTime`, params);
// 结束绑定平车
export const endCar = params => axios.post(`${project}/end`, params);
// 上传通用内容的图片和记录
export const otherUpload = params => axios.post(`${otherRecords}/upload`, params);
// 查询通用内容的图片和记录
export const otherQuery = params => axios.post(`${otherRecords}/queryList`, params);
// 查询医生的历史患者
export const findOldPatient = params => axios.post(`${patientAndFamily}/findOldPatient`, params);
// 查询患者信息(用于回显)
export const queryPatientInfo = params => axios.post(`${patientAndFamily}/queryPatientInfo`, params);
// 修改患者信息
export const updatePatientInfo = params => axios.post(`${patientAndFamily}/updatePatientInfo`, params);
// 查询首页节点进度
export const findStepIsOver = params => axios.post(`${statistics}/step`, params);
// 查询急救时长分析
export const getPointTime = params => axios.post(`${statistics}/getPointTime`, params);
// 质控表格
export const getControl = params => axios.post(`${proxyUrl}/controlTable`, params);
// 时间轴列表
export const getTimeLine = params => axios.post(`${proxyUrl}/timeLine`, params);
// 统计每天质控报告echarts数据图
export const everyday = params => axios.post(`${statistics}/queryQuality/everyday`, params);
// 查询质控报告(月和周)
export const queryQuality = params => axios.post(`${statistics}/queryQuality`, params);
// 查询医院成员和急救期间是否值班
export const queryAllDoctor = params => axios.post(`${worker}/queryAllDoctor`, params);
// 正式接口
// 患者列表
export const getPatientList = params => axios.post(`${patient}/query`, params);
// 批量提交急救信息
export const aidRecord = params => axios.post(`${patient}/aidRecord`, params);
// 批量查询急救信息
export const queryAidRecord = params => axios.post(`${patient}/queryAidRecord`, params);
// 根据项目id查询患者信息
export const queryByProject = params => axios.post(`${patient}/queryByProject`, params);
// 创建病例
export const createCase = params => axios.post(`${project}/createCase`, params);

30
src/config/setting.js

@ -0,0 +1,30 @@
const title = process.env.VUE_APP_TITLE;
const description = process.env.VUE_APP_DESCRIPTION;
const baseUrl = process.env.VUE_APP_BASE_URL;
const apiUrl = process.env.VUE_APP_API_URL;
const proxyUrl = process.env.VUE_APP_PROXY_URL;
const publicPath = process.env.VUE_APP_PUBLIC_PATH;
// const msgUrl = process.env.VUE_APP_MSG_URL;
module.exports = {
// 首页标题
title,
// 首页描述信息
description,
// 基础地址
baseUrl,
// api基础地址
apiUrl,
// 消息系统地址
// msgUrl,
// api代理地址
proxyUrl,
// 生成文件目录 publicPath
publicPath,
};

19
src/config/user.js

@ -0,0 +1,19 @@
/*
* Copyright (c) 2019.
* author: wally
* email: 18603454788@163.com
*/
// 用户登录client
export const SIGN_IN_CLIENTS = { mp: 0, h5: 1, android: 2, ios: 3 };
// 用户登录类型
export const SIGN_IN_TYPES = {
mp: 0,
phone: 1,
email: 2,
username: 3,
wx: 4,
wx_web: 5,
wb: 6,
};

33
src/main.js

@ -0,0 +1,33 @@
/*
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-01-29 11:16:27
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 09:51:17
*/
// @ts-ignore
import Vue from 'vue';
import './plugins/axios';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
import store from './store';
import './plugins/ant-design-vue.js';
import 'common/portrait.styl';
import echarts from 'echarts';
import 'echarts-gl';
// import 'echarts/map/js/province/shanxi.js'; //对应的省份
import './plugins/vue-quill-editor.js';
// import VueDOMPurifyHTML from 'vue-dompurify-html';
// Vue.use(VueDOMPurifyHTML);
Vue.prototype.$echarts = echarts;
import moment from 'moment'; //导入文件
Vue.prototype.$moment = moment; //赋值使用
Vue.config.productionTip = false;
window.vm = new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

95
src/plugins/ant-design-vue.js

@ -0,0 +1,95 @@
/*
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-01-29 11:16:27
* @LastEditors: aBin
* @LastEditTime: 2021-06-02 10:10:30
*/
import Vue from 'vue';
import {
Pagination,
Button,
Input,
InputNumber,
message,
notification,
Modal,
Tag,
Table,
Tabs,
Icon,
Empty,
Form,
Select,
Upload,
Badge,
Popconfirm,
DatePicker,
Switch,
Radio,
Dropdown,
Menu,
Row,
Col,
Timeline,
Checkbox,
BackTop,
Progress,
Carousel,
Spin,
Card,
List,
Collapse,
Cascader,
TimePicker,
Divider,
} from 'ant-design-vue';
import { ConfigProvider } from 'ant-design-vue';
Vue.component(ConfigProvider.name, ConfigProvider);
Vue.use(Pagination);
Vue.use(Button);
Vue.use(Input);
Vue.use(Modal);
Vue.use(Tag);
Vue.use(Table);
Vue.use(Tabs);
Vue.use(Icon);
Vue.use(Empty);
Vue.use(Form);
Vue.use(Select);
Vue.use(Upload);
Vue.use(Badge);
Vue.use(Popconfirm);
Vue.use(DatePicker);
Vue.use(Switch);
Vue.use(Radio);
Vue.use(Dropdown);
Vue.use(Menu);
Vue.use(Row);
Vue.use(Col);
Vue.use(Timeline);
Vue.use(Checkbox);
Vue.use(BackTop);
Vue.use(Progress);
Vue.use(Carousel);
Vue.use(Spin);
Vue.use(Card);
Vue.use(List);
Vue.use(Collapse);
Vue.use(Cascader);
Vue.use(InputNumber);
Vue.use(TimePicker);
Vue.use(Divider);
Vue.prototype.$message = message;
Vue.prototype.$notification = notification;
Vue.prototype.$info = Modal.info;
Vue.prototype.$success = Modal.success;
Vue.prototype.$error = Modal.error;
Vue.prototype.$warning = Modal.warning;
Vue.prototype.$confirm = Modal.confirm;
message.config({
duration: 3,
maxCount: 3,
});

84
src/plugins/axios.js

@ -0,0 +1,84 @@
/*
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-04-19 10:23:19
* @LastEditors: wally
* @LastEditTime: 2021-05-06 11:42:20
*/
'use strict';
import Vue from 'vue';
import axios from 'axios';
import router from '../router/index';
import store from '../store/index';
// Full config: https://github.com/axios/axios#request-config
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let config = {
// baseURL: process.env.baseURL || process.env.apiUrl || ""
timeout: 60 * 1000, // Timeout
// withCredentials: true, // Check cross-site Access-Control
};
const _axios = axios.create(config);
axios.interceptors.request.use(
function(config) {
let token = store.state.anyringToken || sessionStorage.getItem('anyringToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
},
);
// Add a response interceptor
axios.interceptors.response.use(
function(response) {
if (response.data && response.data.code >= 400 && response.data.code < 500) {
store.commit('user/sign', '');
router.replace({
path: '/user/login',
query: { redirect: router.currentRoute.fullPath },
});
}
// Do something with response data
return response;
},
function(error) {
// Do something with response error
return Promise.reject(error);
},
);
Plugin.install = function(Vue) {
Vue.axios = _axios;
window.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
},
},
$axios: {
get() {
return _axios;
},
},
$http: {
get() {
return _axios;
},
},
});
};
Vue.use(Plugin);
export default Plugin;

3
src/plugins/vue-quill-editor.js

@ -0,0 +1,3 @@
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';

34
src/registerServiceWorker.js

@ -0,0 +1,34 @@
/* eslint-disable no-console */
import { register } from "register-service-worker";
if (process.env.NODE_ENV === "production") {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(
"App is being served from cache by a service worker.\n" +
"For more details, visit https://goo.gl/AFskqB"
);
},
registered() {
console.log("Service worker has been registered.");
},
cached() {
console.log("Content has been cached for offline use.");
},
updatefound() {
console.log("New content is downloading.");
},
updated() {
console.log("New content is available; please refresh.");
},
offline() {
console.log(
"No internet connection found. App is running in offline mode."
);
},
error(error) {
console.error("Error during service worker registration:", error);
}
});
}

202
src/router/index.js

@ -0,0 +1,202 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from 'views/Index/Index.vue';
Vue.use(VueRouter);
const routes = [
// 首页数据统计
{
path: '/',
name: 'Home',
component: Home,
},
// 选择平车界面
{
path: '/choice',
name: 'Choice',
component: () => import('@/views/Choice/Choice.vue'),
},
// 患者表格
{
path: '/patient',
name: 'Patient',
component: () => import('@/views/Choice/Patient.vue'),
},
// 通用界面
{
path: '/currency',
name: 'Currency',
component: () => import('@/views/Currency/Currency.vue'),
},
// 创建病例界面
{
path: '/establish',
name: 'Establish',
component: () => import('@/views/Establish/Establish.vue'),
},
// 创建病例界面
{
path: '/assessment',
name: 'Assessment',
component: () => import('@/views/Establish/Assessment.vue'),
},
// 团注界面
{
path: '/groupNotes',
name: 'GroupNotes',
component: () => import('@/views/GroupNotes/GroupNotes.vue'),
},
// 视频谈话界面
{
path: '/video',
name: 'Video',
component: () => import('@/views/Video/Video.vue'),
},
// 到场插件
{
path: '/information',
name: 'Information',
component: () => import('@/views/Information/Information.vue'),
},
// 省季度数据分析报告
{
path: '/provinceQuarter',
name: 'Quarter',
component: () => import('@/views/Quarter/Province/Quarter.vue'),
},
// 省年度数据分析报告
{
path: '/provinceYear',
name: 'Year',
component: () => import('@/views/Quarter/Province/Year.vue'),
},
// 省数据分析报告详情
{
path: '/provinceDetails',
name: 'ProvinceDetails',
component: () => import('@/views/Quarter/Province/Details.vue'),
},
// 院值班表
{
path: '/courtyardBeOnDuty',
name: 'BeOnDuty',
component: () => import('@/views/Quarter/Courtyard/BeOnDuty.vue'),
},
// 院急救数据详情
{
path: '/courtyardDetails',
name: 'Details',
component: () => import('@/views/Quarter/Courtyard/Details.vue'),
},
// 院中心领导急救数据详情
{
path: '/detailsCore',
name: 'DetailsCore',
component: () => import('@/views/Quarter/Courtyard/DetailsCore.vue'),
},
// 院信息科
{
path: '/courtyardInfor',
name: 'Infor',
component: () => import('@/views/Quarter/Courtyard/Infor.vue'),
},
// 院运维界面
{
path: '/courtyardOperation',
name: 'Operation',
component: () => import('@/views/Quarter/Courtyard/Operation.vue'),
},
// 院质控数据分析报告
{
path: '/courtyardQualityControl',
name: 'QualityControl',
component: () => import('@/views/Quarter/Courtyard/QualityControl.vue'),
},
// 院中心领导质控数据分析报告
{
path: '/controlCore',
name: 'ControlCore',
component: () => import('@/views/Quarter/Courtyard/ControlCore.vue'),
},
// 评估插件
{
path: '/assess',
name: 'assess',
component: () => import('@/views/Assess/Assess.vue'),
},
// 医技插件
{
path: '/medicalSkill',
name: 'MedicalSkill',
component: () => import('@/views/MedicalSkill/MedicalSkill.vue'),
},
// 治疗方案
{
path: '/treatmentPlan',
name: 'treatmentPlan',
component: () => import('@/views/TreatmentPlan/TreatmentPlan.vue'),
},
// 质控界面
{
path: '/control',
name: 'Control',
component: () => import('@/views/Control/Control.vue'),
// 1月质控报告详情界面
},
{
path: '/report',
name: 'Report',
component: () => import('@/views/Report/Report.vue'),
},
// 患者列表
{
path: '/patientList',
name: 'PatientList',
component: () => import('@/views/PatientList/PatientList.vue'),
},
// 静脉溶栓插件
{
path: '/vein',
name: 'Vein',
component: () => import('@/views/Vein/Vein.vue'),
},
// 添加患者列表
{
path: '/addPatient',
name: 'AddPatient',
component: () => import('@/views/AddPatient/AddPatient.vue'),
},
// 介入治疗插件
{
path: '/therapy',
name: 'Therapy',
component: () => import('@/views/Therapy/Therapy.vue'),
},
// 知情谈话
{
path: '/treatment',
name: 'Treatment',
component: () => import('@/views/Treatment/Treatment.vue'),
},
// 会诊界面
{
path: '/diagnosis',
name: 'Diagnosis',
component: () => import('@/views/Diagnosis/Diagnosis.vue'),
},
// 信息直报
{
path: '/infoReport',
name: 'InfoReport',
component: () => import('@/views/InfoReport/InfoReport.vue'),
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
export default router;

7
src/store/index.js

@ -0,0 +1,7 @@
import Vue from 'vue';
import Vuex from 'vuex';
import home from './modules/home/index';
// import messages from './modules/messages/index';
Vue.use(Vuex);
export default new Vuex.Store({ modules: { home } });

85
src/store/modules/home/actions.js

@ -0,0 +1,85 @@
/*
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-04-19 10:23:19
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 11:48:40
*/
import axios from 'axios';
import { message } from 'ant-design-vue';
import { getUserId } from 'config/api-user';
import { setProStart, getStartTime } from 'config/api';
const actions = {
/**
* 通过userId获取token
* @param {any} commit
* @param {object} params 提交的参数
*/
async getUserId({ commit }, params) {
try {
const res = await getUserId({ params });
const { code, msg, data } = res.data;
if (code === 200) {
commit('sign', data.token);
commit('setUser', data);
return data;
} else {
throw msg;
}
} catch (error) {
throw error || '获取个人信息失败';
}
},
/**
* 点击开始
* @param {any} commit
* @param {object} params 提交的参数
*/
async setStart({ rootState }, startTime) {
try {
console.log('rootState1:', rootState.home);
const params = {
param: {
startTime,
taskSubId: rootState.home.ptProps.id,
},
};
console.log('rootState2:', rootState.home);
const res = await setProStart(params);
const { code, msg, data } = res.data;
if (code === 200) {
message.success('成功');
} else {
message.error('请求失败,请重新尝试');
}
} catch (error) {
message.error('请求失败,请重新尝试');
}
},
/**
* 根据任务Id获取已经填写的时间
* @param {any} commit
* @param {object} params 提交的参数
*/
async getStart({ rootState }) {
try {
const params = { param: { taskSubId: rootState.home.ptProps.id } };
const res = await getStartTime(params);
const { code, msg, data } = res.data;
if (code === 200) {
if (data && data.startTime) {
return data.startTime;
}
} else {
return false;
}
} catch (error) {
return false;
}
},
};
export default actions;

26
src/store/modules/home/getters.js

@ -0,0 +1,26 @@
/*
* @Author: your name
* @Date: 2021-07-28 12:00:41
* @LastEditTime: 2021-07-29 10:07:25
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \wisdomcar_mobile\src\store\modules\home\getters.js
*/
const getters = {
// 获取用户的id
userId({ user }) {
try {
if (!user) return '';
return user.id;
} catch (error) {
console.warn("user's getters 获取userId失败", error);
return '';
}
},
};
// 域定制导航展示形式
// 0 -> 无特殊导航文字
// 1 -> 横向定制导航
// 2 -> 纵向定制导航
export default getters;

6
src/store/modules/home/index.js

@ -0,0 +1,6 @@
import mutations from './mutations';
import actions from './actions';
import getters from './getters';
import state from './state';
export default { namespaced: true, state, getters, mutations, actions };

91
src/store/modules/home/mutations.js

@ -0,0 +1,91 @@
/*
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-05-31 17:25:39
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 11:48:32
*/
const mutations = {
/**
* 设置token
* @param { object } state
* @param { string } token
*/
sign(state, token) {
state.anyringToken = token;
sessionStorage.setItem('anyringToken', token);
},
/**
* 设置token
* @param { object } state
* @param { string } token
*/
getToken(state, token) {
state.anyringToken = sessionStorage.getItem('anyringToken');
},
/**
* 设置user用户信息
* @param {object} state
* @param {object} user {id, account, phone}
*/
setUser(state, user) {
if (!user) return;
state.user = { ...user };
sessionStorage.setItem('user', JSON.stringify(user));
},
/**
* 设置user用户信息
* @param {object} state
* @param {Array} data
*/
setControlGroups(state, data) {
state.controlGroups = data;
},
/**
* 设置Pt传过来的参数
* @param {object} state
* @param {string} data
*/
setPtProps(state, data) {
state.ptProps = { ...data };
console.log('setPtProps.ptProps', state.ptProps);
},
/**
* 设置标题
*/
setTitle(state, data) {
state.title = data;
},
/**
* 设置标题图标
* 格式 [{ icon: 'plus-circle', path: '/addPatient', type: 1 }]
* icon 图标类型 || 图片路径
* type 1 图标 2 图片 3 文字
* path 跳转路径
*/
setTitleIcon(state, data) {
state.list = data;
},
/**
* 设置正式演示
* @param {object} state
* @param {number} data 0正式 1演示
*/
setValueType(state, data) {
state.valueType = data;
},
/**
* 增加了一个到场医生后值加一到场信息界面监听到值变化后重新查询
* @param {object} state
* @param {number} data
*/
setAddNum(state, data) {
state.addNum = data;
},
};
export default mutations;

24
src/store/modules/home/state.js

@ -0,0 +1,24 @@
/*
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-04-19 10:23:19
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 18:45:35
*/
const state = {
anyringToken: '',
user: { id: '', phone: '', account: '', wxInfo: { nickname: '' } },
ptProps: {
userId: '',
// taskId: '',
// projectId: '',
id: '1400657516546887680',
projectId: '1420652719055839232',
}, // 接受PT传过来的 pluginId,projectId,roleId,taskId(id),userId
title: '智慧平车',
list: [],
valueType: 0,
addNum: 0,
};
export default state;

283
src/views/AddPatient/AddPatient.vue

@ -0,0 +1,283 @@
<template>
<div class="d-flex flex-column pb-10">
<div :key="indexa" class="tow mb-3" v-for="(index, indexa) in data">
<a-list :data-source="index" class="white" item-layout="horizontal">
<a-list-item class="mx-3" slot="renderItem" slot-scope="item" v-if="item.show">
<div class="d-flex flex-nowrap align-center" style="width: 100%">
<div class="mr-3">
{{ item.title }}
<span class="text-red" v-if="item.required">*</span>
</div>
<div class="flex-1 flex-row-reverse">
<a-input @change="onChange($event, item.name)" placeholder="请输入" style="width: 150px" v-if="item.type === 'text'" />
<a-input
@change="onChange($event, item.name)"
placeholder="请输入"
style="width: 150px"
type="number"
v-if="item.type === 'heath'"
/>
<div type="number" v-else-if="item.type === 'heaths'">自动生成</div>
<a-radio-group @change="onChange($event, item.name)" class="d-flex flex-nowrap" v-else-if="item.type === 'gender'">
<a-radio :style="radioStyle" :value="0" class="flex-1"></a-radio>
<a-radio :style="radioStyle" :value="1" class="flex-1"></a-radio>
</a-radio-group>
<a-radio-group @change="onChange($event, item.name)" class="d-flex flex-nowrap" v-else-if="item.type === 'timeType'">
<a-radio :style="radioStyle" :value="0">已知</a-radio>
<a-radio :style="radioStyle" :value="1">未知</a-radio>
<a-radio :style="radioStyle" :value="2">醒后卒中</a-radio>
</a-radio-group>
<!-- 发病时间 -->
<a-date-picker
@change="onTimeChange($event, item.name)"
format="YYYY-MM-DD HH:mm"
placeholder="请选择发病时间"
show-time
style="width: 150px"
v-else-if="item.type === 'time'"
/>
<!-- 最后看起来正常时间 -->
<a-date-picker
@change="onTimeChange($event, item.name)"
format="YYYY-MM-DD HH:mm"
placeholder="请选择最后正常时间"
show-time
style="width: 150px"
v-else-if="item.type === 'lastNormalTime'"
/>
<a-radio-group @change="onChange($event, item.name)" class="d-flex flex-nowrap" v-else-if="item.type === 'radio'">
<a-radio :style="radioStyle" :value="0" class="flex-1"></a-radio>
<a-radio :style="radioStyle" :value="1" class="flex-1"></a-radio>
</a-radio-group>
<a-date-picker
@change="onTimeChange($event, item.name)"
format="YYYY-MM-DD HH:mm"
placeholder="请选择到院时间"
show-time
style="width: 150px"
v-else-if="item.type === 'arriveTime'"
/>
<a-date-picker
@change="onTimeChange($event, item.name)"
format="YYYY-MM-DD HH:mm"
placeholder="请选择住院时间"
show-time
style="width: 150px"
v-else-if="item.type === 'inspect'"
/>
<a-select
@change="handleSelectChange($event, item.name)"
placeholder="请选择"
style="width: 150px"
v-else-if="item.type === 'select'"
>
<a-select-option :key="listIndex" :value="list.id" v-for="(list, listIndex) in item.lists">{{
list.value
}}</a-select-option>
</a-select>
<!-- 入院途径 -->
<div v-else-if="item.type === 'pathway'" style="width: 150px">
<a-select @change="handleSelectChange($event, item.name)" placeholder="请选择" style="width: 150px">
<a-select-option :key="listIndex" :value="list.id" v-for="(list, listIndex) in item.lists">{{
list.value
}}</a-select-option>
</a-select>
<a-input
@change="onPathwayChange($event, item.name)"
placeholder="请输入其他入院途径"
class="mt-3"
style="width: 150px"
v-if="showOther"
/>
</div>
<a-cascader
v-else-if="item.type === 'inHospitalType'"
style="width: 150px"
:options="item.lists"
placeholder="请选择"
change-on-select
@change="handleSelectChange($event, item.name)"
/>
<a-upload
:headers="headers"
:multiple="true"
@change="handleChange"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
name="file"
v-else-if="item.type === 'photo'"
>
<a-button class="uploads">
<a-icon type="camera" />
</a-button>
</a-upload>
</div>
</div>
</a-list-item>
</a-list>
</div>
<img @click="openChoice" class="yan" src="../../assets/fixed.png" />
<a-button :loading="loading" @click="submit" class="mx-3 mb-10" type="primary">完成创建患者</a-button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from 'vuex';
import { data } from './config';
import { createCase } from 'config/api';
export default {
data() {
return {
data,
loading: false,
current: 0,
radioStyle: {
display: 'block',
height: '30px',
lineHeight: '30px',
},
headers: { authorization: 'authorization-text' },
options: {},
showOther: false,
};
},
computed: {
...mapState('home', ['valueType']),
...mapGetters('home', ['userId']),
},
created() {
this.setTitle('基本信息');
const item = [{ icon: '(演)', path: '', type: 3 }];
this.setTitleIcon(item);
},
methods: {
...mapMutations('home', ['setTitle', 'setTitleIcon']),
onChange(e, name) {
this.options[name] = e.target.value;
if (name === 'timeType') {
if (e.target.value === 0) {
this.data[3][1].show = true;
this.data[3][2].show = false;
} else if (e.target.value === 1) {
this.data[3][1].show = false;
this.data[3][2].show = false;
} else {
this.data[3][1].show = false;
this.data[3][2].show = true;
}
}
if (name === 'hospitalStroke') {
if (e.target.value === 0) {
this.data[3][4].show = true;
} else {
this.data[3][4].show = false;
}
}
},
onTimeChange(time, name) {
const chooseTime = this.$moment(time).format('x');
this.options[name] = chooseTime;
},
handleSelectChange(value, name) {
console.log('value, name: ', value, name);
console.log('name', name === 'pathway' && value === '其他');
if (name === 'inHospitalType') {
this.showOther = false;
this.options[name] = value[value.length - 1];
} else if (name === 'pathway' && value === '其他') {
this.showOther = true;
} else {
this.showOther = false;
this.options[name] = value;
}
},
onPathwayChange(e, name) {
console.log('e, name: ', e.target.value, name);
this.options['pathway'] = e.target.value;
},
handleChange(info) {
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
this.$message.success(`${info.file.name} file uploaded successfully`);
} else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} file upload failed.`);
}
},
//
async submit() {
try {
this.loading = true;
const param = this.options;
const params = { param };
params.param.valueType = this.valueType;
const res = await createCase(params);
this.loading = false;
const { code, data, msg } = res.data;
if (code === 200) {
this.$message.success('创建成功');
location.href = `http://www.tall.wiki/tall/v3.0.0/#/?u=${this.userId}&p=${data.projectId}`;
} else {
this.$message.error(msg || '创建失败');
}
} catch (error) {
this.loading = false;
console.log('error: ', error);
}
},
//
openChoice() {
this.$router.push('/choice');
this.setTitleIcon([]);
},
},
};
</script>
<style scoped>
.ant-list-item >>> input {
outline: none;
border: none;
text-align: right;
}
.ant-calendar-picker >>> input {
padding-right: 34px;
}
.ant-select >>> .ant-select-selection {
border: none;
}
.ant-select >>> .ant-select-selection__placeholder,
.ant-select-search__field__placeholder {
text-align: right;
}
.ant-select >>> .ant-select-selection-selected-value {
width: 100%;
text-align: right;
padding-right: 11px;
}
.ant-cascader-picker >>> .ant-cascader-input.ant-input {
padding-right: 35px;
}
.ant-cascader-picker >>> .ant-cascader-picker-label {
text-align: right;
padding-right: 35px;
}
.yan {
position: fixed;
right: 0;
top: 50%;
}
</style>

117
src/views/AddPatient/config.js

@ -0,0 +1,117 @@
export const data = [
[{ title: '身份信息', name: 'idcardInfo', type: 'photo', show: true }],
[
{ title: '姓名', name: 'name', type: 'text', required: true, show: true },
{ title: '性别', name: 'gender', type: 'gender', required: true, show: true },
{ title: '年龄', name: 'age', type: 'heath', required: true, show: true },
{
title: '民族',
name: 'nation',
type: 'select',
show: true,
lists: [
{ id: '汉族', value: '汉族' },
{ id: '蒙古族', value: '蒙古族' },
{ id: '回族', value: '回族' },
{ id: '藏族', value: '藏族' },
{ id: '维吾尔族', value: '维吾尔族' },
{ id: '苗族', value: '苗族' },
{ id: '彝族', value: '彝族' },
{ id: '壮族', value: '壮族' },
{ id: '布依族', value: '布依族' },
{ id: '朝鲜族', value: '朝鲜族' },
{ id: '满族', value: '满族' },
{ id: '侗族', value: '侗族' },
{ id: '瑶族', value: '瑶族' },
{ id: '白族', value: '白族' },
{ id: '土家族', value: '土家族' },
{ id: '哈尼族', value: '哈尼族' },
{ id: '哈萨克族', value: '哈萨克族' },
{ id: '傣族', value: '傣族' },
{ id: '黎族', value: '黎族' },
{ id: '傈僳族', value: '傈僳族' },
{ id: '佤族', value: '佤族' },
{ id: '畲族', value: '畲族' },
{ id: '高山族', value: '高山族' },
{ id: '拉祜族', value: '拉祜族' },
{ id: '水族', value: '水族' },
{ id: '东乡族', value: '东乡族' },
{ id: '纳西族', value: '纳西族' },
{ id: '景颇族', value: '景颇族' },
{ id: '柯尔克孜族', value: '柯尔克孜族' },
{ id: '土族', value: '土族' },
{ id: '达斡尔族', value: '达斡尔族' },
{ id: '仫佬族', value: '仫佬族' },
{ id: '羌族', value: '羌族' },
{ id: '布朗族', value: '布朗族' },
{ id: '撒拉族', value: '撒拉族' },
{ id: '毛南族', value: '毛南族' },
{ id: '仡佬族', value: '仡佬族' },
{ id: '锡伯族', value: '锡伯族' },
{ id: '阿昌族', value: '阿昌族' },
{ id: '普米族', value: '普米族' },
{ id: '塔吉克族', value: '塔吉克族' },
{ id: '怒族', value: '怒族' },
{ id: '乌孜别克族', value: '乌孜别克族' },
{ id: '俄罗斯族', value: '俄罗斯族' },
{ id: '鄂温克族', value: '鄂温克族' },
{ id: '德昂族', value: '德昂族' },
{ id: '保安族', value: '保安族' },
{ id: '裕固族', value: '裕固族' },
{ id: '京族', value: '京族' },
{ id: '塔塔尔族', value: '塔塔尔族' },
{ id: '独龙族', value: '独龙族' },
{ id: '鄂伦春族', value: '鄂伦春族' },
{ id: '赫哲族', value: '赫哲族' },
{ id: '门巴族', value: '门巴族' },
{ id: '珞巴族', value: '珞巴族' },
{ id: '基诺族', value: '基诺族' },
],
}, // 民族
{ title: '证件号', name: 'idcard', type: 'text', show: true },
{ title: '住院号', name: 'medicalRecordNum', type: 'text', show: true },
],
[
{ title: '联系电话', name: 'phone', type: 'heath', show: true },
{ title: '亲属电话', name: 'kinsfolkPhone', type: 'heath', show: true },
],
[
{ title: '发病时间类型', name: 'timeType', type: 'timeType', show: true },
{ title: '发病时间', name: 'time', type: 'time', show: true },
{ title: '最后正常时间', name: 'lastNormalTime', type: 'lastNormalTime', show: false },
{ title: '是否在院内卒中', name: 'hospitalStroke', type: 'radio', show: true },
{ title: '到院时间', name: 'arriveHospitalTime', type: 'arriveTime', show: true },
{ title: '住院时间', name: 'hospitalizedTime', type: 'inspect', show: true },
{
title: '入院途径',
name: 'pathway',
type: 'pathway',
lists: [
{ id: '急诊', value: '急诊' },
{ id: '门诊', value: '门诊' },
{ id: '其他医疗机构转入', value: '其他医疗机构转入' },
{ id: '其他', value: '其他' },
],
show: true,
},
{
title: '来院方式',
name: 'inHospitalType',
type: 'inHospitalType',
lists: [
{ value: 1, label: '本院急救车' },
{ value: 2, label: '当地120' },
{
value: 7,
label: '外院转院',
children: [
{ value: 3, label: '网络协作医院' },
{ value: 4, label: '非网络协作医院' },
],
},
{ value: 5, label: '自行来院' },
],
show: true,
},
],
];

307
src/views/Assess/Assess.vue

@ -0,0 +1,307 @@
<template>
<div class="d-flex flex-column pb-10">
<div class="tow mb-3" v-for="(index, indexa) in information" :key="indexa">
<a-list item-layout="horizontal" class="white" :data-source="index">
<a-list-item class="mx-3" slot="renderItem" slot-scope="item">
<div class="d-flex flex-nowrap align-center" style="width: 100%">
<div class="mr-3">{{ item.title }}</div>
<div class="flex-1 flex-row-reverse">
<span
v-if="item.type === 'heath'"
class="pr-3"
@click="
openNumKey(
item.title.split(' ')[0],
item.title.split(' ')[1],
record[`${item.name}`] && record[`${item.name}`].length ? record[`${item.name}`][0] : '',
item.name,
)
"
>
{{ item.value || (record[`${item.name}`] && record[`${item.name}`].length ? record[`${item.name}`][0] : '') }}
</span>
<div v-else-if="item.type === 'heaths'" type="number" class="pr-3">
{{ weight && height ? (weight / (height * height)).toFixed(2) : 0 }}
</div>
<div v-else-if="item.type === 'radio'">
<a-radio-group
:default-value="record[`${item.name}`] && record[`${item.name}`].length ? record[`${item.name}`][0] : ''"
:key="record[`${item.name}`] && record[`${item.name}`].length ? record[`${item.name}`][0] : ''"
@change="onChange($event, item.name)"
class="d-flex flex-nowrap"
>
<a-radio :style="radioStyle" value="0" class="flex-1"> </a-radio>
<a-radio :style="radioStyle" value="1" class="flex-1"> </a-radio>
</a-radio-group>
<div v-if="show" class="mt-3">
洼田饮水试验
<a-input
@click="showModel = true"
style="width: 50px; border-bottom: 1px solid #666; border-radius: 0"
type="text"
:value="currentValue"
/>
</div>
</div>
<a-checkbox-group
v-else-if="item.type === 'radios'"
v-model="checkedList"
:options="plainOptions"
@change="onCheckChange($event, item.name)"
/>
</div>
</div>
</a-list-item>
</a-list>
</div>
<test-model v-if="showModel" :lists="lists" :current-value="currentValue" @closeModel="closeModel"></test-model>
<num-key
v-if="showNumModel"
:title="title"
:unit="unit"
:num-value="numValue"
:type="type"
@closeNumModel="closeNumModel"
@changeValue="changeValue"
/>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { information } from './config';
import { queryAidRecord, aidRecord } from 'config/api';
import TestModel from '@/components/TestModel/TestModel.vue';
import NumKey from '../../components/NumKey/NumKey.vue';
export default {
components: { TestModel, NumKey },
data() {
return {
information,
current: 0,
radioStyle: {
display: 'block',
height: '30px',
lineHeight: '30px',
},
plainOptions: ['糖尿病', '高血压'],
checkedList: [],
show: false,
record: {},
headers: { authorization: 'authorization-text' },
options: {
answer: '',
questionCode: '',
},
height: 0,
weight: 0,
info: {
RYPGheight: 0,
RYPGweight: 0,
RYPGsystolicPressure: 0,
RYPGdiastolicPressure: 0,
RYPGpulse: 0,
RYPGbloodGlucose: 0,
RYPGmRSScore: 0,
RYPGNIHSSScore: 0,
RYPGswallowingFunction: 0,
RYPGmedicalHistory: 0,
},
lists: ['1', '2', '3', '4', '5', '未评'],
showModel: false,
currentValue: '',
numValue: '0',
title: '',
unit: '',
type: '',
showNumModel: false,
};
},
computed: mapState('home', ['ptProps']),
created() {
this.setTitle('入院评估');
this.getQuery();
},
methods: {
...mapMutations('home', ['setTitle']),
//
openNumKey(title, unit, value, name) {
this.title = title;
this.unit = unit;
this.type = name;
this.numValue = value;
this.showNumModel = true;
},
//
closeNumModel() {
this.showNumModel = false;
},
//
changeValue(value, name) {
this.showNumModel = false;
if (name === 'RYPG-height') {
this.height = value / 100 - 0;
}
if (name === 'RYPG-weight') {
this.weight = value - 0;
}
//
for (var i = 0; i < this.information.length; i++) {
const item = this.information[i];
for (var j = 0; j < item.length; j++) {
if (item[j].name === name) {
item[j].value = value;
}
}
}
this.options = {};
this.options.answer = [value];
this.options.questionCode = name;
this.submit(this.options);
},
onChange(e, name) {
if (name === 'RYPG-swallowingFunction') {
if (e.target.value === '0') {
this.show = false;
} else {
this.show = true;
}
}
this.options = {};
this.options.answer = [e.target.value];
this.options.questionCode = name;
this.submit(this.options);
},
onCheckChange(value, name) {
this.options = {};
this.options.answer = value;
this.options.questionCode = name;
this.submit(this.options);
},
//
closeModel(i) {
this.showModel = false;
if (i) {
this.currentValue = this.lists[i];
this.options = {};
this.options.answer = [this.lists[i]];
this.options.questionCode = 'RYPG-test';
this.submit(this.options);
}
},
/**
* 批量查询急救信息
* @param { Array } codeList code列表
* @param { String } projectId 项目id
*/
async getQuery() {
try {
const params = {
param: {
codeList: [
'RYPG-height',
'RYPG-weight',
'RYPG-weight',
'RYPG-systolicPressure',
'RYPG-diastolicPressure',
'RYPG-pulse',
'RYPG-bloodGlucose',
'RYPG-mRSScore',
'RYPG-NIHSSScore',
'RYPG-swallowingFunction',
'RYPG-medicalHistory',
'RYPG-test',
],
projectId: this.ptProps.projectId,
},
};
const res = await queryAidRecord(params);
const { code, data, msg } = res.data;
if (code === 200) {
this.record = data.record;
// BMI
if (this.record['RYPG-height']) {
this.height = this.record['RYPG-height'] / 100 - 0;
}
if (this.record['RYPG-weight']) {
this.weight = this.record['RYPG-weight'] - 0;
}
if (this.record['RYPG-medicalHistory']) {
this.checkedList = this.record['RYPG-medicalHistory'];
}
if (this.record['RYPG-test'] && this.record['RYPG-swallowingFunction'] && this.record['RYPG-swallowingFunction'] === '1') {
this.show = true;
this.currentValue = this.record['RYPG-test'];
}
//
} else {
this.$message.error(msg || '查询失败');
}
} catch (error) {
console.log('error: ', error);
}
},
/**
* 提交信息
* @param { Array } codeAndAnswerList code和答案
* @param { String } projectId 项目id
* @param { Number } userType 提交人类型0平车 1
*/
async submit(options) {
try {
const params = {
param: {
codeAndAnswerList: [options],
projectId: this.ptProps.projectId,
userType: 0,
},
};
const res = await aidRecord(params);
const { code, data, msg } = res.data;
if (code === 200) {
} else {
this.$message.error(msg || '提交失败');
}
} catch (error) {
console.log('error: ', error);
}
},
},
};
</script>
<style scoped>
.ant-list-item >>> input {
outline: none;
border: none;
text-align: right;
}
.ant-calendar-picker >>> input {
padding-right: 34px;
}
.ant-select >>> .ant-select-selection {
border: none;
}
.ant-select >>> .ant-select-selection__placeholder,
.ant-select-search__field__placeholder {
text-align: right;
}
</style>

19
src/views/Assess/config.js

@ -0,0 +1,19 @@
export const information = [
[
{ title: '身高 cm', name: 'RYPG-height', type: 'heath', value: '' },
{ title: '体重 kg', name: 'RYPG-weight', type: 'heath', value: '' },
{ title: 'BMI(系统自动计算)', name: 'RYPG-bmi', type: 'heaths', value: '' },
],
[
{ title: '收缩压 mmHg', name: 'RYPG-systolicPressure', type: 'heath', value: '' },
{ title: '舒张压 mmHg', name: 'RYPG-diastolicPressure', type: 'heath', value: '' },
{ title: '脉搏 次/分', name: 'RYPG-pulse', type: 'heath', value: '' },
{ title: '快速血糖 mmol/L', name: 'RYPG-bloodGlucose', type: 'heath', value: '' },
],
[
{ title: '本次入院mRS评分', name: 'RYPG-mRSScore', type: 'heath', value: '' },
{ title: '本次入院NIHSS评分', name: 'RYPG-NIHSSScore', type: 'heath', value: '' },
{ title: '吞咽功能', name: 'RYPG-swallowingFunction', type: 'radio', value: null },
],
[{ title: '既往病史', name: 'RYPG-medicalHistory', type: 'radios' }],
];

296
src/views/Choice/Choice.vue

@ -0,0 +1,296 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:07:17
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 23:57:56
-->
<template>
<div class="d-flex flex-wrap flex-column">
<div v-if="showInfo">
<a-card class="fill-width" style="position: relative">
<div slot="title" class="d-flex align-center">
<span> 选择平车 </span>
<div class="flex-1 justify-center">
<a-button type="primary" v-if="everCar && everCar.carSerial" @click="showInfo = false">查看平车信息</a-button>
</div>
<a-icon type="undo" class="title-icon" @click="getCar" />
</div>
<a-spin tip="正在重新获取平车数据..." :spinning="spinning">
<a-radio-group class="d-flex flex-column" v-if="list.length" @change="choiceCar">
<div v-for="item in list" :key="item.id" class="radio-box d-flex">
<a-radio :key="item.id" class="radio-item" :value="item.id">
{{ item.serial }}
</a-radio>
<div class="radio-name" v-if="item.patientName">已绑定</div>
</div>
</a-radio-group>
<a-empty v-else description="暂时没有平车数据" />
</a-spin>
</a-card>
<a-card class="fill-width mt-1">
<div slot="title" class="d-flex align-center">
<span class="flex-1"> 选择时间 </span>
</div>
<div class="d-flex align-center">
<div class="flex-1">开始时间</div>
<a-date-picker
class="mr-2"
:default-value="$moment(startTime)"
format="YYYY-MM-DD HH:mm"
:show-time="{ format: 'HH:mm' }"
placeholder="开始时间"
@change="changeStart"
/>
</div>
<div class="d-flex align-center mt-2">
<div class="flex-1">结束时间</div>
<a-date-picker
class="mr-2"
format="YYYY-MM-DD HH:mm"
:show-time="{ format: 'HH:mm' }"
placeholder="结束时间"
@change="changeEnd"
/>
</div>
</a-card>
<a-button v-if="carInfo !== null" class="mt-2 mb-4" style="height: 40px" type="primary" block @click="suspend"> 提交 </a-button>
<a-modal v-model="visible" title="提示" @ok="submitCar">
<p v-if="carInfo">
此平车已绑定病人
<!-- <span class="name-box" @click="changePro(carInfo.projectId)">{{ carInfo.name }}(点击查看详情)</span> -->
<br />
确定换绑吗
</p>
</a-modal>
</div>
<div v-else>
<a-card style="padding: 0 12px">
<div class="align-center d-flex flex-row flex-nowrap justify-space-between">
<div class="title-box">患者{{ everCar.name }}</div>
<div class="title-box" v-if="everCar && everCar.startTime">{{ $moment(+everCar.startTime).format('MM-DD HH:mm') }}</div>
<div class="car-box" @click="showInfo = true">卒中专用平车{{ everCar.carNumber }}</div>
</div>
</a-card>
<a-card class="mt-1 fill-width">
<!-- <process :list="infoList" class="my-4" /> -->
<img class="fill-width" src="https://www.tall.wiki/staticrec/photos/step.png" />
</a-card>
<a-card class="mt-1">
<data-table :list="infoList" />
</a-card>
<a-card class="mt-1">
<!-- <analysis /> -->
<img class="fill-width" src="https://www.tall.wiki/staticrec/photos/step-echart.png" />
</a-card>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { bindingCar, queryBindingCar, queryAllCar, switchProject, findStepIsOver, endCar } from 'config/api';
// import Analysis from './../Index/components/Analysis.vue';
import DataTable from './../Index/components/DataTable.vue';
// import Process from './../Index/components/Process.vue';
export default {
name: 'Choice',
components: { DataTable },
data() {
return {
spinning: false,
list: [],
startTime: Date.parse(new Date()),
endTime: 0,
id: 0,
carInfo: null,
oldChoiceCar: [],
visible: false,
infoList: [],
everCar: null,
showInfo: true,
};
},
computed: mapState('home', ['ptProps']),
created() {
this.getChoice();
this.getCar();
this.setTitle('选择平车');
},
methods: {
...mapMutations('home', ['setTitle']),
choiceCar(e) {
let { list } = this;
// this.id = e.target.value;
const index = list.findIndex(item => item.id === e.target.value);
this.carInfo = list[index];
},
async getCar() {
try {
const that = this;
that.spinning = true;
const params = { param: {} };
const res = await queryAllCar(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.list = [...data];
that.spinning = false;
} else {
that.spinning = false;
}
} catch (error) {
that.spinning = false;
}
},
suspend() {
const { carInfo } = this;
if (!carInfo) {
this.$message.warning('没有选择平车');
return;
} else if (carInfo.patientName) {
this.visible = true;
} else {
this.submitCar();
}
},
async submitCar() {
try {
// if (carInfo && carInfo.name) {
// const isEnd = await this.endCarData();
// if (!isEnd) {
// this.$message.warning('');
// return;
// }
// }
const { projectId } = this.ptProps;
const { carInfo, startTime, endTime } = this;
const params = {
param: {
carId: carInfo.id,
startTime,
projectId,
// taskSubId: id,
endTime,
},
};
const res = await bindingCar(params);
const { code } = res.data;
if (code === 200) {
this.$message.success('选择成功');
this.getChoice();
} else {
this.$message.warning(msg);
}
} catch (error) {
this.$message.warning('选择失败');
}
},
async endCarData() {
try {
const { patientCarId } = this.carInfo;
const params = { param: { id: patientCarId } };
const res = await endCar(params);
const { code, data } = res.data;
if (code === 200) {
return true;
} else {
return false;
}
} catch (error) {
return false;
}
},
changeStart(e) {
this.startTime = e._i;
},
changeEnd(e) {
this.endTime = e._i;
},
async getChoice() {
try {
// const params = { param: { taskSubId: '1400297464451436544' } };
const params = { param: { projectId: this.ptProps.projectId } };
const res = await queryBindingCar(params);
const { code, data } = res.data;
if (code === 200) {
this.everCar = data;
this.getList(data);
this.showInfo = false;
}
} catch (error) {}
},
async changePro(projectId) {
try {
const params = { param: { projectId } };
await switchProject(params);
} catch (error) {}
},
async getList() {
try {
const { projectId } = this.ptProps;
const params = { param: { projectId } };
const res = await findStepIsOver(params);
const { code, data } = res.data;
if (code === 200) {
this.infoList = data;
}
} catch (error) {}
},
},
};
</script>
<style lang="stylus" scoped>
/deep/.ant-spin-spinning {
background: rgba(0, 0, 0, 0.15);
}
// /deep/ .ant-radio {
// margin: 12px 0;
// }
.name-box {
color: green;
}
.radio-box {
background-color: rgb(239, 247, 250);
margin-bottom: 10px;
border: 1px dashed rgba(24, 144, 255, 0.2);
border-radius: 5px;
padding-left: 10px;
}
.radio-name {
height: 40px;
line-height: 40px;
width: 40%;
text-align: center;
color: green;
}
.radio-item {
display: 'block';
height: 40px;
line-height: 40px;
width: 60%;
}
.title-icon {
color: rgba(24, 144, 255, 0.5);
font-size: 20px;
}
.car-box {
background-color: #49cc90;
color: #fff;
padding: 0 8px;
font-weight: 500;
height: 32px;
line-height: 32px;
border-radius: 10px;
}
</style>

106
src/views/Choice/Patient.vue

@ -0,0 +1,106 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-03 18:26:42
* @LastEditors: aBin
* @LastEditTime: 2021-06-11 16:15:23
-->
<template>
<div class="d-flex flex-column">
<div class="flex-1" v-if="list && list.length">
<a-table
:columns="columns"
:pagination="false"
:data-source="list"
:row-key="record => record.id"
bordered
class="white pa-3 fill-width"
>
<template slot="id" slot-scope="text, record, index">
<span>{{ index + 1 }}</span>
</template>
<template slot="sex" slot-scope="text, record">
<span v-if="record.sex === 0"></span>
<span v-else></span>
</template>
<template slot="edit" slot-scope="text, record">
<span style="color: #1890ff; font-weight: 600" @click="changePro(record.projectId)">查看</span>
</template>
</a-table>
</div>
<a-empty v-else />
</div>
</template>
<script>
import { mapMutations } from 'vuex';
import { findOldPatient, switchProject } from 'config/api';
const columns = [
{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
scopedSlots: { customRender: 'id' },
},
{
title: '姓名',
align: 'center',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
align: 'center',
dataIndex: 'age',
key: 'age',
},
{
title: '性别',
align: 'center',
dataIndex: 'sex',
key: 'sex',
scopedSlots: { customRender: 'sex' },
},
{
title: '操作',
align: 'center',
dataIndex: 'edit',
key: 'edit',
scopedSlots: { customRender: 'edit' },
},
];
export default {
name: 'Patient',
data() {
return {
columns,
list: [],
};
},
created() {
this.getData();
this.setTitle('患者表格');
},
methods: {
...mapMutations('home', ['setTitle']),
async getData() {
try {
const params = { param: {} };
const res = await findOldPatient(params);
const { code, data } = res.data;
if (code === 200) {
this.list = data;
}
} catch (error) {}
},
async changePro(projectId) {
try {
const params = { param: { projectId } };
await switchProject(params);
} catch (error) {}
},
},
};
</script>

244
src/views/Control/Control.vue

@ -0,0 +1,244 @@
<template>
<div class="d-flex flex-column">
<div class="tips d-flex justify-space-between align-center px-2">
<div class="d-flex">时间单位min</div>
<div class="d-flex flex-row align-center">
<div class="yuanquan bg-green mr-1"></div>
标准范围事件
</div>
<div class="d-flex flex-row align-center">
<div class="yuanquan bg-red mr-1"></div>
超出参考时间
</div>
</div>
<Table :table-list="tableList" />
<TimeLine :line-list="lineList" />
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex';
import { getControl, queryByProject, queryAidRecord } from 'config/api';
import Table from './components/Table.vue';
import TimeLine from './components/TimeLine.vue';
export default {
name: 'Control',
components: { Table, TimeLine },
data() {
return {
tableList: [
{
time: 35,
scope: 'ONT',
beyond: '发病-溶栓',
},
{
time: 40,
scope: 'DNT',
beyond: '到院-溶栓',
},
{
time: 55,
scope: 'OPT',
beyond: '发病-穿刺',
},
{
time: 50,
scope: 'DPT',
beyond: '到院-穿刺',
},
{
time: 48,
scope: 'DRT',
beyond: '到院-再通',
},
],
lineList: [
{
codeT: '就诊时间',
valueT: 0,
codeB: 'CT完成时间',
valueB: 0,
},
{
codeT: 'CT完成时间',
valueT: 0,
codeB: '溶栓开始知情',
valueB: 0,
},
{
codeT: '就诊时间',
valueT: 0,
codeB: 'CT完成时间',
valueB: 0,
},
{
codeT: '溶栓开始知情',
valueT: 0,
codeB: '溶栓签署知情',
valueB: 0,
},
{
codeT: '就诊时间',
valueT: 0,
codeB: '溶栓签署知情',
valueB: 0,
},
{
codeT: '第一次医疗接触时间',
valueT: 0,
codeB: '溶栓开始时间',
valueB: 0,
},
{
codeT: '就诊时间',
valueT: 0,
codeB: '溶栓开始时间',
valueB: 0,
},
{
codeT: '最后正常时间',
valueT: 0,
codeB: '溶栓开始时间',
valueB: 0,
},
{
codeT: '血管内治疗开始知情',
valueT: 0,
codeB: '血管内治疗签署知情',
valueB: 0,
},
{
codeT: '血管内治疗签署知情',
valueT: 0,
codeB: '穿刺时间',
valueB: 0,
},
{
codeT: '穿刺时间',
valueT: 0,
codeB: '造影完成',
valueB: 0,
},
{
codeT: '穿刺时间',
valueT: 0,
codeB: '血管再通时间',
valueB: 0,
},
{
codeT: '发病时间',
valueT: 0,
codeB: '到达医院大门时间',
valueB: 0,
},
{
codeT: '到达医院大门时间',
valueT: 0,
codeB: '穿刺时间',
valueB: 0,
},
],
};
},
computed: { ...mapState('home', ['ptProps']) },
async created() {
this.setTitle('质控');
// this.getControlData();
await this.getLineData();
await this.getRecord();
},
methods: {
...mapMutations('home', ['setTitle']),
async getControlData() {
try {
const params = { param: {} };
const res = await getControl(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.tableList = data;
} else {
console.log(msg);
}
} catch (error) {
console.log(error);
}
},
// code
async getRecord() {
try {
const { projectId } = this.ptProps;
const { lineList } = this;
const params = {
param: {
codeList: ['YJJL-CTendTime', 'ZQTH-THSJ', 'ZQTH-ZQSJ', 'JMRSSJ', 'JRZL-CCSJ', 'JRZL-ZCKT'],
projectId,
},
};
const res = await queryAidRecord(params);
const { code, msg, data } = res.data;
if (code === 200) {
lineList[0].valueB = data.record['YJJL-CTendTime'][0];
lineList[1].valueT = data.record['YJJL-CTendTime'][0];
lineList[1].valueB = data.record['ZQTH-THSJ'][0];
lineList[2].valueB = data.record['YJJL-CTendTime'][0];
lineList[3].valueT = data.record['ZQTH-THSJ'][0];
lineList[3].valueB = data.record['ZQTH-ZQSJ'][0];
lineList[4].valueB = data.record['ZQTH-ZQSJ'][0];
lineList[5].valueB = data.record['JMRSSJ'][0];
lineList[6].valueB = data.record['ZQTH-ZQSJ'][0];
lineList[7].valueB = data.record['ZQTH-ZQSJ'][0];
lineList[9].valueB = data.record['JRZL-CCSJ'][0];
lineList[10].valueT = data.record['JRZL-CCSJ'][0];
lineList[11].valueT = data.record['JRZL-CCSJ'][0];
lineList[11].valueB = data.record['JRZL-ZCKT'][0];
lineList[13].valueB = data.record['JRZL-CCSJ'][0];
this.lineList = [...lineList];
} else {
this.$message.error(msg || '查询失败');
}
} catch (error) {}
},
// id
async getLineData() {
try {
const { projectId } = this.ptProps;
const { lineList } = this;
const params = { param: { projectId } };
const res = await queryByProject(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.lineList[0].valueT = data.arriveHospitalTime;
this.lineList[2].valueT = data.arriveHospitalTime;
this.lineList[4].valueT = data.arriveHospitalTime;
this.lineList[6].valueT = data.arriveHospitalTime;
this.lineList[12].valueT = data.lastNormalTime;
this.lineList[12].valueB = data.time;
this.lineList[13].valueT = data.time;
this.lineList = [...lineList];
} else {
this.$message.error(msg || '查询失败');
}
} catch (error) {}
},
},
};
</script>
<style lang="scss" scoped>
.tips {
height: 40px;
width: 100%;
color: rgba(0, 0, 0, 0.85);
}
.yuanquan {
height: 16px;
width: 16px;
border-radius: 50%;
}
.bg-red {
background-color: rgba(255, 0, 0, 0.85);
}
.bg-green {
background-color: #7ed321;
}
</style>

38
src/views/Control/components/Table.vue

@ -0,0 +1,38 @@
<template>
<div class="bg-white">
<a-list item-layout="horizontal" :data-source="tableList">
<a-list-item slot="renderItem" slot-scope="item, index" :class="index % 2 === 1 ? 'bg-green' : ''">
<div class="d-flex justify-space-between align-center fill-width" style="padding: 0 20px">
<div>{{ item.time }}</div>
<div>{{ item.scope }}</div>
<div>{{ item.beyond }}</div>
</div>
</a-list-item>
</a-list>
</div>
</template>
<script>
export default {
name: 'Table',
props: {
tableList: {
default: () => [],
type: Array,
},
},
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.bg-white {
background-color: white;
}
.bg-green {
background-color: rgba(126, 211, 33, 0.15);
}
.ant-list-item {
padding: 8px 0;
}
</style>

79
src/views/Control/components/TimeLine.vue

@ -0,0 +1,79 @@
<template>
<div class="bg-white mt-2" style="padding-top: 4px">
<div v-for="(item, index) in lineList" :key="index" class="d-flex flex-row">
<div style="width: 40px d-flex flex-row">
<div class="yuanquan"></div>
<div class="line"></div>
</div>
<div class="mt-1 ml-2 flex-1" style="padding-right: 10px">
<a-card size="small" class="fill-width">
<div class="d-flex flex-column">
<div class="flex-1 flex-column">
<div class="title-code">{{ item.codeT }}</div>
<div class="title-value d-flex align-center">
<div class="flex-1">
{{ item.valueT ? $moment(+item.valueT).format('YYYY-MM-DD HH:mm') : '...' }}
</div>
<div class="align-center">时长</div>
<div class="align-center" style="font-size: 24px; font-weight: 600">
{{ item.valueT && item.valueB ? ((item.valueB - item.valueT) / 1000 / 60).toFixed(0) : 0 }}
</div>
</div>
</div>
<div class="flex-1 flex-column">
<div class="title-code">{{ item.codeB }}</div>
<div class="title-value d-flex align-center">
<div class="flex-1">
{{ item.valueB ? $moment(+item.valueB).format('YYYY-MM-DD HH:mm') : '...' }}
</div>
<div class="align-center">参考</div>
<div class="align-center">-min</div>
</div>
</div>
</div>
</a-card>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'TimeLine',
props: {
lineList: {
default: () => [],
type: Array,
},
},
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.bg-white {
background-color: white;
}
.yuanquan {
margin-left: 12px;
height: 16px;
width: 16px;
border-radius: 50%;
background: #7ed321;
margin-top: 4px;
}
.line {
width: 20px;
height: 82%;
border-right: 1px solid #7ed321;
margin-bottom: 2px;
}
.title-code {
font-size: 16px;
font-weight: bold;
}
.title-value {
font-size: 14px;
margin-bottom: 4px;
}
</style>

58
src/views/Currency/Currency.vue

@ -0,0 +1,58 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:07:56
* @LastEditors: aBin
* @LastEditTime: 2021-06-10 14:23:36
-->
<template>
<div class="d-flex flex-wrap flex-column">
<a-card class="fill-width">
<div class="d-flex flex-nowrap">
<div class="flex-1">
<a-date-picker
:value="$moment(time)"
:show-time="{ format: 'HH:mm' }"
format="YYYY-MM-DD HH:mm"
placeholder="选择时间"
style="width: 100%"
@change="onChange"
@ok="onChange"
/>
</div>
<!-- <a-button v-if="isShow" style="width: 100px" type="primary" block @click="start"> 开始 </a-button> -->
</div>
</a-card>
<Content :time="time" />
</div>
</template>
<script>
import { mapActions, mapMutations } from 'vuex';
import Content from 'components/Content/Content.vue';
export default {
name: 'Currency',
components: { Content },
data() {
return { time: Date.parse(new Date()), isShow: false };
},
async created() {
const start = await this.getStart();
if (start) {
this.time = +start;
}
this.setTitle('通用界面');
},
methods: {
...mapActions('home', ['getStart']),
...mapMutations('home', ['setTitle']),
onChange(e) {
let str = this.$moment(e._d).format('YYYY-MM-DD HH:mm');
str += ':00';
this.time = new Date(str).valueOf();
},
},
};
</script>
<style lang="stylus" scoped></style>

156
src/views/Diagnosis/Diagnosis.vue

@ -0,0 +1,156 @@
<template>
<div class="d-flex flex-column">
<div class="bg-white title d-flex align-center pl-4" style="height: 44px">山西医科大学第一医院</div>
<a-collapse default-active-key="1" @change="changeActivekey">
<a-collapse-panel key="1" header="神经内科">
<div class="d-flex flex-wrap">
<div class="duty-box" v-for="(item, index) in list1" :key="index">
<img class="duty-img" src="./png/duty.png" />
<div v-if="item.onDutyStatus" class="duty-isDuty">值班</div>
<div class="duty-name">{{ item.name }}</div>
<a class="duty-tel" :href="'tel:' + item.phone">
<img class="tel-img" src="./png/tel.png" />
呼叫
</a>
</div>
</div>
</a-collapse-panel>
<a-collapse-panel key="2" header="急诊科">
<div class="d-flex flex-wrap">
<div class="duty-box" v-for="(item, index) in list2" :key="index">
<img class="duty-img" src="./png/duty.png" />
<div v-if="item.onDutyStatus" class="duty-isDuty">值班</div>
<div class="duty-name">{{ item.name }}</div>
<a class="duty-tel" :href="'tel:' + item.phone">
<img class="tel-img" src="./png/tel.png" />
呼叫
</a>
</div>
</div>
</a-collapse-panel>
</a-collapse>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
import { queryAllDoctor } from 'config/api';
export default {
name: 'Diagnosis',
data() {
return {
list: [
{
name: '传小控',
isDuty: true,
tel: 1234657890,
},
{
name: '传小控',
isDuty: true,
tel: 1234657890,
},
{
name: '传小控',
isDuty: false,
tel: 1234657890,
},
{
name: '传小控',
isDuty: false,
tel: 1234657890,
},
],
list1: [],
list2: [],
};
},
created() {
this.getDoctor();
this.setTitle('会诊');
},
methods: {
...mapMutations('home', ['setTitle']),
changeActivekey(key) {
console.log('key: ', key);
},
async getDoctor() {
try {
const params = { param: {} };
const res = await queryAllDoctor(params);
// console.log('res: ', res);
// console.log('res.data: ', res.data);
const { code, msg, data } = res.data;
if (code === 200) {
console.log(data);
this.list1 = data['1'];
this.list2 = data['2'];
} else {
console.log(msg);
}
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style lang="scss" scoped>
.bg-white {
background-color: #fff;
}
.title {
border-bottom: 1px solid #ddd;
}
.duty-box {
height: 140px;
width: 30%;
margin: 5px 1.65%;
position: relative;
border-radius: 5px;
border: 1px solid #ccc;
box-shadow: 1px 0 0 -1px #ccc;
}
.duty-img {
position: absolute;
top: 30px;
height: 50px;
width: 50px;
margin-left: 50%;
left: -25px;
}
.duty-isDuty {
background-color: #4b8aff;
position: absolute;
font-size: 12px;
padding: 1px 4px;
color: #fff;
border-radius: 0 5px 0 8px;
right: 0;
top: 0;
}
.duty-name {
width: 60px;
position: absolute;
margin-left: 50%;
left: -30px;
top: 64%;
font-weight: bold;
text-align: center;
}
.duty-tel {
position: absolute;
bottom: 0;
width: 101%;
border-radius: 0 0 5px 5px;
height: 26px;
line-height: 26px;
text-align: center;
color: #fff;
background-color: #4b8aff;
}
.tel-img {
height: 16px;
margin: -4px 4px 0 0;
}
</style>

BIN
src/views/Diagnosis/png/duty.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/views/Diagnosis/png/tel.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

51
src/views/Establish/Assessment.vue

@ -0,0 +1,51 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 19:54:26
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 20:48:29
-->
<template>
<div class="d-flex flex-column">
<a-card title="流行病学史" class="fill-width mt-1">
<a-list item-layout="horizontal">
<a-list-item class="d-flex flex-nowrap">
<div>发病前14天内有无---</div>
<a-switch />
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>发病前14天内有无---</div>
<a-switch />
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>发病前14天内有无---</div>
<a-switch />
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>有聚集性发病</div>
<a-switch />
</a-list-item>
</a-list>
</a-card>
<a-card title="临床症状" class="fill-width mt-1">
<a-list item-layout="horizontal">
<a-list-item class="d-flex flex-nowrap">
<div>发热/呼吸道症状</div>
<a-switch />
</a-list-item>
</a-list>
</a-card>
<a-button class="mt-2 mb-4" style="height: 40px" type="primary" block> 提交 </a-button>
</div>
</template>
<script>
export default {
name: 'Assessment',
data() {
return {};
},
};
</script>
<style lang="stylus" scoped></style>

331
src/views/Establish/Establish.vue

@ -0,0 +1,331 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:06:14
* @LastEditors: aBin
* @LastEditTime: 2021-06-10 14:32:31
-->
<template>
<div class="d-flex flex-wrap flex-column">
<a-spin :spinning="spinning" tip="正在努力创建病例...">
<a-card class="fill-width">
<div slot="title" style="color: rgba(76, 115, 177, 0.9)">基本信息填写</div>
<a-list item-layout="horizontal" :data-source="list">
<a-list-item slot="renderItem" slot-scope="item" class="d-flex flex-nowrap">
<div>
{{ item.title }}
<span v-if="item.isTrue" style="color: red">*</span>
</div>
<div v-if="item.type === 'card'">
<a-upload
name="part"
style="width: 60%"
:headers="headers"
:multiple="false"
:action="action"
:default-file-list="fileList"
list-type="picture-card"
@change="handleChange"
>
<div v-if="fileList.length < 1 && !isUpload">
<a-icon type="plus" />
<div class="ant-upload-text">上传身份证</div>
</div>
</a-upload>
</div>
<a-input v-model="item.value" v-else-if="item.type === 'ipt'" style="width: 60%" />
<a-input-number v-model="item.value" v-else-if="item.type === 'iptNum'" style="width: 60%" />
<a-radio-group v-model="patientSex" v-else-if="item.type === 'radio'" class="d-flex flex-nowrap" style="width: 60%">
<a-radio :style="radioStyle" :value="0" class="flex-1"> </a-radio>
<a-radio :style="radioStyle" :value="1" class="flex-1"> </a-radio>
</a-radio-group>
</a-list-item>
</a-list>
</a-card>
<a-card class="fill-width mt-1">
<a-list item-layout="horizontal">
<a-list-item @click="jump('/assessment')" class="d-flex flex-nowrap">
<div>新冠肺炎评估</div>
<a-icon type="right" />
</a-list-item>
<!-- <a-list-item class="d-flex flex-nowrap">
<div>病案号</div>
<span style="color: #999">001</span>
</a-list-item> -->
</a-list>
</a-card>
<a-button class="mt-2 mb-4" style="height: 40px" type="primary" block @click="setCase">
<span v-if="!patientId"> 创建病例 </span>
<span v-else> 修改信息 </span>
</a-button>
</a-spin>
<a-modal title="提示" :visible="visible" @ok="handleOk" @cancel="handleCancel">
<p>是否跳转到该病例的项目详情页?</p>
</a-modal>
</div>
<!-- action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
:headers="headers"
@change="handleChange" -->
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { createCase, identifyWords, queryPatientInfo, updatePatientInfo, switchProject } from 'config/api';
const list = [
{
title: '身份信息',
isTrue: true,
type: 'card',
},
{
title: '姓名',
isTrue: true,
type: 'ipt',
value: '',
name: 'name',
},
{
title: '性别',
isTrue: true,
type: 'radio',
},
{
title: '年龄',
isTrue: true,
type: 'iptNum',
value: '',
name: 'age',
},
{
title: '身份证号',
isTrue: false,
type: 'ipt',
value: '',
name: 'idCard',
},
{
title: '联系电话',
isTrue: false,
type: 'iptNum',
value: '',
name: 'phone',
},
{
title: '亲属姓名',
isTrue: false,
type: 'ipt',
value: '',
name: 'familyName',
},
{
title: '亲属电话',
isTrue: false,
type: 'iptNum',
value: '',
name: 'familyPhone',
},
];
export default {
name: 'Establish',
data() {
return {
list,
formLayout: 'horizontal',
form: this.$form.createForm(this, { name: 'Establish' }),
action: identifyWords,
radioStyle: {
display: 'block',
height: '30px',
lineHeight: '30px',
},
patientSex: 0,
fileList: [],
isUpload: false,
patientId: '',
visible: false,
projectId: '',
spinning: false,
};
},
computed: {
...mapState('home', ['ptProps']),
//
headers() {
const token = sessionStorage.getItem('anyringToken');
return { Authorization: `Bearer ${token}` };
},
},
created() {
// this.getPatientInfo();
this.setTitle('创建病例');
},
methods: {
...mapMutations('home', ['setTitle']),
jump(url) {
this.$router.push(url);
},
//
handleChange(info) {
const status = info.file.status;
if (status === 'uploading') {
this.isUpload = true;
}
if (status === 'done') {
// console.log(info);
const file = info.file;
const obj = {
uid: file.uid,
name: file.response.data.name,
status: status,
url: file.thumbUrl,
};
for (let i = 0; i < this.list.length; i++) {
if (list[i].name === 'idCard') {
list[i].value = file.response.data.idCardNo;
} else if (list[i].name === 'name') {
list[i].value = file.response.data.name;
} else if (list[i].name === 'age') {
list[i].value = file.response.data.age;
}
}
this.patientSex = file.response.data.sex;
this.fileList.push(obj);
} else if (status === 'removed') {
this.fileList = [];
this.isUpload = false;
}
},
//
async setCase() {
this.spinning = true;
console.log(this.patientId);
if (this.patientId) {
await this.updatePatientInfo();
this.spinning = false;
} else {
await this.addPatientInfo();
this.spinning = false;
}
},
async addPatientInfo() {
try {
const { patientSex } = this;
const params = {
param: {
familyName: this.getValue('familyName'),
familyPhone: this.getValue('familyPhone'),
patientAge: this.getValue('age'),
patientIdCard: this.getValue('idCard'),
patientName: this.getValue('name'),
patientPhone: this.getValue('phone'),
patientSex: patientSex,
},
};
const res = await createCase(params);
const { code, data } = res.data;
if (code === 200) {
this.$message.success('创建成功');
this.projectId = data.projectId;
this.visible = true;
} else {
this.$message.error('创建失败');
}
} catch (error) {}
},
//
getValue(str) {
const { list } = this;
return list.find(item => {
if (item.name && item.name === str) {
return item;
}
}).value;
},
async getPatientInfo() {
try {
const parmas = { param: { projectId: this.ptProps.projectId } };
const res = await queryPatientInfo(parmas);
const { code, msg, data } = res.data;
const { list } = this;
if (code === 200) {
console.log(data);
for (let i = 0; i < list.length; i++) {
for (let key in data) {
if (list[i].name === key) {
list[i].value = data[key];
}
}
}
this.patientSex = data.sex;
this.patientId = data.id;
this.list = [...list];
} else {
console.error(msg);
}
} catch (error) {
console.error(error);
}
},
async updatePatientInfo() {
try {
const { patientSex } = this;
const params = {
param: {
id: this.patientId,
familyName: this.getValue('familyName'),
familyPhone: this.getValue('familyPhone'),
age: this.getValue('age'),
idCard: this.getValue('idCard'),
name: this.getValue('name'),
phone: this.getValue('phone'),
sex: patientSex,
},
};
const res = await updatePatientInfo(params);
const { code, msg } = res.data;
if (code === 200) {
this.$message.success('修改成功');
} else {
this.$message.warning(msg);
}
} catch (error) {
console.error(error);
}
},
async handleOk() {
const { projectId } = this;
const params = { param: { projectId } };
const res = await switchProject(params);
const { code } = res.data;
if (code === 200) {
this.visible = false;
}
},
handleCancel() {
this.visible = false;
},
},
};
</script>
<style lang="stylus" scoped>
/deep/ .ant-card-body {
padding: 12px;
}
.card-btn {
color: #1890ff;
border: 1px solid rgba(24, 144, 255, 0.5);
}
/deep/ .ant-input-number-handler-wrap {
display: none;
}
/deep/ .ant-upload.ant-upload-select-picture-card {
height: 90px;
width: 90px;
}
</style>

120
src/views/GroupNotes/GroupNotes.vue

@ -0,0 +1,120 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:09:48
* @LastEditors: aBin
* @LastEditTime: 2021-06-11 14:14:33
-->
<template>
<div class="d-flex flex-wrap flex-column">
<a-card class="fill-width">
<a-list item-layout="horizontal">
<a-list-item class="d-flex flex-nowrap">
<div>患者体重kg</div>
<span v-if="weight !== -1">{{ weight }}</span>
<span v-else class="color-c">暂无数据</span>
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>溶栓剂量mg </div>
<span v-if="medicine !== -1">{{ medicine }}</span>
<span v-else class="color-c">暂无数据</span>
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>团注剂量mg </div>
<span v-if="dose !== -1">{{ dose }}</span>
<span v-else class="color-c">暂无数据</span>
</a-list-item>
<a-list-item class="d-flex flex-nowrap">
<div>维持剂量mg </div>
<span v-if="maintain !== -1">{{ maintain }}</span>
<span v-else class="color-c">暂无数据</span>
</a-list-item>
</a-list>
<div class="d-flex mt-4">
<div class="flex-1">
<a-date-picker
:value="$moment(time)"
:show-time="{ format: 'HH:mm' }"
format="YYYY-MM-DD HH:mm"
placeholder="选择时间"
style="width: 100%"
@change="onChange"
@ok="onChange"
/>
</div>
<!-- <a-button v-if="isShow" style="width: 100px" type="primary" block @click="start"> 开始 </a-button> -->
</div>
</a-card>
<Content :time="time" />
</div>
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
import { getWeight } from 'config/api';
import Content from 'components/Content/Content.vue';
export default {
name: 'GroupNotes',
components: { Content },
data() {
return {
weight: -1, //
medicine: -1, //
dose: -1, //
maintain: -1, //
time: Date.parse(new Date()),
isShow: false,
};
},
computed: mapState('home', ['ptProps']),
async created() {
const start = await this.getStart();
if (start) {
this.time = +start;
}
this.getData();
this.setTitle('团注');
},
methods: {
...mapActions('home', ['getStart']),
...mapMutations('home', ['setTitle']),
async getData() {
try {
const parmas = { param: { projectId: this.ptProps.projectId } };
const res = await getWeight(parmas);
const { code, msg, data } = res.data;
if (code === 200) {
console.log(data);
if (data && data.length) {
for (let i = 0; i < data.length; i++) {
if (data[i].type === 1) {
this.weight = data[i].value;
} else if (data[i].type === 8) {
this.medicine = data[i].value;
} else if (data[i].type === 9) {
this.dose = data[i].value;
} else if (data[i].type === 10) {
this.maintain = data[i].value;
}
}
}
} else {
console.log(msg);
}
} catch (error) {}
},
onChange(e) {
let str = this.$moment(e._d).format('YYYY-MM-DD HH:mm');
str += ':00';
this.time = new Date(str).valueOf();
},
},
};
</script>
<style lang="stylus" scoped>
.color-c {
color: #ccc;
}
</style>

82
src/views/Index/Index.vue

@ -0,0 +1,82 @@
<!--
* @Author: wally
* @email: 18603454788@163.com
* @Date: 2021-02-22 09:20:03
* @LastEditors: aBin
* @LastEditTime: 2021-06-11 14:12:54
-->
<template>
<div class="d-flex flex-wrap flex-column">
<a-card style="padding: 0 12px">
<div class="align-center d-flex flex-row flex-nowrap justify-space-between">
<div class="title-box">患者{{ carInfo.name }}</div>
<div class="title-box" v-if="carInfo && carInfo.startTime">{{ $moment(+carInfo.startTime).format('MM-DD HH:mm') }}</div>
<div class="car-box">卒中专用平车{{ carInfo.carNumber }}</div>
</div>
</a-card>
<a-card class="mt-1">
<process :list="list" class="my-4" />
</a-card>
<a-card class="mt-1">
<data-table :list="list" />
</a-card>
<a-card class="mt-1">
<analysis />
</a-card>
</div>
</template>
<script>
import { findStepIsOver } from 'config/api';
import Analysis from './components/Analysis.vue';
import DataTable from './components/DataTable.vue';
import Process from './components/Process.vue';
export default {
name: 'Index',
components: { Analysis, Process, DataTable },
data() {
return {
list: [],
carInfo: null,
};
},
async created() {
this.carInfo = this.$route.query.carInfo[0];
await this.getList();
},
methods: {
async getList() {
try {
const { projectId } = this.ptProps;
const params = { param: { projectId: projectId } };
const res = await findStepIsOver(params);
const { code, data } = res.data;
if (code === 200) {
this.list = data;
}
} catch (error) {}
},
},
};
</script>
<style lang="stylus" scoped>
/deep/ .ant-card-body {
padding: 12px 2px;
}
.car-box {
background-color: #49cc90;
color: #fff;
padding: 0 8px;
font-weight: 500;
height: 32px;
line-height: 32px;
border-radius: 10px;
}
.title-box {
font-weight: 700;
color: rgba(0, 0, 0, 0.75);
}
</style>

138
src/views/Index/components/Analysis.vue

@ -0,0 +1,138 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 18:23:18
* @LastEditors: aBin
* @LastEditTime: 2021-06-04 09:50:02
-->
<template>
<div :style="{ width: 'width' }">
<div id="Analysis" style="width: 100%; height: 300px"></div>
</div>
</template>
<script>
import { getPointTime } from 'config/api';
export default {
name: 'Analysis',
data() {
return {
width: '',
height: '',
list: {
pointTimeCurrentList: [],
pointTimeHospital: [],
pointTimeInternation: [],
},
};
},
computed: {
option() {
return {
tooltip: { trigger: 'axis' },
legend: {
x: 'center',
y: 'bottom',
data: ['我院标准', '国际标准', '当前数据'],
textStyle: {
fontWeight: 'normal',
color: '#666', //
},
},
grid: {
left: '3%',
// right: '4%',
top: '10%',
bottom: '10%',
containLabel: true,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['呼叫', '分诊', '一线', '采血', '心电', 'CT', '二线', '谈话', '签字', '团注', '介入', '置鞘', '病房'],
axisLabel: {
textStyle: {
fontWeight: 'normal',
color: '#666', //
},
formatter: function(value) {
return value.split('').join('\n');
},
},
},
yAxis: {
type: 'value',
name: '秒',
axisLabel: {
textStyle: {
fontWeight: 'normal',
color: '#666', //
},
},
nameTextStyle: { color: '#666' },
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#666',
},
},
},
series: [
{
name: '我院标准',
type: 'line',
connectNulls: true,
symbolSize: 6,
data: this.list.pointTimeHospital,
color: 'rgb(18, 131, 227)',
},
{
name: '国际标准',
type: 'line',
connectNulls: true,
symbolSize: 6,
data: this.list.pointTimeInternation,
color: 'rgb(30, 231, 231)',
},
{
name: '当前数据',
type: 'line',
connectNulls: true,
symbolSize: 6,
data: this.list.pointTimeCurrentList,
color: 'rgb(227, 18, 187)',
},
],
};
},
},
mounted() {
let wh = window.innerWidth;
let hg = window.innerHeight;
this.width = wh + 'px';
this.height = hg + 'px';
console.log(this.height);
this.drawLine();
},
methods: {
async drawLine() {
// domecharts
await this.getData();
var myChart = this.$echarts.init(document.getElementById('Analysis'));
//
myChart.setOption(this.option);
},
async getData() {
try {
const params = { param: { id: 0 } };
const res = await getPointTime(params);
const { code, data } = res.data;
if (code === 200) {
this.list = { ...data };
}
} catch (error) {}
},
},
};
</script>

101
src/views/Index/components/DataTable.vue

@ -0,0 +1,101 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 18:22:38
* @LastEditors: aBin
* @LastEditTime: 2021-06-03 19:26:50
-->
<template>
<div>
<div style="width: 100%" v-if="list.length > 0">
<a-table :columns="columns" :pagination="false" :data-source="list" :row-key="record => record.id" bordered class="white pa-3">
<template slot="id" slot-scope="text, record, index">
<span>{{ index + 1 }}</span>
</template>
<template slot="startTime" slot-scope="text, record">
<span v-if="record.startTime">{{ $moment(+record.startTime).format('MM-DD HH:mm') }}</span>
</template>
<template slot="type" slot-scope="text, record">
<span v-if="record.type === 0">平车</span>
<span v-else-if="record.type === 1">{{ record.memberName }}</span>
</template>
</a-table>
</div>
<a-empty v-else />
<div v-if="list.length > 0" class="fill-width">
<a-button class="btn my-4"> 数据导出 </a-button>
</div>
</div>
</template>
<script>
const columns = [
{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
scopedSlots: { customRender: 'id' },
},
{
title: '流程',
align: 'center',
dataIndex: 'stepName',
key: 'stepName',
},
{
title: '开始时间',
align: 'center',
dataIndex: 'startTime',
key: 'startTime',
scopedSlots: { customRender: 'startTime' },
},
// {
// title: '',
// align: 'center',
// dataIndex: 'control',
// key: 'control',
// scopedSlots: { customRender: 'control' },
// },
{
title: '操作者',
align: 'center',
dataIndex: 'type',
key: 'type',
scopedSlots: { customRender: 'type' },
},
];
export default {
name: 'Table',
props: {
list: {
type: Array,
default: () => [],
},
},
data() {
return { columns };
},
};
</script>
<style lang="stylus" scoped>
.btn {
background-color: rgba(0, 128, 0, 0.75);
color: #fff;
float: right;
}
/deep/ .ant-table-thead > tr > th {
padding: 16px 4px;
}
/deep/ .ant-table-thead > tr > th {
font-weight: 700;
}
/deep/ .ant-table {
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
</style>

110
src/views/Index/components/Process.vue

@ -0,0 +1,110 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 18:21:47
* @LastEditors: aBin
* @LastEditTime: 2021-06-11 15:14:39
-->
<template>
<div style="margin: 0 10px">
<div class="fill-width d-flex flex-row flex-nowrap">
<div v-for="(item, index) in list" :key="item.stepId" class="flex-1 justify-center">
<div v-if="(index + 1) % 2 === 0" class="d-flex flex-column">
<div style="text-align: center; font-weight: 600">{{ item.stepName }}</div>
<div class="circle" :class="{ 'bd-green': item.startTime }">
{{ index + 1 }}
</div>
<div class="line" :class="{ 'br-green': item.startTime }"></div>
<div class="circle-small" :class="{ 'bg-green': item.startTime }"></div>
</div>
</div>
</div>
<div style="margin: 0 15px">
<a-progress :percent="100" :show-info="false" stroke-color="#ccc" :stroke-width="2" />
</div>
<div class="fill-width d-flex flex-row flex-nowrap">
<div v-for="(item, index) in list" :key="item.id" class="flex-1 justify-center">
<div v-if="(index + 1) % 2 === 1" class="d-flex flex-column">
<div class="circle-small-bottom" :class="{ 'bg-green': item.startTime }"></div>
<div class="line" :class="{ 'br-green': item.startTime }"></div>
<div class="circle" :class="{ 'bd-green': item.startTime }">
{{ index + 1 }}
</div>
<div style="text-align: center; font-weight: 600">{{ item.stepName }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Process',
props: {
list: {
type: Array,
default: () => [],
},
},
data() {
return {};
},
};
</script>
<style lang="stylus" scoped>
.circle {
height: 30px;
width: 30px;
font-weight: 700;
text-align: center;
line-height: 30px;
border-radius: 50%;
border: 1px solid #666;
}
.line {
border-right: 2px solid #999;
height: 30px;
width: 50%;
}
.br-green {
border-right: 2px solid green;
}
.circle-small {
width: 10px;
height: 10px;
border-radius: 50%;
border: 2px solid #ccc;
margin-bottom: -18px;
z-index: 1;
margin-left: 32%;
background-color: #fff;
}
.bg-green {
border: 2px solid green !important;
}
.bd-green {
border: 2px solid green !important;
color: green !important;
}
.br-red {
border: 2px solid red !important;
}
.circle-small-bottom {
width: 10px;
height: 10px;
border-radius: 50%;
border: 2px solid #ccc;
margin-top: -13px;
z-index: 1;
margin-left: 32%;
background-color: #fff;
}
</style>

26
src/views/InfoReport/InfoReport.vue

@ -0,0 +1,26 @@
<template>
<div class="d-flex flex-column fill-width">
<img class="fill-width" src="https://www.tall.wiki/staticrec/photos/info01.jpg" />
<img class="fill-width" src="https://www.tall.wiki/staticrec/photos/info02.jpg" />
<img class="fill-width" src="https://www.tall.wiki/staticrec/photos/info03.jpg" />
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
name: 'InfoReport',
data() {
return {};
},
created() {
this.setTitle('信息直报');
},
methods: mapMutations('home', ['setTitle']),
};
</script>
<style lang="stylus" scoped></style>

102
src/views/Information/Information.vue

@ -0,0 +1,102 @@
<template>
<div class="d-flex flex-column" style="padding: 0 16px">
<div class="d-flex" v-for="(timeAxio, timeIndex) in timeAxios" :key="timeIndex">
<div>
<div class="circle"></div>
<div class="faaxis" v-if="timeIndex !== timeAxios.length - 1">
<div class="axis"></div>
</div>
</div>
<div class="flex-1 d-flex flex-column">
<div>
<div class="time" style="">{{ $moment(+timeAxio.time).format('MM-DD HH:mm') }}</div>
<div class="present">{{ timeAxio.name ? timeAxio.name : user.wxInfo.nickname + '记录' }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { queryArriveWorker } from 'config/api';
import { mapMutations } from 'vuex';
import { mapState } from 'vuex';
export default {
data() {
return {
index: 0,
timeAxios: [],
};
},
computed: mapState('home', ['ptProps', 'user', 'addNum']),
watch: {
addNum(val) {
this.getMembers();
},
},
created() {
this.setTitle('到场信息');
const item = [{ icon: 'plus-circle', type: 4 }];
this.setTitleIcon(item);
this.getMembers();
},
methods: {
...mapMutations('home', ['setTitle', 'setTitleIcon']),
//
async getMembers() {
try {
const params = { param: { projectId: this.ptProps.projectId } };
const res = await queryArriveWorker(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.timeAxios = data.reverse();
} else {
console.log(msg);
}
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style scoped lang="stylus">
.circle {
height: 20px;
width: 20px;
background: #68D33A;
border: 2px solid #68D33A;
border-radius: 50%;
margin: 10px;
}
.faaxis {
height: 60px;
width: 20px;
display: flex;
justify-content: center;
margin: 0 10px;
}
.axis {
height: 60px;
width: 2px;
background: #68D33A;
}
.time {
height: 20px;
margin: 10px auto;
}
.present {
height: 60px;
width: 100%;
background: #FFFFFF;
border-radius: 5px;
padding: 10px;
display: flex;
align-items: center;
font-weight: bold;
}
</style>

345
src/views/MedicalSkill/MedicalSkill.vue

@ -0,0 +1,345 @@
<template>
<div class="d-flex flex-column pb-10">
<div class="tow mb-3" v-for="(index, indexa) in data" :key="indexa">
<a-list item-layout="horizontal" class="white" :data-source="index">
<a-list-item class="mx-3" slot="renderItem" slot-scope="item, itemIndex">
<div class="d-flex flex-nowrap align-center" style="width: 100%">
<div class="mr-3">{{ item.title }}</div>
<div class="flex-1 flex-row-reverse">
<div @click="openTimeSelect(item.title, indexa, itemIndex)" v-if="item.type === 'inspect'">
<span class="mr-3" v-if="item.value || item.codeA">{{
item.value || $moment(+item.codeA).format('YYYY-MM-DD HH:mm')
}}</span>
<span class="mr-3 gray-text" v-else>请选择时间</span>
<a-icon type="calendar" />
</div>
<!-- <a-upload
v-else-if="item.type === 'photo'"
name="file"
:multiple="true"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
:headers="headers"
@change="handleChange($event, item.name)"
>
<a-button class="uploads"> <a-icon type="camera" /> </a-button>
</a-upload> -->
<div v-else-if="item.type === 'CTreportPhoto'">
<div>
<a-upload
name="files"
style="width: 60%"
:headers="headers"
:multiple="false"
:action="action"
@change="handleChange($event, item.name)"
:show-upload-list="false"
list-type="picture-card"
>
<div v-if="fileList.length < 1">
<a-icon type="plus" />
<div class="ant-upload-text">上传图片</div>
</div>
</a-upload>
</div>
<a-list-item v-for="fileItem in fileList" :key="fileItem.id">
<div class="d-flex justify-space-between fill-width align-center">
<img @click="lookImg(fileItem.url)" :src="fileItem.url" class="mr-3" style="width: 80px; height: 80px" />
<a-popconfirm placement="left" ok-text="确定" cancel-text="再想想" @confirm="confirm(fileItem.code)">
<template slot="title"> 确定删除此图片吗? </template>
<a-icon type="delete" class="text-red" />
</a-popconfirm>
</div>
</a-list-item>
</div>
<div v-else-if="item.type === 'NMRreportPhoto'">
<div>
<a-upload
name="files"
style="width: 60%"
:headers="headers"
:multiple="false"
:action="action"
@change="handleChangeHc($event, item.name)"
:show-upload-list="false"
list-type="picture-card"
>
<div v-if="fileListHc.length < 1">
<a-icon type="plus" />
<div class="ant-upload-text">上传图片</div>
</div>
</a-upload>
</div>
<a-list-item v-for="fileItem in fileListHc" :key="fileItem.id">
<div class="d-flex justify-space-between fill-width align-center">
<img @click="lookImg(fileItem.url)" :src="fileItem.url" class="mr-3" style="width: 80px; height: 80px" />
<a-popconfirm placement="left" ok-text="确定" cancel-text="再想想" @confirm="confirmHc(fileItem.code)">
<template slot="title"> 确定删除此图片吗? </template>
<a-icon type="delete" class="text-red" />
</a-popconfirm>
</div>
</a-list-item>
</div>
</div>
</div>
</a-list-item>
</a-list>
</div>
<time-select
:first-index="firstIndex"
:second-index="secondIndex"
@chooseTime="chooseTime"
v-if="show"
:title="title"
:show="show"
@closeTimeSelect="closeTimeSelect"
/>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { data } from './config';
import { upload, queryAidRecord, aidRecord } from 'config/api';
import TimeSelect from 'components/TimeSelect/TimeSelect.vue';
export default {
components: { TimeSelect },
data() {
return {
data,
current: 0,
radioStyle: {
display: 'block',
height: '30px',
lineHeight: '30px',
},
record: {},
headers: { authorization: 'authorization-text' },
options: {
answer: '',
questionCode: '',
},
show: false,
title: '',
firstIndex: 0,
secondIndex: 0,
action: upload,
fileList: [],
fileListHc: [],
};
},
computed: mapState('home', ['ptProps']),
created() {
this.setTitle('医技结论');
this.setTitleIcon('', '');
this.getQuery();
},
methods: {
...mapMutations('home', ['setTitle', 'setTitleIcon']),
//
openTimeSelect(title, firstIndex, secondIndex) {
this.show = true;
this.title = title;
this.firstIndex = firstIndex;
this.secondIndex = secondIndex;
},
//
closeTimeSelect() {
this.show = false;
},
//
chooseTime(time, firstIndex, secondIndex) {
//
this.data[firstIndex][secondIndex].value = this.$moment(time).format('YYYY-MM-DD HH:mm');
//
this.options = {};
this.options.answer = [time];
this.options.questionCode = this.data[firstIndex][secondIndex].name;
this.submit(this.options);
this.closeTimeSelect();
},
//
lookImg(url) {
window.open(url);
},
confirm(code) {
this.fileList = [];
this.options = { answer: [], questionCode: code };
this.submit(this.options);
},
confirmHc(code) {
this.fileListHc = [];
this.options = { answer: [], questionCode: code };
this.submit(this.options);
},
handleChange(info, code) {
const status = info.file.status;
if (status === 'done') {
const file = info.file;
//
const obj = {
uid: file.response.data[0].id,
name: file.response.data[0].name,
status: status,
url: file.response.data[0].visitUrl,
thumbUrl: file.response.data[0].visitUrl,
code,
};
this.fileList.push(obj);
this.options = {};
this.options.answer = [file.response.data[0].visitUrl];
this.options.questionCode = code;
this.submit(this.options);
}
},
handleChangeHc(info, code) {
const status = info.file.status;
if (status === 'done') {
const file = info.file;
//
const obj = {
uid: file.response.data[0].id,
name: file.response.data[0].name,
status: status,
url: file.response.data[0].visitUrl,
thumbUrl: file.response.data[0].visitUrl,
code,
};
this.fileListHc.push(obj);
this.options = {};
this.options.answer = [file.response.data[0].visitUrl];
this.options.questionCode = code;
this.submit(this.options);
}
},
/**
* 批量查询急救信息
* @param { Array } codeList code列表
* @param { String } projectId 项目id
*/
async getQuery() {
try {
console.log('this.ptProps: ', this.ptProps);
const params = {
param: {
codeList: [
'YJJL-ECGstartTime',
'CT-START',
'YJJL-CTendTime',
'YJJL-CTreportPhoto',
'YJJL-NMRstartTime',
'YJJL-NMRendTime',
'YJJL-NMRreportPhoto',
'YJJL-bloodroutineReportTime',
'YJJL-coagulationReportTime',
'YJJL-biochemicalReportTime',
],
projectId: this.ptProps.projectId,
},
};
const res = await queryAidRecord(params);
const { code, data, msg } = res.data;
if (code === 200) {
this.record = data.record;
this.data[0][0].codeA = data.record['YJJL-ECGstartTime'] ? data.record['YJJL-ECGstartTime'][0] : null;
this.data[1][0].codeA = data.record['CT-START'] ? data.record['CT-START'][0] : null;
this.data[1][1].codeA = data.record['YJJL-CTendTime'] ? data.record['YJJL-CTendTime'][0] : null;
this.data[2][0].codeA = data.record['YJJL-NMRstartTime'] ? data.record['YJJL-NMRstartTime'][0] : null;
this.data[2][1].codeA = data.record['YJJL-NMRendTime'] ? data.record['YJJL-NMRendTime'][0] : null;
this.data[3][0].codeA = data.record['YJJL-bloodroutineReportTime'] ? data.record['YJJL-bloodroutineReportTime'][0] : null;
this.data[3][1].codeA = data.record['YJJL-coagulationReportTime'] ? data.record['YJJL-coagulationReportTime'][0] : null;
this.data[3][2].codeA = data.record['YJJL-biochemicalReportTime'] ? data.record['YJJL-biochemicalReportTime'][0] : null;
if (this.record['YJJL-CTreportPhoto'] && this.record['YJJL-CTreportPhoto'].length) {
const obj = {
uid: this.record['YJJL-CTreportPhoto'][0],
name: this.record['YJJL-CTreportPhoto'][0],
status: 'done',
url: this.record['YJJL-CTreportPhoto'][0],
thumbUrl: this.record['YJJL-CTreportPhoto'][0],
code: 'YJJL-CTreportPhoto',
};
this.fileList.push(obj);
}
if (this.record['YJJL-NMRreportPhoto'] && this.record['YJJL-NMRreportPhoto'].length) {
const obj = {
uid: this.record['YJJL-NMRreportPhoto'][0],
name: this.record['YJJL-NMRreportPhoto'][0],
status: 'done',
url: this.record['YJJL-NMRreportPhoto'][0],
thumbUrl: this.record['YJJL-NMRreportPhoto'][0],
code: 'YJJL-NMRreportPhoto',
};
this.fileListHc.push(obj);
}
} else {
this.$message.error(msg || '查询失败');
}
} catch (error) {
console.log('error: ', error);
}
},
/**
* 提交信息
* @param { Array } codeAndAnswerList code和答案
* @param { String } projectId 项目id
* @param { Number } userType 提交人类型0平车 1
*/
async submit(options) {
try {
const params = {
param: {
codeAndAnswerList: [options],
projectId: this.ptProps.projectId,
userType: 0,
},
};
const res = await aidRecord(params);
const { code, data, msg } = res.data;
if (code === 200) {
console.log('data: ', data);
} else {
this.$message.error(msg || '提交失败');
}
} catch (error) {
console.log('error: ', error);
}
},
},
};
</script>
<style scoped>
.ant-list-item >>> input {
outline: none;
border: none;
text-align: right;
}
.ant-calendar-picker >>> input {
padding-right: 34px;
}
.ant-select >>> .ant-select-selection {
border: none;
}
.ant-select >>> .ant-select-selection__placeholder,
.ant-select-search__field__placeholder {
text-align: right;
}
.ant-time-picker >>> input {
padding-right: 34px;
}
</style>

18
src/views/MedicalSkill/config.js

@ -0,0 +1,18 @@
export const data = [
[{ title: '心电开始时间', name: 'YJJL-ECGstartTime', codeA: null, type: 'inspect', value: null }],
[
{ title: 'CT开始时间', name: 'CT-START', codeA: null, type: 'inspect', value: null },
{ title: 'CT结束时间', name: 'YJJL-CTendTime', codeA: null, type: 'inspect', value: null },
{ title: 'CT报告拍照', name: 'YJJL-CTreportPhoto', codeA: null, type: 'CTreportPhoto' },
],
[
{ title: '核磁开始时间', name: 'YJJL-NMRstartTime', codeA: null, type: 'inspect', value: null },
{ title: '核磁结束时间', name: 'YJJL-NMRendTime', codeA: null, type: 'inspect', value: null },
{ title: '核磁报告拍照', name: 'YJJL-NMRreportPhoto', codeA: null, type: 'NMRreportPhoto' },
],
[
{ title: '血常规报告时间', name: 'YJJL-bloodroutineReportTime', codeA: null, type: 'inspect', value: null },
{ title: '凝血报告时间', name: 'YJJL-coagulationReportTime', codeA: null, type: 'inspect', value: null },
{ title: '生化报告时间', name: 'YJJL-biochemicalReportTime', codeA: null, type: 'inspect', value: null },
],
];

134
src/views/PatientList/PatientList.vue

@ -0,0 +1,134 @@
<template>
<div class="d-flex flex-column pt-3">
<div class="tips d-flex justify-space-between align-center px-2">
<a-input placeholder="请输入患者" style="width: 160px" @change="patientChange">
<a-icon slot="prefix" type="search" />
</a-input>
<div class="ml-3 flex-1 d-flex flex-row-reverse align-center">
<a-select :default-value="types[type].value" style="width: 120px" @change="handleChange">
<a-select-option v-for="typeItem in types" :key="typeItem.id" :value="typeItem.id">{{ typeItem.value }}</a-select-option>
</a-select>
<span class="mr-2">类型</span>
</div>
</div>
<List class="list" :spinning="spinning" :lists="lists" :to-end="toEnd" :type="type" @getControlData="getControlData" />
</div>
</template>
<script>
import { mapMutations } from 'vuex';
import { getPatientList } from 'config/api';
import List from './components/List.vue';
export default {
name: 'Control',
components: { List },
data() {
return {
types: [
{
id: 0,
value: '急救患者',
},
{
id: 1,
value: '平车患者',
},
{
id: 2,
value: '转归患者',
},
],
lists: [],
type: 0,
patientName: '',
toEnd: false,
spinning: false,
};
},
created() {
this.setTitle('急救绿色通道列表');
this.getControlData();
const item = [{ icon: 'plus-circle', path: '/addPatient', type: 1 }];
this.setTitleIcon(item);
},
methods: {
...mapMutations('home', ['setTitle', 'setTitleIcon']),
patientChange(e) {
this.patientName = e.target.value;
this.lists = [];
this.getControlData();
},
handleChange(value) {
this.type = value;
this.lists = [];
this.getControlData();
},
/**
* 患者列表查询
* @param {number} page 第几页
* @param {number} pageSize 每页多少条
* @param {number} patientName 患者名称 不传查询全部
* @param {number} type 患者类型 0急救患者 1平车患者 2转归患者
*/
async getControlData(options) {
try {
this.spinning = true;
const params = {
param: {
pageSize: 10,
patientName: this.patientName,
type: this.type,
},
};
params.param.page = options && options.page ? options.page : 1;
const res = await getPatientList(params);
this.spinning = false;
const { code, msg, data } = res.data;
if (code === 200) {
if (data.list && data.list.length) {
this.lists = this.lists.concat(data.list);
} else {
this.toEnd = true;
}
} else {
console.log(msg);
}
} catch (error) {
this.spinning = false;
console.log(error);
}
},
},
};
</script>
<style lang="scss" scoped>
.tips {
height: 54px;
width: 100%;
color: rgba(0, 0, 0, 0.85);
position: fixed;
top: 48px;
z-index: 99;
background: #f5f5f5;
}
.yuanquan {
height: 16px;
width: 16px;
border-radius: 50%;
}
.bg-red {
background-color: rgba(255, 0, 0, 0.85);
}
.bg-green {
background-color: #7ed321;
}
.list {
margin-top: 40px;
}
</style>

140
src/views/PatientList/components/List.vue

@ -0,0 +1,140 @@
<!--
* @Author: your name
* @Date: 2021-07-28 14:16:38
* @LastEditTime: 2021-07-29 14:16:49
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \wisdomcar_mobile\src\views\PatientList\components\List.vue
-->
<template>
<div class="mt-2" style="padding-top: 4px">
<div class="d-flex flex-column white px-3 mb-2 pt-3">
<div class="font-bold-16 ml-1">{{ type === 0 ? '急救患者' : type === 1 ? '平车患者' : '转归患者' }}</div>
<div class="d-flex flex-column mt-3 mb-2" v-if="lists && lists.length">
<div v-for="(patient, index) in lists" :key="index">
<div class="card d-flex flex-column">
<div class="text-white px-3 py-1" :class="patient.carId ? 'blue' : 'gray'">
<img class="mr-2 pingche" src="@/assets/pingche.png" />
<span>{{ patient.carId || '未绑定' }}</span>
</div>
<div class="d-flex flex-column">
<div class="pa-3 card-main">
<div class="d-flex flex-nowrap mb-2">
<!-- 姓名 -->
<span class="font-bold mr-3">{{ patient.name || '无名氏' }}</span>
<!-- 性别 -->
<span class="font-bold mr-3" v-if="patient.gender">{{ patient.gender === 0 ? '' : '' }}</span>
<span class="font-bold mr-3" v-else>--</span>
<!-- 年龄 -->
<span class="font-bold mr-3">{{ patient.age || '--' }}</span>
<!-- 脑卒中 -->
<a-tag color="blue" class="mr-3"> 脑卒中 </a-tag>
<!-- 待接诊 -->
<a-tag color="orange" v-if="!patient.greenwayTime"> 待接诊 </a-tag>
</div>
<img class="yan" v-if="patient.demonstrate === 1" src="@/assets/yan.png" />
<!-- 发病时间 -->
<div class="mb-2" v-if="type !== 2">
<span class="font-bold">发病时间</span>
<span v-if="patient.morbidityTime">{{ $moment(+patient.morbidityTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div>
<div class="mb-2" v-else>
<span class="font-bold">转归时间</span>
<span v-if="patient.transformationTime">{{ $moment(+patient.transformationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div>
<!-- 启动绿道 -->
<div v-if="type !== 2">
<span class="font-bold" style="color: #6fc8bf">启动绿道</span>
<span v-if="patient.greenwayTime">{{ $moment(+patient.greenwayTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div>
<div v-else>
<span class="font-bold" style="color: #6fc8bf">转归去向</span>
<span>{{ patient.transformation || '--' }}</span>
</div>
</div>
<a-divider class="my-0" v-if="patient.doctorList && patient.doctorList.length" />
<div class="d-flex flex-wrap font-12 pa-3" v-if="patient.doctorList && patient.doctorList.length">
<div v-for="doctor in patient.doctorList" :key="doctor.id">
<span class="font-bold ml-2">{{ doctor.post }}</span>{{ doctor.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-center">
<a-spin :spinning="spinning" />
</div>
<a-divider v-if="toEnd">无更多数据</a-divider>
</div>
</template>
<script>
export default {
name: 'TimeLine',
props: {
lists: {
type: Array,
default: () => [],
},
type: {
type: Number,
default: 0,
},
toEnd: {
type: Boolean,
default: false,
},
spinning: {
type: Boolean,
default: false,
},
},
data() {
return { page: 1 };
},
created() {
const that = this;
window.onscroll = function() {
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (scrollTop + windowHeight == scrollHeight) {
if (that.toEnd) return;
//
const nextPage = (that.page += 1);
const options = { page: nextPage };
that.$emit('getControlData', options);
}
};
},
};
</script>
<style scoped lang="scss">
.pingche {
position: relative;
top: -2px;
}
.card {
margin-bottom: 12px;
border-radius: 8px;
box-shadow: -2px 2px 8px #ccc;
overflow: hidden;
}
.card-main {
position: relative;
}
.yan {
position: absolute;
right: 24px;
bottom: 12px;
}
</style>

22
src/views/Quarter/Courtyard/BeOnDuty.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:16:21
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:16:34
-->
<template>
<div class="d-flex flex-wrap">值班表</div>
</template>
<script>
export default {
name: 'BeOnDuty',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

10
src/views/Quarter/Courtyard/ControlCore.vue

@ -0,0 +1,10 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 10:58:01
* @LastEditors: aBin
* @LastEditTime: 2021-06-02 10:58:27
-->
<template>
<div>院中心领导质控数据分析报告</div>
</template>

22
src/views/Quarter/Courtyard/Details.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:13:14
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:15:55
-->
<template>
<div class="d-flex flex-wrap">急救数据详情</div>
</template>
<script>
export default {
name: 'Details',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

10
src/views/Quarter/Courtyard/DetailsCore.vue

@ -0,0 +1,10 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-02 10:56:44
* @LastEditors: aBin
* @LastEditTime: 2021-06-02 10:58:37
-->
<template>
<div>院中心领导急救数据详情</div>
</template>

22
src/views/Quarter/Courtyard/Infor.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:17:55
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:18:09
-->
<template>
<div class="d-flex flex-wrap">信息科</div>
</template>
<script>
export default {
name: 'Infor',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

22
src/views/Quarter/Courtyard/Operation.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:18:33
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:39:58
-->
<template>
<div class="d-flex flex-wrap">运维界面</div>
</template>
<script>
export default {
name: 'Operation',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

22
src/views/Quarter/Courtyard/QualityControl.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:15:02
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:15:16
-->
<template>
<div class="d-flex flex-wrap">质控数据分析报告</div>
</template>
<script>
export default {
name: 'QualityControl',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

22
src/views/Quarter/Province/Details.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:13:14
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:37:37
-->
<template>
<div class="d-flex flex-wrap">省数据分析报告详情</div>
</template>
<script>
export default {
name: 'ProvinceDetails',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

22
src/views/Quarter/Province/Quarter.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:11:02
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:12:24
-->
<template>
<div class="d-flex flex-wrap">省季度数据分析报告</div>
</template>
<script>
export default {
name: 'Quarter',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

22
src/views/Quarter/Province/Year.vue

@ -0,0 +1,22 @@
<!--
* @Author: aBin
* @email: binbin0314@126.com
* @Date: 2021-06-01 16:12:50
* @LastEditors: aBin
* @LastEditTime: 2021-06-01 16:15:24
-->
<template>
<div class="d-flex flex-wrap">省年度数据分析报告</div>
</template>
<script>
export default {
name: 'Year',
data() {
return {};
},
method: {},
};
</script>
<style lang="stylus" scoped></style>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save