瀏覽代碼

合并代码

yuwenfen 4 年之前
父節點
當前提交
927b4ed334
共有 75 個文件被更改,包括 2830 次插入326 次删除
  1. 14 8
      App.vue
  2. 1 0
      README.md
  3. 8 6
      components/date-time-pick-group/date-time-pick-group.vue
  4. 1 1
      components/date-time-picker/date-time-picker.vue
  5. 63 0
      components/tm-simple-btn-group/tm-simple-btn-group.vue
  6. 2 2
      components/tm-steps/tm-steps.vue
  7. 3 11
      components/tm-trees/row.vue
  8. 91 89
      manifest.json
  9. 13 0
      package-lock.json
  10. 1 0
      package.json
  11. 22 10
      pages.json
  12. 8 5
      pages/configure/configure.vue
  13. 3 3
      pages/configure/server.js
  14. 286 0
      pages/creatingSituations/components/checkMap.vue
  15. 137 0
      pages/creatingSituations/components/checkMapAdd.vue
  16. 151 0
      pages/creatingSituations/components/checkMapDetail.vue
  17. 284 0
      pages/creatingSituations/components/checkPlan.vue
  18. 170 0
      pages/creatingSituations/components/checkRent.vue
  19. 124 25
      pages/creatingSituations/components/condition.vue
  20. 189 0
      pages/creatingSituations/components/situationPreview.vue
  21. 50 29
      pages/creatingSituations/components/theme.vue
  22. 129 12
      pages/creatingSituations/creatingSituations.vue
  23. 35 0
      pages/creatingSituations/model.js
  24. 26 0
      pages/creatingSituations/server.js
  25. 292 116
      pages/home/home.vue
  26. 14 0
      pages/home/model.js
  27. 18 0
      pages/home/server.js
  28. 1 1
      pages/login/server.js
  29. 203 0
      pages/messages/messages.vue
  30. 14 0
      pages/messages/model.js
  31. 18 0
      pages/messages/server.js
  32. 62 2
      pages/mission/mission.vue
  33. 3 3
      pages/mission/server.js
  34. 9 1
      pages/model.js
  35. 14 0
      pages/role-switching/model.js
  36. 150 0
      pages/role-switching/role-switching.vue
  37. 13 0
      pages/role-switching/server.js
  38. 0 0
      static/bottom-img.png
  39. 0 0
      static/disable-img.png
  40. 0 0
      static/icon-add-dis.png
  41. 0 0
      static/icon-add.png
  42. 二進制
      static/icon-blueMore.png
  43. 0 0
      static/icon-del.png
  44. 0 0
      static/icon-jinyong.png
  45. 0 0
      static/icon-map-dis.png
  46. 0 0
      static/icon-map.png
  47. 0 0
      static/icon-qiyong.png
  48. 0 0
      static/icon-shang-dis.png
  49. 0 0
      static/icon-shang.png
  50. 0 0
      static/icon-xia-dis.png
  51. 0 0
      static/icon-xia.png
  52. 0 0
      static/images/boy-avatar.png
  53. 0 0
      static/images/boy.png
  54. 0 0
      static/images/girl-avatar.png
  55. 0 0
      static/images/girl.png
  56. 0 0
      static/images/icon-more.png
  57. 0 0
      static/images/messagebubble.png
  58. 0 0
      static/images/pcbg.png
  59. 0 0
      static/images/shade.png
  60. 0 0
      static/incon-more.png
  61. 二進制
      static/list-close.png
  62. 二進制
      static/list-open.png
  63. 0 0
      static/theme.png
  64. 0 0
      static/theme0.png
  65. 0 0
      static/theme1.png
  66. 0 0
      static/top-img.png
  67. 二進制
      static/橙色已读.png
  68. 二進制
      static/橙色未读.png
  69. 二進制
      static/绿色已读.png
  70. 二進制
      static/绿色未读.png
  71. 14 0
      utils/arrFilter.js
  72. 72 0
      utils/dateHandle.js
  73. 2 2
      utils/request.js
  74. 119 0
      utils/ws.js
  75. 1 0
      utils/wsUrl.js

+ 14 - 8
App.vue

@@ -36,20 +36,15 @@
 
 <style lang="less">
 	/*每个页面公共css */
-
+	
 	body,
 	uni-app,
 	uni-page,
 	uni-page-wrapper,
 	uni-page-body {
 		height: 100%;
-		font-size: 12.5rpx;
-		line-height: 18.75rpx;
-	}
-
-	body,
-	uni-app,
-	uni-page {
+		font-size: 20rpx;
+		line-height: 30rpx;
 		background-color: #F5F6FA;
 	}
 
@@ -85,4 +80,15 @@
 			color: #3377FF;
 		}
 	}
+	// 新建情境样式start
+	.creatingSituations {
+		.title {
+			padding-bottom: 35rpx;
+			padding-left: 25rpx;
+			font-size: 30rpx;
+			line-height: 45rpx;
+			color: #292C33;
+		}
+	}
+	// 新建情境样式end
 </style>

+ 1 - 0
README.md

@@ -8,6 +8,7 @@
 2. 树形控件:tm-trees。
 3. 底部tabBar:tm-tabbar。
 4. 单选列表组合/下拉式单选列表组合:tm-radio-group。使用步骤看tm-radio-group/README.md
+5. 底部简单双按钮:tm-simple-btn-group。
 
 ### 公共组件的注册方式
 ---

+ 8 - 6
components/date-time-pick-group/date-time-pick-group.vue

@@ -10,7 +10,7 @@
         :pickType="'start'"
         placeholder="开始日期时间"
 			  @change="bindChange" />
-				 <text class="inner">~</text>
+			<text class="inner">~</text>
 			<date-time-picker
 				:fields="fields"
 				:start="dateObj.startTime"
