fanghuisheng 2 years ago
parent
commit
f5ddc36d2f
100 changed files with 11687 additions and 0 deletions
  1. 10 0
      README.md
  2. BIN
      favicon.ico
  3. 42 0
      index.html
  4. 9 0
      jsconfig.json
  5. 72 0
      package.json
  6. 59 0
      src/App.vue
  7. 13 0
      src/api/business/mhxf/deviceManage/index.js
  8. 13 0
      src/api/business/mhxf/informationSelect/index.js
  9. 24 0
      src/api/business/mhxf/xunJian/collect.js
  10. 10 0
      src/api/business/mhxf/xunJian/index.js
  11. 91 0
      src/api/business/mhxf/xunJian/plan.js
  12. 24 0
      src/api/business/mhxf/xunJian/record.js
  13. 40 0
      src/api/index/index.js
  14. 55 0
      src/api/login.js
  15. 41 0
      src/api/system/user.js
  16. 116 0
      src/components/calendar/calendar.vue
  17. 20 0
      src/components/export.vue
  18. 175 0
      src/components/helang-compress/helang-compress.vue
  19. 205 0
      src/components/list-test/list-test.vue
  20. 123 0
      src/components/mpvue-echarts/src/echarts.vue
  21. 73 0
      src/components/mpvue-echarts/src/wx-canvas.js
  22. 102 0
      src/components/searchSelect/searchSelect.vue
  23. 45 0
      src/components/square/square.vue
  24. 236 0
      src/components/yealuo-select/yealuo-select.vue
  25. 120 0
      src/components/zzlb-mutiselect/zzlb-mutiselect.vue
  26. 29 0
      src/config.js
  27. 56 0
      src/main.js
  28. 182 0
      src/manifest.json
  29. 400 0
      src/pages.json
  30. 63 0
      src/pages/analyse/analyse.vue
  31. 13 0
      src/pages/authority/authority.vue
  32. 54 0
      src/pages/business/mhxf/coordination/index.vue
  33. 317 0
      src/pages/business/mhxf/deviceManage/index.vue
  34. 721 0
      src/pages/business/mhxf/informationSelect/index.vue
  35. 125 0
      src/pages/business/mhxf/xunJian/collect/components/collectDetail.vue
  36. 130 0
      src/pages/business/mhxf/xunJian/collect/components/collectRecord.vue
  37. 232 0
      src/pages/business/mhxf/xunJian/collect/index.vue
  38. 158 0
      src/pages/business/mhxf/xunJian/components/echarts/chart.vue
  39. 0 0
      src/pages/business/mhxf/xunJian/components/index.vue
  40. 250 0
      src/pages/business/mhxf/xunJian/plan/components/content.vue
  41. 89 0
      src/pages/business/mhxf/xunJian/plan/components/drawer.vue
  42. 242 0
      src/pages/business/mhxf/xunJian/plan/components/report.vue
  43. 266 0
      src/pages/business/mhxf/xunJian/plan/components/siteDetails.vue
  44. 73 0
      src/pages/business/mhxf/xunJian/plan/components/upload.vue
  45. 440 0
      src/pages/business/mhxf/xunJian/plan/index.vue
  46. 67 0
      src/pages/business/mhxf/xunJian/record/record.vue
  47. 130 0
      src/pages/business/mhxf/xunJian/record/recordDetail/index.vue
  48. 115 0
      src/pages/business/mhxf/xunJian/xunJian.vue
  49. 43 0
      src/pages/common/textview/index.vue
  50. 34 0
      src/pages/common/webview/index.vue
  51. 138 0
      src/pages/export/export.vue
  52. 504 0
      src/pages/index.vue
  53. 79 0
      src/pages/info/fireBase/fireBase.vue
  54. 91 0
      src/pages/info/fireBashDetail/fireBashDetail.vue
  55. 72 0
      src/pages/info/info.vue
  56. 192 0
      src/pages/info/pushList/pushList.vue
  57. 419 0
      src/pages/login.vue
  58. 75 0
      src/pages/mine/about/index.vue
  59. 634 0
      src/pages/mine/avatar/index.vue
  60. 114 0
      src/pages/mine/help/index.vue
  61. 194 0
      src/pages/mine/index.vue
  62. 138 0
      src/pages/mine/info/edit.vue
  63. 50 0
      src/pages/mine/info/index.vue
  64. 85 0
      src/pages/mine/pwd/index.vue
  65. 82 0
      src/pages/mine/setting/index.vue
  66. 157 0
      src/pages/setting/building/building.vue
  67. 271 0
      src/pages/setting/funReport/funReport.vue
  68. 405 0
      src/pages/setting/funReport/funcAdd/funcAdd.vue
  69. 235 0
      src/pages/setting/messagePush/messagePush.vue
  70. 185 0
      src/pages/setting/setting.vue
  71. 77 0
      src/pages/test/export.vue
  72. 105 0
      src/pages/test/test-1.vue
  73. 36 0
      src/pages/test/test-select-picker.vue
  74. 126 0
      src/pages/test/test.vue
  75. 183 0
      src/pages/work/index.vue
  76. 39 0
      src/permission.js
  77. 60 0
      src/plugins/auth.js
  78. 17 0
      src/plugins/index.js
  79. 74 0
      src/plugins/modal.js
  80. 30 0
      src/plugins/tab.js
  81. 551 0
      src/static/amap/1.html
  82. BIN
      src/static/amap/img/hz.png
  83. BIN
      src/static/amap/img/lc1.png
  84. BIN
      src/static/amap/img/lc2.png
  85. BIN
      src/static/amap/img/lc3.png
  86. BIN
      src/static/amap/img/lc4.png
  87. BIN
      src/static/amap/img/map1.png
  88. BIN
      src/static/amap/img/map2.png
  89. BIN
      src/static/amap/img/map3.png
  90. BIN
      src/static/amap/img/map4.png
  91. BIN
      src/static/amap/img/map5.png
  92. BIN
      src/static/amap/img/map6.png
  93. BIN
      src/static/amap/img/qxjy.png
  94. BIN
      src/static/amap/img/shjz.png
  95. 71 0
      src/static/amap/js/M_select/M_select.css
  96. 251 0
      src/static/amap/js/M_select/M_select.js
  97. BIN
      src/static/amap/js/M_select/down2.png
  98. BIN
      src/static/amap/js/M_select/down4.png
  99. BIN
      src/static/amap/js/M_select/down5.png
  100. BIN
      src/static/amap/js/M_select/up2.png

+ 10 - 0
README.md

@@ -0,0 +1,10 @@
+# sass移动端
+### 文档(吉超博、詹叶俊)
+### https://docs.apipost.cn/preview/61b2861af42252f6/a453b7fa01ec4c0f?target_id=2c54712b-9b38-4642-b3a9-7205d58072ca
+
+
+### 坐标系(GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统、
+
+
+### 账号:fire_admin
+### 密码:FIRE_admin123

BIN
favicon.ico


+ 42 - 0
index.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="UTF-8" />
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta name="viewport" content="width=device-width,initial-scale=1.0">
+	<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico">
+	<script>
+		var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+			CSS.supports('top: constant(a)'))
+		document.write(
+			'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+			(coverSupport ? ', viewport-fit=cover' : '') + '" />')
+	</script>
+
+	<!-- 高德地图 -->
+	<script type="text/javascript">
+		window._AMapSecurityConfig = {
+			securityJsCode: 'be916fcd16d0b33d228c49f0ff096b17',
+		}
+	</script>
+	<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=d4d73a7d572b6ff6028d5f67de62029a">
+	</script>
+
+	<!-- <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=ffc71dfd4e576596027f8f45a1b8fb2f">
+	</script> -->
+	<!-- <script src="https://webapi.amap.com/loader.js"></script> -->
+	<!-- <script type="text/javascript" src="//webapi.amap.com/ui/1.1/main.js"></script> -->
+	<title></title>
+	<!--preload-links-->
+	<!--app-context-->
+</head>
+
+<body>
+	<div id="app">
+		<!--app-html-->
+	</div>
+	<script type="module" src="/src/main.js"></script>
+</body>
+
+</html>

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "types": [
+      "@dcloudio/types",
+      "miniprogram-api-typings",
+      "mini-types"
+    ]
+  }
+}

+ 72 - 0
package.json

@@ -0,0 +1,72 @@
+{
+    "name": "uni-preset-vue",
+    "version": "0.0.0",
+    "scripts": {
+        "dev:app": "uni -p app",
+        "dev:custom": "uni -p",
+        "dev:h5": "uni",
+        "dev:h5:ssr": "uni --ssr",
+        "dev:mp-alipay": "uni -p mp-alipay",
+        "dev:mp-baidu": "uni -p mp-baidu",
+        "dev:mp-kuaishou": "uni -p mp-kuaishou",
+        "dev:mp-lark": "uni -p mp-lark",
+        "dev:mp-qq": "uni -p mp-qq",
+        "dev:mp-toutiao": "uni -p mp-toutiao",
+        "dev:mp-weixin": "uni -p mp-weixin",
+        "dev:quickapp-webview": "uni -p quickapp-webview",
+        "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
+        "dev:quickapp-webview-union": "uni -p quickapp-webview-union",
+        "build:app": "uni build -p app",
+        "build:custom": "uni build -p",
+        "build:h5": "uni build",
+        "build:h5:ssr": "uni build --ssr",
+        "build:mp-alipay": "uni build -p mp-alipay",
+        "build:mp-baidu": "uni build -p mp-baidu",
+        "build:mp-kuaishou": "uni build -p mp-kuaishou",
+        "build:mp-lark": "uni build -p mp-lark",
+        "build:mp-qq": "uni build -p mp-qq",
+        "build:mp-toutiao": "uni build -p mp-toutiao",
+        "build:mp-weixin": "uni build -p mp-weixin",
+        "build:quickapp-webview": "uni build -p quickapp-webview",
+        "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
+        "build:quickapp-webview-union": "uni build -p quickapp-webview-union",
+        "clear": "rimraf node_modules&&cnpm install"
+    },
+    "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
+        "@dcloudio/uni-app": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-app-plus": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-components": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-h5": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-alipay": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-baidu": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-lark": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-qq": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-mp-weixin": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3050320220729001",
+        "@element-plus/icons-vue": "^2.0.9",
+        "echarts": "^5.3.3",
+        "element-plus": "^2.2.12",
+        "node-sass": "^7.0.1",
+        "pinia": "^2.0.17",
+        "pinia-plugin-persistedstate": "^2.1.1",
+        "vue": "^3.2.37",
+        "vue-echarts": "^6.2.3",
+        "vue-i18n": "^9.1.9",
+        "vue-json-excel": "^0.3.0",
+        "vuex": "^4.0.2",
+        "weixin-js-sdk": "^1.6.0"
+    },
+    "devDependencies": {
+        "@dcloudio/types": "^3.0.7",
+        "@dcloudio/uni-automator": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/uni-stacktracey": "3.0.0-alpha-3050320220729001",
+        "@dcloudio/vite-plugin-uni": "3.0.0-alpha-3050320220729001",
+        "@vitejs/plugin-vue": "^2.3.3",
+        "sass": "^1.54.3",
+        "vite": "^2.9.14"
+    }
+}

+ 59 - 0
src/App.vue

@@ -0,0 +1,59 @@
+<script setup>
+import config from "./config";
+import store from "@/store";
+import { getToken } from "@/utils/auth";
+
+import { defineComponent, getCurrentInstance, inject, onMounted } from "vue";
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+
+let tab = inject("$tab");
+const { proxy } = getCurrentInstance();
+
+function initApp() {
+  // 初始化应用配置
+  initConfig();
+  // 检查用户登录状态
+  //#ifdef H5
+  checkLogin();
+  //#endif
+}
+
+function initConfig() {
+  getApp().globalData.config = config;
+}
+
+function checkLogin() {
+  if (!getToken()) {
+    proxy.$tab.reLaunch("/pages/login");
+  }
+}
+
+onShow(() => {
+  console.log("App Show");
+});
+
+onHide(() => {
+  console.log("App Hide");
+});
+
+onLaunch(() => {
+  console.log("App Launch");
+  initApp();
+});
+</script>
+
+<style lang="scss">
+@import "@/static/scss/index.scss";
+@import "@/static/scss/public.scss";
+@import "static/iconfont/iconfont.css";
+@import "static/iconfont/uciconfont/iconfont.css";
+</style>
+
+<style lang="scss">
+@import "@/uni_modules/uview-plus/index.scss";
+
+uni-page-body,
+uni-page-refresh {
+  height: 100%;
+}
+</style>

+ 13 - 0
src/api/business/mhxf/deviceManage/index.js

@@ -0,0 +1,13 @@
+import upload from "@/utils/upload";
+import request from "@/utils/request";
+
+/**
+ * @分类信息查询
+ */
+export function dataRtList(param) {
+  return request({
+    url: "/service-fire/dataRt/dataRtList",
+    method: "GET",
+    data: param,
+  });
+}

+ 13 - 0
src/api/business/mhxf/informationSelect/index.js

@@ -0,0 +1,13 @@
+import upload from "@/utils/upload";
+import request from "@/utils/request";
+
+/**
+ * @分类信息查询
+ */
+export function dataList(URL, param) {
+  return request({
+    url: URL,
+    method: "GET",
+    data: param,
+  });
+}

+ 24 - 0
src/api/business/mhxf/xunJian/collect.js

@@ -0,0 +1,24 @@
+import upload from "@/utils/upload";
+import request from "@/utils/request";
+
+/**
+ * @提交
+ */
+export function addSite(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/addSite",
+    method: "POST",
+    data: param,
+  });
+}
+
+/**
+ * @采集记录接口查询
+ */
+export function siteList(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/siteList",
+    method: "GET",
+    data: param,
+  });
+}

+ 10 - 0
src/api/business/mhxf/xunJian/index.js

@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+
+// ehcarts接口请求
+export function appPlanStatistics(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/appPlanStatistics",
+    method: "GET",
+    data: param,
+  });
+}

+ 91 - 0
src/api/business/mhxf/xunJian/plan.js

@@ -0,0 +1,91 @@
+import upload from "@/utils/upload";
+import request from "@/utils/request";
+
+//
+export function recordList(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/recordList",
+    method: "GET",
+    data: param,
+  });
+}
+
+//
+export function recordOption(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/recordOption",
+    method: "GET",
+    data: param,
+  });
+}
+
+//
+export function planList(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/planList",
+    method: "GET",
+    data: param,
+  });
+}
+
+//
+export function patrolInspectionPlan(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/patrolInspectionPlan",
+    method: "GET",
+    data: param,
+  });
+}
+
+//统计接口请求
+export function appPlanStatistics(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/appPlanStatistics",
+    method: "GET",
+    data: param,
+  });
+}
+
+// 图片上传
+export function uploadAvatar(data) {
+  return upload({
+    url: "/service-file/upload",
+    name: data.name,
+    filePath: data.filePath,
+  });
+}
+
+/**
+ * @站点详情
+ * @siteList站点详情信息存储
+ * @contentList内容详情信息存储
+ */
+export function siteDetails(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/siteDetails",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @地点列表
+ */
+export function planSonSiteDetails(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/planSonSiteDetails",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @提交
+ */
+export function updatePlan(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/updatePlan",
+    method: "POST",
+    data: param,
+  });
+}

+ 24 - 0
src/api/business/mhxf/xunJian/record.js