@@ -105,7 +105,7 @@ export default {
 .date-pick {
 	display: flex;
 	align-items: center;
-	height: 25rpx;
+	// height: 25rpx;
 
 	.label {
 		margin-right: 3.12rpx;
@@ -118,11 +118,13 @@ export default {
 		display: flex;
 		justify-content: space-between;
 		align-items: center;
-		width: 238.28rpx;
-		height: 25rpx;
-		background: #ffffff;
-		border-radius: 3.12rpx;
+		border-radius: 5rpx;
 		border: 0.78rpx solid #e1e4ed;
+		padding: 9.37rpx 25rpx;
+		// width: 238.28rpx;
+		// height: 25rpx;
+		white-space: nowrap;
+		background: #ffffff;
 		color: #2e2f33;
 		box-sizing: border-box;
 

+ 1 - 1
components/date-time-picker/date-time-picker.vue

@@ -89,7 +89,7 @@ export default {
       // 设置默认值
       this.setDefaultValue();
     },
-    start(){
+    start(newVal, oldVal){
        if(newVal != oldVal){
         this.setDisabled()
       }

+ 63 - 0
components/tm-simple-btn-group/tm-simple-btn-group.vue

@@ -0,0 +1,63 @@
+<template>
+	<view class="tm-simple-btn-group">
+		<button v-for="(item, index) in options" 
+			@click="changeStep(item.id)"
+			:key="index">{{item.label}}</button>
+	</view>
+</template>
+
+<script>
+	/**
+	 * 底部组件,只有两个按钮的简单组件(只有文字没图标),按钮内容需要自行传入数据
+	 * props:{
+		 * options: [{id:按钮的唯一id,会在点击后返回,label:显示的文本内容}]
+		 * callback: 点击事件返回函数,返回参数是按钮id
+		 * }
+	 */
+	export default {
+		props: {
+			options: {
+				type: Array,
+				default: [
+					{id: 'pre', label: '上一步'},
+					{id: 'next', label: '下一步'}
+				]
+			}
+		},
+		methods: {
+			changeStep: function(type) {
+				this.$emit('callback', type);
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.tm-simple-btn-group {
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		display: flex;
+		flex-direction: row;
+		border-top: 0.62rpx solid #DADEE6;
+		width: 100%;
+		height: 75rpx;
+		
+		button {
+			border-radius: 0;
+			width: 50%;
+			height: 100%;
+			font-size: 22.5rpx;
+			line-height: 75rpx;
+			color: #3377FF;
+			background-color: #fff;
+			&:last-child {
+				color: #fff;
+				background-color: #3377FF;
+			}
+			&:after {
+				border: 0;
+			}
+		}
+	}
+</style>

+ 2 - 2
components/tm-steps/tm-steps.vue

@@ -49,7 +49,7 @@
 			flex-direction: row;
 			justify-content: space-between;
 			align-items: center;
-			margin: 37.5rpx 25rpx 50rpx 25rpx;
+			padding: 37.5rpx 25rpx 50rpx 25rpx;
 			
 			.item {
 				display: flex;
@@ -114,7 +114,7 @@
 		}
 		.component-wrap {
 			width: 100%;
-			height: calc(100% - 101.87rpx);
+			height: calc(100% - 160rpx);
 		}
 	}
 </style>

+ 3 - 11
components/tm-trees/row.vue

@@ -27,6 +27,7 @@
 
 <script>
 	import {_stopPropagation} from "../../utils/compatible.js";
+	import {arrFilter} from "../../utils/arrFilter.js";
 	
 	export default {
 		data() {
@@ -61,20 +62,11 @@
 		methods: {
 			rowClick: function() {
 				if(!this.hasChildren) return;
-				this.openKeysHandle(this.keysHandle(this.open, this.openKeys));
+				this.openKeysHandle(arrFilter(this.option.key, this.openKeys));
 			},
 			checkedHandle: function(e) {
 				_stopPropagation(e);
-				this.checkedKeysHandle(this.keysHandle(this.checked, this.checkedKeys));
-			},
-			keysHandle: function(condition, oldKeys) {
-				let keys = [];
-				if(condition) {
-					keys = oldKeys.filter((key)=> key !== this.option.key);
-				} else {
-					keys = [...oldKeys, this.option.key];
-				}
-				return keys;
+				this.checkedKeysHandle(arrFilter(this.option.key, this.checkedKeys));
 			},
 			openKeysHandle: function(arr) {
 				this.$emit('open-keys', arr);

+ 91 - 89
manifest.json

@@ -1,91 +1,93 @@
 {
-	"name" : "TracerMethodology",
-	"appid" : "__UNI__E410614",
-	"description": "",
-	"versionName": "1.0.0",
-	"versionCode": "100",
-	"transformPx": false,
-	"app-plus": { /* 5+App特有相关 */
-		"usingComponents": true,
-		"nvueCompiler": "uni-app",
-		"splashscreen": {
-			"alwaysShowBeforeRender": true,
-			"waiting": true,
-			"autoclose": true,
-			"delay": 0
-		},
-		"modules": { /* 模块配置 */
-
-		},
-		"distribute": { /* 应用发布信息 */
-			"android": { /* android打包配置 */
-				"permissions": [
-					"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
-					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
-					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
-					"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
-					"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
-					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
-					"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
-					"<uses-feature android:name=\"android.hardware.camera\"/>",
-					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
-				]
-			},
-			"ios": { /* ios打包配置 */
-
-			},
-			"sdkConfigs": { /* SDK配置 */
-
-			}
-		}
-	},
-	"quickapp": { /* 快应用特有相关 */
-
-	},
-	"mp-weixin": { /* 小程序特有相关 */
-		"appid": "",
-		"setting": {
-			"urlCheck": false
-		},
-		"usingComponents": true
-	},
-	"h5" : {
-	    "title" : "追踪方法学",
-	    "router" : {
-	        "mode" : "hash",
-	        "base" : "/TracerMethodology/"
-	    },
-	    "devServer" : {
-	        "port" : 8901,
-	        "headers" : {
-	            "Access-Control-Allow-Origin" : "*"
-	        },
-	        "proxy" : {
-	            "/TracerMethodology/api/*" : {
-	                "pathRewrite" : {
-	                    "^/TracerMethodology/api" : "/topro"
-	                },
-	                // "target" : "http://192.168.1.55:8901", // 内网
-	                "target" : "http://192.168.1.45:8088", // 内网
-	                "changeOrigin" : true,
-	                "secure" : false,
-	                "logLevel" : "debug"
-	            }
-	        }
-	    },
-	    "optimization" : {
-	        "treeShaking" : {
-	            "enable" : true
-	        }
-	    },
-	    "networkTimeout" : {
-	        "request" : 5000
-	    }
-	}
+    "name" : "TracerMethodology",
+    "appid" : "__UNI__E410614",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    "app-plus" : {
+        /* 5+App特有相关 */
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {},
+        /* 模块配置 */
+        "distribute" : {
+            /* 应用发布信息 */
+            "android" : {
+                /* android打包配置 */
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            "ios" : {},
+            /* ios打包配置 */
+            "sdkConfigs" : {
+                "ad" : {}
+            }
+        }
+    },
+    /* SDK配置 */
+    "quickapp" : {},
+    /* 快应用特有相关 */
+    "mp-weixin" : {
+        /* 小程序特有相关 */
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "h5" : {
+        "title" : "追踪方法学",
+        "router" : {
+            "mode" : "hash",
+            "base" : "/TracerMethodology/"
+        },
+        "devServer" : {
+            "port" : 8901,
+            "headers" : {
+                "Access-Control-Allow-Origin" : "*"
+            },
+            "proxy" : {
+                "/TracerMethodology/api/*" : {
+                    "pathRewrite" : {
+                        "^/TracerMethodology/api" : ""
+                    },
+                    // "target" : "http://192.168.1.55:8901", // 内网
+                    "target" : "http://192.168.1.45:8088", // 内网
+                    "changeOrigin" : true,
+                    "secure" : false,
+                    "logLevel" : "debug"
+                }
+            }
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        },
+        "networkTimeout" : {
+            "request" : 5000
+        }
+    }
 }

+ 13 - 0
package-lock.json

@@ -14,11 +14,24 @@
       "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.29.1.tgz",
       "integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M="
     },
+    "ometa": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npm.taobao.org/ometa/download/ometa-0.2.2.tgz",
+      "integrity": "sha1-9TxHNbptVq9aRrBN+3xDNMWW1E4="
+    },
     "qs": {
       "version": "6.9.6",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
       "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
     },
+    "scss": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npm.taobao.org/scss/download/scss-0.2.4.tgz",
+      "integrity": "sha1-BA2QPtN8XU+krTOuH9OJrBKk4GU=",
+      "requires": {
+        "ometa": "0.2.2"
+      }
+    },
     "vuex": {
       "version": "3.6.2",
       "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",

+ 1 - 0
package.json

@@ -7,6 +7,7 @@
     "crypto-js": "^4.0.0",
     "moment": "^2.29.1",
     "qs": "^6.9.6",
+    "scss": "^0.2.4",
     "vuex": "^3.6.0"
   },
   "devDependencies": {},

+ 22 - 10
pages.json

@@ -43,17 +43,29 @@
 				"navigationBarTitleText": "改善任务",
 				"enablePullDownRefresh": false
 			}
+		},
+		{
+			"path": "pages/home/home",
+			"style": {
+				"navigationBarTitleText": "个人中心",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/role-switching/role-switching",
+			"style": {
+				"navigationBarTitleText": "角色切换",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/messages/messages",
+			"style": {
+				"navigationBarTitleText": "消息中心",
+				"enablePullDownRefresh": false
+			}
 		}
-	    ,{
-            "path" : "pages/home/home",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "个人中心",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-    ],
+	],
 	"globalStyle": {
 		"navigationStyle": "custom",
 		"navigationBarTextStyle": "black",

+ 8 - 5
pages/configure/configure.vue

@@ -55,7 +55,7 @@ export default {
       showPopup: false,
       radioVal: null,
       index: null,
-	  timer:null,
+      timer: null,
     };
   },
   created() {
@@ -64,7 +64,8 @@ export default {
   methods: {
     //获取最新配置
     getResultConfig() {
-      this.$store.dispatch({
+      this.$store
+        .dispatch({
           type: "configure/commActions",
           payload: {
             key: "getResultConfig",
@@ -76,7 +77,8 @@ export default {
     },
     //恢复最初配置
     recoveryList() {
-      this.$store.dispatch({
+      this.$store
+        .dispatch({
           type: "configure/commActions",
           payload: {
             key: "getDefault",
@@ -88,7 +90,8 @@ export default {
     },
     //保存配置
     sureList() {
-      this.$store.dispatch({
+      this.$store
+        .dispatch({
           type: "configure/commActions",
           payload: {
             key: "postResultConfig",
@@ -99,7 +102,7 @@ export default {
         })
         .then(() => {
           this.getResultConfig();
-		  clearTimeout(this.timer)
+          clearTimeout(this.timer);
         });
     },
     showConfig() {

+ 3 - 3
pages/configure/server.js

@@ -4,17 +4,17 @@ const requestList = {
 	// 保存配置
 	postResultConfig: {
 		method: 'POST',
-		url: 'imed/pfm/resultConfig'
+		url: 'resultConfig'
 	},
 	//最新配置
 	getResultConfig:{
 		method: 'GET',
-		url: 'imed/pfm/resultConfig'
+		url: 'resultConfig'
 	},
 	//默认配置列表
 	getDefault:{
 		method: 'GET',
-		url: 'imed/pfm/resultConfig/default'
+		url: 'resultConfig/default'
 	}
 	
 };

+ 286 - 0
pages/creatingSituations/components/checkMap.vue

@@ -0,0 +1,286 @@
+<template>
+	<view class="check-map">
+		<view class="title">请对查核地图进行配置</view>
+		<view class="list">
+			<view class="item" 
+				v-for="(item, index) in list" 
+				:class="{disable: item.status === 'disable'}"
+				@click="detail(item)"
+				:key="index">
+				<view class="title-wrap">
+					<text>{{item.name}}</text>
+					<view>
+						<image src="../../../static/icon-map.png"></image>
+						<text>{{item.deptClassName}}</text>
+					</view>
+				</view>
+				<view class="content">
+					<text>包含{{item.pointCount}}个查核要点,{{item.itemCount}}个查核项目</text>
+					<text>
+						<text v-for="(point, c) in item.pointList" :key="c">
+							{{point.name}};
+						</text>
+					</text>
+				</view>
+				<view class="btn-group">
+					<view class="btn" 
+						v-for="(btn, index) in btnGroupArr" 
+						@click="btnClick($event, btn.id)"
+						:key="index">
+						<image :src="`../../static/icon-${btn.id}${item.status === 'disable' 
+							? 'dis' : ''}.png`"></image>
+						<text>{{btn.label}}</text>
+					</view>
+					<view class="btn">
+						<image :src="`../../static/icon-${creatIcon(item.status)['icon']}.png`">
+						</image>
+						<text>{{ creatIcon(item.status)['label'] }}</text>
+					</view>
+				</view>
+				<view class="add-img-wrap" v-if="item.status === 'add'">
+					<image src="../../../static/top-img.png"></image>
+					<text>新增项</text>
+				</view>
+				<view class="dis-img-wrap" v-if="item.status === 'disable'">
+					<image src="../../../static/disable-img.png"></image>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex";
+	import {_stopPropagation} from "../../../utils/compatible.js";
+	const btnGroupArr = [
+		{id: 'add', label: '新增'},
+		{id: 'shang', label: '上移'},
+		{id: 'xia', label: '下移'},
+	];
+	export default {
+		data() {
+			return {
+				btnGroupArr,
+				list: [
+					{status: 'normal'},
+					{status: 'add'},
+					{status: 'disable'},
+				]
+			}
+		},
+		computed: {
+			...mapState({
+				checkMap: state => state.creatingSituations.checkMap,
+				checkRent: state => state.creatingSituations.checkRent,
+				condition: state => state.creatingSituations.condition,
+			})
+		},
+		created:function(){
+			if(this.checkMap.list.length === 0) {
+				const {points} = this.checkRent.checkedItem;
+				if(!points) return;
+				let checkPointIds = points.map(({id})=> id);
+				console.log(checkPointIds)
+				this.$store.dispatch({
+					type: 'creatingSituations/commActions',
+					key: 'checkDeptList',
+					data: { 
+						depType: this.condition.depType,
+						checkPointIds,
+					}
+				}).then((data)=> {
+					if(data) this.myCommit('list', data);
+				});
+			}
+		},
+		methods: {
+			creatIcon: function(status) {
+				let obj = {icon: 'jinyong', label: '禁用'};
+				switch(status) {
+					case 'add': 
+						obj = {icon: 'del', label: '删除'};
+						break;
+					case 'disable': 
+						obj = {icon: 'qiyong', label: '启用'};
+						break;
+				}
+				return obj;
+			},
+			detail: function(item) {
+				this.$store.commit({
+					type: 'creatingSituations/comChangeState',
+					key: 'showCheckMapDetail',
+					data: true
+				});
+			},
+			btnClick: function(e, id) {
+				_stopPropagation(e);
+				switch(id) {
+					case 'add': 
+						this.$store.commit({
+							type: 'creatingSituations/comChangeState',
+							key: 'showCheckMapAdd',
+							data: true
+						});
+						break;
+				}
+			},
+			/**
+			 * 更新condition数据
+			 * @param {Object} key 要更新的属性
+			 * @param {Object} value 值
+			 */
+			myCommit: function(key, value) {
+				let data = {...this.checkMap};
+				data[key] = value;
+				this.$store.commit({
+					type: 'creatingSituations/comChangeState', 
+					key: 'checkMap', 
+					data
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.check-map {
+		.list {
+			overflow: hidden;
+			padding: 0 25rpx;
+			.item {
+				position: relative;
+				overflow: hidden;
+				margin-bottom: 25rpx;
+				border-radius: 5rpx;
+				padding-top: 16.25rpx;
+				padding-bottom: 0;
+				width: 100%;
+				background-color: #fff;
+				box-shadow: 0 3.75rpx 12.5rpx 0 rgba(0, 13, 51, 0.1);
+				
+				.title-wrap {
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					padding: 0 25rpx;
+					>text {
+						font-size: 35rpx;
+						line-height: 52.5rpx;
+						color: #292C33;
+					}
+					>view {
+						display: flex;
+						flex-direction: row;
+						align-items: center;
+						margin-left: 20rpx;
+						border-radius: 17.5rpx;
+						height: 35rpx;
+						font-size: 17.5rpx;
+						line-height: 35rpx;
+						color: #8F9BB3;
+						background-color: #EDF2FA;
+						image {
+							width: 35rpx;
+							height: 35rpx;
+						}
+						text {
+							padding-left: 10rpx;
+							padding-right: 20rpx;
+						}
+					}
+				}
+				.content {
+					display: flex;
+					flex-direction: column;
+					padding: 11.25rpx 25rpx 20rpx;
+					text {
+						overflow: hidden;
+						white-space: nowrap;
+						text-overflow: ellipsis;
+						font-size: 20rpx;
+						line-height: 30rpx;
+						color: #666F80;
+						&:first-child {
+							margin-bottom: 5rpx;
+							font-weight: bold;
+							color: #292C33;
+						}
+					}
+				}
+				.btn-group {
+					display: flex;
+					flex-direction: row;
+					padding: 15rpx 0;
+					width: 100%;
+					height: 77.5rpx;
+					background-color: #FAFBFC;
+					.btn {
+						display: flex;
+						flex-direction: column;
+						align-items: center;
+						justify-content: center;
+						border-right: 1px solid #DADEE6;
+						flex: 1;
+						font-size: 17.5rpx;
+						line-height: 26.25rpx;
+						color: #7A8599;
+						&:last-child {
+							border-right: 0;
+						}
+						image {
+							width: 25rpx;
+							height: 25rpx;
+						}
+					}
+				}
+				.dis-img-wrap,
+				.add-img-wrap {
+					position: absolute;
+					top: 18.75rpx;
+					right: 18.75rpx;
+					width: 93.75rpx;
+					height: 93.75rpx;
+					image {
+						width: 100%;
+						height: 100%;
+					}
+				}
+				.add-img-wrap {
+					top: 0;
+					right: 0;
+					width: 100rpx;
+					height: 35rpx;
+					text {
+						position: absolute;
+						top: 4.37rpx;
+						left: 28.75rpx;
+						font-size: 17.5rpx;
+						line-height: 26.25rpx;
+						color: #fff;
+					}
+				}
+				&.disable {
+					.title-wrap {
+						>text, >view {
+							color: #B8BECC;
+						}
+					}
+					.content {
+						text {
+							color: #B8BECC;
+						}
+					}
+					.btn-group {
+						.btn {
+							color: #B8BECC;
+							&:last-child {
+								color: #7A8599;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 137 - 0
pages/creatingSituations/components/checkMapAdd.vue

@@ -0,0 +1,137 @@
+<template>
+	<view class="modal">
+		<scroll-view scroll-y="true" class="modal-body">
+			<view class="body-content">
+				<text class="top-title">选择要新增的单位</text>
+				<view class="list">
+					<view class="item">
+						<view class="item-title">门诊</view>
+						<view class="chidren">
+							<view class="child" 
+								:class="{active: checkedIds.includes(0)}"
+								@click="changeChecked(0)">
+								<text>挂号处</text>
+								<image v-if="checkedIds.includes(0)" 
+									src="../../../static/bottom-img.png"></image>
+							</view>
+							<view class="child">
+								<text>分诊处</text>
+							</view>
+							<view class="child">
+								<text>挂号处</text>
+							</view>
+							<view class="child">
+								<text>分诊处</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<tm-simple-btn-group :options="botmBtnGroup"
+				v-on:callback="btnClick" ></tm-simple-btn-group>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	import {arrFilter} from "../../../utils/arrFilter.js";
+	export default {
+		data() {
+			return {
+				checkedIds: []
+			}
+		},
+		computed: {
+			botmBtnGroup: function() {
+				return [
+					{id: 'cancle', label: '取消'},
+					{id: 'ok', label: `已选${this.checkedIds.length}项,确定新增`}
+				];
+			}
+		},
+		methods: {
+			changeChecked: function(id) {
+				this.checkedIds = arrFilter(id, this.checkedIds);
+			},
+			btnClick: function(id) {
+				if(id === 'ok') {
+					
+				} else {
+					this.$store.commit({
+						type: 'creatingSituations/comChangeState',
+						key: 'showCheckMapAdd',
+						data: false
+					});
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.modal {
+		position: absolute;
+		bottom: 0;
+		width: 100%;
+		height: 100%;
+		z-index: 1000;
+		background-color: rgba(18, 20, 26, 0.5);
+		
+		.modal-body {
+			margin-top: 10%;
+			border-radius: 25rpx 25rpx 0 0;
+			padding: 35rpx 40rpx 75rpx;
+			width: 100%;
+			height: 90%;
+			font-size: 22.5rpx;
+			line-height: 33.75rpx;
+			color: #292C33;
+			background-color: #fff;
+			.top-title {
+				font-size: 30rpx;
+				line-height: 45rpx;
+			}
+			.list {
+				margin-top: 25rpx;
+				.item {
+					.item-title {
+						margin-bottom: 3.75rpx;
+						font-size: 25rpx;
+						line-height: 37.5rpx;
+						font-weight: bold;
+					}
+					.chidren {
+						display: flex;
+						flex-direction: row;
+						flex-wrap: wrap;
+						justify-content: space-between;
+						.child {
+							position: relative;
+							display: flex;
+							flex-direction: row;
+							justify-content: center;
+							align-items: center;
+							margin: 10rpx 0;
+							border-radius: 5rpx;
+							width: 200rpx;
+							height: 50rpx;
+							font-weight: 500;
+							background-color: #EBEDF2;
+							image {
+								position: absolute;
+								right: 0;
+								bottom: 0;
+								width: 25rpx;
+								height: 25rpx;
+							}
+							&.active {
+								color: #3377FF;
+								background-color: #E6EEFF;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 151 - 0
pages/creatingSituations/components/checkMapDetail.vue

@@ -0,0 +1,151 @@
+<template>
+	<view class="check-map-detail">
+		<view class="item">
+			<view class="icon-wrap" @click="openChildren(0)">
+				<image :src="`../../static/list-${openItems.includes(0)
+					?'close':'open'}.png`"></image>
+			</view>
+			<view class="content">
+				<view class="content-title" @click="openChildren(0)">疼痛之评估及再评估</view>
+				<view class="children" v-if="openItems.includes(0)">
+					<view class="child">
+						<text>PRN order时间间隔与时机</text>
+						<view class="check-icon-wrap" @click="changeChecked(1)">
+							<image :src="`../../static/check-${checkedIds.includes(1)
+								?'checkbox':'no'}.png`"></image>
+						</view>
+					</view>
+					<view class="child">
+						<text>过敏反应表现</text>
+						<view class="check-icon-wrap">
+							<image src="../../../static/check-no.png"></image>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="item">
+			<view class="icon-wrap" @click="openChildren(1)">
+				<image :src="`../../static/list-${openItems.includes(1)
+					?'close':'open'}.png`"></image>
+			</view>
+			<view class="content">
+				<view class="content-title" @click="openChildren(1)">疼痛之评估及再评估</view>
+				<view class="children" v-if="openItems.includes(1)">
+					<view class="child">
+						<text>PRN order时间间隔与时机</text>
+						<view class="check-icon-wrap">
+							<image src="../../../static/check-no.png"></image>
+						</view>
+					</view>
+					<view class="child">
+						<text>过敏反应表现</text>
+						<view class="check-icon-wrap">
+							<image src="../../../static/check-no.png"></image>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<tm-simple-btn-group :options="botmBtnGroup"
+			v-on:callback="btnClick" ></tm-simple-btn-group>
+	</view>
+</template>
+
+<script>
+	import {arrFilter} from "../../../utils/arrFilter.js";
+	
+	export default {
+		data() {
+			return {
+				openItems: [],
+				checkedIds: [],
+			}
+		},
+		computed: {
+			botmBtnGroup: function() {
+				return [
+					{id: 'cancle', label: '取消'},
+					{id: 'ok', label: `已选${this.checkedIds.length}项,确定`}
+				];
+			}
+		},
+		methods: {
+			openChildren: function(key) {
+				this.openItems = arrFilter(key, this.openItems);
+			},
+			changeChecked: function(id) {
+				this.checkedIds = arrFilter(id, this.checkedIds);
+			},
+			btnClick: function(id) {
+				if(id === 'ok') {
+					
+				} else {
+					this.$store.commit({
+						type: 'creatingSituations/comChangeState',
+						key: 'showCheckMapDetail',
+						data: false
+					});
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="less">
+	.check-map-detail {
+		padding-bottom: 75rpx;
+		width: 100%;
+		height: 100%;
+		.item {
+			display: flex;
+			flex-direction: row;
+			border-top: 1px solid #DADEE6;
+			padding-left: 25rpx;
+			width: 100%;
+			background-color: #fff;
+			.icon-wrap {
+				padding-top: 28.12rpx;
+				padding-right: 23.75rpx;
+				width: 45rpx;
+				height: inherit;
+				image {
+					width: 100%;
+					height: 12.5rpx;
+				}
+			}
+			.content {
+				width: 100%;
+				color: #292C33;
+				line-height: 87.5rpx;
+				.content-title {
+					height: 87.5rpx;
+					font-size: 22.5rpx;
+					font-weight: 500;
+				}
+				.children {
+					width: 100%;
+					.child {
+						display: flex;
+						flex-direction: row;
+						justify-content: space-between;
+						border-top: 1px solid #DADEE6;
+						height: 87.5rpx;
+						.check-icon-wrap {
+							display: flex;
+							flex-direction: row;
+							justify-content: center;
+							align-items: center;
+							width: 75rpx;
+							height: 100%;
+							image {
+								width: 25rpx;
+								height: 25rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 284 - 0
pages/creatingSituations/components/checkPlan.vue

@@ -0,0 +1,284 @@
+<template>
+	<view class="check-plan">
+		<view class="title">请制定查核计划({{showCheckPlan1 ? 1 : 2}}/2)</view>
+		<view class="content1" v-if="showCheckPlan1">
+			<view class="list">
+				<view class="item" v-for="(item, index) in list" :key="index">
+					<view class="text-wrap">
+						<input v-if="item.id === 'custom'" 
+							v-model="item.model" 
+							type="number" 
+							@input="createList"
+							placeholder="自定义" />
+						<text>{{item.label}}</text>
+					</view>
+					<view class="img-wrap" @click="checkModel(item)">
+						<image :src="`../../static/check-${checkedItem.id === item.id 
+							? 'radio': 'no'}.png`"></image>
+					</view>
+				</view>
+			</view>
+			<view class="date-box">
+				<text>起止时间</text>
+				<view>
+					<date-time-pick-group fields="day" 
+						:startTime="startTime()"
+						:startSelectValue="dateObj.start"
+						:endSelectValue="dateObj.end"
+						v-on:changeDate="changeDate"></date-time-pick-group>
+					<image src="../../../static/incon-more.png"></image>
+				</view>
+			</view>
+			<view class="result-box">
+				<text>查核频次</text>
+				<text>{{checkNumber}}</text>
+			</view>
+		</view>
+		<view class="content2" v-else>
+			<view class="top-box">
+				<view class="result-box">
+					<text>开始日期</text>
+					<text>{{dateObj.start}}</text>
+				</view>
+				<view class="date-box">
+					<text>结束日期</text>
+					<view>
+						<date-time-picker fields="day"
+							placeholder="请选择结束日期"
+							pickType="end"
+							:start="startTime()"
+							:defaultValue="dateObj.end"
+							v-on:change="changeDate"></date-time-picker>
+						<image src="../../../static/incon-more.png"></image>
+					</view>
+				</view>
+			</view>
+			<view class="content2-list">
+				<view class="item" v-for="(item, index) in checkList" :key="index">
+					<text>第{{index + 1}}次查核</text>
+					<view class="date-box">
+						<text>开始日期</text>
+						<view>
+							<date-time-picker fields="day"
+								:start="startDate(index)"
+								:end="formateStartEnd(endDate())"
+								placeholder="请选择开始日期"
+								:defaultValue="item"
+								v-on:change="changeChildDate($event, index)"></date-time-picker>
+							<image src="../../../static/incon-more.png"></image>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {dateHandle} from "../../../utils/dateHandle.js";
+	import { mapState } from "vuex";
+	const {dateDiff, getNewData, todayDate, compare} = dateHandle;
+	const list = [
+		{id: 'week', label: '每周', model: 7},
+		{id: 'month', label: '每月', model: 30},
+		{id: 'twoMonth', label: '每两月', model: 60},
+		{id: 'quarter', label: '每季度', model: 90},
+		{id: 'halfAYear', label: '每半年', model: 180},
+		{id: 'custom', label: '天', model: null},
+	];
+	export default {
+		data() {
+			return {
+				list, 
+				checkedItem: list[1], // 选中的取模方式对象
+				dateObj: { // 保存开始日期结束日期的对象
+					start: todayDate(),
+					end: '',
+					dayNum: 0 // 两个日期间隔的天数
+				}, 
+				checkList: [], // 核查计划数组
+			}
+		},
+		computed: {
+			...mapState({
+				showCheckPlan1: state => state.creatingSituations.showCheckPlan1,
+			}),
+			checkNumber: function() { // 查核频次
+				return this.checkList.length;
+			}
+		},
+		methods: {
+			checkModel: function(item) {
+				this.checkedItem = item;
+				this.createList();
+			},
+			/**
+			 * 开始、结束日期变化函数
+			 * @param {Object} date 日期对象
+			 * @param {Object} type 返回类型(start/end)
+			 */
+			changeDate: function(date, type) {
+				this.dateObj[type] = date.f1;
+				const {start, end} = this.dateObj;
+				if(start && end) {
+					this.dateObj.dayNum = dateDiff(start, end);
+					this.createList();
+				}
+			},
+			/**
+			 * 构造计划列表
+			 */
+			createList: function() {
+				const { model } = this.checkedItem;
+				const {start, dayNum} = this.dateObj;
+				if(model && dayNum > 0) { // 确保前两步都做好了
+					let num = Math.floor(dayNum / model);
+					this.checkList = [start];
+					for(let i = 0; i < num - 1; i++) {
+						this.checkList[i+1] = getNewData(this.checkList[i], model);
+					}
+				} else {
+					this.checkList = [];
+				}
+			},
+			/**
+			 * 已经生成的计划日期变化
+			 * @param {Object} date
+			 */
+			changeChildDate: function(date, index) {
+				let newList = this.checkList.slice(0, index); // 不包括index
+				newList[index] = date.f1;
+				const { model } = this.checkedItem;
+				let i = index;
+				// 判断下一个计划开始时间日期不能大于结束的前X(模)天
+				while(compare(this.endDate(), getNewData(newList[i], model))) { 
+					newList[i+1] = getNewData(newList[i], model);
+					i++;
+				}
+				this.checkList = newList;
+			},
+			startTime: function() { // 限制只能从今天开始
+				return this.formateStartEnd(todayDate());
+			},
+			endDate: function() { // 获取能选择的最大日期,取结束日期的前模天
+				let day = -Number(this.checkedItem.model); // 使用负数能取前X天
+				return getNewData(this.dateObj.end, day);
+			},
+			startDate: function(index) { // 子级能选择的最早开始时间
+				if(index > 0) {
+					let day = Number(this.checkedItem.model);
+					return this.formateStartEnd(getNewData(this.checkList[index - 1], day));
+				} else {
+					return this.startTime();
+				}
+			},
+			formateStartEnd: function(str) {
+				return str + ' 00:00';
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.check-plan {
+		font-size: 22.5rpx;
+		line-height: 33.75rpx;
+		color: #292C33;
+		.content1 {
+			.list {
+				padding-left: 25rpx;
+				background-color: #fff;
+				.item {
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+					align-items: center;
+					border-bottom: 1px solid #DADEE6;
+					width: 100%;
+					height: 87.5rpx;
+					.text-wrap {
+						display: flex;
+						flex-direction: row;
+						align-items: center;
+						input {
+							margin-right: 25rpx;
+							width: 75rpx;
+							font-size: 22.5rpx;
+							line-height: 33.75rpx;
+							color: #292C33;
+						}
+					}
+					.img-wrap {
+						display: flex;
+						flex-direction: row;
+						justify-content: center;
+						align-items: center;
+						width: 75rpx;
+						height: 100%;
+						image {
+							width: 25rpx;
+							height: 25rpx;
+						}
+					}
+				}
+			}
+		}
+		.content2 {
+			.top-box {
+				padding-left: 25rpx;
+				background-color: #fff;
+				.date-box,
+				.result-box {
+					padding-left: 0;
+				}
+				.result-box {
+					border-bottom: 1px solid #DADEE6;
+				}
+			}
+			.content2-list {
+				padding-bottom: 25rpx;
+				.item {
+					display: flex;
+					flex-direction: column;
+					margin-top: 19.37rpx;
+					>text {
+						padding-bottom: 9.37rpx;
+						padding-left: 25rpx;
+						color: #666F80;
+					}
+				}
+			}
+			.date-box,
+			.result-box {
+				margin-top: 0;
+			}
+		}
+		.date-box,
+		.result-box {
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			margin-top: 15rpx;
+			padding: 0 25rpx;
+			width: 100%;
+			height: 87.5rpx;
+			background-color: #fff;
+			>text:first-child {
+				margin-right: 85rpx;
+				white-space: nowrap;
+				color: #525866;
+			}
+			>view {
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+				align-items: center;
+				width: 100%;
+				image {
+					width: 12.5rpx;
+					height: 21.25rpx;
+				}
+			}
+		}
+	}
+</style>

+ 170 - 0
pages/creatingSituations/components/checkRent.vue

@@ -0,0 +1,170 @@
+<template>
+	<view class="check-rent">
+		<view class="title">请指定负责查核的查核组</view>
+		<view class="list">
+			<view class="item" 
+				v-for="(item, index) in checkRent.list" 
+				:key="index"
+				@click="openItemHandle(item.id)">
+				<view class="img-wrap">
+					<image :src="`../../static/list-${openItems.includes(item.id)
+						?'close':'open'}.png`"></image>
+				</view>
+				<view class="content">
+					<view class="info">
+						<view class="text">
+							<view>{{item.name}}</view>
+							<view>组长:{{item.groupManagerName}}</view>
+						</view>
+						<view class="icon" @click="checkedHandle($event, item)">
+							<image :src="`../../static/check-${checkRent.checkedItem.id === item.id ? 'radio' : 'no'}.png`"></image>
+						</view>
+					</view>
+					<view class="chidren" v-if="openItems.includes(item.id)">
+						<view class="chid-item"> 
+							<view>小组成员</view>
+							<view>{{item.members.join('、')}}</view>
+						</view>
+						<view class="chid-item"> 
+							<view>负责要点</view>
+							<view>
+								<text v-for="(point, c) in item.points" :key="c">
+									{{point.name}};
+								</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex";
+	import {_stopPropagation} from "../../../utils/compatible.js";
+	import {arrFilter} from "../../../utils/arrFilter.js";
+	
+	export default {
+		data() {
+			return {
+				openItems: []
+			}
+		},
+		computed: {
+			...mapState({
+				checkRent: state => state.creatingSituations.checkRent,
+				condition: state => state.creatingSituations.condition,
+			})
+		},
+		created:function(){
+			if(this.checkRent.list.length === 0) {
+				this.$store.dispatch({
+					type: 'creatingSituations/commActions',
+					key: 'checkGroupList',
+					data: { conditionIds: this.condition.conditionIds}
+				}).then((data)=> {
+					if(data) this.myCommit('list', data);
+				});
+			}
+		},
+		methods: {
+			openItemHandle: function(key) {
+				this.openItems = arrFilter(key, this.openItems);
+			},
+			checkedHandle: function(e, item) {
+				_stopPropagation(e);
+				this.myCommit('checkedItem', item);
+			},
+			/**
+			 * 更新condition数据
+			 * @param {Object} key 要更新的属性
+			 * @param {Object} value 值
+			 */
+			myCommit: function(key, value) {
+				let data = {...this.checkRent};
+				data[key] = value;
+				this.$store.commit({
+					type: 'creatingSituations/comChangeState', 
+					key: 'checkRent', 
+					data
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.check-rent {
+		.list {
+			.item {
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+				margin-bottom: 15rpx;
+				padding: 25rpx;
+				padding-right: 0;
+				width: 100%;
+				background-color: #fff;
+				
+				.img-wrap {
+					width: 36.25rpx;
+					image {
+						width: 21.25rpx;
+						height: 12.5rpx;
+					}
+				}
+				.content {
+					width: calc(100% - 36.25rpx);
+					font-size: 20rpx;
+					line-height: 30rpx;
+					color: #666E80;
+					.info {
+						display: flex;
+						flex-direction: row;
+						justify-content: space-between;
+						margin-top: -25rpx;
+						.text {
+							padding-top: 25rpx;
+							view:first-child {
+								margin-bottom: 25rpx;
+								font-size: 25rpx;
+								line-height: 37.5rpx;
+								color: #292C33;
+							}
+						}
+						.icon { // 图标样式,用view包裹img防止挤压变形
+							padding-top: 25rpx;
+							padding-left: 25rpx;
+							width: 75rpx;
+							height: inherit;
+							image {
+								width: 25rpx;
+								height: 25rpx;
+							}
+						}
+					}
+					.chidren {
+						margin-top: 25rpx;
+						border-top: 1px solid #DADEE6;
+						width: 100%;
+						.chid-item {
+							padding-top: 25rpx;
+							padding-right: 25rpx;
+							view {
+								overflow: hidden;
+								white-space: nowrap;
+								text-overflow: ellipsis;
+								&:first-child {
+									padding-bottom: 15rpx;
+									font-weight: bold;
+									color: #292C33;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 124 - 25
pages/creatingSituations/components/condition.vue

@@ -1,43 +1,142 @@
 <template>
 	<view class="condition">
-		
-		<tm-trees :options="options"
-		 :defaultOpen="defaultOpen" 
-		 :defaultChecked="defaultChecked"
+		<view class="title">请选择追踪条件(可多选)</view>
+		<view class="select-btn">
+			<text>选择门诊或急诊</text>
+			<view>
+				<button :class="{active: condition.depType === 1}" 
+					@click="selectBtnHandle(1)">门诊</button>
+				<button :class="{active: condition.depType === 2}" 
+					@click="selectBtnHandle(2)">急诊</button>
+			</view>
+		</view>
+		<tm-trees :options="condition.options"
+		 :defaultOpen="condition.defaultOpen" 
+		 :defaultChecked="condition.conditionIds"
 		 v-on:checked-keys="checkedHandle"></tm-trees>
 	</view>
 </template>
 
 <script>
+	import { mapState } from "vuex";
 	export default {
-		data() {
-			return {
-				options: [
-					{key: 'zhuyuan',label: '住院', children: [
-						{key: 'ICU',label: 'ICU', children: []},
-						{key: 'RCC',label: 'RCC', children: []},
-						{key: 'shengchan',label: '生产', children: [{
-							key: 'ziranchan',label: '自然产'
-						}]},
-					]},{key: 'zhuyuan',label: '住院', children: [
-						{key: 'ICU',label: 'ICU', children: []},
-						{key: 'RCC',label: 'RCC', children: []},
-						{key: 'shengchan',label: '生产', children: [{
-							key: 'ziranchan',label: '自然产'
-						}]},
-					]}
-				],
-				defaultOpen: ['zhuyuan'],
-				defaultChecked: ['ICU']
-			}
+		computed: {
+			...mapState({
+				condition: state => state.creatingSituations.condition,
+				theme: state => state.creatingSituations.theme
+			})
+		},
+		created: function(){
+			if(this.condition.options.length === 0)
+				this.getOptions(this.condition.depType);
 		},
 		methods: {
 			checkedHandle: function(keys) {
-				console.log(keys);
+				this.myCommit('conditionIds', keys);
+			},
+			selectBtnHandle: function(depType) {
+				this.myCommit('depType', depType);
+				this.getOptions(depType);
+			},
+			/**
+			 * 获取树形节点数据
+			 */
+			getOptions: function(depType) {
+				this.checkedHandle([]); // 切换后清空选中
+				const {id} = this.theme;
+				if(id || id === 0) {
+					this.$store.dispatch({
+						type: 'creatingSituations/commActions',
+						key: 'conditions',
+						data: { depType, type: id }
+					}).then((data)=> {
+						if(data) {
+							if(data.length > 0) {
+								this.myCommit('defaultOpen', [data[0].id]);
+							}
+							this.myCommit('options', this.optionsHandle(data));
+						} 
+					});
+				} else {
+					uni.showModal({
+					  title: '温馨提示',
+					  content: '请先选择主题!',
+					  showCancel: false
+					});
+				}
+			},
+			/**
+			 * 增加树形数据字段,以适配公共组件
+			 * @param {Object} data
+			 */
+			optionsHandle: function(data) {
+				let options = data.map((item, i)=>{
+					return {
+						...item,
+						key: item.id,
+						label: item.name,
+						children: this.optionsHandle(item.child)
+					}
+				});
+				return options;
+			},
+			/**
+			 * 更新condition数据
+			 * @param {Object} key 要更新的属性
+			 * @param {Object} value 值
+			 */
+			myCommit: function(key, value) {
+				let data = {...this.condition};
+				data[key] = value;
+				this.$store.commit({
+					type: 'creatingSituations/comChangeState', 
+					key: 'condition', 
+					data
+				});
 			}
 		}
 	}
 </script>
 
 <style lang="less">
+	.select-btn {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 15rpx;
+		padding: 0 25rpx;
+		width: 100%;
+		height: 87.5rpx;
+		font-size: 22.5rpx;
+		line-height: 33.75rpx;
+		color: #525866;
+		background-color: #fff;
+		
+		view {
+			display: flex;
+			flex-direction: row;
+			
+			button {
+				border: 0;
+				border-radius: 25rpx;
+				padding: 0 46.25rpx;
+				height: 50rpx;
+				line-height: 50rpx;
+				color: #292C33;
+				background-color: #EBEFF7;
+				
+				&:first-child {
+					margin-right: 20rpx;
+				}
+				&::after {
+					border: 0;
+				}
+				&.active {
+					color: #fff;
+					background-color: #3377FF;
+				}
+			}
+		}
+	}
 </style>

+ 189 - 0
pages/creatingSituations/components/situationPreview.vue

@@ -0,0 +1,189 @@
+<template>
+	<view class="situation-preview">
+		<view class="title">情境预览</view>
+		<view class="box1">
+			<view class="row1">
+				<view class="top">
+					<text>主题:个案追踪</text>
+					<view>
+						<text>查看查核地图</text>
+						<image src="../../../static/icon-blueMore.png"></image>
+					</view>
+				</view>
+				<view class="list">
+					<text>门诊</text>
+					<text>住院</text>
+					<text>ICU</text>
+				</view>
+			</view>
+			<view class="row2">
+				<view class="item">
+					<text>查核组</text>
+					<text>内科查核二组</text>
+				</view>
+				<view class="item">
+					<text>组长</text>
+					<text>王晓雪</text>
+				</view>
+			</view>
+		</view>
+		<view class="box2">
+			<view>情景名称</view>
+			<view class="input-wrap">
+				<input placeholder="限2~16个中文、英文或数字" />
+			</view>
+		</view>
+		<view class="box2">
+			<view>
+				<text>计划开始前</text>
+				<input placeholder="请输入" type="number" />
+				<text>天的</text>
+				<input placeholder="请输入" type="number" />
+				<text>时提醒</text>
+			</view>
+			<view>
+				<text>启动</text>
+				<input placeholder="请输入" type="number" />
+				<text>天前提醒</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.situation-preview {
+		overflow: hidden;
+		font-size: 22.5rpx;
+		line-height: 33.75rpx;
+		color: #292C33;
+		.box1,
+		.box2 {
+			margin-bottom: 15rpx;
+			padding: 25rpx;
+			width: 100%;
+			background-color: #fff;
+		}
+		.box1 {
+			display: flex;
+			flex-direction: column;
+			.row1 {
+				display: flex;
+				flex-direction: column;
+				margin-bottom: 35rpx;
+				.top {
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+					margin-bottom: 6.25rpx;
+					>text {
+						font-size: 30rpx;
+						line-height: 45rpx;
+					}
+					>view {
+						display: flex;
+						flex-direction: row;
+						align-items: center;
+						font-size: 20rpx;
+						line-height: 30rpx;
+						color: #3377FF;
+						image {
+							margin-left: 10rpx;
+							width: 11.87rpx;
+							height: 20rpx;
+						}
+					}
+				}
+				.list {
+					overflow: hidden;
+					display: flex;
+					flex-direction: row;
+					flex-wrap: wrap;
+					align-items: center;
+					>text {
+						margin-top: 6.25rpx;
+						margin-right: 15rpx;
+						border-radius: 5rpx;
+						padding: 2.5rpx 20.62rpx;
+						font-size: 17.5rpx;
+						line-height: 26.25rpx;
+						color: #7A8499;
+						background-color: #EBEFF7;
+					}
+				}
+			}
+			.row2 {
+				display: flex;
+				flex-direction: row;
+				justify-content: center;
+				align-items: center;
+				.item {
+					display: flex;
+					flex-direction: column;
+					width: 47.5%;
+					text {
+						overflow: hidden;
+						white-space: nowrap;
+						text-overflow: ellipsis;
+						font-size: 25rpx;
+						line-height: 37.5rpx;
+					}
+					text:first-child {
+						margin-bottom: 4.37rpx;
+						font-size: 17.5rpx;
+						line-height: 26.25rpx;
+						color: #666F80;
+					}
+					&:first-child {
+						margin-right: 5%;
+						border-right: 1px solid #DADEE6;
+					}
+				}
+			}
+		}
+		.box2 {
+			padding: 0;
+			padding-left: 25rpx;
+			>view {
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+				border-bottom: 1px solid #DADEE6;
+				height: 87.5rpx;
+				color: #525866;
+				>text {
+					white-space: nowrap;
+					color: #292C33;
+				}
+				>input {
+					padding: 0 9.37rpx;
+					width: 80rpx;
+					height: 33.75rpx;
+					font-size: 22.5rpx;
+					line-height: 33.75rpx;
+					text-align: center;
+				}
+				&:last-child {
+					border-bottom: 0;
+				}
+				&.input-wrap {
+					>input {
+						padding: 0;
+						padding-right: 25rpx;
+						width: 100%;
+						text-align: left;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 50 - 29
pages/creatingSituations/components/theme.vue

@@ -1,34 +1,53 @@
 <template>
 	<view class="theme">
-		<text class="title">请先选定一个主题进行追踪</text>
+		<view class="title">请先选定一个主题进行追踪</view>
 		<view class="content">
-			<view class="item">
+			<view class="item" 
+				v-for="(item, index) in themeList" 
+				@click="checkedHandle(item)"
+				:key="index">
 				<view class="left">
-					<image src="../../../static/gean.png"></image>
+					<image :src="`../../static/theme${item.id}.png`"></image>
 				</view>
 				<view class="right">
-					<text>个案追踪</text>
-					<text>评价诊疗服务的内涵质量以及对各种诊疗规范、临床路径等的执行力</text>
-				</view>
-			</view>
-			<view class="item">
-				<view class="left">
-					<image src="../../../static/xitong.png"></image>
-				</view>
-				<view class="right">
-					<text>系统追踪</text>
-					<text>评价对各种质量与安全管理制度与流程的执行力、医院服务的连贯性及多学科综合的服务能力</text>
+					<text>{{item.title}}</text>
+					<text>{{item.des}}</text>
 				</view>
+				<image v-if="theme.id === item.id" src="../../../static/theme.png"></image>
 			</view>
 		</view>
 	</view>
 </template>
 
 <script>
+	import { mapState } from "vuex";
+	const themeList = [{
+			id: 0, 
+			title: '个案追踪', 
+			des: '评价诊疗服务的内涵质量以及对各种诊疗规范、临床路径等的执行力',
+		},{
+			id: 1, 
+			title: '系统追踪', 
+			des: '评价对各种质量与安全管理制度与流程的执行力、医院服务的连贯性及多学科综合的服务能力',
+	}]
 	export default {
 		data() {
 			return {
-				
+				themeList
+			}
+		},
+		computed: {
+			...mapState({
+				theme: state => state.creatingSituations.theme
+			})
+		},
+		methods: {
+			checkedHandle: function(item) {
+				this.myCommit('theme', item);
+				this.myCommit('stepActive', 1);
+			},
+			myCommit: function(key, data) {
+				this.$store.commit({type: 'creatingSituations/comChangeState',key,data});
 			}
 		}
 	}
@@ -36,29 +55,30 @@
 
 <style lang="less">
 	.theme {
+		overflow: hidden;
 		width: 100%;
-		.title {
-			padding-left: 25rpx;
-			font-size: 30rpx;
-			line-height: 45rpx;
-			color: #292C33;
-		}
 		.content {
 			display: flex;
 			flex-direction: column;
 			align-items: center;
-			margin-top: 25rpx;
 			.item {
+				position: relative;
 				display: flex;
 				flex-direction: row;
-				margin-top: 125rpx;
+				margin: 62.5rpx 0;
 				border-radius: 15rpx;
 				padding: 37.5rpx 50rpx;
 				width: 625rpx;
 				height: 187.5rpx;
-				background: linear-gradient(270deg, #00CCBB 0%, #00CCAA 100%);
-				box-shadow: 0 12.5rpx 12.5rpx 0 rgba(0, 204, 170, 0.2);
-				
+				background: linear-gradient(270deg, #6697FE 0%, #4980F2 100%);
+				box-shadow: 0 12.5rpx 12.5rpx 0 rgba(73, 128, 242, 0.2);
+				>image {
+					position: absolute;
+					top: 10rpx;
+					right: 10rpx;
+					width: 46.87rpx;
+					height: 46.87rpx;
+				}
 				.left {
 					margin-right: 25rpx;
 					image {
@@ -81,9 +101,10 @@
 						}
 					}
 				}
-				&:last-child {
-					background: linear-gradient(270deg, #6697FE 0%, #4980F2 100%);
-					box-shadow: 0 12.5rpx 12.5rpx 0 rgba(73, 128, 242, 0.2);
+				&:first-child {
+					margin-top: 125rpx;
+					background: linear-gradient(270deg, #00CCBB 0%, #00CCAA 100%);
+					box-shadow: 0 12.5rpx 12.5rpx 0 rgba(0, 204, 170, 0.2);
 				}
 			}
 		}

+ 129 - 12
pages/creatingSituations/creatingSituations.vue

@@ -1,37 +1,154 @@
 <template>
 	<view class="creatingSituations">
-		<tm-steps :options="options" :active="active"></tm-steps>
+		<check-map-detail v-if="showCheckMapDetail"></check-map-detail>
+		<view v-else class="page-wrap" 
+			:style="{paddingBottom: stepActive !== 0 ? '75rpx' : 0}">
+			<tm-steps :options="options" :active="stepActive"></tm-steps>
+			<tm-simple-btn-group v-if="stepActive !== 0" 
+				:options="botmBtnGroup"
+				v-on:callback="changeStep"></tm-simple-btn-group>
+		</view>
+		<check-map-add v-if="showCheckMapAdd"></check-map-add>
 	</view>
 </template>
 
 <script>
+	import { mapState } from "vuex";
 	import theme from "./components/theme.vue";
 	import condition from "./components/condition.vue";
+	import checkRent from "./components/checkRent.vue";
+	import checkMap from "./components/checkMap.vue";
+	import checkMapDetail from "./components/checkMapDetail.vue";
+	import checkMapAdd from "./components/checkMapAdd.vue";
+	import checkPlan from "./components/checkPlan.vue";
+	import situationPreview from "./components/situationPreview.vue";
+	
+	const normalBtnGroup = [
+		{id: 'pre', label: '上一步'},
+		{id: 'next', label: '下一步'}
+	];
+	const btnGroupPlan1 = [
+		{id: 'pre', label: '上一步'},
+		{id: 'checkPlanCreate', label: '生成查核计划'}
+	];
+	const btnGroupPlan2 = [
+		{id: 'checkPlanCallback', label: '返回'},
+		{id: 'next', label: '下一步'}
+	];
+	const btnGroupSituationPreview = [
+		{id: 'pre', label: '上一步'},
+		{id: 'situationPreviewOK', label: '完成'}
+	];
 	
 	export default {
 		data() {
 			return {
 				options: [
-					{title: '主题', component: theme},
-					{title: '条件', component: condition},
-					{title: '查核组'},
-					{title: '地图'},
-					{title: '计划'},
-					{title: '配置'},
-				],
-				active: 1
+					{id: 'theme', title: '主题', component: theme},
+					{id: 'condition', title: '条件', component: condition, hint: '追踪条件'},
+					{id: 'checkRent', title: '查核组', component: checkRent, hint: '查核组'},
+					{id: 'checkMap', title: '地图', component: checkMap, hint: '地图'},
+					{id: 'checkPlan', title: '计划', component: checkPlan, hint: '计划'},
+					{id: 'situationPreview', title: '预览', component: situationPreview},
+				]
+			}
+		},
+		computed: {
+			...mapState({
+				showCheckMapDetail: state => state.creatingSituations.showCheckMapDetail,
+				showCheckMapAdd: state => state.creatingSituations.showCheckMapAdd,
+				showCheckPlan1: state => state.creatingSituations.showCheckPlan1,
+				stepActive: state => state.creatingSituations.stepActive,
+				condition: state => state.creatingSituations.condition,
+				checkRent: state => state.creatingSituations.checkRent,
+			}),
+			botmBtnGroup: function() {
+				if(this.stepActive === 4) {
+					if(this.showCheckPlan1) {
+						return btnGroupPlan1;
+					} else {
+						return btnGroupPlan2;
+					}
+				} else if(this.stepActive === 5) {
+					return btnGroupSituationPreview;
+				} else {
+					return normalBtnGroup;
+				}
 			}
 		},
 		methods: {
-			
+			changeStep: function(id) {
+				switch(id) {
+					case 'pre': // 上一步
+						if(this.stepActive > 0) 
+							this.myCommit('stepActive', this.stepActive - 1);
+						break;
+					case 'next': // 下一步
+						if(this.stepActive < this.options.length) 
+							this.nextHandle(this.stepActive);
+						break;
+					case 'checkPlanCreate': // 生成查核计划
+						this.myCommit('showCheckPlan1', false);
+						break;
+					case 'checkPlanCallback': // 生成查核计划-返回
+						this.myCommit('showCheckPlan1', true);
+						break;
+				}
+			},
+			/**
+			 * 处理【下一步】逻辑
+			 */
+			nextHandle: function(stepActive) {
+				let flage = false;
+				switch(stepActive) {
+					case 1: 
+						flage = this.errorHandle(this.condition.conditionIds.length > 0, 1);
+						break;
+					case 2: 
+						const {points} = this.checkRent.checkedItem;
+						let condition = this.checkRent.checkedItem.id !== null && points;
+						flage = this.errorHandle(condition, 2);
+						break;
+				}
+				if(flage) this.myCommit('stepActive', stepActive + 1);
+			},
+			/**
+			 * 错误处理,满足条件返回true
+			 * @param {Object} condition 条件
+			 * @param {Object} index 当前下标
+			 */
+			errorHandle: function(condition, index) {
+				if(condition) {
+					return true;
+				} else {
+					uni.showModal({
+						title: '温馨提示',
+						content: `请先选择${this.options[index].hint}!`,
+						showCancel: false
+					});
+					return false;
+				}
+			},
+			myCommit: function(key, data) {
+				this.$store.commit({type: 'creatingSituations/comChangeState',key,data});
+			}
+		},
+		components: {
+			checkMapDetail,
+			checkMapAdd
 		}
 	}
 </script>
 
 <style lang="less">
-		.creatingSituations {
+	.creatingSituations {
+		width: 100%;
+		height: 100%;
+		background-color: #F5F6FA;
+		.page-wrap {
+			padding-bottom: 75rpx;
 			width: 100%;
 			height: 100%;
-			background-color: #F5F6FA;
 		}
+	}
 </style>

+ 35 - 0
pages/creatingSituations/model.js

@@ -0,0 +1,35 @@
+import { commServer } from './server.js';
+
+export default {
+  namespaced: true,
+  state: {
+		showCheckMapDetail: false,
+		showCheckMapAdd: false,
+		showCheckPlan1: true,
+		stepActive: 0, // 步骤进度
+		theme: {id: null, title: null, des: null}, // 主题选中数据(id: 0个案 1系统)
+		condition: { // 条件页面数据
+			options: [], // 树形节点数据
+			conditionIds: [], // 选中的key
+			depType: 1, // 门急诊类型 1-门诊 2-急诊
+			defaultOpen: [], // 默认展开的项
+		},
+		checkRent: { // 查核组页面数据
+			list: [],
+			checkedItem: {id: null}
+		},
+		checkMap: { // 查核地图数据
+			list: [], // 列表数据
+		}
+  },
+  mutations: {
+		comChangeState(state, {key, data}) {
+			state[key] = data;
+		},
+  },
+  actions: {
+		commActions({ commit, state }, { key, data }) {
+      return commServer(key, data);
+		},
+  }
+}

+ 26 - 0
pages/creatingSituations/server.js

@@ -0,0 +1,26 @@
+import { creatRequest } from '../../utils/request.js';
+
+const requestList = {
+  // 获取条件树
+  conditions: {
+    method: 'GET',
+    url: 'common/conditions',
+		// successMessage: '',
+		// needLoading: false // 还有这两个参数,但不是必传的,默认loading
+  }, 
+	// 查核组列表
+  checkGroupList: {
+    method: 'POST',
+    url: 'situation/checkGroupList',
+  },
+	// 查核地图列表
+  checkDeptList: {
+    method: 'POST',
+    url: 'situation/checkDeptList',
+  },
+};
+
+export const commServer = (key, data) => {
+  let obj = requestList[key];
+  return creatRequest(obj, data);
+}

+ 292 - 116
pages/home/home.vue

@@ -2,35 +2,55 @@
 	<view class="home-page">
 		<view class="content-info">
 			<view class="top-box">
-				<image class="bgpic" src="/static/images/个人中心背景.png"></image>
+				<image class="bgpic" src="/static/images/pcbg.png"></image>
+				<text class="hosname">{{hospName}}</text>
 			</view>
 			<view class="avatar-box">
-				<image class="avatar" src="/static/images/小哥哥.png"></image>
+				<image class="avatar" src="/static/images/boy-avatar.png"></image>
 			</view>
 			<view class="info-box">
-				<text class="">
-					毛之易
-				</text>
+				<view class="head">
+					<text class="name">
+						{{name}}
+					</text>
+					<!-- <image class="gender" src="/static/images/boy.png"></image> -->
+					<text class="username">{{code}}</text>
+				</view>
+				<!-- <view class="row">
+					<text class="text">心血管内科</text>
+				</view> -->
+				<view class="row">
+					<view class="col">
+						<text class="text">主管:{{depManager}}</text>
+					</view>
+					<view class="col">
+						<text class="text">|</text>
+					</view>
+					<view class="col">
+						<text class="text">所属查核组:{{dep}}</text>
+					</view>
+				</view>
+
 			</view>
 			<view class="function-box">
-				<view class="role-switch">
+				<view class="role-switch" @click="switchRole">
 					<text class="func-text">角色切换</text>
-					<image class="msgbubble" src="/static/images/消息气泡.png"></image>
-					<image class="icon-more" src="/static/images/icon更多.png"></image>
-					<text class="role">管理员</text>
-				</view>			
-				<view class="sys-setting">
-					<text class="func-text">系统设置</text>
-					<image class="icon-more" src="/static/images/icon更多.png"></image>
-				</view>
-			</view>
-			<view class="bg-box">
-				<view class="logout-box">
-					<text class=""></text>
+					<view class="msg-box" v-show="isMsgShow">
+						<text class="msg-text">{{this.totalTodo}}</text>
+					</view>
+					<image class="icon-more" src="/static/images/icon-more.png"></image>
+					<text class="role">{{nowPermissionName}}</text>
 				</view>
+				<!-- 				<view class="sys-setting">
+					<text class="func-text">系统设置</text>
+					<image class="icon-more" src="/static/images/icon-more.png"></image>
+				</view> -->
 			</view>
 		</view>
-		<tm-tabbar />
+		<view class="logout-box" @click="logOut">
+			<text class="logout-text">退出登录</text>
+		</view>
+		<tm-tabbar :permission="nowPermission" />
 	</view>
 </template>
 
@@ -38,110 +58,266 @@
 	export default {
 		data() {
 			return {
-				nowPermission:'',//用户当前第一权限
+				nowPermission: '', //用户当前第一权限
+				nowPermissionName:'',//当前权限名
+				code:'',//用户名
+				name:'',//名字
+				dep:'',//所属查核组
+				depManager:'',//查核组组长
+				hospName:'',//医院名
+				totalTodo:0,//总待办数
+				pemissionList:[
+					{permission: 1, name: '管理员'},
+					{permission: 2, name: '查核组长'},
+					{permission: 3, name: '查核组员'},
+					{permission: 4, name: '单位负责人'},
+					{permission: 5, name: '改善者'}
+				]
 			}
 		},
+		created: function() {
+			this.$store.dispatch({
+				type: 'home/commActions',
+				payload: {
+					key: 'getuser',
+				}
+			}).then((data) => {
+				if (data) {
+					uni.setStorageSync('permissions', data.permissions);
+					uni.setStorageSync('nowPermission', data.nowPermission);
+					this.code=data.code;
+					this.name=data.name;
+					this.nowPermission=data.nowPermission;
+					this.dep=data.dep;
+					this.depManager=data.depManager;
+					this.hospName=data.hospName;
+					let current=this.pemissionList.find(item => item.permission == data.nowPermission);
+					this.nowPermissionName=current.name;
+					this.totalTodo=data.permissions.reduce(function(total,currentValue){
+						return total+currentValue.todoNum;
+					},0);
+				}
+			});
+		},
 		methods: {
-			
+			logOut() {
+				this.$store.dispatch({
+					type: 'home/commActions',
+					payload: {
+						key: 'logout',
+					}
+				}).then((data)=>{
+					if(data!==null){
+						uni.navigateTo({
+							url: '/pages/login/login'
+						});
+					}
+				});
+			},
+			switchRole() {
+				uni.navigateTo({
+					url: '/pages/role-switching/role-switching'
+				});
+			}
+		},
+		computed:{
+			isMsgShow(){
+				return this.totalTodo<=0?false:true;
+			}
 		}
 	}
 </script>
 
 <style lang="less">
-	.top-box{
-		position: relative;
-		height: 350rpx;
-	}
-	.bgpic{
-		width: 750rpx;
-		height: 350rpx;
-	}
-	.info-box{
-		width: 700rpx;
-		height: 250rpx;
-		border-radius: 15rpx;
-		background-color: #FFFFFF;
-		position: absolute;
-		left: 25rpx;
-		right: 25rpx;
-		top: 226.25rpx;
-		box-shadow: 0px 10px 30px 0px rgba(0, 13, 51, 0.1);
-	}
-	.avatar-box{
-		width: 125rpx;
-		height: 125rpx;
-		position: absolute;
-		right: 75rpx;
-		top: 187.5rpx;
-		background: #FFFFFF;
-		z-index: 2;
-		border-radius:50%
-	}
-	.avatar{
-		width: 112.5rpx;
-		height: 112.5rpx;
-		margin-left: 6.25rpx;
-		margin-top: 6.25rpx;
-		border-radius:50%
-	}
-	.function-box{
-		position: absolute;
-		top: 496.25rpx;
-		width: 750rpx;
-	}
-	.role-switch{
-		height: 100rpx;
-		width: 725rpx;
-		margin-left: 25rpx;
-		background: #FFFFFF;
-		border-bottom: 0.62rpx solid #DADEE6;
-	}
-	.sys-setting{
-		height: 100rpx;
-		width: 725rpx;
-		margin-left: 25rpx;
-		background: #FFFFFF;
-	}
-	.func-text{
-		font-size: 22.5rpx;
-		font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-		font-weight: 500;
-		color: #292C33;
-		line-height: 100rpx;
-		float: left;
-	}
-	.icon-more{
-		width: 12.37rpx;
-		height: 21.21rpx;
-		line-height: 100rpx;
-		float: right;
-		margin-top: 39.37rpx;
-		margin-right: 25rpx;
-	}
-	.msgbubble{
-		width: 50rpx;
-		height: 30rpx;
-		background: #FF4060;
-		border-radius: 24px;
-		float: left;
-		margin-top: 35rpx;
-		margin-left: 15rpx;
-	}
-	.bg-box{
-		width: 750rpx;
-		height: 416.25rpx;
-		position: absolute;
-		bottom: 87.5rpx;
-		background-color: #F5F6FA;
-		z-index: -1;
-	}
-	.role{
-		font-size: 22.5rpx;
-		font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-		font-weight: 400;
-		color: #7A8599;
-		line-height: 100rpx;
-		float: right;
-		margin-right: 25rpx;
+	.home-page {
+		height: 100%;
+
+		.content-info {
+			height: 596.25rpx;
+			background-color: #FFFFFF;
+
+			.top-box {
+				position: relative;
+				height: 350rpx;
+
+				.bgpic {
+					width: 750rpx;
+					height: 350rpx;
+				}
+
+				.hosname {
+					font-size: 45rpx;
+					font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+					font-weight: 400;
+					color: #FFFFFF;
+					position: absolute;
+					left: 50rpx;
+					top: 92.5rpx;
+				}
+			}
+
+			.info-box {
+				width: 700rpx;
+				height: 250rpx;
+				border-radius: 15rpx;
+				background-color: #FFFFFF;
+				position: absolute;
+				left: 25rpx;
+				right: 25rpx;
+				top: 226.25rpx;
+				box-shadow: 0px 10px 30px 0px rgba(0, 13, 51, 0.1);
+
+				.head {
+					margin-left: 37.5rpx;
+					margin-top: 68.75rpx;
+
+					.name {
+						font-size: 35rpx;
+						font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+						font-weight: 400;
+						color: #17181A;
+					}
+
+					.gender {
+						width: 25rpx;
+						height: 25rpx;
+						background: linear-gradient(135deg, #4DA6FF 0%, #4D88FF 100%);
+						border-radius: 6.25rpx;
+						margin-left: 15rpx;
+					}
+
+					.username {
+						font-size: 25rpx;
+						font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+						font-weight: 400;
+						color: #17181A;
+						margin-left: 55rpx;
+					}
+				}
+
+				.row {
+					margin-left: 37.5rpx;
+					margin-top: 62.5rpx;
+
+					.col {
+						display: inline-block;
+						margin-right: 25rpx;
+					}
+				}
+
+				.text {
+					font-size: 22.5rpx;
+					font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+					font-weight: 400;
+					color: #666E80;
+				}
+
+			}
+
+			.avatar-box {
+				width: 125rpx;
+				height: 125rpx;
+				position: absolute;
+				right: 75rpx;
+				top: 187.5rpx;
+				background: #FFFFFF;
+				z-index: 2;
+				border-radius: 50%
+			}
+
+			.avatar {
+				width: 112.5rpx;
+				height: 112.5rpx;
+				margin-left: 6.25rpx;
+				margin-top: 6.25rpx;
+				border-radius: 50%
+			}
+
+			.function-box {
+				position: absolute;
+				top: 496.25rpx;
+				width: 750rpx;
+
+				.role-switch {
+					height: 100rpx;
+					width: 725rpx;
+					margin-left: 25rpx;
+					background: #FFFFFF;
+					border-bottom: 0.62rpx solid #DADEE6;
+
+					.msg-box {
+						width: 50rpx;
+						height: 30rpx;
+						float: left;
+						margin-top: 35rpx;
+						margin-left: 15rpx;
+						position: relative;
+						background: #FF4060;
+						border-radius: 24px;
+						text-align: center;
+
+						.msg-text {
+							font-size: 17.5rpx;
+							font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+							font-weight: 400;
+							color: #FFFFFF;
+							line-height: 30rpx;
+						}
+					}
+
+					.role {
+						font-size: 22.5rpx;
+						font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+						font-weight: 400;
+						color: #7A8599;
+						line-height: 100rpx;
+						float: right;
+						margin-right: 25rpx;
+					}
+				}
+
+				// .sys-setting{
+				// 	height: 100rpx;
+				// 	width: 725rpx;
+				// 	margin-left: 25rpx;
+				// 	background: #FFFFFF;
+				// }
+				.func-text {
+					font-size: 22.5rpx;
+					font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+					font-weight: 500;
+					color: #292C33;
+					line-height: 100rpx;
+					float: left;
+				}
+
+				.icon-more {
+					width: 12.37rpx;
+					height: 21.21rpx;
+					line-height: 100rpx;
+					float: right;
+					margin-top: 39.37rpx;
+					margin-right: 25rpx;
+				}
+			}
+
+
+		}
+
+		.logout-box {
+			width: 750rpx;
+			height: 100rpx;
+			background-color: #FFFFFF;
+			margin-top: 15rpx;
+
+			.logout-text {
+				font-size: 22.5rpx;
+				font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+				font-weight: 500;
+				color: #292C33;
+				line-height: 100rpx;
+				margin-left: 330rpx;
+			}
+		}
 	}
 </style>

+ 14 - 0
pages/home/model.js

@@ -0,0 +1,14 @@
+import { commServer } from './server.js';
+
+export default {
+  namespaced: true,
+  state: {
+  },
+  mutations: {},
+  actions: {
+		commActions({ commit, state }, { payload }) {
+			// payload = {key,data} // data是请求数据,key是请求接口id
+      return commServer(payload);
+		},
+  }
+}

+ 18 - 0
pages/home/server.js

@@ -0,0 +1,18 @@
+import { creatRequest } from '../../utils/request.js';
+
+const requestList = {
+  //退出登录
+  logout: {
+    method: 'POST',
+    url: 'login/out'
+  },
+	//获取用户信息
+	getuser:{
+		method: 'GET',
+		url: 'user'
+	}
+};
+export const commServer = ({ key, data }) => {
+  let obj = requestList[key];
+  return creatRequest(obj, data);
+}

+ 1 - 1
pages/login/server.js

@@ -4,7 +4,7 @@ const requestList = {
   //登录
   login: {
     method: 'POST',
-    url: 'imed/pfm/login/in'
+    url: 'login/in'
   },
 };
 export const commServer = ({ key, data }) => {

+ 203 - 0
pages/messages/messages.vue

@@ -0,0 +1,203 @@
+<template>
+  <view class="messages-page">
+    <view
+      class="contBody"
+      @touchend="touchend"
+      :style="MessList.length <= 8 ? { height: 'calc(100% - 30rpx)' } : {}"
+    >
+      <view
+        v-for="(item, index) in MessList"
+        :key="index"
+        class="messages-content"
+        @click="toDetail(item)"
+      >
+        <view class="imgView">
+          <image
+            :src="
+              item.businessType == 1
+                ? item.readStatus
+                  ? '/static/橙色已读.png'
+                  : '/static/橙色未读.png'
+                : item.readStatus
+                ? '/static/绿色已读.png'
+                : '/static/绿色未读.png'
+            "
+          ></image>
+        </view>
+        <view class="contView">
+          <view class="contView-title">
+            {{ item.title }}
+          </view>
+          <view class="contView-content">
+            {{ item.content }}
+          </view>
+          <view class="contView-time">
+            {{ item.effectTime }}
+          </view>
+        </view>
+      </view>
+      <view class="bottomPanDuan"></view>
+    </view>
+
+    <view class="bottomTishi">
+      <view v-if="loading"> 向上滑动加载更多! </view>
+      <view v-else> 已经到底了~ </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import moment from "moment";
+export default {
+  data() {
+    return {
+      pageNum: 1,
+      pageSize: 10,
+      MessList: [],
+      loading: false,
+      currentPage: 0,
+      totalPage: 0,
+    };
+  },
+  mounted() {
+    this.getMessList();
+  },
+  methods: {
+    getMessList() {
+      var currPage = this.currentPage + 1;
+      this.$store.dispatch({
+          type: "messages/commActions",
+          payload: {
+            key: "messagesList",
+            data: {
+              pageNum: currPage,
+              pageSize: this.pageSize,
+            },
+          },
+        })
+        .then((res) => {
+          this.totalPage = res.totalPage;
+          res.list.map((item) => {
+            item.effectTime = moment(item.effectTime).format("MM-DD hh:mm");
+          });
+          //获取当前页码
+          this.currentPage = res.pageNum;
+          //当前页码与总页码进行比对
+          this.loading = this.currentPage < this.totalPage;
+          //将获得的数据拼接当前渲染数据中
+          this.MessList = this.MessList.concat(res.list);
+        });
+    },
+    touchend() {
+      if (this.currentPage < this.totalPage) {
+        var box = document.getElementsByClassName("bottomPanDuan")[0];
+        var pos = box.getBoundingClientRect();
+        if (pos.bottom <= document.documentElement.clientHeight) {
+          this.getMessList();
+        }
+      }
+    },
+    toDetail(data) {
+      this.$store.dispatch({
+          type: "messages/commActions",
+          payload: {
+            key: "toRead",
+            data: {
+              id: data.id,
+            },
+          },
+        })
+        .then((res) => {
+          if (data.businessType == 1) {
+            uni.navigateTo({
+              url: `/pages/mission-details/mission-details?taskId=${data.businessId}`,
+            });
+          } else if (data.businessType == 2) {
+            uni.navigateTo({
+              url: `/pages/home/home`,
+            });
+          }
+          this.MessList = [];
+          for (let i = 1; i < this.currentPage + 1; i++) {
+            this.$store.dispatch({
+                type: "messages/commActions",
+                payload: {
+                  key: "messagesList",
+                  data: {
+                    pageNum: i,
+                    pageSize: this.pageSize,
+                  },
+                },
+              })
+              .then((res) => {
+                res.list.map((item) => {
+                  item.effectTime = moment(item.effectTime).format(
+                    "MM-DD hh:mm"
+                  );
+                });
+                this.MessList = this.MessList.concat(res.list);
+              });
+          }
+        });
+    },
+  },
+  computed: {},
+};
+</script>
+
+<style lang="less">
+.messages-page {
+  padding-top: 15rpx;
+  height: 100%;
+  overflow-y: auto;
+  .messages-content {
+    display: flex;
+    background-color: #fff;
+    .imgView {
+      margin-top: 25rpx;
+      margin-left: 25rpx;
+      margin-right: 25rpx;
+      margin-bottom: 63.75rpx;
+      width: 56.25rpx;
+      height: 56.25rpx;
+      vertical-align: top;
+      .image-circle {
+        background-color: ;
+      }
+      image {
+        width: 56.25rpx;
+        height: 90px;
+      }
+    }
+    .contView {
+      flex: 1;
+      border-bottom: 0.62rpx solid #dadee6;
+      .contView-title {
+        margin-top: 25rpx;
+        font-size: 22.5rpx;
+        font-weight: 500;
+        color: #292c33;
+      }
+      .contView-content {
+        margin: 15rpx 0 20rpx;
+        font-size: 20rpx;
+        color: #525866;
+      }
+      .contView-time {
+        margin-bottom: 25rpx;
+        font-size: 17.5rpx;
+        color: #666e80;
+      }
+    }
+  }
+  .bottomTishi {
+    padding: 6.25rpx 0px;
+    width: 100%;
+    // position: absolute;
+    // bottom: 0rpx;
+    text-align: center;
+    font-size: 17.5rpx;
+    color: #525866;
+  }
+}
+</style>

+ 14 - 0
pages/messages/model.js

@@ -0,0 +1,14 @@
+import { commServer } from './server.js';
+
+export default {
+  namespaced: true,
+  state: {
+  },
+  mutations: {},
+  actions: {
+	commActions({ commit, state }, { payload }) {
+		// payload = {key,data} // data是请求数据,key是请求接口id
+        return commServer(payload);
+	},
+  }
+}

+ 18 - 0
pages/messages/server.js

@@ -0,0 +1,18 @@
+import { creatRequest } from '../../utils/request.js';
+
+const requestList = {
+  //获取分页列表
+  messagesList: {
+    method: 'GET',
+    url: 'notice/page'
+  },
+  //已读
+  toRead: {
+    method: 'GET',
+    url: 'notice/read'
+  },
+};
+export const commServer = ({ key, data }) => {
+  let obj = requestList[key];
+  return creatRequest(obj, data);
+}

+ 62 - 2
pages/mission/mission.vue

@@ -1,5 +1,8 @@
 <template>
 	<view class="mission-page">
+		<view class="message-remind" @click="toMessagePage">
+			<image :src="messageType?'/static/mission/消息中心未读.png':'/static/mission/消息中心已读.png'" mode=""></image>
+		</view>
 	 	<scroll-view class="scroll-y" scroll-y="true">
 			<list-item
 				v-for="(item, i) in improvingTaskList"
@@ -32,6 +35,7 @@
 <script>
 	// 任务列表
 	import listItem from './components/list-item.vue';
+	import websocket from '../../utils/ws.js';//引入websocket
 	export default {
 		data(){
 			return {
@@ -74,11 +78,24 @@
 				],
 				// 历史任务
 				completeTaskList: [],
+				refTimer: null,
+				isInitWs:null,
+				messageType:null,
 			}
 		},
 		created() {
-			this.getMissionList()
+			// this.getMissionList();
+			this.init(true);
+			this.refTimer = setInterval(() => {
+			    this.isInitWs = websocket.ws ? false : true;
+			    this.init(this.isInitWs);
+			}, 3 * 60 * 1000);
 		},
+		beforeDestroy() {
+		    // 关闭ws连接
+		    websocket.close();
+		    clearInterval(this.refTimer);
+		  },
 		methods: {
 			toggleBtn() {
 				let flag = !this.showCloseList;
@@ -88,6 +105,10 @@
 					name: flag ? '收起历史任务' : '展示历史任务'
 				}
 			},
+			init(isInitWs) {
+				this.isInitWs = isInitWs;
+			    this.getMissionList()
+			},
 			// 获取改善任务列表
 			getMissionList(data) {
 				this.$store.dispatch({
@@ -100,12 +121,36 @@
 					if(data) {
 						this.improvingTaskList = data.improvingTaskResponses || [];
 						this.completeTaskList = data.improveCompleteResponses || [];
+						let hiId = uni.getStorageSync('hiId');
+						let user = uni.getStorageSync('id');
+						let permission = uni.getStorageSync('nowPermission');
+						this.isInitWs && this.initWebsocket(hiId,user,permission);
 					}
 				});
 				/** 请求参数 data
 				 * situationId: 情境id 当管路员或者查核者通过情境进入任务列表时 必传
 				 * checkItemId 单位负责人通过 查核要点进入改善任务列表时 必传
 				 */
+			},
+			initWebsocket(hiId,user,permission) {
+			    websocket.url = `ws://192.168.1.45:8088/imed/pfm/websocket/${hiId}/${user}/${permission}`;
+			    websocket.createWebSocket(this.resolverWsData.bind(this));
+			},
+			// 解析websocket返回数据
+			resolverWsData(type) {
+			  switch (type) {
+			    case "TO_READ":
+			      this.messageType = true;
+			      break;
+			    default:
+				  this.messageType = false;
+			      break;
+			  }
+			},
+			toMessagePage(){
+				uni.navigateTo({
+				  url: `/pages/messages/messages`
+				});
 			}
 		},
 		components: {
@@ -118,7 +163,22 @@
  .mission-page {
    height: 100%;
    padding-top: 15rpx;
-
+	.message-remind{
+		width: 62.5rpx;
+		height: 62.5rpx;
+		position: fixed;
+		top: 25rpx;
+		right: 25rpx;
+		background: rgba(255, 255, 255, 0.95);
+		border-radius: 50%;
+		z-index: 2;
+		image{
+			margin-left: 17.5rpx;
+			margin-top: 16.87rpx;
+			width: 27.5rpx;
+			height: 28.75rpx;
+		}
+	}
    	.scroll-y {
 			height: calc(100% - 87.5rpx);
 

+ 3 - 3
pages/mission/server.js

@@ -6,17 +6,17 @@ const requestList = {
 	// 改善任务列表
 	getMissionList: {
 		method: 'GET',
-		url: 'imed/pfm/improverTask/list'
+		url: 'improverTask/list'
 	},
 	// 改善任务详情
 	getMissionDetails: {
 		method: 'GET',
-		url: 'imed/pfm/improverTask/detail'
+		url: 'improverTask/detail'
 	},
 	// 查询部门人员树 (通用接口)
 	getEmpDeptTree: {
 		method: 'GET',
-		url: 'imed/pfm/common/empDeptTree'
+		url: 'common/empDeptTree'
 	}
 };
 

+ 9 - 1
pages/model.js

@@ -1,9 +1,17 @@
 import login from './login/model.js';
+import home from './home/model.js';
+import roleSwitching from './role-switching/model.js';
 import configure from './configure/model.js';
+import messages from './messages/model.js';
 import mission from './mission/model.js';
+import creatingSituations from "./creatingSituations/model.js";
 
 export default module = {
   login,
   configure,
-	mission,
+  home,
+  roleSwitching,
+  messages,
+  mission,
+	creatingSituations
 }

+ 14 - 0
pages/role-switching/model.js

@@ -0,0 +1,14 @@
+import { commServer } from './server.js';
+
+export default {
+  namespaced: true,
+  state: {
+  },
+  mutations: {},
+  actions: {
+		commActions({ commit, state }, { payload }) {
+			// payload = {key,data} // data是请求数据,key是请求接口id
+      return commServer(payload);
+		},
+  }
+}

+ 150 - 0
pages/role-switching/role-switching.vue

@@ -0,0 +1,150 @@
+<template>
+	<view class="role-page">
+		<view class="row-box">
+			<view class="role-list" v-for="(item,index) in permissionList">
+				<text class="role-name">{{item.label}}</text>
+				<view class="radio-item" @click="toggleSelect(item,index)">
+					<image class="icon" :src="`/static/${item.isChecked ? 'check-radio' : 'check-no'}.png`"></image>
+				</view>
+				<text class="nowrole" v-show="item.isNowRole" >当前角色</text>
+				<text class="task-msg">{{item.todoNum}}</text>
+			</view>
+		</view>
+		<view class="btn-confirm" @click="saveChange">
+			<text class="btn-text">确定</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				permissionList:[],//权限列表
+				nowPermission:'',//当前权限
+				selectedPermission:'',//当前选中的权限
+				roleList:[
+					{permission: 1, name: '管理员'}, 
+					{permission: 2, name: '查核组长'},
+					{permission: 3, name: '查核组员'},
+					{permission: 4, name: '单位负责人'},
+					{permission: 5, name: '改善者'}
+				]
+			}
+		},
+		created() {
+			let permissions=uni.getStorageSync('permissions');
+			this.nowPermission=uni.getStorageSync('nowPermission');
+			this.permissionList=permissions.map((item,index)=>{
+				let match=this.roleList.find(i => i.permission == item.permission);
+				return {
+					value:match.permission,
+					label:match.name,
+					todoNum:item.todoNum>0?item.todoNum+'个任务待处理':'暂无待处理',
+					isNowRole:this.nowPermission==match.permission?true:false,
+					isChecked:this.nowPermission==match.permission?true:false,
+				}
+			});
+		},
+		methods: {
+			toggleSelect(item,index) {
+				this.permissionList.map((item,index)=>{
+					item.isChecked=false;
+				});
+				this.permissionList[item.value-1].isChecked=true;
+				this.selectedPermission=item.value;
+			},
+			saveChange(){
+				this.$store.dispatch({
+					type: 'roleSwitching/commActions',
+					payload: {
+						key: 'updatePermission',
+						data: {
+							permission: this.selectedPermission,
+						}
+					}
+				}).then((data)=>{
+					if(data!==null){
+						uni.navigateTo({
+							url: '/pages/home/home'
+						});
+					}
+				});
+			}
+		},
+	}
+</script>
+
+<style lang="less">
+	.role-page {
+		height: 100%;
+
+		.row-box {
+			.role-list {
+				height: 107.5rpx;
+				width: 750rpx;
+				background: #FFFFFF;
+				border-bottom: 0.62rpx solid #DADEE6;
+				position: relative;
+				.role-name {
+					font-size: 22.5rpx;
+					font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+					font-weight: bold;
+					color: #292C33;
+					float: left;
+					margin-left: 25rpx;
+					margin-top: 25rpx;
+				}
+				
+				.nowrole {
+					float: right;
+					font-size: 22.5rpx;
+					font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+					font-weight: 400;
+					color: #7A8599;
+					margin-top: 42.5rpx;
+					margin-right: 25rpx;
+				}
+				
+				.radio-item {
+					float: right;
+					margin-right: 25rpx;
+					margin-top: 41.25rpx;
+				
+					.icon {
+						width: 25rpx;
+						height: 25rpx;
+					}
+				}
+				
+				.task-msg {
+					font-size: 20rpx;
+					font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+					font-weight: 400;
+					color: #7A8599;
+					position: absolute;
+					top: 62.5rpx;
+					left: 25rpx;
+				}
+					
+			}
+		}
+
+		.btn-confirm {
+			width: 750rpx;
+			height: 75rpx;
+			background: #3377FF;
+			position: absolute;
+			bottom: 0rpx;
+
+			.btn-text {
+				font-size: 22.5rpx;
+				font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+				font-weight: 400;
+				color: #FFFFFF;
+				line-height: 75rpx;
+				margin-left: 352.5rpx;
+			}
+		}
+	}
+</style>

+ 13 - 0
pages/role-switching/server.js

@@ -0,0 +1,13 @@
+import { creatRequest } from '../../utils/request.js';
+
+const requestList = {
+  //角色设置
+  updatePermission: {
+    method: 'GET',
+    url: 'login/updatePermission'
+  },
+};
+export const commServer = ({ key, data }) => {
+  let obj = requestList[key];
+  return creatRequest(obj, data);
+}

+ 0 - 0
static/蓝色勾选.png → static/bottom-img.png


+ 0 - 0
static/禁用标志.png → static/disable-img.png


+ 0 - 0
static/icon新增(禁用).png → static/icon-add-dis.png


+ 0 - 0
static/icon新增.png → static/icon-add.png


二進制
static/icon-blueMore.png


+ 0 - 0
static/icon删除.png → static/icon-del.png


+ 0 - 0
static/icon禁用.png → static/icon-jinyong.png


+ 0 - 0
static/icon地点(禁用).png → static/icon-map-dis.png


+ 0 - 0
static/icon地点.png → static/icon-map.png


+ 0 - 0
static/icon启用.png → static/icon-qiyong.png


+ 0 - 0
static/icon上移(禁用).png → static/icon-shang-dis.png


+ 0 - 0
static/icon上移.png → static/icon-shang.png


+ 0 - 0
static/icon下移(禁用).png → static/icon-xia-dis.png


+ 0 - 0
static/icon下移.png → static/icon-xia.png


+ 0 - 0
static/images/小哥哥.png → static/images/boy-avatar.png


+ 0 - 0
static/images/男生.png → static/images/boy.png


+ 0 - 0
static/images/小姐姐.png → static/images/girl-avatar.png


+ 0 - 0
static/images/女生标识.png → static/images/girl.png


+ 0 - 0
static/images/icon更多.png → static/images/icon-more.png


+ 0 - 0
static/images/消息气泡.png → static/images/messagebubble.png


+ 0 - 0
static/images/个人中心背景.png → static/images/pcbg.png


+ 0 - 0
static/images/底纹.png → static/images/shade.png


+ 0 - 0
static/查看更多_.png → static/incon-more.png


二進制
static/list-close.png


二進制
static/list-open.png


+ 0 - 0
static/主题勾选.png → static/theme.png


+ 0 - 0
static/gean.png → static/theme0.png


+ 0 - 0
static/xitong.png → static/theme1.png


+ 0 - 0
static/绿色角标.png → static/top-img.png


二進制
static/橙色已读.png


二進制
static/橙色未读.png


二進制
static/绿色已读.png


二進制
static/绿色未读.png


+ 14 - 0
utils/arrFilter.js

@@ -0,0 +1,14 @@
+/**
+ * 判断原来的数组里是否有某个值,有就删除,没有就添加,然后返回新数组。
+ * 千里及
+ * 2021.2.2
+ */
+export const arrFilter = (key, oldKeys) => {
+	let keys = [];
+	if(oldKeys.includes(key)) {
+		keys = oldKeys.filter((item)=> item !== key);
+	} else {
+		keys = [...oldKeys, key];
+	}
+	return keys;
+}

+ 72 - 0
utils/dateHandle.js

@@ -0,0 +1,72 @@
+/**
+ * 千里及
+ * 2021.2.3
+ * 处理日期的对象
+ */
+export const dateHandle = {
+	/**
+	 * 获取今天的日期时间串
+	 */
+	todayDate: function() {
+		var date = new Date();
+		var year = date.getFullYear();
+		var month = date.getMonth() + 1;
+		var day = date.getDate();
+		return year + "-" + dateHandle.add0(month) + "-" + dateHandle.add0(day);
+	},
+	/**
+	 * 计算两个日期之间相差的天数
+	 * @param {Object} sDate1
+	 * @param {Object} sDate2
+	 */
+	dateDiff: function(sDate1, sDate2) {
+		if(sDate1 == sDate2){
+			return 0;
+		}
+		if(!sDate1){
+			var date = new Date();
+			var year = date.getFullYear();
+			var month = date.getMonth()+1;
+			var day = date.getDate();
+			sDate1 = year + "-" + month + "-" + day;
+		}
+		var oDate1, oDate2, iDays ; 
+		oDate1 = dateHandle.createDate(sDate1);
+		oDate2 = dateHandle.createDate(sDate2);
+		//把相差的毫秒数转换为天数  
+		iDays  =  parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24);
+		return  iDays;  
+	},
+	/**
+	 * 计算指定日期之后X天数的日期
+	 * @param {Object} dateTemp
+	 * @param {Object} days
+	 */
+	getNewData: function(dateTemp, days) {  
+		var nDate = dateHandle.createDate(dateTemp);
+		var millSeconds = Math.abs(nDate) + (days * 24 * 60 * 60 * 1000);  
+		var rDate = new Date(millSeconds);
+		var year = rDate.getFullYear();  
+		var month = rDate.getMonth() + 1;  
+		var date = rDate.getDate();  
+		return year + "-" + dateHandle.add0(month) + "-" + dateHandle.add0(date); 
+	},
+	/**
+	 * 比较第一个日期是否大于第二个
+	 * @param {Object} date1
+	 * @param {Object} date2
+	 */
+	compare: function(date1, date2) {
+		var oDate1 = dateHandle.createDate(date1);
+	 	var oDate2 = dateHandle.createDate(date2);
+		return oDate1.getTime() > oDate2.getTime();
+	},
+	createDate: function(str) {
+		var dateTemp = str.split("-");
+		return new Date(dateTemp[0], Number(dateTemp[1]) - 1, dateTemp[2]);
+	},
+	add0: function(num) {
+		if (Number(num) < 10) num = "0" + num; 
+		return num;
+	}
+}

+ 2 - 2
utils/request.js

@@ -8,7 +8,7 @@
 import { URL } from "./requestUrl";
 import { stringify } from 'qs';
 
-const BASE_URL = `${URL}/`;
+const BASE_URL = `${URL}/imed/pfm/`;
 let AllRequestNum = 0; // 存放请求数,以保证有请求未返回就持续loading
 
 /**
@@ -116,7 +116,7 @@ function notifyException(resArr, additional) {
       uni.showModal({
         title: '提示',
         content: '登录过期,请重新登录!',
-        success: function(_res) {
+        success: function (_res) {
           if (_res.confirm) {
             LoginExpired();
           } else if (_res.cancel) {

+ 119 - 0
utils/ws.js

@@ -0,0 +1,119 @@
+//心跳检测
+const heartCheck = {
+  timeout: 10000, //10s发一次心跳
+  timeoutObj: null,
+  serverTimeoutObj: null,
+  start(ws) {
+    let self = this;
+    this.timeoutObj && clearTimeout(this.timeoutObj);
+    this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
+    this.timeoutObj = setTimeout(() => {
+      // 表示连接已经关闭或者连接不能打开。
+      if (ws && ws.readyState === 3) return;
+      //发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
+      ws && ws.send({ data: "ping" });
+      self.serverTimeoutObj = setTimeout(() => {
+        ws && ws.close();
+        websocket.reconnect();
+      }, self.timeout + 3000);
+    }, this.timeout);
+  }
+};
+
+const websocket = {
+  ws: null,
+  url: '',
+  connected: false,
+  connecting: false,
+  reconnectTimeId: null,
+  callback: null, // 存放回调函数
+  reconnetCount: 0, // 重连次数
+  lockReconnect: false, // 避免ws重复连接
+  createWebSocket(callback) {
+
+    if (this.connected || this.connecting) { // 正在连接或者已经连接,请勿重复连接
+      return false
+    }
+    try {
+      if (callback) websocket.callback = callback;
+      this.connecting = true;
+      // 创建
+      this.ws = uni.connectSocket({
+        url: this.url,
+        success(data) {
+          console.log("websocket连接成功!");
+        }
+      });
+      // 监听 Ws 连接打开
+      this.ws.onOpen((res) => {
+        this.connecting = false;
+        this.connected = true;
+        console.log("websocket连接打开正常!");
+        //心跳检测重置
+        heartCheck.start(this.ws);
+        this.reconnetCount && (this.reconnetCount = 0);
+      });
+      this.ws.onError((res) => {
+        this.connecting = false;
+        this.connected = false;
+        console.log("ws连接错误!", res);
+        this.reconnect();
+      });
+      this.ws.onMessage((res) => {
+        if (res.data === 'ping') {
+          heartCheck.start(this.ws); //获取到消息,心跳检测重置
+          console.log("ws 没有收到消息");
+          this.reconnetCount && (this.reconnetCount = 0);
+        } else {
+          // const { type, data } = JSON.parse(res.data);
+          const { data } = res;
+          console.log("ws 收到消息啦:" + data);
+          if (callback) {
+            callback(data);
+          } else if (websocket.callback) {
+            websocket.callback(data);
+          }
+        }
+      });
+      this.ws.onClose((res) => {
+        this.connected = false;
+        this.ws = null;
+        // console.log('WebSocket 已关闭!');
+        // this.reconnect();
+      });
+    } catch (e) {// 重连
+      this.connected = false;
+      this.ws = null;
+      this.reconnect();
+    }
+  },
+  reconnect() { // 重连
+    if (this.lockReconnect) return;
+    if (this.reconnetCount === 6) {
+      this.close();
+      return
+    }
+    this.lockReconnect = true;
+    this.reconnetCount++;
+    this.reconnectTimeId && clearTimeout(this.reconnectTimeId);
+    this.reconnectTimeId = setTimeout(() => {//没连接上会一直重连,设置延迟避免请求过多
+      this.createWebSocket(websocket.callback);
+      this.lockReconnect = false;
+    }, 3000);
+  },
+  close() { // 关闭
+    if (this.ws && this.ws.close) {
+      this.ws.close && this.ws.close();
+      this.ws = null;
+    }
+    this.connected = false;
+    this.connecting = false;
+    this.lockReconnect = false;
+    this.reconnetCount = 0;
+    this.reconnectTimeId && clearTimeout(this.reconnectTimeId);
+    heartCheck.timeoutObj && clearTimeout(heartCheck.timeoutObj);
+    heartCheck.serverTimeoutObj && clearTimeout(heartCheck.serverTimeoutObj);
+  }
+}
+
+export default websocket;

+ 1 - 0
utils/wsUrl.js

@@ -0,0 +1 @@
+export const wsURL = `ws://192.168.1.45:8088/websocket/${hiId}/${user}/${permission}`;