@@ -0,0 +1,24 @@
+import upload from "@/utils/upload";
+import request from "@/utils/request";
+
+/**
+ * @巡检记录列表数据请求
+ */
+export function getInspectionRecordList(param) {
+  return request({
+    url: "Inspection/getInspectionRecordList",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @巡检记录列详情数据请求
+ */
+export function getInspectionRecordDetails(param) {
+  return request({
+    url: "Inspection/getInspectionRecordDetails",
+    method: "GET",
+    data: param,
+  });
+}

+ 40 - 0
src/api/index/index.js

@@ -0,0 +1,40 @@
+import request from "@/utils/request";
+
+// 扫码请求
+export function scan_push(param) {
+  return request({
+    url: "/ScanPush/scan_push",
+    method: "GET",
+    data: param,
+  });
+}
+
+//echarts图表请求
+export function getHomePageData(param) {
+  return request({
+    url: "/Index/getHomePageData",
+    method: "GET",
+    data: param,
+  });
+}
+
+// 未处理告警请求
+export function getFunctionalModuleStatistics(param) {
+  return request({
+    url: "/Index/getFunctionalModuleStatistics",
+    method: "GET",
+    data: param,
+  });
+}
+
+// 登录方法
+// export function login(data) {
+//   return request({
+//     url: "/system/appLogin",
+//     headers: {
+//       isToken: false,
+//     },
+//     method: "POST",
+//     data: data,
+//   });
+// }

+ 55 - 0
src/api/login.js

@@ -0,0 +1,55 @@
+import request from "@/utils/request";
+
+// 登录方法
+export function login(data) {
+  return request({
+    url: "/system/appLogin",
+    headers: {
+      isToken: false,
+    },
+    method: "POST",
+    data: data,
+  });
+}
+
+// 获取用户详细信息
+export function getInfo() {
+  return request({
+    url: "/system/getInfo",
+    method: "get",
+  });
+}
+
+// 退出方法
+export function logout() {
+  return request({
+    url: "/system/logout",
+    method: "delete",
+  });
+}
+
+// 获取验证码
+export function getCodeImg(data) {
+  return request({
+    url: "/system/SendSms/noteSending",
+    headers: {
+      isToken: false,
+    },
+    method: "GET",
+    data: data,
+  });
+}
+
+/** 获取登录页数据 */
+export function getMobileTenantConfig(data) {
+  return request({
+    url: "/system/sysMobileTenantConfig/getMobileTenantConfig",
+    headers: {
+      isToken: false,
+    },
+    method: "GET",
+    data: data,
+  });
+}
+
+

+ 41 - 0
src/api/system/user.js

@@ -0,0 +1,41 @@
+import upload from '@/utils/upload'
+import request from '@/utils/request'
+
+// 用户密码重置
+export function updateUserPwd(oldPassword, newPassword) {
+  const data = {
+    oldPassword,
+    newPassword
+  }
+  return request({
+    url: '/system/user/profile/updatePwd',
+    method: 'put',
+    params: data
+  })
+}
+
+// 查询用户个人信息
+export function getUserProfile() {
+  return request({
+    url: '/system/user/profile',
+    method: 'get'
+  })
+}
+
+// 修改用户个人信息
+export function updateUserProfile(data) {
+  return request({
+    url: '/system/user/profile',
+    method: 'put',
+    data: data
+  })
+}
+
+// 用户头像上传
+export function uploadAvatar(data) {
+  return upload({
+    url: '/system/user/profile/avatar',
+    name: data.name,
+    filePath: data.filePath
+  })
+}

+ 116 - 0
src/components/calendar/calendar.vue

@@ -0,0 +1,116 @@
+<template>
+  <view class="leave_cont">
+    <view class="ul">
+      <view class="li">
+        <view class="flex1">
+          <picker
+            mode="date"
+            :value="start_date"
+            :start="start_date"
+            :end="other"
+            @change="bindDateChange"
+          >
+            <view class="date">{{ start_date }}</view>
+          </picker>
+        </view>
+      </view>
+      ~
+      <view class="li">
+        <view class="flex1">
+          <picker
+            mode="date"
+            :value="start_date"
+            :start="start_date"
+            @change="bindDateChange2"
+          >
+            <view class="date">{{ end_date }}</view>
+          </picker>
+        </view>
+      </view>
+      <image class="canlendar-icon" src="@/static/images/calendar.png"></image>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    const currentDate = this.getDate({
+      format: true,
+    });
+    return {
+      start_date: "请选择开始日期",
+      end_date: "请选择结束日期",
+      other: "请输入",
+    };
+  },
+  computed: {},
+  methods: {
+    // 选择日期
+    bindDateChange: function (e) {
+      this.start_date = e.target.value;
+    },
+    bindDateChange2: function (e) {
+      this.end_date = e.target.value;
+      this.other = this.end_date;
+    },
+    // 获取当前时间
+    getDate(type) {
+      const date = new Date();
+      let year = date.getFullYear();
+      let month = date.getMonth() + 1;
+      let day = date.getDate();
+
+      if (type === "start") {
+        year = year - 60;
+      } else if (type === "end") {
+        year = year + 2;
+      }
+      month = month > 9 ? month : "0" + month;
+      day = day > 9 ? day : "0" + day;
+      return `${year}-${month}-${day}`;
+    },
+  },
+};
+</script>
+
+<style>
+.leave_cont .ul {
+  border: 1px solid red;
+  margin: 24rpx 24rpx;
+  border: 1px solid #e8f1ff;
+  border-radius: 36rpx;
+  line-height: 70rpx;
+  position: relative;
+}
+
+.leave_cont .ul .li {
+  display: inline-block;
+  text-align: center;
+  width: 35%;
+}
+
+.leave_cont .ul .li text {
+  padding: 40rpx 0;
+  font-size: 30rpx;
+  color: #666666;
+  text-align: center;
+}
+
+.leave_cont .ul .li .flex1 {
+  flex: 1;
+  color: #999999;
+  font-size: 32rpx;
+}
+
+.date {
+  height: 42rpx;
+}
+.canlendar-icon {
+  width: 36rpx;
+  height: 36rpx;
+  position: absolute;
+  right: 30rpx;
+  top: 16rpx;
+}
+</style>

+ 20 - 0
src/components/export.vue

@@ -0,0 +1,20 @@
+<template>
+	<view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		name:"export",
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 175 - 0
src/components/helang-compress/helang-compress.vue

@@ -0,0 +1,175 @@
+<template>
+	<view class="compress">
+		<canvas :style="{ width: canvasSize.width,height: canvasSize.height}" canvas-id="myCanvas"></canvas>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				pic:'',
+				canvasSize: {
+					width: 0,
+					height: 0
+				}
+			}
+		},
+		methods: {
+			// 压缩
+			compress(params) {
+				return new Promise(async (resolve, reject) => {
+					// 等待图片信息
+					let info = await this.getImageInfo(params.src).then(info=>info).catch(err=>err);
+					
+					if(!info){
+						reject('获取图片信息异常');
+						return;
+					}
+					
+					// 设置最大 & 最小 尺寸
+					const maxSize = params.maxSize || 1080;
+					const minSize = params.minSize || 640;
+					
+					// 当前图片尺寸
+					let {width,height} = info;
+					
+					// 非 H5 平台进行最小尺寸校验
+					// #ifndef H5
+					if(width <= minSize && height <= minSize){
+						resolve(params.src);
+						return;
+					}
+					// #endif
+					
+					// 最大尺寸计算
+					if (width > maxSize || height > maxSize) {
+						if (width > height) {
+							height = Math.floor(height / (width / maxSize));
+							width = maxSize;
+						} else {
+							width = Math.floor(width / (height / maxSize));
+							height = maxSize;
+						}
+					}
+
+					// 设置画布尺寸
+					this.$set(this,"canvasSize",{
+						width: `${width}rpx`,
+						height: `${height}rpx`
+					});
+					
+					// Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新
+					setTimeout(() => {
+						const ctx = uni.createCanvasContext('myCanvas', this);
+						ctx.clearRect(0,0,width, height)
+						ctx.drawImage(info.path, 0, 0, uni.upx2px(width), uni.upx2px(height));
+						ctx.draw(false, () => {
+							uni.canvasToTempFilePath({
+								x: 0,
+								y: 0,
+								width: uni.upx2px(width),
+								height: uni.upx2px(height),
+								destWidth: width,
+								destHeight: height,
+								canvasId: 'myCanvas',
+								fileType: params.fileType || 'png',
+								quality: params.quality || 0.9,
+								success: (res) => {
+									// 在H5平台下,tempFilePath 为 base64
+									resolve(res.tempFilePath);
+								},
+								fail:(err)=>{
+									reject(null);
+								}
+							},this);
+						});
+					}, 300);
+				});
+			},
+			// 获取图片信息
+			getImageInfo(src){
+				return new Promise((resolve, reject)=>{
+					uni.getImageInfo({
+						src,
+						success: (info)=> {
+							resolve(info);
+						},
+						fail: () => {
+							reject(null);
+						}
+					});
+				});
+			},
+			// 批量压缩
+			batchCompress(params){
+				// index:进度,done:成功,fail:失败
+				let [index,done,fail] = [0,0,0];
+				// 压缩完成的路径集合
+				let paths = [];
+				// 批量压缩方法
+				let batch = ()=>{
+					return new Promise((resolve, reject)=>{
+						// 开始
+						let start = async ()=>{
+							params.progress && params.progress({
+								done,
+								fail,
+								count:params.batchSrc.length
+							});
+							// 等待图片压缩方法返回
+							let path = await next();
+							if(path){
+								done++;
+								paths.push(path);
+							}else{
+								fail++;
+							}
+							
+							index++;
+							// 压缩完成
+							if(index >= params.batchSrc.length){
+								resolve(true);
+							}else{
+								start();
+							}
+						}
+						start();
+					});
+				}
+				// 依次调用压缩方法
+				let next = ()=>{
+					return this.compress({
+						src:params.batchSrc[index],
+						maxSize:params.maxSize,
+						fileType:params.fileType,
+						quality:params.quality,
+						minSize:params.minSize
+					})
+				}
+				
+				// 全部压缩完成后调用
+				return new Promise(async (resolve, reject)=>{
+					// 批量压缩方法回调
+					let res = await batch();
+					if(res){
+						resolve(paths);
+					}else{
+						reject(null);
+					}
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.compress{
+		position: fixed;
+		width: 12px;
+		height: 12px;
+		overflow: hidden;
+		top: -99999px;
+		left: 0;
+	}
+</style>

+ 205 - 0
src/components/list-test/list-test.vue

@@ -0,0 +1,205 @@
+<template>
+	<view  class="site-wrapper" ref="contentWrapper">
+		
+		<!-- 筛选框start -->
+		<view class="ding">
+			<view class="cu-bar search bg-gray filter-section">
+				<view class="search-form round bg-white">
+					<text class="cuIcon-search"></text>
+					<input class="" @focus="InputFocus" @blur="InputBlur" :adjust-position="false" type="text" placeholder="请输入站点名称"
+					 confirm-type="search" v-model="nowSiteName"></input>
+				</view>
+				<view class="action">
+					<button class="cu-btn bg-blue round" @click="searchData">查询</button>
+				</view>
+			</view>
+		</view>
+		<!-- 筛选框end -->
+		
+		<!-- 站点列表start -->
+		<view class="site-items">
+			<view class="cu-list menu-avatar">
+				<view class="cu-item" :class="modalName=='move-box-'+ index?'move-cur':''" v-for="(item,index) in bindData"
+				 :key="index" :data-target="'move-box-' + index">
+					<view class="cu-avatar round lg"  v-bind:style="{ 'background-image': 'url(' + nowIcon+ ')' }"></view>
+					
+					
+					<view class="content" v-if="nowType==1"  @tap="goNowUrl(item)" >
+						<view class="text-grey site-tit">
+							<text style="width:260rpx;" class="inOneLine">{{item.siteName}}</text>
+							
+							<text style="font-size:28rpx;text-align:right"> 
+							   ( 共{{item.siteAlarmCount}}个未处理告警 )
+							</text>
+						</view>
+					</view>
+					
+					<view class="content" v-else  @tap="goNowUrl" @longpress="showDetail(item)">
+						<view class="text-grey site-tit">
+							{{item.siteName}}
+							<text>(共3个设备)</text>
+						</view>
+						<view class="showDetail" v-if="item.isShow" @tap.stop="goNowDetailUrl" >查看详情</view>
+					</view>
+					
+					
+					
+					
+					<view class="nav-right num">
+						<view class="text-grey">
+							<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 站点列表end -->
+	
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		// name: 'listTest',
+		props:{
+			bindType:{
+				type:Number,
+				default: ''
+			},
+			bindData:{
+				type:Array,
+				default: ''
+			},
+			bindUrl:{
+				type:String,
+				default: ''
+			},
+			bindDetailUrl:{
+				type:String,
+				default: ''
+			},
+			bindIcon:{
+				type:String,
+				default: ''
+			},
+			bindNum:{
+				type:String,
+				default: ''
+			},
+			bindSiteName:{
+				type:String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				modalName: null,
+				nowData:this.bindData,
+				nowUrl:this.bindUrl,
+				nowDetailUrl:this.bindDetailUrl,
+				nowIcon:this.bindIcon,
+				nowNum:this.bindNum,
+				nowType:this.bindType,
+				nowSiteName:this.bindSiteName,
+				
+			};
+		},
+		onPullDownRefresh() {
+			console.log('refresh');
+			setTimeout(function() {
+				uni.stopPullDownRefresh();
+			}, 1000);
+		},
+		
+		computed: {
+			newSiteListData() {
+				return this.nowData.map(item => {
+					this.$set(item, "isShow", false)
+					return item
+				})
+			}
+		
+		},
+		
+		mounted() {
+			document.addEventListener('click', (e) => {
+				if (e.target.className != 'showDetail') {
+					this.nowData.forEach(item => {
+						item.isShow = false
+					})
+				}
+			})
+		},
+		methods:{
+			
+			searchData(){
+				// console.log("a: "+val, oldVal);
+				this.$parent.getDataList({
+					"siteName":this.nowSiteName
+				})
+			},
+			
+			
+			// 隐藏显示
+			showDetail(e) {
+				// alert(1);
+				// 存储点击那一项的状态
+				const nowStatu = e.isShow;
+				// 将每一项列表的isShow设置为false,让所有的列表都隐藏
+				this.nowData.forEach(item => {
+					item.isShow = false
+				})
+				// 用于再次点击该项的取反
+				e.isShow = !nowStatu
+			},
+			
+			
+			
+			// 页面跳转
+			goNowUrl(item) {
+				if(item.siteAlarmCount){
+					uni.navigateTo({
+						url: this.nowUrl+'?companyCode='+item.companyCode,
+						success: res => {},
+						fail: () => {},
+						complete: () => {}
+					});
+				}
+				
+			},
+			
+			goNowDetailUrl() {
+				uni.navigateTo({
+					url: this.nowDetailUrl,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			},
+			InputFocus(e) {
+				this.InputBottom = e.detail.height
+			},
+			InputBlur(e) {
+				this.InputBottom = 0
+			},
+		}
+	}
+</script>
+
+<style>
+	
+	.showDetail {
+		position: absolute;
+		background: #fff;
+		box-shadow: 0 1px 6px 0 rgb(32 33 36 / 28%);
+		padding: 0rpx 32rpx;
+		border-radius: 10rpx;
+		top: 42rpx;
+		right: 0%;
+		z-index: 3000000;
+		font-size: 28rpx;
+	
+	}
+
+</style>

+ 123 - 0
src/components/mpvue-echarts/src/echarts.vue

@@ -0,0 +1,123 @@
+<template>
+	<canvas v-if="canvasId" class="ec-canvas" :id="canvasId" :canvasId="canvasId" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error"></canvas>
+</template>
+
+<script>
+import WxCanvas from './wx-canvas';
+
+export default {
+	props: {
+		canvasId: {
+			type: String,
+			default: 'ec-canvas'
+		},
+		lazyLoad: {
+			type: Boolean,
+			default: false
+		},
+		disableTouch: {
+			type: Boolean,
+			default: false
+		},
+		throttleTouch: {
+			type: Boolean,
+			default: false
+		}
+	},
+	// #ifdef H5
+	mounted() {
+		if (!this.lazyLoad) this.init();
+	},
+	// #endif
+	// #ifndef H5
+	onReady() {
+		if (!this.lazyLoad) this.init();
+	},
+	// #endif
+	methods: {
+		setChart(chart){
+			this.chart = chart
+		},
+		init() {
+			const { canvasId } = this;
+			this.ctx = wx.createCanvasContext(canvasId, this);
+
+			this.canvas = new WxCanvas(this.ctx, canvasId);
+
+			const query = wx.createSelectorQuery().in(this);
+			query
+				.select(`#${canvasId}`)
+				.boundingClientRect(res => {
+					if (!res) {
+						setTimeout(() => this.init(), 50);
+						return;
+					}
+					this.$emit('onInit', {
+						width: res.width,
+						height: res.height
+					});
+				})
+				.exec();
+		},
+		canvasToTempFilePath(opt) {
+			const { canvasId } = this;
+			this.ctx.draw(true, () => {
+				wx.canvasToTempFilePath({
+					canvasId,
+					...opt
+				});
+			});
+		},
+		touchStart(e) {
+			const { disableTouch, chart } = this;
+			if (disableTouch || !chart || !e.mp.touches.length) return;
+			const touch = e.mp.touches[0];
+			chart._zr.handler.dispatch('mousedown', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+			chart._zr.handler.dispatch('mousemove', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		},
+		touchMove(e) {
+			const { disableTouch, throttleTouch, chart, lastMoveTime } = this;
+			if (disableTouch || !chart || !e.mp.touches.length) return;
+
+			if (throttleTouch) {
+				const currMoveTime = Date.now();
+				if (currMoveTime - lastMoveTime < 240) return;
+				this.lastMoveTime = currMoveTime;
+			}
+
+			const touch = e.mp.touches[0];
+			chart._zr.handler.dispatch('mousemove', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		},
+		touchEnd(e) {
+			const { disableTouch, chart } = this;
+			if (disableTouch || !chart) return;
+			const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
+			chart._zr.handler.dispatch('mouseup', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+			chart._zr.handler.dispatch('click', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		}
+	}
+};
+</script>
+
+<style scoped>
+.ec-canvas {
+	width: 100%;
+	height: 100%;
+	flex: 1;
+}
+</style>

+ 73 - 0
src/components/mpvue-echarts/src/wx-canvas.js

@@ -0,0 +1,73 @@
+export default class WxCanvas {
+  constructor(ctx, canvasId) {
+    this.ctx = ctx;
+    this.canvasId = canvasId;
+    this.chart = null;
+
+    WxCanvas.initStyle(ctx);
+    this.initEvent();
+  }
+
+  getContext(contextType) {
+    return contextType === '2d' ? this.ctx : null;
+  }
+
+  setChart(chart) {
+    this.chart = chart;
+  }
+
+  attachEvent() {
+    // noop
+  }
+
+  detachEvent() {
+    // noop
+  }
+
+  static initStyle(ctx) {
+    const styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
+      'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
+      'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
+
+    styles.forEach((style) => {
+      Object.defineProperty(ctx, style, {
+        set: (value) => {
+          if ((style !== 'fillStyle' && style !== 'strokeStyle')
+            || (value !== 'none' && value !== null)
+          ) {
+            ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
+          }
+        },
+      });
+    });
+
+    ctx.createRadialGradient = () => ctx.createCircularGradient(arguments);
+  }
+
+  initEvent() {
+    this.event = {};
+    const eventNames = [{
+      wxName: 'touchStart',
+      ecName: 'mousedown',
+    }, {
+      wxName: 'touchMove',
+      ecName: 'mousemove',
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'mouseup',
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'click',
+    }];
+
+    eventNames.forEach((name) => {
+      this.event[name.wxName] = (e) => {
+        const touch = e.mp.touches[0];
+        this.chart._zr.handler.dispatch(name.ecName, {
+          zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
+          zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
+        });
+      };
+    });
+  }
+}

+ 102 - 0
src/components/searchSelect/searchSelect.vue

@@ -0,0 +1,102 @@
+<template>
+  <view>
+    <view class="searchSelect shadow" v-if="flag">
+      <view class="cu-bar search bg-white">
+        <view class="search-form round" style="margin-top: 0">
+          <input
+            @focus="InputFocus"
+            @blur="InputBlur"
+            @input="handleInput()"
+            v-model="searchInput"
+            :adjust-position="false"
+            type="text"
+            placeholder=""
+            confirm-type="search"
+            style="border: none"
+          />
+          <text class="cuIcon-search"></text>
+        </view>
+      </view>
+      <view class="select-items">
+        <view
+          class="select-item"
+          v-for="(item, index) in searchList"
+          @click="clickSelectItem(item, index)"
+          :key="index"
+          >{{ item }}</view
+        >
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "searchSelect",
+  props: {
+    flag: {
+      type: Boolean,
+      default: false,
+    },
+    searchList: {
+      type: Array,
+      // default: []
+    },
+    searchList2: {
+      type: Array,
+      // default: []
+    },
+  },
+  data() {
+    return {
+      searchInput: "",
+      // flag: false,
+      // searchList: [],
+      // searchList2: [],
+    };
+  },
+  onload() {
+    this.getSearchList();
+  },
+  methods: {
+    //请求
+    async getSearchList(ming = {}) {
+      const res = await this.$myRequest({
+        url: "Index/getSiteDropDownBox",
+        data: ming,
+      });
+      res.data.data.forEach((item) => {
+        this.searchList.push(item.siteName);
+        this.searchList2.push(item.siteName);
+      });
+    },
+    // 下拉选择
+    clickSelectItem(item, index) {
+      this.getSearchList({
+        siteName: item,
+      });
+      this.flag = false;
+    },
+    handleInput() {
+      var newlist = this.searchList2.filter(
+        (item) => item.indexOf(this.searchInput) > -1
+      );
+      this.searchList = newlist;
+    },
+
+    InputFocus(e) {
+      this.InputBottom = e.detail.height;
+    },
+    InputBlur(e) {
+      this.InputBottom = 0;
+    },
+
+    changeTab(Inv) {
+      that.navIdx = Inv;
+    },
+  },
+};
+</script>
+
+<style>
+</style>

+ 45 - 0
src/components/square/square.vue

@@ -0,0 +1,45 @@
+<template>
+	<view>
+		<view class="section2 section  bg-white margin-top-sm">
+			<view class="cu-list grid col-3 no-border">
+				<view class="cu-item justify-center align-center" @tap="goSiteList(item.redirectUrl)"  v-for="(item,index) in cuIconList" :key="index">
+					<image :src="`${item.imgUrl}`" style="width:100rpx;height:100rpx"></image>
+					<view class="cu-tag badge" v-if="item.badge!=0">
+						<block class="cu-tag badge" v-if="item.badge!=1">{{item.badge>99?'99+':item.badge}}</block>
+					</view>
+					<text>{{item.name}}</text>
+				</view>
+			</view>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		props:[ 'cuIconList'] ,  //接收外界传过来的数据
+		data() {
+			return {
+
+			}
+		},
+		methods: {
+			goSiteList(url) {
+				 // console.log(url);
+				uni.navigateTo({
+					url: url,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+	.cu-list.grid.no-border{
+		padding:30rpx 10rpx
+	}
+
+</style>

+ 236 - 0
src/components/yealuo-select/yealuo-select.vue

@@ -0,0 +1,236 @@
+<template>
+	<view class="yealuo-select" >
+		<view class="yealuo-background" @tap="isShow=false" v-show="isShow"></view>
+		<view class="yealuo-con" :style="inputStyle" @tap='isShow=isShow?false:nowData.length'>
+			<slot name='left'></slot>
+			<input :disabled="theDisabled" :placeholder="placeholder" v-model="theValue" @input="theInput"  @focus="theFocus" @blur="theBlur" autocomplete="off" />
+			<slot name='right' v-if="selectIco">
+				<svg class="icon" v-if="!isShow" style="width: 1.5em; height: 1.5em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="530"><path d="M512 714.666667c-8.533333 0-17.066667-2.133333-23.466667-8.533334l-341.333333-341.333333c-12.8-12.8-12.8-32 0-44.8 12.8-12.8 32-12.8 44.8 0l320 317.866667 317.866667-320c12.8-12.8 32-12.8 44.8 0 12.8 12.8 12.8 32 0 44.8L533.333333 704c-4.266667 8.533333-12.8 10.666667-21.333333 10.666667z" p-id="531"></path></svg>
+				<svg class="icon" v-else style="width: 1.5em; height: 1.5em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1927"><path d="M904.533333 674.133333l-362.666666-362.666666c-17.066667-17.066667-42.666667-17.066667-59.733334 0l-362.666666 362.666666c-17.066667 17.066667-17.066667 42.666667 0 59.733334 17.066667 17.066667 42.666667 17.066667 59.733333 0L512 401.066667l332.8 332.8c8.533333 8.533333 19.2 12.8 29.866667 12.8s21.333333-4.266667 29.866666-12.8c17.066667-17.066667 17.066667-42.666667 0-59.733334z" p-id="1928"></path></svg>
+			</slot>
+		</view>
+		<view class="yealuo-select" v-show="show" :style="selectStyle">
+			<view class="data">
+				<radio-group v-if="checkType=='radio'"  @change="selectCheckbox">
+				<view class="select-item" :class="'item-'+overflow" v-for="(item, index) in nowData" :key="index" >
+					<label class="item-text" :class="{active: theValue==item.value}">
+					<radio name="name1" checked v-if="theValue==item.value" :value="item.value+'|'+item.id"></radio>
+					<radio name="name1" v-else :value="item.value+'|'+item.id"></radio>
+					{{item.value}}
+					</label>
+				</view>
+				</radio-group>
+				<checkbox-group v-else-if="checkType=='checkbox'" @change="selectCheckbox">
+				<view class="select-item" :class="'item-'+overflow" v-for="(item, index) in nowData" :key="index" >
+					<label class="item-text" :class="{active: theValue.indexOf(item.value)!=-1 }">
+					<checkbox name="name1" checked v-if="theValue.indexOf(item.value)!=-1 " :value="item.value+'|'+item.id"></checkbox>
+					<checkbox name="name1" v-else :value="item.value+'|'+item.id"></checkbox>
+					{{item.value}}
+					</label>
+				</view>
+				</checkbox-group>
+				<radio-group v-else  @change="selectCheckbox">
+				<view class="select-item" :class="'item-'+overflow" v-for="(item, index) in nowData" :key="index" >
+					<label class="item-text" :class="{active: theValue==item.value}">
+					<radio name="name1" style="display: none;" checked v-if="theValue==item.value" :value="item.value+'|'+item.id"></radio>
+					<radio name="name1" style="display: none;" v-else :value="item.value+'|'+item.id"></radio>
+					{{item.value}}
+					</label>
+				</view>
+				</radio-group>
+			</view>
+			<view class="item-close" @tap="isShow=false">收起</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * v1.0.3
+	 * 最后修改: 2021.02.02
+	 * 创建: 2020.9.30
+	 * Author:yealuo.com
+	 * contact:470797533@qq.com
+	 */
+	let fontUnit = 'upx'
+	// #ifdef MP-WEIXIN
+	fontUnit = 'rpx'
+	// #endif
+	export default {
+		name: 'yealuoInputs',
+		props: {
+			placeholder: {
+				type: String,
+				default: ''
+			},
+			value: {
+				type: String,
+				default: ''
+			},
+			checkType: {
+				type: String,
+				default: ''
+			},
+			itemKey: {
+				type: String,
+				default: ''
+			},
+			width: {
+				type: String,
+				default: '600'
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			inputStyle: {
+				type: String,
+				default: ''
+			},
+			selectStyle: {
+				type: String,
+				default: ''
+			},
+			overflow: {
+				type: String,
+				default: 'auto'
+			},
+			tags: {
+				type: String,
+				default: ''
+			},
+			
+			binData:{
+				type:Array,
+				default: ''
+			},
+			selectIco:{
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				odData:this.binData,
+				nowData:this.binData,
+				isShow: false,
+				theValue: this.value,
+				theDisabled: this.disabled
+			}
+		},
+		watch: {
+			value(val){
+				this.theValue = val;
+			},
+			//监听数据变化
+			nowData:{
+				handler:function(){
+				 this.nowData=this.binData;
+				},
+				deep:true
+			}
+			
+		},
+		computed: {
+			show(){
+				return this.isShow && this.nowData.length
+			}
+			
+		},
+		methods: {
+			//获取焦点
+			theFocus(e){
+				this.nowData=this.odData;
+			},
+			//失去焦点
+			theBlur(e){
+				this.$emit('blur',e)
+			},
+			//获取输入值
+			theInput(e) {
+				var val=e.detail.value;
+				let data = [];
+				var odData=this.odData;
+				for(var i=0;i<odData.length;i++){
+					var isHas=false;
+					if(odData[i].value.indexOf(val)!=-1){
+						data.push(odData[i])
+						if(odData[i].value==val){
+							isHas=true;
+							var arr=[];
+							arr.push(odData[i].value+"|"+odData[i].id)
+						  this.$emit('getBackVal',arr);
+						}
+					}
+					if(!isHas){
+						var arr=[];
+						arr.push(val)
+						 this.$emit('getBackVal',arr);
+					}
+				}
+				this.nowData=data;
+			},
+			//下拉选中
+			selectCheckbox(e){
+				var val=e.target.value;
+				var str=val;
+				if(typeof(str)!="string"){
+					str="";
+					for(var i=0;i<val.length;i++){
+						var vt=val[i].split("|");
+						str+=i>0?","+vt[0]:vt[0];
+					}
+				}
+				else{
+					this.isShow = false;
+					str=str.split("|")[0];
+				}
+				this.$emit('getBackVal',val+"|"+this.tags)
+				this.theValue = str;
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+.yealuo-select{
+	max-width: 100%;
+	position: relative;
+	.yealuo-background{position: fixed;top:0;left:0;width: 750upx;height: 100%;}
+	.yealuo-con{display: flex;align-items: center;justify-content: center;
+		input{flex: 1;margin: 0 6upx;}
+	}
+	
+	.yealuo-select {
+		border: 1px solid #f3f3f4;
+		position: absolute;
+		z-index: 999;
+		background: #fff;
+		width: 100%;
+		.data{
+			max-height: 600upx;
+			padding: 10upx;
+			overflow: auto;
+			.select-item {width: 100%;color:#666;
+				.item-text{ width:100%; display:block;}
+				.active{font-weight: bold;}
+			}
+			.item-auto{overflow: auto;
+				.item-text{width: max-content;}
+			}
+			.item-hide .item-text{
+				overflow: hidden;
+				text-overflow:ellipsis;
+				white-space: nowrap;
+			}
+		}
+		.item-close {
+			padding: 20upx;
+			text-align: center;
+			font-size: 32upx;
+			border-top: 1px solid #f3f3f4;
+			color:#8F8F94;
+		}
+	}
+}
+</style>

+ 120 - 0
src/components/zzlb-mutiselect/zzlb-mutiselect.vue

@@ -0,0 +1,120 @@
+<template>
+  <view class="" style="width: 100%;">
+    <view class=" flex flex-wrap">
+      <view v-for="(item, index) in items" class="cu-tag bg-cyan radius">
+        <slot name="default" v-bind:item="item">{{ item }}</slot>
+        <text class="margin-left line-blue cuIcon-close round bg-red" @click="onremove(index)"></text>
+      </view>
+      <view class="flex ">
+        <input style1="width: 60px;" placeholder="输入..." type="text" v-model="query" @input="onshuru" @click="onquery" @keyup="onquery" />
+        <text
+          v-if="query"
+          class=" cuIcon-close "
+          @click="
+            query = '';
+            onquery();
+          "
+        ></text>
+        <text v-if="visible" class="cu-btn sm" @click="onqueren">确认</text>
+      </view>
+    </view>
+    <view v-if="visible" class="fixed bg-white">
+      <!-- <view class="flex justify-between ">
+        <button class="cu-btn " @click="visible = 0">取消</button>
+        <button class="cu-btn " @click="onqueren">确认</button>
+      </view> -->
+      <picker-view
+        class="picker-view"
+        @change="e => (pvvalue = mlist[e.detail.value[0]])"
+        indicator-style1="height:40px"
+        :style1="{ height: (mlist.length > 6 ? 6 : mlist.length / 2) * 34 + 'px' }"
+      >
+        <picker-view-column>
+          <view class="item" v-for="(item, index) in mlist" :key="index">
+            <slot name="option" v-bind:item="item">{{ item }}</slot>
+          </view>
+        </picker-view-column>
+      </picker-view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  props: {
+    url: { type: String, default: '' },
+    list: {
+      type: Array,
+      default: function() {
+        return [];
+      }
+    },
+    value: {
+      type: Array,
+      default: function() {
+        return [];
+      }
+    }
+  },
+  data() {
+    return {
+      visible: 0,
+      items: [],
+      query: '',
+      mlist: [],
+      pvvalue: []
+    };
+  },
+  computed: {},
+  watch: {
+    value() {
+      this.items = this.value || [];
+    }
+  },
+  methods: {
+    onquery() {
+      console.log(this.query);
+      this.visible = 1;
+      this.pvvalue = this.mlist[0];
+
+      if (this.list && this.list.length > 0) {
+        const l = this.list.filter(f => f.indexOf(this.query) > -1);
+        if (l.indexOf(this.pvvalue) === -1) {
+          this.pvvalue = l[0];
+        }
+        this.mlist = l;
+        return;
+      }
+      this.$http.get(this.url, { params: { title: this.query } }).then(r => {
+        r.data.list;
+        this.mlist = r.data.list;
+        this.pvvalue = this.mlist[0];
+      });
+    },
+    onremove(index) {
+      this.items.splice(index, 1);
+      this.$emit('input', this.items);
+    },
+    onshuru() {
+      this.visible = 1;
+    },
+    onqueren() {
+      this.visible = 0;
+      if (this.pvvalue) this.items.push(this.pvvalue);
+      this.$emit('input', this.items);
+    }
+  }
+};
+</script>
+<style>
+.picker-view {
+  width: 100%;
+  height: 100px;
+  /* margin-top: 20rpx; */
+}
+.item {
+  /* height: 50px; */
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+}
+</style>

+ 29 - 0
src/config.js

@@ -0,0 +1,29 @@
+// 应用全局配置
+export default {
+  // baseUrl: 'https://vue.ruoyi.vip/prod-api',
+  // baseUrl: 'http://localhost:8080/prod-api',
+  baseUrl: "http://172.16.120.165:13200/prod-api",
+  websiteUrl: "https://qhome.usky.cn",
+  // 应用信息
+  appInfo: {
+    // 应用名称
+    name: "usky-app-mobile",
+    // 应用版本
+    version: "1.0.0",
+    // 应用logo
+    logo: "/static/logo.png",
+    // 官方网站
+    site_url: "http://www.usky.cn/",
+    // 政策协议
+    agreements: [
+      {
+        title: "隐私政策",
+        url: "https://ruoyi.vip/protocol.html",
+      },
+      {
+        title: "用户服务协议",
+        url: "https://ruoyi.vip/protocol.html",
+      },
+    ],
+  },
+};

+ 56 - 0
src/main.js

@@ -0,0 +1,56 @@
+import { createSSRApp } from "vue";
+import App from "./App";
+import store from "./store"; // store
+import plugins from "./plugins"; // plugins
+import "./permission"; // permission
+
+import config from "@/config";
+
+// 引入json导出组件
+import JsonExcel from "vue-json-excel";
+
+// 引入微信js-sdk
+// import jweixin from 'weixin-js-sdk'
+
+// 引入UI组件
+import uviewPlus from "@/uni_modules/uview-plus";
+
+// 引入ElementPlus
+import ElementPlus from "element-plus";
+import locale from "element-plus/lib/locale/lang/zh-cn"; // 中文语言
+import "element-plus/theme-chalk/index.css";
+import * as Elicons from "@element-plus/icons-vue";
+
+export function createApp() {
+  const app = createSSRApp(App);
+
+  // 挂载json导出
+  app.component("downloadExcel", JsonExcel);
+
+  // 挂宅icons-vue组件icon
+  for (const name in Elicons) {
+    app.component(name, Elicons[name]);
+  }
+
+  // 添加全局变量
+  app.provide("$store", store);
+  app.config.globalProperties.$store = store;
+
+  app.provide("$BASE_URL", config.baseUrl);
+  app.config.globalProperties.$BASE_URL = config.baseUrl;
+
+  app.provide("$websiteUrl", config.websiteUrl);
+  app.config.globalProperties.$websiteUrl = config.websiteUrl;
+
+  app
+    .use(ElementPlus, {
+      locale: locale,
+    })
+    .use(uviewPlus)
+    .use(store)
+    .use(plugins);
+
+  return {
+    app,
+  };
+}

+ 182 - 0
src/manifest.json

@@ -0,0 +1,182 @@
+{
+    "name" : "智慧消防",
+    "appid" : "__UNI__D9E08B3",
+    "description" : "智慧消防",
+    "versionName" : "2.0",
+    "versionCode" : 2,
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "compatible" : {
+            "ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
+        },
+        "kernel" : {
+            "ios" : "WKWebview" //或者 "WKWebview"
+        },
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "VideoPlayer" : {},
+            "iBeacon" : {},
+            "Geolocation" : {},
+            "Maps" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "dSYMs" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "ad" : {},
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f"
+                    }
+                },
+                "geolocation" : {
+                    "system" : {
+                        "__platform__" : [ "android" ]
+                    },
+                    "amap" : {
+                        "__platform__" : [ "android" ],
+                        "appkey_ios" : "",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f"
+                    }
+                }
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "default",
+                "android" : {
+                    "hdpi" : "src/static/images/wt/bg.png"
+                }
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false,
+            "checkSiteMap" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "h5" : {
+        "publicPath" : "./",
+        "title" : "智慧消防",
+        "router" : {
+            "mode" : "hash"
+        },
+        "devServer" : {
+            "https" : false,
+            "proxy" : {
+                "/system" : {
+                    "target" : "http://172.16.120.165:13200/prod-api",
+                    "changeOrigin" : true,
+                    "secure" : false,
+                    "pathRewrite" : {
+                        "^/system" : "/system"
+                    }
+                }
+            }
+        },
+        "sdkConfigs" : {
+            "maps" : {
+                "amap" : {
+                    "key" : "d4d73a7d572b6ff6028d5f67de62029a",
+                    "securityJsCode" : "be916fcd16d0b33d228c49f0ff096b17",
+                    "serviceHost" : ""
+                }
+            }
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        },
+        "template" : "index.html"
+    },
+    "vueVersion" : "3",
+    "locale" : "zh-Hans"
+}

+ 400 - 0
src/pages.json

@@ -0,0 +1,400 @@
+{
+  "pages": [
+    {
+      "path": "pages/login",
+      "style": {
+        "navigationBarTitleText": "登录",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/index",
+      "style": {
+        "navigationBarTitleText": "",
+        "app-plus": {
+          "titleNView": {
+            "buttons": [
+              {
+                "text": "\ue607",
+                "fontSize": "18px",
+                // "redDot": true,
+                "float": "right",
+                "fontSrc": "/static/iconfont/iconfont.ttf",
+                "width": "auto"
+              }
+              // {
+              //     "text": "\ue63d",
+              //     "fontSize": "18px",
+              //     "float": "left",
+              //     "fontSrc": "/static/iconfont/iconfont.ttf",
+              //     "width": "auto"
+              // }
+            ]
+          }
+        }
+      }
+    },
+    {
+      "path": "pages/work/index",
+      "style": {
+        "navigationBarTitleText": "工作台"
+      }
+    },
+    {
+      "path": "pages/mine/index",
+      "style": {
+        "navigationBarTitleText": "我的"
+      }
+    },
+    {
+      "path": "pages/mine/avatar/index",
+      "style": {
+        "navigationBarTitleText": "修改头像"
+      }
+    },
+    {
+      "path": "pages/mine/info/index",
+      "style": {
+        "navigationBarTitleText": "个人信息"
+      }
+    },
+    {
+      "path": "pages/mine/info/edit",
+      "style": {
+        "navigationBarTitleText": "编辑资料"
+      }
+    },
+    {
+      "path": "pages/mine/pwd/index",
+      "style": {
+        "navigationBarTitleText": "修改密码"
+      }
+    },
+    {
+      "path": "pages/mine/setting/index",
+      "style": {
+        "navigationBarTitleText": "应用设置"
+      }
+    },
+    {
+      "path": "pages/mine/help/index",
+      "style": {
+        "navigationBarTitleText": "常见问题"
+      }
+    },
+    {
+      "path": "pages/mine/about/index",
+      "style": {
+        "navigationBarTitleText": "关于我们"
+      }
+    },
+    {
+      "path": "pages/common/webview/index",
+      "style": {
+        "navigationBarTitleText": "浏览网页"
+      }
+    },
+    {
+      "path": "pages/common/textview/index",
+      "style": {
+        "navigationBarTitleText": "浏览文本"
+      }
+    },
+    {
+      "path": "pages/export/export",
+      "style": {
+        "navigationBarTitleText": "导出",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "components/square/square",
+      "style": {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/authority/authority",
+      "style": {
+        "navigationBarTitleText": "授权",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/test/test",
+      "style": {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": false
+      }
+    },
+    //消防督察单模块 开始
+
+    //消防督察单模块 结束
+
+    //巡检模块 开始
+    {
+      "path": "pages/business/mhxf/xunJian/xunJian",
+      "style": {
+        "navigationBarTitleText": "巡检",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/plan/index",
+      "style": {
+        "navigationBarTitleText": "巡检计划",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/plan/components/siteDetails",
+      "style": {
+        "navigationBarTitleText": "站点详情",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/plan/components/content",
+      "style": {
+        "navigationBarTitleText": "巡检内容",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/plan/components/report",
+      "style": {
+        "navigationBarTitleText": "巡检上报",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/record/record",
+      "style": {
+        "navigationBarTitleText": "巡检记录",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/record/recordDetail/index",
+      "style": {
+        "navigationBarTitleText": "巡检记录详情",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/collect/index",
+      "style": {
+        "navigationBarTitleText": "点位采集",
+        "enablePullDownRefresh": false,
+        "app-plus": {
+          "titleNView": {
+            "buttons": [
+              {
+                "text": "采集记录",
+                "fontSize": "12px",
+                // "redDot": true,
+                "float": "right",
+                "fontSrc": "/static/iconfont/iconfont.ttf",
+                "width": "auto"
+              }
+            ]
+          }
+        }
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/collect/components/collectDetail",
+      "style": {
+        "navigationBarTitleText": "采集上报",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/business/mhxf/xunJian/collect/components/collectRecord",
+      "style": {
+        "navigationBarTitleText": "采集记录",
+        "enablePullDownRefresh": false,
+        "app-plus": {
+          "titleNView": {
+            "buttons": [
+              {
+                "text": "\ue7c7",
+                "fontSize": "18px",
+                // "redDot": true,
+                "float": "right",
+                "fontSrc": "/static/iconfont/uciconfont/iconfont.ttf",
+                "width": "auto"
+              }
+            ]
+          }
+        }
+      }
+    },
+    //巡检模块 结束
+
+    //信息查询 开始
+    {
+      "path": "pages/business/mhxf/informationSelect/index",
+      "style": {
+        "navigationBarTitleText": "信息查询",
+        "enablePullDownRefresh": false
+      }
+    },
+    //信息查询 结束
+
+    //设备管理 开始
+    {
+      "path": "pages/business/mhxf/deviceManage/index",
+      "style": {
+        "navigationBarTitleText": "设备管理",
+        "enablePullDownRefresh": false
+      }
+    },
+    //设备管理 结束
+
+    //协同作战地图 开始
+    {
+      "path": "pages/business/mhxf/coordination/index",
+      "style": {
+        "navigationBarTitleText": "协同作战地图",
+        "enablePullDownRefresh": false
+      }
+    },
+    //协同作战地图 结束
+
+    //消息 开始
+    {
+      "path": "pages/info/info",
+      "style": {
+        "navigationBarTitleText": "消息",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/info/fireBase/fireBase",
+      "style": {
+        "navigationBarTitleText": "消防知识库",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/info/pushList/pushList",
+      "style": {
+        "navigationBarTitleText": "消息推送",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/info/fireBashDetail/fireBashDetail",
+      "style": {
+        "navigationBarTitleText": "火灾逃生十大要诀",
+        "enablePullDownRefresh": false
+      }
+    },
+    //消息 结束
+
+    //分析 开始
+    {
+      "path": "pages/analyse/analyse",
+      "style": {
+        "navigationBarTitleText": "分析"
+      }
+    },
+    //分析 结束
+
+    //设置 开始
+    {
+      "path": "pages/setting/setting",
+      "style": {
+        "navigationBarTitleText": "设置"
+      }
+    },
+    {
+      "path": "pages/setting/messagePush/messagePush",
+      "style": {
+        "navigationBarTitleText": "消息推送设置",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/setting/building/building",
+      "style": {
+        "navigationBarTitleText": "建筑管理",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/setting/funReport/funReport",
+      "style": {
+        "navigationBarTitleText": "功能报备",
+        "enablePullDownRefresh": false,
+        "onReachBottomDistance": 100 //距离底部多远时触发 单位px
+      }
+    },
+    {
+      "path": "pages/setting/funReport/funcAdd/funcAdd",
+      "style": {
+        "navigationBarTitleText": "功能报备新增",
+        "enablePullDownRefresh": false
+      }
+    }
+    //设置 结束
+  ],
+  "tabBar": {
+    "color": "#a9a9a9",
+    "selectedColor": "#000000",
+    "borderStyle": "white",
+    "backgroundColor": "#ffffff",
+    "list": [
+      {
+        "pagePath": "pages/index",
+        "iconPath": "static/images/tabBar/home.png",
+        "selectedIconPath": "static/images/tabBar/home-selected.png",
+        "text": "主页"
+      },
+      // {
+      //   "pagePath": "pages/analyse/analyse",
+      //   "iconPath": "static/images/tabBar/analyse.png",
+      //   "selectedIconPath": "static/tabBar/analyse-selected.png",
+      //   "text": "分析"
+      // },
+      // {
+      //   "pagePath": "pages/info/info",
+      //   "iconPath": "static/images/tabBar/info.png",
+      //   "selectedIconPath": "static/tabBar/info-selected.png",
+      //   "text": "消息"
+      // },
+      // {
+      //   "pagePath": "pages/work/index",
+      //   "iconPath": "static/images/tabBar/work.png",
+      //   "selectedIconPath": "static/images/tabBar/work_.png",
+      //   "text": "工作台"
+      // },
+      {
+        "pagePath": "pages/mine/index",
+        "iconPath": "static/images/tabBar/setting.png",
+        "selectedIconPath": "static/images/tabBar/setting-selected.png",
+        "text": "我的"
+      }
+    ]
+  },
+  "globalStyle": {
+    "navigationBarTextStyle": "white",
+    "navigationBarTitleText": "uni-app",
+    "navigationBarBackgroundColor": "#149EFF",
+    "backgroundColor": "#F8F8F8"
+    // "enablePullDownRefresh": true
+  },
+  "condition": {
+    //模式配置,仅开发期间生效
+    "current": 0, //当前激活的模式(list 的索引项)
+    "list": [
+      {
+        "name": "", //模式名称
+        "path": "pages/index/index", //启动页面,必选
+        "query": "" //启动参数,在页面的onLoad函数里面得到
+      }
+    ]
+  }
+}

+ 63 - 0
src/pages/analyse/analyse.vue

@@ -0,0 +1,63 @@
+<template>
+  <view class="analyse-wrapper" style="height: 100%">
+    <view class="justify-center align-center text-center">
+      <u-image src="@/static/images/analyse/analyse-bg.png" width="100%" height="273rpx" :showLoading="false" :fade="false"></u-image>
+    </view>
+    <view class="cu-list menu-avatar padding-lr-sm padding-top-sm" style="height: calc(100% - 8.53125rem)">
+      <view class="cu-item margin-bottom-sm" @tap="goMonthReport()">
+        <view class="cu-avatar">
+          <image class="image-bg" src="@/static/images/analyse/yb-icon.png" />
+        </view>
+        <view class="content">
+          <view class="">月报</view>
+        </view>
+        <view class="nav-right">
+          <view class="text-grey">
+            <text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+          </view>
+        </view>
+      </view>
+      <view class="cu-item margin-bottom-sm" @tap="goBuildingCheck()">
+        <view class="cu-avatar">
+          <image class="image-bg" src="@/static/images/analyse/build-icon.png" />
+        </view>
+        <view class="content">
+          <view class="">建筑体检</view>
+        </view>
+        <view class="nav-right">
+          <view class="text-grey">
+            <text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    goMonthReport() {
+      // uni.navigateTo({
+      // 	url: '/pages/analyse/monthReport/monthReport',
+      // });
+    },
+    goBuildingCheck() {
+      // uni.navigateTo({
+      // 	url: '/pages/analyse/buildingCheck/buildingCheck',
+      // });
+    },
+  },
+};
+</script>
+
+<style>
+body {
+  background: #fff;
+}
+</style>
+
+<style lang="scss"></style>

+ 13 - 0
src/pages/authority/authority.vue

@@ -0,0 +1,13 @@
+<template>
+  <view style="text-align: center; padding-top: 100rpx">
+    <image src="@/static/images/index/chart3-2.png" style="width: 100rpx; height: 100rpx"></image>
+    <br />
+    <br />
+    <view>该用户权限尚未开通,请联系管理员!</view>
+  </view>
+</template>
+
+<script setup>
+</script>
+
+<style></style>

+ 54 - 0
src/pages/business/mhxf/coordination/index.vue

@@ -0,0 +1,54 @@
+<template>
+  <web-view ref="amapView" src="/../static/amap/1.html" bindmessage="receiveMessage"></web-view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { getCurrentInstance, ref, onMounted, inject, shallowRef, reactive, nextTick } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/collect/components/collectRecord",
+    });
+  } else {
+  }
+});
+
+onLoad((options) => {});
+
+onReady(() => {});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.coordination {
+}
+.headerTop {
+  display: flex;
+  background-color: transparent;
+  width: 100%;
+}
+
+.is-selected {
+  color: #1989fa;
+} 
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: transparent;
+  height: 100%;
+}
+</style>

+ 317 - 0
src/pages/business/mhxf/deviceManage/index.vue

@@ -0,0 +1,317 @@
+<template>
+  <u-sticky bgColor="#fff" style="border-bottom: 1px #ececec solid">
+    <u-tabs :list="list" @click="tabsClick" :current="current" :scrollable="list.length >= 5 ? true : false"></u-tabs>
+  </u-sticky>
+
+  <view class="deviceManage" @touchstart="fingerstart" @touchend="fingerend">
+    <uni-swipe-action>
+      <uni-swipe-action-item style="background-color: #ffffff">
+        <view class="content1">
+          <view style="padding: 10px">
+            <u-input style="border-radius: 50px" v-model="dataInput" @blur="blur" prefixIcon="search" prefixIconStyle="color: #0c7bf9" placeholder="请输入设备编号"> </u-input>
+          </view>
+
+          <view style="text-align: center; padding: 10px; color: rgb(189, 189, 189); font-size: 14px" v-if="!dataRes">暂无数据</view>
+
+          <u-collapse @change="change" @close="close" @open="open" accordion v-else>
+            <u-collapse-item class="uCollapseItem" v-for="da in dataList" :key="da">
+              <template v-slot:title>
+                <view style="display: flex">
+                  <view class="cu-avatar lg" style="margin: 0 10px auto 0; background-color: rgba(0, 0, 0, 0)">
+                    <image class="image-bg" style="width: 80rpx; height: 80rpx" src="@/static/images/deviceManage/1.png"></image>
+                  </view>
+                  <view style="width: 100%">
+                    <view style="display: flex; color: #000000">
+                      <view>设备编号:{{ da.deviceCode }}</view>
+                      <view v-if="da.deviceStatus == 0" style="margin-left: 20px; font-size: 12px; background-color: #aeaeae; color: #ffffff; padding: 0 5px; border-radius: 20px; line-height: 20px">
+                        离线
+                      </view>
+                      <view
+                        v-else-if="da.deviceStatus == 1"
+                        style="margin-left: 20px; font-size: 12px; background-color: #12c100; color: #ffffff; padding: 0 5px; border-radius: 20px; line-height: 20px"
+                      >
+                        正常
+                      </view>
+                      <view
+                        v-else-if="da.deviceStatus == 2"
+                        style="margin-left: 20px; font-size: 12px; background-color: #ff1313; color: #ffffff; padding: 0 5px; border-radius: 20px; line-height: 20px"
+                      >
+                        故障
+                      </view>
+                      <view v-else style="margin-left: 20px; font-size: 12px; background-color: #0d88f0; color: #ffffff; padding: 0 5px; border-radius: 20px; line-height: 20px"> 告警 </view>
+                    </view>
+                    <view style="display: flex; font-size: 14px; color: #666666; margin: 10px 0">
+                      <view style="width: 50%; word-break: break-all">监测对象:{{ da.installAddress }}</view>
+                      <view style="width: 50%; word-break: break-all; padding-left: 10px">所属单位:{{ da.companyName }}</view>
+                    </view>
+                    <view style="display: flex; font-size: 14px; color: #666666">
+                      <view style="width: 50%; word-break: break-all">负责人:{{ da.linkPerson }}</view>
+                      <view style="width: 50%; word-break: break-all; padding-left: 10px">联系电话:{{ da.linkPhone }}</view>
+                    </view>
+                  </view>
+                </view>
+              </template>
+
+              <view class="u-collapse-content">
+                <!-- <view style="display: flex; flex-wrap: wrap; margin-left: 5%">
+                  <view style="width: 50%; height: 30px; line-height: 30px" v-for="ch in da.dataList" :key="ch">
+                    <span>{{ ch.label }}:</span>
+                    <span :style="ch.value === '正常' ? 'color:#12C100' : 'color:#FF0101'">{{ ch.value }}</span>
+                  </view>
+                </view> -->
+                <view style="display: flex; flex-wrap: wrap; margin-left: 5%">
+                  <view style="width: 50%; height: 30px; line-height: 30px" v-for="ch in da.dataList" :key="ch">
+                    <span>{{ ch.portName }}:</span>
+                    <span>{{ ch.portData }}</span>
+                  </view>
+                </view>
+              </view>
+            </u-collapse-item>
+          </u-collapse>
+        </view>
+      </uni-swipe-action-item>
+    </uni-swipe-action>
+  </view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive, watchEffect } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { dataRtList } from "@/api/business/mhxf/deviceManage";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const dataInput = ref("");
+
+const dataRes = ref(0);
+const systemTypeNo = ref(5);
+const dataList = ref([]); //设备管理数据存储
+
+const current = ref(0);
+const list = ref([
+  {
+    id: 5,
+    name: "电气火灾",
+  },
+  {
+    id: 4,
+    name: "烟感",
+  },
+  {
+    id: 3,
+    name: "水系统",
+    badge: {
+      // isDot: true,
+      // value: 5,
+    },
+  },
+]);
+
+const startData = ref({
+  clientX: "",
+  clientY: "",
+});
+const updDistance = ref(100);
+const lrDistance = ref(50);
+const topMed = ref("");
+const bottomMed = ref("");
+const leftMed = ref("");
+const rightMed = ref("");
+
+/**
+ * @tabs点击事件
+ */
+function tabsClick(e) {
+  current.value = e.index;
+  // alert(current.value)
+  dataInput.value = "";
+}
+
+/**
+ * @当按下去的时候
+ */
+function fingerstart(e) {
+  // 记录 距离可视区域左上角 左边距 和 上边距
+  startData.value.clientX = e.changedTouches[0].clientX;
+  startData.value.clientY = e.changedTouches[0].clientY;
+}
+/**
+ * @当抬起来的时候
+ */
+function fingerend(e) {
+  // 当前位置 减去 按下位置 计算 距离
+  const subX = e.changedTouches[0].clientX - startData.value.clientX;
+  const subY = e.changedTouches[0].clientY - startData.value.clientY;
+  if (subY > updDistance.value || subY < -updDistance.value) {
+    if (subY > updDistance.value) {
+      bottomscroll(subY);
+    } else if (subY < -updDistance.value) {
+      topscroll(subY);
+    }
+  } else {
+    if (subX > lrDistance.value) {
+      rightscroll(subX);
+    } else if (subX < -lrDistance.value) {
+      leftscroll(subX);
+    } else {
+      console.log("无效操作");
+    }
+  }
+}
+/**
+ * @上滑触发
+ */
+function topscroll(dista) {
+  topMed.value ? (topMed.value = dista) : (topMed.value = null);
+  console.log("触发了上滑方法!");
+}
+/**
+ * @下滑触发
+ */
+function bottomscroll(dista) {
+  bottomMed.value ? (bottomMed.value = dista) : (bottomMed.value = null);
+  console.log("触发了下滑方法!");
+}
+/**
+ * @右滑触发
+ */
+function rightscroll(dista) {
+  rightMed.value ? (rightMed.value = dista) : (rightMed.value = null);
+  console.log("触发了右滑方法!");
+  if (current.value >= 1) {
+    current.value--;
+  } else {
+    current.value = 0;
+  }
+}
+/**
+ * @左滑触发
+ */
+function leftscroll(dista) {
+  leftMed.value ? (leftMed.value = dista) : (leftMed.value = null);
+  console.log("触发了左滑方法!");
+  if (current.value < list.value.length - 1) {
+    current.value++;
+  } else {
+    current.value = 0;
+  }
+}
+function blur(e) {
+  if (dataInput.value) {
+    classifySearch({ systemType: 5, deviceCode: dataInput.value });
+  }
+}
+
+//分类信息查询 start
+function classifySearch(params) {
+  // classifyData.value = []
+
+  dataRtList(params).then((res) => {
+    console.log("------");
+    console.log(res.data.records);
+
+    dataList.value = res.data.records;
+
+    if (!dataList.value[0]) {
+      dataRes.value = 0;
+    } else {
+      dataRes.value = 1;
+    }
+  });
+}
+// end
+function goSearch() {
+  if (current.value == 0) {
+    console.log(current.value);
+    systemTypeNo.value = 5;
+  } else if (current.value == 1) {
+    systemTypeNo.value = 1;
+    console.log(current.value);
+  } else if (current.value == 2) {
+    systemTypeNo.value = 2;
+    console.log(current.value);
+  }
+  classifySearch({ systemType: systemTypeNo.value, deviceCode: dataInput.value, pageNum: "", pageSize: "" });
+}
+
+watchEffect(() => {
+  goSearch();
+});
+
+function open(e) {
+  // console.log('open', e)
+}
+function close(e) {
+  // console.log('close', e)
+}
+function change(e) {
+  // console.log('change', e)
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/collect/components/collectRecord",
+    });
+  } else {
+  }
+});
+
+onLoad((options) => {
+  // classifySearch({systemType:5,deviceCode:dataInput.value})
+});
+
+onReady(() => {});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+body {
+  background: #fff;
+}
+.is-selected {
+  color: #1989fa;
+}
+
+.deviceManage {
+  height: calc(100% - 45px);
+  background-color: #ffffff;
+
+  .content1 {
+    .u-row {
+      .u-col {
+        border: 1px #e4e3e3 solid;
+        border-right: 0px;
+        border-bottom: 0px;
+      }
+
+      .u-col:last-child {
+        border-right: 1px #e4e3e3 solid;
+      }
+    }
+
+    .u-row:last-child {
+      .u-col {
+        border-bottom: 1px #e4e3e3 solid;
+      }
+    }
+  }
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+  height: 100%;
+}
+</style>

+ 721 - 0
src/pages/business/mhxf/informationSelect/index.vue

@@ -0,0 +1,721 @@
+<template>
+  <u-sticky bgColor="#fff" style="border-bottom: 1px #ececec solid">
+    <u-tabs :list="list" @click="tabsClick" :current="current"></u-tabs>
+  </u-sticky>
+
+  <view class="informationSelect" @touchstart="fingerstart" @touchend="fingerend" style="background-color: #ffffff; padding: 10px">
+    <uni-swipe-action>
+      <uni-swipe-action-item>
+        <!-- 各类查询 start -->
+        <view class="content1">
+          <u-input style="border-radius: 50px; margin-bottom: 10px" @blur="blur" v-model="dataInput" prefixIcon="search" prefixIconStyle="color: #0c7bf9" :placeholder="placeholderText"> </u-input>
+          <view style="text-align: center; color: rgb(189, 189, 189); font-size: 14px" v-if="!dataRes">暂无数据</view>
+          <view v-if="current == 8">
+            <view class="con" style="">
+              <view class="time">{{ newTime }}</view>
+              <video src="http://file.usky.cn/statics/video/20230203.mp4" autoplay :controls="false" :show-center-play-btn="false" :loop="true" style="width: 100%"></video>
+            </view>
+          </view>
+          <view v-else>
+            <u-row v-for="po in classifyData" :key="po" style="height: 36px; line-height: 36px">
+              <u-col span="4">
+                <view style="text-align: right; padding: 0px 5px 0px 5px">{{ po.title }}</view>
+              </u-col>
+              <u-col span="8">
+                <view style="text-align: left; padding: 0px 5px 0px 5px">{{ po.value }}</view>
+              </u-col>
+            </u-row>
+          </view>
+        </view>
+        <!-- 各类查询 end -->
+      </uni-swipe-action-item>
+    </uni-swipe-action>
+  </view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive, watchEffect } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { dataList } from "@/api/business/mhxf/informationSelect";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const dataInput = ref("");
+const current = ref(0);
+const classifyUrl = ref("");
+const classifyCode = ref("");
+const placeholderText = ref("");
+const dataRes = ref(0);
+
+const list = ref([
+  {
+    id: 1,
+    name: "警情查询",
+  },
+  {
+    id: 2,
+    name: "火灾查询",
+  },
+  {
+    id: 3,
+    name: "人员查询",
+    badge: {
+      // isDot: true,
+      // value: 5,
+    },
+  },
+  {
+    id: 4,
+    name: "车辆查询",
+    badge: {
+      // value: 5,
+    },
+  },
+  {
+    id: 5,
+    name: "站点查询",
+    badge: {
+      // value: 5,
+    },
+  },
+  {
+    id: 6,
+    name: "消火栓",
+    badge: {
+      // value: 5,
+    },
+  },
+
+  {
+    id: 7,
+    name: "重点单位",
+    badge: {
+      // value: 5,
+    },
+  },
+  {
+    id: 8,
+    name: "消防检查信息",
+    badge: {
+      // value: 5,
+    },
+  },
+  {
+    id: 9,
+    name: "视频监控",
+    badge: {
+      // value: 5,
+    },
+  },
+]);
+
+const startData = ref({
+  clientX: "",
+  clientY: "",
+});
+const updDistance = ref(100);
+const lrDistance = ref(50);
+const topMed = ref("");
+const bottomMed = ref("");
+const leftMed = ref("");
+const rightMed = ref("");
+const classifyData = ref([]); //警情查询数据存储
+
+/**
+ * @当按下去的时候
+ */
+function fingerstart(e) {
+  // 记录 距离可视区域左上角 左边距 和 上边距
+  startData.value.clientX = e.changedTouches[0].clientX;
+  startData.value.clientY = e.changedTouches[0].clientY;
+}
+/**
+ * @当抬起来的时候
+ */
+function fingerend(e) {
+  // 当前位置 减去 按下位置 计算 距离
+  const subX = e.changedTouches[0].clientX - startData.value.clientX;
+  const subY = e.changedTouches[0].clientY - startData.value.clientY;
+  if (subY > updDistance.value || subY < -updDistance.value) {
+    if (subY > updDistance.value) {
+      bottomscroll(subY);
+    } else if (subY < -updDistance.value) {
+      topscroll(subY);
+    }
+  } else {
+    if (subX > lrDistance.value) {
+      rightscroll(subX);
+    } else if (subX < -lrDistance.value) {
+      leftscroll(subX);
+    } else {
+      console.log("无效操作");
+    }
+  }
+}
+/**
+ * @上滑触发
+ */
+function topscroll(dista) {
+  topMed.value ? (topMed.value = dista) : (topMed.value = null);
+  console.log("触发了上滑方法!");
+}
+/**
+ * @下滑触发
+ */
+function bottomscroll(dista) {
+  bottomMed.value ? (bottomMed.value = dista) : (bottomMed.value = null);
+  console.log("触发了下滑方法!");
+}
+/**
+ * @右滑触发
+ */
+function rightscroll(dista) {
+  rightMed.value ? (rightMed.value = dista) : (rightMed.value = null);
+  console.log("触发了右滑方法!");
+  if (current.value >= 1) {
+    current.value--;
+  } else {
+    current.value = 0;
+  }
+}
+/**
+ * @左滑触发
+ */
+function leftscroll(dista) {
+  leftMed.value ? (leftMed.value = dista) : (leftMed.value = null);
+  console.log("触发了左滑方法!");
+  if (current.value < list.value.length - 1) {
+    current.value++;
+  } else {
+    current.value = 0;
+  }
+}
+
+function blur(e) {
+  if (dataInput.value) {
+    goSearch();
+  }
+}
+
+/**
+ * @tabs点击事件
+ */
+function tabsClick(e) {
+  current.value = e.index;
+  console.log(current.value);
+  dataInput.value = "";
+}
+
+function goSearch() {
+  if (current.value == 0) {
+    //警情查询
+    classifyUrl.value = "/service-fire/demPoliceInfo/page";
+    placeholderText.value = "请输入案件编号";
+    classifySearch(classifyUrl.value, {
+      caseCode: dataInput.value,
+    });
+  } else if (current.value == 1) {
+    //火灾查询
+    placeholderText.value = "请输入火灾地址";
+    classifyUrl.value = "/service-fire/demFireStatisticsAttach/page";
+    classifySearch(classifyUrl.value, {
+      address: dataInput.value,
+    });
+  } else if (current.value == 2) {
+    //人员查询
+    placeholderText.value = "请输入值班人员名称";
+    classifyUrl.value = "/service-fire/unitBeOnDuty/list";
+    classifySearch(classifyUrl.value, {
+      name: dataInput.value,
+    });
+  } else if (current.value == 3) {
+    //车辆信息
+    placeholderText.value = "请输入车牌号";
+    classifyUrl.value = "/service-fire/unitBeOnDuty/vehiclelist";
+    classifySearch(classifyUrl.value, {
+      licensePlate: dataInput.value,
+    });
+  } else if (current.value == 4) {
+    //站点查询
+    placeholderText.value = "请输入站点名称";
+    classifyUrl.value = "/service-fire/unitBeOnDuty/page";
+    classifySearch(classifyUrl.value, {
+      stationName: dataInput.value,
+    });
+  } else if (current.value == 5) {
+    //消火栓
+    placeholderText.value = "请输入水源名称";
+    classifyUrl.value = "/service-fire/demWaterSource/waterSourceList";
+    classifySearch(classifyUrl.value, {
+      waterName: dataInput.value,
+    });
+  } else if (current.value == 6) {
+    //重点单位
+    placeholderText.value = "请输入单位名称";
+    classifyUrl.value = "/service-fire/baseCompany/companyList";
+    classifySearch(classifyUrl.value, {
+      companyName: dataInput.value,
+    });
+  } else if (current.value == 7) {
+    //消防检查信息
+    placeholderText.value = "请输入单位ID";
+    classifyUrl.value = "/service-fire/demFireInspect/fireInspectList";
+    classifySearch(classifyUrl.value, {
+      companyId: dataInput.value,
+    });
+  } else if (current.value == 8) {
+    //消防检查信息
+    placeholderText.value = "";
+    // classifyUrl.value = "/service-fire/demFireInspect/fireInspectList";
+    // classifySearch(classifyUrl.value, {
+    //   companyId: dataInput.value,
+    // });
+  }
+}
+
+//分类信息查询 start
+function classifySearch(URL, params) {
+  classifyData.value = [];
+
+  dataList(URL, params).then((res) => {
+    if (res.status == "SUCCESS") {
+      if (current.value == 2) {
+        var records = res.data[0][0];
+      } else if (current.value == 3) {
+        var records = res.data.data[0];
+      } else {
+        var records = res.data.records[0];
+      }
+      if (!records) {
+        dataRes.value = 0;
+      } else {
+        dataRes.value = 1;
+      }
+
+      switch (current.value) {
+        case 0: //警情查询
+          var classifyTitle = [
+            "案件编号",
+            "主管支队",
+            "案件时间段",
+            "通知到场时间",
+            "通知出水时间",
+            "通知控制时间",
+            "通知熄火时间",
+            "通知返队时间",
+            "区域",
+            "案件类型",
+            "案发地址",
+            "立案时间",
+            "立案日期",
+            "处置对象",
+            "案件等级",
+            "主管中队",
+            "区县",
+            "案件状态",
+            "案件性质",
+            "填表时间",
+            "街镇",
+            "创建时间",
+          ];
+          var classifyValue = [
+            records.caseCode,
+            records.branch,
+            records.timeSlot,
+            records.noticeArrivalTime,
+            records.noticeEffluentTime,
+            records.controlTime,
+            records.quenchTime,
+            records.returnTime,
+            records.caseArea,
+            records.caseTypeCode,
+            records.address,
+            records.filingTime,
+            records.filingDate,
+            records.handleObject,
+            records.caseLevel,
+            records.squadron,
+            records.district,
+            records.caseStatus,
+            records.caseNature,
+            records.bdpAudit,
+            records.streetTown,
+            records.createTime,
+          ];
+          break;
+        case 1: //火灾查询
+          var classifyTitle = [
+            "地区",
+            "街镇",
+            "经度",
+            "维度",
+            "平台ID",
+            "火灾地址",
+            "过火面积",
+            "直接财产损失",
+            "死亡人数",
+            "受伤人数",
+            "受灾户数",
+            "火灾原因",
+            "火灾等级",
+            "场所一级",
+            "场所二级",
+            "起火物一级",
+            "起火物二级",
+            "性质",
+          ];
+          var classifyValue = [
+            records.district,
+            records.street,
+            records.longitude,
+            records.latitude,
+            records.id,
+            records.address,
+            records.burnedArea,
+            records.propertyLoss,
+            records.deathToll,
+            records.nonFatal,
+            records.disasterHome,
+            records.fireCause,
+            records.fireLevel,
+            records.placeOne,
+            records.placeTwo,
+            records.fireGoodsOne,
+            records.fireGoodsTwo,
+            records.nature,
+          ];
+          break;
+        case 2: //人员查询
+          var classifyTitle = ["值班人员信息", "岗位名称", "机构名称", "机构简称", "机构地址", "值班日期"];
+          var classifyValue = [records.name, records.postName, records.organizationName, records.organizationShort, records.organizationAddress, records.time];
+          break;
+        case 3: //车辆查询
+          var classifyTitle = [
+            "车辆信息",
+            "单件装备编码",
+            "装备名称",
+            "装备编码",
+            "上级装备编码",
+            "所属消防机构",
+            "车牌号码",
+            "资产编号",
+            "商标",
+            "颜色",
+            "生产厂家名称",
+            "有效期至",
+            "车架号",
+            "发动机编号",
+            "批次号",
+            "电台呼号",
+            "车辆简称",
+            "电台频道",
+            "指挥员姓名",
+            "驾驶员",
+          ];
+          var classifyValue = [
+            records.vehicleId,
+            records.singleEquipCode,
+            records.equipName,
+            records.equipCode,
+            records.superiorEquipCode,
+            records.fireOrga,
+            records.licensePlate,
+            records.assetCode,
+            records.assetCode,
+            records.colour,
+            records.productName,
+            records.validityTime,
+            records.frameCode,
+            records.engineCode,
+            records.batchCode,
+            records.radioCallSign,
+            records.vehicleAbbreviat,
+            records.radioChannel,
+            records.commanderName,
+            records.driver,
+          ];
+          break;
+        case 4: //站点查询
+          var classifyTitle = [
+            "平台ID",
+            "支队名称",
+            "所属辖区中队",
+            "消防站名称",
+            "单位性质",
+            "地址",
+            "所在位置",
+            "联动固定电话",
+            "负责人姓名",
+            "负责人手机号码",
+            "备注",
+            "消防站类型",
+            "经度",
+            "维度",
+            "创建时间",
+            "更新时间",
+            "支队id",
+            "中队id",
+            "编号",
+            "原单位性质",
+          ];
+          var classifyValue = [
+            records.id,
+            records.branchName,
+            records.squadron,
+            records.stationName,
+            records.companyNature,
+            records.address,
+            records.location,
+            records.fixedPhone,
+            records.chargeName,
+            records.chargePhone,
+            records.remark,
+            records.stationType,
+            records.longitude,
+            records.dimension,
+            records.createTime,
+            records.updateTime,
+            records.branchId,
+            records.squadronId,
+            records.number,
+            records.primaryCompanyNature,
+          ];
+          break;
+        case 5: //消火栓
+          var classifyTitle = [
+            "可用状态名称",
+            "消防站简介",
+            "水源地址",
+            "建造时间",
+            "消火栓接口形式",
+            "水源类型",
+            "管辖机构名称",
+            "取水形式",
+            "联系方式",
+            "可用状态",
+            "水源性质",
+            "水源名称",
+            "管网单位",
+            "管网压力",
+          ];
+          var classifyValue = [
+            records.availableStatusName,
+            records.fireAbbreviat,
+            records.waterAddress,
+            records.buildTime,
+            records.hydrantInterface,
+            records.waterType,
+            records.organizateName,
+            records.waterForm,
+            records.contactMode,
+            records.availableStatus,
+            records.waterNature,
+            records.waterName,
+            records.pipeCompany,
+            records.pipePressure,
+          ];
+          break;
+        case 6: //重点单位
+          var classifyTitle = [
+            "单位联系电话",
+            "单位详细地址",
+            "职工人数",
+            "单位类型",
+            "消防安全责任人姓名",
+            "法人代表姓名",
+            "单位名称",
+            "消防安全管理人姓名",
+            "单位主属性",
+            "建筑面积",
+            "行政区域",
+            "单位成立时间",
+            "占地面积",
+            "火灾危险性",
+            "创建时间",
+            "单位性质",
+            "固定资产(单位:万元)",
+          ];
+          var classifyValue = [
+            records.linkPhone,
+            records.address,
+            records.employeeNum,
+            records.companyType,
+            records.fireDutyName,
+            records.delegateName,
+            records.companyName,
+            records.fireManageName,
+            records.mainAttribute,
+            records.buildArea,
+            records.administrativeDivision,
+            records.foundTimecoverArea,
+            records.coverArea,
+            records.fireHazard,
+            records.createTime,
+            records.companyNature,
+            records.fixedAssets,
+          ];
+          break;
+        case 7: //消防检查信息
+          var classifyTitle = ["单位ID", "检查人员ID", "计划生成时间", "检查结果", "创建人", "创建时间", "检查员名称", "检查员职位", "单位电话"];
+          var classifyValue = [
+            records.companyId,
+            records.personId,
+            records.planTime,
+            records.inspectResult,
+            records.creator,
+            records.createTime,
+            records.personName,
+            records.personPosition,
+            records.linkPhone,
+          ];
+          break;
+        // default:
+        //    默认代码块
+      }
+
+      for (var i = 0; i < classifyTitle.length; i++) {
+        var obj = {};
+        obj.title = classifyTitle[i];
+        obj.value = classifyValue[i];
+        classifyData.value.push(obj);
+
+        console.log(classifyData.value);
+      }
+    } else {
+    }
+  });
+}
+// end
+
+watchEffect(() => {
+  goSearch();
+});
+
+// start
+
+const newTime = ref("");
+function getNowTime() {
+  var date = new Date();
+  var time =
+    addZero(date.getFullYear()) +
+    "-" +
+    addZero(date.getMonth() + 1) +
+    "-" +
+    addZero(date.getDate()) +
+    " " +
+    addZero(date.getHours()) +
+    ":" +
+    addZero(date.getMinutes()) +
+    ":" +
+    addZero(date.getSeconds());
+  newTime.value = time;
+}
+//根据自己的需求,看要不要在时间不大于10的时候在前面补0,如果需要直接this.addZero(date.getMinutes()),其它与之相同,如果不需要删掉addZero()方法即可。
+//小于10的拼接上0字符串
+function addZero(s) {
+  return s < 10 ? "0" + s : s;
+}
+
+// end
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/collect/components/collectRecord",
+    });
+  } else {
+  }
+});
+
+onLoad((options) => {
+  getNowTime(); //进入页面调用该方法获取当前时间
+  clearInterval(myTimeDisplay); //销毁之前定时器
+  var myTimeDisplay = setInterval(() => {
+    getNowTime(); //每秒更新一次时间
+  }, 1000);
+});
+
+onReady(() => {});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.uni-swipe {
+  overflow: visible;
+}
+body {
+  background: #fff;
+}
+.is-selected {
+  color: #1989fa;
+}
+
+.informationSelect {
+  height: calc(100% - 45px);
+  background-color: #ffffff;
+  .content1 {
+    .u-row {
+      height: 36px;
+      line-height: 36px;
+      .u-col {
+        border: 1px #e4e3e3 solid;
+        border-right: 0px;
+        border-bottom: 0px;
+        text-align: center;
+
+        view {
+          padding: 0 10px;
+          min-height: 40px;
+          overflow: hidden; //超出的文本隐藏
+          // text-overflow: ellipsis; //溢出用省略号显示
+          overflow: auto;
+          white-space: nowrap; // 默认不换行;
+          font-size: 14px;
+        }
+      }
+
+      .u-col:last-child {
+        border-right: 1px #e4e3e3 solid;
+      }
+    }
+
+    .u-row:last-child {
+      .u-col {
+        border-bottom: 1px #e4e3e3 solid;
+      }
+    }
+  }
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+
+.time {
+  position: absolute;
+  z-index: 99999;
+  top: 3px;
+  left: 3px;
+  display: inline-block;
+  color: #fff;
+}
+.con {
+  text-align: center;
+  position: relative;
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+body {
+  background: #fff;
+}
+</style>

+ 125 - 0
src/pages/business/mhxf/xunJian/collect/components/collectDetail.vue

@@ -0,0 +1,125 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="whiteBackgroundColor" style="padding: 15px 15px 15px 15px">
+      <u-form ref="form" labelPosition="left" :model="model" :rules="rules" labelWidth="82">
+        <u-form-item label="地点号码:" prop="siteNubmber">
+          <u-input v-model="model.siteNubmber" disabled></u-input>
+        </u-form-item>
+        <u-form-item label="地点名称:" prop="siteName">
+          <u-input v-model="model.siteName"></u-input>
+        </u-form-item>
+        <u-form-item label="备注:" prop="siteDescribe">
+          <u-input v-model="model.siteDescribe"></u-input>
+        </u-form-item>
+      </u-form>
+
+      <u-button type="primary" style="width: 100%; height: 40px; font-size: 14px; margin-top: 15px" @click="handleInsert()" shape="circle"> 保存 </u-button>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import {
+  onReady,
+  onLoad,
+  onShow,
+  onPullDownRefresh, //下拉刷新
+  onReachBottom, // 上拉加载
+  onNavigationBarButtonTap,
+} from "@dcloudio/uni-app";
+import { reactive, ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const form = ref(null); //表单refs获取
+const model = reactive({
+  siteType: 1,
+  siteTime: "",
+  swipeBool: false,
+  siteName: "",
+  siteNubmber: "",
+  siteDescribe: "",
+}); //form表单数据定义
+const rules = ref({
+  siteName: {
+    type: "string",
+    required: true,
+    message: "地点名称不能为空",
+    trigger: ["blur", "change"],
+  },
+
+  siteNubmber: [{ required: true, message: "地点编号不能为空", trigger: "blur" }],
+
+  siteDescribe: [{ min: 1, max: 30, message: "长度在 1 到 30 个字符", trigger: "blur" }],
+}); //form表单校验
+
+/**
+ * @保存按钮点击事件
+ */
+function handleInsert() {
+  form.value
+    .validate()
+    .then((res) => {
+      let endTime = new Date();
+      model.siteTime = settingsStore.formatterDate(endTime, "yyyy-MM-dd hh:mm:ss");
+
+      settingsStore.collectDataList.push(model);
+
+      //   uni.navigateTo({
+      //     url: "/pages/business/mhxf/xunJian/collect/index",
+      //   });
+      uni.navigateBack({
+        delta: 1, //返回到需要执行方法的页面
+      });
+    })
+    .catch((errors) => {
+      uni.$u.toast("校验失败");
+    });
+}
+
+onLoad((options) => {
+  model.siteNubmber = options.siteNubmber;
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 130 - 0
src/pages/business/mhxf/xunJian/collect/components/collectRecord.vue

@@ -0,0 +1,130 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="example-body" v-if="show">
+      <uni-datetime-picker v-model="datetimerange" type="daterange" rangeSeparator="~" @change="confirm" />
+    </view>
+    <view v-for="(cu, index) in dataList.siteList" :key="index" class="whiteBackgroundColor" style="display: flex; padding: 15px 0px 15px 15px; margin-bottom: 15px">
+      <view class="reportLeft">
+        <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/scan.png" v-if="cu.siteType == 1" shape="circle"></u-image>
+
+        <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/NFC.png" v-if="cu.siteType == 2" shape="circle"></u-image>
+      </view>
+      <view class="reportCenter">
+        <view class="centerSiteName">
+          {{ cu.siteName }}
+        </view>
+
+        <view style="font-size: 13px; color: #a1a1a1">
+          {{ cu.createTime == "" || cu.createTime == null ? "无" : cu.createTime }}
+        </view>
+      </view>
+      <view style="margin: auto"></view>
+      <view class="reportRight">
+        <view style="margin: auto">
+          <view style="padding: 0; font-size: 14px; color: #a1a1a1"> 已提交 </view>
+        </view>
+      </view>
+    </view>
+
+    <u-empty marginTop="20%" mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" v-if="dataList.siteList.length <= 0"> </u-empty>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { reactive, ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { siteList } from "@/api/business/mhxf/xunJian/collect.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const show = ref(false);
+
+const dataList = reactive({
+  siteList: [],
+  startTime: "",
+  endTime: "",
+});
+
+/**
+ * @日期选中事件回调
+ */
+function confirm(e) {
+  dataList.startTime = e[0];
+  dataList.endTime = e[1];
+  handleSelectApi();
+}
+
+/**
+ * @采集记录接口查询
+ * @api请求
+ */
+async function handleSelectApi() {
+  siteList({
+    startTime: dataList.startTime, //开始时间
+    endTime: dataList.endTime, //结束时间
+  }),
+    then((res) => {
+      if (res.status == "SUCCESS") {
+        dataList.siteList = res.data;
+      } else {
+      }
+    });
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    show.value = !show.value;
+  } else {
+  }
+});
+
+onLoad((options) => {});
+
+onReady(() => {});
+
+onMounted(() => {
+  handleSelectApi();
+});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 232 - 0
src/pages/business/mhxf/xunJian/collect/index.vue

@@ -0,0 +1,232 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <!-- 按组使用 -->
+    <uni-swipe-action>
+      <uni-swipe-action-item
+        v-for="(cu, index) in settingsStore.collectDataList"
+        :key="index"
+        :right-options="options"
+        @click="bindClick($event, index)"
+        @change="swipeChange($event, index)"
+        style="margin-bottom: 15px"
+      >
+        <view class="whiteBackgroundColor" style="display: flex; padding: 15px 0px 15px 15px">
+          <view class="reportLeft">
+            <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/scan.png" v-if="cu.siteType == 1" shape="circle"></u-image>
+
+            <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/NFC.png" v-if="cu.siteType == 2" shape="circle"></u-image>
+          </view>
+          <view class="reportCenter">
+            <view class="centerSiteName">
+              {{ cu.siteName }}
+            </view>
+
+            <view style="font-size: 13px; color: #a1a1a1">
+              {{ cu.siteTime == "" || cu.siteTime == null ? "无" : cu.siteTime }}
+            </view>
+          </view>
+          <view style="margin: auto"></view>
+          <view class="reportRight">
+            <view style="margin: auto" v-if="cu.swipeBool == false">
+              <view style="padding: 0; font-size: 14px; color: #409eff" @click="handleInsert(cu)"> 提交 </view>
+            </view>
+          </view>
+        </view>
+      </uni-swipe-action-item>
+    </uni-swipe-action>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image width="67" height="67" src="@/static/images/xunjian/plan-scan.png" shape="circle" @click="scanClick()"></u-image>
+    </view>
+
+    <!-- 提示信息弹窗 -->
+    <uni-popup ref="message" type="message">
+      <uni-popup-message
+        :style="{
+          color: messageList.color,
+        }"
+        :type="messageList.type"
+        :message="messageList.message"
+        :duration="messageList.duration"
+      ></uni-popup-message>
+    </uni-popup>
+
+    <u-empty marginTop="20%" mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" v-if="settingsStore.collectDataList.length <= 0"> </u-empty>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { addSite } from "@/api/business/mhxf/xunJian/collect.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+function scanClick() {
+  uni.scanCode({
+    success: (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+      uni.navigateTo({
+        url: "/pages/business/mhxf/xunJian/collect/components/collectDetail?siteNubmber=" + e.result,
+      });
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @api请求
+ * @提交按钮点击事件
+ */
+const message = ref(null);
+const messageList = reactive({
+  type: "",
+  message: "",
+  duration: 0,
+  color: "",
+});
+function handleInsert(e) {
+  uni.getLocation({
+    type: "wgs84",
+    success: function (res) {
+      console.log("当前位置的经度:" + res.longitude);
+      console.log("当前位置的纬度:" + res.latitude);
+      api(res.longitude, res.latitude);
+    },
+    fail: function (res) {
+      uni.showToast({
+        title: "请打开手机定位或相关应用权限定位!",
+        icon: "none",
+      });
+    },
+  });
+
+  function api(longitude, latitude) {
+    addSite({
+      siteName: e.siteName, //地点名称
+      siteNubmber: e.siteNubmber, //地点号码
+      siteDescribe: e.siteDescribe, //地点描述
+      siteType: e.siteType, //地点类型(1二维码,2NFC)
+      longitude: longitude, //经度
+      latitude: latitude, //纬度
+      pictureUrl: "", //图片地址
+      distanceRange: 10, //误差范围
+      // areaId: 0, //区域id
+      // companyId: 0, //单位ID
+    }).then((res) => {
+      if (res.status == "SUCCESS") {
+        messageList.type = "SUCCESS";
+        messageList.message = "提交成功";
+        messageList.duration = 2000;
+        messageList.color = "#09bb07";
+        message.value.open();
+
+        settingsStore.collectDataList.splice(settingsStore.collectDataList.indexOf(e), 1);
+      } else {
+      }
+    });
+  }
+}
+
+const options = ref([
+  {
+    text: "删除",
+    style: {
+      backgroundColor: "#dd524d",
+    },
+  },
+]);
+
+/**
+ * @左滑删除点击事件
+ */
+function bindClick(e, index) {
+  settingsStore.collectDataList.splice(index, 1);
+}
+
+/**
+ * @左滑删除change事件
+ */
+function swipeChange(e, index) {
+  if (e == "right") {
+    settingsStore.collectDataList[index].swipeBool = true;
+  } else {
+    settingsStore.collectDataList[index].swipeBool = false;
+  }
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/collect/components/collectRecord",
+    });
+  } else {
+  }
+});
+
+onLoad((options) => {});
+
+onReady(() => {});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 158 - 0
src/pages/business/mhxf/xunJian/components/echarts/chart.vue

@@ -0,0 +1,158 @@
+<template>
+  <view class="content">
+    <l-echart ref="domMyChart" class="echarts"></l-echart>
+  </view>
+</template>
+
+<script setup>
+import * as echarts from "echarts";
+import { onLoad, onShow, onHide, onLaunch, onResize } from "@dcloudio/uni-app";
+import { defineComponent, ref, onMounted, nextTick } from "vue";
+
+const props = defineProps({
+  currentDateList: {
+    type: Object,
+    default: null,
+  },
+});
+
+let myChart;
+const domMyChart = ref(null);
+
+var datas = [
+  {
+    name: "漏检任务",
+    value: 0,
+  },
+  {
+    name: "已巡检任务",
+    value: 0,
+  },
+];
+
+datas[0].value = props.currentDateList[0].undetectedCount;
+datas[1].value = props.currentDateList[0].patrolledCount;
+
+let option = {
+  color: ["#F07D28", "#00CDAC"],
+  title: [
+    {
+      text: "今日巡检情况",
+      left: "center",
+      top: 15,
+      textStyle: {
+        color: "black",
+        fontWeight: "normal",
+        fontSize: 14,
+      },
+    },
+    {
+      text: [`{value|${props.currentDateList[0].planSonCount}}`, "{name|巡检总数}"].join("\n "),
+      top: "40%",
+      left: "center",
+      textStyle: {
+        color: "black",
+        fontWeight: "normal",
+        fontSize: 14,
+        lineHeight: 22,
+        rich: {
+          name: {
+            fontFamily: "PingFangSC-Regular",
+            fontSize: 13,
+            color: "rgba(0,0,0,0.45)",
+            lineHeight: 22,
+            marginBottom: "5px",
+          },
+          value: {
+            fontFamily: "HelveticaNeue",
+            fontSize: 24,
+            color: "rgba(0,0,0,0.85)",
+            lineHeight: 30,
+          },
+        },
+      },
+    },
+  ],
+
+  series: {
+    type: "pie",
+    radius: [40, 80],
+    height: "100%",
+    left: "center",
+    width: "100%",
+    itemStyle: {
+      borderColor: "#fff",
+      borderWidth: 1,
+    },
+    label: {
+      alignTo: "edge",
+      formatter: function (el) {
+        return `${el.name}\n${el.value}`;
+      },
+      minMargin: 5,
+      edgeDistance: 10,
+      lineHeight: 20,
+      rich: {
+        time: {
+          fontSize: 10,
+          color: "#999",
+        },
+      },
+    },
+    labelLine: {
+      length: 25,
+      length2: 0,
+      maxSurfaceAngle: 80,
+    },
+    labelLayout: function (params) {
+      // var isLeft = params.labelRect.x < myChart.getWidth() / 2;
+      var isLeft = params.labelRect.x < myChart.nodeWidth / 2;
+      var points = params.labelLinePoints;
+      points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
+      return {
+        labelLinePoints: points,
+      };
+    },
+
+    data: datas,
+  },
+};
+
+function initEcharts() {
+  // let dom = uni.createSelectorQuery().select("#linEcharts");
+  // myChart = echarts.init(document.getElementById("linEcharts"));
+  // 观测更新的数据在 view 层可以直接访问到
+  // myChart.setOption(option);
+
+  myChart = domMyChart.value;
+  myChart.init(echarts, (myChart) => {
+    myChart.setOption(option);
+  });
+}
+
+onLoad(() => {
+  nextTick(() => {
+    initEcharts();
+  });
+});
+
+onResize(() => {
+  myChart.resize();
+});
+</script>
+
+<style>
+.content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+.echarts {
+  width: 100%;
+  height: 600rpx;
+  /* margin-top: 70rpx; */
+  /* background:pink */
+}
+</style>

+ 0 - 0
src/pages/business/mhxf/xunJian/components/index.vue


+ 250 - 0
src/pages/business/mhxf/xunJian/plan/components/content.vue

@@ -0,0 +1,250 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view>
+      <view class="whiteBackgroundColor" style="padding: 15px; margin-bottom: 15px" v-for="(con, index) in contentList" :key="index">
+        <view class="siteHeader">
+          <uni-section :title="con.contentTitle" type="line"></uni-section>
+
+          <view style="margin: auto"> </view>
+
+          <u-button v-if="con.remarksBool == false" type="primary" icon="list-dot" style="width: 18px; height: 18px; padding: 0; margin: 0" shape="circle" @click="remarksClick(index)"> </u-button>
+        </view>
+        <view>
+          <view v-if="con.submissionMethod == 1" style="margin-top: 15px">
+            <u-checkbox-group
+              v-model="con.contentOptionListValue1"
+              @change="
+                (val) => {
+                  checkboxChange(val, index);
+                }
+              "
+              :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2"
+            >
+              <u-row style="width: 100%; flex-wrap: wrap">
+                <u-col v-for="option in con.contentOptionList" :key="option" span="6" style="margin-bottom: 15px">
+                  <u-checkbox :label="option.optionName" :name="option.id" :checked="con.contentOptionListValue1.length > 0 ? con.contentOptionListValue1.indexOf(option.id) >= 0 : false">
+                  </u-checkbox>
+                </u-col>
+              </u-row>
+            </u-checkbox-group>
+
+            <view v-if="con.remarksBool == true" style="display: flex; height: 32px; line-height: 32px; white-space: nowrap">
+              <span style="">备注:</span>
+              <u-input v-model="con.remarks" placeholder="请输入备注" :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2"></u-input>
+            </view>
+          </view>
+          <view v-if="con.submissionMethod == 2" style="margin-top: 15px">
+            <u-radio-group placement="row" v-model="con.contentOptionListValue">
+              <u-row style="width: 100%; flex-wrap: wrap">
+                <u-col v-for="option in con.contentOptionList" :key="option" :span="6" style="margin-bottom: 15px">
+                  <u-radio :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2" :label="option.optionName" :name="option.id"> </u-radio>
+                </u-col>
+              </u-row>
+            </u-radio-group>
+
+            <view v-if="con.remarksBool == true" style="display: flex; height: 32px; line-height: 32px; white-space: nowrap">
+              <span style="">备注:</span>
+              <u-input v-model="con.remarks" placeholder="请输入备注" :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2"></u-input>
+            </view>
+          </view>
+          <view v-if="con.submissionMethod == 3" style="margin-top: 15px">
+            <u-textarea v-model="con.contentOptionListValue" placeholder="请输入" maxlength="30" :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2"></u-textarea>
+
+            <view v-if="con.remarksBool == true" style="display: flex; margin-top: 15px; height: 32px; line-height: 32px; white-space: nowrap">
+              <span style="">备注:</span>
+              <u-input v-model="con.remarks" placeholder="请输入备注" :disabled="settingsStore.contentArray.siteList.inspectionStatus == 2"></u-input>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <view style="margin-bottom: 125px"></view>
+    </view>
+    <view style="position: fixed; left: 0; right: 0; bottom: 0; padding: 15px">
+      <view>
+        <u-button
+          v-if="settingsStore.contentArray.siteList.inspectionStatus == 1"
+          type="primary"
+          style="width: 100%; height: 40px; font-size: 14px; margin-bottom: 15px"
+          shape="circle"
+          @click="buttonClick(1)"
+        >
+          上一步
+        </u-button>
+      </view>
+      <view>
+        <u-button v-if="settingsStore.contentArray.siteList.inspectionStatus == 1" type="primary" style="width: 100%; height: 40px; font-size: 14px" shape="circle" @click="buttonClick(2)">
+          提交
+        </u-button>
+      </view>
+    </view>
+
+    <u-modal ref="uModal" :show="show" :title="title" :content="content" @confirm="confirm"></u-modal>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+
+import useXunJianStore from "@/store/modules/xunJian";
+import { updatePlan } from "@/api/business/mhxf/xunJian/plan.js";
+
+const BASE_URL = inject("$BASE_URL");
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const contentList = ref([]);
+function checkboxChange(value, index) {
+  contentList.value[index].contentOptionListValue1 = value;
+}
+
+/**
+ * @按钮点击事件
+ * @备注显示事件
+ */
+function remarksClick(index) {
+  settingsStore.contentArray.contentList[index].remarksBool = true;
+}
+
+/**
+ * @confirm确定回调事件
+ * @模态框
+ */
+const show = ref(false);
+const title = ref("");
+const content = ref("");
+function confirm() {
+  show.value = false;
+  uni.$emit("planSelect"); //执行页面中的自定义方法
+  uni.navigateBack({
+    delta: 3, //返回到需要执行方法的页面
+  });
+}
+
+/**
+ * @按钮点击事件
+ * @上一步
+ * @提交
+ */
+async function buttonClick(type) {
+  if (type == 1) {
+    //上一步
+    uni.navigateBack({
+      delta: 1,
+    });
+  } else if (type == 2) {
+    //提交
+
+    const recordOptionList = [];
+    if (contentList.value.length > 0) {
+      contentList.value.forEach((e) => {
+        if (e.contentOptionListValue && e.contentOptionList.length > 0) {
+          recordOptionList.push({
+            contentId: e.id,
+            contentOptionId: e.contentOptionListValue,
+            remarks: e.remarks,
+          });
+        }
+
+        if (e.contentOptionListValue && e.contentOptionList.length == 0) {
+          recordOptionList.push({
+            contentId: e.id,
+            content: e.contentOptionListValue,
+            remarks: e.remarks,
+          });
+        }
+
+        if (e.contentOptionListValue1.length > 0) {
+          e.contentOptionListValue1.forEach((l) => {
+            recordOptionList.push({
+              contentId: e.id,
+              contentOptionId: l,
+              remarks: e.remarks,
+            });
+          });
+        }
+      });
+    }
+
+    const array = {
+      siteType: settingsStore.contentArray.siteList.siteType,
+      siteNubmber: settingsStore.contentArray.siteList.siteNubmber,
+      siteName: settingsStore.contentArray.siteList.siteName,
+      siteStatus: 1, //定位 (0:未定位 1:已定位)
+      longitude: settingsStore.contentArray.siteList.longitude,
+      latitude: settingsStore.contentArray.siteList.latitude,
+      planSonId: settingsStore.contentArray.siteList.planSonId,
+      siteId: settingsStore.contentArray.siteList.id,
+      recordPictureList: settingsStore.contentArray.siteList.recordPictureList,
+      recordOptionList: recordOptionList,
+    };
+
+    updatePlan(array).then((res) => {
+      if (res.status == "SUCCESS") {
+        title.value = "消息";
+        content.value = "提交成功,确定后返回!";
+        show.value = true;
+      } else {
+      }
+    });
+  }
+}
+
+onLoad((options) => {
+  contentList.value = settingsStore.contentArray.contentList;
+
+  if (settingsStore.contentArray.siteList.inspectionStatus == 2) {
+    if (contentList.value.length > 0) {
+      contentList.value.forEach((el) => {
+        el.contentOptionListValue1 = [];
+      });
+
+      contentList.value.filter((e) => {
+        if (e.remarks) {
+          e.remarksBool = true;
+        } else {
+          e.remarksBool = false;
+        }
+
+        if (e.contentOptionList) {
+          e.contentOptionList.forEach((s) => {
+            if (e.contentOptionValue.indexOf(s.id) >= 0) {
+              //提交方式:1多选 2单选 3输入框
+              if (e.submissionMethod == 1) {
+                e.contentOptionListValue1.push(s.id);
+              } else if (e.submissionMethod == 2) {
+                e.contentOptionListValue = s.id;
+              }
+            }
+          });
+        } else {
+          e.contentOptionListValue = e.content;
+        }
+      });
+    }
+  }
+});
+
+onMounted(() => {});
+</script>
+
+<style scoped>
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+</style>
+
+<style lang="scss">
+.siteHeader {
+  display: flex;
+  height: 18px;
+  line-height: 18px;
+  margin-bottom: 10px;
+}
+</style>

+ 89 - 0
src/pages/business/mhxf/xunJian/plan/components/drawer.vue

@@ -0,0 +1,89 @@
+<template>
+  <u-popup :show="scanBool" @close="close" @open="open" mode="bottom">
+    <template #default>
+      <view style="margin-bottom: 15px; margin-top: 15px">
+        <h4 style="font-size: 16px; color: #149eff; text-align: center; margin-bottom: 10px">请选择计划</h4>
+        <view style="font-size: 12px; color: #b7b7b7; text-align: center"> 当前地点存在于多个计划,请选择目标计划 </view>
+      </view>
+      <scroll-view scroll-y style="padding-left: 15px; padding-right: 15px; height: calc(100vh - 30rem)">
+        <view v-for="(scan, index) in scanArray" :key="index">
+          <view style="display: flex; font-size: 15px; height: 50px; line-height: 50px">
+            <view style="margin-right: 15px">
+              <img src="@/static/images/xunjian/plan-scan-drawer.png" alt="" />
+            </view>
+            <view>{{ scan.planName }} </view>
+            <view style="margin: auto"></view>
+            <view style="margin: auto 0">
+              <u-button type="primary" shape="circle" style="height: 25px; font-size: 13px" @click="reportClick(scan.siteId, scan.id)"> 上报 </u-button>
+            </view>
+          </view>
+
+          <view style="border-bottom: 1.5px #dad7d7 solid"></view>
+        </view>
+      </scroll-view>
+    </template>
+  </u-popup>
+</template>
+
+<script setup>
+import { ElMessageBox } from "element-plus";
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, watchEffect } from "vue";
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const props = defineProps({
+  scanArray: {
+    type: Object,
+    default: null,
+  },
+  scanBool: {
+    type: Boolean,
+    default: null,
+  },
+});
+const emit = defineEmits(["scanClose"]);
+
+const scanArray = ref(props.scanArray);
+const scanBool = ref(false);
+
+/**
+ * @巡检上报
+ * @按钮点击事件
+ */
+function reportClick(siteId, planSonId) {
+  settingsStore.contentArray = {};
+  settingsStore.siteNubmber = undefined;
+  settingsStore.siteId = siteId;
+  settingsStore.planSonId = planSonId;
+
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+  });
+}
+
+/**
+ * @开启抽屉时执行
+ */
+function open() {}
+
+/**
+ * @关闭抽屉时执行
+ */
+function close() {
+  scanBool.value = false;
+  emit("scanClose", false);
+}
+
+/**
+ * @监听器
+ */
+watchEffect((fn, options) => {
+  scanBool.value = props.scanBool;
+});
+
+onLoad((options) => {});
+
+onMounted(() => {});
+</script>

+ 242 - 0
src/pages/business/mhxf/xunJian/plan/components/report.vue

@@ -0,0 +1,242 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="whiteBackgroundColor" style="display: flex; padding: 15px 0px 15px 15px; margin-bottom: 15px" v-for="cu in currentDateList" :key="cu">
+      <view class="reportLeft" @click="pulicClick(cu)">
+        <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/scan.png" v-if="cu.siteType == 1" shape="circle"></u-image>
+
+        <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/NFC.png" v-if="cu.siteType == 2" shape="circle"></u-image>
+      </view>
+      <view class="reportCenter" @click="pulicClick(cu)">
+        <view class="centerSiteName">
+          {{ cu.siteName }}
+          <view
+            :style="{
+              margin: 'auto auto auto 15px',
+              fontSize: '5px',
+              backgroundColor: cu.inspectionStatus == 1 ? '#ffbebb' : '#ABE399',
+              color: cu.inspectionStatus == 1 ? '#FF3128' : '#189400',
+              borderRadius: '10px',
+              padding: '0px 5px',
+            }"
+          >
+            {{ cu.inspectionStatus == 1 ? "未巡检" : "已巡检" }}
+          </view>
+
+          <!-- "inspectionStatus": 2 //巡检状态(1 未巡检,2 已巡检) -->
+        </view>
+        <view style="font-size: 13px; color: #a1a1a1; margin-bottom: 5px"> 描述:{{ cu.siteDescribe == "" || cu.siteDescribe == null ? "无" : cu.siteDescribe }} </view>
+        <view style="font-size: 13px; color: #a1a1a1">
+          完成时间:
+          {{ cu.inspectionTime == "" || cu.inspectionTime == null ? "无" : cu.inspectionTime }}
+        </view>
+      </view>
+      <view style="margin: auto" @click="pulicClick(cu)"></view>
+      <view class="reportRight">
+        <view
+          class="rightChild"
+          :style="{
+            color: cu.siteStatus == null || cu.siteStatus == 0 ? '#a0a0a0' : '#1989fa',
+          }"
+        >
+          <text class="iconfont ucicon-map" style="font-size: 22px"></text>
+          <view>定位</view>
+        </view>
+        <view
+          class="rightChild"
+          :style="{
+            color: cu.siteStatus == null || cu.siteStatus == 0 ? '#a0a0a0' : '#1989fa',
+          }"
+        >
+          <text class="iconfont ucicon-appstore" style="font-size: 22px"></text>
+
+          <view>状态</view>
+        </view>
+      </view>
+    </view>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image width="67" height="67" src="@/static/images/xunjian/plan-scan.png" shape="circle" @click="scanClick()"></u-image>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { recordList, recordOption, siteDetails, planSonSiteDetails } from "@/api/business/mhxf/xunJian/plan.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+function pulicClick(obj) {
+  if (obj.inspectionStatus == 2) {
+    recordList({
+      siteId: obj.id,
+      planSonId: settingsStore.planSonId,
+    }).then((res) => {
+      if (res.status == "SUCCESS") {
+        if (res.data.length > 0) {
+          recordOption({
+            siteId: res.data[0].siteId,
+            recordId: res.data[0].id,
+          }).then((res1) => {
+            res.data[0].inspectionStatus = 2;
+            res.data[0].pictureUrl = obj.pictureUrl;
+
+            settingsStore.contentArray = {
+              contentList: [res1.data.contentList],
+              siteList: res.data[0],
+            };
+            settingsStore.siteId = undefined;
+            settingsStore.siteNubmber = undefined;
+          });
+        }
+      } else {
+      }
+    });
+  } else {
+    settingsStore.contentArray = {};
+    settingsStore.siteId = obj.id;
+    settingsStore.siteNubmber = undefined;
+  }
+
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+  });
+}
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+async function scanClick() {
+  uni.scanCode({
+    success: async (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+
+      settingsStore.contentArray = {};
+      settingsStore.siteId = undefined;
+      settingsStore.siteNubmber = e.result;
+
+      siteDetails({
+        siteId: settingsStore.siteId,
+        siteNubmber: settingsStore.siteNubmber,
+        planSonId: settingsStore.planSonId,
+      }).then((res) => {
+        if (res.status == "SUCCESS") {
+          currentDateList.value.forEach((e) => {
+            if (e.id == res.data.siteList[0].id) {
+              uni.navigateTo({
+                url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+              });
+            }
+          });
+        } else {
+        }
+      });
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @地点列表
+ * @api接口请求
+ */
+const currentDateList = ref([]); //地点列表list数据存储
+function currentApi() {
+  planSonSiteDetails({
+    planSonId: settingsStore.planSonId,
+  }).then((res) => {
+    if (res.status == "SUCCESS") {
+      currentDateList.value = res.data;
+
+      currentDateList.value.forEach((e) => {
+        if (e.inspectionTime) {
+          e.inspectionTime = e.inspectionTime.replace("T", " ");
+        }
+      });
+    } else {
+    }
+  });
+}
+
+onLoad((options) => {
+  currentApi();
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  background-color: rgba(238, 238, 238, 0.3);
+  margin: -15px 0;
+}
+
+.reportRight .rightChild {
+  margin: auto;
+  text-align: center;
+  padding: 10px;
+}
+
+.reportRight .rightChild .el-icon {
+  font-size: 20px;
+  margin: auto;
+  font-weight: 600;
+}
+
+.reportRight .rightChild view {
+  font-size: 12px;
+  margin: auto;
+  font-weight: 600;
+}
+</style>

+ 266 - 0
src/pages/business/mhxf/xunJian/plan/components/siteDetails.vue

@@ -0,0 +1,266 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view>
+      <view class="whiteBackgroundColor" style="display: flex; padding: 15px; margin-bottom: 15px">
+        <view style="margin-right: 15px; display: flex">
+          <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/scan.png" v-if="siteList.siteType == 1" shape="circle"></u-image>
+
+          <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/NFC.png" v-if="siteList.siteType == 2" shape="circle"></u-image>
+        </view>
+        <view>
+          <view style="font-size: 15px; margin-bottom: 2px">
+            {{ siteList.siteName }}
+          </view>
+          <view style="font-size: 13px; color: #a1a1a1"> {{ siteList.contentCount }}项内容 </view>
+        </view>
+        <view style="margin: auto"></view>
+        <view style="margin: auto 0">
+          <!-- {{ siteList.siteStatus == null }} -->
+          <view style="font-size: 15px; color: #30bb00">已定位</view>
+          <!-- #f07d28 -->
+        </view>
+      </view>
+
+      <view class="whiteBackgroundColor" style="margin-bottom: 15px; padding: 15px">
+        <view class="siteHeader">
+          <uni-section title="上报现场" type="line"></uni-section>
+        </view>
+        <view style="display: flex; flex-wrap: wrap">
+          <view class="uploadView" v-for="record in siteList.recordPictureList" :key="record">
+            <view class="uploadUimage">
+              <u-image width="100%" height="100%" :src="record.pictureUrl"></u-image>
+            </view>
+
+            <view v-if="siteList.inspectionStatus == 1" class="uploadViewClose" @click="uploadViewClose(record)">
+              <u-icon name="close" color="#ffffff" size="12"></u-icon>
+            </view>
+          </view>
+          <view :class="siteList.inspectionStatus == 2 ? 'uploadView upload-buttom uploadDisabled' : 'uploadView upload-buttom'" @click="uploadClick">
+            <u-icon style="margin: auto" name="plus" color="#909399" size="28"></u-icon>
+          </view>
+        </view>
+      </view>
+
+      <view class="whiteBackgroundColor" style="margin-bottom: 15px; padding: 15px; height: 170px; max-height: 170px">
+        <view class="siteHeader">
+          <uni-section title="备注" type="line"></uni-section>
+        </view>
+        <view style="height: calc(100% - 25px)">
+          <span v-if="siteList.inspectionStatus == 2">
+            {{ siteList.remarks }}
+          </span>
+
+          <u-textarea v-if="siteList.inspectionStatus == 1" style="height: 100%" v-model="siteList.remarks" placeholder="请输入备注" maxlength="50"></u-textarea>
+        </view>
+      </view>
+
+      <view class="whiteBackgroundColor" style="padding: 15px">
+        <view class="siteHeader">
+          <uni-section title="消防设施分布图" type="line"></uni-section>
+        </view>
+        <view>
+          <u-image width="100%" :src="siteList.pictureUrl"></u-image>
+        </view>
+      </view>
+
+      <view style="margin-bottom: 70px"></view>
+    </view>
+    <view style="position: fixed; left: 0; right: 0; bottom: 0; padding: 15px">
+      <view>
+        <u-button v-if="siteList.inspectionStatus == 1" type="primary" style="width: 100%; height: 40px; font-size: 14px" @click="buttonClick()" shape="circle"> 下一步 </u-button>
+
+        <u-button v-if="siteList.inspectionStatus == 2" type="primary" style="width: 100%; height: 40px; font-size: 14px" @click="buttonClick()" shape="circle"> 查看巡检项 </u-button>
+      </view>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { uploadAvatar, siteDetails } from "@/api/business/mhxf/xunJian/plan.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @站点详情
+ * @api接口查询
+ * @siteList站点详情信息存储
+ * @contentList内容详情信息存储
+ */
+const siteList = ref([]);
+const contentList = ref([]);
+function selectAPI() {
+  siteDetails({
+    siteId: settingsStore.siteId,
+    siteNubmber: settingsStore.siteNubmber,
+    planSonId: settingsStore.planSonId,
+  }).then((res) => {
+    if (res.status == "SUCCESS") {
+      contentList.value = res.data.contentList;
+      siteList.value = res.data.siteList[0];
+      siteList.value.recordPictureList = [];
+
+      contentList.value.forEach((el) => {
+        el.remarksBool = false;
+        el.contentOptionListValue = "";
+        el.contentOptionListValue1 = [];
+      });
+    } else {
+    }
+  });
+}
+
+/**
+ * @按钮点击事件
+ * @下一步
+ * @查看巡检项
+ */
+function buttonClick() {
+  settingsStore.contentArray = {
+    contentList: contentList.value,
+    siteList: siteList.value,
+  };
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/content",
+  });
+}
+
+/**
+ * @upload图片上传
+ * @点击事件
+ */
+function uploadClick() {
+  uni.chooseImage({
+    count: 1, //默认9
+    sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
+    sourceType: ["album", "camera"], //从相册选择、摄像头
+    success: function (res) {
+      uploadApi(res);
+    },
+  });
+}
+
+/**
+ * @upload图片上传
+ * @api接口请求
+ */
+async function uploadApi(res) {
+  let data = { name: "file", filePath: res.tempFilePaths[0] };
+
+  uploadAvatar(data).then((response) => {
+    siteList.value.recordPictureList.push({
+      name: response.data.name,
+      pictureUrl: response.data.url,
+    });
+  });
+}
+
+/**
+ * @upload图片上传
+ * @点击事件
+ * @删除事件
+ */
+function uploadViewClose(el) {
+  siteList.value.recordPictureList.splice(siteList.value.recordPictureList.indexOf(el), 1);
+}
+
+onLoad((options) => {
+  if (JSON.stringify(settingsStore.contentArray) == "{}") {
+    selectAPI();
+  } else {
+    contentList.value = settingsStore.contentArray.contentList[0];
+    siteList.value = settingsStore.contentArray.siteList;
+  }
+});
+
+onMounted(() => {});
+</script>
+
+<style scoped>
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.siteHeader {
+  display: flex;
+  height: 20px;
+  line-height: 20px;
+  margin-bottom: 10px;
+}
+</style>
+
+<!--自定义图片上传功能样式-->
+<style scoped>
+.uploadView {
+  position: relative;
+  overflow: hidden;
+  width: calc(33% - 10px);
+  height: 110px;
+  margin: 0 15px 15px 0;
+  border: 1px solid #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+}
+
+.uploadView .uploadUimage {
+  height: 100%;
+}
+
+.uploadView .uploadUimage > uni-view {
+  height: 100%;
+}
+
+.uploadViewClose {
+  position: absolute;
+  background-color: #409eff;
+  transform: rotate(45deg);
+  width: 40px;
+  height: 24px;
+  text-align: center;
+  right: -15px;
+  top: -6px;
+  cursor: pointer;
+}
+
+.uploadViewClose .u-icon,
+.uploadViewClose .el-icon {
+  font-size: 12px;
+  margin-top: 4px;
+  margin-left: 10px;
+  transform: rotate(-45deg);
+  color: #ffffff;
+}
+
+.uploadView img {
+  width: 100%;
+}
+
+.upload-buttom {
+  display: flex;
+  font-size: 28px;
+  color: #909399;
+  border: 1px dashed #d9d9d9;
+  background-color: #fafafa;
+}
+
+.uploadView:nth-child(3n) {
+  margin: 0 !important;
+}
+
+.upload-buttom:hover {
+  border: 1px dashed #409eff;
+}
+
+::v-deep .uploadDisabled {
+  display: none !important;
+}
+</style>

+ 73 - 0
src/pages/business/mhxf/xunJian/plan/components/upload.vue

@@ -0,0 +1,73 @@
+<template>
+  <scroll-view scroll-y>
+    <el-upload
+      v-model:file-list="siteList.recordPictureList"
+      :class="
+        settingsStore.inspectionStatus == 2
+          ? 'avatar-uploader uploadDisabled'
+          : 'avatar-uploader'
+      "
+      :headers="{ Authorization: Authorization }"
+      :action="uploadUrl"
+      :on-success="uploadSuccess"
+      list-type="picture-card"
+    >
+      <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
+      <template #file="{ file }">
+        <div :id="file.url">
+          <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
+          <span class="el-upload-list__item-actions">
+            <span
+              v-if="!disabled"
+              class="el-upload-list__item-delete"
+              @click="handleRemove(file)"
+            >
+              <el-icon><Delete /></el-icon>
+            </span>
+          </span>
+        </div>
+      </template>
+    </el-upload>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const BASE_URL = inject("$BASE_URL");
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const siteList = ref({ recordPictureList: [] });
+
+const uploadUrl = ref(BASE_URL + "/service-file/upload");
+const Authorization = uni.getStorageSync("Authorization");
+const disabled = ref(false);
+function handleRemove(file) {
+  document.getElementById(file.url).parentNode.remove();
+  siteList.value.recordPictureList.splice(
+    siteList.value.recordPictureList.indexOf(file),
+    1
+  );
+}
+/**
+ * @upload图片上传
+ * @图片上传成功回调
+ */
+function uploadSuccess(el, UploadFile) {
+  UploadFile.name = el.data.name;
+  UploadFile.url = el.data.url;
+}
+
+onLoad((options) => {});
+
+onMounted(() => {});
+</script>
+
+
+<style scoped>
+::v-deep .uploadDisabled .el-upload--picture-card {
+  display: none;
+}
+</style>

+ 440 - 0
src/pages/business/mhxf/xunJian/plan/index.vue

@@ -0,0 +1,440 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="grayBackgroundColor">
+      <view>
+        <el-calendar id="calendar" ref="calendar" v-model="currentDatevalue" @touchstart="touchStart" @touchend="touchEnd">
+          <template #header="{ date }">
+            <view style="display: flex; width: 100%">
+              <view>{{ date }}</view>
+              <view style="margin: auto"></view>
+              <view style="display: flex">
+                <view style="margin: 0px 10px">
+                  <span style="margin-right: 5px">合格</span>
+                  <span style="color: #00cdac">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.patrolledCount }}</span>
+                </view>
+                <view class="margin-left-xs">
+                  <span style="margin-right: 5px">漏检</span>
+                  <span style="color: #f07d28">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.undetectedCount }}</span>
+                </view>
+              </view>
+            </view>
+          </template>
+          <template #date-cell="{ data }">
+            <view @click="calendarClick(data)">
+              <p :class="data.isSelected ? 'is-selected' : ''">
+                {{ data.day.split("-").slice(2).join("-") }}
+              </p>
+              <view v-if="data.isSelected" class="filter"></view>
+            </view>
+          </template>
+        </el-calendar>
+      </view>
+      <view>
+        <view class="padding-sm" style="display: flex; margin: 10px; padding: 10px 5rem">
+          <u-subsection :list="list" :current="tabPosition" inactiveColor="#303133" activeColor="#3c9cff" @change="tabPositionChange"></u-subsection>
+        </view>
+        <view>
+          <view id="planTimeline1" v-if="activities.length > 0">
+            <view style="margin: 0px -3.5px; font-size: 13px; color: #409eff" @click="activitiesSortClick()"> 排序 </view>
+            <view v-for="(activity, index) in activities" :key="index" v-show="tabPosition == 0">
+              <view style="display: flex; height: 25px; line-height: 25px">
+                <view style="margin: auto 0">
+                  <u-icon name="info-circle-fill" color="#409eff" size="18"></u-icon>
+                </view>
+                <view style="display: flex; width: 100%; margin-left: 15px">
+                  <view style="font-size: 15px; color: #000000">
+                    {{ activity.planName }}
+                  </view>
+                  <view style="margin: auto"> </view>
+                  <view style="font-size: 14px; color: #b5b5b5">
+                    {{ activity.timestamp }}
+                  </view>
+                </view>
+              </view>
+
+              <view style="display: flex">
+                <view style="width: 18px; display: flex">
+                  <view v-if="index != activities.length - 1" style="width: 2px; background-color: #e4e7ed; margin: -5px auto"></view>
+                </view>
+                <view style="width: 100%; margin: 15px 0px 15px 15px; padding: 15px; background-color: #fff; border-radius: 10px">
+                  <view style="display: flex" v-if="activity.planStatus == 2">
+                    <view>
+                      <view>巡检任务结束</view>
+                      <br />
+                      <view style="padding: 0; font-size: 14px; color: #409eff" @click="reportClick(activity)"> 点击查看 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                  <view style="display: flex" v-if="activity.planStatus == 1">
+                    <view>
+                      <view>巡检任务执行中,还需完成 {{ activity.undetectedSiteCount }}个 </view>
+                      <br />
+                      <view @click="reportClick(activity)" style="padding: 0; font-size: 14px; color: #409eff"> 点击巡检 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                  <view style="display: flex" v-if="activity.planStatus == 3">
+                    <view>
+                      <view>巡检任务结束</view>
+                      <br />
+                      <view>
+                        <span style="margin-right: 20px">
+                          合格:
+                          <span style="color: #00cdac">
+                            {{ activity.patrolledSiteCount }}
+                          </span>
+                        </span>
+                        <span>
+                          漏检:
+                          <span style="color: #f07d28">
+                            {{ activity.undetectedSiteCount }}
+                          </span>
+                        </span>
+                      </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                </view>
+              </view>
+            </view>
+
+            <view v-for="(activity, index) in activities" :key="index" v-show="tabPosition == 1">
+              <view style="display: flex; height: 25px; line-height: 25px">
+                <view style="margin: auto 0">
+                  <u-icon name="info-circle-fill" color="#409eff" size="18"></u-icon>
+                </view>
+                <view style="display: flex; width: 100%; margin-left: 15px">
+                  <view style="font-size: 15px; color: #000000">
+                    {{ activity.areaName }}
+                  </view>
+                  <view style="margin: auto"> </view>
+                  <view style="font-size: 14px; color: #b5b5b5">
+                    {{ activity.createTime }}
+                  </view>
+                </view>
+              </view>
+
+              <view style="display: flex">
+                <view style="width: 18px; display: flex">
+                  <view v-if="index != activities.length - 1" style="width: 2px; background-color: #e4e7ed; margin: -5px auto"></view>
+                </view>
+                <view style="width: 100%; margin: 15px 0px 15px 15px; padding: 15px; background-color: #fff; border-radius: 10px">
+                  <view style="display: flex">
+                    <view>
+                      <view>已检查{{ activity.contentCount }}项内容</view>
+                      <br />
+                      <view style="padding: 0; font-size: 14px; color: #409eff" @click="reportClick(activity)"> 点击查看 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex; font-size: 15px; color: #30bb00">
+                      <view style="margin: auto">
+                        {{ activity.siteStatus == 0 ? "未定位" : "已定位" }}
+                      </view>
+                    </view>
+                  </view>
+                </view>
+              </view>
+            </view>
+          </view>
+
+          <view id="planTimeline" style="text-align: center; color: #bdbdbd; font-size: 14px" v-else> 暂无数据 </view>
+        </view>
+      </view>
+    </view>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image width="67" height="67" src="@/static/images/xunjian/plan-scan.png" shape="circle" @click="scanClick()"></u-image>
+    </view>
+
+    <drawer v-if="scanArray.length > 0" :scanArray="scanArray" :scanBool="scanBool" @scanClose="scanClose"></drawer>
+  </scroll-view>
+</template>
+
+<script setup>
+import drawer from "./components/drawer.vue";
+
+import { onLoad, onShow, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { recordList, recordOption, planList, patrolInspectionPlan, appPlanStatistics } from "@/api/business/mhxf/xunJian/plan.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @点击巡检
+ * @点击事件
+ */
+function reportClick(obj) {
+  if (tabPosition.value == 0) {
+    settingsStore.planSonId = obj.id;
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/plan/components/report",
+    });
+  } else if (tabPosition.value == 1) {
+    recordList({
+      siteId: obj.id,
+      planSonId: obj.planSonId,
+    }).then((res) => {
+      if (res.status == "SUCCESS") {
+        if (res.data.length > 0) {
+          recordOption({
+            siteId: res.data[0].siteId,
+            recordId: res.data[0].id,
+          }).then((res1) => {
+            res.data[0].inspectionStatus = 2;
+            res.data[0].pictureUrl = obj.pictureUrl;
+
+            settingsStore.contentArray = {
+              contentList: [res1.data.contentList],
+              siteList: res.data[0],
+            };
+            settingsStore.siteId = undefined;
+            settingsStore.siteNubmber = undefined;
+
+            uni.navigateTo({
+              url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+            });
+          });
+        }
+      } else {
+      }
+    });
+  }
+}
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+function scanClick() {
+  uni.scanCode({
+    success: async (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+      settingsStore.inspectionStatus = 1;
+
+      planList({
+        siteNubmber: e.result,
+      }).then((res) => {
+        if (res.status == "SUCCESS") {
+          if (res.data.length > 0) {
+            scanArray.value = res.data;
+            scanBool.value = true;
+          } else {
+            uni.showToast({
+              title: "此点位下暂无数据,请切换点位重试!",
+              icon: "none",
+            });
+          }
+        } else {
+        }
+      });
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      // uni.showToast({
+      //   title: "扫码结束",
+      //   icon: "none",
+      // });
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @抽屉emit
+ * @关闭事件
+ */
+function scanClose(flag) {
+  scanBool.value = flag;
+}
+
+/**
+ * @巡检任务
+ * @巡检记录
+ * @api接口请求
+ */
+const activities = ref([]);
+function activitiesApi() {
+  activities.value = [];
+  if (tabPosition.value == 0) {
+    patrolInspectionPlan({
+      currentDate: currentDate.value,
+      sort: activitiesSort.value,
+    }).then((res) => {
+      if (res.status == "SUCCESS") {
+        res.data.forEach((el) => {
+          activities.value.push({
+            id: el.id,
+            planName: el.planName,
+            timestamp:
+              (el.startTime == null || el.startTime == "" ? "" : el.startTime.split(":")[0] + ":" + el.startTime.split(":")[1] + "~") +
+              (el.endTime == null || el.endTime == "" ? "" : el.endTime.split(":")[0] + ":" + el.endTime.split(":")[1]),
+
+            planStatus: el.planStatus,
+            completion: el.completion,
+            patrolledSiteCount: el.patrolledSiteCount,
+            undetectedSiteCount: el.undetectedSiteCount,
+          });
+        });
+      } else {
+      }
+    });
+  } else if (tabPosition.value == 1) {
+    recordList({
+      currentDate: currentDate.value,
+      sort: activitiesSort.value,
+    }).then((res) => {
+      if (res.status == "SUCCESS") {
+        res.data.forEach((el) => {
+          activities.value.push({
+            areaName: el.areaName,
+            siteName: el.siteName,
+            contentCount: el.contentCount,
+            createTime: el.createTime.replace("T", " "),
+            siteStatus: el.siteStatus,
+          });
+        });
+      } else {
+      }
+    });
+  }
+}
+
+/**
+ * @统计
+ * @api接口请求
+ */
+const currentDate = ref(settingsStore.getDate().year + "-" + settingsStore.getDate().month + "-" + settingsStore.getDate().dates); //统计时间数据存储
+const currentDatevalue = ref(new Date());
+const currentDateList = ref({}); //统计list数据存储
+function currentApi() {
+  appPlanStatistics({
+    currentDate: currentDate.value,
+  }).then((res) => {
+    if (res.status == "SUCCESS") {
+      currentDateList.value = res.data;
+    } else {
+    }
+  });
+} 
+
+/**
+ * @排序按钮
+ */
+const activitiesSort = ref("DESC");
+function activitiesSortClick() {
+  if (activitiesSort.value == "ASC") {
+    activitiesSort.value = "DESC";
+  } else {
+    activitiesSort.value = "ASC";
+  }
+  activitiesApi();
+}
+
+/**
+ * @tabs切换change事件
+ */
+const list = ref(["巡检任务", "巡检记录"]);
+const tabPosition = ref(settingsStore.planTabs);
+function tabPositionChange(index) {
+  tabPosition.value = index;
+  activitiesApi();
+}
+
+/**
+ * @日期click事件
+ */
+const calendar = ref(); //获取日期refs元素
+function calendarClick(data) {
+  currentDate.value = data.day;
+  currentApi();
+  activitiesApi();
+}
+
+/**
+ * @触摸开始
+ **/
+let touchStartX = 0; // 触屏起始点x
+let touchStartY = 0; // 触屏起始点y
+function touchStart(e) {
+  console.log("触摸开始");
+  touchStartX = e.touches[0].clientX;
+  touchStartY = e.touches[0].clientY;
+}
+
+/**
+ * @触摸结束
+ **/
+function touchEnd(e) {
+  console.log("触摸结束");
+  let deltaX = e.changedTouches[0].clientX - touchStartX;
+  let deltaY = e.changedTouches[0].clientY - touchStartY;
+  if (Math.abs(deltaX) > 50 && Math.abs(deltaX) > Math.abs(deltaY)) {
+    if (deltaX >= 0) {
+      console.log("左滑");
+
+      calendar.value.selectDate("prev-month");
+    } else {
+      console.log("右滑");
+      calendar.value.selectDate("next-month");
+    }
+  } else if (Math.abs(deltaY) > 50 && Math.abs(deltaX) < Math.abs(deltaY)) {
+    if (deltaY < 0) {
+      console.log("上滑");
+    } else {
+      console.log("下滑");
+    }
+  } else {
+    console.log("可能是误触!");
+  }
+}
+
+onLoad((options) => {
+  currentApi();
+  activitiesApi();
+
+  // 从详情页返回该页面的获取数据
+  uni.$on("planSelect", () => {
+    currentApi();
+    activitiesApi();
+  });
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+</style>

+ 67 - 0
src/pages/business/mhxf/xunJian/record/record.vue

@@ -0,0 +1,67 @@
+<template>
+  <view class="">
+    <view class="cu-list menu-avatar">
+      <view class="cu-item" :class="modalName == 'move-box-' + index ? 'move-cur' : ''" v-for="(item, index) in getData" :key="index" :data-target="'move-box-' + index" @tap="goDetail(item)">
+        <view class="content" style="left: 0; width: 80%">
+          <view class="pro-title">
+            <view class="cut">计划:{{ item.plan_name }}</view>
+          </view>
+          <view class="pro-des">
+            <view class="text-cut"> 点位:{{ item.spot_name }} </view>
+          </view>
+          <view class="pro-date">{{ item.wc_time }}</view>
+        </view>
+        <view class="nav-right num margin-right-sm">
+          <view class="text-grey">
+            <button class="cu-btn radius bg-green sm" v-if="item.spot_abnormal == 0">正常</button>
+            <button class="cu-btn radius bg-orange sm" v-if="item.spot_abnormal == 1">异常</button>
+            <button class="cu-btn radius bg-red sm" v-if="item.spot_abnormal == 2">故障</button>
+            <button class="cu-btn radius bg-orange sm" v-if="item.spot_abnormal == 3">其他</button>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import json from "@/data/json.js";
+
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+
+import { getInspectionRecordList } from "@/api/business/mhxf/xunJian/record.js";
+
+const modalName = ref(null);
+const getData = ref([]);
+
+// 巡检记录列表数据请求
+function goRecordList(params = {}) {
+  getInspectionRecordList(params).then((res) => {
+    getData.value = res.data;
+  });
+}
+
+function goDetail(item) {
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/record/recordDetail/index?id=" + item.id,
+  });
+}
+
+onNavigationBarButtonTap((e) => {
+  console.log(e);
+  uni.navigateTo({
+    url: "/pages/export/export",
+  });
+});
+
+onLoad((option) => {
+  goRecordList({ company_code: uni.getStorageSync("selectedCode") });
+});
+</script>
+
+<style lang="scss">
+.cu-item {
+  height: 180rpx !important;
+}
+</style>

+ 130 - 0
src/pages/business/mhxf/xunJian/record/recordDetail/index.vue

@@ -0,0 +1,130 @@
+<template>
+  <view>
+    <view class="timeBox flex justify-between align-center padding-lr-sm">
+      <view class="time">{{ getData.plan_name }}</view>
+      <button class="cu-btn radius bg-green sm" v-if="getData.spot_abnormal == 0">正常</button>
+      <button class="cu-btn radius bg-orange sm" v-if="getData.spot_abnormal == 1">异常</button>
+      <button class="cu-btn radius bg-red sm" v-if="getData.spot_abnormal == 2">故障</button>
+      <button class="cu-btn radius bg-red sm" v-if="getData.spot_abnormal == 3">其他</button>
+    </view>
+
+    <view>
+      <view class="basic-info">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          基本信息
+        </view>
+        <view class="info-content">
+          <view class="info-one-info">
+            <text>所属单位:</text>
+            <text>{{ getData.owner_name }}</text>
+          </view>
+
+          <view class="info-one-info">
+            <text>单位地址:</text>
+            <text>{{ getData.owner_address }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>巡检点位:</text>
+            <text>{{ getData.spot_name }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>点位地址:</text>
+            <text>{{ getData.spot_address }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>预期时间:</text>
+            <text>{{ getData.ywc_time }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>完成时间:</text>
+            <text>{{ getData.wc_time }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 巡检信息 -->
+      <view class="basic-info">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          巡检信息
+        </view>
+        <view class="info-content">
+          <view class="info-one-info">
+            <text>巡检人员:</text>
+            <text>{{ getData.name }}</text>
+          </view>
+
+          <view class="info-one-info">
+            <text>联系方式:</text>
+            <text>{{ getData.phone }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>巡检描述:</text>
+            <text>{{ getData.dwsb_remarks }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 处理状态start -->
+      <view class="processStatus">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          巡检图片
+        </view>
+        <view class="padding-lr padding-bottom-lg imgPic">
+          <image v-if="!getData.report_photos && dataRes == 1" mode="widthFix" src="@/static/images/defaultImg.jpg" width="100%" />
+          <image v-else mode="widthFix" :src="`${websiteUrl}${getData.report_photos}`" width="100%" />
+
+          <!-- <image class="image-bg"  v-if="!getData.report_photos&&dataRes==1"  src="@/static/images/defaultImg.jpg"/>
+						<image  class="image-bg" v-else :src="getData.report_photos" /> -->
+        </view>
+      </view>
+      <!-- 处理状态end -->
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { onLoad, onShow, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, toRefs, reactive } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { getInspectionRecordDetails } from "@/api/business/mhxf/xunJian/record.js";
+
+const websiteUrl = inject("$websiteUrl");
+
+const arrayList = reactive({
+  radio: "A",
+  radio: "B",
+  modalName: null,
+  reason: "",
+  type: "0",
+  detailMessage: {},
+  detailMessage2: {},
+  msg: "",
+  msg2: "",
+  flag: false,
+  companyCode: 0,
+  getData: {},
+  dataRes: 0,
+});
+
+const { radio, modalName, reason, type, detailMessage, detailMessage2, msg, msg2, flag, companyCode, getData, dataRes } = toRefs(data);
+
+// 巡检记录列详情数据请求
+function goRecordDetail(params = {}) {
+  getInspectionRecordDetails(params).then((res) => {
+    getData.value = res.data[0];
+    dataRes.value = 1;
+  });
+}
+
+onLoad((option) => {
+  goRecordDetail({
+    company_code: uni.getStorageSync("selectedCode"),
+    id: option.id,
+  });
+});
+</script>
+
+<style lang="scss"></style>

+ 115 - 0
src/pages/business/mhxf/xunJian/xunJian.vue

@@ -0,0 +1,115 @@
+<template>
+  <scroll-view scroll-x class="grayBackgroundColor">
+    <view class="padding-sm">
+      <!-- 图表 -->
+      <view class="section1 section bg-white padding-xs">
+        <chart v-if="currentDateList.length > 0" :currentDateList="currentDateList"></chart>
+      </view>
+      <!-- 图表 end-->
+
+      <!-- <view class="cu-list menu-avatar">
+				<view class="cu-item deviceTypeItem" v-for="(item,index) in inspectList" :key="index"
+					@tap="goRecordPage(index)">
+					<view class="cu-avatar round">
+						<image class="image-bg" :src=item.imgUrl />
+					</view>
+					<view class="content">
+						<view class="title">{{item.title}}</view>
+					</view>
+					<view class="nav-right num">
+						<view>
+							<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+						</view>
+					</view>
+				</view>
+			</view> -->
+
+      <!-- 宫格列表 -->
+      <view class="section2 section bg-white margin-top-sm">
+        <view class="cu-list grid col-4 no-border" style="padding-top: 0.3125rem">
+          <view class="cu-item justify-center align-center" v-for="(item, index) in inspectList" :key="index" @tap="navItemClick(item.redirectUrl, item.id)">
+            <image :src="item.imgUrl" style="width: 40px; height: 40px"></image>
+            <view class="cu-tag badge" v-if="item.num != 0">
+              <block v-if="item.num != 0">{{ item.num > 99 ? "99+" : item.num }}</block>
+            </view>
+            <text style="font-size: 14px">{{ item.title }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 宫格列表 end -->
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject } from "vue";
+
+import chart from "./components/echarts/chart.vue";
+import json from "@/static/js/json.js";
+import useXunJianStore from "@/store/modules/xunJian";
+
+import { appPlanStatistics } from "@/api/business/mhxf/xunJian/index.js";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const inspectList = json.xunJianList; //九宫格json数据
+
+const currentDate = settingsStore.getDate().year + "-" + settingsStore.getDate().month + "-" + settingsStore.getDate().dates;
+const currentDateList = ref([]);
+
+function navItemClick(url, id) {
+  if (url) {
+    if (id == 1) {
+      settingsStore.planTabs = 0;
+    } else if (id == 2) {
+      settingsStore.planTabs = 1;
+    }
+
+    uni.navigateTo({
+      url: url,
+    });
+  } else {
+    uni.showModal({
+      title: "Tips",
+      content: "此模块开发中~",
+      showCancel: false,
+      success: function (res) {
+        if (res.confirm) {
+        } else if (res.cancel) {
+        }
+      },
+    });
+  }
+}
+
+/**
+ * @ehcarts
+ * @api接口请求
+ */
+async function echartsApi() {
+  appPlanStatistics({
+    currentDate: currentDate,
+  }).then((res) => {
+    if (res.status == "SUCCESS") {
+      currentDateList.value = [res.data];
+    } else {
+    }
+  });
+}
+
+onLoad(() => {
+  echartsApi();
+});
+</script>
+
+<style lang="scss"></style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+</style>

+ 43 - 0
src/pages/common/textview/index.vue

@@ -0,0 +1,43 @@
+<template>
+  <view>
+    <uni-card class="view-title" :title="title">
+      <text class="uni-body view-content">{{ content }}</text>
+    </uni-card>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        title: '',
+        content: ''
+      }
+    },
+    onLoad(options) {
+      this.title = options.title
+      this.content = options.content
+      uni.setNavigationBarTitle({
+        title: options.title
+      })
+    }
+  }
+</script>
+
+<style scoped>
+  page {
+    background-color: #ffffff;
+  }
+
+  .view-title {
+    font-weight: bold;
+  }
+
+  .view-content {
+    font-size: 26rpx;
+    padding: 12px 5px 0;
+    color: #333;
+    line-height: 24px;
+    font-weight: normal;
+  }
+</style>

+ 34 - 0
src/pages/common/webview/index.vue

@@ -0,0 +1,34 @@
+<template>
+  <view v-if="params.url">
+    <web-view :webview-styles="webviewStyles" :src="`${params.url}`"></web-view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        params: {},
+        webviewStyles: {
+          progress: {
+            color: "#FF3333"
+          }
+        }
+      }
+    },
+    props: {
+      src: {
+        type: [String],
+        default: null
+      }
+    },
+    onLoad(event) {
+      this.params = event
+      if (event.title) {
+        uni.setNavigationBarTitle({
+          title: event.title
+        })
+      }
+    }
+  }
+</script>

+ 138 - 0
src/pages/export/export.vue

@@ -0,0 +1,138 @@
+<template>
+  <view class="processWrapper exportBody">
+    <view style="height: 98rpx"></view>
+    <view class="ding">
+      <!-- <calendar></calendar> -->
+      <view class="example-body">
+        <uni-datetime-picker
+          v-model="datetimerange"
+          type="daterange"
+          start-placeholder="请选择开始时间"
+          end-placeholder="请选择结束时间"
+          start="2000-3-20 12:00:00"
+          end="2025-10-20 20:00:00"
+          rangeSeparator="至"
+        />
+      </view>
+    </view>
+
+    <block>
+      <view class="processList">
+        <view class="cu-list menu-avatar">
+          <view class="cu-item" v-for="(item, index) in getExportData" :key="index">
+            <view class="cu-avatar lg">
+              <image class="image-bg" :src="item.clzt == 0 ? '@/static/images/export/process-icon.png' : '@/static/images/export/processed-icon.png'" />
+            </view>
+            <view class="content">
+              <view class="pro-title">
+                <view class="cut">{{ keyWords == "人工督察单" ? item.artificial_code : item.supervise_code }}</view>
+              </view>
+              <view class="pro-des">
+                <view class="text-cut">{{ item.content }}</view>
+              </view>
+              <view class="pro-date">{{ item.timestamp }}</view>
+            </view>
+            <view class="action" style="z-index: 99">
+              <view class="unProcess" style="color: #ff4e00" v-if="item.clzt == 0">未处理</view>
+              <view class="processed" style="color: #08be04" v-else>已处理</view>
+            </view>
+          </view>
+          <view class="text-center margin-top" v-if="!getExportData.length && dataRes">暂无数据...</view>
+        </view>
+      </view>
+    </block>
+    <view v-if="getExportData.length > 0" class="padding-lr padding-bottom-lg bg-white" style="position: fixed; bottom: 0; width: 100%">
+      <view class="btn-area">
+        <button class="bg-blue round missReport margin-top" @tap="exportButton()">导 出</button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import config from "@/config";
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject, watchEffect } from "vue";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+  getExportData: [],
+  dataRes: 0,
+  datetimerange: ["", ""],
+  keyWords: "",
+});
+
+let { getExportData, dataRes, datetimerange, keyWords } = toRefs(data);
+
+onLoad((option) => {
+  keyWords = option.keywords;
+  getData({
+    company_code: uni.getStorageSync("selectedCode"),
+    start_time: "",
+    end_time: "",
+  });
+});
+
+function datetimerange1(newval) {
+  getData({
+    company_code: uni.getStorageSync("selectedCode"),
+
+    start_time: newval[0],
+    end_time: newval[1],
+  });
+}
+
+async function getData(params = {}) {
+  const res = await this.$myRequest({
+    // url: listUrl, //人员督察单渲染
+    url: keyWords == "人工督察单" ? "FireInspector/getManualInspectorList" : "FireInspector/getElectronicInspectorList",
+    data: params,
+    showLoading: true,
+  });
+  getExportData = res.data.data;
+  dataRes = 1;
+}
+
+function exportButton() {
+  let url2 = "";
+  switch (keyWords) {
+    case "人工督察单":
+      url2 = "ExportModule/getManualInspectorListExpor";
+      break;
+    case "电子督察单":
+      url2 = "ExportModule/getElectronicInspectorListExpor";
+      break;
+    default:
+      break;
+  }
+
+  //#ifdef H5
+  var start_time = datetimerange[0] ? `start_time/${datetimerange[0]}/` : "";
+  var end_time = datetimerange[1] ? `end_time/${datetimerange[1]}/` : "";
+  let exportUrl = config.BASE_URL + url2 + `/${start_time}${end_time}company_code/${uni.getStorageSync("selectedCode")}/`;
+  var ua = window.navigator.userAgent.toLowerCase();
+  // alert(exportUrl)
+  if (ua.match(/MicroMessenger/i) == "micromessenger") {
+    uni.showModal({
+      showCancel: false,
+      content: "如需下载,请在默认浏览器中操作",
+      success: function (res) {
+        window.location.href = exportUrl;
+      },
+    });
+  } else {
+    window.location.href = exportUrl;
+  }
+  //#endif
+}
+
+watchEffect(() => {
+  datetimerange1();
+});
+</script>
+
+<style lang="scss"></style>

+ 504 - 0
src/pages/index.vue

@@ -0,0 +1,504 @@
+<template>
+  <!-- <u-sticky bgColor="#fff"> </u-sticky> -->
+
+  <scroll-view scroll-x>
+    <view>
+      <!-- 下拉选择 -->
+      <!-- <view class="searchSelect shadow" v-if="flag">
+        <view class="cu-bar search bg-white">
+          <view class="search-form round" style="margin-top: 0">
+            <input
+              @focus="InputFocus"
+              @blur="InputBlur"
+              @input="handleInput()"
+              v-model="searchInput"
+              :adjust-position="false"
+              type="text"
+              placeholder=""
+              confirm-type="search"
+              style="border: none !important"
+            />
+            <text class="cuIcon-search"></text>
+          </view>
+        </view>
+        <view class="select-items">
+          <view
+            class="site-item"
+            v-if="!searchList.length"
+            style="text-align: center"
+            >暂无结果</view
+          >
+          <view
+            class="select-item"
+            v-for="(item, index) in searchList"
+            @click="clickSelectItem(item, index)"
+            :key="index"
+            >{{ item.owner_name }}</view
+          >
+        </view>
+      </view> -->
+      <!-- 下拉选择 end -->
+
+      <!-- 图表 -->
+      <!-- <view class="section1 section bg-white padding-xs">
+        <view
+          class="
+            static-tabs
+            grid
+            margin-bottom
+            text-center
+            col-3
+            margin-top-sm margin-bottom-sm
+          "
+        >
+          <view
+            :class="['padding-sm ', Inv == 0 ? 'active' : '']"
+            @click="Inv = 0"
+            >报警信息统计</view
+          >
+          <view
+            :class="['padding-sm ', Inv == 1 ? 'active' : '']"
+            @click="Inv = 1"
+            >数据等级统计</view
+          >
+          <view
+            :class="['padding-sm ', Inv == 2 ? 'active' : '']"
+            @click="Inv = 2"
+            >设备运行状态</view
+          >
+        </view>
+        <view class="time text-center"
+          >统计时段:{{ staticData.statisticalPeriod }}
+        </view>
+        <view style="height: 570rpx">
+          <view v-if="Inv == 0"> </view>
+          <view v-if="Inv == 1"> </view>
+          <view v-if="Inv == 2" class="chart3-box">
+            <ul class="chart3-icon">
+              <li>
+                <image
+                  src="@/static/images/index/chart3-1.png"
+                  style="width: 64rpx; height: 64rpx"
+                ></image>
+              </li>
+              <li>
+                <image
+                  src="@/static/images/index/chart3-2.png"
+                  style="width: 64rpx; height: 64rpx"
+                ></image>
+              </li>
+              <li>
+                <image
+                  src="@/static/images/index/chart3-3.png"
+                  style="width: 64rpx; height: 64rpx"
+                ></image>
+              </li>
+              <li>
+                <image
+                  src="@/static/images/index/chart3-4.png"
+                  style="width: 64rpx; height: 64rpx"
+                ></image>
+              </li>
+              <li>
+                <image
+                  src="@/static/images/index/chart3-5.png"
+                  style="width: 64rpx; height: 64rpx"
+                ></image>
+              </li>
+            </ul>
+          </view>
+        </view>
+      </view> -->
+      <!-- 图表 end-->
+
+      <!-- 轮播图 开始 -->
+      <u-swiper :list="arrayList.swiperList" indicator indicatorMode="line" radius="0" height="160" circular> </u-swiper>
+      <!-- 轮播图 结束 -->
+
+      <!-- 宫格列表 -->
+      <view class="section2 section bg-white" style="margin-bottom: 10px" v-if="arrayList.recentlyUsed.length > 0">
+        <view style="color: #000000; font-size: 16px; padding: 10px 10px 5px 10px">最近使用</view>
+        <view class="cu-list grid col-5 no-border">
+          <view class="cu-item justify-center align-center" @tap="navItemClick(item)" v-for="(item, index) in arrayList.recentlyUsed" :key="index">
+            <image :src="item.imgUrl" style="width: 40px; height: 40px"></image>
+            <view class="cu-tag badge" v-if="item.badge != 0">
+              <block v-if="item.badge != 0">{{ item.badge > 99 ? "99+" : item.badge }}</block>
+            </view>
+            <text style="font-size: 14px">{{ item.name }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 宫格列表 end -->
+
+      <!-- 宫格列表 -->
+      <view class="section2 section bg-white">
+        <view style="color: #000000; font-size: 16px; padding: 10px 10px 5px 10px">常用功能</view>
+        <view class="cu-list grid col-5 no-border">
+          <view class="cu-item justify-center align-center" @tap="navItemClick(item)" v-for="(item, index) in arrayList.cuIconList" :key="index">
+            <image :src="item.imgUrl" style="width: 40px; height: 40px"></image>
+            <view class="cu-tag badge" v-if="item.badge != 0">
+              <block v-if="item.badge != 0">{{ item.badge > 99 ? "99+" : item.badge }}</block>
+            </view>
+            <text style="font-size: 14px">{{ item.name }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 宫格列表 end -->
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import searchSelect from "@/components/searchSelect/searchSelect.vue";
+
+import json from "@/static/js/json.js"; //引入api请求封装方法
+import * as jwx from "@/utils/jssdk.js"; //引入js sdk的封装
+
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+import useXunJianStore from "@/store/modules/xunJian.js";
+
+import { scan_push, getHomePageData, getFunctionalModuleStatistics } from "@/api/index";
+
+const settingsStore = useXunJianStore(); //全局变量值Store
+const BASE_URL = inject("$BASE_URL");
+
+const arrayList = reactive({
+  InputBottom: 0,
+  staticData: "",
+  indicator: [],
+  datavalue: [],
+  dataname: [],
+  Inv: 0,
+  flag: false,
+  searchList: [],
+  searchList2: [],
+  searchInput: "",
+  selectedCode: 10012,
+  codeResult: "",
+
+  swiperList: ["../static/images/index/banner1.png", "../static/images/index/banner2.jpg", "../static/images/index/banner3.jpg"],
+  cuIconList: json.cuIconList,
+  recentlyUsed: [],
+});
+
+onLoad((option) => {
+  //获取首页标题
+  if (uni.getStorageSync("homeTitle")) {
+    uni.setNavigationBarTitle({
+      title: uni.getStorageSync("homeTitle"),
+    });
+  } else {
+    uni.setNavigationBarTitle({
+      title: "首页",
+    });
+  }
+
+  if (uni.getStorageSync("recentlyUsed")) {
+    arrayList.recentlyUsed = uni.getStorageSync("recentlyUsed");
+  }
+
+  // var res = uni.getStorageSync("selectedCode");
+  // var res2 = uni.getStorageSync("selectedName");
+  // if (res) {
+  //   uni.setNavigationBarTitle({
+  //     title: res2,
+  //   });
+  // }
+
+  // // 图表切换渲染
+  // this.hackReset = false;
+  // this.$nextTick(() => {
+  //   this.hackReset = true;
+  // });
+});
+
+async function init() {
+  window.location.href = BASE_URL + "Com/getPageAuthorization1";
+}
+//扫码
+function scanQRCode() {
+  // console.log(1);
+  // this.scanCode();
+  // 将this赋值给that
+  let that = this;
+  // 微信公众号获取位置
+  jwx.configWeiXin((jweixin) => {
+    jweixin.scanQRCode({
+      needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+      scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
+      success: function (res) {
+        setTimeout(function () {
+          /* 放1000ms后执行的代码 */
+          alert(res.resultStr);
+          that.getCodeResult({
+            ercode: res.resultStr,
+          });
+        }, 1000);
+      },
+    });
+  });
+}
+
+function scanCode() {
+  uni.scanCode({
+    scanType: ["qrCode"],
+    success: (res) => {
+      console.log("扫码成功", res);
+    },
+    fail: (err) => {
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      console.log("扫码结束");
+    },
+  });
+}
+
+// 扫码成功后请求
+async function getCodeResult(param = {}) {
+  scan_push(param).then((res) => {
+    if (res.data.flag) {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+    }
+  });
+}
+
+//获取地理位置
+function getLocation() {
+  // 将this赋值给that
+  let that = this;
+  // 微信公众号获取位置
+  jwx.configWeiXin((jweixin) => {
+    alert(22);
+    jweixin.getLocation({
+      type: "gcj02", // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
+      success: function (res) {
+        alert(res.longitude);
+      },
+    });
+  });
+}
+
+// 九宫格页面跳转
+function navItemClick(item) {
+  if (item.redirectUrl) {
+    item.sort = 0;
+
+    arrayList.recentlyUsed.push(item);
+
+    if (arrayList.recentlyUsed.length > 0) {
+      arrayList.recentlyUsed = arrayList.recentlyUsed.filter((currentValue, currentIndex, selfArr) => {
+        return selfArr.findIndex((x) => x.redirectUrl === currentValue.redirectUrl) === currentIndex;
+      });
+
+      arrayList.recentlyUsed.filter((el) => {
+        if (el.redirectUrl === item.redirectUrl) {
+          el.sort++;
+        }
+      });
+    }
+
+    arrayList.recentlyUsed = settingsStore.sortEvent(arrayList.recentlyUsed, 1);
+
+    uni.setStorageSync("recentlyUsed", arrayList.recentlyUsed);
+
+    uni.navigateTo({
+      url: item.redirectUrl,
+    });
+  } else {
+    uni.showModal({
+      title: "Tips",
+      content: "此模块开发中~",
+      showCancel: false,
+      success: function (res) {
+        if (res.confirm) {
+        } else if (res.cancel) {
+        }
+      },
+    });
+  }
+}
+
+function showTag() {
+  arrayList.flag = !arrayList.flag;
+}
+// 下拉选择
+function clickSelectItem(item, index) {
+  arrayList.staticData = "";
+  arrayList.selectedCode = item.owner_code;
+  uni.setStorageSync("selectedCode", item.owner_code);
+  uni.setStorageSync("selectedName", item.owner_name);
+  arrayList.searchInput = item.owner_name;
+  uni.setNavigationBarTitle({
+    title: arrayList.searchInput,
+  });
+
+  getHomeData({
+    company_code: uni.getStorageSync("selectedCode"),
+  });
+  getHandleData({
+    company_code: uni.getStorageSync("selectedCode"),
+  });
+
+  arrayList.flag = false;
+}
+
+function handleInput() {
+  var newlist = arrayList.searchList2.filter((item) => item.owner_name.indexOf(arrayList.searchInput) > -1);
+  arrayList.searchList = newlist;
+}
+
+function InputFocus(e) {
+  arrayList.InputBottom = e.detail.height;
+}
+
+function InputBlur(e) {
+  arrayList.InputBottom = 0;
+}
+//echarts图表请求
+async function getHomeData(param = {}) {
+  getHomePageData(param).then((res) => {
+    // console.log('首页请求staticData')
+    // console.log(res.data.data[0])
+    arrayList.staticData = res.data.data[0];
+
+    // var data = res.data.data[0]
+
+    var datavalue = [
+      arrayList.staticData.fire_water_count,
+      arrayList.staticData.alarm_host_count,
+      arrayList.staticData.electrical_fire_count,
+      arrayList.staticData.other_count,
+      arrayList.staticData.video_monitoring_count,
+    ];
+    var dataname = ["消防水系统", "报警主机", "电气火灾", "其他", "监控视频"];
+    var color = ["#3C8BF0", "#06CDF8", "#0ECB70", "#6744EF", "#FFD803"];
+
+    var aa = [
+      arrayList.staticData.fire_water_count,
+      arrayList.staticData.alarm_host_count,
+      arrayList.staticData.electrical_fire_count,
+      arrayList.staticData.other_count,
+      arrayList.staticData.video_monitoring_count,
+    ];
+    aa.sort(function (a, b) {
+      return a - b;
+    });
+    aa = aa.pop();
+    var datamax = [aa, aa, aa, aa, aa];
+
+    arrayList.datavalue = datavalue;
+    arrayList.dataname = dataname;
+
+    dataname.map((val, ind) => {
+      arrayList.indicator.push({
+        name: val,
+        max: datamax[ind],
+        color: color[ind],
+      });
+    });
+    arrayList.indicator = arrayList.indicator.slice(-5);
+  });
+}
+
+// 未处理告警请求
+async function getHandleData(param = {}) {
+  getFunctionalModuleStatistics(param).then((res) => {
+    arrayList.cuIconList[0].badge = res.data.data[0].comprehensive_alarm_count;
+    arrayList.cuIconList[2].badge = res.data.data[0].fire_brigade_inspector_count;
+  });
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    // alert("你点击了扫一扫");
+    this.scanQRCode();
+  } else {
+    // alert("你点击了获取位置");
+    // this.getLocation()
+    this.showTag();
+  }
+});
+</script>
+
+<style>
+.select-items {
+  overflow: auto;
+  height: 80vh;
+}
+
+.static-tabs {
+  border-radius: 50rpx;
+  border: 1rpx solid #4074e7;
+}
+
+.static-tabs > view {
+  color: #4074e7;
+  font-size: 30rpx;
+}
+
+.static-tabs > view.active {
+  color: #fff;
+  background: #4074e7;
+}
+
+.static-tabs > view:first-child {
+  border-top-left-radius: 50rpx;
+  border-bottom-left-radius: 50rpx;
+}
+
+.static-tabs > view:nth-child(2) {
+  border-left: 1px solid #4074e7;
+  border-right: 1px solid #4074e7;
+}
+
+.static-tabs > view:last-child {
+  border-top-right-radius: 50rpx;
+  border-bottom-right-radius: 50rpx;
+}
+
+/* 检测时间 */
+.time {
+  border-radius: 50rpx;
+  background: #fafcff;
+  border: 1px solid #e8f1ff;
+  padding: 20rpx;
+  color: #666666;
+  font-size: 30rpx;
+}
+
+.chart3-box {
+  position: relative;
+}
+
+.chart3-icon {
+  width: 90%;
+  position: absolute;
+  top: 60rpx;
+  left: 30rpx;
+  z-index: 1;
+}
+
+.chart3-icon li {
+  padding-top: 25rpx;
+}
+
+ul,
+li {
+  padding: 0;
+  margin: 0;
+  list-style: none;
+}
+</style>
+
+<style scoped>
+uni-page-body,
+uni-page-refresh {
+  background: rgb(241, 241, 241);
+}
+</style>

+ 79 - 0
src/pages/info/fireBase/fireBase.vue

@@ -0,0 +1,79 @@
+<template>
+	<view class="fireBashWrapper">
+		
+		<block>
+			<view class="" style="margin-top:0">
+				<view class="cu-list menu-avatar ">
+					<view class="cu-item" v-for="(item,index) in this.getData" :key="index"  @tap="goDetail(item)">
+						
+						<view class="cu-avatar">
+							<image class="image-bg" src="@/static/images/info/fire-base1.png" />
+						</view>
+						
+						<view class="content">
+							<view class="pro-title">
+								<view class="cut">{{item.title}}</view>
+							</view>
+							<view class="pro-des  ">
+								<view class="text-cut">
+									{{item.author}}
+								</view>
+							</view>
+							<view class="pro-date">{{item.release_time}}</view>
+						</view>
+						
+					</view>
+				</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				getData:[]
+			};
+		},
+		onLoad:function(option){
+			this.getFireBaseList({'company_code':uni.getStorageSync('selectedCode')})
+		
+		},
+		methods: {
+			
+			
+			// 列表数据请求
+			async getFireBaseList(params = {}) {
+				const res = await this.$myRequest({
+					url: 'KnowledgeBase/getKnowledgeBaseList',
+					data:params,
+					showLoading: true
+				})
+				this.getData=res.data.data;
+				console.log(this.getData)
+			},
+
+			
+			// 页面跳转
+			
+			goDetail(item){
+				uni.navigateTo({
+					url: '/pages/info/fireBashDetail/fireBashDetail?id='+item.id+'&title='+item.title,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+				
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+
+	.processList{
+		position:static;
+	}
+	
+</style>

+ 91 - 0
src/pages/info/fireBashDetail/fireBashDetail.vue

@@ -0,0 +1,91 @@
+<template>
+  <view class="padding fireBashDetailWrapper">
+    <view class="margin-bottom fireD-tit">{{ this.getData.title }}</view>
+    <view class="flex justify-between align-center">
+      <view>
+        <!-- <view class="cu-avatar round" style="background-image:url(@/static/images/info/fireBase.png)"></view> -->
+
+        <image class="cu-avatar round" src="@/static/images/info/fireBase.png" />
+
+        <text class="margin-left-sm margin-right-sm text-sm">{{
+          this.getData.author
+        }}</text>
+        <text>{{ this.getData.release_time }}</text>
+      </view>
+      <view style="color: #999">阅读:{{ this.getData.frequency }}</view>
+    </view>
+
+    <view class="fireD-content margin-top padding-top-xs">
+      <view class="">
+        <view v-html="this.getData.content"></view>
+      </view>
+    </view>
+
+    <view class="preAndNext" style="display: none">
+      <view class="flex align-top">
+        <view style="width: 120rpx">上一篇:</view>
+        <view style="width: calc(100% - 120rpx)">火灾逃生十大要诀</view>
+      </view>
+      <view class="flex align-top">
+        <view style="width: 120rpx">下一篇:</view>
+        <view style="width: calc(100% - 120rpx)">火灾逃生十大要诀</view>
+      </view>
+    </view>
+
+    <!-- <view class="share grid col-3">
+			<view class="share-item align">
+				<text class="icon iconfont margin-right-xs margin-left-lg">&#xe60c;</text>
+				分享
+			</view>
+			<view class="share-item" @click="clickPraise()" :class="[praise?'active':'']"><text class="icon iconfont margin-right-xs margin-left-lg"  >&#xe62a;</text>收藏</view>
+			<view class="share-item"  @click="clickZan()" :class="[zan?'active':'']"><text class="icon iconfont margin-right-xs margin-left-lg">&#xe600;</text>点赞</view>
+		</view> -->
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      praise: false,
+      zan: false,
+      getData: {},
+    };
+  },
+
+  onLoad: function (option) {
+    this.getFireBaseDetail({
+      company_code: uni.getStorageSync("selectedCode"),
+      id: option.id,
+    });
+    console.log("option");
+    console.log(option);
+    uni.setNavigationBarTitle({
+      title: option.title,
+    });
+  },
+
+  methods: {
+    // 详情页数据请求
+    async getFireBaseDetail(params = {}) {
+      const res = await this.$myRequest({
+        url: "KnowledgeBase/getKnowledgeBaseDetails",
+        data: params,
+        showLoading: true,
+      });
+      this.getData = res.data.data[0];
+      console.log(this.getData);
+    },
+
+    clickPraise() {
+      this.praise = !this.praise;
+    },
+    clickZan() {
+      this.zan = !this.zan;
+    },
+  },
+};
+</script>
+
+<style>
+</style>

+ 72 - 0
src/pages/info/info.vue

@@ -0,0 +1,72 @@
+<template>
+  <view class="analyse-wrapper info-wrapper" style="height: 100%">
+    <view class="justify-center align-center text-center">
+      <u-image src="@/static/images/info/info-bg.png" width="100%" height="273rpx" :showLoading="false" :fade="false"></u-image>
+    </view>
+
+    <scroll-view scroll-y style="height: calc(100% - 273rpx)">
+      <view class="cu-list menu-avatar padding-lr-sm padding-top-sm">
+        <view class="cu-item margin-bottom-sm" @tap="goFireBase()">
+          <view class="cu-avatar">
+            <image class="image-bg" src="@/static/images/info/fireBase.png" />
+          </view>
+          <view class="content">
+            <view class="">消防知识库</view>
+          </view>
+          <view class="nav-right">
+            <view class="text-grey">
+              <text class="icon iconfont margin-right-xs margin-left-lg"> &#xe629; </text>
+            </view>
+          </view>
+        </view>
+        <!-- <view class="cu-item " @tap="goPushList()">
+				<view class="cu-avatar " style="background-image:url(@/static/images/info/pushList.png)"></view>
+				<view class="content">
+					<view class="">消息推送</view>
+				</view>
+				<view class="nav-right">
+					<view class="text-grey">
+						<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+					</view>
+				</view>
+			</view> -->
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script>
+import indexBackgroundImage from "@/static/images/info/fireBase.png";
+
+export default {
+  data() {
+    return {
+      indexBackgroundImage: indexBackgroundImage,
+    };
+  },
+  methods: {
+    goFireBase() {
+      uni.navigateTo({
+        url: "/pages/info/fireBase/fireBase",
+        success: (res) => {},
+        fail: () => {},
+        complete: () => {},
+      });
+    },
+    goPushList() {
+      uni.navigateTo({
+        url: "/pages/info/pushList/pushList",
+        success: (res) => {},
+        fail: () => {},
+        complete: () => {},
+      });
+    },
+  },
+};
+</script>
+
+<style>
+body {
+  background: #fff;
+}
+</style>

+ 192 - 0
src/pages/info/pushList/pushList.vue

@@ -0,0 +1,192 @@
+<template>
+	<view class="fireBashWrapper pushListWrapper ">
+		<view style="height:90rpx"></view>
+		<view class="ding">
+			<scroll-view scroll-x class="bg-white nav text-center">
+				<view class="cu-item" :class="index==TabCur?'text-blue cur':''" v-for="(item,index) in tabNav"
+					:key="index" @tap="tabSelect" :data-id="index">
+					<view class="cu-tag badge">
+						<block class="cu-tag badge" v-if="item.badge!=1">99</block>
+					</view>
+					{{tabNav[index]}}
+				</view>
+			</scroll-view>
+		</view>
+
+		<block v-if="TabCur==0">
+			<view class="" style="margin-top:0">
+				<view class="cu-list menu-avatar ">
+					<view class="cu-item" v-for="(item,index) in unporcessList" :key="index" @tap="goFireBaseDetail">
+						<view class="cu-avatar" style="background-image:url(@/static/images/info/push-list.png);"></view>
+						<view class="content">
+							<view class="pro-title">
+								<view class="cut">{{item.title}}</view>
+							</view>
+							<view class="pro-des  ">
+								<view class="text-cut">
+									{{item.subtit}}
+								</view>
+							</view>
+							<view class="pro-date">{{item.time}}</view>
+						</view>
+
+					</view>
+				</view>
+			</view>
+		</block>
+		<block v-if="TabCur==1">
+			<view class="" style="margin-top:0">
+				<view class="cu-list menu-avatar ">
+					<view class="cu-item" v-for="(item,index) in unporcessList" :key="index" @tap="goFireBaseDetail">
+						<view class="cu-avatar" style="background-image:url(@/static/images/info/push-list.png);"></view>
+						<view class="content">
+							<view class="pro-title">
+								<view class="cut">{{item.title}}</view>
+							</view>
+							<view class="pro-des  ">
+								<view class="text-cut">
+									{{item.subtit}}
+								</view>
+							</view>
+							<view class="pro-date">{{item.time}}</view>
+						</view>
+
+					</view>
+				</view>
+			</view>
+		</block>
+
+	</view>
+</template>
+
+<script>
+	import json from '../../../data/json.js';
+	export default {
+		data() {
+			return {
+				unporcessList: [{
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}, {
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}, {
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}, {
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}, {
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}, {
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					},
+					{
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					},
+					{
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					},
+					{
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					},
+					{
+						title: '火灾逃生九大要诀',
+						time: '2020-02-12',
+						subtit: 'admin'
+					}
+				],
+
+				processedList: json.processedList,
+
+				type: '0',
+				modalName: null,
+				listTouchStart: 0,
+				listTouchDirection: null,
+				CustomBar: this.CustomBar,
+				TabCur: 0,
+				tabNav: ['未读', '已读']
+			};
+		},
+
+		methods: {
+			tabSelect(e) {
+				this.TabCur = e.currentTarget.dataset.id;
+				this.scrollLeft = (e.currentTarget.dataset.id - 1) * 60
+			},
+
+			// 页面跳转
+			goUnprocessDetail() {
+				uni.navigateTo({
+					url: '/pages/unprocessDetail/unprocessDetail?type=1',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			},
+			goProcessedDetail() {
+				uni.navigateTo({
+					url: '/pages/processedDetail/processedDetail?type=1',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			},
+			goVideoUnprocessDetail() {
+				uni.navigateTo({
+					url: '/pages/unprocessDetail/unprocessDetail?type=2',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			},
+			goVideoProcessedDetail() {
+				uni.navigateTo({
+					url: '/pages/processedDetail/processedDetail?type=2',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	//已处理未处理消息个数样式
+
+	.nav .cu-item.cur {
+		position: relative;
+		border-bottom: 8rpx solid;
+	}
+
+	.cu-tag.badge {
+		top: 14rpx;
+		right: 96rpx;
+	}
+
+	.nav .cu-item {
+		width: 50%;
+		margin: 0;
+
+		.text-blue,
+		.line-blue,
+		.lines-blue {
+			color: #4274E7
+		}
+	}
+</style>

+ 419 - 0
src/pages/login.vue

@@ -0,0 +1,419 @@
+<template>
+  <view class="section">
+    <view class="bg">
+      <image class="bgImage" :src="bg" v-if="bg" />
+      <image class="bgImage" src="@/static/images/wt/bg.png" v-if="!bg" />
+    </view>
+    <view class="top">
+      <image class="logo" :src="logo" mode="widthFix" v-if="logo" />
+      <text class="title">{{ title }}</text>
+    </view>
+    <view class="middle login">
+      <view id="login-input" style="margin-top: 20px" v-if="switchText == '账号密码登录'">
+        <u-input v-model="phone" prefixIcon="phone" placeholder="请输入手机号码" />
+      </view>
+
+      <view id="login-input" style="display: flex; margin-top: 20px" v-if="switchText == '账号密码登录'">
+        <u-input style="width: 60%" v-model="verify" prefixIcon="search" placeholder="请输入验证码" />
+
+        <u-button @click="getVerifyCode">{{ !codeTime ? "获取验证码" : codeTime + "s" }}</u-button>
+      </view>
+
+      <view id="login-input" style="margin-top: 20px" v-if="switchText == '验证码登录'">
+        <u-input type="text" v-model="username" prefixIcon="lock" placeholder="请输入账号" />
+
+        <u-input style="margin-top: 20px" v-model="password" prefixIcon="search" placeholder="请输入密码" :password="inputIconBool">
+          <template #suffix>
+            <text class="iconfont ucicon-eye" @click="inputIcon()" v-if="!inputIconBool"></text>
+            <text class="iconfont ucicon-eye-close" @click="inputIcon()" v-if="inputIconBool"></text>
+          </template>
+        </u-input>
+      </view>
+
+      <!--  -->
+
+      <view class="switchText" @click="switchMode">
+        <text>{{ switchText }}</text>
+      </view>
+      <button class="submit" @click="submitRes">登 录</button>
+    </view>
+    <view class="bottom">
+      <div class="title">{{ bottomTitle }}</div>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { reactive, getCurrentInstance, toRefs, inject } from "vue";
+import { getToken, setToken, removeToken } from "@/utils/auth";
+import { Lock, User, Cellphone } from "@element-plus/icons-vue";
+import { getCodeImg, getMobileTenantConfig } from "@/api/login";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+  /** saas数据 */
+  bg: "/static/images/wt/bg.png",
+  logo: undefined,
+  title: undefined,
+  bottomTitle: undefined,
+  /** login数据 */
+  phone: undefined,
+  verify: undefined,
+  codeTime: 0,
+  switchText: "验证码登录",
+  tenantId: undefined,
+  username: undefined,
+  password: undefined,
+  inputIconBool: true,
+
+  // VerificationCodeOne
+});
+
+const { title, bg, bottomTitle, logo, phone, verify, codeTime, switchText, username, password, tenantId, inputIconBool } = toRefs(data);
+/**登录方式切换 */
+function switchMode() {
+  if (switchText.value == "验证码登录") {
+    switchText.value = "账号密码登录";
+  } else {
+    switchText.value = "验证码登录";
+  }
+}
+/** 点击发送验证码 */
+function getVerifyCode() {
+  if (!phone.value) {
+    uni.showToast({
+      title: "请输入手机号码...",
+      icon: "none",
+    });
+    return;
+  }
+  if (!/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(phone.value)) {
+    uni.showToast({
+      title: "请输入正确的手机号码...",
+      icon: "none",
+    });
+    return;
+  }
+  verify.value = undefined;
+  getSendSms({
+    phone: phone.value,
+  });
+  //
+  if (codeTime.value > 0) {
+    uni.showToast({
+      title: "不能重复获取",
+      icon: "none",
+    });
+    return;
+  } else {
+    codeTime.value = 60;
+    let timer = setInterval(() => {
+      codeTime.value--;
+      if (codeTime.value < 1) {
+        clearInterval(timer);
+        codeTime.value = 0;
+      }
+    }, 1000);
+  }
+}
+/** 获取验证码 */
+async function getSendSms(params) {
+  getCodeImg(params).then((res) => {
+    console.log(res);
+  });
+}
+
+/**
+ * 判断运行环境
+ */
+function env() {
+  // const u = navigator.userAgent
+  // //https://blog.csdn.net/weixin_42659644/article/details/126294231
+  // if(u.indexOf('saas')>-1){ //指定app内 获取app识别号
+  // }else{
+
+  // }
+
+  let port = uni.getSystemInfoSync().platform;
+  switch (port) {
+    case "android":
+      console.log("Android"); //android
+      break;
+    case "ios":
+      console.log("iOS"); //ios
+      break;
+    case "windows":
+      // console.log("H5"); //H5
+      //getMobileTenantConfigApi({ url: "172.16.1.47:3000" })
+      getMobileTenantConfigApi({ url: window.location.host });
+      break;
+    default: //devtools
+      console.log("小程序");
+      break;
+  }
+}
+// env();
+//getMobileTenantConfigApi({ url: "172.16.1.47:3000" }) // 测试
+/** 点击提交按钮 */
+async function submitRes() {
+  if (switchText.value == "账号密码登录") {
+    if (!phone.value) {
+      uni.showToast({
+        title: "请输入手机号码...",
+        icon: "none",
+      });
+      return;
+    }
+    if (!/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(phone.value)) {
+      uni.showToast({
+        title: "请输入正确的手机号码...",
+        icon: "none",
+      });
+      return;
+    }
+    if (!verify.value) {
+      uni.showToast({
+        title: "请输入验证码...",
+        icon: "none",
+      });
+      return;
+    }
+    login({
+      phone: phone.value,
+      verify: verify.value,
+      tenantId: tenantId.value,
+    });
+  } else {
+    if (!username.value) {
+      uni.showToast({
+        title: "请输入账户",
+        icon: "none",
+      });
+      return;
+    }
+    if (!password.value) {
+      uni.showToast({
+        title: "请输入密码",
+        icon: "none",
+      });
+      return;
+    }
+    login({
+      username: username.value,
+      password: password.value,
+      tenantId: tenantId.value,
+    });
+  }
+}
+
+/** 获取登录数据 */
+async function login(data) {
+  proxy.$modal.loading("登录中,请耐心等待...");
+
+  useStore.Login(data).then(() => {
+    info();
+  });
+}
+
+/** 获取用户信息 */
+async function info() {
+  proxy.$modal.closeLoading();
+  useStore.GetInfo().then((res) => {
+    proxy.$tab.reLaunch("/pages/index");
+  });
+}
+
+/** 获取登录页数据 */
+async function getMobileTenantConfigApi(params) {
+  getMobileTenantConfig(params).then((res) => {
+    if (res.data.data.length > 0) {
+      let data = res.data.data[0];
+      bg.value = data.loginBackUrl;
+      title.value = data.loginTitle;
+
+      bottomTitle.value = data.loginFooter;
+      tenantId.value = data.tenantId;
+      uni.setStorageSync("homeTitle", data.loginTitle);
+    }
+  });
+}
+
+/**
+ * @密码显示隐藏icon图标事件
+ * @icon点击事件
+ */
+function inputIcon() {
+  inputIconBool.value = !inputIconBool.value;
+}
+
+/**
+ * @onLoad
+ */
+onLoad(() => {
+  const token = getToken();
+  //需要登录
+  if (token) {
+    uni.switchTab({
+      url: "/pages/index",
+    });
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.section {
+  position: fixed;
+  height: 100%;
+  width: 100%;
+  overflow: hidden;
+  .bg {
+    width: 100%;
+    height: 100%;
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 0;
+    background: #000;
+    .bgImage {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .top {
+    margin: 90px auto 0px;
+    .logo {
+      width: 110px;
+      margin: 0 auto 44px;
+      display: block;
+    }
+    .title {
+      width: 100%;
+      position: absolute;
+      z-index: 1;
+      font-size: 20px;
+      text-align: center;
+      color: #fff;
+      font-weight: 700;
+    }
+  }
+  .middle {
+    position: absolute;
+    z-index: 1;
+    width: calc(100% - 64px);
+    margin: 40px 32px 0;
+    .switchText {
+      color: #fff;
+      font-size: 18px;
+      margin-top: 19px;
+      width: 100%;
+      display: block;
+    }
+    .submit {
+      height: 48px;
+      line-height: 48px;
+      border-radius: 24px;
+      background: #2a98ff;
+      color: #fff;
+      margin-top: 45px;
+    }
+  }
+  .bottom {
+    position: absolute;
+    width: 100%;
+    bottom: 10px;
+    .title {
+      text-align: center;
+      color: #fff;
+      font-size: 14px;
+    }
+  }
+}
+
+.content {
+  height: 434rpx;
+  text-align: center;
+  position: relative;
+}
+
+.login-box {
+  height: 600rpx;
+  position: relative;
+  top: -150rpx;
+  background: #fff;
+  border-radius: 30rpx;
+  padding: 100rpx 20rpx;
+}
+
+.shadow {
+  box-shadow: 0px 2px 4px rgb(26 26 26 / 10%);
+}
+
+.title {
+  position: absolute;
+  color: #fff;
+  font-size: 60rpx;
+  bottom: 180rpx;
+  display: block;
+  width: 100%;
+}
+
+input,
+button {
+  width: 100%;
+  height: 100rpx;
+  line-height: 100rpx;
+  opacity: 1;
+  border: 1px solid #dbdbdb;
+  border-radius: 100rpx;
+  background: #fff;
+  color: #333;
+  margin: 40rpx 0;
+  font-size: 34rpx;
+}
+
+input {
+  text-indent: 100rpx;
+}
+.submit {
+  background: #4074e7;
+  color: #fff;
+}
+.phone-box,
+.password-box {
+  position: relative;
+}
+.password-box .verify {
+  font-size: 30rpx;
+  color: #999999;
+}
+.left-icon {
+  position: absolute;
+  left: 48rpx;
+  top: 50%;
+  margin-top: -20rpx;
+  line-height: 100%;
+  font-size: 40rpx;
+  color: #7a7a7a;
+}
+.right-icon {
+  position: absolute;
+  right: 48rpx;
+  top: 50%;
+  margin-top: -20rpx;
+  line-height: 100%;
+  font-size: 40rpx;
+}
+.right-icon.verify {
+  margin-top: -10rpx;
+  color: #4074e7;
+}
+.iconfont {
+  color: #999;
+}
+</style>

+ 75 - 0
src/pages/mine/about/index.vue

@@ -0,0 +1,75 @@
+<template>
+  <view class="about-container">
+    <view class="header-section text-center">
+      <image style="width: 150rpx; height: 150rpx" src="@/static/logo200.png" mode="widthFix"> </image>
+      <uni-title type="h2" title="永天saas移动端"></uni-title>
+    </view>
+
+    <view class="content-section">
+      <view class="menu-list">
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>版本信息</view>
+            <view class="text-right">v{{ version }}</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>官方邮箱</view>
+            <!-- <view class="text-right">ruoyi@xx.com</view> -->
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>服务热线</view>
+            <!-- <view class="text-right">400-999-9999</view> -->
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>公司网站</view>
+            <view class="text-right">
+              <uni-link :href="url" :text="url" showUnderLine="false"></uni-link>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <view class="copyright">
+      <!-- <view>Copyright &copy; 2022 ruoyi.vip All Rights Reserved.</view> -->
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const url = ref(getApp().globalData.config.appInfo.site_url);
+const version = ref(getApp().globalData.config.appInfo.version);
+</script>
+
+<style lang="scss">
+page {
+  background-color: #f8f8f8;
+}
+
+.copyright {
+  margin-top: 50rpx;
+  text-align: center;
+  line-height: 60rpx;
+  color: #999;
+}
+
+.header-section {
+  display: flex;
+  padding: 30rpx 0 0;
+  flex-direction: column;
+  align-items: center;
+}
+</style>

+ 634 - 0
src/pages/mine/avatar/index.vue

@@ -0,0 +1,634 @@
+<template>
+  <view class="container">
+    <view class="page-body uni-content-info">
+      <view class="cropper-content">
+        <view v-if="isShowImg" class="uni-corpper" :style="'width:' + cropperInitW + 'px;height:' + cropperInitH + 'px;background:#000'">
+          <view class="uni-corpper-content" :style="'width:' + cropperW + 'px;height:' + cropperH + 'px;left:' + cropperL + 'px;top:' + cropperT + 'px'">
+            <image :src="imageSrc" :style="'width:' + cropperW + 'px;height:' + cropperH + 'px'"></image>
+            <view
+              class="uni-corpper-crop-box"
+              @touchstart.stop="contentStartMove"
+              @touchmove.stop="contentMoveing"
+              @touchend.stop="contentTouchEnd"
+              :style="'left:' + cutL + 'px;top:' + cutT + 'px;right:' + cutR + 'px;bottom:' + cutB + 'px'"
+            >
+              <view class="uni-cropper-view-box">
+                <view class="uni-cropper-dashed-h"></view>
+                <view class="uni-cropper-dashed-v"></view>
+                <view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-point point-tr" data-drag="topTight"></view>
+                <view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-point point-rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
+                <view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
+                <view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+                <view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="cropper-config">
+        <button type="primary reverse" @click="getImage" style="margin-top: 30rpx">选择头像</button>
+        <button type="warn" @click="getImageInfo" style="margin-top: 30rpx">提交</button>
+      </view>
+      <canvas canvas-id="myCanvas" :style="'position:absolute;border: 1px solid red; width:' + imageW + 'px;height:' + imageH + 'px;top:-9999px;left:-9999px;'"></canvas>
+    </view>
+  </view>
+</template>
+
+<script>
+import config from "@/config";
+import store from "@/store";
+import { uploadAvatar } from "@/api/system/user";
+
+const baseUrl = config.baseUrl;
+let sysInfo = uni.getSystemInfoSync();
+let SCREEN_WIDTH = sysInfo.screenWidth;
+let PAGE_X, // 手按下的x位置
+  PAGE_Y, // 手按下y的位置
+  PR = sysInfo.pixelRatio, // dpi
+  T_PAGE_X, // 手移动的时候x的位置
+  T_PAGE_Y, // 手移动的时候Y的位置
+  CUT_L, // 初始化拖拽元素的left值
+  CUT_T, // 初始化拖拽元素的top值
+  CUT_R, // 初始化拖拽元素的
+  CUT_B, // 初始化拖拽元素的
+  CUT_W, // 初始化拖拽元素的宽度
+  CUT_H, //  初始化拖拽元素的高度
+  IMG_RATIO, // 图片比例
+  IMG_REAL_W, // 图片实际的宽度
+  IMG_REAL_H, // 图片实际的高度
+  DRAFG_MOVE_RATIO = 1, //移动时候的比例,
+  INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
+  DRAW_IMAGE_W = sysInfo.screenWidth; // 设置生成的图片宽度
+
+export default {
+  /**
+   * 页面的初始数据
+   */
+  data() {
+    return {
+      imageSrc: store.getters.avatar,
+      isShowImg: false,
+      // 初始化的宽高
+      cropperInitW: SCREEN_WIDTH,
+      cropperInitH: SCREEN_WIDTH,
+      // 动态的宽高
+      cropperW: SCREEN_WIDTH,
+      cropperH: SCREEN_WIDTH,
+      // 动态的left top值
+      cropperL: 0,
+      cropperT: 0,
+
+      transL: 0,
+      transT: 0,
+
+      // 图片缩放值
+      scaleP: 0,
+      imageW: 0,
+      imageH: 0,
+
+      // 裁剪框 宽高
+      cutL: 0,
+      cutT: 0,
+      cutB: SCREEN_WIDTH,
+      cutR: "100%",
+      qualityWidth: DRAW_IMAGE_W,
+      innerAspectRadio: DRAFG_MOVE_RATIO,
+    };
+  },
+  /**
+   * 生命周期函数--监听页面初次渲染完成
+   */
+  onReady: function () {
+    this.loadImage();
+  },
+  methods: {
+    setData: function (obj) {
+      let that = this;
+      Object.keys(obj).forEach(function (key) {
+        that.$set(that.$data, key, obj[key]);
+      });
+    },
+    getImage: function () {
+      var _this = this;
+      uni.chooseImage({
+        success: function (res) {
+          _this.setData({
+            imageSrc: res.tempFilePaths[0],
+          });
+          _this.loadImage();
+        },
+      });
+    },
+    loadImage: function () {
+      var _this = this;
+
+      uni.getImageInfo({
+        src: _this.imageSrc,
+        success: function success(res) {
+          IMG_RATIO = 1 / 1;
+          if (IMG_RATIO >= 1) {
+            IMG_REAL_W = SCREEN_WIDTH;
+            IMG_REAL_H = SCREEN_WIDTH / IMG_RATIO;
+          } else {
+            IMG_REAL_W = SCREEN_WIDTH * IMG_RATIO;
+            IMG_REAL_H = SCREEN_WIDTH;
+          }
+          let minRange = IMG_REAL_W > IMG_REAL_H ? IMG_REAL_W : IMG_REAL_H;
+          INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange;
+          // 根据图片的宽高显示不同的效果   保证图片可以正常显示
+          if (IMG_RATIO >= 1) {
+            let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2);
+            let cutB = cutT;
+            let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2);
+            let cutR = cutL;
+            _this.setData({
+              cropperW: SCREEN_WIDTH,
+              cropperH: SCREEN_WIDTH / IMG_RATIO,
+              // 初始化left right
+              cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+              cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH / IMG_RATIO) / 2),
+              cutL: cutL,
+              cutT: cutT,
+              cutR: cutR,
+              cutB: cutB,
+              // 图片缩放值
+              imageW: IMG_REAL_W,
+              imageH: IMG_REAL_H,
+              scaleP: IMG_REAL_W / SCREEN_WIDTH,
+              qualityWidth: DRAW_IMAGE_W,
+              innerAspectRadio: IMG_RATIO,
+            });
+          } else {
+            let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - SCREEN_WIDTH * IMG_RATIO) / 2);
+            let cutR = cutL;
+            let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2);
+            let cutB = cutT;
+            _this.setData({
+              cropperW: SCREEN_WIDTH * IMG_RATIO,
+              cropperH: SCREEN_WIDTH,
+              // 初始化left right
+              cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH * IMG_RATIO) / 2),
+              cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+
+              cutL: cutL,
+              cutT: cutT,
+              cutR: cutR,
+              cutB: cutB,
+              // 图片缩放值
+              imageW: IMG_REAL_W,
+              imageH: IMG_REAL_H,
+              scaleP: IMG_REAL_W / SCREEN_WIDTH,
+              qualityWidth: DRAW_IMAGE_W,
+              innerAspectRadio: IMG_RATIO,
+            });
+          }
+          _this.setData({
+            isShowImg: true,
+          });
+          uni.hideLoading();
+        },
+      });
+    },
+    // 拖动时候触发的touchStart事件
+    contentStartMove(e) {
+      PAGE_X = e.touches[0].pageX;
+      PAGE_Y = e.touches[0].pageY;
+    },
+
+    // 拖动时候触发的touchMove事件
+    contentMoveing(e) {
+      var _this = this;
+      var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
+      var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
+      // 左移
+      if (dragLengthX > 0) {
+        if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL;
+      } else {
+        if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR;
+      }
+
+      if (dragLengthY > 0) {
+        if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT;
+      } else {
+        if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB;
+      }
+      this.setData({
+        cutL: this.cutL - dragLengthX,
+        cutT: this.cutT - dragLengthY,
+        cutR: this.cutR + dragLengthX,
+        cutB: this.cutB + dragLengthY,
+      });
+
+      PAGE_X = e.touches[0].pageX;
+      PAGE_Y = e.touches[0].pageY;
+    },
+
+    contentTouchEnd() {},
+
+    // 获取图片
+    getImageInfo() {
+      var _this = this;
+      uni.showLoading({
+        title: "图片生成中...",
+      });
+      // 将图片写入画布
+      const ctx = uni.createCanvasContext("myCanvas");
+      ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
+      ctx.draw(true, () => {
+        // 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
+        var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W;
+        var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H;
+        var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W;
+        var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H;
+        uni.canvasToTempFilePath({
+          x: canvasL,
+          y: canvasT,
+          width: canvasW,
+          height: canvasH,
+          destWidth: canvasW,
+          destHeight: canvasH,
+          quality: 0.5,
+          canvasId: "myCanvas",
+          success: function (res) {
+            uni.hideLoading();
+            let data = { name: "avatarfile", filePath: res.tempFilePath };
+            uploadAvatar(data).then((response) => {
+              store.commit("SET_AVATAR", baseUrl + response.imgUrl);
+              uni.showToast({ title: "修改成功", icon: "success" });
+              uni.navigateBack();
+            });
+          },
+        });
+      });
+    },
+    // 设置大小的时候触发的touchStart事件
+    dragStart(e) {
+      T_PAGE_X = e.touches[0].pageX;
+      T_PAGE_Y = e.touches[0].pageY;
+      CUT_L = this.cutL;
+      CUT_R = this.cutR;
+      CUT_B = this.cutB;
+      CUT_T = this.cutT;
+    },
+
+    // 设置大小的时候触发的touchMove事件
+    dragMove(e) {
+      var _this = this;
+      var dragType = e.target.dataset.drag;
+      switch (dragType) {
+        case "right":
+          var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
+          if (CUT_R + dragLength < 0) dragLength = -CUT_R;
+          this.setData({
+            cutR: CUT_R + dragLength,
+          });
+          break;
+        case "left":
+          var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
+          if (CUT_L - dragLength < 0) dragLength = CUT_L;
+          if (CUT_L - dragLength > this.cropperW - this.cutR) dragLength = CUT_L - (this.cropperW - this.cutR);
+          this.setData({
+            cutL: CUT_L - dragLength,
+          });
+          break;
+        case "top":
+          var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
+          if (CUT_T - dragLength < 0) dragLength = CUT_T;
+          if (CUT_T - dragLength > this.cropperH - this.cutB) dragLength = CUT_T - (this.cropperH - this.cutB);
+          this.setData({
+            cutT: CUT_T - dragLength,
+          });
+          break;
+        case "bottom":
+          var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
+          if (CUT_B + dragLength < 0) dragLength = -CUT_B;
+          this.setData({
+            cutB: CUT_B + dragLength,
+          });
+          break;
+        case "rightBottom":
+          var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
+          var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
+
+          if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B;
+          if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R;
+          let cutB = CUT_B + dragLengthY;
+          let cutR = CUT_R + dragLengthX;
+
+          this.setData({
+            cutB: cutB,
+            cutR: cutR,
+          });
+          break;
+        default:
+          break;
+      }
+    },
+  },
+};
+</script>
+
+<style>
+/* pages/uni-cropper/index.wxss */
+
+.uni-content-info {
+  /* position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		display: block;
+		align-items: center;
+		flex-direction: column; */
+}
+
+.cropper-config {
+  padding: 20rpx 40rpx;
+}
+
+.cropper-content {
+  min-height: 750rpx;
+  width: 100%;
+}
+
+.uni-corpper {
+  position: relative;
+  overflow: hidden;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-tap-highlight-color: transparent;
+  -webkit-touch-callout: none;
+  box-sizing: border-box;
+}
+
+.uni-corpper-content {
+  position: relative;
+}
+
+.uni-corpper-content image {
+  display: block;
+  width: 100%;
+  min-width: 0 !important;
+  max-width: none !important;
+  height: 100%;
+  min-height: 0 !important;
+  max-height: none !important;
+  image-orientation: 0deg !important;
+  margin: 0 auto;
+}
+/* 移动图片效果 */
+
+.uni-cropper-drag-box {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  cursor: move;
+  background: rgba(0, 0, 0, 0.6);
+  z-index: 1;
+}
+/* 内部的信息 */
+
+.uni-corpper-crop-box {
+  position: absolute;
+  background: rgba(255, 255, 255, 0.3);
+  z-index: 2;
+}
+
+.uni-corpper-crop-box .uni-cropper-view-box {
+  position: relative;
+  display: block;
+  width: 100%;
+  height: 100%;
+  overflow: visible;
+  outline: 1rpx solid #69f;
+  outline-color: rgba(102, 153, 255, 0.75);
+}
+/* 横向虚线 */
+
+.uni-cropper-dashed-h {
+  position: absolute;
+  top: 33.33333333%;
+  left: 0;
+  width: 100%;
+  height: 33.33333333%;
+  border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
+  border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
+}
+/* 纵向虚线 */
+
+.uni-cropper-dashed-v {
+  position: absolute;
+  left: 33.33333333%;
+  top: 0;
+  width: 33.33333333%;
+  height: 100%;
+  border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
+  border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
+}
+/* 四个方向的线  为了之后的拖动事件*/
+
+.uni-cropper-line-t {
+  position: absolute;
+  display: block;
+  width: 100%;
+  background-color: #69f;
+  top: 0;
+  left: 0;
+  height: 1rpx;
+  opacity: 0.1;
+  cursor: n-resize;
+}
+
+.uni-cropper-line-t::before {
+  content: "";
+  position: absolute;
+  top: 50%;
+  right: 0rpx;
+  width: 100%;
+  -webkit-transform: translate3d(0, -50%, 0);
+  transform: translate3d(0, -50%, 0);
+  bottom: 0;
+  height: 41rpx;
+  background: transparent;
+  z-index: 11;
+}
+
+.uni-cropper-line-r {
+  position: absolute;
+  display: block;
+  background-color: #69f;
+  top: 0;
+  right: 0rpx;
+  width: 1rpx;
+  opacity: 0.1;
+  height: 100%;
+  cursor: e-resize;
+}
+
+.uni-cropper-line-r::before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 50%;
+  width: 41rpx;
+  -webkit-transform: translate3d(-50%, 0, 0);
+  transform: translate3d(-50%, 0, 0);
+  bottom: 0;
+  height: 100%;
+  background: transparent;
+  z-index: 11;
+}
+
+.uni-cropper-line-b {
+  position: absolute;
+  display: block;
+  width: 100%;
+  background-color: #69f;
+  bottom: 0;
+  left: 0;
+  height: 1rpx;
+  opacity: 0.1;
+  cursor: s-resize;
+}
+
+.uni-cropper-line-b::before {
+  content: "";
+  position: absolute;
+  top: 50%;
+  right: 0rpx;
+  width: 100%;
+  -webkit-transform: translate3d(0, -50%, 0);
+  transform: translate3d(0, -50%, 0);
+  bottom: 0;
+  height: 41rpx;
+  background: transparent;
+  z-index: 11;
+}
+
+.uni-cropper-line-l {
+  position: absolute;
+  display: block;
+  background-color: #69f;
+  top: 0;
+  left: 0;
+  width: 1rpx;
+  opacity: 0.1;
+  height: 100%;
+  cursor: w-resize;
+}
+
+.uni-cropper-line-l::before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 50%;
+  width: 41rpx;
+  -webkit-transform: translate3d(-50%, 0, 0);
+  transform: translate3d(-50%, 0, 0);
+  bottom: 0;
+  height: 100%;
+  background: transparent;
+  z-index: 11;
+}
+
+.uni-cropper-point {
+  width: 5rpx;
+  height: 5rpx;
+  background-color: #69f;
+  opacity: 0.75;
+  position: absolute;
+  z-index: 3;
+}
+
+.point-t {
+  top: -3rpx;
+  left: 50%;
+  margin-left: -3rpx;
+  cursor: n-resize;
+}
+
+.point-tr {
+  top: -3rpx;
+  left: 100%;
+  margin-left: -3rpx;
+  cursor: n-resize;
+}
+
+.point-r {
+  top: 50%;
+  left: 100%;
+  margin-left: -3rpx;
+  margin-top: -3rpx;
+  cursor: n-resize;
+}
+
+.point-rb {
+  left: 100%;
+  top: 100%;
+  -webkit-transform: translate3d(-50%, -50%, 0);
+  transform: translate3d(-50%, -50%, 0);
+  cursor: n-resize;
+  width: 36rpx;
+  height: 36rpx;
+  background-color: #69f;
+  position: absolute;
+  z-index: 1112;
+  opacity: 1;
+}
+
+.point-b {
+  left: 50%;
+  top: 100%;
+  margin-left: -3rpx;
+  margin-top: -3rpx;
+  cursor: n-resize;
+}
+
+.point-bl {
+  left: 0%;
+  top: 100%;
+  margin-left: -3rpx;
+  margin-top: -3rpx;
+  cursor: n-resize;
+}
+
+.point-l {
+  left: 0%;
+  top: 50%;
+  margin-left: -3rpx;
+  margin-top: -3rpx;
+  cursor: n-resize;
+}
+
+.point-lt {
+  left: 0%;
+  top: 0%;
+  margin-left: -3rpx;
+  margin-top: -3rpx;
+  cursor: n-resize;
+}
+/* 裁剪框预览内容 */
+
+.uni-cropper-viewer {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+
+.uni-cropper-viewer image {
+  position: absolute;
+  z-index: 2;
+}
+</style>

+ 114 - 0
src/pages/mine/help/index.vue

@@ -0,0 +1,114 @@
+<template>
+  <view class="help-container">
+    <view v-for="(item, findex) in list" :key="findex" :title="item.title" class="list-title">
+      <view class="text-title"> <view :class="item.icon"></view>{{ item.title }} </view>
+      <view class="childList">
+        <view v-for="(child, zindex) in item.childList" :key="zindex" class="question" hover-class="hover" @click="handleText(child)">
+          <view class="text-item">{{ child.title }}</view>
+          <view class="line" v-if="zindex !== item.childList.length - 1"></view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      list: [
+        // {
+        //   icon: 'iconfont icon-github',
+        //   title: '若依问题',
+        //   childList: [{
+        //     title: '若依开源吗?',
+        //     content: '开源'
+        //   }, {
+        //     title: '若依可以商用吗?',
+        //     content: '可以'
+        //   }, {
+        //     title: '若依官网地址多少?',
+        //     content: 'http://ruoyi.vip'
+        //   }, {
+        //     title: '若依文档地址多少?',
+        //     content: 'http://doc.ruoyi.vip'
+        //   }]
+        // },
+        {
+          icon: "iconfont icon-help",
+          title: "其他问题",
+          childList: [
+            {
+              title: "如何退出登录?",
+              content: "请点击[我的] - [应用设置] - [退出登录]即可退出登录",
+            },
+            {
+              title: "如何修改用户头像?",
+              content: "请点击[我的] - [选择头像] - [点击提交]即可更换用户头像",
+            },
+            {
+              title: "如何修改登录密码?",
+              content: "请点击[我的] - [应用设置] - [修改密码]即可修改登录密码",
+            },
+          ],
+        },
+      ],
+    };
+  },
+  methods: {
+    handleText(item) {
+      this.$tab.navigateTo(`/pages/common/textview/index?title=${item.title}&content=${item.content}`);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+page {
+  background-color: #f8f8f8;
+}
+
+.help-container {
+  margin-bottom: 100rpx;
+  padding: 30rpx;
+}
+
+.list-title {
+  margin-bottom: 30rpx;
+}
+
+.childList {
+  background: #ffffff;
+  box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2);
+  border-radius: 16rpx;
+  margin-top: 10rpx;
+}
+
+.line {
+  width: 100%;
+  height: 1rpx;
+  background-color: #f5f5f5;
+}
+
+.text-title {
+  color: #303133;
+  font-size: 32rpx;
+  font-weight: bold;
+  margin-left: 10rpx;
+
+  .iconfont {
+    font-size: 16px;
+    margin-right: 10rpx;
+  }
+}
+
+.text-item {
+  font-size: 28rpx;
+  padding: 24rpx;
+}
+
+.question {
+  color: #606266;
+  font-size: 28rpx;
+}
+</style>

+ 194 - 0
src/pages/mine/index.vue

@@ -0,0 +1,194 @@
+<template>
+  <view class="mine-container" :style="{ height: `${windowHeight}px` }">
+    <!--顶部个人信息栏-->
+    <view class="header-section">
+      <view class="flex padding justify-between">
+        <view class="flex align-center">
+          <view v-if="!avatar" class="cu-avatar xl round bg-white">
+            <view class="iconfont icon-people text-gray icon"></view>
+          </view>
+          <image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="widthFix"> </image>
+          <view v-if="!data.name" @click="handleToLogin" class="login-tip"> 点击登录 </view>
+          <view v-if="data.name" @click="handleToInfo" class="user-info">
+            <view class="u_title"> 用户名:{{ data.name }} </view>
+          </view>
+        </view>
+        <view @click="handleToInfo" class="flex align-center">
+          <text>个人信息</text>
+          <view class="iconfont icon-right"></view>
+        </view>
+      </view>
+    </view>
+
+    <view class="content-section">
+      <view class="mine-actions grid col-4 text-center">
+        <view class="action-item" @click="handleJiaoLiuQun">
+          <view class="iconfont icon-friendfill text-pink icon"></view>
+          <text class="text">客服QQ</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-service text-blue icon"></view>
+          <text class="text">在线客服</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-community text-mauve icon"></view>
+          <text class="text">反馈社区</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-dianzan text-green icon"></view>
+          <text class="text">点赞我们</text>
+        </view>
+      </view>
+
+      <view class="menu-list">
+        <view class="list-cell list-cell-arrow" @click="handleToEditInfo">
+          <view class="menu-item-box">
+            <view class="iconfont icon-user menu-icon"></view>
+            <view>编辑资料</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleHelp">
+          <view class="menu-item-box">
+            <view class="iconfont icon-help menu-icon"></view>
+            <view>常见问题</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleAbout">
+          <view class="menu-item-box">
+            <view class="iconfont icon-aixin menu-icon"></view>
+            <view>关于我们</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleToSetting">
+          <view class="menu-item-box">
+            <view class="iconfont icon-setting menu-icon"></view>
+            <view>应用设置</view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import config from "@/config";
+import storage from "@/utils/storage";
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+  name: useStore.$state.name,
+  version: getApp().globalData.config.appInfo.version,
+});
+
+const avatar = computed(() => {
+  return useStore.$state.avatar;
+});
+const windowHeight = computed(() => {
+  return uni.getSystemInfoSync().windowHeight - 50;
+});
+
+function handleToInfo() {
+  proxy.$tab.navigateTo("/pages/mine/info/index");
+}
+function handleToEditInfo() {
+  proxy.$tab.navigateTo("/pages/mine/info/edit");
+}
+function handleToSetting() {
+  proxy.$tab.navigateTo("/pages/mine/setting/index");
+}
+function handleToLogin() {
+  proxy.$tab.reLaunch("/pages/login");
+}
+function handleToAvatar() {
+  proxy.$tab.navigateTo("/pages/mine/avatar/index");
+}
+function handleLogout() {
+  proxy.$modal.confirm("确定注销并退出系统吗?").then(() => {
+    useStore.LogOut().then(() => {
+      proxy.$tab.reLaunch("/pages/index");
+    });
+  });
+}
+function handleHelp() {
+  proxy.$tab.navigateTo("/pages/mine/help/index");
+}
+function handleAbout() {
+  proxy.$tab.navigateTo("/pages/mine/about/index");
+}
+function handleJiaoLiuQun() {
+  // proxy.$modal.showToast("QQ:1813914505");
+  proxy.$modal.showToast("模块建设中~");
+}
+function handleBuilding() {
+  proxy.$modal.showToast("模块建设中~");
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #f5f6f7;
+}
+
+.mine-container {
+  width: 100%;
+  height: 100%;
+
+  .header-section {
+    padding: 15px 15px 45px 15px;
+    background-color: #3c96f3;
+    color: white;
+
+    .login-tip {
+      font-size: 18px;
+      margin-left: 10px;
+    }
+
+    .cu-avatar {
+      border: 2px solid #eaeaea;
+
+      .icon {
+        font-size: 40px;
+      }
+    }
+
+    .user-info {
+      margin-left: 15px;
+
+      .u_title {
+        font-size: 18px;
+        line-height: 30px;
+      }
+    }
+  }
+
+  .content-section {
+    position: relative;
+    top: -50px;
+
+    .mine-actions {
+      margin: 15px 15px;
+      padding: 20px 0px;
+      border-radius: 8px;
+      background-color: white;
+
+      .action-item {
+        .icon {
+          font-size: 28px;
+        }
+
+        .text {
+          display: block;
+          font-size: 13px;
+          margin: 8px 0px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 138 - 0
src/pages/mine/info/edit.vue

@@ -0,0 +1,138 @@
+<template>
+  <view class="container">
+    <view class="example">
+      <uni-forms ref="form" :model="user" labelWidth="80px">
+        <uni-forms-item label="用户昵称" name="nickName">
+          <uni-easyinput v-model="user.nickName" placeholder="请输入昵称" />
+        </uni-forms-item>
+        <uni-forms-item label="手机号码" name="phonenumber">
+          <uni-easyinput v-model="user.phonenumber" placeholder="请输入手机号码" />
+        </uni-forms-item>
+        <uni-forms-item label="邮箱" name="email">
+          <uni-easyinput v-model="user.email" placeholder="请输入邮箱" />
+        </uni-forms-item>
+        <uni-forms-item label="性别" name="sex" required>
+          <uni-data-checkbox v-model="user.sex" :localdata="sexs" />
+        </uni-forms-item>
+      </uni-forms>
+      <button type="primary" @click="submit">提交</button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { getUserProfile } from "@/api/system/user";
+import { updateUserProfile } from "@/api/system/user";
+
+export default {
+  data() {
+    return {
+      user: {
+        nickName: "",
+        phonenumber: "",
+        email: "",
+        sex: "",
+      },
+      sexs: [
+        {
+          text: "男",
+          value: "0",
+        },
+        {
+          text: "女",
+          value: "1",
+        },
+      ],
+      rules: {
+        nickName: {
+          rules: [
+            {
+              required: true,
+              errorMessage: "用户昵称不能为空",
+            },
+          ],
+        },
+        phonenumber: {
+          rules: [
+            {
+              required: true,
+              errorMessage: "手机号码不能为空",
+            },
+            {
+              pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+              errorMessage: "请输入正确的手机号码",
+            },
+          ],
+        },
+        email: {
+          rules: [
+            {
+              required: true,
+              errorMessage: "邮箱地址不能为空",
+            },
+            {
+              format: "email",
+              errorMessage: "请输入正确的邮箱地址",
+            },
+          ],
+        },
+      },
+    };
+  },
+  onLoad() {
+    this.getUser();
+  },
+  onReady() {
+    this.$refs.form.setRules(this.rules);
+  },
+  methods: {
+    getUser() {
+      getUserProfile().then((response) => {
+        this.user = response.data;
+      });
+    },
+    submit(ref) {
+      this.$refs.form.validate().then((res) => {
+        updateUserProfile(this.user).then((response) => {
+          this.$modal.msgSuccess("修改成功");
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+page {
+  background-color: #ffffff;
+}
+
+.example {
+  padding: 15px;
+  background-color: #fff;
+}
+
+.segmented-control {
+  margin-bottom: 15px;
+}
+
+.button-group {
+  margin-top: 15px;
+  display: flex;
+  justify-content: space-around;
+}
+
+.form-item {
+  display: flex;
+  align-items: center;
+  flex: 1;
+}
+
+.button {
+  display: flex;
+  align-items: center;
+  height: 35px;
+  line-height: 35px;
+  margin-left: 10px;
+}
+</style>

+ 50 - 0
src/pages/mine/info/index.vue

@@ -0,0 +1,50 @@
+<template>
+  <view class="container">
+    <uni-list>
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'person-filled' }" title="昵称" :rightText="user.nickName" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'phone-filled' }" title="手机号码" :rightText="user.phonenumber" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'email-filled' }" title="邮箱" :rightText="user.email" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'auth-filled' }" title="岗位" :rightText="postGroup" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'staff-filled' }" title="角色" :rightText="roleGroup" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{ type: 'calendar-filled' }" title="创建日期" :rightText="user.createTime" />
+    </uni-list>
+  </view>
+</template>
+
+<script setup>
+import { getUserProfile } from "@/api/system/user";
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+  name: useStore.$state.name,
+  version: getApp().globalData.config.appInfo.version,
+});
+
+const user = ref({});
+const roleGroup = ref("");
+const postGroup = ref("");
+
+function getUser() {
+  getUserProfile().then((response) => {
+    user.value = response.data;
+    roleGroup.value = response.roleGroup;
+    postGroup.value = response.postGroup;
+  });
+}
+
+onLoad(() => {
+  getUser();
+});
+</script>
+
+<style lang="scss">
+page {
+  background-color: #ffffff;
+}
+</style>

+ 85 - 0
src/pages/mine/pwd/index.vue

@@ -0,0 +1,85 @@
+<template>
+  <view class="pwd-retrieve-container">
+    <uni-forms ref="form" :value="user" labelWidth="80px">
+      <uni-forms-item name="oldPassword" label="旧密码">
+        <uni-easyinput type="password" v-model="user.oldPassword" placeholder="请输入旧密码" />
+      </uni-forms-item>
+      <uni-forms-item name="newPassword" label="新密码">
+        <uni-easyinput type="password" v-model="user.newPassword" placeholder="请输入新密码" />
+      </uni-forms-item>
+      <uni-forms-item name="confirmPassword" label="确认密码">
+        <uni-easyinput type="password" v-model="user.confirmPassword" placeholder="请确认新密码" />
+      </uni-forms-item>
+      <button type="primary" @click="submit">提交</button>
+    </uni-forms>
+  </view>
+</template>
+
+<script>
+  import { updateUserPwd } from "@/api/system/user"
+
+  export default {
+    data() {
+      return {
+        user: {
+          oldPassword: undefined,
+          newPassword: undefined,
+          confirmPassword: undefined
+        },
+        rules: {
+          oldPassword: {
+            rules: [{
+              required: true,
+              errorMessage: '旧密码不能为空'
+            }]
+          },
+          newPassword: {
+            rules: [{
+                required: true,
+                errorMessage: '新密码不能为空',
+              },
+              {
+                minLength: 6,
+                maxLength: 20,
+                errorMessage: '长度在 6 到 20 个字符'
+              }
+            ]
+          },
+          confirmPassword: {
+            rules: [{
+                required: true,
+                errorMessage: '确认密码不能为空'
+              }, {
+                validateFunction: (rule, value, data) => data.newPassword === value,
+                errorMessage: '两次输入的密码不一致'
+              }
+            ]
+          }
+        }
+      }
+    },
+    onReady() {
+      this.$refs.form.setRules(this.rules)
+    },
+    methods: {
+      submit() {
+        this.$refs.form.validate().then(res => {
+          updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
+            this.$modal.msgSuccess("修改成功")
+          })
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #ffffff;
+  }
+
+  .pwd-retrieve-container {
+    padding-top: 36rpx;
+    padding: 15px;
+  }
+</style>

+ 82 - 0
src/pages/mine/setting/index.vue

@@ -0,0 +1,82 @@
+<template>
+  <view class="setting-container" :style="{ height: `${windowHeight}px` }">
+    <view class="menu-list">
+      <view class="list-cell list-cell-arrow" @click="handleToPwd">
+        <view class="menu-item-box">
+          <view class="iconfont icon-password menu-icon"></view>
+          <view>修改密码</view>
+        </view>
+      </view>
+      <view class="list-cell list-cell-arrow" @click="handleToUpgrade">
+        <view class="menu-item-box">
+          <view class="iconfont icon-refresh menu-icon"></view>
+          <view>检查更新</view>
+        </view>
+      </view>
+      <view class="list-cell list-cell-arrow" @click="handleCleanTmp">
+        <view class="menu-item-box">
+          <view class="iconfont icon-clean menu-icon"></view>
+          <view>清理缓存</view>
+        </view>
+      </view>
+    </view>
+    <view class="cu-list menu">
+      <view class="cu-item item-box">
+        <view class="content text-center" @click="handleLogout">
+          <text class="text-black">退出登录</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+
+import useStores from "@/store/modules/user.js";
+const useStore = useStores();
+
+const { proxy } = getCurrentInstance();
+
+const data = reactive({});
+
+const windowHeight = computed(() => {
+  return uni.getSystemInfoSync().windowHeight - 50;
+});
+
+function handleToPwd() {
+  proxy.$tab.navigateTo("/pages/mine/pwd/index");
+}
+function handleToUpgrade() {
+  proxy.$modal.showToast("模块建设中~");
+}
+function handleCleanTmp() {
+  proxy.$modal.showToast("模块建设中~");
+}
+function handleLogout() {
+  proxy.$modal.confirm("确定注销并退出系统吗?").then(() => {
+    useStore.LogOut().then(() => {
+      proxy.$tab.reLaunch("/pages/login");
+    });
+  });
+}
+</script>
+
+<style lang="scss" scoped>
+.page {
+  background-color: #f8f8f8;
+}
+
+.item-box {
+  background-color: #ffffff;
+  margin: 30rpx;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 10rpx;
+  border-radius: 8rpx;
+  color: #303133;
+  font-size: 32rpx;
+}
+</style>

+ 157 - 0
src/pages/setting/building/building.vue

@@ -0,0 +1,157 @@
+<template>
+  <view>
+    <view class="basic-info">
+      <view class="info-tit margin-left-xs">
+        <text class="cuIcon-titles margin-right-xs"></text>
+        基本信息
+      </view>
+      <view class="info-content padding-lr">
+        <table
+          style="border: 1px solid #ccc"
+          cellspacing="0"
+          cellpadding="0"
+          align="center"
+        >
+          <tr>
+            <td>建筑物名称</td>
+            <td>{{ this.getDetailData.build_name }}</td>
+          </tr>
+          <tr>
+            <td>建筑物类别</td>
+            <td>{{ this.getDetailData.build_type }}</td>
+          </tr>
+          <tr>
+            <td>建造日期</td>
+            <td>{{ this.getDetailData.build_time }}</td>
+          </tr>
+          <tr>
+            <td>使用性质</td>
+            <td>{{ this.getDetailData.nature_use }}</td>
+          </tr>
+          <tr>
+            <td>火灾危险级</td>
+            <td>{{ this.getDetailData.fire_risk_level }}</td>
+          </tr>
+          <tr>
+            <td>耐火等级</td>
+            <td>{{ this.getDetailData.fire_resistance_rating }}</td>
+          </tr>
+          <tr>
+            <td>结构类型</td>
+            <td>{{ this.getDetailData.structure_type }}</td>
+          </tr>
+          <tr>
+            <td>建筑高度</td>
+            <td>{{ this.getDetailData.build_height }}</td>
+          </tr>
+          <tr>
+            <td>建筑面积</td>
+            <td>{{ this.getDetailData.build_area }}</td>
+          </tr>
+          <tr>
+            <td>占地面积</td>
+            <td>{{ this.getDetailData.land_occupation_area }}</td>
+          </tr>
+
+          <tr>
+            <td>标准层面积</td>
+            <td>{{ this.getDetailData.standard_area }}</td>
+          </tr>
+          <tr>
+            <td>地上层数</td>
+            <td>{{ this.getDetailData.aboveground_layer }}</td>
+          </tr>
+          <tr>
+            <td>地上层面积</td>
+            <td>{{ this.getDetailData.aboveground_area }}</td>
+          </tr>
+
+          <tr>
+            <td>地下层数</td>
+            <td>{{ this.getDetailData.underground_floor }}</td>
+          </tr>
+          <tr>
+            <td>地下层面积</td>
+            <td>{{ this.getDetailData.underground_area }}</td>
+          </tr>
+          <tr>
+            <td>消防控制室位置</td>
+            <td>{{ this.getDetailData.control_room }}</td>
+          </tr>
+          <tr>
+            <td>避难层数量</td>
+            <td>{{ this.getDetailData.refuge_layer }}</td>
+          </tr>
+          <tr>
+            <td>消防电梯数量</td>
+            <td>{{ this.getDetailData.fire_elevator }}</td>
+          </tr>
+        </table>
+      </view>
+    </view>
+
+    <view class="processStatus">
+      <view class="info-tit margin-left-xs">
+        <text class="cuIcon-titles margin-right-xs"></text>
+        消防设施平面布置图
+      </view>
+      <view class="padding-lr imgPic">
+        <image
+          v-if="!this.getDetailData.build_plan && this.dataRes == 1"
+          mode="widthFix"
+          src="@/static/images/defaultImg.jpg"
+        />
+        <image v-else mode="widthFix" :src="this.getDetailData.layout_plan" />
+      </view>
+    </view>
+
+    <view class="processStatus">
+      <view class="info-tit margin-left-xs">
+        <text class="cuIcon-titles margin-right-xs"></text>
+        建筑平面图
+      </view>
+      <view class="padding-lr padding-bottom-lg imgPic">
+        <image
+          v-if="!this.getDetailData.build_plan && this.dataRes == 1"
+          mode="widthFix"
+          src="@/static/images/defaultImg.jpg"
+        />
+        <image v-else :src="this.getDetailData.build_plan" mode="widthFix" />
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      getDetailData: {},
+      dataRes: 0,
+    };
+  },
+  onLoad: function (option) {
+    this.getDetails({ company_code: uni.getStorageSync("selectedCode") });
+  },
+  methods: {
+    // 建筑基础数据请求
+    async getDetails(params = {}) {
+      const res = await this.$myRequest({
+        url: "BuildingInformation/getBuildingManagement",
+        data: params,
+        showLoading: true,
+      });
+      this.getDetailData = res.data.data[0];
+      console.log(this.getDetailData);
+      this.dataRes = 1;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep .image-bg > div {
+  background-size: cover !important;
+}
+</style>
+

+ 271 - 0
src/pages/setting/funReport/funReport.vue

@@ -0,0 +1,271 @@
+<template>
+
+	<view class="">
+		
+		<!-- 筛选框start -->
+		<view style="height:98rpx"></view>
+		<view class="ding">
+			<!-- <calendar></calendar> -->
+			<view class="example-body">
+				<uni-datetime-picker v-model="datetimerange" type="daterange" start-placeholder="请选择开始时间"
+					end-placeholder="请选择结束时间" start="2000-3-20 12:00:00" end="2025-10-20 20:00:00" rangeSeparator="至" />
+			</view>
+		</view>
+		<!-- 筛选框end -->
+		<view  class="site-items" style="margin-top:0;height: calc(100vh - 286rpx)">
+			<view class="cu-list menu-avatar" >
+				<view class="cu-item" :class="modalName=='move-box-'+ index?'move-cur':''"
+					v-for="(item,index) in funcReport" :key="index" 
+					@touchstart="ListTouchStart"
+					@touchmove="ListTouchMove" @touchend="ListTouchEnd" :data-target="'move-box-' + index"
+					>
+					<view class="cu-avatar round lg">
+						<image class="image-bg" src="@/static/images/setting/funcList.png"/>
+					</view>
+					<view class="content">
+						<view class="pro-title">
+							<view class="cut">{{item.report_name}}</view>
+						</view>
+						<view class="pro-des  ">
+							<view class="text-cut">
+								{{item.remarks  }}
+							</view>
+						</view>
+						<view class="pro-date ">{{item.add_time}}</view>
+					</view>
+					<view class="nav-right num">
+						<view class="text-grey">
+							<text class="icon iconfont margin-right-sm margin-left-lg">&#xe629;</text>
+						</view>
+					</view>
+					<view class="move">
+						<view class="bg-grey" @click.stop="editItem(item)">编辑</view>
+						<view class="bg-red" @click.stop="deleteItem(item)">删除</view>
+					</view>
+				</view>
+			</view>
+			<view v-if="!funcReport.length&&authListRes==1" class="text-center margin-top"> 暂无数据</view>
+			<view v-show="isLoadMore&&this.pages>1" style="padding-bottom:60px">
+				<uni-load-more :status="loadStatus"></uni-load-more>
+			</view>
+			
+			<view  style="padding-bottom:60px"></view>
+			
+			
+		</view>
+		
+		
+		
+		<!-- 新增按钮start -->
+			<view style="width: 100%;
+		position: fixed;
+		bottom: 0px;
+		right: 0px;
+		height: 64px;
+		background: #fff;">
+				<view class="plus">
+					<image src="@/static/images/setting/plus.png" style="width:100rpx;height:100rpx" @tap="goAddPage()"></image>
+				</view>
+			</view>
+			
+			<!-- 新增按钮end -->
+	</view>
+</template>
+
+<script>
+	import json from '../../../data/json.js';
+	export default {
+		data() {
+			return {
+				funcReport: [],
+				modalName: null,
+				getData:[],
+				dwtype:0,
+				datetimerange: ['', ''],
+				
+				listTouchStart: 0,
+				listTouchDirection: null,
+				
+				
+				flag:false,
+				
+				authListRes:0,
+				
+				
+				pages: 1,
+				size: 12,
+				loadStatus: 'loading', //加载样式:more-加载前样式,loading-加载中样式,nomore-没有数据样式
+				isLoadMore: false, //是否加载中
+				deleteStatus:false,
+			};
+		},
+		
+		onReachBottom() { //上拉触底函数
+			if (!this.isLoadMore) { //此处判断,上锁,防止重复请求
+				this.isLoadMore = true
+				this.pages += 1;
+				this.loadData()
+			}
+		},
+
+		onLoad: function(option) {
+			this.dwtype=option.dwtype
+			this.loadData()
+
+		},
+		onNavigationBarButtonTap(e) {
+			console.log(e)
+			uni.navigateTo({
+				url: './export/export?dwtype='+this.dwtype,
+
+			});
+		},
+		watch: {
+			
+			
+			datetimerange:function(){
+				this.funcReport=[];
+				this.pages = 1;
+				this.authListRes=[]
+				this.loadData()
+			},
+			
+			
+		},
+		methods: {
+			
+			loadData(){
+			
+				this.getDeviceList({
+					'company_code':uni.getStorageSync('selectedCode'),
+					'start_time':this.datetimerange[0],
+					'end_time':this.datetimerange[1],
+					'pages': this.pages,
+					'size': this.size
+				})
+				
+			},
+
+		
+			
+			// 设备类型数据请求
+			async getDeviceList(params = {}) {
+				const res = await this.$myRequest({
+					url: 'AlarmReport/index',
+					data:params,
+					showLoading: true
+				})
+				
+				if(this.deleteStatus){
+					this.funcReport=[];
+					this.deleteStatus=false;
+				}
+				this.authListRes = 1;
+				
+			
+				if (res.data.totalcount) {
+					this.funcReport = this.funcReport.concat(res.data.data)
+					if (res.data.data.length < this.size) { //判断接口返回数据量小于请求数据量,则表示此为最后一页
+			
+						this.isLoadMore = true
+						this.loadStatus = 'nomore'
+					} else {
+						this.isLoadMore = false
+					}
+				} else {
+					this.isLoadMore = true
+					this.loadStatus = 'nomore'
+				}
+				
+	
+			},
+			
+			//编辑
+			editItem(item) {
+				uni.redirectTo({
+					url: '/pages/setting/funReport/funcAdd/funcAdd?id=' + item.id + '',
+				});
+			},
+			
+			//删除
+			deleteItem(item) {
+				 let deleteT=0;
+				 this.deleteStatus=true
+				 uni.showModal({	
+				     title: '确认删除吗?',
+				     content: '',
+				     success: function (result) {
+				         if (result.confirm) {
+							  this.deleteAlarm({
+							 	"id": item.id
+							 });
+				         } else if (result.cancel) {
+				             console.log('用户点击取消');
+				         }
+				     }.bind(this)
+				 }); 
+			},
+			
+			
+			// 删除请求接口
+			async deleteAlarm(ming = {}) {
+				let res = await  this.$myRequest({
+					url: 'AlarmReport/del ',
+					data: ming
+				})
+				if (!res.data.flag) {
+					alert('删除失败');
+					return;
+				}
+				this.getDeviceList({'company_code':uni.getStorageSync('selectedCode')})
+				
+				return res;
+			},
+			
+			// 新增
+			goAddPage(type) {
+				uni.redirectTo({
+					url: '/pages/setting/funReport/funcAdd/funcAdd',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			},
+			
+			
+			
+			// ListTouch触摸开始
+			ListTouchStart(e) {
+				this.listTouchStart = e.touches[0].pageX
+			},
+			
+			// ListTouch计算方向
+			ListTouchMove(e) {
+				this.listTouchDirection = e.touches[0].pageX - this.listTouchStart < -80 ? 'left' : 'right'
+			},
+			
+			// ListTouch计算滚动
+			ListTouchEnd(e) {
+				if (this.listTouchDirection == 'left') {
+					this.modalName = e.currentTarget.dataset.target
+				} else {
+					this.modalName = null
+				}
+				this.listTouchDirection = null
+			}
+			
+		}
+
+	}
+</script>
+
+<style lang="scss">
+	.cu-item {
+		height: 180rpx !important
+	}
+	.plus {
+	    position: fixed;
+	    bottom: 3px;
+	    right: 3px;
+	}
+</style>

+ 405 - 0
src/pages/setting/funReport/funcAdd/funcAdd.vue

@@ -0,0 +1,405 @@
+<template>
+  <view
+    class="appWrapper padding-top"
+    style="height: calc(100vh - 250rpx); overflow: scroll"
+  >
+    <form action="" class="funcAdd">
+      <view class="form-item selectBox">
+        <view class="title"><text class="necessary">*</text>报备类型:</view>
+        <el-select v-model="report_type" name="" id="" placeholder="" clearable>
+          <el-option value="">请选择</el-option>
+          <el-option value="1">单位</el-option>
+          <el-option value="2">类型</el-option>
+          <el-option value="3">设备</el-option>
+        </el-select>
+        <text class="icon iconfont margin-right-sm margin-left">&#xe63d;</text>
+      </view>
+      <view
+        class="form-item selectBox"
+        v-if="report_type == 2 || report_type == 3"
+      >
+        <view class="title"><text class="necessary">*</text>设备类型:</view>
+        <el-select v-model="device_type" name="" id="" placeholder="" clearable>
+          <el-option value="">请选择</el-option>
+          <el-option value="1">火系统</el-option>
+          <el-option value="2">水系统</el-option>
+          <el-option value="3">烟感系统</el-option>
+          <el-option value="4">消防栓</el-option>
+          <el-option value="5">液位</el-option>
+          <el-option value="6">RTU</el-option>
+          <el-option value="7">电气火灾</el-option>
+          <el-option value="16">视频监控</el-option>
+          <el-option value="128">井盖</el-option>
+          <el-option value="131">可燃气体</el-option>
+          <el-option value="130">门禁监测</el-option>
+          <el-option value="129">地磁监测</el-option>
+          <el-option value="17">电梯监测</el-option>
+        </el-select>
+        <text class="icon iconfont margin-right-sm margin-left">&#xe63d;</text>
+      </view>
+
+      <view class="form-item" v-if="report_type">
+        <view class="title">
+          <text class="necessary">*</text>
+          开始时间:
+        </view>
+        <view class="example-body">
+          <uni-datetime-picker
+            v-model="start_time"
+            :start="this.id ? '' : now"
+          />
+        </view>
+      </view>
+      <view class="form-item" v-if="report_type">
+        <view class="title">
+          <text class="necessary">*</text>
+          结束时间:
+        </view>
+        <view class="example-body">
+          <uni-datetime-picker v-model="end_time" :start="start_time" />
+        </view>
+      </view>
+
+      <view class="form-item" v-if="report_type == 3 && device_type == 6">
+        <view class="title"><text class="necessary">*</text>端口号:</view>
+        <input name="input" v-model="device_port" />
+      </view>
+
+      <view
+        class="form-item selectBox"
+        v-if="report_type == 3 && device_type == 6"
+      >
+        <view class="title"><text class="necessary">*</text>端口类型:</view>
+        <el-select v-model="port_type" name="" id="" placeholder="" clearable>
+          <el-option value="">请选择</el-option>
+          <el-option value="1">数字量</el-option>
+          <el-option value="2">模拟量</el-option>
+        </el-select>
+        <text class="icon iconfont margin-right-sm margin-left">&#xe63d;</text>
+      </view>
+
+      <view class="form-item selectBox" v-if="report_type == 3 && device_type">
+        <view class="title"><text class="necessary">*</text>报备设备:</view>
+        <el-select v-model="device_code" name="" id="" placeholder="" clearable>
+          <el-option value="">请选择</el-option>
+          <el-option
+            :value="item.owner_code"
+            v-for="(item, index) in deviceListData"
+            :key="index"
+          >
+            {{ item.owner_name }}
+          </el-option>
+        </el-select>
+        <text class="icon iconfont margin-right-sm margin-left">&#xe63d;</text>
+      </view>
+
+      <view class="form-item" v-if="report_type">
+        <view class="title"><text class="necessary"></text>备注:</view>
+        <input name="input" v-model="remarks" />
+      </view>
+
+      <view class="btn-area submitBottomBtn padding-lr-sm">
+        <button class="bg-blue round margin-top" @tap="submit()">提 交</button>
+      </view>
+    </form>
+  </view>
+</template>
+<style scoped>
+::v-deep .funcAdd .uni-date-x--border,
+.uni-date-x {
+  border-radius: 0 !important;
+}
+.funcAdd .example-body {
+  margin: 0;
+  width: calc(100% - 200rpx);
+}
+</style>
+
+<script>
+export default {
+  data() {
+    return {
+      id: "",
+
+      report_type: "",
+      device_type: "",
+      start_time: "",
+      end_time: "",
+      remarks: "",
+      device_port: "",
+      port_type: "",
+      device_code: "",
+      now: "",
+
+      deviceListData: [],
+      detailsData: "",
+    };
+  },
+  onLoad: function (option) {
+    this.id = option.id;
+    uni.setNavigationBarTitle({
+      title: option.id ? "编辑" : "新增",
+    });
+
+    var nowTemp = new Date();
+    this.now = new Date(
+      nowTemp.getFullYear(),
+      nowTemp.getMonth(),
+      nowTemp.getDate(),
+      0,
+      0,
+      0,
+      0
+    );
+
+    if (option.id) {
+      this.getDetailsData({ id: option.id });
+    }
+  },
+  watch: {
+    start_time: function () {
+      // alert(this.start_time)
+    },
+    report_type: function (newVal) {
+      if (newVal) {
+        var array123 = [
+          "",
+          "1",
+          "2",
+          "3",
+          "4",
+          "5",
+          "6",
+          "7",
+          "16",
+          "128",
+          "131",
+          "130",
+          "129",
+          "17",
+        ];
+        if (array123.indexOf(this.device_type) == -1) {
+          this.device_type = "";
+        }
+      }
+    },
+    device_type: function (newVal) {
+      if (newVal) {
+        this.deviceList({
+          company_code: uni.getStorageSync("selectedCode"),
+          device_type: this.device_type,
+        });
+      }
+    },
+  },
+  methods: {
+    // 回显信息请求
+    async getDetailsData(params = {}) {
+      const res = await this.$myRequest({
+        url: "AlarmReport/editData",
+        data: params,
+        showLoading: true,
+      });
+
+      this.detailsData = res.data.data[0];
+      console.log(this.detailsData);
+      this.report_type = this.detailsData.report_type;
+      this.device_type = this.detailsData.device_type;
+      this.start_time = this.detailsData.start_time;
+      this.end_time = this.detailsData.end_time;
+      this.remarks = this.detailsData.remarks;
+      this.port_type = this.detailsData.port_type;
+      this.device_port = this.detailsData.device_port;
+      this.device_code = this.detailsData.device_code;
+    },
+
+    async submit() {
+      //提交验证
+
+      if (!this.report_type) {
+        uni.showToast({
+          title: "请输入报备类型",
+          icon: "none",
+        });
+        return;
+      }
+      if (this.report_type == 1) {
+        if (!this.start_time.replace(/^\s*/g, "")) {
+          uni.showToast({
+            title: "请选择开始时间",
+            icon: "none",
+          });
+          return;
+        }
+        if (!this.end_time.replace(/^\s*/g, "")) {
+          uni.showToast({
+            title: "请选择结束时间",
+            icon: "none",
+          });
+          return;
+        }
+      }
+      if (this.report_type == 2 || this.report_type == 3) {
+        if (!this.device_type) {
+          uni.showToast({
+            title: "请选择设备类型",
+            icon: "none",
+          });
+          return;
+        }
+        if (!this.start_time.replace(/^\s*/g, "")) {
+          uni.showToast({
+            title: "请输入开始时间",
+            icon: "none",
+          });
+          return;
+        }
+        if (!this.end_time.replace(/^\s*/g, "")) {
+          uni.showToast({
+            title: "请输入结束时间",
+            icon: "none",
+          });
+          return;
+        }
+      }
+
+      if (this.report_type == 3 && this.device_type) {
+        if (this.device_type == 6) {
+          if (!this.device_port.replace(/^\s*/g, "")) {
+            uni.showToast({
+              title: "请输入端口号",
+              icon: "none",
+            });
+            return;
+          }
+          if (!this.port_type) {
+            uni.showToast({
+              title: "请选择端口类型",
+              icon: "none",
+            });
+            return;
+          }
+          if (!this.device_code) {
+            uni.showToast({
+              title: "请选择报备设备",
+              icon: "none",
+            });
+            return;
+          }
+        }
+        if (!this.device_code) {
+          uni.showToast({
+            title: "请选择报备设备",
+            icon: "none",
+          });
+          return;
+        }
+      }
+
+      let queryParam = {};
+      if (this.id) {
+        queryParam.id = this.id;
+      }
+      queryParam.report_type = this.report_type;
+      queryParam.company_code = uni.getStorageSync("selectedCode");
+      queryParam.remarks = this.remarks;
+      queryParam.start_time = this.start_time;
+      queryParam.end_time = this.end_time;
+
+      if (this.id) {
+        queryParam.id = this.id;
+      }
+
+      if (this.report_type == 1) {
+        this.addDevice(queryParam);
+        return;
+      }
+      if (this.report_type == 2) {
+        queryParam.device_type = this.device_type;
+        this.addDevice(queryParam);
+        return;
+      }
+      if (this.report_type == 3) {
+        queryParam.device_type = this.device_type;
+        if (this.device_type == 6) {
+          queryParam.port_type = this.port_type;
+          queryParam.device_port = this.device_port;
+        }
+        queryParam.device_code = this.device_code;
+        this.addDevice(queryParam);
+        return;
+      }
+
+      this.addDevice(queryParam);
+    },
+
+    async addDevice(params = {}) {
+      const res = await this.$myRequest({
+        url: this.id ? "AlarmReport/edit" : "AlarmReport/add",
+        data: params,
+      });
+
+      if (!res.data.flag) {
+        uni.showToast({
+          title: "提交失败",
+          icon: "none",
+        });
+      } else {
+        uni.showToast({
+          title: "提交成功",
+        });
+      }
+      setTimeout(() => {
+        uni.redirectTo({
+          url: "/pages/setting/funReport/funReport",
+        });
+      }, 1000);
+    },
+
+    radioChange(e) {
+      console.log("type:" + e.detail.value);
+      this.radioOne = e.detail.value;
+    },
+
+    //报备设备下拉请求数据
+    async deviceList(params = {}) {
+      const res = await this.$myRequest({
+        url: "AlarmReport/deviceList",
+        data: params,
+      });
+      this.deviceListData = res.data.data;
+
+      var arr = [];
+      this.deviceListData.forEach(function (item) {
+        arr.push(item.owner_code);
+      });
+      if (arr.indexOf(this.device_code) == -1) {
+        this.device_code = "";
+      }
+    },
+  },
+};
+</script>
+
+
+
+
+<style lang="scss">
+input,
+select,
+option {
+  line-height: 70rpx;
+  padding: 0 20rpx;
+  height: 70rpx;
+  border: 1px solid #ededed;
+  // width:500rpx!important;
+  background-color: #fff;
+  box-sizing: border-box;
+  appearance: none;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+  color: #999;
+}
+
+/* 站点多选下拉样式end */
+</style>

+ 235 - 0
src/pages/setting/messagePush/messagePush.vue

@@ -0,0 +1,235 @@
+<template>
+	<view class="padding-sm messagePush">
+
+		<form action="">
+
+			<checkbox-group class="block" @change="CheckboxChange">
+				<view class="margin-top  ">
+					<view class="flex align-center checkItems" v-for="(item,index) in checkbox">
+						<checkbox class="blue" :class="item.checked==1?'checked':''"
+							:checked="item.checked==1?true:false" :value="item.value"></checkbox>
+						<view class="title">{{item.title}}</view>
+
+
+					</view>
+				</view>
+			</checkbox-group>
+
+			<view class="btn-area submitBottomBtn padding-lr-sm">
+				<button class="bg-blue round  margin-top" @click="$noMultipleClicks(btnSubmit)">提 交 </button>
+			</view>
+
+		</form>
+
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				noClick: true,
+				flag: false,
+				getData: {},
+				checkedValue: [],
+				checkbox: [{
+						value: 'm1',
+						checked: false,
+						title: '火警报警'
+					},
+					{
+						value: 'm2',
+						checked: false,
+						title: '火警故障'
+					},
+					{
+						value: 'm3',
+						checked: false,
+						title: '水压越线'
+					},
+					{
+						value: 'm4',
+						checked: false,
+						title: '开关变化'
+					},
+					{
+						value: 'm5',
+						checked: false,
+						title: '设备离线'
+					},
+					{
+						value: 'm6',
+						checked: false,
+						title: '烟感报警'
+					},
+					{
+						value: 'm7',
+						checked: false,
+						title: '电气火灾'
+					},
+					{
+						value: 'm8',
+						checked: false,
+						title: '视频报警'
+					},
+					{
+						value: 'm9',
+						checked: false,
+						title: '电梯监测'
+					},
+					{
+						value: 'm10',
+						checked: false,
+						title: '井盖监测'
+					}
+				],
+
+			}
+		},
+		onLoad: function(option) {
+			this.getCheckList();
+		},
+		methods: {
+			CheckboxChange(e) {
+				this.flag = true;
+				var items = this.checkbox,
+					values = e.detail.value;
+				this.checkedValue = values;
+				// console.log(values)
+
+				// console.log('点击复选框时this.checkedValue')
+				// console.log(this.checkedValue)
+				for (var i = 0, lenI = items.length; i < lenI; ++i) {
+					items[i].checked = false;
+					for (var j = 0, lenJ = values.length; j < lenJ; ++j) {
+						if (items[i].value == values[j]) {
+							items[i].checked = true;
+							break
+						}
+					}
+				}
+			},
+
+
+			// 回显数据请求
+			async getCheckList(params = {}) {
+				const res = await this.$myRequest({
+					url: 'PushSettings/setperm',
+					data: params,
+					showLoading: true
+				})
+				this.getData = res.data.data[0];
+
+
+
+				// 遍历checkbox数组对象
+				for (let i = 0; i < this.checkbox.length; i++) {
+					//判断value是否存在于返回对象中.存在的话checked重新赋值
+					if (this.getData.hasOwnProperty(this.checkbox[i].value)) {
+						// console.log(this.checkbox[i].value)
+						this.checkbox[i].checked = true
+					}
+				}
+			},
+
+
+			//提交
+			async btnSubmit() {
+
+				// 提交验证
+				// alert(this.aa);
+				// alert(this.checkedValue)
+				// if (!this.aa.length) {
+				// 	uni.showToast({
+				// 		title: "请选择推送选项",
+				// 		icon: "none"
+				// 	});
+				// 	return
+				// }
+
+
+				let mingParams = {};
+				if (!this.flag) {
+					//不点击默认传参
+					var obgj = this.getData;
+					console.log('不点击默认传参obgj')
+					console.log(obgj);
+					var arr = [];
+					for (var key in obgj) {
+						console.log(key)
+						console.log(obgj[key])
+						arr.push([key][0])
+					}
+					arr.map((e) => {
+						mingParams[e] = true;
+					});
+				} else {
+					//点击复选框后传参
+					var arr = this.checkedValue;
+					console.log('自由选中复选框后传参arr')
+					console.log(arr)
+
+
+					arr.map((e) => {
+						mingParams[e] = true;
+					});
+					console.log('mingParams')
+					console.log(mingParams)
+
+
+				}
+
+
+
+				let res = await this.PushSettings(mingParams);
+				// let res = await this.PushSettings({'m1':true,"m2":true,"m6":true});
+
+				if (!res.data.flag) {
+					uni.showToast({
+						title: "添加失败",
+						icon: "none"
+					});
+				} else {
+					uni.showToast({
+						title: "添加成功",
+					});
+					setTimeout(() => {
+						uni.switchTab({
+							url: '/pages/setting/setting',
+						});
+					}, 1000);
+					
+				}
+				
+				
+
+			},
+			PushSettings(params = {}) {
+				return this.$myRequest({
+					url: 'PushSettings/setperm',
+					data: params
+				})
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.checkItems {
+		width: 50%;
+		display: inline-block;
+		text-align: center;
+		margin-bottom: 40rpx;
+
+		.title {
+			display: inline-block;
+			margin-left: 10rpx;
+		}
+	}
+	
+	.padding-sm{
+		
+	}
+</style>

+ 185 - 0
src/pages/setting/setting.vue

@@ -0,0 +1,185 @@
+<template>
+  <view class="setting-wrapper">
+    <view class="top-banner justify-center align-center text-center">
+      <view>
+        <image width="130" src="@/static/images/setting/personal-head.png"></image>
+        <view class="userName">{{ useStores.$state.userName }}</view>
+        <!-- <view>上海永天科技股份有限公司</view> -->
+      </view>
+    </view>
+    <view class="cu-list menu-avatar padding-lr-sm padding-top-sm">
+     <!-- <view class="cu-item margin-bottom-sm" @tap="goMessagePush()">
+        <view class="cu-avatar">
+          <image class="image-bg" src="@/static/images/setting/push-icon.png" />
+        </view>
+        <view class="content">
+          <view class="">推送设置</view>
+        </view>
+        <view class="nav-right">
+          <view class="text-grey">
+            <text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+          </view>
+        </view>
+      </view>
+
+      <view class="cu-item margin-bottom-sm" @tap="goBuilding()">
+        <view class="cu-avatar">
+          <image class="image-bg" src="@/static/images/setting/building-icon.png" />
+        </view>
+        <view class="content">
+          <view class="">建筑管理</view>
+        </view>
+        <view class="nav-right">
+          <view class="text-grey">
+            <text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+          </view>
+        </view>
+      </view>
+
+      <view class="cu-item margin-bottom-sm" @tap="goFunReport()">
+        <view class="cu-avatar">
+          <image class="image-bg" src="@/static/images/setting/funcReport.png" />
+        </view>
+        <view class="content">
+          <view class="">功能报备</view>
+        </view>
+        <view class="nav-right">
+          <view class="text-grey">
+            <text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+          </view>
+        </view>
+      </view> -->
+
+      <view class="margin-bottom-sm">
+        <u-button @click="loginOut()" text="退出登录"></u-button>
+      </view>
+
+      <!-- <view class="cu-item" @tap="goSiteManage" v-if="permissionLabel==1">
+				<view class="cu-avatar " style="background-image:url(@/static/images/setting/setting-icon2.png)"></view>
+				<view class="content">
+					<view class="">站点管理</view>
+				</view>
+				<view class="nav-right">
+					<view class="text-grey">
+						<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+					</view>
+				</view>
+			</view>
+			<view class="cu-item" @tap="goAuthManage" v-if="permissionLabel==1">
+				<view class="cu-avatar " style="background-image:url(@/static/images/setting/setting-icon4.png)"></view>
+				<view class="content">
+					<view class="">权限管理</view>
+				</view>
+				<view class="nav-right">
+					<view class="text-grey">
+						<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+					</view>
+				</view>
+			</view> -->
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+
+import useStore from "@/store/modules/user";
+import useXunJianStore from "@/store/modules/xunJian";
+const useStores = useStore(); //全局用户信息Store
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const permissionLabel = ref(0);
+
+async function getAuthorization(params) {
+  const res = await this.$myRequest({
+    url: "Com/getAuthorization",
+    showLoading: true,
+    data: params,
+  });
+
+  this.permissionLabel = res.data.permissionLabel;
+}
+
+function goMessagePush() {
+  uni.navigateTo({
+    url: "/pages/setting/messagePush/messagePush",
+    success: (res) => {},
+    fail: () => {},
+    complete: () => {},
+  });
+}
+function goBuilding() {
+  uni.navigateTo({
+    url: "/pages/setting/building/building",
+    success: (res) => {},
+    fail: () => {},
+    complete: () => {},
+  });
+}
+function goFunReport() {
+  uni.navigateTo({
+    url: "/pages/setting/funReport/funReport",
+    success: (res) => {},
+    fail: () => {},
+    complete: () => {},
+  });
+}
+
+/**
+ * @退出登录
+ */
+function loginOut() {
+  //销毁存储的token
+  uni.clearStorage();
+  //关闭当前页面 返回指定页面
+  uni.redirectTo({
+    url: "/pages/login/login",
+  });
+}
+
+onLoad(() => {});
+</script>
+
+<style lang="scss">
+.setting-wrapper {
+  .top-banner {
+    width: 100%;
+    height: 380rpx;
+    background: url(@/static/images/setting/setting-bg.png) no-repeat;
+    background-size: cover;
+    color: #fff;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    image {
+      width: 130rpx;
+      height: 130rpx;
+    }
+    .userName {
+      margin-top: 30rpx;
+      margin-bottom: 10rpx;
+    }
+  }
+
+  .cu-list.menu-avatar .cu-item {
+    border-radius: 5px;
+    padding: 30rpx 0;
+    box-shadow: 1px 1px 4px rgb(26 26 26 / 10%);
+    .cu-avatar {
+      background-color: rgba(0, 0, 0, 0);
+      background-size: 100% 100%;
+      left: 26rpx;
+    }
+    .content {
+      left: 130rpx;
+      font-size: 32rpx;
+    }
+  }
+}
+</style>
+<style>
+body {
+  background: #fff;
+}
+</style>

+ 77 - 0
src/pages/test/export.vue

@@ -0,0 +1,77 @@
+<template>
+	<view>
+		<!-- 多个复选框,带全选 -->
+		<view>
+			<checkbox-group class="block" @change="changeCheckbox">
+				<view v-for="item in newDeviceManage" :key="item.id">				
+					<checkbox :value="String(item.id)" :checked="checkedArr.includes(String(item.id))" :class="{'checked':checkedArr.includes(String(item.id))}"></checkbox>
+					<text>{{item.title}}</text>
+				</view>
+			</checkbox-group>
+		</view>
+		<view>
+			<checkbox-group @change="allChoose">
+				<label>
+					<checkbox value="all" :class="{'checked':allChecked}" :checked="allChecked?true:false"></checkbox> 全选
+				</label>
+			</checkbox-group>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				isChecked:false,
+				newDeviceManage:[
+					{'id':0,'title':'选项一'},
+					{'id':1,'title':'选项二'},
+					{'id':2,'title':'选项三'},
+					{'id':3,'title':'选项四'},
+					{'id':4,'title':'选项五'},
+					{'id':5,'title':'选项六'},
+					{'id':6,'title':'选项七'},
+					{'id':7,'title':'选项八'},
+					{'id':8,'title':'选项九'},
+					{'id':9,'title':'选项十'}
+				],
+				checkedArr:[], //复选框选中的值
+				allChecked:false //是否全选
+			}
+		},
+		methods: {
+			// 多选复选框改变事件
+			changeCheckbox(e){
+				this.checkedArr = e.detail.value;
+				// 如果选择的数组中有值,并且长度等于列表的长度,就是全选
+				if(this.checkedArr.length>0 && this.checkedArr.length==this.newDeviceManage.length){
+					this.allChecked=true;
+				}else{
+					this.allChecked=false;
+				}
+			},
+			// 全选事件
+			allChoose(e){
+				let chooseItem = e.detail.value;
+				// 全选
+				if(chooseItem[0]=='all'){
+					this.allChecked=true;
+					for(let item of this.newDeviceManage){
+						let itemVal=String(item.id);
+						if(!this.checkedArr.includes(itemVal)){
+							this.checkedArr.push(itemVal);
+						}
+					}					
+				}else{
+					// 取消全选
+					this.allChecked=false;
+					this.checkedArr=[];
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 105 - 0
src/pages/test/test-1.vue

@@ -0,0 +1,105 @@
+<template>
+  <view>
+    <button class="bg-blue" @click="scancode()">扫码</button>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+
+  onLoad() {
+    // #ifdef H5
+    let redirect_uri = location.href.split("#")[0];
+    uni.request({
+      url: "https://qhome.usky.cn/USKYZHAF/sign.php",
+      header: {
+        "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
+      },
+      data: {
+        url: redirect_uri,
+      },
+      method: "GET",
+      success: (res) => {
+        let apiList = [
+          // 可能需要用到的能力 需要啥就写啥。多写也没有坏处
+          "openLocation",
+          "getLocation",
+          "scanQRCode",
+        ];
+        let info = {
+          debug: true, // 调试,发布的时候改为false
+          appId: res.data.appid,
+          nonceStr: res.data.nonceStr,
+          timestamp: parseInt(res.data.timestamp),
+          signature: res.data.sha_str,
+          jsApiList: apiList,
+        };
+        this.wx_co(info);
+      },
+    });
+
+    // #endif
+  },
+
+  methods: {
+    wx_co: function (wx_co) {
+      this.$wx.config({
+        debug: false, // 开启调试模式
+
+        appId: wx_co.appId, // 必填,公众号的唯一标识
+
+        timestamp: wx_co.timestamp, // 必填,生成签名的时间戳
+
+        nonceStr: wx_co.nonceStr, // 必填,生成签名的随机串
+
+        signature: wx_co.signature, // 必填,签名,见附录1
+
+        jsApiList: ["onMenuShareAppMessage", "scanQRCode"], // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
+      });
+
+      this.$wx.ready(function () {
+        //需在用户可能点击分享按钮前就先调用
+
+        this.$wx.checkJsApi({
+          jsApiList: ["scanQRCode"], // 需要检测的JS接口列表,所有JS接口列表见附录2,
+
+          success: function (res) {
+            // 以键值对的形式返回,可用的api值true,不可用为false
+            // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
+          },
+        });
+      });
+
+      this.$wx.error(function (res) {
+        console.log(res, "this.$wx.error"); // config信息验证失败会执行error函数
+      });
+    },
+
+    scancode: function () {
+      alert(1);
+      this.$wx.scanQRCode({
+        needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+
+        scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
+
+        success: function (res) {
+          setTimeout(function () {
+            /* 放200ms后执行的代码 */
+            alert(2);
+          }, 1000);
+
+          var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
+        },
+      });
+    },
+  },
+};
+</script>
+
+
+
+<style lang="scss">
+</style>

+ 36 - 0
src/pages/test/test-select-picker.vue

@@ -0,0 +1,36 @@
+<template>
+    <view>
+        <view class="uni-title uni-common-pl">地区选择器</view>
+        <view class="uni-list">
+            <view class="uni-list-cell">
+                <view class="uni-list-cell-db">
+                    <picker @change="bindPickerChange" :value="index" :range="array">
+                        <view class="uni-input">{{array[index]}}</view>
+                    </picker>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+	export default {
+    data() {
+        return {
+            array: ['中国', '美国', '巴西', '日本'],
+            index: 0,
+        }
+    },
+    computed: {
+    },
+    methods: {
+        bindPickerChange: function(e) {
+            console.log('picker发送选择改变,携带值为', e.target.value)
+            this.index = e.target.value
+        },
+    }
+}
+</script>
+
+<style>
+</style>

+ 126 - 0
src/pages/test/test.vue

@@ -0,0 +1,126 @@
+<template>
+	<view>
+		<view @tap="goCamera()" class="cameraButton">
+			拍照按钮
+		</view>
+		
+		<view class="uni-list list-pd">
+			<view class="uni-uploader__files">
+				<view v-for="(image, index) in imageList" :key="index" class="abc">
+					<view class="uni-uploader__file" style="inline-block">
+						<view class="delete " :style="{'z-index': 99}" @tap="onDeleteClick(index)">x</view>
+						<view class=" images-one">
+							<image class="uni-uploader__img image-bg" :src="image" :data-src="image"
+								@tap="previewImage"></image>
+						</view>
+
+					</view>
+				</view>
+				<view class="uni-uploader__input-box" v-show="imageList.length > 0">
+					<view class="uni-uploader__input" @tap="onGetImgClick"></view>
+				</view>
+			</view>
+		</view>
+
+
+
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+				imageList: [],
+
+			}
+		},
+		mounted() {
+
+		},
+
+
+		//拍照
+		methods: {
+
+			// 删除图片
+			onDeleteClick(index) {
+				this.imageList.splice(index, 1)
+			},
+			// previewImage() {
+			// 	// 预览功能,相关博客有
+			// },
+
+
+
+			goCamera() {
+				const that = this
+				uni.chooseImage({
+					count: 2, // 最多可以选择的图片张数,默认9
+					sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有
+					sourceType: ['camera'], //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
+					success: function(res) {
+						
+						var tempFilePaths = res.tempFilePaths[0]
+						alert(1)
+						alert(tempFilePaths)
+						const len = that.imageList.length
+						if (len >= 2) {
+							uni.showToast({
+								title: '图片最多上传2张'
+							})
+						} else {
+							for (let i = 0; i < 2 - len; i++) {
+								if (res.tempFilePaths[i]) that.imageList.push(res.tempFilePaths[i])
+							}
+						}
+					}
+				})
+
+			},
+
+
+
+
+		}
+
+	}
+</script>
+
+<style>
+	.cameraButton {
+		border: 1px solid red;
+		display: inline-block;
+		border-radius: 10rpx;
+		padding: 10rpx
+	}
+
+	.images-one {
+		white-space: nowrap;
+		position: relative;
+		width: 150rpx;
+		height: 150rpx;
+		background-size: cover;
+		background-position: center;
+		vertical-align: middle;
+		font-size: 1.5em;
+		display: inline-block;
+		margin-right: 20rpx
+	}
+
+	.image-bg {
+		position: absolute;
+		z-index: -1;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		right: 0;
+		width: 100%;
+		height: 100%;
+	}
+
+	.abc {
+		display: inline-block
+	}
+</style>

+ 183 - 0
src/pages/work/index.vue

@@ -0,0 +1,183 @@
+<template>
+  <view class="work-container">
+    <!-- 轮播图 -->
+    <uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
+      <swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
+        <swiper-item v-for="(item, index) in data" :key="index">
+          <view class="swiper-item" @click="clickBannerItem(item)">
+            <image :src="item.image" mode="aspectFill" :draggable="false" />
+          </view>
+        </swiper-item>
+      </swiper>
+    </uni-swiper-dot>
+
+    <!-- 宫格组件 -->
+    <uni-section title="系统管理" type="line"></uni-section>
+    <view class="grid-body">
+      <uni-grid :column="4" :showBorder="false" @change="changeGrid">
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="person-filled" size="30"></uni-icons>
+            <text class="text">用户管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="staff-filled" size="30"></uni-icons>
+            <text class="text">角色管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="color" size="30"></uni-icons>
+            <text class="text">菜单管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="settings-filled" size="30"></uni-icons>
+            <text class="text">部门管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="heart-filled" size="30"></uni-icons>
+            <text class="text">岗位管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="bars" size="30"></uni-icons>
+            <text class="text">字典管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="gear-filled" size="30"></uni-icons>
+            <text class="text">参数设置</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="chat-filled" size="30"></uni-icons>
+            <text class="text">通知公告</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="wallet-filled" size="30"></uni-icons>
+            <text class="text">日志管理</text>
+          </view>
+        </uni-grid-item>
+      </uni-grid>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      current: 0,
+      swiperDotIndex: 0,
+      data: [
+        {
+          image: "/static/images/banner/banner01.jpg",
+        },
+        {
+          image: "/static/images/banner/banner02.jpg",
+        },
+        {
+          image: "/static/images/banner/banner03.jpg",
+        },
+      ],
+    };
+  },
+  methods: {
+    clickBannerItem(item) {
+      console.info(item);
+    },
+    changeSwiper(e) {
+      this.current = e.detail.current;
+    },
+    changeGrid(e) {
+      this.$modal.showToast("模块建设中~");
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+/* #ifndef APP-NVUE */
+page {
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+  background-color: #fff;
+  min-height: 100%;
+  height: auto;
+}
+
+view {
+  font-size: 14px;
+  line-height: inherit;
+}
+
+/* #endif */
+
+.text {
+  text-align: center;
+  font-size: 26rpx;
+  margin-top: 10rpx;
+}
+
+.grid-item-box {
+  flex: 1;
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 15px 0;
+}
+
+.uni-margin-wrap {
+  width: 690rpx;
+  width: 100%;
+}
+
+.swiper {
+  height: 300rpx;
+}
+
+.swiper-box {
+  height: 150px;
+}
+
+.swiper-item {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  color: #fff;
+  height: 300rpx;
+  line-height: 300rpx;
+}
+
+@media screen and (min-width: 500px) {
+  .uni-swiper-dot-box {
+    width: 400px;
+    /* #ifndef APP-NVUE */
+    margin: 0 auto;
+    /* #endif */
+    margin-top: 8px;
+  }
+
+  .image {
+    width: 100%;
+  }
+}
+</style>

+ 39 - 0
src/permission.js

@@ -0,0 +1,39 @@
+import { getToken } from '@/utils/auth'
+
+// 登录页面
+const loginPage = "/pages/login"
+  
+// 页面白名单
+const whiteList = [
+  '/pages/login', '/pages/common/webview/index'
+]
+
+// 检查地址白名单
+function checkWhite(url) {
+  const path = url.split('?')[0]
+  return whiteList.indexOf(path) !== -1
+}
+
+// 页面跳转验证拦截器
+let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]
+list.forEach(item => {
+  uni.addInterceptor(item, {
+    invoke(to) {
+      if (getToken()) {
+        if (to.url === loginPage) {
+          uni.reLaunch({ url: "/" })
+        }
+        return true
+      } else {
+        if (checkWhite(to.url)) {
+          return true
+        }
+        uni.reLaunch({ url: loginPage })
+        return false
+      }
+    },
+    fail(err) {
+      console.log(err)
+    }
+  })
+})

+ 60 - 0
src/plugins/auth.js

@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+  const all_permission = "*:*:*"
+  const permissions = store.getters && store.getters.permissions
+  if (permission && permission.length > 0) {
+    return permissions.some(v => {
+      return all_permission === v || v === permission
+    })
+  } else {
+    return false
+  }
+}
+
+function authRole(role) {
+  const super_admin = "admin"
+  const roles = store.getters && store.getters.roles
+  if (role && role.length > 0) {
+    return roles.some(v => {
+      return super_admin === v || v === role
+    })
+  } else {
+    return false
+  }
+}
+
+export default {
+  // 验证用户是否具备某权限
+  hasPermi(permission) {
+    return authPermission(permission)
+  },
+  // 验证用户是否含有指定权限,只需包含其中一个
+  hasPermiOr(permissions) {
+    return permissions.some(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否含有指定权限,必须全部拥有
+  hasPermiAnd(permissions) {
+    return permissions.every(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否具备某角色
+  hasRole(role) {
+    return authRole(role)
+  },
+  // 验证用户是否含有指定角色,只需包含其中一个
+  hasRoleOr(roles) {
+    return roles.some(item => {
+      return authRole(item)
+    })
+  },
+  // 验证用户是否含有指定角色,必须全部拥有
+  hasRoleAnd(roles) {
+    return roles.every(item => {
+      return authRole(item)
+    })
+  }
+}

+ 17 - 0
src/plugins/index.js

@@ -0,0 +1,17 @@
+import tab from "./tab";
+import auth from "./auth";
+import modal from "./modal";
+
+export default {
+  install(app) {
+    // 页签操作
+    app.provide("$tab", tab);
+    app.config.globalProperties.$tab = tab;
+    // 认证对象
+    app.provide("$auth", auth);
+    app.config.globalProperties.$auth = auth;
+    // 模态框对象
+    app.provide("$modal", modal);
+    app.config.globalProperties.$modal = modal;
+  },
+};

+ 74 - 0
src/plugins/modal.js

@@ -0,0 +1,74 @@
+export default {
+  // 消息提示
+  msg(content) {
+    uni.showToast({
+      title: content,
+      icon: 'none'
+    })
+  },
+  // 错误消息
+  msgError(content) {
+    uni.showToast({
+      title: content,
+      icon: 'error'
+    })
+  },
+  // 成功消息
+  msgSuccess(content) {
+    uni.showToast({
+      title: content,
+      icon: 'success'
+    })
+  },
+  // 隐藏消息
+  hideMsg(content) {
+    uni.hideToast()
+  },
+  // 弹出提示
+  alert(content) {
+    uni.showModal({
+      title: '提示',
+      content: content,
+      showCancel: false
+    })
+  },
+  // 确认窗体
+  confirm(content) {
+    return new Promise((resolve, reject) => {
+      uni.showModal({
+        title: '系统提示',
+        content: content,
+        cancelText: '取消',
+        confirmText: '确定',
+        success: function(res) {
+          if (res.confirm) {
+            resolve(res.confirm)
+          }
+        }
+      })
+    })
+  },
+  // 提示信息
+  showToast(option) {
+    if (typeof option === "object") {
+      uni.showToast(option)
+    } else {
+      uni.showToast({
+        title: option,
+        icon: "none",
+        duration: 2500
+      })
+    }
+  },
+  // 打开遮罩层
+  loading(content) {
+    uni.showLoading({
+      title: content,
+      icon: 'none'
+    })
+  },
+  // 关闭遮罩层
+  closeLoading() {
+    uni.hideLoading()
+  }
+}

+ 30 - 0
src/plugins/tab.js

@@ -0,0 +1,30 @@
+export default {
+  // 关闭所有页面,打开到应用内的某个页面
+  reLaunch(url) {
+    return uni.reLaunch({
+      url: url
+    })
+  },
+  // 跳转到tabBar页面,并关闭其他所有非tabBar页面
+  switchTab(url) {
+    return uni.switchTab({
+      url: url
+    })
+  },
+  // 关闭当前页面,跳转到应用内的某个页面
+  redirectTo(url) {
+    return uni.redirectTo({
+      url: url
+    })
+  },
+  // 保留当前页面,跳转到应用内的某个页面
+  navigateTo(url) {
+    return uni.navigateTo({
+      url: url
+    })
+  },
+  // 关闭当前页面,返回上一页面或多级页面
+  navigateBack() {
+    return uni.navigateBack()
+  }
+}

+ 551 - 0
src/static/amap/1.html

@@ -0,0 +1,551 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
+    <title>协同作战地图</title>
+    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
+    <link rel="stylesheet" type="text/css" href="./js/M_select/M_select.css">
+    <link rel="stylesheet" type="text/css" href="./js/notification/index.css">
+    <style>
+        html,
+        body,
+        #mapF {
+            height: 100%;
+            width: 100%;
+        }
+    </style>
+</head>
+
+<body>
+    <div id="mapF" class="map" tabindex="0"></div>
+
+    <div style="padding: 0 10px;">
+        <div style="position: absolute;top: 0;display:inline-block;width: 50%;padding-top: 10px;">
+            <select id="selectId" class="select02">
+            </select>
+        </div>
+    </div>
+
+    <div id="notification" style="display: none;">
+        <div class="mask"> </div>
+        <div class="content"> </div>
+    </div>
+
+    <script src="https://a.amap.com/jsapi_demos/static/china.js"></script>
+    <script type="text/javascript"
+        src="https://webapi.amap.com/maps?v=2.0&key=8e266e1ac2ad2383c7773ff504ac248f"></script>
+    <script type="text/javascript" src="https://webapi.amap.com/ui/1.1/main.js"></script>
+    <script type="text/javascript" src="./js/jquery-2.2.1.min.js"></script>
+    <script src="./js/M_select/M_select.js"></script>
+    <script type="text/javascript" src="./js/map-data.js"></script>
+    <script type="text/javascript" src="./js/map-text.js"></script>
+
+    <script type="text/javascript">
+        var checkedArray = {
+            checkedData: 1,
+            checkedList: [
+                { value: 1, label: "消防站" },
+                { value: 2, label: "消防车" },
+                { value: 3, label: "监控" },
+                { value: 4, label: "重点单位" },
+                { value: 5, label: "消火栓/天然水源" },
+            ],
+        }//类型筛选
+
+        $.each(checkedArray.checkedList, function (i, item) {
+            $("#selectId").append(`<option value="${item.value}">${item.label}</option>`)
+        })
+        $(function () {
+            $(".select02").M_select({
+                // 手动添加下拉款图片(以html页面为起始位置写路径)
+                "Img": "./js/M_select/up4.png",
+                "Img2": "./js/M_select/down4.png",
+                "radius": "15px",
+                "Title": "--请选择--",
+                "inputName": "selected_value",
+                // 默认选中的值(参数值写需要选中的select的value值)
+                "selected": "1",
+                Succee: function () {
+                    checkedArray.checkedData = parseInt($(".inputHidden").val())
+                    mapCluster();
+                }
+            });
+        });
+
+        //点击遮罩层关闭
+        $('#notification .mask').on('click', function (e) {
+            $('#notification').css('display', 'none')
+
+            $('#notification .content #xxxx').remove()
+        })
+    </script>
+
+    <script type="text/javascript">
+
+        var cluster, markers = [];
+        var map = [];
+        var mapPolList = [];
+        var colorList = [
+            ['#99e', "#F33"],
+            ['#ee6', "#c38"],
+            ['#c38', "#F33"],
+            ['#6E7', '#F33'],
+            ['#6A7', "#F33"],
+            ['#EF7', "#F33"],
+            ['#AF7', "#F33"],
+            ['#BAC', "#F33"],
+            ['#BEF', "#F33"],
+            ['#BBB', "#F33"],
+            ['#EFA', "#F33"],
+            ['#FE6', "#F33"],
+            ['#7F6', "#F33"],
+            ['#7dc', "#F33"],
+        ];
+        var colorIndList = [-1, 7, 21, 26, 31, 37, 46, 52, 57, 66, 68, 71, 74, 100]
+
+        var polygon1 = null //选中地图区域数据存储
+        var textList = [] //地图文字数据存储
+
+        var streetTown = ""//街镇信息存储
+        var streetTownList = [
+            { value: "", label: "全区" },
+            { value: "华漕镇", label: "华漕镇" },
+            { value: "虹桥镇", label: "虹桥镇" },
+            { value: "梅陇镇", label: "梅陇镇" },
+            { value: "七宝镇", label: "七宝镇" },
+            { value: "颛桥镇", label: "颛桥镇" },
+            { value: "马桥镇", label: "马桥镇" },
+            { value: "吴泾镇", label: "吴泾镇" },
+            { value: "浦江镇", label: "浦江镇" },
+            { value: "新虹街道", label: "新虹街道" },
+            { value: "古美路街道", label: "古美路街道" },
+            { value: "江川路街道", label: "江川路街道" },
+            { value: "浦锦街道", label: "浦锦街道" },
+            { value: "莘庄镇", label: "莘庄镇" },
+        ]
+
+        var tankuangXY = {}//撒点弹框坐标
+        var arrayList = {}//撒点弹框数据存储
+
+
+        function initMap() {
+            map = new AMap.Map("mapF", {
+                // mapStyle: 'amap://styles/d0ddc09bd7cbd7331a8e8fa691e5b0da', //设置地图的显示样式
+                resizeEnable: true,
+                zoom: 13,
+                zooms: [3, 16],
+            });
+
+
+            AMap.plugin(["AMap.Geolocation"], () => {
+                var geolocation = new AMap.Geolocation({
+                    showButton: false, //是否显示定位按钮
+                    buttonPosition: "RT", //定位按钮的位置
+                    /* LT LB RT RB */
+                    buttonOffset: new AMap.Pixel(10, 20), //定位按钮距离对应角落的距离
+                    zoomToAccuracy: false, //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
+                    showMarker: true, //是否显示定位点
+                    markerOptions: {
+                        //自定义定位点样式,同Marker的Options
+                        offset: new AMap.Pixel(-18, -36),
+                        content: '<img src="https://a.amap.com/jsapi_demos/static/resource/img/user.png" style="width:36px;height:36px"/>',
+                    },
+                    convert: true,
+                    showCircle: true, //是否显示定位精度圈
+                    circleOptions: {
+                        //定位精度圈的样式
+                        strokeColor: "#0093FF",
+                        noSelect: true,
+                        strokeOpacity: 0.5,
+                        strokeWeight: 1,
+                        fillColor: "#02B0FF",
+                        fillOpacity: 0.25,
+                    },
+                });
+                map.addControl(geolocation);
+                // geolocation.getCurrentPosition();
+            });
+
+            mapPolList = mapData.map((el, ind) => {
+                // console.log(val)
+
+                let color = colorList[0];
+
+                let polygon = new AMap.Polygon({
+                    map: this.map,
+                    zIndex: 2,
+                    fillOpacity: 0.5,
+                    path: el.value,
+                    fillColor: color[0],
+                    strokeColor: color[1],
+                });
+
+                //插入覆盖物自定义数据
+                polygon.setExtData(el);
+
+                //鼠标移入覆盖物事件
+                polygon.on("mouseover", () => {
+                    polygon.setOptions({
+                        fillOpacity: 0.4,
+                        fillColor: color[1],
+                    });
+                });
+
+                //鼠标移出覆盖物事件
+                polygon.on("mouseout", (val) => {
+                    if (streetTown) {
+                        if (streetTown == polygon.getExtData().name) {
+                            polygon.setOptions({
+                                fillOpacity: 0.4,
+                                fillColor: color[1],
+                            });
+                        } else {
+                            polygon.setOptions({
+                                fillOpacity: 0.5,
+                                fillColor: color[0],
+                            });
+                        }
+                    } else {
+                        polygon.setOptions({
+                            fillOpacity: 0.5,
+                            fillColor: color[0],
+                        });
+                    }
+                });
+
+                polygon.on("click", (handler, context) => {
+                    if (polygon1) {
+                        //修改上一次选中样式
+                        polygon1.setOptions({
+                            fillOpacity: 0.5,
+                            fillColor: color[0],
+                        });
+                    }
+                    //存储点击区域元素
+                    polygon1 = polygon;
+
+                    if (streetTown === polygon.getExtData().name) {
+                        //修改全局街镇数据
+                        streetTown = "";
+
+                        //修改上一次选中样式
+                        polygon1.setOptions({
+                            fillOpacity: 0.5,
+                            fillColor: color[0],
+                        });
+                        polygon1 = null;
+                    } else {
+                        //修改全局街镇数据
+                        streetTown = polygon.getExtData().name;
+
+                        //修改上一次选中样式
+                        polygon1.setOptions({
+                            fillOpacity: 0.4,
+                            fillColor: color[1],
+                        });
+                    }
+
+                    mapCluster()
+
+                    //销毁点位信息弹窗
+                    map.clearInfoWindow();
+                });
+            })
+
+            mapText.map((val, ind) => {
+                let text = new AMap.Text({
+                    zIndex: 1,
+                    style: {
+                        color: "black",
+                        backgroundColor: "transparent",
+                        border: "none",
+                    },
+                    position: val.position,
+                    text: val.name,
+                    angle: val.angle,
+                });
+
+                text.setMap(map);
+
+                textList.push(text);
+            });
+
+            map.setFitView();
+
+            var logMapinfo = function () {
+                var zoom = map.getZoom(); //获取当前地图级别
+
+                var dom = document.getElementsByClassName("amap-overlay-text-container");
+                for (let i = 0; i <= 13; i++) {
+                    if (zoom > 12) {
+                        dom[i].style.cssText = "display: block;font-size:13px !important;background: transparent;border: 0px;";
+                    } else if (zoom > 10.5 || zoom > 11) {
+                        dom[i].style.cssText = "display: block;font-size:11px !important;background: transparent;border: 0px;";
+                    } else if (zoom < 10) {
+                        dom[i].style.cssText = "display:none !important;font-size:11px;background: transparent;border: 0px;";
+                    }
+                }
+            };
+
+            map.on("zoomstart", logMapinfo);
+        }
+
+
+        /**
+         * @聚合撒点
+         * @param {数据list} data
+         * @param {页面类型} pageType
+         * @param {类型} type
+         */
+        function initMarkers(data, pageType, type) {
+            var _this = this;
+
+            var tag = 1; //1.自定义图标 2.完全自定义 3.默认
+            var style = ""; //地图最大化小图标
+            var points = []; //地图撒点处理数据存储
+
+            if (pageType === "警情综合处置") {
+                data.forEach((val) => {
+                    points.push({ lnglat: [val.longitude, val.latitude], array: val });
+                });
+
+                if (type) {
+                    if (type == 1) {
+                        //消防站
+                        style = `background: url('./img/map1.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    } else if (type == 2) {
+                        //消防车
+                        style = `background: url('./img/map2.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    } else if (type == 3) {
+                        //监控
+                        style = `background: url('./img/map3.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    } else if (type == 4) {
+                        //重点单位
+                        style = `background: url('./img/map4.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    } else if (type == 5) {
+                        //消火栓/天然水源
+                        style = `background: url('./img/map5.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    } else if (type == 6) {
+                        //实时告警
+                        style = `background: url('./img/map6.png') no-repeat; height: 53px; width: 47px; border: 0px !important; border-radius: 0px !important; box-shadow: 0 0 0 0 !important;`;
+                    }
+                } else {
+                    style = `background-color: hsla(180, 100%, 50%, 0.5); height: 24px; width: 24px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 1px;`;
+                }
+            }
+
+            var _renderMarker = function (context) {
+                var content = `<div style="${style}"></div>`;
+                var offset = new AMap.Pixel(-9, -9);
+                context.marker.setContent(content);
+                context.marker.setOffset(offset);
+
+                // 给每个点坐标绑定鼠标经过事件,这里是实现点击功能的重点
+                context.marker.on("mouseover", (e) => {
+                    tankuangXY = { x: e.pixel.x, y: e.pixel.y };
+
+                    if (pageType === "警情综合处置") {
+                        if (type !== 6) {
+                            //   console.log(context.data[0].array);
+                        }
+                    }
+                });
+
+
+                address
+                :
+                "上海市闵行区浦江镇沿浦路15号"
+                companyName
+                :
+                "上海闵行区晨星敬老院"
+                companyTypeName
+                :
+                "重点单位"
+                id
+                :
+                371
+                latitude
+                :
+                "31.01668"
+                linkPhone
+                :
+                "13472846477"
+                longitude
+                :
+                "121.54048"
+                streetTown
+                :
+                "浦江镇"
+
+                context.marker.on("click", (e) => {
+                    if (pageType === "警情综合处置") {
+                        if (type == 1) {
+
+                            $("#notification .content").append(
+                                `
+                                <div id="xxxx">
+                                    <div class="title">${context.data[0].array.stationName}</div>
+                                    <div class="borderBottom"></div>
+                                    <div class="ctn">
+                                        <div style="text-align: center;">经度:${context.data[0].array.longitude}</div>
+                                        <div style="text-align: center;">纬度:${context.data[0].array.latitude}</div>
+                                    </div>
+                                </div>
+                                `)
+
+                            $('#notification').css('display', 'block')
+
+                        } else if (type == 4) {
+                            $("#notification .content").append(
+                                `
+                                <div id="xxxx">
+                                    <div class="title">${context.data[0].array.companyName}</div>
+                                    <div class="borderBottom"></div>
+                                    <div class="ctn">
+                                        <div style="width:100%">地址:${context.data[0].array.address}</div>
+                                        <div style="width:100%">单位性质:${context.data[0].array.companyTypeName}</div>
+                                    </div>
+                                    <div class="ctn">
+                                        <div >所属街镇:${context.data[0].array.streetTown}</div>
+                                    </div>
+                                </div>
+                                `)
+
+                            $('#notification').css('display', 'block')
+                        } else if (type == 5) {
+                            $("#notification .content").append(
+                                `
+                                <div id="xxxx">
+                                    <div class="title">${context.data[0].array.waterName}</div>
+                                    <div class="borderBottom"></div>
+                                    <div class="ctn">
+                                        <div style="width:100%">水源所在位置:${context.data[0].array.waterAddress}</div>
+                                    </div>
+                                </div>
+                                `)
+
+                            $('#notification').css('display', 'block')
+                        } else if (type == 6) {
+                            //实时告警
+                            console.log(context.data[0].array);
+                        }
+
+                        console.log(context.data[0].array);
+                    }
+                });
+            };
+
+            if (cluster) {
+                cluster.setMap(null);
+            }
+            if (tag == 2) {
+                //完全自定义
+                this.map.plugin(["AMap.MarkerClusterer"], function () {
+                    cluster = new AMap.MarkerCluster(map, points, {
+                        gridSize: 80, // 设置网格像素大小
+                        renderClusterMarker: function (context) {
+                            var factor = Math.pow(context.count / points.length, 1 / 18);
+                            var div = document.createElement("div");
+                            var Hue = 180 - factor * 180;
+                            var bgColor = "hsla(" + Hue + ",100%,40%,0.7)";
+                            var fontColor = "hsla(" + Hue + ",100%,90%,1)";
+                            var borderColor = "hsla(" + Hue + ",100%,40%,1)";
+                            var shadowColor = "hsla(" + Hue + ",100%,90%,1)";
+                            div.style.backgroundColor = bgColor;
+                            var size = Math.round(30 + Math.pow(context.count / points.length, 1 / 5) * 20);
+                            div.style.width = div.style.height = size + "px";
+                            div.style.border = "solid 1px " + borderColor;
+                            div.style.borderRadius = size / 2 + "px";
+                            div.style.boxShadow = "0 0 5px " + shadowColor;
+                            div.innerHTML = context.count;
+                            div.style.lineHeight = size + "px";
+                            div.style.color = fontColor;
+                            div.style.fontSize = "14px";
+                            div.style.textAlign = "center";
+                            context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
+                            context.marker.setContent(div);
+                        }, // 自定义聚合点样式
+                        renderMarker: _renderMarker, // 自定义非聚合点样式
+                    });
+                });
+            } else if (tag == 1) {
+                //自定义图标
+                var sts = [{
+                    url: "https://a.amap.com/jsapi_demos/static/images/blue.png",
+                    size: new AMap.Size(32, 32),
+                    offset: new AMap.Pixel(-16, -16),
+                },
+                {
+                    url: "https://a.amap.com/jsapi_demos/static/images/green.png",
+                    size: new AMap.Size(32, 32),
+                    offset: new AMap.Pixel(-16, -16),
+                },
+                {
+                    url: "https://a.amap.com/jsapi_demos/static/images/orange.png",
+                    size: new AMap.Size(36, 36),
+                    offset: new AMap.Pixel(-18, -18),
+                },
+                {
+                    url: "https://a.amap.com/jsapi_demos/static/images/red.png",
+                    size: new AMap.Size(48, 48),
+                    offset: new AMap.Pixel(-24, -24),
+                },
+                {
+                    url: "https://a.amap.com/jsapi_demos/static/images/darkRed.png",
+                    size: new AMap.Size(48, 48),
+                    offset: new AMap.Pixel(-24, -24),
+                },
+                ];
+
+                map.plugin(["AMap.MarkerCluster"], function () {
+                    cluster = new AMap.MarkerCluster(map, points, {
+                        styles: sts,
+                        gridSize: 80,
+                        renderMarker: _renderMarker, // 自定义非聚合点样式
+                    });
+                });
+            } else {
+                //默认样式
+                map.plugin(["AMap.MarkerCluster"], function () {
+                    cluster = new AMap.MarkerCluster(map, points, { gridSize: 80 });
+                });
+            }
+        }
+
+
+        /**
+         * @高德地图聚合撒点
+         */
+        function mapCluster() {
+            var label = "";
+            checkedArray.checkedList.forEach((val) => {
+                if (val.value == checkedArray.checkedData) {
+                    label = val.label;
+                }
+            });
+
+
+            $.get('http://mobile.usky.cn:8099/prod-api/service-fire/demPoliceInfo/synthesizePoliceSituationScatterer', {
+                streetTown: streetTown,
+                scattererType: label
+            }, function (res) {
+                console.log(res)
+
+                if (res.data.length > 0) {
+                    initMarkers(res.data, "警情综合处置", checkedArray.checkedData);
+                } else {
+                    initMarkers([], "警情综合处置", checkedArray.checkedData);
+                }
+            })
+            // 
+        }
+
+        initMap();
+        mapCluster();
+    </script>
+</body>
+
+</html>

BIN
src/static/amap/img/hz.png


BIN
src/static/amap/img/lc1.png


BIN
src/static/amap/img/lc2.png


BIN
src/static/amap/img/lc3.png


BIN
src/static/amap/img/lc4.png


BIN
src/static/amap/img/map1.png


BIN
src/static/amap/img/map2.png


BIN
src/static/amap/img/map3.png


BIN
src/static/amap/img/map4.png


BIN
src/static/amap/img/map5.png


BIN
src/static/amap/img/map6.png


BIN
src/static/amap/img/qxjy.png


BIN
src/static/amap/img/shjz.png


+ 71 - 0
src/static/amap/js/M_select/M_select.css

@@ -0,0 +1,71 @@
+.sel-box{
+	width: 100%;
+	border:1px solid #ddd;
+	overflow: hidden;
+	background-color: white;
+}
+.sel-box.on{
+	/* border-color: #15A0F5; */
+}
+.sel-title-box{
+	position: relative;
+	cursor: default;
+	overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.sel-title{
+	padding-left: 12px;
+	line-height: 2.2;
+}
+.sel-sign{
+	position: absolute;
+	display: inline-block;
+	right: 0;
+	top: 0;
+	background: url(down2.png);
+	background-size: 100% 100%;
+}
+.sel-sign.on{
+	background: url(down22.png);
+	background-size: 100% 100%;
+}
+.sel-float-box{
+	position: absolute;
+	border:1px solid #ddd;
+	z-index: 2;
+	background-color:white;
+	margin-left: -1px;
+	overflow: hidden;
+	line-height: 2;
+}
+.sel-float-box.on{
+	/* border-color: #15A0F5; */
+}
+.sel-float-div{
+	padding-left: 12px;
+	cursor: default;
+	overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+	background-color: white;
+	color:#666;
+}
+.sel-float-div:hover{
+	background-color:#15A0F5;
+	color:white;
+}
+.sel-float-div-disabled{
+	padding-left: 12px;
+	line-height: 1.8;
+	color:#bbb;
+	overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+}
+
+.sel-hide{
+	display: none;
+
+}

+ 251 - 0
src/static/amap/js/M_select/M_select.js

@@ -0,0 +1,251 @@
+
+;(function($){
+    var ser_object2,ser_object2_img,radius_v;
+  	
+    jQuery.fn.extend({
+        
+        // ***********************
+        // ***********************
+        // select下拉框
+        // 
+        // $("").M_select();
+        // ***********************
+        // ***********************
+        "M_select":function(options){
+            var ojc_arr=this,ojc;
+            
+            // select下拉框
+            for(i=0;i<ojc_arr.length;i++){
+                var ser_object=$(ojc_arr[i]);
+                // 当前下拉框初始化的对象
+                var $ser_object=$(ser_object);
+                $ser_object.parent().addClass("select-con");
+                $ser_object.parent().css("z-index","1");
+                $ser_object.wrap("<section class='sel-hide'></section>");
+                $ser_object.parent().parent().append('<section class="sel-box"><div class="sel-title-box"><span class="sel-title"></span><span class="sel-sign"></span></div><section class="sel-float-box"></section></section>');
+                var w=$ser_object.parent().parent().width();
+                $ser_object.parent().parent().find(".sel-float-box").css("width",w);
+                var ojc=$ser_object.children();
+                for(a=0;a<ojc.length;a++){
+                    var t=$(ojc[a]).text();
+                    var v=$(ojc[a]).attr("value");
+                   $ser_object.parent().parent().find(".sel-float-box").append('<div class="sel-float-div sel-Hcolor" value='+v+'>'+t+'</div>');
+                };
+               
+                for(a=0;a<ojc.length;a++){
+                        
+                        var sel_disabled=$(ojc[a]).attr("disabled");
+                        
+                        if(sel_disabled=="disabled"||sel_disabled=="true"){
+                            var div_ojc=$ser_object.parent().parent().find('.sel-float-box').children();
+                            $(div_ojc[a]).removeClass("sel-float-div");
+                            $(div_ojc[a]).addClass("sel-float-div-disabled");
+                        
+                        }
+                    };
+
+                var sel_textFirst=$ser_object.parent().parent().find(".sel-float-box").children().eq(0).text();
+
+             
+                // 默认参数
+                var defaultOption = {
+                   
+                    ico:1,
+                    Img:"",
+                    Img2:"",
+                    Title:"",
+                    inputName:"sel_v",
+                    selected:"0",
+                    radius:"0",
+                    Succee:function(){}
+                
+                };
+                // 合并自定义参数和默认参数,出现相同属性名时自定义参数会覆盖默认参数
+                options = $.extend({},defaultOption,options);
+
+                // 判断Test是否为空
+                if(options.Title){
+                    sel_textFirst=options.Title;
+                  
+                };
+                $ser_object.parent().parent().find(".sel-title").text(sel_textFirst);
+
+                // 判断使用哪种ico样式
+                var Img,Img2;
+                if(!(options.Img)&&!(options.Img2)){
+                 
+                    if(options.ico==1){
+                        Img="./js/M_select/down1.png";
+                        Img2="./js/M_select/up1.png";
+                    }
+                    if(options.ico==2){
+                        Img="./js/M_select/down2.png";
+                        Img2="./js/M_select/up2.png";
+                    }
+                    if(options.ico==3){
+                        Img="./js/M_select/down3.png";
+                        Img2="./js/M_select/up3.png";
+                    }
+                    if(options.ico==4){
+                        Img="./js/M_select/down4.png";
+                        Img2="./js/M_select/up4.png";
+                    }
+                    if(options.ico==5){
+                        Img="./js/M_select/down5.png";
+                        Img2="./js/M_select/up5.png";
+                    }
+                }else if(!(options.Img)&&(options.Img2!=null)){
+                        Img=options.Img2;
+                        Img2=options.Img2;
+                }else if(!(options.Img2)&&(options.Img!=null)){
+                        Img=options.Img;
+                        Img2=options.Img;
+                }else if((options.Img!=null)&&(options.Img2!=null)){
+                        Img=options.Img;
+                        Img2=options.Img2;
+                }
+
+                // 可传参css
+                $ser_object.parent().parent().find(".sel-sign").css("background","url("+Img+")");
+                $ser_object.parent().parent().find(".sel-sign").css("background-size","100% 100%");
+                $ser_object.parent().parent().find(".sel-box").append('<input type="hidden" name="'+options.inputName+'" value="'+options.selected+'" class="inputHidden">');
+                $ser_object.parent().parent().find(".sel-box").css("border-radius",options.radius);
+                $ser_object.parent().parent().find(".sel-float-box").css("border-radius","0 0 "+options.radius +" "+options.radius+" ");
+             
+                // 获取图片的高
+                var ico_h=$ser_object.parent().parent().find(".sel-title-box").height();
+                // 设置图片的宽高
+                $ser_object.parent().parent().find(".sel-sign").css({'width':+ico_h+'px','height':+ico_h+'px'});
+                $ser_object.parent().parent().find(".sel-title-box").css("padding-right",ico_h+"px");
+
+                // 获取有多少个选项
+                var selLength=$ser_object.parent().parent().find(".sel-float-box").children().length;
+                var selListHeight=$ser_object.parent().parent().find(".sel-float-box").children().height();
+                // 获取选项的高度
+               
+                var selHeight=selListHeight*10;
+                // 隐藏下拉框
+                $(".sel-float-box").hide();
+                if(selLength>10){
+                    $ser_object.parent().parent().find(".sel-float-box").css("height",selHeight);
+                    $ser_object.parent().parent().find(".sel-float-box").css("overflow-y","scroll");
+                }
+
+                // 根据selected 的值选中(即input value)
+                var input_val=$ser_object.parent().parent().find(".inputHidden").attr("value");
+                var div_objoct=$ser_object.parent().parent().find(".sel-float-div");
+                for(a=0;a<div_objoct.length;a++){
+                        
+                    var div_val=$(div_objoct[a]).attr("value");
+                    if(div_val==input_val){
+                        var div_text=$(div_objoct[a]).text();
+                        $ser_object.parent().parent().find(".sel-title").text(div_text);
+                        };
+                };
+
+                
+                // 点击事件
+                $ser_object.parent().parent().find(".sel-title-box").on("click",function(){
+                	var $ser_object2=$(ser_object2);
+                    // 切换图片
+                    $ser_object2.parent().parent().find(".sel-sign").css("background","url("+ser_object2_img+")");
+                    $ser_object2.parent().parent().find(".sel-sign").css("background-size","100% 100%");
+                    $ser_object2.parent().css("border-radius",radius_v);
+                    $('.sel-box').removeClass("on");
+                    ser_object2=this;
+                    ser_object2_img=Img;
+                    // 圆角值
+                    radius_v=options.radius;
+
+                    var floatAttr=$(this).parent().find(".sel-float-box").css("display");
+                    if(floatAttr=="block"){
+                    	$(".sel-float-box").hide();
+                        var $this=$(this).parent();
+                        $this.find(".sel-float-box").hide();
+                        $this.removeClass("on");
+                        $this.find(".sel-float-box").removeClass("on");
+
+                        $this.css("border-radius",options.radius);
+                        // 切换图片
+                        $this.parent().find(".sel-sign").css("background","url("+Img+")");
+                        $this.parent().find(".sel-sign").css("background-size","100% 100%");
+                    }else if(floatAttr=="none"){
+                    	var $this=$(this).parent();
+                        // 切换图片
+                        $this.parent().find(".sel-sign").css("background","url("+Img2+")");
+                        $this.parent().find(".sel-sign").css("background-size","100% 100%");
+                        $(".sel-float-box").hide();
+                        $this.find(".sel-float-box").show();
+
+                        $this.addClass("on");
+                        $this.find(".sel-float-box").addClass("on");
+
+                        $this.css("border-radius",options.radius+" "+options.radius+"  0 0");
+                    }
+                    
+                });
+
+                // 选项点击事件
+                $ser_object.parent().parent().find(".sel-float-div").on("click",function(){
+                    var sel_text=$(this).text();
+                    var sel_value=$(this).attr("value");
+                    var $this=$(this).parent();
+                    // 切换图片
+                    $this.parent().find(".sel-sign").css("background","url("+Img+")");
+                    $this.parent().find(".sel-sign").css("background-size","100% 100%");
+
+                    $this.hide();
+                    $this.parent().find(".sel-title").text(sel_text);
+                    $this.parent().css("border-radius",options.radius);
+               
+                    $this.parent().find(".sel-title").attr("value",sel_value);
+                    var selected_value=$this.parent().find(".sel-title").attr("value");
+                    $this.parent().find(".inputHidden").attr("value",selected_value);
+                    var v;
+                    var ojc_option=$(this).parent().parent().parent().find("option");
+                    for(a=0;a<ojc_option.length;a++){
+                        
+                        v=$(ojc_option[a]).attr("value");
+                        
+                        if(v==selected_value){
+                            $(ojc_option).attr("selected",false);
+                            $(ojc_option[a]).attr("selected",true);
+                           
+                        }
+                    };
+                    // 判断函数是否为空
+                   if(options.Succee!=null){
+                        options.Succee(selected_value);
+                   }
+                       
+                  
+                });
+            }// for循环语句结束
+           
+        },
+        
+    });
+    // 点击其他位置下拉消失
+    
+     $(document).on('click', function (e) { 
+        var parent = $(e.target).parents('.select-con').length;
+        if(!parent) {
+        	var $ser_object2=$(ser_object2);
+            // // 切换图片
+            $ser_object2.parent().parent().find(".sel-sign").css("background","url("+ser_object2_img+")");
+            $ser_object2.parent().parent().find(".sel-sign").css("background-size","100% 100%");
+            $ser_object2.parent().css("border-radius",radius_v);
+            // console.log(ser_object2);
+            $('.sel-float-box').hide();
+            $('.sel-box').removeClass("on");
+        };
+
+    });
+
+})(jQuery);
+// jsion对象初始化插件
+function M_select_init(ojt){
+    ojt.forEach(function(val){
+        $(val.Name).M_select(val.data);
+    });
+};

BIN
src/static/amap/js/M_select/down2.png


BIN
src/static/amap/js/M_select/down4.png


BIN
src/static/amap/js/M_select/down5.png


BIN
src/static/amap/js/M_select/up2.png


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