Browse Source

设备绑定,嵌入h5页面

WangYiHan 11 tháng trước cách đây
mục cha
commit
0620657c14
100 tập tin đã thay đổi với 9997 bổ sung1492 xóa
  1. 1 0
      App.vue
  2. 30 0
      api/sleep/equ.js
  3. 32 0
      api/sleep/index.js
  4. 1 1
      config/app.js
  5. 3 1
      libs/login.js
  6. 3 1
      manifest.json
  7. 24 436
      package-lock.json
  8. 6 0
      package.json
  9. 54 2
      pages.json
  10. 253 0
      pages/equ_list/add_equ.vue
  11. 392 0
      pages/equ_list/bind.vue
  12. 196 0
      pages/equ_list/choose.vue
  13. 563 0
      pages/equ_list/index.vue
  14. 337 0
      pages/index/condition/altitude/index.vue
  15. 227 0
      pages/index/condition/blood_oxygen/components/content.vue
  16. 391 0
      pages/index/condition/blood_oxygen/index.vue
  17. 222 0
      pages/index/condition/blood_pressure/components/content.vue
  18. 387 0
      pages/index/condition/blood_pressure/index.vue
  19. 233 0
      pages/index/condition/heart_rate/components/content.vue
  20. 802 0
      pages/index/condition/heart_rate/index.vue
  21. 415 0
      pages/index/condition/sleep/index.vue
  22. 433 0
      pages/index/condition/step/index.vue
  23. 208 0
      pages/index/condition/temperature/components/content.vue
  24. 392 0
      pages/index/condition/temperature/index.vue
  25. 1083 1044
      pages/index/index.vue
  26. BIN
      static/img/addequ.png
  27. BIN
      static/img/addicon.png
  28. BIN
      static/img/arrow.png
  29. BIN
      static/img/breathe-icon.png
  30. BIN
      static/img/breathe.png
  31. BIN
      static/img/heart-icon.png
  32. BIN
      static/img/heart.png
  33. BIN
      static/img/none.png
  34. BIN
      static/img/noneEqu.png
  35. BIN
      static/img/scan.png
  36. BIN
      static/img/sleep-icon.png
  37. BIN
      static/img/sleep.png
  38. BIN
      static/img/sos.png
  39. BIN
      static/img/unbreathe-icon.png
  40. BIN
      static/img/unheart-icon.png
  41. BIN
      static/img/unsleep-icon.png
  42. 2 1
      store/getters.js
  43. 7 1
      store/modules/app.js
  44. 108 0
      utils/request - 副本.js
  45. 11 5
      utils/request.js
  46. 110 0
      utils/request2.js
  47. 1 0
      wxcomponents/vant/dist/action-sheet/index.d.ts
  48. 71 0
      wxcomponents/vant/dist/action-sheet/index.js
  49. 8 0
      wxcomponents/vant/dist/action-sheet/index.json
  50. 112 0
      wxcomponents/vant/dist/action-sheet/index.vue
  51. 69 0
      wxcomponents/vant/dist/action-sheet/index.wxml
  52. 1 0
      wxcomponents/vant/dist/action-sheet/index.wxss
  53. 1 0
      wxcomponents/vant/dist/area/index.d.ts
  54. 220 0
      wxcomponents/vant/dist/area/index.js
  55. 6 0
      wxcomponents/vant/dist/area/index.json
  56. 234 0
      wxcomponents/vant/dist/area/index.vue
  57. 20 0
      wxcomponents/vant/dist/area/index.wxml
  58. 8 0
      wxcomponents/vant/dist/area/index.wxs
  59. 1 0
      wxcomponents/vant/dist/area/index.wxss
  60. 1 0
      wxcomponents/vant/dist/button/index.d.ts
  61. 64 0
      wxcomponents/vant/dist/button/index.js
  62. 7 0
      wxcomponents/vant/dist/button/index.json
  63. 90 0
      wxcomponents/vant/dist/button/index.vue
  64. 56 0
      wxcomponents/vant/dist/button/index.wxml
  65. 39 0
      wxcomponents/vant/dist/button/index.wxs
  66. 0 0
      wxcomponents/vant/dist/button/index.wxss
  67. 37 0
      wxcomponents/vant/dist/calendar/calendar.vue
  68. 68 0
      wxcomponents/vant/dist/calendar/calendar.wxml
  69. 1 0
      wxcomponents/vant/dist/calendar/components/header/index.d.ts
  70. 37 0
      wxcomponents/vant/dist/calendar/components/header/index.js
  71. 3 0
      wxcomponents/vant/dist/calendar/components/header/index.json
  72. 64 0
      wxcomponents/vant/dist/calendar/components/header/index.vue
  73. 16 0
      wxcomponents/vant/dist/calendar/components/header/index.wxml
  74. 1 0
      wxcomponents/vant/dist/calendar/components/header/index.wxss
  75. 6 0
      wxcomponents/vant/dist/calendar/components/month/index.d.ts
  76. 154 0
      wxcomponents/vant/dist/calendar/components/month/index.js
  77. 3 0
      wxcomponents/vant/dist/calendar/components/month/index.json
  78. 192 0
      wxcomponents/vant/dist/calendar/components/month/index.vue
  79. 39 0
      wxcomponents/vant/dist/calendar/components/month/index.wxml
  80. 71 0
      wxcomponents/vant/dist/calendar/components/month/index.wxs
  81. 0 0
      wxcomponents/vant/dist/calendar/components/month/index.wxss
  82. 1 0
      wxcomponents/vant/dist/calendar/index.d.ts
  83. 356 0
      wxcomponents/vant/dist/calendar/index.js
  84. 10 0
      wxcomponents/vant/dist/calendar/index.json
  85. 384 0
      wxcomponents/vant/dist/calendar/index.vue
  86. 26 0
      wxcomponents/vant/dist/calendar/index.wxml
  87. 37 0
      wxcomponents/vant/dist/calendar/index.wxs
  88. 1 0
      wxcomponents/vant/dist/calendar/index.wxss
  89. 12 0
      wxcomponents/vant/dist/calendar/utils.d.ts
  90. 83 0
      wxcomponents/vant/dist/calendar/utils.js
  91. 25 0
      wxcomponents/vant/dist/calendar/utils.wxs
  92. 1 0
      wxcomponents/vant/dist/card/index.d.ts
  93. 49 0
      wxcomponents/vant/dist/card/index.js
  94. 6 0
      wxcomponents/vant/dist/card/index.json
  95. 105 0
      wxcomponents/vant/dist/card/index.vue
  96. 56 0
      wxcomponents/vant/dist/card/index.wxml
  97. 1 0
      wxcomponents/vant/dist/card/index.wxss
  98. 1 0
      wxcomponents/vant/dist/cascader/index.d.ts
  99. 208 0
      wxcomponents/vant/dist/cascader/index.js
  100. 8 0
      wxcomponents/vant/dist/cascader/index.json

+ 1 - 0
App.vue

@@ -151,6 +151,7 @@
 	}
 </script>
 <style>
+	@import '/wxcomponents/vant/dist/common/index.wxss';
 	@import url("@/plugin/animate/animate.min.css");
 	@import 'static/css/base.css';
 	@import 'static/iconfont/iconfont.css';

+ 30 - 0
api/sleep/equ.js

@@ -0,0 +1,30 @@
+import request from "@/utils/request.js";
+
+// 会员所有绑定设备列表接口
+export function getEquList(data) {
+  return request.get("app-api/member/user-device-bind/bind-list", data, {
+  });
+}
+export function bindEqu(data) {
+  return request.post('app-api/member/user-device-bind/bind', data, {
+    noAuth: true 
+  });
+}
+// 获取关系列表接口
+export function getDetailList(data) {
+  return request.get("app-api/member/user-relation/detail-list", data, {
+    noAuth: true 
+  });
+}
+// 关系列表创建
+export function createRelation(data) {
+  return request.post('app-api/member/user-relation/create-relation', data, {
+    noAuth: true 
+  });
+}
+// 会员设置默认绑定设备
+export function bindDefaultEqu(data) {
+  return request.post('app-api/member/user-device-bind/bind-default', data, {
+    noAuth: true 
+  });
+}

+ 32 - 0
api/sleep/index.js

@@ -0,0 +1,32 @@
+import request from "@/utils/request2.js";
+
+export function getHrInfo(data) {
+  return request.post("get/new/health-hr", data);
+}
+export function geth5url(data) {
+  return request.post("get/new/report/h5url", data);
+}
+
+// export function getAfterSale(id) {
+//   return request.get("app-api/trade/after-sale/get", {
+//     id
+//   });
+// }
+
+// export function getApplyingAfterSaleCount() {
+//   return request.get("app-api/trade/after-sale/get-applying-count");
+// }
+
+// export function getAfterSalePage(data) {
+//   return request.get("app-api/trade/after-sale/page", data);
+// }
+
+
+
+// export function cancelAfterSale(id) {
+//   return request.delete("app-api/trade/after-sale/cancel?id=" + id);
+// }
+
+// export function deliveryAfterSale(data) {
+//   return request.put("app-api/trade/after-sale/delivery", data);
+// }

+ 1 - 1
config/app.js

@@ -1,5 +1,5 @@
 
-let domain = 'http://apif.java.crmeb.net'
+let domain = 'http://192.168.110.5:48080'
 // let domain = 'http://127.0.0.1:48080'
 
 module.exports = {

+ 3 - 1
libs/login.js

@@ -38,7 +38,8 @@ export function _toLogin(push, pathLogin) {
 		} else {
 			if (['/pages/user/index'].indexOf(login_back_url) === -1) {
 				uni.navigateTo({
-					url: '/pages/users/wechat_login/index'
+					// url: '/pages/users/wechat_login/index'
+					url: '/pages/users/login/index'
 				})
 			}
 		}
@@ -55,6 +56,7 @@ export function _toLogin(push, pathLogin) {
 		// #ifdef MP
     uni.navigateTo({
       url: '/pages/users/wechat_login/index'
+	  // url: '/pages/users/login/index'
     })
 		// #endif
 	}

+ 3 - 1
manifest.json

@@ -66,9 +66,11 @@
             "postcss" : true,
             "es6" : true
         },
+		"requiredPrivateInfos":["getLocation"],
+		
         "permission" : {
             "scope.userLocation" : {
-                "desc" : "你的位置信息将用于和门店的距离长度"
+                "desc" : "你的位置信息将用于位置接口的效果展示"
             }
         },
         // "plugins" : {

+ 24 - 436
package-lock.json

@@ -1,447 +1,35 @@
 {
+  "name": "yyky_new_app",
+  "lockfileVersion": 2,
   "requires": true,
-  "lockfileVersion": 1,
-  "dependencies": {
-    "ansi-regex": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
-    },
-    "ansi-styles": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
-    },
-    "babel-code-frame": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-      "requires": {
-        "chalk": "^1.1.3",
-        "esutils": "^2.0.2",
-        "js-tokens": "^3.0.2"
-      }
-    },
-    "babel-core": {
-      "version": "6.26.3",
-      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
-      "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
-      "requires": {
-        "babel-code-frame": "^6.26.0",
-        "babel-generator": "^6.26.0",
-        "babel-helpers": "^6.24.1",
-        "babel-messages": "^6.23.0",
-        "babel-register": "^6.26.0",
-        "babel-runtime": "^6.26.0",
-        "babel-template": "^6.26.0",
-        "babel-traverse": "^6.26.0",
-        "babel-types": "^6.26.0",
-        "babylon": "^6.18.0",
-        "convert-source-map": "^1.5.1",
-        "debug": "^2.6.9",
-        "json5": "^0.5.1",
-        "lodash": "^4.17.4",
-        "minimatch": "^3.0.4",
-        "path-is-absolute": "^1.0.1",
-        "private": "^0.1.8",
-        "slash": "^1.0.0",
-        "source-map": "^0.5.7"
-      }
-    },
-    "babel-generator": {
-      "version": "6.26.1",
-      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
-      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
-      "requires": {
-        "babel-messages": "^6.23.0",
-        "babel-runtime": "^6.26.0",
-        "babel-types": "^6.26.0",
-        "detect-indent": "^4.0.0",
-        "jsesc": "^1.3.0",
-        "lodash": "^4.17.4",
-        "source-map": "^0.5.7",
-        "trim-right": "^1.0.1"
-      }
-    },
-    "babel-helpers": {
-      "version": "6.24.1",
-      "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
-      "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
-      "requires": {
-        "babel-runtime": "^6.22.0",
-        "babel-template": "^6.24.1"
-      }
-    },
-    "babel-messages": {
-      "version": "6.23.0",
-      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
-      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
-      "requires": {
-        "babel-runtime": "^6.22.0"
-      }
-    },
-    "babel-register": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
-      "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
-      "requires": {
-        "babel-core": "^6.26.0",
-        "babel-runtime": "^6.26.0",
-        "core-js": "^2.5.0",
-        "home-or-tmp": "^2.0.0",
-        "lodash": "^4.17.4",
-        "mkdirp": "^0.5.1",
-        "source-map-support": "^0.4.15"
-      }
-    },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "requires": {
-        "core-js": "^2.4.0",
-        "regenerator-runtime": "^0.11.0"
-      }
-    },
-    "babel-template": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
-      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
-      "requires": {
-        "babel-runtime": "^6.26.0",
-        "babel-traverse": "^6.26.0",
-        "babel-types": "^6.26.0",
-        "babylon": "^6.18.0",
-        "lodash": "^4.17.4"
-      }
-    },
-    "babel-traverse": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
-      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
-      "requires": {
-        "babel-code-frame": "^6.26.0",
-        "babel-messages": "^6.23.0",
-        "babel-runtime": "^6.26.0",
-        "babel-types": "^6.26.0",
-        "babylon": "^6.18.0",
-        "debug": "^2.6.8",
-        "globals": "^9.18.0",
-        "invariant": "^2.2.2",
-        "lodash": "^4.17.4"
-      }
-    },
-    "babel-types": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
-      "requires": {
-        "babel-runtime": "^6.26.0",
-        "esutils": "^2.0.2",
-        "lodash": "^4.17.4",
-        "to-fast-properties": "^1.0.3"
-      }
-    },
-    "babylon": {
-      "version": "6.18.0",
-      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
-      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
-    },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "chalk": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-      "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-      "requires": {
-        "ansi-styles": "^2.2.1",
-        "escape-string-regexp": "^1.0.2",
-        "has-ansi": "^2.0.0",
-        "strip-ansi": "^3.0.0",
-        "supports-color": "^2.0.0"
-      }
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-    },
-    "convert-source-map": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
-      "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
-      "requires": {
-        "safe-buffer": "~5.1.1"
-      }
-    },
-    "core-image-xhr": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/core-image-xhr/-/core-image-xhr-1.0.3.tgz",
-      "integrity": "sha1-khHXtcQSGa9atpuThMoqR9VytHY="
-    },
-    "core-js": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
-      "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
-    },
-    "daycaca": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/daycaca/-/daycaca-1.0.11.tgz",
-      "integrity": "sha512-2SJTpnpmxUGVWbFPTRhaZLvisCD7bYjvuFpLAhjfAAvtnBb26dAqIqaZ9Jq8yvSlugpEGY+v/YXHXGP3paVV9A=="
-    },
-    "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "requires": {
-        "ms": "2.0.0"
-      }
-    },
-    "detect-indent": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
-      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
-      "requires": {
-        "repeating": "^2.0.0"
-      }
-    },
-    "dom7": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/dom7/-/dom7-2.1.3.tgz",
-      "integrity": "sha512-QTxHHDox+M6ZFz1zHPAHZKI3JOHY5iY4i9BK2uctlggxKQwRhO3q3HHFq1BKsT25Bm/ySSj70K6Wk/G4bs9rMQ==",
-      "requires": {
-        "ssr-window": "^1.0.1"
-      }
-    },
-    "emoji-awesome": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/emoji-awesome/-/emoji-awesome-0.0.2.tgz",
-      "integrity": "sha512-ggortYTr4+f4Jqp/R3vV9FAec+wRkIyRM458LUrv81mKQSKIJW9+xDlbqHsUpMeNKCLG45RsbbCyprrOoGZ6UQ=="
-    },
-    "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
-    },
-    "esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
-    },
-    "globals": {
-      "version": "9.18.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
-      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
-    },
-    "has-ansi": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
-      "requires": {
-        "ansi-regex": "^2.0.0"
-      }
-    },
-    "home-or-tmp": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
-      "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
-      "requires": {
-        "os-homedir": "^1.0.0",
-        "os-tmpdir": "^1.0.1"
-      }
-    },
-    "invariant": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-      "requires": {
-        "loose-envify": "^1.0.0"
-      }
-    },
-    "is-finite": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
-      "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w=="
-    },
-    "js-tokens": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
-    },
-    "jsesc": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
-      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
-    },
-    "json5": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
-      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
-    },
-    "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
-    },
-    "loose-envify": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
-      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
-      "requires": {
-        "js-tokens": "^3.0.0 || ^4.0.0"
-      }
-    },
-    "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-      "requires": {
-        "brace-expansion": "^1.1.7"
+  "packages": {
+    "": {
+      "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
+        "@vant/weapp": "^1.11.6"
       }
     },
-    "minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
-    },
-    "mkdirp": {
-      "version": "0.5.5",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-      "requires": {
-        "minimist": "^1.2.5"
-      }
-    },
-    "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-    },
-    "os-homedir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
-    },
-    "os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
-    },
-    "path-is-absolute": {
+    "node_modules/@amap/amap-jsapi-loader": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
-    },
-    "private": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
-      "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+      "resolved": "https://registry.npmjs.org/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
     },
-    "regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
-    },
-    "repeating": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
-      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
-      "requires": {
-        "is-finite": "^1.0.0"
-      }
-    },
-    "safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-    },
-    "slash": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
-    },
-    "source-map": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
-    },
-    "source-map-support": {
-      "version": "0.4.18",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
-      "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
-      "requires": {
-        "source-map": "^0.5.6"
-      }
-    },
-    "ssr-window": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-1.0.1.tgz",
-      "integrity": "sha512-dgFqB+f00LJTEgb6UXhx0h+SrG50LJvti2yMKMqAgzfUmUXZrLSv2fjULF7AWGwK25EXu8+smLR3jYsJQChPsg=="
-    },
-    "strip-ansi": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-      "requires": {
-        "ansi-regex": "^2.0.0"
-      }
-    },
-    "supports-color": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-    },
-    "swiper": {
-      "version": "5.3.8",
-      "resolved": "https://registry.npmjs.org/swiper/-/swiper-5.3.8.tgz",
-      "integrity": "sha512-bCxrayTgzC2bZBRuFwAx7T4exWeHqMADBpcuTQ7PNCOIIzJRPqNh4ySIvW06LEEU3Q0KncaNre4hrn+jXcWivQ==",
-      "requires": {
-        "dom7": "^2.1.3",
-        "ssr-window": "^1.0.1"
-      }
-    },
-    "to-fast-properties": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
-      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
-    },
-    "trim-right": {
+    "node_modules/@vant/weapp": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.11.6.tgz",
+      "integrity": "sha512-a3heReWYT2gNdsyj6x1hBwsM8V8NrjcPAmle86NH2CD2V/i/h0le75piW6KntSfOPCwekVWMBKhysNrBpJeKdw=="
+    }
+  },
+  "dependencies": {
+    "@amap/amap-jsapi-loader": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
-      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
-    },
-    "vue": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
-      "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
+      "resolved": "https://registry.npmjs.org/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
     },
-    "vue-awesome-swiper": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/vue-awesome-swiper/-/vue-awesome-swiper-4.1.1.tgz",
-      "integrity": "sha512-50um10t6N+lJaORkpwSi1wWuMmBI1sgFc9Znsi5oUykw2cO5DzLaBHcO2JNX21R+Ue4TGoIJDhhxjBHtkFrTEQ=="
-    },
-    "vue-core-image-upload": {
-      "version": "2.4.11",
-      "resolved": "https://registry.npmjs.org/vue-core-image-upload/-/vue-core-image-upload-2.4.11.tgz",
-      "integrity": "sha512-He0OcNqUaL2yHQebFwk4IxLr1Q8m1S7u8zTUek7pMaOUHW76MXOOn6sHoJMruURNvsv3SyeqFEt4N7JQBnMviA==",
-      "requires": {
-        "babel-core": "^6.26.0",
-        "core-image-xhr": "^1.0.3",
-        "daycaca": "^1.0.6",
-        "vue": "^2.5.13"
-      }
+    "@vant/weapp": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.11.6.tgz",
+      "integrity": "sha512-a3heReWYT2gNdsyj6x1hBwsM8V8NrjcPAmle86NH2CD2V/i/h0le75piW6KntSfOPCwekVWMBKhysNrBpJeKdw=="
     }
   }
 }

+ 6 - 0
package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
+    "@vant/weapp": "^1.11.6"
+  }
+}

+ 54 - 2
pages.json

@@ -3,7 +3,7 @@
 		{
 			"path": "pages/index/index",
 			"style": {
-				"navigationBarTitleText": "首页",
+				"navigationBarTitleText": "",
 				"navigationStyle": "custom"
 				// "app-plus": {
 				// 	"scrollIndicator": false //禁用原生导航栏
@@ -45,6 +45,40 @@
 				"navigationBarTitleText": "找回密码"
 			}
 		},
+		{
+			"path": "pages/equ_list/index",
+			"style": {
+				"navigationBarTitleText": "设备列表",
+				"enablePullDownRefresh": false
+			}
+		
+		}, {
+			"path": "pages/equ_list/add_equ",
+			"style": {
+				"navigationBarTitleText": "添加设备",
+				"navigationBarBackgroundColor": "#F35546",
+				"navigationBarTextStyle": "#fff",
+				"enablePullDownRefresh": false
+			}
+		
+		},
+		{
+			"path": "pages/equ_list/choose",
+			"style": {
+				"navigationBarTitleText": "选择关系",
+				"navigationBarBackgroundColor": "#F35546",
+				"navigationBarTextStyle": "#fff",
+				"enablePullDownRefresh": false
+			}
+		
+		}, {
+			"path": "pages/equ_list/bind",
+			"style": {
+				"navigationBarTitleText": "",
+				"navigationBarBackgroundColor": "#F35546",
+				"enablePullDownRefresh": false
+			}
+		},
 		// #ifdef H5
 		{
 			"path": "pages/customer_list/index",
@@ -481,6 +515,15 @@
 					"navigationBarTitleText": "精品推荐"
 				}
 			}]
+		},{
+			"root": "pages/index/condition",
+			"name": "condition",
+			"pages": [{
+				"path": "heart_rate/index",
+				"style": {
+					"navigationBarTitleText": ""
+				}
+			}]
 		}, {
           "root": "pages/goods",
           "name": "goods",
@@ -507,7 +550,16 @@
 		"titleNView": false,
 		"rpxCalcMaxDeviceWidth": 960,
 		"rpxCalcBaseDeviceWidth": 375,
-		"rpxCalcIncludeWidth": 750
+		"rpxCalcIncludeWidth": 750,
+		"usingComponents":{
+			"van-popup": "/wxcomponents/vant/dist/popup/index",
+			"van-calendar": "/wxcomponents/vant/dist/calendar/index",
+			"van-tabs": "/wxcomponents/vant/dist/tabs/index",
+			"van-tab": "/wxcomponents/vant/dist/tab/index",
+			"van-field": "/wxcomponents/vant/dist/field/index",
+			"van-dialog": "/wxcomponents/vant/dist/dialog/index"
+			// "van-form": "/wxcomponents/vant/dist/form/index"
+		}
 	},
 	"tabBar": {
 		"color": "#282828",

+ 253 - 0
pages/equ_list/add_equ.vue

@@ -0,0 +1,253 @@
+<template>
+	<view class="box">
+		<van-tabs v-model="active">
+			<van-tab title="扫码">
+				<view class="scan">
+					<view class="scan_box">
+						<image src="/static/img/scan.png" mode=""></image>
+					</view>
+					<view class="scan_btn" @click="scanQRCode">扫码</view>
+					<view class="warn_text">
+						<view class="text">
+							请确保设备插卡并且处于开机状态,SIM卡有效并且开通GPRS
+							业务
+						</view>
+					</view>
+				</view>
+			</van-tab>
+			<van-tab title="输入">
+				<view class="input">
+					<view class="text_box">
+						<input type="text" placeholder="请输入设备ID号" v-model="text">
+					</view>
+					<view class="scan_btn" @click="next">
+						<!-- <view class=""> -->
+						下一步
+						<!-- </view> -->
+					</view>
+					<view class="warn_text">
+						<view class="text">
+							请确保设备插卡并且处于开机状态,SIM卡有效并且开通GPRS
+							业务
+						</view>
+					</view>
+				</view>
+			</van-tab>
+
+
+		</van-tabs>
+		<!-- <u-tabs :list="list" :current="current" @click="click" lineColor="#F35546" lineWidth="88" lineHeight="4"
+			bg-color="#fff"></u-tabs>
+		<view class="scan" v-if="current === 0">
+			<view class="scan_box">
+				<image src="/static/image/scan.png" mode=""></image>
+			</view>
+			<view class="scan_btn" @click="scanQRCode">扫码</view>
+			<view class="warn_text">
+				<view class="text">
+					请确保设备插卡并且处于开机状态,SIM卡有效并且开通GPRS
+					业务
+				</view>
+			</view>
+		</view>
+		<view class="input" v-if="current === 1">
+			<view class="text_box">
+				<input type="text" placeholder="请输入设备ID号" v-model="text">
+			</view>
+			<view class="scan_btn" @click="next">
+				下一步
+			</view>
+			<view class="warn_text">
+				<view class="text">
+					请确保设备插卡并且处于开机状态,SIM卡有效并且开通GPRS
+					业务
+				</view>
+			</view>
+		</view> -->
+	</view>
+</template>
+
+<script>
+	
+	export default {
+		data() {
+			return {
+				list: [{
+					name: '扫码'
+				}, {
+					name: '输入'
+				}],
+				current: 0,
+				text: ''
+			}
+		},
+		onShow: function() {
+
+		},
+		methods: {
+			click(item) {
+				this.current = item.index;
+			},
+			next() {
+				console.log(this.text, 777);
+				if (this.text) {
+					uni.navigateTo({
+						url: `/pages/equ_list/bind?deviceCode=${this.text}`
+					})
+				} else {
+					this.$util.Tips({
+						title: '请输入设备ID号'
+					});
+				}
+			},
+			scanQRCode() {
+				uni.scanCode({
+					success: (res) => {
+						console.log(res); // 打印扫码结果
+						// 在这里可以对扫码结果进行处理
+						uni.navigateTo({
+							url: `/pages/equ_list/bind?deviceCode=${res.result}`
+						})
+					},
+					fail: (res) => {
+						console.log(res);
+						// 处理扫码失败的情况
+						this.$util.Tips({
+							title:'扫码失败',
+							icon:'error'
+						})
+					}
+				});
+			}
+			// uni.scanCode({
+			// 	success: res => {
+			// 		let code = null
+			// 		this.modelCode = null
+			// 		if (res.result && res.result.indexOf('SN') == -1) {
+			// 			code = +res.result
+			// 		} else if (res.result && res.result.indexOf('"SN"') != -1) {
+			// 			res.result = JSON.parse(res.result)
+			// 			code = +res.result.SN
+			// 		} else {
+			// 			return uni.showToast({
+			// 				icon: 'none',
+			// 				title: '非法的TBOX编号',
+			// 			})
+			// 		}
+			// 		const codeType = typeof code === 'number' && !isNaN(code)
+			// 		if (!codeType) {
+			// 			return uni.showToast({
+			// 				icon: 'none',
+			// 				title: '非法的TBOX编号',
+			// 			})
+			// 		}
+			// 		// 数据重置
+			// 		this.resetData()
+			// 		this.tboxCode = code
+			// 		this.scanning && this.getTBoxInfo(code)
+			// 	},
+			// 	fail: function() {
+			// 		this.scanning = true
+			// 		uni.hideLoading()
+			// 	},
+			// })
+		}
+	}
+</script>
+
+<style lang="scss">
+	.box {
+		width: 750rpx;
+		height: 100vh;
+		background-color: #fff;
+
+		.scan {
+			padding: 55rpx 32rpx 477rpx;
+			text-align: center;
+			background-color: #F7F7F7;
+
+			.scan_box {
+				image {
+					width: 386rpx;
+					height: 533rpx;
+				}
+			}
+
+			.scan_btn {
+				height: 98rpx;
+				line-height: 98rpx;
+				background: #F35546;
+				border-radius: 9rpx;
+				margin-top: 79rpx;
+				font-size: 32rpx;
+				font-weight: 500;
+				color: #FFFFFF;
+			}
+
+			.warn_text {
+				font-size: 24rpx;
+				font-weight: 500;
+				color: #777777;
+				margin-top: 42rpx;
+				text-align: start;
+				line-height: 33rpx;
+			}
+
+		}
+
+		.input {
+			padding: 55rpx 32rpx 477rpx;
+			// text-align: center;
+			height: 100%;
+			background-color: #F7F7F7;
+
+			.text_box {
+				background-color: #fff;
+				height: 98rpx;
+				line-height: 98rpx;
+				padding: 0 32rpx;
+
+				input {
+					width: 100%;
+					height: 100%;
+					// width: 386rpx;
+					// height: 533rpx;
+				}
+			}
+
+			.scan_btn {
+				height: 98rpx;
+				line-height: 98rpx;
+				text-align: center;
+				background: #F35546;
+				border-radius: 9rpx;
+				margin-top: 131rpx;
+				font-size: 32rpx;
+				font-weight: 500;
+				color: #FFFFFF;
+			}
+
+			.warn_text {
+				font-size: 24rpx;
+				font-weight: 500;
+				color: #777777;
+				margin-top: 42rpx;
+				text-align: start;
+				line-height: 33rpx;
+			}
+
+		}
+	}
+
+	/* ::v-deep .u-tabs__wrapper__nav{
+		justify-content: center !important;
+	} */
+	::v-deep .u-tabs__wrapper__nav__item[data-v-0de61367] {
+		width: 375rpx;
+	}
+
+	::v-deep uni-input[data-v-1b9e2be9] {
+		width: 100% !important;
+		height: 100% !important;
+	}
+</style>

+ 392 - 0
pages/equ_list/bind.vue

@@ -0,0 +1,392 @@
+<template>
+	<view class="page">
+		<view class="content_box">
+			<van-field v-model="formData.deviceCode" readonly name="ID号" label="ID号" placeholder="ID号" />
+			<view class="content">
+				<van-form @submit="bindEqu" ref="formData" :model="formData" label-width="48" :colon="true">
+					<van-field class="btn" v-model="formData.photo" name="照片" label="照片" placeholder="照片" readonly
+						@click.native.stop.prevent="uploadpic" input-align="right">
+						<template #button>
+							<image src="/static/img/arrow.png" mode=""></image>
+						</template>
+					</van-field>
+					<van-field v-model="formData.nickName" name="姓名" label="姓名" placeholder="请输入姓名"
+						:rules="[{ required: true, message: '请填写姓名' }]" @change="formData.nickName = $event.detail" />
+
+					<van-field v-model="formData.cardNumber" name="证件号" label="证件号" placeholder="请输入证件号"
+						:rules="[{ required: true, message: '请填写证件号' }]" @blur="cardNumberBlur"
+						@change="formData.cardNumber = $event.detail" />
+					<van-field class="btn" readonly clickable name="picker" :value="formData.sexValue" label="性别"
+						placeholder="请选择性别">
+						<!-- @click.native.stop.prevent="showPickerFn" -->
+						<template #button>
+							<image src="/static/img/arrow.png" mode=""></image>
+						</template>
+					</van-field>
+					<van-field class="btn" readonly clickable name="calendar" :value="formData.birthday" label="生日"
+						placeholder="年/月/日" @click.native.stop.prevent="showCalendarFn">
+						<template #button>
+							<image src="/static/image/calendar.png" mode=""></image>
+						</template>
+					</van-field>
+					<van-field v-model="formData.tel" name="手机号" label="手机号" placeholder="请输入手机号"
+						:rules="[{ required: true, message: '请填写手机号' }]" @blur="telBlur" @change="formData.tel = $event.detail" />
+
+				</van-form>
+
+				<van-popup :show="showPicker" position="bottom">
+					<van-picker show-toolbar :columns="columns" @confirm="pickerConfirm" @cancel="showPicker = false" />
+				</van-popup>
+				<van-popup :show="showCalendar" position="bottom">
+					<van-datetime-picker @cancel="showCalendar=false" @confirm="calendarConfirm" :value="currentDay"
+						type="date" :min-date="minDate" />
+					<!-- :min-date="minDate" -->
+				</van-popup>
+			</view>
+			<van-field readonly class="btn" v-model="formData.relationValue" label="关系" clearable
+				placeholder="请选择与设备使用者关系" @click.native.stop.prevent="goChooseRelation">
+				<template #button>
+					<image src="/static/img/arrow.png" mode=""></image>
+				</template>
+			</van-field>
+			
+		</view>
+		<view class="footer_btn">
+			<view class="footer" @click="bindEqu('formData')">
+				绑定
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import * as infoApi from '@/api/sleep/equ.js';
+	import {
+		mapGetters
+	} from "vuex";
+	export default {
+		data() {
+			return {
+				formData: {
+					photo:'',
+					deviceCode: '',
+					nickName: '',
+					relationId: null,
+					relationValue: '',
+					passWord: '',
+					sex: null, //1 男 2女
+					sexValue: '',
+					birthday: '',
+					cardNumber:'',
+					tel:''
+				},
+
+				username: '',
+				password: '',
+				showCalendar: false,
+				showPicker: false,
+				columns: ['男', '女'],
+				currentDay: new Date().getTime(),
+				minDate: new Date(1900, 0, 1).getTime(),
+				id: '',
+				list: [],
+			}
+		},
+		computed: mapGetters(['uid', 'deviceId']),
+		async onLoad(options) {
+			console.log(options, 88888);
+			this.formData.deviceCode = options.deviceCode ? options.deviceCode : ''
+			if (options.id) {
+				this.id = options.id
+				await this.getList()
+				this.getBindDetailInfo()
+			}
+		},
+		methods: {
+			getList() {
+				infoApi.getDetailList().then(res => {
+					let obj = {
+						name: '自定义',
+						avatar: 'https://employmenter.oss-cn-beijing.aliyuncs.com/%E9%80%89%E6%8B%A9%E5%85%B3%E7%B3%BB_slices/%E7%BC%96%E7%BB%84%2013%402x.png',
+						id: 99
+					}
+					this.list = [...res.data, obj]
+				})
+			},
+			getBindDetailInfo() {
+				infoApi.getBindDetailInfo({
+					id: this.id
+				}).then(res => {
+					if (res.code === 0) {
+						this.formData = res.data
+						this.formData.sexValue = res.data.sex === 1 ? '男' : '女'
+						this.formData.relationValue = this.list.find(item => item.id === res.data.relationId).name
+					}
+				})
+			},
+			bindEqu() {
+				console.log(this.$refs.formData, 555);
+				// this.$refs.formData.validate().then(() => {
+				// 	this.$toast.success('提交成功')
+				// }).catch(() => {
+				// 	this.$toast.fail('提交失败')
+				// })
+				const {
+					photo,
+					nickName,
+					cardNumber,
+					relationId,
+					passWord,
+					sex,
+					birthday,
+					tel
+				} = this.formData
+				// if(photo == '') {
+				// 	this.$util.Tips({
+				// 		title: '请上传图片',
+				// 		icon: 'none'
+				// 	})
+				// }else 
+				if (nickName == '') {
+					this.$util.Tips({
+						title: '请填写姓名',
+						icon: 'none'
+					})
+				} else if (cardNumber == '') {
+				 	this.$util.Tips({
+				 		title: '请填写证件号',
+				 		icon: 'none'
+				 	})
+				 } else if (tel == '') {
+				 	this.$util.Tips({
+				 		title: '请填写手机号',
+				 		icon: 'none'
+				 	})
+				 }else if (relationId == null) {
+					this.$util.Tips({
+						title: '请选择与设备使用者关系',
+						icon: 'none'
+					})
+				} else {
+					let params = {
+						deviceId: this.deviceId,
+						...this.formData,
+						birthday: this.formData.birthday + ' ' + '00:00:00',
+						memberId: this.uid
+					}
+					console.log(params, 7778);
+					infoApi.bindEqu(params).then(res => {
+							this.$util.Tips({
+								title: '绑定成功',
+								icon: 'success'
+							}, () => {
+								uni.navigateBack({
+									delta: 2
+								})
+							})
+
+						})
+						.catch(err => {
+							console.log(err);
+							return this.$util.Tips({
+								title: err,
+								// icon: 'error'
+							});
+						});
+
+				}
+
+			},
+			idCardValidator(rule, value, callback) {
+				const regex =
+					/^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
+				if (!value || value === '' || value === undefined) {
+					callback(new Error('请输入证件号码'));
+				} else if ((value.length === 15 || value.length === 18) && regex.test(value)) {
+					callback();
+				} else {
+					callback(new Error('请输入正确的证件号码'));
+				}
+			},
+			cardNumberBlur(e) {
+				console.log(e.detail.value, 66666)
+				// 调用身份证号验证方法
+				this.idCardValidator({}, e.detail.value, (error) => {
+					if (error) {
+						// 这里可以根据验证结果处理逻辑
+						this.$util.Tips({
+							title: error.message,
+							icon: 'none'
+						})
+					} else {
+						console.log('身份证号格式正确');
+						// 这里可以根据验证结果处理逻辑
+						const {
+							sex,
+							sexValue,
+							birthday
+						} = this.parseIDCard(e.detail.value);
+						console.log('性别:', sexValue);
+						console.log('出生年月日:', birthday);
+						this.$set(this.formData,'sex',sex)
+						this.$set(this.formData,'sexValue',sexValue)
+						this.$set(this.formData,'birthday',birthday)
+					}
+				});
+			},
+			telBlur(e){
+				if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(e.detail.value))) {
+					return this.$util.Tips({
+					  title: '请输入正确的手机号码!'
+					});
+				}
+			},
+			parseIDCard(idCard) {
+				let birthday = '';
+				let sex = '';
+				let sexValue = '';
+
+				if (idCard.length === 15) {
+					birthday = '19' + idCard.substring(6, 12);
+					sexValue = parseInt(idCard.substr(14, 1)) % 2 === 0 ? '女' : '男';
+				} else if (idCard.length === 18) {
+					birthday = idCard.substring(6, 14);
+					sexValue = parseInt(idCard.substr(16, 1)) % 2 === 0 ? '女' : '男';
+					sex = parseInt(idCard.substr(16, 1)) % 2 === 0 ? '2' : '1';
+				}
+
+				// 将出生年月日格式化为年-月-日
+				const year = birthday.substring(0, 4);
+				const month = birthday.substring(4, 6);
+				const day = birthday.substring(6, 8);
+				const formattedBirthday = year + '-' + month + '-' + day;
+
+				console.log('性别:', sexValue);
+				console.log('出生年月日:', formattedBirthday);
+
+				return {
+					sex:sex,
+					sexValue: sexValue,
+					birthday: formattedBirthday
+				};
+			},
+			/**
+			 * 上传文件
+			 */
+			uploadpic: function() {
+				this.$util.uploadImageOne({}, res => {
+					this.newAvatar = res.data;
+				});
+			},
+			getValue(item) {
+				console.log(item, 112233);
+				this.formData.relationId = item.id
+				this.formData.relationValue = item.name
+			},
+			goChooseRelation() {
+				uni.navigateTo({
+					url: '/pages/equ_list/choose'
+				})
+			},
+			showCalendarFn() {
+				this.showCalendar = true
+			},
+			showPickerFn() {
+				this.showPicker = true
+			},
+			pickerConfirm(value) {
+				console.log(value, 66666);
+				this.formData.sex = value.detail.index + 1;
+				this.formData.sexValue = value.detail.value;
+				this.showPicker = false;
+			},
+			calendarConfirm(date) {
+				this.formData.birthday = this.formatDate(date.detail)
+				this.showCalendar = false;
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+	.avatar_box {
+		height: 342rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		background-color: #F35546;
+
+		image {
+			width: 210rpx;
+			height: 210rpx;
+		}
+
+	}
+
+	.page {
+		// padding: 60rpx 30rpx;
+	}
+
+	.content_box {
+		background-color: #F7F7F7;
+		    padding: 60rpx 30rpx;
+
+		.btn {
+			image {
+				width: 32rpx;
+				height: 32rpx;
+			}
+		}
+
+		.content {
+			/* height: 588rpx; */
+			background-color: #fff;
+			margin-top: 32rpx;
+			// padding: 0 32rpx;
+			// height: calc(100vh - 342rpx);
+			margin-bottom: 30rpx;
+			border-radius: 10rpx;
+			overflow: hidden;
+
+			.btn {
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+	}
+	.footer_btn {
+		width: 100%;
+		height: 98rpx;
+		line-height: 98rpx;
+		position: fixed;
+		bottom: 68rpx;
+		color: #fff;
+		font-size: 32rpx;
+		padding: 32rpx;
+		box-sizing: border-box;
+	
+		.footer {
+			background: #F35546;
+			border-radius: 9rpx;
+			text-align: center;
+		}
+	
+	}
+
+	::v-deep uni-image {
+		width: 210rpx;
+		height: 210rpx;
+	}
+
+	// ::v-deep .van-field__label{
+	// 	font-size: 32rpx;
+	// 	font-weight: 500;
+	// 	color: #000000;
+	// }
+</style>

+ 196 - 0
pages/equ_list/choose.vue

@@ -0,0 +1,196 @@
+<template>
+	<view class="content">
+		<view class="top-box">
+			<view class="box-item" v-for="(item,index) in list" :key="index" @click="choose(item)">
+				<image :src="item.avatar" mode=""></image>
+				<text>{{item.name}}</text>
+			</view>
+		</view>
+		<!-- <view class="under-box">
+			<view class="btn">
+				确认
+			</view>
+		</view> -->
+		<van-dialog use-slot title="自定义" :show="showDialog" show-cancel-button="true" @close="showDialog=false"
+			@confirm="confirm">
+			<van-field class="chageName" :value="nameValue" :focus="true" placeholder="请输入"
+				@change="nameValue = $event.detail" />
+		</van-dialog>
+	</view>
+</template>
+
+<script>
+	import {
+		mapGetters
+	} from "vuex";
+	import * as infoApi from '@/api/sleep/equ.js';
+	export default {
+		data() {
+			return {
+				// list: [{
+				// 		src: '/pages/users/static/choose1.png',
+				// 		name: '爸爸',
+				// 		value: 1
+				// 	}, {
+				// 		src: '/pages/users/static/choose2.png',
+				// 		name: '妈妈',
+				// 		value: 2
+				// 	}, {
+				// 		src: '/pages/users/static/choose3.png',
+				// 		name: '儿子',
+				// 		value: 3
+				// 	}, {
+				// 		src: '/pages/users/static/choose4.png',
+				// 		name: '女儿',
+				// 		value: 4
+				// 	}, {
+				// 		src: '/pages/users/static/choose5.png',
+				// 		name: '爷爷',
+				// 		value: 5
+				// 	}, {
+				// 		src: '/pages/users/static/choose6.png',
+				// 		name: '奶奶',
+				// 		value: 6
+				// 	}, {
+				// 		src: '/pages/users/static/choose7.png',
+				// 		name: '姥爷',
+				// 		value: 7
+				// 	}, {
+				// 		src: '/pages/users/static/choose8.png',
+				// 		name: '姥姥',
+				// 		value: 8
+				// 	},
+				// 	{
+				// 		src: '/pages/users/static/vip04.png',
+				// 		name: '自定义',
+				// 		value: 9,
+				// 		id: 99
+				// 	},
+				// ],
+				list: [],
+				showDialog: false,
+				nameValue: '',
+			}
+		},
+		computed: mapGetters(['uid']),
+		onLoad() {
+			this.getList()
+		},
+		methods: {
+			getList() {
+				infoApi.getDetailList().then(res => {
+					let obj = {
+						name: '自定义',
+						avatar: 'https://employmenter.oss-cn-beijing.aliyuncs.com/%E9%80%89%E6%8B%A9%E5%85%B3%E7%B3%BB_slices/%E7%BC%96%E7%BB%84%2013%402x.png',
+						id: 99
+					}
+					this.list = [...res.data, obj]
+				})
+			},
+			confirm() {
+				console.log(this.nameValue, 777);
+				if (this.nameValue) {
+					infoApi.createRelation({
+						name: this.nameValue,
+						memberId: this.uid
+					}).then(res => {
+						if (res.code === 0) {
+							const item = {
+								name: this.nameValue,
+								id: res.data
+							}
+							this.goBack(item)
+						}
+					})
+					.catch(err => {
+						// close();
+						return this.$util.Tips({
+							title: err
+						});
+					});
+
+				}
+			},
+			goBack(item) {
+				// 1. 获取当前页面栈实例(此时最后一个元素为当前页)
+				let pages = getCurrentPages()
+
+				// 2. 上一页面实例
+				// 注意是length长度,所以要想得到上一页面的实例需要 -2
+				// 若要返回上上页面的实例就 -3,以此类推
+				let prevPage = pages[pages.length - 2]
+
+				// 3. 给上一页面实例绑定getValue()方法和参数(注意是$vm)
+				prevPage.$vm.getValue(item)
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			choose(item) {
+				if (item.id == 99) {
+					this.showDialog = true
+				} else {
+					this.goBack(item)
+				}
+
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+	.content {
+		position: relative;
+
+		.top-box {
+			padding: 61rpx 89rpx 0;
+			width: 100%;
+			height: auto;
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: space-between;
+			box-sizing: border-box;
+
+			.box-item {
+				width: 30%;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				justify-content: center;
+				margin-top: 55rpx;
+
+				image {
+					width: 118rpx;
+					height: 118rpx;
+				}
+
+				text {
+					font-size: 32rpx;
+					font-weight: 400;
+					color: #000000;
+					margin-top: 16rpx;
+				}
+			}
+		}
+
+		.under-box {
+			width: 100%;
+			position: fixed;
+			bottom: 0;
+			padding: 32rpx;
+			box-sizing: border-box;
+
+			.btn {
+				width: 100%;
+				height: 98rpx;
+				line-height: 98rpx;
+				font-size: 32rpx;
+				font-weight: 500;
+				color: #FFFFFF;
+				text-align: center;
+				border-radius: 9rpx;
+				background-color: #F35546;
+			}
+		}
+	}
+</style>

+ 563 - 0
pages/equ_list/index.vue

@@ -0,0 +1,563 @@
+<template>
+	<view>
+		<view >
+			<view class='address-management' :class='equipmentList.length === 0 ? "fff":""'>
+				<radio-group class="radio-group" @change="radioChange" v-if="equipmentList.length">
+					<view class='item borRadius14' v-for="(item,index) in equipmentList" :key="index">
+						<view class="content_box_top">
+							<u-avatar class="avatar" :src="item.relationVo.avatar" mode="square" :show-sex="true"
+								:sex-icon="item.sex === 1 ? 'male':'female'"
+								:icon-color="gender === 'male' ? '#409EFF' : '#F56C6C'"></u-avatar>
+							<view class='address' @click='goIndex(item.id,item.deviceCode)'>
+								<view class="address-left">
+									<view class='consignee'>
+										<view>昵称:{{ item.nickName }}</view>
+										<view class="online-box">
+											<image v-if="item.onlineForce||item.onlineStatus"
+												src="/static/image/online.png" mode=""></image>
+											<image v-if="!item.onlineForce&&!item.onlineStatus"
+												src="/static/image/offline.png" mode=""></image>
+										</view>
+										<!-- <text class='phone'>ID:{{item.deviceCode}}</text> -->
+									</view>
+									<text class='phone'>ID:{{item.deviceCode}}</text>
+									<!-- <view>收货地址:{{item.areaName}} {{item.detailAddress}}</view> -->
+								</view>
+								<image src="/static/image/arrow.png" mode=""></image>
+							</view>
+						</view>
+						<view class='operation acea-row row-between-wrapper'>
+							<!-- #ifndef MP -->
+							<radio class="radio" :value="index.toString()" :checked="item.status">
+								<text>设为默认</text>
+							</radio>
+							<!-- #endif -->
+							<!-- #ifdef MP -->
+							<radio class="radio" :value="index" :checked="item.status">
+								<text>设为默认</text>
+							</radio>
+							<!-- #endif -->
+							<view class='acea-row row-middle'>
+								<!-- <view @click='editAddress(item.id)'>
+								<text class='iconfont icon-bianji' />编辑
+							</view> -->
+								<view @click='delEquipment(item,index)'>
+									<text class='iconfont icon-shanchu' />删除
+								</view>
+							</view>
+						</view>
+					</view>
+				</radio-group>
+				<view class='loadingicon acea-row row-center-wrapper' v-if="equipmentList.length">
+					<text class='loading iconfont icon-jiazai' :hidden='!loading'></text>{{loadTitle}}
+				</view>
+				<view class='noCommodity' v-if="equipmentList.length < 1">
+					<view class='pictrue'>
+						<image src='/static/img/none.png'></image>
+					</view>
+				</view>
+				<view style='height:120rpx;'></view>
+			</view>
+			<view class="footer" @click="addEqu">
+				<image src="/static/img/addicon.png" mode=""></image>
+				<view>
+					添加设备
+				</view>
+			</view>
+		</view>
+		<!-- <view class="swiper" v-if="undeviceId">
+			<swiper indicator-dots="true" :autoplay="autoplay" :circular="circular" :interval="interval" :duration="duration"
+			 indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff" @change="handleSwiperChange">
+				<block v-for="(item,index) in imgUrls" :key="index">
+					<swiper-item>
+						<image :src="item.src" class="slide-image"></image>
+					</swiper-item>
+				</block>
+			</swiper>
+		</view> -->
+		<van-dialog id="van-dialog" />
+		<!-- <home></home> -->
+	</view>
+</template>
+<script>
+	// import Dialog from '../../wxcomponents/vant/dist/dialog/dialog';
+	import Dialog from '@/wxcomponents/vant/dist/dialog/dialog';
+	// import /wxcomponents/vant/dist/dialog/index
+	import * as infoApi from '@/api/sleep/equ.js';
+	import {
+		editAddress
+	} from '@/api/user.js';
+	// import {
+	// 	toLogin
+	// } from '@/libs/login.js';
+	import {
+		mapGetters
+	} from "vuex";
+	import home from '@/components/home';
+	import * as AddressApi from '@/api/member/address.js';
+	export default {
+		components: {
+			home
+		},
+		data() {
+			return {
+				// equipmentList: [{
+				// 	id: 11,
+				// 	name: '王艺涵',
+				// 	mobile: 177
+				// }, {
+				// 	id: 11,
+				// 	name: '王艺涵',
+				// 	mobile: 177
+				// }],
+				equipmentList: [],
+				loading: false,
+				loadTitle: '加载更多',
+
+				// TODO 芋艿:看看后面咋搞回来
+				preOrderNo: '',
+				cartId: '',
+				pinkId: 0,
+				couponId: 0,
+				bargain: false, // 是否是砍价
+				combination: false, // 是否是拼团
+				secKill: false, // 是否是秒杀
+				src: 'http://pic2.sc.chinaz.com/Files/pic/pic9/202002/hpic2119_s.jpg',
+				
+				autoplay: false,
+				circular: true,
+				interval: 3000,
+				duration: 500,
+				undeviceId:false,
+				imgUrls:[{src:'/static/image/0001.png'},{src:'/static/image/0002.png'},{src:'/static/image/0003.png'}]
+			};
+		},
+		computed: mapGetters(['uid', 'deviceId']),
+		watch: {
+			// isLogin: {
+			// 	handler: function(newV, oldV) {
+			// 		if (newV) {
+			// 			this.getUserAddress(true);
+			// 		}
+			// 	},
+			// 	deep: true
+			// }
+		},
+		onLoad(options) {
+			if (!this.deviceId) {
+				console.log('我没有deviceId');
+				this.undeviceId=true
+			}
+			// if (!this.isLogin) {
+			// 	toLogin();
+			// 	return;
+			// }
+			this.preOrderNo = options.preOrderNo || 0;
+			this.getEquipmentList();
+		},
+		onShow: function() {
+			this.getEquipmentList();
+		},
+		methods: {
+			// 轮播图改变事件
+			handleSwiperChange :function(e) {
+				console.log(e,666);
+				if(e.detail.current==0){
+					console.log('进来了等于0');
+					this.undeviceId=false
+				}
+      //  this.currentValChange = e.detail.current
+      //  console.log(this.currentValChange)
+   			// if (this.swiperChangeSelect) {
+   			// 	console.log("swiperChange")
+   			// 	console.log(e)
+   			// }
+   		},
+			/**
+			 * 获取地址列表
+			 */
+			getEquipmentList: function() {
+				if (this.loading) {
+					return;
+				}
+				this.loading = true;
+				this.loadTitle = '';
+				let params = {
+					memberId: this.uid
+				}
+				infoApi.getEquList(params).then(res => {
+					this.$set(this, 'equipmentList', res.data);
+					this.loadTitle = '我也是有底线的';
+					this.loading = false;
+				}).catch(err => {
+					this.loading = false;
+					this.loadTitle = '加载更多';
+				});
+			},
+			/**
+			 * 设置默认地址
+			 */
+			radioChange: function(e) {
+				const index = parseInt(e.detail.value);
+				const item = this.equipmentList[index];
+				if (item === undefined) {
+					return this.$util.Tips({
+						title: '您设置的默认地址不存在!'
+					});
+				}
+				infoApi.bindDefaultEqu({
+					memberId: this.uid,
+					id: item.id
+				}).then(res => {
+					if (res.code === 0 && res.data.bindCount === 1) {
+						for (let i = 0, len = this.equipmentList.length; i < len; i++) {
+							if (i === index) {
+								this.equipmentList[i].status = true;
+							} else {
+								this.equipmentList[i].status = false;
+							}
+						}
+						this.$util.Tips({
+							title: '设置成功',
+							icon: 'success'
+						}, () => {
+							this.$store.commit("DEVICE_ID", res.data.deviceId);
+							// this.$set(this, 'equipmentList', this.equipmentList);
+							this.getEquipmentList()
+						});
+					}
+				}).catch(err => {
+					return this.$util.Tips({
+						title: err
+					});
+				});
+			},
+			/**
+			 * 编辑地址
+			 */
+			editAddress: function(id) {
+				let cartId = this.cartId,
+					pinkId = this.pinkId,
+					couponId = this.couponId;
+				this.cartId = '';
+				this.pinkId = '';
+				this.couponId = '';
+				uni.navigateTo({
+					url: '/pages/users/user_address/index?id=' + id + '&cartId=' + cartId + '&pinkId=' +
+						pinkId + '&couponId=' +
+						couponId + '&secKill' + this.secKill + '&combination=' + this.combination +
+						'&bargain=' + this.bargain
+				})
+			},
+			/**
+			 * 删除设备
+			 */
+			delEquipment(item, index) {
+				const address = this.equipmentList[index];
+				if (address === undefined) {
+					return this.$util.Tips({
+						title: '您删除的地址不存在!'
+					});
+				}
+				Dialog.confirm({
+						title: '',
+						message: '是否确认删除此设备?',
+						context: this,
+					})
+					.then(() => {
+						let params = {
+							memberId: this.uid,
+							id: item.id
+						}
+						infoApi.bindDelete(params).then(res => {
+							this.$util.Tips({
+								title: '删除成功',
+								icon: 'success'
+							}, () => {
+								this.equipmentList.splice(index, 1);
+								this.getEquipmentList()
+							});
+						}).catch(err => {
+							return this.$util.Tips({
+								title: err
+							});
+						});
+					})
+					.catch(() => {
+						// on cancel
+					});
+
+
+			},
+			/**
+			 * 新增地址
+			 */
+			addAddress: function() {
+				this.cartId = '';
+				this.pinkId = '';
+				this.couponId = '';
+				uni.navigateTo({
+					url: '/pages/users/user_address/index?preOrderNo=' + this.preOrderNo
+				})
+			},
+
+			// TODO 芋艿:微信导入;
+			/**
+			 * 导入微信地址(小程序)
+			 */
+			getWxAddress: function() {
+				let that = this;
+				uni.authorize({
+					scope: 'scope.address',
+					success: function(res) {
+						uni.chooseAddress({
+							success: function(res) {
+								let addressP = {};
+								addressP.province = res.provinceName;
+								addressP.city = res.cityName;
+								addressP.district = res.countyName;
+								addressP.cityId = 0;
+								editAddress({
+									address: addressP,
+									status: true,
+									realName: res.userName,
+									postCode: res.postalCode,
+									phone: res.telNumber,
+									detail: res.detailInfo,
+									id: 0
+									//type: 1//区别城市id(导入微信地址无城市id需要后台自己查找);
+								}).then(res => {
+									that.$util.Tips({
+										title: "添加成功",
+										icon: 'success'
+									}, function() {
+										that.getEquipmentList(true);
+									});
+								}).catch(err => {
+									return that.$util.Tips({
+										title: err
+									});
+								});
+							},
+							fail: function(res) {
+								if (res.errMsg == 'chooseAddress:cancel') return that.$util
+									.Tips({
+										title: '取消选择'
+									});
+							},
+						})
+					},
+					fail: function(res) {
+						uni.showModal({
+							title: '您已拒绝导入微信地址权限',
+							content: '是否进入权限管理,调整授权?',
+							success(res) {
+								if (res.confirm) {
+									uni.openSetting({
+										success: function(res) {
+											console.log(res.authSetting)
+										}
+									});
+								} else if (res.cancel) {
+									return that.$util.Tips({
+										title: '已取消!'
+									});
+								}
+							}
+						})
+					}
+				})
+			},
+			getAddress() {
+				let that = this;
+				that.$wechat.openAddress().then(userInfo => {
+					// open();
+					editAddress({
+							realName: userInfo.userName,
+							phone: userInfo.telNumber,
+							address: {
+								province: userInfo.provinceName,
+								city: userInfo.cityName,
+								district: userInfo.countryName,
+								cityId: 0
+							},
+							detail: userInfo.detailInfo,
+							postCode: userInfo.postalCode,
+							status: true
+						})
+						.then(() => {
+							that.$util.Tips({
+								title: "添加成功",
+								icon: 'success'
+							}, function() {
+								// close();
+								that.getEquipmentList();
+							});
+						})
+						.catch(err => {
+							// close();
+							return that.$util.Tips({
+								title: err || "添加失败"
+							});
+						});
+				});
+			},
+			goIndex(id,code) {
+				infoApi.bindDefaultEqu({
+					memberId: this.uid,
+					id: id
+				}).then(res => {
+					// this.$store.commit("DEVICE_ID", res.data.AddressApi
+					// uni.setStorageSync('deviceCode',code)
+					this.$store.commit("DEVICE_CODE", code)
+					uni.switchTab({
+						url: '/pages/index/index'
+					})
+				}).catch(err => {
+					return this.$util.Tips({
+						title: err
+					});
+				});
+			},
+			addEqu() {
+				uni.navigateTo({
+					url: '/pages/equ_list/add_equ'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.swiper{
+		height: 100vh;
+		swiper{
+			height: 100%;
+			image{
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+	.address-management {
+		padding: 20rpx 0;
+	}
+
+	.address-management.fff {
+		background-color: #F7F7F7;
+		height: 1300rpx
+	}
+
+	.line {
+		width: 100%;
+		height: 3rpx;
+
+		image {
+			width: 100%;
+			height: 100%;
+			display: block;
+		}
+	}
+
+	.address-management .item {
+		background-color: #fff;
+		padding: 0 20rpx;
+		margin-bottom: 20rpx;
+	}
+
+	.address-management .content_box_top {
+		display: flex;
+		// justify-content: space-between;
+		align-items: center;
+	}
+
+	.address-management .content_box_top .avatar {
+		width: 96rpx;
+		height: 96rpx;
+	}
+
+	.address-management .item .content_box_top .address {
+		flex: 1;
+		padding: 35rpx 0;
+		border-bottom: 1rpx solid #eee;
+		font-size: 28rpx;
+		color: #282828;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-left: 32rpx;
+	}
+
+	.address-management .item .content_box_top .address-left {
+		width: 90%;
+	}
+
+	.address-management .item .content_box_top .address image {
+
+		width: 32rpx;
+		height: 32rpx;
+
+	}
+
+
+	.address-management .item .address .consignee {
+		font-size: 28rpx;
+		font-weight: bold;
+		margin-bottom: 8rpx;
+		display: flex;
+		align-items: center;
+	}
+
+	.address-management .item .address .consignee .online-box {
+		margin-left: 25rpx;
+		width: 50rpx;
+		height: 30rpx;
+	}
+
+	.address-management .item .address .consignee .online-box image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.address-management .item .operation {
+		height: 83rpx;
+		font-size: 28rpx;
+		color: #282828;
+	}
+
+	.address-management .item .operation .radio text {
+		margin-left: 13rpx;
+	}
+
+	.address-management .item .operation .iconfont {
+		color: #2c2c2c;
+		font-size: 35rpx;
+		vertical-align: -2rpx;
+		margin-right: 10rpx;
+	}
+
+	.address-management .item .operation .iconfont.icon-shanchu {
+		margin-left: 35rpx;
+		font-size: 38rpx;
+	}
+
+	.footer {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		position: fixed;
+		bottom: 44rpx;
+		width: 100%;
+		height: 98rpx;
+		line-height: 98rpx;
+		text-align: center;
+		background-color: #fff;
+
+	}
+
+	.footer image {
+		width: 32rpx;
+		height: 32rpx;
+		margin-right: 16rpx;
+	}
+</style>

+ 337 - 0
pages/index/condition/altitude/index.vue

@@ -0,0 +1,337 @@
+<template>
+	<view>
+		<view class="top-box">
+			<view class="container-top" @click="showDayPicker = true">
+				<view class="top-left">
+					<view class="word">今日</view>
+					<text>{{formatDate(dayValue)}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+					<image src="/static/image/full.png" mode=""></image>
+				</view> -->
+			</view>
+			<view class="chartsMain" v-if="Area.categories.length">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-else>
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<view class="content-box">
+			<view class="word-box">
+				<view class="word-title">
+					海拔记录
+				</view>
+			</view>
+			<view class="list-box">
+				<block v-for="(item,index) in dayInfo.list">
+					<view class="list-box-item">
+						<view class="list-box-left">
+							<image src="/static/image/hearticon.png" mode=""></image>
+							<text>{{formatHms(item.createTime)}}</text>
+						</view>
+						<view class="list-box-right">
+							<view class="num">{{item.altitude}}</view>
+							<view>m</view>
+						</view>
+					</view>
+				</block>
+
+			</view>
+		</view>
+
+		<van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+		</van-popup>
+	</view>
+</template>
+
+<script>
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import {
+		mapGetters
+	} from "vuex";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		data() {
+			return {
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				dayValue: new Date(),
+				showDayPicker: false,
+				currentDay: new Date().getTime(),
+				dayInfo: {},
+				list: [{
+					time: '09:00',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}],
+				// 折线图
+				Area: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				}
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+
+		},
+		methods: {
+			async onConfirm(value) {
+				this.dayValue = value.detail;
+				await this.getData()
+				this.getServerData();
+				this.showDayPicker = false;
+			},
+			getData() {
+				let data = this.formatDate(this.dayValue).split("-"); // ["2023", "10", "18"]
+				let params = {
+					deviceId: this.deviceId,
+					year: data[0],
+					month: data[1],
+					day: data[2],
+					// day:"17",
+				}
+				return infoApi.getAltitude(params).then(res => {
+						console.log(res, 44);
+						this.dayInfo = res.data
+
+
+						// 组装接口数据。上方折线图若超过10条,截取10条
+						let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+						let seriesArr = res.data.list.map(item => item.altitude)
+						this.Area.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+							categoriesArr
+						this.Area.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("HH:mm");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatHms: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+			getServerData() {
+				_self.showArea("canvasArea", this.chartData);
+
+			},
+
+
+
+			// 折线图
+			showArea(canvasId, chartData) {
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: true,
+					dataLabel: false,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: _self.Area.categories,
+					series: _self.Area.series,
+					animation: true,
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'dash',
+						dashLength: 8,
+						rotateLabel: true,
+						rotateAngle: -50,
+					},
+					yAxis: {
+						gridType: 'dash',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						min: 10,
+						max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+			font-size: 32rpx;
+			font-weight: 600;
+			color: #000000;
+
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 0 32rpx;
+
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.list-box-left {
+					display: flex;
+					align-items: center;
+
+					image {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					text {
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+
+				.list-box-right {
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+
+					.num {
+						margin-right: 30rpx;
+					}
+
+				}
+			}
+
+		}
+	}
+</style>

+ 227 - 0
pages/index/condition/blood_oxygen/components/content.vue

@@ -0,0 +1,227 @@
+<template>
+	<view class="content-box">
+		<!-- <line-chart></line-chart> -->
+		<view class="number-box">
+			<view class="box-item">
+				<text>最低</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.min}}</text>
+					</view>
+					<text>HbO2</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>平均</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.avg}}</text>
+					</view>
+					<text>HbO2</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>最高</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.max}}</text>
+					</view>
+					<text>HbO2</text>
+				</view>
+			</view>
+		</view>
+		<view class="word-box">
+			<view class="word-title">
+				测量结果仅供参考,成人静息心率:
+			</view>
+			<view class="word">
+				<p>{{word1}}</p>
+				<p>{{word2}}</p>
+				<p>{{word3}}</p>
+			</view>
+		</view>
+		<view class="list-box">
+			<block v-for="(item,index) in dayInfo.list" :key="index">
+				<view class="list-box-item">
+					<view class="list-box-left">
+						<image src="/static/image/hearticon.png" mode=""></image>
+						<text>{{formatDate(item.createTime)}}</text>
+					</view>
+					<view class="list-box-right">
+						<view class="num">{{item.bloodOxygen}}</view>
+						<view>HbO2</view>
+					</view>
+				</view>
+			</block>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	// import lineChart from './line_chart.vue'
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	export default {
+		props: {
+		    dayInfo: {
+		        type: Object,
+		        default: {},
+		    },
+		},
+		// components: {
+		// 	lineChart
+		// },
+		data() {
+			return {
+				list: [{
+					time: '09:00',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}],
+				word1: '正常水平: 95%~100%;',
+				word2: '高风险值:小于80%,可能会造成多器官乏氧,造成损伤;',
+				word3: '调整建议:当确认存在低氧血症后,会查找病因,采取相应治疗措施。',
+			}
+		},
+		onLoad() {
+			
+		},
+		methods: {
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+		.number-box {
+			height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-around;
+
+			.box-item {
+				width: 218rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+
+				text {
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+
+					.item-under-left {
+						display: flex;
+						align-items: center;
+						margin-right: 5rpx;
+						image {
+							width: 32rpx;
+							height: 32rpx;
+						}
+
+						text {
+							margin-left: 12rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+
+			.word-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #000000;
+			}
+
+			.word {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: #000000;
+				line-height: 40rpx;
+				margin-top: 18rpx;
+			}
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 0 32rpx;
+
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.list-box-left {
+					display: flex;
+					align-items: center;
+
+					image {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					text {
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+
+				.list-box-right {
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+
+					.num {
+						margin-right: 30rpx;
+					}
+
+				}
+			}
+
+		}
+	}
+</style>

+ 391 - 0
pages/index/condition/blood_oxygen/index.vue

@@ -0,0 +1,391 @@
+<template>
+	<view>
+		<!-- <van-tabs v-model="active">
+			<van-tab title="日"> -->
+		<view class="top-box">
+			<view class="container-top" @click="showDayPicker = true">
+				<view class="top-left">
+					<view class="word">今日</view>
+					<text>{{formatDate(dayValue)}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+					<image src="/static/image/full.png" mode=""></image>
+				</view> -->
+			</view>
+			<view class="chartsMain" v-if="dayArea.categories.length">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-else>
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<content-page :dayInfo="dayInfo"></content-page>
+		<!-- </van-tab>
+			<van-tab title="月">
+				<view class="top-box">
+					<view class="container-top" @click="showMonthPicker = true">
+						<view class="top-left">
+							<view class="word">月份</view>
+							<text>{{formatMonth(monthValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasMonthArea" id="canvasMonthArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+			<van-tab title="年">
+				<view class="top-box">
+					<view class="container-top" @click="showYearPicker = true">
+						<view class="top-left">
+							<view class="word">年份</view>
+							<text>{{formatYear(yearValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasYearArea" id="canvasYearArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+
+		</van-tabs> -->
+
+		<van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+		</van-popup>
+		<van-popup :show="showMonthPicker" position="bottom">
+			<van-datetime-picker @cancel="showMonthPicker=false" @confirm="onMonthConfirm" type="year-month"
+				:value="currentMonth" />
+		</van-popup>
+		<van-popup :show="showYearPicker" position="bottom">
+			<van-datetime-picker @cancel="showYearPicker=false" @confirm="onYearConfirm" type="year"
+				:value="currentYear" />
+		</van-popup>
+	</view>
+</template>
+
+<script>
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import contentPage from './components/content.vue'
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	import {
+		mapGetters
+	} from "vuex";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		components: {
+			contentPage
+		},
+		data() {
+			return {
+				active: 2,
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				dayValue: new Date(),
+				monthValue: new Date(),
+				yearValue: new Date(),
+				showDayPicker: false, //日
+				showMonthPicker: false, //月
+				showYearPicker: false, //年
+				// minDate:new Date().getTime(),
+				currentDay: new Date().getTime(),
+				currentMonth: new Date().getTime(),
+				currentYear: new Date().getTime(),
+				fullscreen: false,
+				dayInfo: {}, //日数据
+				dayTimeList: [], //日X轴数据
+				dayDataList: [], //日图表数据
+
+				// 日折线图
+				dayArea: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '',
+						data: [],
+						// data: [68,92,66,79],
+						color: '#F35546'
+					}]
+				},
+				// 月折线图
+				monthArea: {
+					categories: ['6月', '7月', '8月', ],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, 95, ],
+						color: '#F35546'
+					}]
+				},
+				// 年折线图
+				yearArea: {
+					categories: ['6月', '7月'],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, ],
+						color: '#F35546'
+					}]
+				},
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+			console.log(this.formatDate(this.currentDate), 333);
+		},
+		methods: {
+			getData() {
+				console.log(this.deviceId, 8889999);
+				let data = this.formatDate(this.dayValue).split("-"); // ["2023", "10", "18"]
+				let params = {
+					deviceId: this.deviceId,
+					year: data[0],
+					month: data[1],
+					day: data[2],
+					// day:"17",
+				}
+				return infoApi.getBloodOxygen(params).then(res => {
+						console.log(res, 44);
+						if (res.data === null) {
+							this.dayInfo = {}
+							this.dayInfo.list = []
+							this.dayArea.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.dayInfo = res.data
+
+
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							let seriesArr = res.data.list.map(item => item.bloodOxygen)
+							this.dayArea.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.dayArea.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+						}
+
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			fullscreenFn() {
+				wx.requestFullScreen({
+					success: (res) => {
+						console.log(res, 666);
+						this.fullscreen = true
+
+					}
+				});
+			},
+			formatter(type, val) {
+				if (type === 'year') {
+					return `${val}年`;
+				} else if (type === 'month') {
+					return `${val}月`;
+				}
+				return val;
+			},
+			onYearConfirm(value) {
+				console.log(value, 444);
+				this.yearValue = value.detail
+				this.showYearPicker = false
+			},
+			onMonthConfirm(value) {
+				this.monthValue = value.detail
+				this.showMonthPicker = false;
+				console.log(this.formatMonth(this.monthValue), 777);
+			},
+			async onConfirm(value) {
+				this.dayValue = value.detail;
+				await this.getData()
+				this.getServerData();
+				this.showDayPicker = false;
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("HH:mm");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatMonth: function(date) {
+				return dayjs(date).format("YYYY-MM");
+			},
+			formatYear: function(date) {
+				return dayjs(date).format("YYYY");
+			},
+			changeDay() {
+				this.showDayPicker = true
+			},
+			getServerData() {
+				console.log('是否先执行');
+				_self.showArea("canvasArea", this.chartData, 'day');
+				_self.showArea("canvasMonthArea", this.chartData, 'month');
+				_self.showArea("canvasYearArea", this.chartData, 'year');
+
+			},
+
+
+			// 折线图
+			showArea(canvasId, chartData, type) {
+				const categories = type == 'day' ? _self.dayArea.categories : type == 'month' ? _self.monthArea
+					.categories : _self.yearArea.categories
+				const series = type == 'day' ? _self.dayArea.series : type == 'month' ? _self.monthArea.series : _self
+					.yearArea.series
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: {
+						show: false
+					},
+					dataLabel: true,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: categories,
+					series: series,
+					animation: true,
+					padding: [20, 10, 10, 10],
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'solid',
+						dashLength: 8,
+						disableGrid: true,
+						rotateLabel: true,
+						rotateAngle: -50,
+					},
+					yAxis: {
+						gridType: 'solid',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						data: [{
+							format: function(val) {
+								return val.toFixed(2);
+							},
+							max: 105,
+							min: 0
+						}]
+						// min: 10,
+						// max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							// type: 'curve',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	// ::v-deep .van-tab__pane--active{
+	// 	width: 100%;
+	// }
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+</style>

+ 222 - 0
pages/index/condition/blood_pressure/components/content.vue

@@ -0,0 +1,222 @@
+<template>
+	<view class="content-box">
+		<!-- <line-chart></line-chart> -->
+		<view class="number-box">
+			<view class="box-item">
+				<text>最小</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/contract.png" mode=""></image>
+						<text>{{dayInfo.hypotensionMax}}</text>
+						<text>收缩压</text>
+					</view>
+					<text>mmHg</text>
+				</view>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/diastole.png" mode=""></image>
+						<text>{{dayInfo.hypotensionMin}}</text>
+						<text>舒张压</text>
+					</view>
+					<text>mmHg</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>最大</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/contract.png" mode=""></image>
+						<text>{{dayInfo.hypertensionMax}}</text>
+						<text>收缩压</text>
+					</view>
+					<text>mmHg</text>
+				</view>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/diastole.png" mode=""></image>
+						<text>{{dayInfo.hypertensionMin}}</text>
+						<text>舒张压</text>
+					</view>
+					<text>mmHg</text>
+				</view>
+			</view>
+		</view>
+		<view class="word-box">
+				<p>{{word1}}</p>
+				<p>{{word2}}</p>
+				<p>{{word3}}</p>
+				<p>{{word4}}</p>
+				<p>{{word5}}</p>
+				<p>{{word6}}</p>
+		</view>
+		<view class="list-box" >
+			<block v-for="(item,index) in dayInfo.list">
+				<view class="list-box-item">
+				<view class="list-box-left">
+					<image src="/static/image/hearticon.png" mode=""></image>
+					<text>{{formatDate(item.createTime)}}</text>
+				</view>
+				<view class="list-box-right">
+					<view class="num">{{item.hypertension}} / {{item.hypotension}}</view>
+					<view>mmHg</view>
+				</view>
+			</view>
+			</block>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	// import lineChart from './line_chart.vue'
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	export default {
+		// components: {
+		// 	lineChart
+		// },
+		props: {
+		    dayInfo: {
+		        type: Object,
+		        default: {},
+		    },
+		},
+		data() {
+			return {
+				list:[{time:'09:00',num:'111/80'},{time:'09:10',num:'111/80'},{time:'09:10',num:'111/80'}],
+				word1:'成年人正常值,收缩压<1200,舒张压<80',
+				word2:'正常高值,收缩压120-139,舒张压80-89',
+				word3:'高血压,收缩压>120,舒张压>80',
+				word4:'1级高血压,收缩压140-159,舒张压90-99',
+				word5:'2级高血压,收缩压160-179,舒张压100-109',
+				word6:'3级高血压,收缩压>180,舒张压>110',
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+		.number-box {
+			// height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-between;
+
+			.box-item {
+				// width: 218rpx;
+				width: 48%;
+				// height: 99rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+				text{
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+
+					.item-under-left {
+						image {
+							width: 32rpx;
+							height: 28rpx;
+						}
+
+						text {
+							margin-left: 15rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+			font-size: 28rpx;
+			font-weight: bold;
+			color: #000000;
+			line-height: 40rpx;
+
+			// .word-title {
+			// 	font-size: 32rpx;
+			// 	font-weight: 600;
+			// 	color: #000000;
+			// }
+
+			// .word {
+			// 	font-size: 28rpx;
+			// 	font-weight: 400;
+			// 	color: #000000;
+			// 	margin-top: 18rpx;
+			// }
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding:0 32rpx;
+			
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.list-box-left {
+					display: flex;
+					align-items: center;
+					image{
+						width: 48rpx;
+						height: 48rpx;
+					}
+					text{
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+				.list-box-right{
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+					.num{
+						margin-right: 30rpx;
+					}
+					
+				}
+			}
+
+		}
+	}
+</style>

+ 387 - 0
pages/index/condition/blood_pressure/index.vue

@@ -0,0 +1,387 @@
+<template>
+	<view>
+		<!-- <van-tabs v-model="active">
+			<van-tab title="日"> -->
+		<view class="top-box">
+			<view class="container-top" @click="showDayPicker = true">
+				<view class="top-left">
+					<view class="word">今日</view>
+					<text>{{formatDate(dayValue)}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+					<image src="/static/image/full.png" mode=""></image>
+				</view> -->
+			</view>
+			<view class="chartsMain" v-if="dayArea.categories.length">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-else>
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<content-page :dayInfo="dayInfo"></content-page>
+		<!-- </van-tab>
+			<van-tab title="月">
+				<view class="top-box">
+					<view class="container-top" @click="showMonthPicker = true">
+						<view class="top-left">
+							<view class="word">月份</view>
+							<text>{{formatMonth(monthValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasMonthArea" id="canvasMonthArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+			<van-tab title="年">
+				<view class="top-box">
+					<view class="container-top" @click="showYearPicker = true">
+						<view class="top-left">
+							<view class="word">年份</view>
+							<text>{{formatYear(yearValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasYearArea" id="canvasYearArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+
+		</van-tabs> -->
+
+		<van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+		</van-popup>
+		<van-popup :show="showMonthPicker" position="bottom">
+			<van-datetime-picker @cancel="showMonthPicker=false" @confirm="onMonthConfirm" type="year-month"
+				:value="currentMonth" />
+		</van-popup>
+		<van-popup :show="showYearPicker" position="bottom">
+			<van-datetime-picker @cancel="showYearPicker=false" @confirm="onYearConfirm" type="year"
+				:value="currentYear" />
+		</van-popup>
+	</view>
+</template>
+
+<script>
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import contentPage from './components/content.vue'
+	import {
+		mapGetters
+	} from "vuex";
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		components: {
+			contentPage
+		},
+		data() {
+			return {
+				active: 2,
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				dayValue: new Date(),
+				monthValue: new Date(),
+				yearValue: new Date(),
+				showDayPicker: false, //日
+				showMonthPicker: false, //月
+				showYearPicker: false, //年
+				// minDate:new Date().getTime(),
+				currentDay: new Date().getTime(),
+				currentMonth: new Date().getTime(),
+				currentYear: new Date().getTime(),
+				fullscreen: false,
+				dayInfo: {}, //日数据
+				dayTimeList: [], //日X轴数据
+				dayDataList: [], //日图表数据
+
+				// 日折线图
+				dayArea: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '低压',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#39C1F6'
+					}, {
+						name: '高压',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				},
+				// 月折线图
+				monthArea: {
+					categories: ['6月', '7月', '8月', ],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, 95, ],
+						color: '#F35546'
+					}]
+				},
+				// 年折线图
+				yearArea: {
+					categories: ['6月', '7月'],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, ],
+						color: '#F35546'
+					}]
+				},
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+			console.log(this.formatDate(this.currentDate), 333);
+		},
+		methods: {
+			getData() {
+				let data = this.formatDate(this.dayValue).split("-"); // ["2023", "10", "18"]
+				let params = {
+					deviceId: this.deviceId,
+					year: data[0],
+					month: data[1],
+					day: data[2],
+					// day:"17",
+				}
+				return infoApi.getBloodPressure(params).then(res => {
+						console.log(res, 44);
+						if (res.data === null) {
+							this.dayInfo = {}
+							this.dayInfo.list = []
+							this.dayArea.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.dayInfo = res.data
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							
+							let seriesArr1 = res.data.list.map(item => item.hypotension)
+							let seriesArr2 = res.data.list.map(item => item.hypertension)
+							this.dayArea.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.dayArea.series[0].data = seriesArr1.length > 10 ? seriesArr1.slice(-10) : seriesArr1
+							this.dayArea.series[1].data = seriesArr2.length > 10 ? seriesArr2.slice(-10) : seriesArr2
+						}
+
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			fullscreenFn() {
+				wx.requestFullScreen({
+					success: (res) => {
+						console.log(res, 666);
+						this.fullscreen = true
+
+					}
+				});
+			},
+			formatter(type, val) {
+				if (type === 'year') {
+					return `${val}年`;
+				} else if (type === 'month') {
+					return `${val}月`;
+				}
+				return val;
+			},
+			onYearConfirm(value) {
+				console.log(value, 444);
+				this.yearValue = value.detail
+				this.showYearPicker = false
+			},
+			onMonthConfirm(value) {
+				this.monthValue = value.detail
+				this.showMonthPicker = false;
+				console.log(this.formatMonth(this.monthValue), 777);
+			},
+			async onConfirm(value) {
+				this.dayValue = value.detail;
+				await this.getData()
+				this.getServerData();
+				this.showDayPicker = false;
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("HH:mm");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatMonth: function(date) {
+				return dayjs(date).format("YYYY-MM");
+			},
+			formatYear: function(date) {
+				return dayjs(date).format("YYYY");
+			},
+			changeDay() {
+				this.showDayPicker = true
+			},
+			getServerData() {
+				console.log('是否先执行');
+				_self.showArea("canvasArea", this.chartData, 'day');
+				_self.showArea("canvasMonthArea", this.chartData, 'month');
+				_self.showArea("canvasYearArea", this.chartData, 'year');
+
+			},
+
+
+			// 折线图
+			showArea(canvasId, chartData, type) {
+				const categories = type == 'day' ? _self.dayArea.categories : type == 'month' ? _self.monthArea
+					.categories : _self.yearArea.categories
+				const series = type == 'day' ? _self.dayArea.series : type == 'month' ? _self.monthArea.series : _self
+					.yearArea.series
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: false,
+					dataLabel: true,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: categories,
+					series: series,
+					animation: true,
+					padding: [20, 10, 10, 10],
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'solid',
+						dashLength: 8,
+						disableGrid: true,
+						rotateLabel: true,
+						rotateAngle: -50,
+					},
+					yAxis: {
+						gridType: 'solid',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						min: 0,
+						max: 200,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							// type: 'curve',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	// ::v-deep .van-tab__pane--active{
+	// 	width: 100%;
+	// }
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+</style>

+ 233 - 0
pages/index/condition/heart_rate/components/content.vue

@@ -0,0 +1,233 @@
+<template>
+	<view class="content-box">
+		<!-- <line-chart></line-chart> -->
+		<view class="number-box">
+			<view class="box-item">
+				<text>最低</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/heart.png" mode=""></image>
+						<text>{{dayInfo.min}}</text>
+					</view>
+					<text>BPM</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>平均</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/heart.png" mode=""></image>
+						<text>{{dayInfo.avg}}</text>
+					</view>
+					<text>BPM</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>最高</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/heart.png" mode=""></image>
+						<text>{{dayInfo.max}}</text>
+					</view>
+					<text>BPM</text>
+				</view>
+			</view>
+		</view>
+		<view class="list-box" v-if="dayInfo.list">
+			<block v-for="(item,index) in dayInfo.list" :key="index">
+				<view class="list-box-item">
+					<view class="list-box-left">
+						<image src="/static/image/hearticon.png" mode=""></image>
+						<text>{{formatDate(item.createTime)}}</text>
+					</view>
+					<view class="list-box-right">
+						<view class="num">{{item.heartRate}}</view>
+						<view>BPM</view>
+					</view>
+				</view>
+			</block>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	// import contentPage from './components/content'
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		props: {
+		    dayInfo: {
+		        type: Object,
+		        default: {},
+		    },
+		},
+		data() {
+			return {
+				list:[{time:'09:00',num:63},{time:'09:10',num:63},{time:'09:10',num:63}],
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				word1:'100<心率值<160,称为窦性心动过速;',
+				word2:'45<心率值<60称为窦性心动过缓;',
+				word3:'心率值<45,应考虑有病态窦房结综合症、房室传导阻滞等情况。',
+			};
+		},
+		onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(750);
+			this.cHeight = uni.upx2px(420);
+			this.getServerData();
+		},
+		computed: {
+
+		},
+		mounted() {
+
+		},
+		methods: {
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.chartsMain {
+		width: 750rpx;
+		height: 450rpx;
+		padding-top: 15rpx;
+		background: #fff;
+		margin-bottom: 24rpx;
+		border-top: 2rpx solid #f2f2f2;
+
+		.charts {
+			width: 750rpx;
+			height: 450rpx;
+			box-sizing: border-box;
+		}
+	}
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+	
+		.number-box {
+			height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-around;
+	
+			.box-item {
+				width: 218rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+				text{
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+	
+					.item-under-left {
+						image {
+							width: 32rpx;
+							height: 28rpx;
+						}
+	
+						text {
+							margin-left: 15rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+	
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+	
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+	
+			.word-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #000000;
+			}
+	
+			.word {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: #000000;
+				line-height: 40rpx;
+				margin-top: 18rpx;
+			}
+		}
+	
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding:0 32rpx;
+			
+	
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.list-box-left {
+					display: flex;
+					align-items: center;
+					image{
+						width: 48rpx;
+						height: 48rpx;
+					}
+					text{
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+				.list-box-right{
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+					.num{
+						margin-right: 30rpx;
+					}
+					
+				}
+			}
+	
+		}
+	}
+</style>

+ 802 - 0
pages/index/condition/heart_rate/index.vue

@@ -0,0 +1,802 @@
+<template>
+	<view class="box">
+		<!-- <van-tabs v-model="active">
+			<van-tab title="日"> -->
+		<view class="user-box">
+			<image class="top-right" src="https://app.tjzhxx.cn:11443/image/enterprise_icon.png" mode=""></image>
+			<view class="right-box">
+				<view class="name">刘嘉琳</view>
+				<view class="info-box">
+					<view class="info-item">
+						<view class="number">78</view>
+						<view class="word">年龄</view>
+					</view>
+					<view class="info-item">
+						<view class="number">156</view>
+						<view class="word">身高</view>
+					</view>
+					<view class="info-item">
+						<view class="number">47.3</view>
+						<view class="word">体重</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="content-box">
+			<view class="number-box">
+				<view class="box-item" :class="{ 'heart-selected': selectedItem === 'item1' }"
+					@click="setSelectedItem('item1')">
+					<view class="item-top">
+						<view class="item-word">心率</view>
+						<image
+							:src="selectedItem === 'item1' ?'/static/img/heart-icon.png':'/static/img/unheart-icon.png'"
+							mode=""></image>
+					</view>
+					<view class="item-under">
+						<view class="number">076</view>
+						<view class="unit">BPM</view>
+					</view>
+				</view>
+				<view class="box-item" :class="{ 'sleep-selected': selectedItem === 'item2' }"
+					@click="setSelectedItem('item2')">
+					<view class="item-top">
+						<view class="item-word">睡眠</view>
+						<image class="sleep-icon"
+							:src="selectedItem === 'item2' ?'/static/img/sleep-icon.png':'/static/img/unsleep-icon.png'"
+							mode=""></image>
+					</view>
+					<view class="item-under">
+						<view class="number">48</view>
+						<view class="unit">MIN</view>
+					</view>
+				</view>
+				<view class="box-item" :class="{ 'breathe-selected': selectedItem === 'item3' }"
+					@click="setSelectedItem('item3')">
+					<view class="item-top">
+						<view class="item-word">呼吸</view>
+						<image class="breathe-icon"
+							:src="selectedItem === 'item3' ?'/static/img/breathe-icon.png':'/static/img/unbreathe-icon.png'"
+							mode=""></image>
+					</view>
+					<view class="item-under">
+						<view class="number">43</view>
+						<view class="unit">AHI</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="top-box">
+			<view class="container-top" @click="showDayPicker = true">
+				<view class="top-left">
+					<view class="word">今日</view>
+					<text>{{formatDate(dayValue)}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+							<image src="/static/image/full.png" mode=""></image>
+						</view> -->
+			</view>
+			<view class="chartsMain" v-if="Area.categories.length">
+				<view class="">数据分析</view>
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts" disable-scroll="false"></canvas>
+			</view>
+			<view class="chartsMain" v-else>
+				<image src="/static/img/none.png" mode=""></image>
+			</view>
+		</view>
+		<view class="under-box" v-if="selectedItem === 'item1'">
+			<view class="under-item">
+				<i class="iconfont icon-arrow-right"></i>
+				<view class="under-top">120 bpm</view>
+				<view class="under-word">最高心率</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">70 bpm</view>
+				<view class="under-word">最低心率</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">84 bpm</view>
+				<view class="under-word">平均心率</view>
+			</view>
+		</view>
+		<view class="under-box" v-if="selectedItem === 'item2'">
+			<view class="under-item">
+				<view class="under-top">8h23min</view>
+				<view class="under-word">深睡时长</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">2h18min</view>
+				<view class="under-word">浅睡时长</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">良好</view>
+				<view class="under-word">睡眠质量</view>
+			</view>
+		</view>
+		<view class="under-box" v-if="selectedItem === 'item3'">
+			<view class="under-item">
+				<view class="under-top">19 次</view>
+				<view class="under-word">最高呼吸率</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">11 次</view>
+				<view class="under-word">最低呼吸率</view>
+			</view>
+			<view class="under-item">
+				<view class="under-top">17 次</view>
+				<view class="under-word">平均呼吸率</view>
+			</view>
+		</view>
+		<!--</van-tab>
+			 <van-tab title="月">
+				<view class="top-box">
+					<view class="container-top" @click="showMonthPicker = true">
+						<view class="top-left">
+							<view class="word">月份</view>
+							<text>{{formatMonth(monthValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasMonthArea" id="canvasMonthArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+			<van-tab title="年">
+				<view class="top-box">
+					<view class="container-top" @click="showYearPicker = true">
+						<view class="top-left">
+							<view class="word">年份</view>
+							<text>{{formatYear(yearValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasYearArea" id="canvasYearArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+
+		</van-tabs> -->
+		<van-calendar :show="showDayPicker" @confirm="onConfirm" @close="showDayPicker = false"
+			:default-date="currentDay" />
+
+		<!-- <van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+		</van-popup>
+		<van-popup :show="showMonthPicker" position="bottom">
+			<van-datetime-picker @cancel="showMonthPicker=false" @confirm="onMonthConfirm" type="year-month"
+				:value="currentMonth" />
+		</van-popup>
+		<van-popup :show="showYearPicker" position="bottom">
+			<van-datetime-picker @cancel="showYearPicker=false" @confirm="onYearConfirm" type="year"
+				:value="currentYear" />
+		</van-popup> -->
+	</view>
+</template>
+
+<script>
+	import {
+		toLogin
+	} from '@/libs/login.js';
+	import {
+		mapGetters
+	} from "vuex";
+	// import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import contentPage from './components/content.vue'
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		computed: mapGetters(['isLogin', 'uid', 'deviceId']),
+		components: {
+			contentPage
+		},
+		data() {
+			return {
+				active: 2,
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				dayValue: new Date(),
+				monthValue: new Date(),
+				yearValue: new Date(),
+				showDayPicker: false, //日
+				showMonthPicker: false, //月
+				showYearPicker: false, //年
+				// minDate:new Date().getTime(),
+				currentDay: new Date().getTime(),
+				currentMonth: new Date().getTime(),
+				currentYear: new Date().getTime(),
+				fullscreen: false,
+				dayInfo: {}, //日数据
+				dayTimeList: [], //日X轴数据
+				dayDataList: [], //日图表数据
+
+				// 日折线图
+				dayArea: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '学习前端',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				},
+				// 月折线图
+				monthArea: {
+					categories: ['6月', '7月', '8月', ],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, 95, ],
+						color: '#F35546'
+					}]
+				},
+				// 年折线图
+				yearArea: {
+					categories: ['6月', '7月'],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, ],
+						color: '#F35546'
+					}]
+				},
+				selectedItem: 'item1',
+
+
+
+
+
+				// 新
+				Area: {
+					categories: ['6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, 95, 150, 112, 132, 151],
+						color: '#facc14'
+					}, {
+						name: '学习后台',
+						data: [70, 40, 65, 100, 44, 68, 78],
+						color: '#2fc25b'
+					}, {
+						name: '学习设计',
+						data: [35, 20, 25, 37, 4, 20, 39],
+						color: '#1890ff'
+					}]
+				}
+
+
+			};
+		},
+		onShow() {
+
+		},
+		async onLoad() {
+			console.log(this.isLogin, '判断是否登录');
+			// if (!this.isLogin) {
+			// 	toLogin();
+			// 	return
+			// }
+
+			_self = this;
+			this.cWidth = uni.upx2px(630);
+			this.cHeight = uni.upx2px(400);
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {},
+		methods: {
+			setSelectedItem(item) {
+				this.selectedItem = this.selectedItem === item ? null : item;
+			},
+			getData() {
+				console.log(this.deviceId, 88877766);
+				let data = this.formatDate(this.dayValue).split("-"); // ["2023", "10", "18"]
+				let params = {
+					deviceId: this.deviceId,
+					year: data[0],
+					month: data[1],
+					day: data[2],
+					// day:"17",
+				}
+				return
+				return infoApi.getHeartRate(params).then(res => {
+						console.log(res, 44);
+						if (res.data === null) {
+							this.dayInfo = {}
+							this.dayInfo.list = []
+							this.dayArea.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.dayInfo = res.data
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							let seriesArr = res.data.list.map(item => item.heartRate)
+							this.dayArea.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.dayArea.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+						}
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			fullscreenFn() {
+				wx.requestFullScreen({
+					success: (res) => {
+						console.log(res, 666);
+						this.fullscreen = true
+
+					}
+				});
+			},
+			formatter(type, val) {
+				if (type === 'year') {
+					return `${val}年`;
+				} else if (type === 'month') {
+					return `${val}月`;
+				}
+				return val;
+			},
+			onYearConfirm(value) {
+				console.log(value, 444);
+				this.yearValue = value.detail
+				this.showYearPicker = false
+			},
+			onMonthConfirm(value) {
+				this.monthValue = value.detail
+				this.showMonthPicker = false;
+				console.log(this.formatMonth(this.monthValue), 777);
+			},
+			async onConfirm(value) {
+				this.dayValue = value.detail;
+				await this.getData()
+				this.getServerData();
+				this.showDayPicker = false;
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("HH:mm");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatMonth: function(date) {
+				return dayjs(date).format("YYYY-MM");
+			},
+			formatYear: function(date) {
+				return dayjs(date).format("YYYY");
+			},
+			changeDay() {
+				this.showDayPicker = true
+			},
+			getServerData() {
+				console.log('是否先执行');
+				_self.showArea("canvasArea", this.chartData, 'day');
+				_self.showArea("canvasMonthArea", this.chartData, 'month');
+				_self.showArea("canvasYearArea", this.chartData, 'year');
+
+			},
+
+
+			// 新
+			showArea(canvasId, chartData) {
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: true,
+					dataLabel: false,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: _self.Area.categories,
+					series: _self.Area.series,
+					animation: true,
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'dash',
+						dashLength: 8,
+						disableGrid: true,
+					},
+					yAxis: {
+						gridType: 'dash',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						min: 10,
+						max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+
+
+
+			// 折线图
+			// showArea(canvasId, chartData, type) {
+			// 	const categories = type == 'day' ? _self.dayArea.categories : type == 'month' ? _self.monthArea
+			// 		.categories : _self.yearArea.categories
+			// 	const series = type == 'day' ? _self.dayArea.series : type == 'month' ? _self.monthArea
+			// 		.series : _self
+			// 		.yearArea.series
+			// 	canvaArea = new uCharts({
+			// 		$this: _self,
+			// 		canvasId: canvasId,
+			// 		type: 'area',
+			// 		fontSize: 11,
+			// 		legend: {
+			// 			show: false
+			// 		},
+			// 		dataLabel: true,
+			// 		dataPointShape: true,
+			// 		background: '#FFFFFF',
+			// 		pixelRatio: _self.pixelRatio,
+			// 		categories: categories,
+			// 		series: series,
+			// 		animation: true,
+			// 		padding: [20, 10, 10, 10],
+			// 		xAxis: {
+			// 			type: 'grid',
+			// 			gridColor: '#CCCCCC',
+			// 			gridType: 'solid',
+			// 			dashLength: 8,
+			// 			disableGrid: true,
+			// 			rotateLabel: true,
+			// 			rotateAngle: -50,
+			// 		},
+			// 		yAxis: {
+			// 			gridType: 'solid',
+			// 			gridColor: '#CCCCCC',
+			// 			dashLength: 8,
+			// 			splitNumber: 5,
+			// 			min: 10,
+			// 			max: 180,
+			// 		},
+			// 		width: _self.cWidth * _self.pixelRatio,
+			// 		height: _self.cHeight * _self.pixelRatio,
+			// 		extra: {
+			// 			area: {
+			// 				type: 'straight',
+			// 				// type: 'curve',
+			// 				opacity: 0.2,
+			// 				addLine: true,
+			// 				width: 2
+			// 			}
+			// 		}
+			// 	});
+			// },
+
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	// ::v-deep .van-tab__pane--active{
+	// 	width: 100%;
+	// }
+	.box {
+		padding: 20rpx 30rpx !important;
+	}
+
+	.user-box {
+		// padding: 40rpx 30rpx;
+		padding: 40rpx 70rpx 40rpx 30rpx;
+		margin-bottom: 60rpx;
+		background-color: #fff;
+		border-radius: 15rpx;
+		display: flex;
+		align-items: center;
+
+		image {
+			width: 190rpx;
+			height: 190rpx;
+			border-radius: 50%;
+		}
+
+		.right-box {
+			flex: 1;
+			margin-left: 30rpx;
+
+			.name {
+				font-weight: 600;
+				font-size: 48rpx;
+				color: #2D2D2D;
+				margin-bottom: 20rpx;
+			}
+
+			.info-box {
+				display: flex;
+				justify-content: space-between;
+
+				.info-item {
+					font-weight: 500;
+
+					.number {
+						font-size: 32rpx;
+						color: #2D2D2D;
+					}
+
+					.word {
+						font-size: 28rpx;
+						color: #A6A6A6;
+					}
+				}
+			}
+		}
+	}
+
+	.content-box {
+		// background-color: #F7F7F7;
+		// height: 100vh;
+		margin-bottom: 60rpx;
+
+		.number-box {
+			height: 120rpx;
+			// background-color: #fff;
+			display: flex;
+			justify-content: space-between;
+
+			.box-item {
+				width: 210rpx;
+				height: 120rpx;
+				padding: 13rpx 20rpx;
+				box-sizing: border-box;
+				border-radius: 15rpx;
+				background-color: #fff;
+
+				text {
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+
+				.item-top {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+
+					.item-word {
+						font-weight: 500;
+						font-size: 32rpx;
+					}
+
+
+					image {
+						width: 30rpx;
+						height: 25rpx;
+					}
+
+					.sleep-icon {
+						width: 31rpx;
+						height: 36rpx;
+					}
+
+					.breathe-icon {
+						width: 32rpx;
+						height: 28rpx;
+					}
+				}
+
+				.item-under {
+					display: flex;
+					align-items: center;
+					// margin-top: 12rpx;
+					font-weight: 500;
+					align-items: flex-end;
+
+					.number {
+						font-size: 36rpx;
+					}
+
+					.unit {
+						font-size: 24rpx;
+						margin-left: 19rpx;
+					}
+
+				}
+			}
+
+			.box-item.heart-selected {
+				background: linear-gradient(180deg, #FF8E8E 0%, #EC3534 100%);
+				color: #fff;
+				/* 选中的字体颜色 */
+			}
+
+			.box-item.sleep-selected {
+				background: linear-gradient(180deg, #80D2FF 0%, #56B6FF 100%);
+				color: #fff;
+				/* 选中的字体颜色 */
+			}
+
+			.box-item.breathe-selected {
+				background: linear-gradient(180deg, #FFDE8F 0%, #FF9A55 100%);
+				color: #fff;
+				/* 选中的字体颜色 */
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+
+			.word-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #000000;
+			}
+
+			.word {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: #000000;
+				line-height: 40rpx;
+				margin-top: 18rpx;
+			}
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 0 32rpx;
+
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.list-box-left {
+					display: flex;
+					align-items: center;
+
+					image {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					text {
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+
+				.list-box-right {
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+
+					.num {
+						margin-right: 30rpx;
+					}
+
+				}
+			}
+
+		}
+	}
+
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+		border-radius: 15rpx;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 630rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+	.under-box{
+		width: 100%;
+		height: 174rpx;
+		box-sizing: border-box;
+		margin-top: 30rpx;
+		display: flex;
+		justify-content: space-between;
+		padding: 40rpx 30rpx;
+		background-color: #fff;
+		border-radius: 15rpx;
+		.under-item{
+			color: #2D2D2D;
+			text-align: center;
+			.under-top{
+				font-weight: 600;
+				font-size: 36rpx;
+			}
+			.under-word{
+				font-size: 30rpx;
+			}
+		}
+	}
+</style>

+ 415 - 0
pages/index/condition/sleep/index.vue

@@ -0,0 +1,415 @@
+<template>
+	<view>
+		<view class="top-box">
+			<view class="container-top" @click="showPicker = true">
+				<view class="top-left">
+					<view class="word">一周内</view>
+					<text>{{formatDate(defaultDate[0])}} ~ {{formatDate(defaultDate[1])}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+					<image src="/static/image/full.png" mode=""></image>
+				</view> -->
+			</view>
+			<view class="chartsMain" v-show="Area.categories.length&&!showPicker">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-show="!Area.categories.length">
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<view class="content-box">
+			<view class="word-box">
+				<view class="word-title">
+					睡眠记录
+				</view>
+			</view>
+			<view class="list-box">
+				<block v-for="(item,index) in infoData.list">
+					<view class="list-box-item">
+						<view class="list-box-left">
+							<image src="/static/image/hearticon.png" mode=""></image>
+							<text>{{formatHms(item.createTime)}}</text>
+						</view>
+						<view class="list-box-right">
+							<view class="num">{{item.rollTimes}}</view>
+							<view>次</view>
+						</view>
+					</view>
+				</block>
+
+			</view>
+		</view>
+
+		<!-- 日历 -->
+		<van-calendar :show="showPicker" type="range" @confirm="onConfirm" @close="showPicker = false"
+			:default-date="defaultDate" allow-same-day="true" :min-date="minDate" />
+	</view>
+</template>
+
+<script>
+	// import contentPage from './components/content.vue'
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import {
+		mapGetters
+	} from "vuex";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		// components: {
+		// 	contentPage
+		// },
+		data() {
+			return {
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				// dayValue: new Date(),
+				defaultDate: [], //默认一周内
+				showPicker: false, //日
+				infoData: {}, //日数据
+
+				minDate: new Date(2023, 0, 1).getTime(),
+				list: [{
+					time: '09:00',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}],
+				// 折线图
+				Area: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '翻转次数',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				}
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			this.defaultDate = [new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000).getTime(), new Date()
+				.getTime()
+			]
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+
+		},
+		methods: {
+			getData() {
+				let params = {
+					deviceId: this.deviceId,
+					startTime: `${this.formatDate(this.defaultDate[0])} 00:00:00`,
+					endTime: `${this.formatDate(this.defaultDate[1])} 23:59:59`,
+				}
+				console.log(params, 111);
+				return infoApi.getSleep(params).then(res => {
+						console.log(res, 44);
+						if (res.data === null) {
+							this.infoData = {}
+							this.infoData.list = []
+							this.Area.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.infoData = res.data
+
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							let seriesArr = res.data.list.map(item => item.rollTimes)
+							this.Area.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.Area.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+
+						}
+
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			formatHms: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("MM-DD");
+			},
+			async onConfirm(date) {
+				console.log(date, 777);
+				this.defaultDate = date.detail;
+				await this.getData()
+				this.getServerData()
+				this.showPicker = false;
+			},
+			getServerData() {
+				_self.showArea("canvasArea", this.chartData);
+			},
+
+			// 折线图
+			showArea(canvasId, chartData) {
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: false,
+					dataLabel: true,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: _self.Area.categories,
+					series: _self.Area.series,
+					animation: true,
+					padding: [20, 10, 10, 10],
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'solid',
+						dashLength: 8,
+						disableGrid: true,
+						rotateLabel:true,
+						rotateAngle:-50,
+					},
+					yAxis: {
+						gridType: 'dash',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						min: 0,
+						// max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+		.chartsMain {
+			width: 750rpx;
+			height: 450rpx;
+			padding-top: 15rpx;
+			background: #fff;
+			margin-bottom: 24rpx;
+			border-top: 2rpx solid #f2f2f2;
+
+			.charts {
+				width: 750rpx;
+				height: 450rpx;
+				box-sizing: border-box;
+			}
+		}
+
+		.number-box {
+			height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-around;
+
+			.box-item {
+				width: 218rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+
+				text {
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+
+					.item-under-left {
+						image {
+							width: 32rpx;
+							height: 32rpx;
+						}
+
+						text {
+							margin-left: 15rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+			font-size: 32rpx;
+			font-weight: 600;
+			color: #000000;
+
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 0 32rpx;
+
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.list-box-left {
+					display: flex;
+					align-items: center;
+
+					image {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					text {
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+
+				.list-box-right {
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+
+					.num {
+						margin-right: 30rpx;
+					}
+
+				}
+			}
+
+		}
+	}
+</style>

+ 433 - 0
pages/index/condition/step/index.vue

@@ -0,0 +1,433 @@
+<template>
+	<view>
+		<view class="top-box">
+			<view class="container-top" @click="showPicker = true">
+				<view class="top-left">
+					<view class="word">一周内</view>
+					<text>{{formatDate(defaultDate[0])}} ~ {{formatDate(defaultDate[1])}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+					<image src="/static/image/full.png" mode=""></image>
+				</view> -->
+			</view>
+			<view class="chartsMain" v-show="Area.categories.length&&!showPicker">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-show="!Area.categories.length">
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<view class="content-box">
+			<view class="number-box">
+				<view class="box-item">
+					<text>最低</text>
+					<view class="item-under">
+						<view class="item-under-left">
+							<image src="/static/image/stepIcon.png" mode=""></image>
+							<text>{{infoData.min}}</text>
+						</view>
+						<text>Step</text>
+					</view>
+				</view>
+				<view class="box-item">
+					<text>平均</text>
+					<view class="item-under">
+						<view class="item-under-left">
+							<image src="/static/image/stepIcon.png" mode=""></image>
+							<text>{{infoData.avg}}</text>
+						</view>
+						<text>Step</text>
+					</view>
+				</view>
+				<view class="box-item">
+					<text>最高</text>
+					<view class="item-under">
+						<view class="item-under-left">
+							<image src="/static/image/stepIcon.png" mode=""></image>
+							<text>{{infoData.max}}</text>
+						</view>
+						<text>Step</text>
+					</view>
+				</view>
+			</view>
+			<view class="word-box">
+				<view class="word-title">
+					步数记录
+				</view>
+			</view>
+			<view class="list-box">
+				<block v-for="(item,index) in infoData.list">
+					<view class="list-box-item">
+						<view class="list-box-left">
+							<image src="/static/image/hearticon.png" mode=""></image>
+							<text>{{formatHms(item.createTime)}}</text>
+						</view>
+						<view class="list-box-right">
+							<view class="num">{{item.stepNumber}}</view>
+							<view>Step</view>
+						</view>
+					</view>
+				</block>
+
+			</view>
+		</view>
+
+		<!-- 日历 -->
+		<van-calendar :show="showPicker" type="range" @confirm="onConfirm" @close="showPicker = false"
+			:default-date="defaultDate" allow-same-day="true" :min-date="minDate" />
+	</view>
+</template>
+
+<script>
+	// import contentPage from './components/content.vue'
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import {
+		mapGetters
+	} from "vuex";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		// components: {
+		// 	contentPage
+		// },
+		data() {
+			return {
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				// dayValue: new Date(),
+				defaultDate: [], //默认一周内
+				showPicker: false, //日
+				infoData: {}, //日数据
+
+				minDate: new Date(2023, 0, 1).getTime(),
+				list: [{
+					time: '09:00',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}, {
+					time: '09:10',
+					num: 63
+				}],
+				// 折线图
+				Area: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '步数',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				}
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			this.defaultDate = [new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000).getTime(), new Date()
+				.getTime()
+			]
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+
+		},
+		methods: {
+			getData() {
+				let params = {
+					deviceId: this.deviceId,
+					startTime: `${this.formatDate(this.defaultDate[0])} 00:00:00`,
+					endTime: `${this.formatDate(this.defaultDate[1])} 23:59:59`,
+				}
+				console.log(params, 111);
+				return infoApi.getStepNumber(params).then(res => {
+						if (res.data === null) {
+							this.infoData = {}
+							this.infoData.list = []
+							this.Area.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.infoData = res.data
+
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							let seriesArr = res.data.list.map(item => item.stepNumber)
+							this.Area.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.Area.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+						}
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			formatHms: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("MM-DD");
+			},
+			async onConfirm(date) {
+				console.log(date, 777);
+				this.defaultDate = date.detail;
+				await this.getData()
+				this.getServerData()
+				this.showPicker = false;
+			},
+			getServerData() {
+				_self.showArea("canvasArea", this.chartData);
+			},
+
+			// 折线图
+			showArea(canvasId, chartData) {
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: false,
+					dataLabel: true,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: _self.Area.categories,
+					series: _self.Area.series,
+					animation: true,
+					padding: [20, 10, 10, 10],
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'solid',
+						dashLength: 8,
+						disableGrid: true,
+						rotateLabel:true,
+						rotateAngle:-50,
+					},
+					yAxis: {
+						gridType: 'dash',
+						gridColor: '#CCCCCC',
+						dashLength: 8,
+						splitNumber: 5,
+						min: 0,
+						// max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	::v-deep .van-calendar{
+		z-index: 15 !important;
+	}
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+				z-index: 10;
+			}
+		}
+	}
+
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+		.number-box {
+			height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-around;
+
+			.box-item {
+				width: 218rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+
+				text {
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+
+					.item-under-left {
+						image {
+							width: 32rpx;
+							height: 32rpx;
+						}
+
+						text {
+							margin-left: 15rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+			font-size: 32rpx;
+			font-weight: 600;
+			color: #000000;
+
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 0 32rpx;
+
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.list-box-left {
+					display: flex;
+					align-items: center;
+
+					image {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					text {
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+
+				.list-box-right {
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+
+					.num {
+						margin-right: 30rpx;
+					}
+
+				}
+			}
+
+		}
+	}
+</style>

+ 208 - 0
pages/index/condition/temperature/components/content.vue

@@ -0,0 +1,208 @@
+<template>
+	<view class="content-box">
+		<!-- <line-chart></line-chart> -->
+		<view class="number-box">
+			<view class="box-item">
+				<text>最低</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.min}}</text>
+					</view>
+					<text>°C</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>平均</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.avg}}</text>
+					</view>
+					<text>°C</text>
+				</view>
+			</view>
+			<view class="box-item">
+				<text>最高</text>
+				<view class="item-under">
+					<view class="item-under-left">
+						<image src="/static/image/oxygen.png" mode=""></image>
+						<text>{{dayInfo.max}}</text>
+					</view>
+					<text>°C</text>
+				</view>
+			</view>
+		</view>
+		<view class="word-box">
+			<view class="word-title">
+				测量结果仅供参考,正常体温范围: 35-37.5
+			</view>
+			<!-- <view class="word">
+				<p>{{word1}}</p>
+				<p>{{word2}}</p>
+				<p>{{word3}}</p>
+			</view> -->
+		</view>
+		<view class="list-box" >
+			<block v-for="(item,index) in dayInfo.list">
+				<view class="list-box-item">
+				<view class="list-box-left">
+					<image src="/static/image/hearticon.png" mode=""></image>
+					<text>{{formatDate(item.createTime)}}</text>
+				</view>
+				<view class="list-box-right">
+					<view class="num">{{item.temperature}}</view>
+					<view>°C</view>
+				</view>
+			</view>
+			</block>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	// import lineChart from './line_chart.vue'
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	export default {
+		// components: {
+		// 	lineChart
+		// },
+		props: {
+		    dayInfo: {
+		        type: Object,
+		        default: {},
+		    },
+		},
+		data() {
+			return {
+				list:[{time:'09:00',num:63},{time:'09:10',num:63},{time:'09:10',num:63}],
+				word1:'100<心率值<160,称为窦性心动过速;',
+				word2:'45<心率值<60称为窦性心动过缓;',
+				word3:'心率值<45,应考虑有病态窦房结综合症、房室传导阻滞等情况。',
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+	.content-box {
+		background-color: #F7F7F7;
+		// height: 100vh;
+
+		.number-box {
+			height: 131rpx;
+			background-color: #fff;
+			display: flex;
+			margin-top: 16rpx;
+			padding: 16rpx 32rpx;
+			justify-content: space-around;
+
+			.box-item {
+				width: 218rpx;
+				padding: 10rpx 16rpx;
+				box-sizing: border-box;
+				border-radius: 12rpx;
+				border: 2rpx solid rgba(119, 119, 119, 0.3);
+				text{
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #777777;
+				}
+				.item-under {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 12rpx;
+
+					.item-under-left {
+						image {
+							width: 32rpx;
+							height: 32rpx;
+						}
+
+						text {
+							margin-left: 15rpx;
+							font-size: 32rpx;
+							font-weight: 400;
+							color: #000000;
+						}
+					}
+
+					text {
+						font-size: 24rpx;
+						font-weight: 400;
+						color: #777777;
+					}
+				}
+			}
+		}
+
+		.word-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding: 32rpx;
+
+			.word-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #000000;
+			}
+
+			.word {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: #000000;
+				line-height: 40rpx;
+				margin-top: 18rpx;
+			}
+		}
+
+		.list-box {
+			margin-top: 16rpx;
+			background-color: #fff;
+			padding:0 32rpx;
+			
+
+			.list-box-item {
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.list-box-left {
+					display: flex;
+					align-items: center;
+					image{
+						width: 48rpx;
+						height: 48rpx;
+					}
+					text{
+						margin-left: 32rpx;
+						font-size: 32rpx;
+						font-weight: 400;
+						color: #000000;
+					}
+				}
+				.list-box-right{
+					display: flex;
+					font-size: 32rpx;
+					font-weight: 600;
+					color: #000000;
+					.num{
+						margin-right: 30rpx;
+					}
+					
+				}
+			}
+
+		}
+	}
+</style>

+ 392 - 0
pages/index/condition/temperature/index.vue

@@ -0,0 +1,392 @@
+<template>
+	<view>
+		<!-- <van-tabs v-model="active">
+			<van-tab title="日"> -->
+		<view class="top-box">
+			<view class="container-top" @click="showDayPicker = true">
+				<view class="top-left">
+					<view class="word">今日</view>
+					<text>{{formatDate(dayValue)}}</text>
+				</view>
+				<!-- <view class="top-right" @click.stop="fullscreenFn">
+							<image src="/static/image/full.png" mode=""></image>
+						</view> -->
+			</view>
+			<view class="chartsMain" v-if="dayArea.categories.length">
+				<canvas canvas-id="canvasArea" id="canvasArea" class="charts"></canvas>
+			</view>
+			<view class="chartsMain" v-else>
+				<image src="/static/image/none.png" mode=""></image>
+			</view>
+		</view>
+		<content-page :dayInfo="dayInfo"></content-page>
+		<!-- </van-tab>
+			<van-tab title="月">
+				<view class="top-box">
+					<view class="container-top" @click="showMonthPicker = true">
+						<view class="top-left">
+							<view class="word">月份</view>
+							<text>{{formatMonth(monthValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasMonthArea" id="canvasMonthArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+			<van-tab title="年">
+				<view class="top-box">
+					<view class="container-top" @click="showYearPicker = true">
+						<view class="top-left">
+							<view class="word">年份</view>
+							<text>{{formatYear(yearValue)}}</text>
+						</view>
+						<view class="top-right">
+							<image src="/static/image/full.png" mode=""></image>
+						</view>
+					</view>
+					<view class="chartsMain">
+						<canvas canvas-id="canvasYearArea" id="canvasYearArea" class="charts"
+							@touchstart="touchArea"></canvas>
+					</view>
+				</view>
+				<content-page></content-page>
+			</van-tab>
+
+		</van-tabs> -->
+
+		<van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+			<!-- :min-date="minDate" -->
+		</van-popup>
+		<van-popup :show="showMonthPicker" position="bottom">
+			<van-datetime-picker @cancel="showMonthPicker=false" @confirm="onMonthConfirm" type="year-month"
+				:value="currentMonth" />
+		</van-popup>
+		<van-popup :show="showYearPicker" position="bottom">
+			<van-datetime-picker @cancel="showYearPicker=false" @confirm="onYearConfirm" type="year"
+				:value="currentYear" />
+		</van-popup>
+	</view>
+</template>
+
+<script>
+	import * as infoApi from '@/api/info/index.js';
+	import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	import contentPage from './components/content.vue'
+	import {
+		mapGetters
+	} from "vuex";
+	// 图表
+	import uCharts from "@/components/ucharts/ucharts.js";
+	// import uCharts from "@/components/u-charts/u-charts.js";
+	var _self;
+	var canvaRing = null;
+	var canvaArea = null;
+	var canvaGauge = null;
+	var canvaPie = null;
+	var canvaColumn = null;
+	var canvaFunnel = null;
+	var canvaWord = null;
+
+	export default {
+		components: {
+			contentPage
+		},
+		data() {
+			return {
+				active: 2,
+				cWidth: '',
+				cHeight: '',
+				pixelRatio: 1,
+				dayValue: new Date(),
+				monthValue: new Date(),
+				yearValue: new Date(),
+				showDayPicker: false, //日
+				showMonthPicker: false, //月
+				showYearPicker: false, //年
+				// minDate:new Date().getTime(),
+				currentDay: new Date().getTime(),
+				currentMonth: new Date().getTime(),
+				currentYear: new Date().getTime(),
+				fullscreen: false,
+				dayInfo: {}, //日数据
+				dayTimeList: [], //日X轴数据
+				dayDataList: [], //日图表数据
+
+				// 日折线图
+				dayArea: {
+					categories: [],
+					// categories: ['08:22','08:22','08:22','08:22'],
+					series: [{
+						name: '学习前端',
+						data: [],
+						// data: [68,89,66,79],
+						color: '#F35546'
+					}]
+				},
+				// 月折线图
+				monthArea: {
+					categories: ['6月', '7月', '8月', ],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, 95, ],
+						color: '#F35546'
+					}]
+				},
+				// 年折线图
+				yearArea: {
+					categories: ['6月', '7月'],
+					series: [{
+						name: '学习前端',
+						data: [100, 80, ],
+						color: '#F35546'
+					}]
+				},
+
+
+			};
+		},
+		computed: mapGetters(['deviceId']),
+		async onLoad() {
+			_self = this;
+			this.cWidth = uni.upx2px(680);
+			this.cHeight = uni.upx2px(400);
+			await this.getData()
+			this.getServerData();
+		},
+		mounted() {
+			console.log(this.formatDate(this.currentDate), 333);
+		},
+		methods: {
+			getData() {
+				let data = this.formatDate(this.dayValue).split("-"); // ["2023", "10", "18"]
+				let params = {
+					deviceId: this.deviceId,
+					year: data[0],
+					month: data[1],
+					day: data[2],
+					// day:"17",
+				}
+				return infoApi.getTemperature(params).then(res => {
+						console.log(res, 44);
+						if (res.data === null) {
+							this.dayInfo = {}
+							this.dayInfo.list = []
+							this.dayArea.categories = []
+						}
+						if (res.code === 0 && res.data.list.length) {
+							this.dayInfo = res.data
+
+							// 组装接口数据。上方折线图若超过10条,截取10条
+							let categoriesArr = res.data.list.map(item => this.formatHHmm(item.createTime))
+							let seriesArr = res.data.list.map(item => item.temperature)
+							this.dayArea.categories = categoriesArr.length > 10 ? categoriesArr.slice(-10) :
+								categoriesArr
+							this.dayArea.series[0].data = seriesArr.length > 10 ? seriesArr.slice(-10) : seriesArr
+
+						}
+
+					})
+					.catch(err => {
+						return this.$util.Tips({
+							title: err,
+							// icon: 'error'
+						});
+					});
+			},
+			fullscreenFn() {
+				wx.requestFullScreen({
+					success: (res) => {
+						console.log(res, 666);
+						this.fullscreen = true
+
+					}
+				});
+			},
+			formatter(type, val) {
+				if (type === 'year') {
+					return `${val}年`;
+				} else if (type === 'month') {
+					return `${val}月`;
+				}
+				return val;
+			},
+			onYearConfirm(value) {
+				console.log(value, 444);
+				this.yearValue = value.detail
+				this.showYearPicker = false
+			},
+			onMonthConfirm(value) {
+				this.monthValue = value.detail
+				this.showMonthPicker = false;
+				console.log(this.formatMonth(this.monthValue), 777);
+			},
+			async onConfirm(value) {
+				this.dayValue = value.detail;
+				await this.getData()
+				this.getServerData();
+				this.showDayPicker = false;
+			},
+			formatHHmm: function(date) {
+				return dayjs(date).format("HH:mm");
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
+			formatMonth: function(date) {
+				return dayjs(date).format("YYYY-MM");
+			},
+			formatYear: function(date) {
+				return dayjs(date).format("YYYY");
+			},
+			changeDay() {
+				this.showDayPicker = true
+			},
+			getServerData() {
+				console.log('是否先执行');
+				_self.showArea("canvasArea", this.chartData, 'day');
+				_self.showArea("canvasMonthArea", this.chartData, 'month');
+				_self.showArea("canvasYearArea", this.chartData, 'year');
+
+			},
+
+
+			// 折线图
+			showArea(canvasId, chartData, type) {
+				const categories = type == 'day' ? _self.dayArea.categories : type == 'month' ? _self.monthArea
+					.categories : _self.yearArea.categories
+				const series = type == 'day' ? _self.dayArea.series : type == 'month' ? _self.monthArea.series : _self
+					.yearArea.series
+				canvaArea = new uCharts({
+					$this: _self,
+					canvasId: canvasId,
+					type: 'area',
+					fontSize: 11,
+					legend: {
+						show: false
+					},
+					dataLabel: true,
+					dataPointShape: true,
+					background: '#FFFFFF',
+					pixelRatio: _self.pixelRatio,
+					categories: categories,
+					series: series,
+					animation: true,
+					padding: [20, 10, 10, 10],
+					xAxis: {
+						type: 'grid',
+						gridColor: '#CCCCCC',
+						gridType: 'solid',
+						dashLength: 8,
+						disableGrid: true,
+						rotateLabel: true,
+						rotateAngle: -50,
+					},
+					// TODO y轴不要小数位
+					yAxis: {
+						gridType: 'solid',
+						gridColor: '#CCCCCC',
+						dashLength: 3,
+						splitNumber: 6,
+
+						data: [{
+							format: function(val) {
+								return val.toFixed(1);
+							},
+							min: 35,
+							max: 42,
+						}]
+						// max: 180,
+					},
+					width: _self.cWidth * _self.pixelRatio,
+					height: _self.cHeight * _self.pixelRatio,
+					extra: {
+						area: {
+							type: 'straight',
+							// type: 'curve',
+							opacity: 0.2,
+							addLine: true,
+							width: 2
+						}
+					}
+				});
+			},
+			touchArea(e) {
+				canvaArea.showToolTip(e, {
+					format: function(item, category) {
+						return item.name + ' ' + category + ' ' + ':' + item.data
+					}
+				});
+			},
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	// ::v-deep .van-tab__pane--active{
+	// 	width: 100%;
+	// }
+	.top-box {
+		padding: 28rpx 32rpx 19rpx;
+		background-color: #fff;
+
+		.container-top {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 28rpx;
+
+			.top-left {
+				.word {
+					font-size: 36rpx;
+					font-weight: 500;
+					color: #000000;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-weight: 500;
+					color: #777777;
+					line-height: 33rpx;
+				}
+			}
+
+			.top-right {
+				width: 32rpx;
+				height: 32rpx;
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.chartsMain {
+			width: 100%;
+			// height: 450rpx;
+			// box-sizing: border-box;
+			background: #fff;
+			border-top: 2rpx solid #f2f2f2;
+			text-align: center;
+
+			image {
+				width: 70%;
+				// height: 100%;
+			}
+
+			.charts {
+				width: 680rpx;
+				height: 400rpx;
+				box-sizing: border-box;
+			}
+		}
+	}
+</style>

+ 1083 - 1044
pages/index/index.vue

@@ -1,1187 +1,1226 @@
 <template>
 	<view>
-		<view class="page-index" :class="{'bgf':navIndex >0}">
-			<!-- #ifdef H5 -->
-			<view class="header">
-				<view class="serch-wrapper flex">
-					<view class="logo">
-						<image :src="logoUrl" mode="" />
+		<view class="map-box" v-if="!deviceCode">
+
+			<!-- <view class="mp-header">
+				<view class="sys-head" :style="'height:'+(statusBarHeight)+'px;'"></view>
+				<view class="serch-box" :style="{height:barHeight+'px'}">
+					<view class="serch-wrapper flex" @click="goEquList">
+						<image class="logo" src='/static/img/addequ.png' mode="" />
+						<view class="name">奶奶</view>
+						<image class="arrow" src="/static/img/arrow.png" mode=""></image>
 					</view>
-					<navigator url="/pages/goods_search/index" class="input" hover-class="none">
-            <text class="iconfont icon-xiazai5" /> 搜索商品
-          </navigator>
 				</view>
-			</view>
-			<!-- #endif -->
-			<!-- #ifdef MP -->
-			<view class="mp-header">
-				<view class="sys-head" :style="{ height: statusBarHeight }"></view>
-				<view class="serch-box" style="height: 40px;">
-					<view class="serch-wrapper flex">
-						<view class="logo">
-							<image :src="logoUrl" mode=""></image>
-						</view>
-						<navigator url="/pages/goods_search/index" class="input" hover-class="none"><text
-								class="iconfont icon-xiazai5"></text>
-							搜索商品</navigator>
-					</view>
+			</view> -->
+			<map id='map' :latitude="latitude" :longitude="longitude" :markers="covers" :polyline="polyline"
+				:scale="scale">
+			</map>
+			<view class="top-input" v-if="!deviceId">
+				<image src="../../static/img/noneEqu.png" mode=""></image>
+				<view class="btn-box" @click="goEquList">
+					<view class="btn">添加设备</view>
 				</view>
 			</view>
-			<!-- #endif -->
-			<!-- 首页展示 -->
-			<view class="page_content" :style="'margin-top:'+(marTop)+'px;'" v-if="navIndex === 0">
-				<view class="mp-bg"></view>
-				<!-- banner 轮播图 -->
-				<view class="swiper" v-if="slideShows.length">
-					<swiper indicator-dots="true" :autoplay="true" :circular="circular" :interval="interval"
-						:duration="duration" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
-						<block v-for="(item,index) in slideShows" :key="index">
-							<swiper-item>
-								<navigator :url='item.url' class='slide-navigator acea-row row-between-wrapper'
-									hover-class='none'>
-									<image :src="item.picUrl" class="slide-image" lazy-load></image>
-								</navigator>
-							</swiper-item>
-						</block>
-					</swiper>
-				</view>
-
-				<!-- 新闻简报 -->
-				<view class='notice acea-row row-middle row-between' v-if="scrollingNews.length">
-					<view class="pic">
-						<image src="/static/images/xinjian.png" />
-					</view>
-					<text class='line'>|</text>
-					<view class='swipers'>
-						<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" duration="500"
-                    vertical="true" circular="true">
-							<block v-for="(item,index) in scrollingNews" :key='index'>
-								<swiper-item>
-									<navigator class='item' :url='item.url' hover-class='none'>
-										<view class='line1'>{{ item.name }}</view>
-									</navigator>
-								</swiper-item>
-							</block>
-						</swiper>
-					</view>
-					<view class="iconfont icon-xiangyou" />
-				</view>
-
-				<!-- menu 菜单 -->
-				<view class='nav acea-row' v-if="menus.length">
-					<block v-for="(item,index) in menus" :key="index">
-						<navigator class='item' v-if="item.show === '1'" :url='item.url' open-type='switchTab'
-                       hover-class='none'>
-							<view class='pictrue'>
-								<image :src='item.picUrl'></image>
-							</view>
-							<view class="menu-txt">{{item.name}}</view>
-						</navigator>
-						<navigator class='item' v-else :url='item.url' hover-class='none'>
-							<view class='pictrue'>
-								<image :src='item.picUrl'></image>
+			<view class="info-box" v-if="deviceId" @click="goBindPage">
+				<view class="scroll-view_H">
+					<scroll-view class="scroll-view-content" scroll-x @scroll="scroll" scroll-left="0">
+						<view id="demo1" class="scroll-view-item_H uni-bg-red" @click="toHeartRate">
+							<image class="bg-image" src="../../static/img/heart.png" mode=""></image>
+							<view class="text-wrapper">
+								<view class="text-overlay black">
+									<view class="top-box">
+										<view class="top-left">
+											<view class="english">Heart rate</view>
+											<view class="chinese">心率</view>
+										</view>
+										<image class="top-right"
+											src="https://app.tjzhxx.cn:11443/image/enterprise_icon.png" mode=""></image>
+									</view>
+									<view class="under-box">
+										<view class="under-left">
+											<view class="number">98</view>
+											<view class="unit">bpm</view>
+										</view>
+										<view class="under-right">
+											<view class="range">75~96 bpm</view>
+											<view class="range-word">平局区间</view>
+										</view>
+									</view>
+								</view>
 							</view>
-							<view class="menu-txt">{{item.name}}</view>
-						</navigator>
-					</block>
-				</view>
-
-				<!-- 优惠券 -->
-				<view class="couponIndex" v-if="couponList.length>0">
-					<view class="acea-row" style="height: 100%;">
-						<view class="titBox">
-							<view class="tit1">领取优惠券</view>
-							<view class="tit2">福利大礼包,省了又省</view>
-							<navigator class='item' url='/pages/users/user_get_coupon/index' hover-class='none'>
-								<view class="tit3">查看全部 <text class="iconfont icon-xiangyou"></text></view>
-							</navigator>
 						</view>
-						<view class="listBox acea-row">
-							<view class="list" :class='item.canTake ? "listActive" : "listHui"'
-                    v-for="(item, index) in couponList" :key="index">
-								<view class="tit line1" :class='item.canTake ? "titActive" : "pricehui"'>{{ item.name }}</view>
-								<view class="price" :class='item.canTake ?  "icon-color" : "pricehui"'>
-                  <text v-if="item.discountType === 1">{{ fen2yuan(item.discountPrice) }} 元</text>
-                  <text v-else>{{ (item.discountPercent / 10.0).toFixed(1) }} 折</text>
-                </view>
-								<view class="ling icon-color" v-if="item.canTake"
-                      @click="getCoupon(item.id,index)">领取</view>
-								<view class="ling pricehui fonthui" v-else>已领取</view>
-								<view class="priceM">满{{ fen2yuan(item.usePrice) }}元可用</view>
+						<view id="demo2" class="scroll-view-item_H uni-bg-green">
+							<image class="bg-image" src="../../static/img/sleep.png" mode=""></image>
+							<view class="text-wrapper white">
+								<view class="text-overlay">
+									<view class="top-box">
+										<view class="top-left">
+											<view class="english">Sleep log</view>
+											<view class="chinese">睡眠</view>
+										</view>
+									</view>
+									<view class="under-box">
+										<view class="under-left white">
+											<view class="number">5h</view>
+											<view class="unit">28 min</view>
+										</view>
+										<view class="under-left white">
+											<view class="number">66%</view>
+											<view class="unit">深睡</view>
+										</view>
+									</view>
+								</view>
 							</view>
 						</view>
-					</view>
-				</view>
-
-				<!-- 营销活动 -->
-				<a_seckill />
-				<b_combination />
-				<c_bargain />
-
-				<!-- 首页推荐 -->
-				<view class="sticky-box" :style="'top:'+(marTop)+'px;'">
-					<scroll-view class="scroll-view_H" style="width: 100%;" scroll-x="true" scroll-with-animation
-						:scroll-left="tabsScrollLeft" @scroll="scroll">
-						<view class="tab nav-bd" id="tab_list">
-							<view id="tab_item" :class="{ 'active': listActive === index}" class="item"
-                    v-for="(item, index) in productRecommends" :key="index" @click="ProductNavTab(item,index)">
-								<view class="txt">{{item.name}}</view>
-								<view class="label">{{item.tag}}</view>
+						<view id="demo3" class="scroll-view-item_H uni-bg-blue">
+							<image class="bg-image" src="../../static/img/breathe.png" mode=""></image>
+							<view class="text-wrapper white">
+								<view class="text-overlay">
+									<view class="top-box">
+										<view class="top-left">
+											<view class="english">Breathe log</view>
+											<view class="chinese">呼吸</view>
+										</view>
+									</view>
+									<view class="under-box">
+										<view class="under-left white">
+											<view class="number">21次</view>
+											<view class="unit">最高</view>
+										</view>
+										<view class="under-left white">
+											<view class="number">17次</view>
+											<view class="unit">平均呼吸</view>
+										</view>
+									</view>
+								</view>
 							</view>
 						</view>
 					</scroll-view>
 				</view>
-				<!-- 首发新品 -->
-				<view class="index-product-wrapper" :class="iSshowH?'on':''">
-					<view class="list-box animated" :class='tempArr.length > 0?"fadeIn on":""'>
-						<view class="item" v-for="(item,index) in tempArr" :key="index" @click="goDetail(item)">
-							<view class="pictrue">
-								<span class="pictrue_log pictrue_log_class"
-									v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 1">秒杀</span>
-								<span class="pictrue_log pictrue_log_class"
-									v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 2">砍价</span>
-								<span class="pictrue_log pictrue_log_class"
-									v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 3">拼团</span>
-								<image :src="item.picUrl" mode="" />
-							</view>
-							<view class="text-info">
-								<view class="title line1">{{ item.name }}</view>
-								<view class="old-price"><text>¥{{ fen2yuan(item.marketPrice) }}</text></view>
-								<view class="price">
-									<text>¥</text>{{ fen2yuan(item.price) }}
-								</view>
-							</view>
-						</view>
-					</view>
-					<view class='loadingicon acea-row row-center-wrapper' v-if="goodScroll">
-						<text class='loading iconfont icon-jiazai' :hidden='!loading' />
-					</view>
-					<view class="mores-txt flex" v-if="!goodScroll">
-						<text>我是有底线的</text>
-					</view>
+				<view class="sos-btn">
+					<image src="../../static/img/sos.png" mode=""></image>
 				</view>
 			</view>
+
+			<view class="icon-box-right" v-if="showBtn">
+				<image src="/static/image/calendarIcon.png" mode="" @click="showDayPicker = true"></image>
+			</view>
+			<van-loading class="loading" v-if="showLoading" type="spinner" color="#000" />
+		</view>
+		<view class="" v-if="deviceCode">
+			<web-view :src="h5url"></web-view>
 		</view>
+
+		<!-- </page-container> -->
+		<van-popup :show="showDayPicker" position="bottom">
+			<van-datetime-picker @cancel="showDayPicker=false" @confirm="onConfirm" :value="currentDay" type="date" />
+			<!-- :min-date="minDate" -->
+		</van-popup>
 	</view>
 </template>
-<script>
-	import Cache from '../../utils/cache';
-	const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
-	let app = getApp();
-	import a_seckill from './components/a_seckill';
-	import b_combination from './components/b_combination';
-	import c_bargain from './components/c_bargain';
-	import goodList from '@/components/goodList';
-	import { goShopDetail } from '@/libs/order.js'
-	import { mapGetters } from "vuex";
-	import countDown from '@/components/countDown';
-	import recommend from '@/components/recommend';
-	import { silenceBindingSpread } from '@/utils';
-	import Loading from '@/components/Loading/index.vue';
-  import * as ProductSpuApi from '@/api/product/spu.js';
-  import * as PromotionActivityApi from '@/api/promotion/activity.js';
-  import * as CouponApi from '@/api/promotion/coupon.js';
-  import * as DecorateApi from '@/api/promotion/decorate.js';
-  import * as ProductUtil from '@/utils/product.js';
-  import * as Util from '@/utils/util.js';
 
+<script>
+	// import AMapLoader from "@amap/amap-jsapi-loader";
+	import {
+		toLogin
+	} from '@/libs/login.js';
+	import {
+		mapGetters
+	} from "vuex";
+	import * as hrApi from '@/api/sleep/index.js';
+	// import * as infoApi from '@/api/info/index.js';
+	// import dayjs from "@/plugin/dayjs/dayjs.min.js";
+	const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
+	const statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	// 获取导航栏高度
+	const barHeight = menuButtonInfo.height + (menuButtonInfo.top - statusBarHeight) * 2
 	export default {
-		computed: mapGetters(['isLogin', 'uid']),
-		components: {
-			goodList,
-			countDown,
-			a_seckill,
-			b_combination,
-			c_bargain,
-			recommend,
-			Loading
-		},
+		computed: mapGetters(['deviceCode', 'isLogin']),
 		data() {
 			return {
 				statusBarHeight: statusBarHeight,
-				navIndex: 0,
-				navTop: [],
-				marTop: 0,
-				configApi: {}, // 分享类容配置
-				tabsScrollLeft: 0, // tabs 当前偏移量
-				scrollLeft: 0,
-
-        slideShows: [], // 轮播图
-        circular: true,
-        interval: 3000,
-        duration: 500,
-        menus: [], // 菜单
-        scrollingNews: [], // 新闻简报
-        indicatorDots: false,
-        autoplay: true,
-        couponList: [], // 优惠劵列表
-        productRecommends: [], // 商品推荐
-
-        site_name: '首页', // 首页 title
-        logoUrl: "",
-
-        // ========== 精品推荐 ===========
-        goodScroll: true, // 精品推荐开关
-        listActive: 0, // 当前选中项
-        goodType: 1, //精品推荐 Type
-        params: { //精品推荐分页
-          page: 1,
-          limit: 10,
-        },
-        loading: false,
-        tempArr: [], // 精品推荐临时数组
-        iSshowH: false,
-      }
-		},
-		watch: {
-			listActive(newVal) { // 监听当前选中项
-				this.setTabList()
+				barHeight: barHeight,
+				showPage: false,
+				aaa: [117.662369, 39.032391],
+				showInfo: true,
+				map: null,
+				windowHeight: 0,
+				mapHeight: 0,
+				timer: null,
+				showDayPicker: false, //日
+				dateTime: '',
+				navigationBarTitle: '定位',
+				currentDay: new Date().getTime(),
+				showLoading: false,
+
+				isDisabled: false,
+				isStart: false,
+				playIndex: 1,
+				showBtn: false, //展示右边日历按钮
+				scale: 13,
+				id: 0, // 使用 marker点击事件 需要填写id
+				title: 'map',
+				latitude: 39.0313466,
+				longitude: 117.6637305,
+				// latitude: '',
+				// longitude: '',
+				// deviceCode: '',
+				onlineForce: false,
+				onlineStatus: false,
+				gpsUpdateTime: '',
+				addressDesc: '',
+				// 标记点
+				// covers: [{
+				// 		id: 1,
+				// 		width: 42,
+				// 		height: 47,
+				// 		// rotate: 270,
+				// 		// latitude: '',
+				// 		// longitude: '',
+				// 		latitude: 39.0313466,
+				// 		longitude: 117.6637305,
+				// 		iconPath: "https://app.tjzhxx.cn:11443/image/enterprise_icon.png",
+				// 		// callout: {
+				// 		//         content: "陕A·88888", // 车牌信息
+				// 		//         display: "ALWAYS",
+				// 		//         fontWeight: "bold",
+				// 		//         color: "#5A7BEE", //文本颜色
+				// 		//         fontSize: "12px",
+				// 		//         bgColor: "#ffffff", //背景色
+				// 		//         padding: 5, //文本边缘留白
+				// 		//         textAlign: "center",
+				// 		// },
+				// 		// anchor: {
+				// 		//         x: 0.5,
+				// 		//         y: 0.5,
+				// 		// }
+				// 	},
+				// 	// 找到当前数据得id,在这个数据得前面造出一个没有id得json,用作北京图片,前提是经纬度一样
+				// 	{
+				// 		id: 2,
+				// 		width: 47,
+				// 		height: 49,
+				// 		latitude: 39.037,
+				// 		longitude: 117.660,
+				// 		iconPath: "https://app.tjzhxx.cn:11443/image/gender_man.png",
+				// 	},
+				// 	{
+				// 		// id: 3,
+				// 		width: 40,
+				// 		height: 45,
+				// 		latitude: 39.037,
+				// 		longitude: 117.660,
+				// 		iconPath: "https://app.tjzhxx.cn:11443/image/enterprise_icon.png",
+				// 	},
+				// 	{
+				// 		id: 3,
+				// 		width: 42,
+				// 		height: 47,
+				// 		latitude: 39.052,
+				// 		longitude: 117.657,
+				// 		iconPath: "https://app.tjzhxx.cn:11443/image/enterprise_icon.png",
+				// 	},
+
+				// ],
+				covers:[],
+
+				// 线
+				polyline: [],
+
+				// 坐标数据
+				coordinates: [{
+						id: 1,
+						latitude: 23.098994,
+						longitude: 113.322520,
+					},
+					{
+						id: 2,
+						latitude: 23.097994,
+						longitude: 113.323520,
+						// iconPath: '/image/location.png',
+
+					},
+
+				],
+				coordinate: [], //坐标数据
+
+				posi: { // 汽车定位点的数据,后面只用改latitude、longitude即可
+					id: 1,
+					width: 32,
+					height: 32,
+					latitude: 0,
+					longitude: 0,
+					iconPath: "/static/image/positonimg.png",
+					callout: {
+						content: "陕A·85Q1Q", // 车牌信息
+						display: "BYCLICK",
+						fontWeight: "bold",
+						color: "#5A7BEE", //文本颜色
+						fontSize: "12px",
+						bgColor: "#ffffff", //背景色
+						padding: 5, //文本边缘留白
+						textAlign: "center",
+					},
+					anchor: {
+						x: 0.5,
+						y: 0.5,
+					},
+				},
+				h5url:''
 			}
 		},
-		mounted() {
-			this.setTabList()
+		beforeCreate() {
+			console.log('我只行啊')
+			uni.setStorageSync('useSleep', true);
 		},
-		onLoad() {
-      // wx.login({
-      //   success (res) {
-      //     if (res.code) {
-      //       console.log(res.code, '======== code 编号 =======')
-      //     }
-      //   }
-      // })
-
-			var that = this;
-			// 获取系统信息
+		onReady() {
+			// 创建map对象
+			this.map = uni.createMapContext('map');
+			// 获取屏幕高度
 			uni.getSystemInfo({
-				success(res) {
-					that.$store.commit("SYSTEM_PLATFORM", res.platform);
-				}
-			});
-			uni.getLocation({
-				type: 'gcj02',
-				altitude: true,
-				geocode: true,
-				success: function(res) {
-					try {
-						uni.setStorageSync('user_latitude', res.latitude);
-						uni.setStorageSync('user_longitude', res.longitude);
-					} catch {}
+				success: res => {
+					this.windowHeight = res.windowHeight;
 				}
 			});
-			this.isLogin && silenceBindingSpread();
-			this.getIndexConfig();
 		},
 		onShow() {
-			uni.setNavigationBarTitle({
-				title: this.site_name
+			// this.initAmap();
+			this.getLocationInfo()
+			// this.getHrdata()
+			console.log(this.deviceCode,'deviceCodedeviceCode')
+			if(this.deviceCode){
+				this.geth5Url()
+			}
+		},
+		onPageUnload: function() {
+
+			uni.navigateBack({
+				delta: 0
 			})
+		},
+		onLoad() {
+			let that =this
+
+			uni.getLocation({
+				type: 'wgs84',
+				success: function (res) {
+					console.log(res,'我是定位接口得返回数据')
+					console.log('当前位置的经度:' + res.longitude);
+					console.log('当前位置的纬度:' + res.latitude);
+				},
+				fail: function (error) {
+				        console.log('获取位置信息失败:', error.errMsg);
+				        // 或者将错误信息显示在页面上
+				        // this.errorMessage = '获取位置信息失败: ' + error.errMsg;
+				    }
+			});
+
+		},
+		onHide: function() {
+			uni.setStorageSync('useSleep', false);
+		},
+
+		mounted() {
+
 		},
 		methods: {
-			// scroll-view滑动事件
-			scroll(e) {
-				this.scrollLeft = e.detail.scrollLeft;
+			geth5Url(){
+				hrApi.geth5url({sn:this.deviceCode}).then(res=>{
+					console.log(res,777)
+					this.h5url=res.data.httpsURL
+					// this.$set("this.h5url",res.data.httpsURL)
+				})
 			},
-			setTabList() {
-				this.$nextTick(() => {
-					this.scrollIntoView()
+			getHrdata(){
+				hrApi.getHrInfo({sn:"B1E507CD076164C7",date:"2024-06-30"}).then(res=>{
+					console.log('我是首页得心率数据',res)
 				})
 			},
-			// 计算tabs位置
-			scrollIntoView() { // item滚动
-				let lineLeft = 0;
-				this.getElementData('#tab_list', (data) => {
-					let list = data[0]
-					this.getElementData(`#tab_item`, (data) => {
-						let el = data[this.listActive]
-            if (el) {
-              lineLeft = el.width / 2 + (-list.left) + el.left - list.width / 2 - this.scrollLeft
-              this.tabsScrollLeft = this.scrollLeft + lineLeft
-            }
-					})
+			toHeartRate() {
+				uni.navigateTo({
+					url: '/pages/index/condition/heart_rate/index'
 				})
 			},
-			getElementData(el, callback) {
-				uni.createSelectorQuery().in(this).selectAll(el).boundingClientRect().exec((data) => {
-					callback(data[0]);
-				});
+			goEquList() {
+				if (!this.isLogin) {
+					toLogin();
+					return
+				}
+				console.log('点击了')
+				uni.navigateTo({
+					url: '/pages/equ_list/index',
+				})
 			},
-			// 首页数据
-			getIndexConfig: function() {
-				let that = this;
-        DecorateApi.getDecorateComponentListByPage(1).then(res => {
-          // TODO 芋艿:暂时写死
-					uni.setNavigationBarTitle({
-						title: '首页'
+			beforeleave() {
+				console.log('出发了');
+				this.showPage = false
+				//判断是上一个页面进入(返回),还是直接进入这个页面(回首页)
+				let pages = getCurrentPages()
+				console.log(pages.length, 5555);
+
+				pages.length = 2
+				console.log(pages.length, 6666);
+				console.log(this.showBtn, '轨迹');
+				console.log(!this.showBtn, '定位');
+				if (pages.length == 2 && this.showBtn) {
+					this.showPage = true
+					uni.navigateTo({
+						url: '/pages/index/map/index'
 					})
-					this.$set(this, "logoUrl", 'https://static.iocoder.cn/ruoyi-vue-pro-logo.png');
-					this.$set(this, "site_name", '首页');
-          // #ifdef H5
-          this.$store.commit("SET_CHATURL", 'https://cschat.antcloud.com.cn/index.htm?tntInstId=jm7_c46J&scene=SCE01197657');
-          Cache.set('chatUrl', 'https://cschat.antcloud.com.cn/index.htm?tntInstId=jm7_c46J&scene=SCE01197657');
-          // #endif
-
-          // 轮播图
-          const slideShow = res.data.find(item => item.code === 'slide-show');
-          if (slideShow) {
-            this.$set(this, "slideShows", JSON.parse(slideShow.value));
-          }
-          // 菜单
-          const menu = res.data.find(item => item.code === 'menu');
-          if (menu) {
-            this.$set(this, "menus", JSON.parse(menu.value));
-          }
-          // 滚动新闻
-          const scrollingNews = res.data.find(item => item.code === 'scrolling-news');
-          if (scrollingNews) {
-            this.$set(this, "scrollingNews", JSON.parse(scrollingNews.value));
-          }
-          // 商品推荐
-          const productRecommend = res.data.find(item => item.code === 'product-recommend');
-          if (productRecommend) {
-            this.$set(this, "productRecommends", JSON.parse(productRecommend.value));
-            if (this.productRecommends.length > 0) {
-              this.goodType = this.productRecommends[0].type
-              this.getGroomList();
-            }
-          }
+				} else {
+					this.showPage = true
+					uni.switchTab({
+						url: '/pages/index/index'
+					})
+				}
+			},
+			onConfirm(e) {
+				this.dateTime = this.formatDate(e.detail)
+				this.showDayPicker = false
+				this.initAmap(3)
+			},
+			getLocationInfo() {
+				this.showLoading = true
+
+				return
+				infoApi.getLocationInfo({
+					deviceId: this.deviceId
+				}).then(res => {
+					this.showLoading = false
+					this.latitude = res.data.lat
+					this.longitude = res.data.lng
+					this.covers[0].latitude = res.data.lat
+					this.covers[0].longitude = res.data.lng
+					this.deviceCode = res.data.deviceCode
+					this.onlineForce = res.data.onlineForce
+					this.onlineStatus = res.data.onlineStatus
+					this.gpsUpdateTime = this.formaTime(res.data.gpsUpdateTime)
+					this.addressDesc = res.data.addressDesc
 				})
-        // 获得分享配置
-        this.shareApi();
-        // 获得优惠劵列表
-        this.getcouponList();
 			},
-
-			shareApi: function() {
-        // TODO 芋艿:写死
-        const configApi = {
-          "title": "芋道商城",
-          "synopsis": "芋道商城,好用!",
-          "img": "https://static.iocoder.cn/ruoyi-vue-pro-logo.png"
-        }
-        this.$set(this, 'configApi', configApi);
-        // #ifdef H5
-        this.setOpenShare(configApi);
-        // #endif
+			formaTime: function(date) {
+				return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
 			},
-			// 微信分享;
-			setOpenShare: function(data) {
-				let that = this;
-				if (that.$wechat.isWeixin()) {
-					let configAppMessage = {
-						desc: data.synopsis,
-						title: data.title,
-						link: location.href,
-						imgUrl: data.img
-					};
-					that.$wechat.wechatEvevt(["updateAppMessageShareData", "updateTimelineShareData"], configAppMessage);
-				}
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
 			},
-
-      // ========== 优惠劵 ===========
-      /**
-       * 获得优惠劵列表
-       */
-      getcouponList() {
-        CouponApi.getCouponTemplateList({ count: 2 }).then(res => {
-          this.$set(this, 'couponList', res.data);
-        }).catch(err => {
-          return this.$util.Tips({
-            title: err
-          });
-        });
-      },
-      /**
-       * 领取优惠劵
-       */
-      getCoupon: function(id, index) {
-        CouponApi.takeCoupon(id).then(res => {
-          // 设置已领取,即不能再领取
-          this.$set(this.couponList[index], 'canTake', res.data !== true);
-          this.$util.Tips({
-            title: '领取成功'
-          });
-        }).catch(err => {
-          return this.$util.Tips({
-            title: err
-          });
-        })
-      },
-
-      // ========== 精品推荐 ===========
-      /**
-       * 首发新品切换
-       */
-      ProductNavTab(item, index) {
-        this.listActive = index
-        this.goodType = item.type
-        this.listActive = index
-        this.tempArr = []
-        this.params.page = 1
-        this.goodScroll = true
-        this.getGroomList(true)
-      },
-      /**
-       * 商品精品推荐
-       */
-			getGroomList(onloadH) {
-				if (!this.goodScroll) {
-          return
-        }
-				if (onloadH) {
-					this.iSshowH = true
-				}
-        this.loading = true
-        ProductSpuApi.getSpuPage({
-          recommendType: this.goodType,
-          pageNo: this.params.page,
-          pageSize: this.params.limit
-        }).then(res => {
-          const good_list = res.data.list;
-          this.iSshowH = false
-					this.loading = false
-					this.goodScroll = good_list.length >= this.params.limit
-					this.params.page++
-
-          // 设置营销活动
-          const spuIds = good_list.map(item => item.id);
-          if (spuIds.length > 0) {
-            PromotionActivityApi.getActivityListBySpuIds(spuIds).then(res => {
-              ProductUtil.setActivityList(good_list, res.data);
-              this.tempArr = this.tempArr.concat(good_list); // 放在此处,避免 Vue 监控不到数组里的元素变化
-            });
-          }
-				})
+			goFenceList() {
+				let center = `${this.longitude},${this.latitude}`
+				uni.navigateTo({
+					url: `/pages/index/map/fencelist?center=${center}`,
+				});
 			},
-      /**
-       * 前往商品详情
-       */
-      goDetail(item) {
-        goShopDetail(item, this.uid).then(res => {
-          uni.navigateTo({
-            url: `/pages/goods_details/index?id=${item.id}`
-          })
-        })
-      },
-      fen2yuan(price) {
-        return Util.fen2yuan(price)
-      }
-		},
-		/**
-		 * 用户点击右上角分享
-		 */
-		// #ifdef MP
-		onShareAppMessage: function() {
-			return {
-				title: this.configApi.title,
-				imageUrl: this.configApi.img,
-				desc: this.configApi.synopsis,
-				path: '/pages/index/index'
-			};
-		},
-		// #endif
-		onReachBottom() {
-			if (this.navIndex === 0) {
-				// 首页加载更多
-				if (this.params.page !== 1) {
-					this.getGroomList();
-				}
-			}
-		}
-	}
-</script>
-<style>
-	page {
-		display: flex;
-		flex-direction: column;
-		height: 100%;
-		/* #ifdef H5 */
-		background-color: #fff;
-		/* #endif */
+			goBindPage() {
 
-	}
-</style>
-<style lang="scss">
-	.notice{
-		width: 100%;
-		height: 70rpx;
-		border-radius: 10rpx;
-		background-color: #fff;
-		margin-bottom: 25rpx;
-		line-height: 70rpx;
-		padding: 0 14rpx;
-		.line {
-			color: #CCCCCC;
-		}
-		.pic{
-			width: 130rpx;
-			height: 36rpx;
-			image{
-				width: 100%;
-				height: 100%;
-				display: block !important;
-			}
-		}
-		.swipers {
-			height: 100%;
-			width: 444rpx;
-			overflow: hidden;
-			swiper {
-				height: 100%;
-				width: 100%;
-				overflow: hidden;
-				font-size: 22rpx;
-				color: #333333;
-			}
-		}
-		.iconfont {
-			color: #999999;
-			font-size: 20rpx;
-		}
-	}
-	.couponIndex {
-		width: auto;
-		height: 238rpx;
-		background-image: url('~@/static/images/yhjsy.png');
-		background-size: 100% 100%;
-		padding-left: 42rpx;
-		margin-bottom: 30rpx;
-
-		.titBox {
-			padding: 47rpx 0;
-			text-align: center;
-			height: 100%;
-
-			.tit1 {
-				color: #FFEBD2;
-				font-size: 34rpx;
-				font-weight: 600;
-			}
-
-			.tit2 {
-				color: #FFEBD2;
-				font-size: 22rpx;
-				margin:10rpx 0 26rpx 0;
-			}
-
-			.tit3 {
-				color: #FFDAAF;
-				font-size: 24rpx;
-				.iconfont {
-					font-size: 20rpx;
-				}
-			}
-		}
-
-		.listBox {
-			padding: 14rpx 0;
-
-			.listActive {
-				background-image: url('~@/static/images/lingyhj.png');
-				background-size: 100% 100%;
-			}
-
-			.listHui {
-				background-image: url('~@/static/images/weiling.png');
-				background-size: 100% 100%;
-			}
-
-			.list {
-				width: 170rpx;
-				height: 210rpx;
-				padding: 16rpx 0;
-				text-align: center;
-				margin-left: 24rpx;
-
-				.tit {
-					font-size: 18rpx;
-					padding: 0 26rpx;
-				}
-
-				.titActive {
-					color: #C99959;
-				}
+			},
+			formatDate: function(date) {
+				return dayjs(date).format("YYYY-MM-DD");
+			},
 
-				.price {
-					font-size: 46rpx;
-					font-weight: 900;
-					margin-top: 4rpx;
+			initAmap(type) {
+				let _this = this;
+				// _this.addMarkers()
+				if (type === 2) {
+					this.showLoading = true
+					infoApi.refreshLocation({
+						deviceId: this.deviceId
+					}).then(res => {
+						this.showLoading = false
+						this.latitude = res.data.lat
+						this.longitude = res.data.lng
+						this.covers[0].latitude = res.data.lat
+						this.covers[0].longitude = res.data.lng
+						this.gpsUpdateTime = this.formaTime(res.data.gpsUpdateTime)
+						this.addressDesc = res.data.addressDesc
+					})
 				}
+				if (type === 3) {
+					uni.navigateTo({
+						url: '/pages/index/map/driving'
+					})
+					// return
+					// this.showBtn = true
+					// this.scale = 18
+					// wx.setNavigationBarTitle({
+					// 	title: "轨迹"
+					// })
+					// // this.onLoad()//重新调方法 改标题,有问题
+					// this.dateTime = this.dateTime ? this.dateTime : this.formatDate(new Date())
+					// let params = {
+					// 	deviceId: this.deviceId,
+					// 	dateTime: this.dateTime,
+					// 	// deviceId:this.deviceId,
+					// 	// dateTime:this.formatDate(new Date())
+					// }
+					// infoApi.getLocationLocus(params).then(res => {
+					// 	if (res.code === 0 && res.data.length) {
+					// 		this.coordinate = res.data.map(item => {
+					// 			console.log('11111');
+					// 			return {
+					// 				latitude: item.lat,
+					// 				longitude: item.lng,
+					// 			}
+					// 		})
+					// 		_this.polyline = [{
+					// 			points: this.coordinate,
+					// 			color: '#F35546',
+					// 			width: 4,
+					// 			dottedLine: false,
+					// 		}];
+					// 		// TODO 找相关api,将轨迹缩放到合适比例,将起点终点放上图标
+					// 		_this.map.translateMarker({
+					// 			markerId: 1,
+					// 			fail(e) {
+					// 				// 轨迹回放失败
+					// 			},
+					// 		});
+					// 	} else {
+					// 		_this.polyline = [{
+					// 			points: [],
+					// 			color: '#F35546',
+					// 			width: 4,
+					// 			dottedLine: false,
+					// 		}];
+					// 		this.$util.Tips({
+					// 			title: `${this.dateTime}暂无轨迹数据`,
+					// 		}, () => {
+
+					// 		});
+					// 	}
+
+					// })
 
-				.pricehui {
-					color: #B2B2B2;
-				}
-                .fonthui{
-					background-color: #F5F5F5 !important;
-				}
-				.yuan {
-					font-size: 24rpx;
 				}
 
-				.ling {
-					font-size: 24rpx;
-					margin-top: 9.5rpx;
-					width: 102rpx;
-					height: 36rpx;
-					line-height: 36rpx;
-					background-color: #FFE5C7;
-					border-radius: 28rpx;
-					margin: auto;
-				}
+			},
+			//         start() {
+			//                 this.isStart = true;
+			//                 this.isDisabled = true;
+			//                 let data = this.coordinate;
+			//                 let len = data.length;
+			//                 let datai = data[this.playIndex];
+			//                 let _this = this;
+
+			//                 _this.map.translateMarker({
+			//                         markerId: 1,
+			//                         autoRotate: true,
+			//                         destination: {
+			//                                 longitude: datai.longitude, // 车辆即将移动到的下一个点的经度
+			//                                 latitude: datai.latitude, // 车辆即将移动到的下一个点的纬度
+			//                         },
+			//                         duration: 700,
+			//                         complete: function() {
+			//                                 _this.playIndex++;
+			//                                 if (_this.playIndex < len) {
+			//                                         _this.start(_this.playIndex, data);
+			//                                 } else {
+			//                                         console.log('okokok');
+			//                                         uni.showToast({
+			//                                                 title: '播放完成',
+			//                                                 duration: 1400,
+			//                                                 icon: 'none'
+			//                                         });
+			//                                         _this.playIndex = 0;
+			//                                         _this.isStart = false;
+			//                                         _this.isDisabled = false;
+			//                                 }
+			//                         },
+			//                         animationEnd: function() {
+			//                                 // 轨迹回放完成 处理H5端
+			//                                 _this.playIndex++;
+			//                                 if (_this.playIndex < len) {
+			//                                         _this.start(_this.playIndex, data);
+			//                                 } else {
+			//                                         console.log('okokok');
+			//                                         uni.showToast({
+			//                                                 title: '播放完成',
+			//                                                 duration: 1400,
+			//                                                 icon: 'none'
+			//                                         });
+			//                                         _this.playIndex = 0;
+			//                                         _this.isStart = false;
+			//                                         _this.isDisabled = false;
+			//                                 }
+			//                         },
+			//                         fail(e) {
+			//                                 // 轨迹回放失败
+			//                         },
+			//                 });
+			//         },
+			// },
+
+			// addMarkers() {
+			//         let _this = this;
+			//         const positions = [{
+			//                 latitude: 23.099994,
+			//                 longitude: 113.324520,
+			//         }, {
+			//                 latitude: 23.099994,
+			//                 longitude: 113.322520,
+			//         }, {
+			//                 latitude: 23.099994,
+			//                 longitude: 113.326520,
+			//         }, {
+			//                 latitude: 23.096994,
+			//                 longitude: 113.329520,
+			//         }]
+
+			//         const markers = []
+
+			//         positions.forEach((p, i) => {
+			//                 console.log(i)
+			//                 markers.push(
+			//                         Object.assign({}, {
+			//                                 id: i + 1,
+			//                                 iconPath: "http://cdn.zhoukaiwen.com/car.png",
+			//                                 width: 50,
+			//                                 height: 50,
+			//                                 joinCluster: true, // 指定了该参数才会参与聚合
+			//                                 label: {
+			//                                         width: 50,
+			//                                         height: 30,
+			//                                         borderWidth: 1,
+			//                                         borderRadius: 10,
+			//                                         bgColor: '#ffffff',
+			//                                         content: `label ${i + 1}`
+			//                                 }
+			//                         }, p)
+			//                 )
+			//         })
+			//         _this.map.addMarkers({
+			//                 markers,
+			//                 clear: false,
+			//                 complete(res) {
+			//                         console.log('addMarkers', res)
+			//                 }
+			//         })
+			// },
+			initmap(type) {
+				AMapLoader.load({
+						// key: '2d7215a1d0f8893f2417d134af7c3798',
+						key: 'c968deab485d6e688e7c68689722ffb4',
+						version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+						plugins: [
+							'AMap.Autocomplete',
+							'AMap.PlaceSearch',
+							'AMap.Scale',
+							'AMap.OverView',
+							'AMap.ToolBar',
+							'AMap.MapType',
+							'AMap.PolyEditor',
+							'AMap.CircleEditor',
+							'MarkerClusterer',
+							'AMap.Geocoder'
+						]
 
-				.priceM {
-					color: #FFDAAF;
-					font-size: 22rpx;
-					margin-top: 14rpx;
-				}
-			}
-		}
-	}
+					})
+					.then((AMap) => {
+						console.log('AMap', AMap)
+						// 地图初始化
+						// Map构造函数第一个传参的map为初始化地图的容器的id,第二个传参是配置对象
+						var map = new AMap.Map('amap', {
+							zoom: 15, //显示的缩放级别
+							// zooms: [2, 30], //地图显示的缩放级别范围, 默认为 [2, 20] ,取值范围 [2 ~ 30]
+							// center: [108.954239, 34.265472], //todo 中心点坐标
+							mapStyle: 'amap://styles/macaron', //todo 地图样式
+							resizeEnable: true //是否监控地图容器尺寸变化
+						});
+						/** 定位 */
+						let marker = new AMap.Marker();
+						if (this.aaa.length) {
+							map.setCenter(this.aaa);
+							map.add(marker);
+							marker.setPosition(this.aaa);
+						}
 
-	.sticky-box {
-		/* #ifndef APP-PLUS-NVUE */
-		display: flex;
-		position: -webkit-sticky;
-		/* #endif */
-		position: sticky;
-		/* #ifdef H5*/
-		top: var(--window-top);
-		/* #endif */
-
-		z-index: 99;
-		flex-direction: row;
-		margin: 0px;
-		background: #f5f5f5;
-		padding: 30rpx 0;
-	}
+						/** 轨迹 */
+						if (type === 3) {
+							this.showInfo = false
+							console.log('进来');
+							map.clearMap();
+							marker?.hide()
+							const historyList = [{
+									"lat": 39.91055750509886,
+									"lng": 116.4036806180665,
+									"gpsTime": "2023-10-08 13:47:14",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.910380195191074,
+									"lng": 116.74977990361894,
+									"gpsTime": "2023-10-08 14:08:14",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.91055750509886,
+									"lng": 116.4036806180665,
+									"gpsTime": "2023-10-08 14:26:00",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.91055750509886,
+									"lng": 116.4036806180665,
+									"gpsTime": "2023-10-08 14:27:00",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.91055750509886,
+									"lng": 116.4036806180665,
+									"gpsTime": "2023-10-08 14:30:00",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.910557505765034,
+									"lng": 116.40368361866521,
+									"gpsTime": "2023-10-08 14:31:00",
+									"gpsId": 867605051108718,
+									"compensate": null
+								},
+								{
+									"lat": 39.032391,
+									"lng": 117.662369,
+									"gpsTime": "2023-10-08 19:10:00",
+									"gpsId": 867605051108718,
+									"compensate": null
+								}
+							]
+							AMap.plugin('AMap.Driving', function() {
+								if (historyList.length >= 2) {
+									var drivingOption = {
+										policy: AMap.DrivingPolicy
+											.LEAST_TIME, // 其它policy参数请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingPolicy
+										ferry: 1, // 是否可以使用轮渡
+										province: '京', // 车牌省份的汉字缩写  
+									}
+									// 构造路线导航类
+									var driving = new AMap.Driving(drivingOption)
+
+									// 根据起终点经纬度规划驾车导航路线
+									driving.search(new AMap.LngLat(historyList[0].lng, historyList[0]
+											.lat),
+										new AMap.LngLat(historyList[historyList.length - 1].lng,
+											historyList[historyList.length - 1].lat),
+										function(status, result) {
+											if (status === 'complete') {
+												if (result.routes && result.routes.length) {
+													console.log(result.routes, 'result.routes');
+													// 绘制第一条路线,也可以按需求绘制其它几条路线
+													drawRoute(result.routes[0])
+													console.log('绘制驾车路线完成')
+												}
+											} else {
+												console.log('获取驾车数据失败:' + result)
+											}
+										});
+
+									function drawRoute(route) {
+										var path = parseRouteToPath(route)
+
+										var startMarker = new AMap.Marker({
+											position: path[0],
+											icon: 'https://webapi.amap.com/theme/v1.3/markers/n/start.png',
+											map: map
+										})
+
+										var endMarker = new AMap.Marker({
+											position: path[path.length - 1],
+											icon: 'https://webapi.amap.com/theme/v1.3/markers/n/end.png',
+											map: map
+										})
+
+										var routeLine = new AMap.Polyline({
+											path: path,
+											isOutline: true,
+											outlineColor: '#ffeeee',
+											borderWeight: 2,
+											strokeWeight: 5,
+											strokeOpacity: 0.9,
+											strokeColor: '#F35546',
+											lineJoin: 'round'
+										})
+
+										map.add(routeLine);
+
+										// 调整视野达到最佳显示区域
+										map.setFitView([startMarker, endMarker, routeLine])
+									}
+
+									// 解析DrivingRoute对象,构造成AMap.Polyline的path参数需要的格式
+									// DrivingResult对象结构参考文档 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DriveRoute
+									function parseRouteToPath(route) {
+										var path = []
+
+										for (var i = 0, l = route.steps.length; i < l; i++) {
+											var step = route.steps[i]
+
+											for (var j = 0, n = step.path.length; j < n; j++) {
+												path.push(step.path[j])
+											}
+										}
+
+										return path
+									}
 
-	.listAll {
-		width: 20%;
-		text-indent: 62rpx;
-		font-size: 30rpx;
-		border-left: 1px #eee solid;
-		margin: 1% 0;
-		padding: 5rpx;
-		position: relative;
+								}
+							})
+						}
 
-		image {
-			position: absolute;
-			left: 20rpx;
-			top: 8rpx;
+					})
+					.catch((e) => {
+						console.error(e) //加载错误提示
+					})
+			},
 		}
-	}
+	};
+</script>
 
-	.tab {
+<style lang="scss">
+	.map-box {
+		z-index: 888;
+		width: 100%;
+		height: 100vh;
 		position: relative;
-		display: flex;
-		font-size: 28rpx;
-		white-space: nowrap;
-
-		&__item {
-			flex: 1;
-			padding: 0 20rpx;
-			text-align: center;
-			height: 60rpx;
-			line-height: 60rpx;
-			color: #666;
 
-			&.active {
-				color: #09C2C9;
-			}
-		}
-	}
-
-	.tab__line {
-		display: block;
-		height: 6rpx;
-		position: absolute;
-		bottom: 0;
-		left: 0;
-		z-index: 1;
-		border-radius: 3rpx;
-		position: relative;
-		background: #2FC6CD;
-	}
+		.mp-header {
+			z-index: 999;
+			position: fixed;
+			left: 0;
+			top: 0;
+			width: 100%;
+			/* #ifdef H5 */
+			padding-bottom: 20rpx;
 
-	.scroll-view_H {
-		/* 文本不会换行,文本会在在同一行上继续,直到遇到 <br> 标签为止。 */
-		white-space: nowrap;
-		width: 100%;
-	}
+			/* #endif */
+			// background-color: $theme-color;
+			.serch-box {
+				height: 100%;
+				width: 210rpx;
+				background-color: #fff;
+				border-radius: 35rpx;
+				// margin: 33rpx 0 0 30rpx;
+				margin: 0 0 0 30rpx;
+
+				.serch-wrapper {
+					height: 100%;
+					align-items: center;
+					padding: 19rpx;
+					box-sizing: border-box;
 
+					image {
+						width: 118rpx;
+						height: 42rpx;
+					}
 
-	.privacy-wrapper {
-		z-index: 999;
-		position: fixed;
-		left: 0;
-		top: 0;
-		width: 100%;
-		height: 100%;
-		background: #7F7F7F;
+					.logo {
+						width: 32rpx;
+						height: 32rpx;
+						display: flex;
+					}
 
-		.privacy-box {
-			position: absolute;
-			left: 50%;
-			top: 50%;
-			transform: translate(-50%, -50%);
-			width: 560rpx;
-			padding: 50rpx 45rpx 0;
-			background: #fff;
-			border-radius: 20rpx;
-
-			.title {
-				text-align: center;
-				font-size: 32rpx;
-				text-align: center;
-				color: #333;
-				font-weight: 700;
-			}
+					.arrow {
+						width: 48rpx;
+						height: 48rpx;
+					}
 
-			.content {
-				margin-top: 20rpx;
-				line-height: 1.5;
-				font-size: 26rpx;
-				color: #666;
-				text-indent: 54rpx;
+					.name {
+						flex: 1;
+						text-align: center;
+						color: #7C7C7C;
+						font-size: 36rpx;
+						margin: 0 13rpx 0 18rpx;
+						white-space: nowrap;
+					}
 
-				i {
-					font-style: normal;
-					color: $theme-color;
+					.input {
+						display: flex;
+						align-items: center;
+						/* #ifdef MP */
+						width: 305rpx;
+						/* #endif */
+						height: 50rpx;
+						padding: 0 0 0 30rpx;
+						background: rgba(247, 247, 247, 1);
+						border: 1px solid rgba(241, 241, 241, 1);
+						border-radius: 29rpx;
+						color: #BBBBBB;
+						font-size: 28rpx;
+
+						.iconfont {
+							margin-right: 20rpx;
+						}
+					}
 				}
 			}
 
-			.btn-box {
-				margin-top: 40rpx;
-				text-align: center;
-				font-size: 30rpx;
-
-				.btn-item {
-					height: 82rpx;
-					line-height: 82rpx;
-					background: linear-gradient(90deg, #F67A38 0%, #F11B09 100%);
-					color: #fff;
-					border-radius: 41rpx;
-				}
-
-				.btn {
-					padding: 30rpx 0;
-				}
-			}
 		}
-	}
 
-	.page-index {
-		display: flex;
-		flex-direction: column;
-		min-height: 100%;
-		background: linear-gradient(180deg, #fff 0%, #f5f5f5 100%);
-
-		.header {
+		#map {
 			width: 100%;
-			background-color: $theme-color;
-			padding: 28rpx 30rpx;
-
-			.serch-wrapper {
-				align-items: center;
-
-
-				.logo {
-					width: 118rpx;
-					height: 42rpx;
-					margin-right: 24rpx;
-				}
+			height: 100%;
+		}
 
-				image {
-					width: 118rpx;
-					height: 42rpx;
-				}
+		::v-deep .uni-image[src^="https://app.tjzhxx.cn:11443/"] {
+			border: 2px solid red;
+			/* 添加2px宽的红色边框 */
+			border-radius: 50%;
+			/* 可选,设置为圆形边框 */
+		}
 
-				.input {
-					display: flex;
-					align-items: center;
-					width: 546rpx;
-					height: 58rpx;
-					padding: 0 0 0 30rpx;
-					background: rgba(247, 247, 247, 1);
-					border: 1px solid rgba(241, 241, 241, 1);
-					border-radius: 29rpx;
-					color: #BBBBBB;
-					font-size: 26rpx;
-
-					.iconfont {
-						margin-right: 20rpx;
-						font-size: 26rpx;
-						color: #666666;
-					}
-				}
-			}
+		.custom-marker {
+			position: relative;
+			width: 42px;
+			/* 根据您的标记点图标宽度调整 */
+			height: 47px;
+			/* 根据您的标记点图标高度调整 */
+		}
 
-			.tabNav {
-				padding-top: 24rpx;
-			}
+		.custom-marker img {
+			width: 100%;
+			height: 100%;
+			/* 在这里添加您需要的自定义CSS样式 */
+			border: 1rpx solid red;
 		}
 
-		/* #ifdef MP */
-		.mp-header {
+		.loading {
 			z-index: 999;
-			position: fixed;
-			left: 0;
-			top: 0;
 			width: 100%;
-			/* #ifdef H5 */
-			padding-bottom: 20rpx;
-			/* #endif */
-			background-color: $theme-color;
-
-			.serch-wrapper {
-				height: 100%;
-				align-items: center;
-				padding: 0 50rpx 0 53rpx;
-
-				image {
-					width: 118rpx;
-					height: 42rpx;
-					margin-right: 30rpx;
-				}
-
-				.input {
-					display: flex;
-					align-items: center;
-					/* #ifdef MP */
-					width: 305rpx;
-					/* #endif */
-					height: 50rpx;
-					padding: 0 0 0 30rpx;
-					background: rgba(247, 247, 247, 1);
-					border: 1px solid rgba(241, 241, 241, 1);
-					border-radius: 29rpx;
-					color: #BBBBBB;
-					font-size: 28rpx;
-
-					.iconfont {
-						margin-right: 20rpx;
-					}
-				}
-			}
+			top: 30%;
+			// left:50%;
+			position: absolute;
 		}
 
-		/* #endif */
-
-		.page_content {
-			background-color: #f5f5f5;
-			/* #ifdef H5 */
-			// margin-top: 20rpx !important;
-			/* #endif */
-			padding: 0 30rpx;
+		.top-input::before {
+			content: "";
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			height: 100%;
+			background: #FF0000;
+			opacity: 0.1;
+			filter: blur(50px);
+			z-index: 66;
+			pointer-events: none;
+		}
 
-			.swiper {
-				position: relative;
+		.top-input {
+			width: 70%;
+			height: 45%;
+			top: 20%;
+			left: 15%;
+			text-align: center;
+			position: absolute;
+			box-sizing: border-box;
+			font-size: 32rpx;
+			font-weight: 500;
+			color: #000000;
+			// border: 1rpx solid red;
+			padding: 119rpx 90rpx;
+
+			image {
 				width: 100%;
-				height: 280rpx;
-				margin: 0 auto;
-				border-radius: 10rpx;
-				overflow: hidden;
-				margin-bottom: 25rpx;
-				/* #ifdef MP */
-				z-index: 10;
-				margin-top: 20rpx;
-
-				/* #endif */
-				swiper,
-				.swiper-item,
-				image {
-					width: 100%;
-					height: 280rpx;
-					border-radius: 10rpx;
-				}
+				height: 368rpx;
 			}
 
-			.nav {
-				padding-bottom: 26rpx;
-				background: #fff;
-				opacity: 1;
-				border-radius: 14rpx;
+			.btn-box {
+				z-index: 999;
 				width: 100%;
-				margin-bottom: 30rpx;
-
-				.item {
-					display: flex;
-					flex-direction: column;
-					align-items: center;
-					justify-content: center;
-					width: 20%;
-					margin-top: 30rpx;
-
-					image {
-						width: 82rpx;
-						height: 82rpx;
-					}
-				}
-			}
-
-
-			.nav-bd {
 				display: flex;
 				align-items: center;
-				justify-content: space-between;
+				justify-content: center;
 
-				.item {
+				.btn {
+					background: rgba(255, 247, 247, 0.3);
+					border-radius: 35rpx;
+					border: 3rpx solid #EC3534;
+					margin-top: 42rpx;
+					width: 236rpx;
+					height: 70rpx;
 					display: flex;
-					flex-direction: column;
 					align-items: center;
 					justify-content: center;
+					font-weight: 600;
+					font-size: 36rpx;
+					color: #EC3534;
+				}
+			}
+		}
 
-					.txt {
-						font-size: 32rpx;
-						color: #282828;
-					}
-
-					.label {
-						display: flex;
-						align-items: center;
-						justify-content: center;
-						width: 124rpx;
-						height: 32rpx;
-						margin-top: 5rpx;
-						font-size: 24rpx;
-						color: #999;
-					}
+		// .top-input {
+		// 	width: 70%;
+		// 	height: 45%;
+		// 	top: 20%;
+		// 	left: 15%;
+		// 	text-align: center;
+		// 	position: absolute;
+		// 	box-sizing: border-box;
+		// 	font-size: 32rpx;
+		// 	font-weight: 500;
+		// 	color: #000000;
+		// 	border: 1rpx solid red;
+		// 	background: #FF0000;
+		// 	opacity: 0.4;
+		// 	filter: blur(50px);
+		// 	padding:119rpx 90rpx;
+		// 	image{
+		// 		width: 100%;
+		// 		height: 368rpx;
+		// 	}
+		// 	.btn-box{
+		// 		width: 100%;
+		// 		display: flex;
+		// 		align-items: center;
+		// 		justify-content: center;
+		// 		.btn{
+		// 			background: rgba(255,247,247,0.3);
+		// 			border-radius: 35rpx;
+		// 			border: 3rpx solid #EC3534;
+		// 			margin-top: 42rpx;
+		// 			width: 236rpx;
+		// 			height: 70rpx;
+		// 			display: flex;
+		// 			align-items: center;
+		// 			justify-content: center;
+		// 		}
+		// 	}
+
+		// }
+
+		.info-box {
+			width: 100%;
+			height: 40%;
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			position: absolute;
+			bottom: 75rpx;
+			z-index: 1000;
+			// background-color: #fff;
+			padding: 0 30rpx 0;
+			font-size: 32rpx;
+			font-weight: 400;
+			color: #000000;
+			box-sizing: border-box;
+
+			.scroll-view_H {
+				width: 100%;
+				height: 80%;
+
+				/* 设置适当的高度 */
+				.scroll-view-content {
+					height: 100%;
+					white-space: nowrap;
+					font-size: 0;
+					overflow-x: auto;
+
+					.scroll-view-item_H {
+						width: 50%;
+						height: 100%;
+						display: inline-block;
+						font-size: 16px;
+						margin-right: 15rpx;
+						position: relative;
+
+						.bg-image {
+							width: 100%;
+							height: 100%;
+							object-fit: cover;
+						}
 
-					&.active {
-						color: $theme-color;
+						.text-wrapper {
+							position: absolute;
+							top: 0;
+							left: 0;
+							width: 100%;
+							height: 100%;
+							display: flex;
+							justify-content: flex-start;
+							padding: 60rpx 30rpx 0;
+						}
 
-						.txt {
-							color: $theme-color;
+						.black {
+							color: #2D2D2D;
 						}
 
-						.label {
-							background: linear-gradient(90deg, $bg-star 0%, $bg-end 100%);
-							border-radius: 16rpx;
+						.white {
 							color: #fff;
 						}
-					}
-				}
-			}
-
-			.index-product-wrapper {
-				margin-bottom: 110rpx;
-
-				&.on {
-					min-height: 1500rpx;
-				}
-
-				.list-box {
-					display: flex;
-					flex-wrap: wrap;
-					justify-content: space-between;
-
-					.item {
-						width: 335rpx;
-						margin-bottom: 20rpx;
-						background-color: #fff;
-						border-radius: 10rpx;
-						overflow: hidden;
 
-						image {
+						.text-overlay {
+							// color: white;
+							font-size: 16px;
 							width: 100%;
-							height: 330rpx;
-						}
+							overflow: hidden;
 
-						.text-info {
-							padding: 10rpx 20rpx 15rpx;
+							.top-box {
+								display: flex;
+								justify-content: space-between;
 
-							.title {
-								color: #222222;
-							}
+								.top-left {
+									.english {
+										font-size: 24rpx;
+									}
 
-							.old-price {
-								margin-top: 8rpx;
-								font-size: 26rpx;
-								color: #AAAAAA;
-								text-decoration: line-through;
+									.chinese {
+										font-size: 32rpx;
+									}
+								}
 
-								text {
-									margin-right: 2px;
-									font-size: 20rpx;
+								.top-right {
+									width: 76rpx;
+									height: 76rpx;
+									border-radius: 50%;
 								}
 							}
 
-							.price {
+							.under-box {
+								margin-top: 8rpx;
 								display: flex;
+								justify-content: space-between;
 								align-items: flex-end;
-								color: $theme-color;
-								font-size: 34rpx;
-								font-weight: 800;
-
-								text {
-									padding-bottom: 4rpx;
-									font-size: 24rpx;
-									font-weight: 800;
+
+								.under-left {
+									color: #EC3534;
+
+									.number {
+										font-size: 36rpx;
+										font-weight: 600;
+									}
+
+									.unit {
+										font-size: 28rpx;
+										font-weight: 500;
+									}
 								}
 
-								.txt {
-									display: flex;
-									align-items: center;
-									justify-content: center;
-									width: 28rpx;
-									height: 28rpx;
-									margin-left: 15rpx;
-									margin-bottom: 10rpx;
-									border: 1px solid $theme-color;
-									border-radius: 4rpx;
-									font-size: 22rpx;
-									font-weight: normal;
+								.under-right {
+									font-weight: 500;
+
+									.range {
+										font-size: 24rpx;
+									}
+
+									.range-word {
+										font-size: 24rpx;
+									}
+								}
+
+								.white {
+									color: #fff;
 								}
 							}
 						}
 					}
-
-					&.on {
-						display: flex;
-					}
 				}
 			}
-		}
-	}
 
-	.productList {
-		/* #ifdef H5 */
-		padding-bottom: 140rpx;
-		/* #endif */
-	}
+			.sos-btn {
+				width: 100%;
+				height: 140rpx;
 
-	.productList .list {
-		padding: 0 20rpx;
-	}
+				image {
+					width: 100%;
+					height: 100%;
+				}
+			}
 
-	.productList .list.on {
-		background-color: #fff;
-		border-top: 1px solid #f6f6f6;
-	}
 
-	.productList .list .item {
-		width: 345rpx;
-		margin-top: 20rpx;
-		background-color: #fff;
-		border-radius: 10rpx;
-	}
 
-	.productList .list .item.on {
-		width: 100%;
-		display: flex;
-		border-bottom: 1rpx solid #f6f6f6;
-		padding: 30rpx 0;
-		margin: 0;
-	}
 
-	.productList .list .item .pictrue {
-		position: relative;
-		width: 100%;
-		height: 345rpx;
-	}
 
-	.productList .list .item .pictrue.on {
-		width: 180rpx;
-		height: 180rpx;
-	}
 
-	.productList .list .item .pictrue image {
-		width: 100%;
-		height: 100%;
-		border-radius: 20rpx 20rpx 0 0;
-	}
-
-	.productList .list .item .pictrue image.on {
-		border-radius: 6rpx;
-	}
 
-	.productList .list .item .text {
-		padding: 20rpx 17rpx 26rpx 17rpx;
-		font-size: 30rpx;
-		color: #222;
-	}
 
-	.productList .list .item .text.on {
-		width: 508rpx;
-		padding: 0 0 0 22rpx;
-	}
 
-	.productList .list .item .text .money {
-		font-size: 26rpx;
-		font-weight: bold;
-		margin-top: 8rpx;
-	}
+			.code {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #000000;
+			}
 
-	.productList .list .item .text .money.on {
-		margin-top: 50rpx;
-	}
+			.time {
+				font-size: 28rpx;
+				font-weight: 400;
+				color: #999999;
+				margin: 10rpx 0 16rpx;
+				display: flex;
+				align-items: center;
 
-	.productList .list .item .text .money .num {
-		font-size: 34rpx;
-	}
+				.online-box {
+					margin-right: 25rpx;
+					width: 55rpx;
+					height: 30rpx;
 
-	.productList .list .item .text .vip {
-		font-size: 22rpx;
-		color: #aaa;
-		margin-top: 7rpx;
-	}
+					image {
+						width: 100%;
+						height: 100%;
+					}
+				}
+			}
 
-	.productList .list .item .text .vip.on {
-		margin-top: 12rpx;
-	}
+			.position {
+				// margin-top: 16rpx;
+			}
+		}
 
-	.productList .list .item .text .vip .vip-money {
-		font-size: 24rpx;
-		color: #282828;
-		font-weight: bold;
-	}
+		.icon-box {
+			width: 10%;
+			height: 30%;
+			top: 20%;
+			position: absolute;
+			left: 5%;
+			display: flex;
+			background-color: #ECECEC;
+			flex-direction: column;
+			justify-content: space-between;
+			border-radius: 10rpx;
+
+			.img-box {
+				text-align: center;
+				height: 24.5%;
+				line-height: 130rpx;
+				background-color: #fff;
 
-	.productList .list .item .text .vip .vip-money image {
-		width: 46rpx;
-		height: 21rpx;
-		margin-left: 4rpx;
-	}
+				image {
+					width: 42rpx;
+					height: 42rpx;
+				}
+			}
 
-	.pictrue {
-		position: relative;
-	}
+			.first {
+				border-radius: 10rpx 10rpx 0 0;
+			}
 
-	.fixed {
-		z-index: 100;
-		position: fixed;
-		left: 0;
-		top: 0;
-		background: linear-gradient(90deg, red 50%, #ff5400 100%);
+			.last {
+				border-radius: 0 0 10rpx 10rpx;
+			}
 
-	}
+			image {
+				width: 42rpx;
+				height: 42rpx;
+			}
 
-	.mores-txt {
-		width: 100%;
-		align-items: center;
-		justify-content: center;
-		height: 70rpx;
-		color: #999;
-		font-size: 24rpx;
-
-		.iconfont {
-			margin-top: 2rpx;
-			font-size: 20rpx;
 		}
-	}
 
-	.menu-txt {
-		font-size: 24rpx;
-		color: #454545;
-	}
-
-	.mp-bg {
-		position: absolute;
-		left: 0;
-		/* #ifdef H5 */
-		top: 98rpx;
-		/* #endif */
-		width: 100%;
-		height: 304rpx;
-		background: linear-gradient(180deg, #E93323 0%, #F5F5F5 100%, #751A12 100%);
-		// border-radius: 0 0 30rpx 30rpx;
+		.icon-box-right {
+			width: 10%;
+			height: 25%;
+			top: 10%;
+			position: absolute;
+			right: 5%;
+			display: flex;
+			flex-direction: column;
+			justify-content: space-between;
+
+			image {
+				width: 70rpx;
+				height: 70rpx;
+			}
+		}
 	}
-</style>
+</style>

BIN
static/img/addequ.png


BIN
static/img/addicon.png


BIN
static/img/arrow.png


BIN
static/img/breathe-icon.png


BIN
static/img/breathe.png


BIN
static/img/heart-icon.png


BIN
static/img/heart.png


BIN
static/img/none.png


BIN
static/img/noneEqu.png


BIN
static/img/scan.png


BIN
static/img/sleep-icon.png


BIN
static/img/sleep.png


BIN
static/img/sos.png


BIN
static/img/unbreathe-icon.png


BIN
static/img/unheart-icon.png


BIN
static/img/unsleep-icon.png


+ 2 - 1
store/getters.js

@@ -9,5 +9,6 @@ export default {
 	chatUrl: state => state.app.chatUrl,
 	systemPlatform: state => state.app.systemPlatform,
 	openid: state => state.app.openid,
-	productType: state => state.app.productType
+	productType: state => state.app.productType,
+	deviceCode: state => state.app.deviceCode
 };

+ 7 - 1
store/modules/app.js

@@ -19,7 +19,8 @@ const state = {
 	homeActive: false,
 	chatUrl: Cache.get('chatUrl') || '',
 	systemPlatform: Cache.get(PLATFORM)?Cache.get(PLATFORM):'',
-	productType: Cache.get('productType') || ''
+	productType: Cache.get('productType') || '',
+	deviceCode: Cache.get('deviceCode') || ''
 };
 
 const mutations = {
@@ -75,6 +76,11 @@ const mutations = {
 	PRODUCT_TYPE(state, productType) {
 		state.productType = productType;
 		Cache.set('productType', productType);
+	},
+	DEVICE_CODE(state, deviceCode) {
+		console.log(deviceCode,'我是vuex里的数据');
+		state.deviceCode = deviceCode;
+		Cache.set('deviceCode', deviceCode);
 	}
 };
 

+ 108 - 0
utils/request - 副本.js

@@ -0,0 +1,108 @@
+import {
+	HTTP_REQUEST_URL,
+	HEADER,
+	TOKENNAME,
+	HEADERPARAMS
+} from '@/config/app';
+import {
+	toLogin,
+	checkLogin
+} from '../libs/login';
+import store from '../store';
+import {getTerminal} from "./util";
+
+// TODO 芋艿:临时解决 uniapp 在小程序,undefined 会被 tostring 的问题
+function deleteUndefinedProperties(obj) {
+  for (let key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      if (typeof obj[key] === 'object' && obj[key] !== null) {
+        deleteUndefinedProperties(obj[key]); // 递归调用,处理嵌套的对象
+      } else if (obj[key] === undefined) {
+        delete obj[key];
+      }
+    }
+  }
+}
+
+/**
+ * 发送请求
+ */
+function baseRequest(url, method, data, {
+	noAuth = false,
+	noVerify = false
+}, params) {
+	let Url = HTTP_REQUEST_URL,header = HEADER
+	if (params != undefined) {
+		header = HEADERPARAMS;
+	}
+	if (!noAuth) {
+		//登录过期自动登录
+		if (!store.state.app.token && !checkLogin()) {
+      // debugger
+			toLogin();
+			return Promise.reject({
+				msg: '未登录'
+			});
+		}
+	}
+
+  deleteUndefinedProperties(data)
+
+  // TODO 补个 header 多租户
+  if (url.indexOf('app-api') >= 0) {
+    header = {
+      ...header
+    }
+    header['tenant-id'] = 1
+  }
+
+  	// 终端
+	header['terminal'] = getTerminal()
+
+	if (store.state.app.token) {
+    // header[TOKENNAME] = store.state.app.token;
+    header['Authorization'] = 'Bearer ' + store.state.app.token;
+  }
+  const isUseSleep = uni.getStorageSync("useSleep")
+  console.log(uni.getStorageSync("useSleep"),'判断从哪来的,true代表从首页来'); 
+  // : 'http://yunai.natapp1.cc/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://127.0.0.1:48080/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://api-dashboard.yudao.iocoder.cn/' + url, // TODO 芋艿:搞个 url 的配置
+  const baseUrl='http://192.168.110.185:48060/'
+  const sleepUrl='http://api.slaaplekker.cn'
+	return new Promise((reslove, reject) => {
+		uni.request({
+			// url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url
+      // url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url:(isUseSleep ? sleepUrl+url: baseUrl + url), // TODO 芋艿:搞个 url 的配置
+		// url: isUseSleep ?sleepUrl+url:(url.indexOf('app-api') < 0 ? Url + '/api/front/' + url : baseUrl + url),
+		url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url:baseUrl+url,
+      method: method || 'GET',
+			header: header,
+			data: data || {},
+			success: (res) => {
+				if (noVerify)
+					reslove(res.data, res);
+				else if (res.data.code === 200 || res.data.code === 0)
+					reslove(res.data, res);
+				else if ([410000, 410001, 410002, 401].indexOf(res.data.code) !== -1) {
+					toLogin();
+					reject(res.data);
+				} else
+					reject(res.data.msg || res.data.message || '系统错误');
+			},
+			fail: (msg) => {
+				reject('请求失败');
+			}
+		})
+	});
+}
+
+const request = {};
+
+['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
+	request[method] = (api, data, opt, params) => baseRequest(api, method, data, opt || {}, params)
+});
+
+
+
+export default request;

+ 11 - 5
utils/request.js

@@ -63,14 +63,20 @@ function baseRequest(url, method, data, {
     // header[TOKENNAME] = store.state.app.token;
     header['Authorization'] = 'Bearer ' + store.state.app.token;
   }
+  const isUseSleep = uni.getStorageSync("useSleep")
+  console.log(uni.getStorageSync("useSleep"),'判断从哪来的,true代表从首页来'); 
+  // : 'http://yunai.natapp1.cc/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://127.0.0.1:48080/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://api-dashboard.yudao.iocoder.cn/' + url, // TODO 芋艿:搞个 url 的配置
+  const baseUrl='http://192.168.110.185:48060/'
+  const sleepUrl='http://api.slaaplekker.cn'
 	return new Promise((reslove, reject) => {
 		uni.request({
 			// url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url
-      url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url
-        // : 'http://yunai.natapp1.cc/' + url, // TODO 芋艿:搞个 url 的配置
-        // : 'http://127.0.0.1:48080/' + url, // TODO 芋艿:搞个 url 的配置
-        // : 'http://api-dashboard.yudao.iocoder.cn/' + url, // TODO 芋艿:搞个 url 的配置
-		: 'http://192.168.110.185:48060/' + url, // TODO 芋艿:搞个 url 的配置
+      // url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url:(isUseSleep ? sleepUrl+url: baseUrl + url), // TODO 芋艿:搞个 url 的配置
+		// url: isUseSleep ?sleepUrl+url:(url.indexOf('app-api') < 0 ? Url + '/api/front/' + url : baseUrl + url),
+		url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url
+		:'http://192.168.110.185:48060/'+url,
       method: method || 'GET',
 			header: header,
 			data: data || {},

+ 110 - 0
utils/request2.js

@@ -0,0 +1,110 @@
+import {
+	HTTP_REQUEST_URL,
+	HEADER,
+	TOKENNAME,
+	HEADERPARAMS
+} from '@/config/app';
+import {
+	toLogin,
+	checkLogin
+} from '../libs/login';
+import store from '../store';
+import {getTerminal} from "./util";
+
+// TODO 芋艿:临时解决 uniapp 在小程序,undefined 会被 tostring 的问题
+function deleteUndefinedProperties(obj) {
+  for (let key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      if (typeof obj[key] === 'object' && obj[key] !== null) {
+        deleteUndefinedProperties(obj[key]); // 递归调用,处理嵌套的对象
+      } else if (obj[key] === undefined) {
+        delete obj[key];
+      }
+    }
+  }
+}
+
+/**
+ * 发送请求
+ */
+function baseRequest(url, method, data, {
+	noAuth = false,
+	noVerify = false
+}, params) {
+	let Url = HTTP_REQUEST_URL,header = HEADER
+	if (params != undefined) {
+		header = HEADERPARAMS;
+	}
+	if (!noAuth) {
+		//登录过期自动登录
+		if (!store.state.app.token && !checkLogin()) {
+      // debugger
+			toLogin();
+			return Promise.reject({
+				msg: '未登录'
+			});
+		}
+	}
+
+  deleteUndefinedProperties(data)
+
+  // TODO 补个 header 多租户
+  if (url.indexOf('app-api') >= 0) {
+    header = {
+      ...header
+    }
+    header['tenant-id'] = 1
+  }
+
+  	// 终端
+	header['terminal'] = getTerminal()
+
+	if (store.state.app.token) {
+    // header[TOKENNAME] = store.state.app.token;
+    header['accessToken'] = '9f36cea4a4f64ba8bfb680ff98d98c1b';
+  }
+  const isUseSleep = uni.getStorageSync("useSleep")
+  console.log(uni.getStorageSync("useSleep"),'判断从哪来的,true代表从首页来'); 
+  // : 'http://yunai.natapp1.cc/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://127.0.0.1:48080/' + url, // TODO 芋艿:搞个 url 的配置
+  // : 'http://api-dashboard.yudao.iocoder.cn/' + url, // TODO 芋艿:搞个 url 的配置
+  const baseUrl='http://192.168.110.185:48060/'
+  const sleepUrl='http://api.slaaplekker.cn'
+  console.log('http://api.slaaplekker.cn/'+url,'我是请求里面的url')
+  console.log(url, '我是请求里面的url')
+	return new Promise((reslove, reject) => {
+		uni.request({
+			// url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url
+      // url: url.indexOf('app-api') < 0 ? Url + '/api/front/' + url:(isUseSleep ? sleepUrl+url: baseUrl + url), // TODO 芋艿:搞个 url 的配置
+		// url: isUseSleep ?sleepUrl+url:(url.indexOf('app-api') < 0 ? Url + '/api/front/' + url : baseUrl + url),
+		url:'http://api.slaaplekker.cn/'+url,
+      method: method || 'GET',
+			header: header,
+			data: data || {},
+			success: (res) => {
+				if (noVerify)
+					reslove(res.data, res);
+				else if (res.data.code === 200 || res.data.code === 0)
+					reslove(res.data, res);
+				else if ([410000, 410001, 410002, 401].indexOf(res.data.code) !== -1) {
+					toLogin();
+					reject(res.data);
+				} else
+					reject(res.data.msg || res.data.message || '系统错误');
+			},
+			fail: (msg) => {
+				reject('请求失败');
+			}
+		})
+	});
+}
+
+const request = {};
+
+['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
+	request[method] = (api, data, opt, params) => baseRequest(api, method, data, opt || {}, params)
+});
+
+
+
+export default request;

+ 1 - 0
wxcomponents/vant/dist/action-sheet/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 71 - 0
wxcomponents/vant/dist/action-sheet/index.js

@@ -0,0 +1,71 @@
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+VantComponent({
+    classes: ['list-class'],
+    mixins: [button],
+    props: {
+        show: Boolean,
+        title: String,
+        cancelText: String,
+        description: String,
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 100,
+        },
+        actions: {
+            type: Array,
+            value: [],
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickAction: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        onSelect(event) {
+            const { index } = event.currentTarget.dataset;
+            const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
+            const item = actions[index];
+            if (item) {
+                this.$emit('select', item);
+                if (closeOnClickAction) {
+                    this.onClose();
+                }
+                if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
+                    wx.getUserProfile({
+                        desc: item.getUserProfileDesc || '  ',
+                        complete: (userProfile) => {
+                            this.$emit('getuserinfo', userProfile);
+                        },
+                    });
+                }
+            }
+        },
+        onCancel() {
+            this.$emit('cancel');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClickOverlay() {
+            this.$emit('click-overlay');
+            this.onClose();
+        },
+    },
+});

+ 8 - 0
wxcomponents/vant/dist/action-sheet/index.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-popup": "../popup/index",
+    "van-loading": "../loading/index"
+  }
+}

+ 112 - 0
wxcomponents/vant/dist/action-sheet/index.vue

@@ -0,0 +1,112 @@
+<template>
+<uni-shadow-root class="vant-dist-action-sheet-index"><van-popup :show="show" position="bottom" :round="round" :z-index="zIndex" :overlay="overlay" custom-class="van-action-sheet custom-class" :safe-area-inset-bottom="safeAreaInsetBottom" :close-on-click-overlay="closeOnClickOverlay" @close="onClickOverlay">
+  <view v-if="title" class="van-action-sheet__header">
+    {{ title }}
+    <van-icon name="cross" custom-class="van-action-sheet__close" @click="onClose"></van-icon>
+  </view>
+  <view v-if="description" class="van-action-sheet__description van-hairline--bottom">
+    {{ description }}
+  </view>
+  <view v-if="actions && actions.length" class="list-class">
+    
+    <button v-for="(item,index) in (actions)" :key="item.index" :open-type="item.disabled || item.loading || (canIUseGetUserProfile && item.openType === 'getUserInfo') ? '' : item.openType" :style="item.color ? 'color: ' + item.color : ''" :class="(utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }))+' '+(item.className || '')" hover-class="van-action-sheet__item--hover" :data-index="index" @click="_$self[(item.disabled || item.loading ? '' : 'onSelect')||'_$noop']($event)" @getuserinfo="onGetUserInfo" @contact="onContact" @getphonenumber="onGetPhoneNumber" @error="onError" @launchapp="onLaunchApp" @opensetting="onOpenSetting" :lang="lang" :session-from="sessionFrom" :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :app-parameter="appParameter">
+      <block v-if="(!item.loading)">
+        {{ item.name }}
+        <view v-if="item.subname" class="van-action-sheet__subname">{{ item.subname }}</view>
+      </block>
+      <van-loading v-else custom-class="van-action-sheet__loading" size="22px"></van-loading>
+    </button>
+  </view>
+  <slot></slot>
+  <block v-if="cancelText">
+    <view class="van-action-sheet__gap"></view>
+    <view class="van-action-sheet__cancel" hover-class="van-action-sheet__cancel--hover" hover-stay-time="70" @click="onCancel">
+      {{ cancelText }}
+    </view>
+  </block>
+</van-popup></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+import VanPopup from '../popup/index.vue'
+import VanLoading from '../loading/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-popup': VanPopup,'van-loading': VanLoading}}
+
+global['__wxRoute'] = 'vant/dist/action-sheet/index'
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+VantComponent({
+    classes: ['list-class'],
+    mixins: [button],
+    props: {
+        show: Boolean,
+        title: String,
+        cancelText: String,
+        description: String,
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 100,
+        },
+        actions: {
+            type: Array,
+            value: [],
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickAction: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        onSelect(event) {
+            const { index } = event.currentTarget.dataset;
+            const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
+            const item = actions[index];
+            if (item) {
+                this.$emit('select', item);
+                if (closeOnClickAction) {
+                    this.onClose();
+                }
+                if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
+                    wx.getUserProfile({
+                        desc: item.getUserProfileDesc || '  ',
+                        complete: (userProfile) => {
+                            this.$emit('getuserinfo', userProfile);
+                        },
+                    });
+                }
+            }
+        },
+        onCancel() {
+            this.$emit('cancel');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClickOverlay() {
+            this.$emit('click-overlay');
+            this.onClose();
+        },
+    },
+});
+export default global['__wxComponents']['vant/dist/action-sheet/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}
+</style>

+ 69 - 0
wxcomponents/vant/dist/action-sheet/index.wxml

@@ -0,0 +1,69 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<van-popup
+  show="{{ show }}"
+  position="bottom"
+  round="{{ round }}"
+  z-index="{{ zIndex }}"
+  overlay="{{ overlay }}"
+  custom-class="van-action-sheet custom-class"
+  safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  bind:close="onClickOverlay"
+>
+  <view wx:if="{{ title }}" class="van-action-sheet__header">
+    {{ title }}
+    <van-icon
+      name="cross"
+      custom-class="van-action-sheet__close"
+      bind:click="onClose"
+    />
+  </view>
+  <view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
+    {{ description }}
+  </view>
+  <view wx:if="{{ actions && actions.length }}" class="list-class">
+    <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
+    <button
+      wx:for="{{ actions }}"
+      wx:key="index"
+      open-type="{{ item.disabled || item.loading || (canIUseGetUserProfile && item.openType === 'getUserInfo') ? '' : item.openType }}"
+      style="{{ item.color ? 'color: ' + item.color : '' }}"
+      class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
+      hover-class="van-action-sheet__item--hover"
+      data-index="{{ index }}"
+      bindtap="{{ item.disabled || item.loading ? '' : 'onSelect' }}"
+      bindgetuserinfo="onGetUserInfo"
+      bindcontact="onContact"
+      bindgetphonenumber="onGetPhoneNumber"
+      binderror="onError"
+      bindlaunchapp="onLaunchApp"
+      bindopensetting="onOpenSetting"
+      lang="{{ lang }}"
+      session-from="{{ sessionFrom }}"
+      send-message-title="{{ sendMessageTitle }}"
+      send-message-path="{{ sendMessagePath }}"
+      send-message-img="{{ sendMessageImg }}"
+      show-message-card="{{ showMessageCard }}"
+      app-parameter="{{ appParameter }}"
+    >
+      <block wx:if="{{ !item.loading }}">
+        {{ item.name }}
+        <view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
+      </block>
+      <van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
+    </button>
+  </view>
+  <slot />
+  <block wx:if="{{ cancelText }}">
+    <view class="van-action-sheet__gap" />
+    <view
+      class="van-action-sheet__cancel"
+      hover-class="van-action-sheet__cancel--hover"
+      hover-stay-time="70"
+      bind:tap="onCancel"
+    >
+      {{ cancelText }}
+    </view>
+  </block>
+</van-popup>

+ 1 - 0
wxcomponents/vant/dist/action-sheet/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}

+ 1 - 0
wxcomponents/vant/dist/area/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 220 - 0
wxcomponents/vant/dist/area/index.js

@@ -0,0 +1,220 @@
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+import { requestAnimationFrame } from '../common/utils';
+const EMPTY_CODE = '000000';
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
+            type: Boolean,
+            value: true,
+        }, value: {
+            type: String,
+            observer(value) {
+                this.code = value;
+                this.setValues();
+            },
+        }, areaList: {
+            type: Object,
+            value: {},
+            observer: 'setValues',
+        }, columnsNum: {
+            type: null,
+            value: 3,
+        }, columnsPlaceholder: {
+            type: Array,
+            observer(val) {
+                this.setData({
+                    typeToColumnsPlaceholder: {
+                        province: val[0] || '',
+                        city: val[1] || '',
+                        county: val[2] || '',
+                    },
+                });
+            },
+        } }),
+    data: {
+        columns: [{ values: [] }, { values: [] }, { values: [] }],
+        typeToColumnsPlaceholder: {},
+    },
+    mounted() {
+        requestAnimationFrame(() => {
+            this.setValues();
+        });
+    },
+    methods: {
+        getPicker() {
+            if (this.picker == null) {
+                this.picker = this.selectComponent('.van-area__picker');
+            }
+            return this.picker;
+        },
+        onCancel(event) {
+            this.emit('cancel', event.detail);
+        },
+        onConfirm(event) {
+            const { index } = event.detail;
+            let { value } = event.detail;
+            value = this.parseValues(value);
+            this.emit('confirm', { value, index });
+        },
+        emit(type, detail) {
+            detail.values = detail.value;
+            delete detail.value;
+            this.$emit(type, detail);
+        },
+        parseValues(values) {
+            const { columnsPlaceholder } = this.data;
+            return values.map((value, index) => {
+                if (value &&
+                    (!value.code || value.name === columnsPlaceholder[index])) {
+                    return Object.assign(Object.assign({}, value), { code: '', name: '' });
+                }
+                return value;
+            });
+        },
+        onChange(event) {
+            var _a;
+            const { index, picker, value } = event.detail;
+            this.code = value[index].code;
+            (_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
+                this.$emit('change', {
+                    picker,
+                    values: this.parseValues(picker.getValues()),
+                    index,
+                });
+            });
+        },
+        getConfig(type) {
+            const { areaList } = this.data;
+            return (areaList && areaList[`${type}_list`]) || {};
+        },
+        getList(type, code) {
+            if (type !== 'province' && !code) {
+                return [];
+            }
+            const { typeToColumnsPlaceholder } = this.data;
+            const list = this.getConfig(type);
+            let result = Object.keys(list).map((code) => ({
+                code,
+                name: list[code],
+            }));
+            if (code != null) {
+                // oversea code
+                if (code[0] === '9' && type === 'city') {
+                    code = '9';
+                }
+                result = result.filter((item) => item.code.indexOf(code) === 0);
+            }
+            if (typeToColumnsPlaceholder[type] && result.length) {
+                // set columns placeholder
+                const codeFill = type === 'province'
+                    ? ''
+                    : type === 'city'
+                        ? EMPTY_CODE.slice(2, 4)
+                        : EMPTY_CODE.slice(4, 6);
+                result.unshift({
+                    code: `${code}${codeFill}`,
+                    name: typeToColumnsPlaceholder[type],
+                });
+            }
+            return result;
+        },
+        getIndex(type, code) {
+            let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+            const list = this.getList(type, code.slice(0, compareNum - 2));
+            // oversea code
+            if (code[0] === '9' && type === 'province') {
+                compareNum = 1;
+            }
+            code = code.slice(0, compareNum);
+            for (let i = 0; i < list.length; i++) {
+                if (list[i].code.slice(0, compareNum) === code) {
+                    return i;
+                }
+            }
+            return 0;
+        },
+        setValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return;
+            }
+            let code = this.code || this.getDefaultCode();
+            const provinceList = this.getList('province');
+            const cityList = this.getList('city', code.slice(0, 2));
+            const stack = [];
+            const indexes = [];
+            const { columnsNum } = this.data;
+            if (columnsNum >= 1) {
+                stack.push(picker.setColumnValues(0, provinceList, false));
+                indexes.push(this.getIndex('province', code));
+            }
+            if (columnsNum >= 2) {
+                stack.push(picker.setColumnValues(1, cityList, false));
+                indexes.push(this.getIndex('city', code));
+                if (cityList.length && code.slice(2, 4) === '00') {
+                    [{ code }] = cityList;
+                }
+            }
+            if (columnsNum === 3) {
+                stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
+                indexes.push(this.getIndex('county', code));
+            }
+            return Promise.all(stack)
+                .catch(() => { })
+                .then(() => picker.setIndexes(indexes))
+                .catch(() => { });
+        },
+        getDefaultCode() {
+            const { columnsPlaceholder } = this.data;
+            if (columnsPlaceholder.length) {
+                return EMPTY_CODE;
+            }
+            const countyCodes = Object.keys(this.getConfig('county'));
+            if (countyCodes[0]) {
+                return countyCodes[0];
+            }
+            const cityCodes = Object.keys(this.getConfig('city'));
+            if (cityCodes[0]) {
+                return cityCodes[0];
+            }
+            return '';
+        },
+        getValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return [];
+            }
+            return this.parseValues(picker.getValues().filter((value) => !!value));
+        },
+        getDetail() {
+            const values = this.getValues();
+            const area = {
+                code: '',
+                country: '',
+                province: '',
+                city: '',
+                county: '',
+            };
+            if (!values.length) {
+                return area;
+            }
+            const names = values.map((item) => item.name);
+            area.code = values[values.length - 1].code;
+            if (area.code[0] === '9') {
+                area.country = names[1] || '';
+                area.province = names[2] || '';
+            }
+            else {
+                area.province = names[0] || '';
+                area.city = names[1] || '';
+                area.county = names[2] || '';
+            }
+            return area;
+        },
+        reset(code) {
+            this.code = code || '';
+            return this.setValues();
+        },
+    },
+});

+ 6 - 0
wxcomponents/vant/dist/area/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-picker": "../picker/index"
+  }
+}

+ 234 - 0
wxcomponents/vant/dist/area/index.vue

@@ -0,0 +1,234 @@
+<template>
+<uni-shadow-root class="vant-dist-area-index"><van-picker class="van-area__picker" active-class="active-class" toolbar-class="toolbar-class" column-class="column-class" :show-toolbar="showToolbar" value-key="name" :title="title" :loading="loading" :columns="computed.displayColumns(columns, columnsNum)" :item-height="itemHeight" :visible-item-count="visibleItemCount" :cancel-button-text="cancelButtonText" :confirm-button-text="confirmButtonText" @change="onChange" @confirm="onConfirm" @cancel="onCancel"></van-picker></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanPicker from '../picker/index.vue'
+global['__wxVueOptions'] = {components:{'van-picker': VanPicker}}
+
+global['__wxRoute'] = 'vant/dist/area/index'
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+import { requestAnimationFrame } from '../common/utils';
+const EMPTY_CODE = '000000';
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
+            type: Boolean,
+            value: true,
+        }, value: {
+            type: String,
+            observer(value) {
+                this.code = value;
+                this.setValues();
+            },
+        }, areaList: {
+            type: Object,
+            value: {},
+            observer: 'setValues',
+        }, columnsNum: {
+            type: null,
+            value: 3,
+        }, columnsPlaceholder: {
+            type: Array,
+            observer(val) {
+                this.setData({
+                    typeToColumnsPlaceholder: {
+                        province: val[0] || '',
+                        city: val[1] || '',
+                        county: val[2] || '',
+                    },
+                });
+            },
+        } }),
+    data: {
+        columns: [{ values: [] }, { values: [] }, { values: [] }],
+        typeToColumnsPlaceholder: {},
+    },
+    mounted() {
+        requestAnimationFrame(() => {
+            this.setValues();
+        });
+    },
+    methods: {
+        getPicker() {
+            if (this.picker == null) {
+                this.picker = this.selectComponent('.van-area__picker');
+            }
+            return this.picker;
+        },
+        onCancel(event) {
+            this.emit('cancel', event.detail);
+        },
+        onConfirm(event) {
+            const { index } = event.detail;
+            let { value } = event.detail;
+            value = this.parseValues(value);
+            this.emit('confirm', { value, index });
+        },
+        emit(type, detail) {
+            detail.values = detail.value;
+            delete detail.value;
+            this.$emit(type, detail);
+        },
+        parseValues(values) {
+            const { columnsPlaceholder } = this.data;
+            return values.map((value, index) => {
+                if (value &&
+                    (!value.code || value.name === columnsPlaceholder[index])) {
+                    return Object.assign(Object.assign({}, value), { code: '', name: '' });
+                }
+                return value;
+            });
+        },
+        onChange(event) {
+            var _a;
+            const { index, picker, value } = event.detail;
+            this.code = value[index].code;
+            (_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
+                this.$emit('change', {
+                    picker,
+                    values: this.parseValues(picker.getValues()),
+                    index,
+                });
+            });
+        },
+        getConfig(type) {
+            const { areaList } = this.data;
+            return (areaList && areaList[`${type}_list`]) || {};
+        },
+        getList(type, code) {
+            if (type !== 'province' && !code) {
+                return [];
+            }
+            const { typeToColumnsPlaceholder } = this.data;
+            const list = this.getConfig(type);
+            let result = Object.keys(list).map((code) => ({
+                code,
+                name: list[code],
+            }));
+            if (code != null) {
+                // oversea code
+                if (code[0] === '9' && type === 'city') {
+                    code = '9';
+                }
+                result = result.filter((item) => item.code.indexOf(code) === 0);
+            }
+            if (typeToColumnsPlaceholder[type] && result.length) {
+                // set columns placeholder
+                const codeFill = type === 'province'
+                    ? ''
+                    : type === 'city'
+                        ? EMPTY_CODE.slice(2, 4)
+                        : EMPTY_CODE.slice(4, 6);
+                result.unshift({
+                    code: `${code}${codeFill}`,
+                    name: typeToColumnsPlaceholder[type],
+                });
+            }
+            return result;
+        },
+        getIndex(type, code) {
+            let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+            const list = this.getList(type, code.slice(0, compareNum - 2));
+            // oversea code
+            if (code[0] === '9' && type === 'province') {
+                compareNum = 1;
+            }
+            code = code.slice(0, compareNum);
+            for (let i = 0; i < list.length; i++) {
+                if (list[i].code.slice(0, compareNum) === code) {
+                    return i;
+                }
+            }
+            return 0;
+        },
+        setValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return;
+            }
+            let code = this.code || this.getDefaultCode();
+            const provinceList = this.getList('province');
+            const cityList = this.getList('city', code.slice(0, 2));
+            const stack = [];
+            const indexes = [];
+            const { columnsNum } = this.data;
+            if (columnsNum >= 1) {
+                stack.push(picker.setColumnValues(0, provinceList, false));
+                indexes.push(this.getIndex('province', code));
+            }
+            if (columnsNum >= 2) {
+                stack.push(picker.setColumnValues(1, cityList, false));
+                indexes.push(this.getIndex('city', code));
+                if (cityList.length && code.slice(2, 4) === '00') {
+                    [{ code }] = cityList;
+                }
+            }
+            if (columnsNum === 3) {
+                stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
+                indexes.push(this.getIndex('county', code));
+            }
+            return Promise.all(stack)
+                .catch(() => { })
+                .then(() => picker.setIndexes(indexes))
+                .catch(() => { });
+        },
+        getDefaultCode() {
+            const { columnsPlaceholder } = this.data;
+            if (columnsPlaceholder.length) {
+                return EMPTY_CODE;
+            }
+            const countyCodes = Object.keys(this.getConfig('county'));
+            if (countyCodes[0]) {
+                return countyCodes[0];
+            }
+            const cityCodes = Object.keys(this.getConfig('city'));
+            if (cityCodes[0]) {
+                return cityCodes[0];
+            }
+            return '';
+        },
+        getValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return [];
+            }
+            return this.parseValues(picker.getValues().filter((value) => !!value));
+        },
+        getDetail() {
+            const values = this.getValues();
+            const area = {
+                code: '',
+                country: '',
+                province: '',
+                city: '',
+                county: '',
+            };
+            if (!values.length) {
+                return area;
+            }
+            const names = values.map((item) => item.name);
+            area.code = values[values.length - 1].code;
+            if (area.code[0] === '9') {
+                area.country = names[1] || '';
+                area.province = names[2] || '';
+            }
+            else {
+                area.province = names[0] || '';
+                area.city = names[1] || '';
+                area.county = names[2] || '';
+            }
+            return area;
+        },
+        reset(code) {
+            this.code = code || '';
+            return this.setValues();
+        },
+    },
+});
+export default global['__wxComponents']['vant/dist/area/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

+ 20 - 0
wxcomponents/vant/dist/area/index.wxml

@@ -0,0 +1,20 @@
+<wxs src="./index.wxs" module="computed" />
+
+<van-picker
+  class="van-area__picker"
+  active-class="active-class"
+  toolbar-class="toolbar-class"
+  column-class="column-class"
+  show-toolbar="{{ showToolbar }}"
+  value-key="name"
+  title="{{ title }}"
+  loading="{{ loading }}"
+  columns="{{ computed.displayColumns(columns, columnsNum) }}"
+  item-height="{{ itemHeight }}"
+  visible-item-count="{{ visibleItemCount }}"
+  cancel-button-text="{{ cancelButtonText }}"
+  confirm-button-text="{{ confirmButtonText }}"
+  bind:change="onChange"
+  bind:confirm="onConfirm"
+  bind:cancel="onCancel"
+/>

+ 8 - 0
wxcomponents/vant/dist/area/index.wxs

@@ -0,0 +1,8 @@
+/* eslint-disable */
+function displayColumns(columns, columnsNum) {
+  return columns.slice(0, +columnsNum);
+}
+
+module.exports = {
+  displayColumns: displayColumns,
+};

+ 1 - 0
wxcomponents/vant/dist/area/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';

+ 1 - 0
wxcomponents/vant/dist/button/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 64 - 0
wxcomponents/vant/dist/button/index.js

@@ -0,0 +1,64 @@
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { canIUseFormFieldButton } from '../common/version';
+const mixins = [button];
+if (canIUseFormFieldButton()) {
+    mixins.push('wx://form-field-button');
+}
+VantComponent({
+    mixins,
+    classes: ['hover-class', 'loading-class'],
+    data: {
+        baseStyle: '',
+    },
+    props: {
+        formType: String,
+        icon: String,
+        classPrefix: {
+            type: String,
+            value: 'van-icon',
+        },
+        plain: Boolean,
+        block: Boolean,
+        round: Boolean,
+        square: Boolean,
+        loading: Boolean,
+        hairline: Boolean,
+        disabled: Boolean,
+        loadingText: String,
+        customStyle: String,
+        loadingType: {
+            type: String,
+            value: 'circular',
+        },
+        type: {
+            type: String,
+            value: 'default',
+        },
+        dataset: null,
+        size: {
+            type: String,
+            value: 'normal',
+        },
+        loadingSize: {
+            type: String,
+            value: '20px',
+        },
+        color: String,
+    },
+    methods: {
+        onClick(event) {
+            this.$emit('click', event);
+            const { canIUseGetUserProfile, openType, getUserProfileDesc, lang, } = this.data;
+            if (openType === 'getUserInfo' && canIUseGetUserProfile) {
+                wx.getUserProfile({
+                    desc: getUserProfileDesc || '  ',
+                    lang: lang || 'en',
+                    complete: (userProfile) => {
+                        this.$emit('getuserinfo', userProfile);
+                    },
+                });
+            }
+        },
+    },
+});

+ 7 - 0
wxcomponents/vant/dist/button/index.json

@@ -0,0 +1,7 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-loading": "../loading/index"
+  }
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 90 - 0
wxcomponents/vant/dist/button/index.vue


+ 56 - 0
wxcomponents/vant/dist/button/index.wxml

@@ -0,0 +1,56 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<button
+  id="{{ id || buttonId }}"
+  data-detail="{{ dataset }}"
+  class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
+  hover-class="{{ disabled || loading ? '' : 'van-button--active hover-class'}}"
+  lang="{{ lang }}"
+  form-type="{{ formType }}"
+  style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
+  open-type="{{ disabled || loading || (canIUseGetUserProfile && openType === 'getUserInfo') ? '' : openType }}"
+  business-id="{{ businessId }}"
+  session-from="{{ sessionFrom }}"
+  send-message-title="{{ sendMessageTitle }}"
+  send-message-path="{{ sendMessagePath }}"
+  send-message-img="{{ sendMessageImg }}"
+  show-message-card="{{ showMessageCard }}"
+  app-parameter="{{ appParameter }}"
+  aria-label="{{ ariaLabel }}"
+  bindtap="{{ disabled || loading ? '' : 'onClick' }}"
+  bindgetuserinfo="onGetUserInfo"
+  bindcontact="onContact"
+  bindgetphonenumber="onGetPhoneNumber"
+  bindgetrealtimephonenumber="onGetRealTimePhoneNumber"
+  bindagreeprivacyauthorization="onAgreePrivacyAuthorization"
+  binderror="onError"
+  bindlaunchapp="onLaunchApp"
+  bindopensetting="onOpenSetting"
+  bindchooseavatar="onChooseAvatar"
+>
+  <block wx:if="{{ loading }}">
+    <van-loading
+      custom-class="loading-class"
+      size="{{ loadingSize }}"
+      type="{{ loadingType }}"
+      color="{{ computed.loadingColor({ type, color, plain }) }}"
+    />
+    <view wx:if="{{ loadingText }}" class="van-button__loading-text">
+      {{ loadingText }}
+    </view>
+  </block>
+  <block wx:else>
+    <van-icon
+      wx:if="{{ icon }}"
+      size="1.2em"
+      name="{{ icon }}"
+      class-prefix="{{ classPrefix }}"
+      class="van-button__icon"
+      custom-style="line-height: inherit;"
+    />
+    <view class="van-button__text">
+      <slot />
+    </view>
+  </block>
+</button>

+ 39 - 0
wxcomponents/vant/dist/button/index.wxs

@@ -0,0 +1,39 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+
+function rootStyle(data) {
+  if (!data.color) {
+    return data.customStyle;
+  }
+
+  var properties = {
+    color: data.plain ? data.color : '#fff',
+    background: data.plain ? null : data.color,
+  };
+
+  // hide border when color is linear-gradient
+  if (data.color.indexOf('gradient') !== -1) {
+    properties.border = 0;
+  } else {
+    properties['border-color'] = data.color;
+  }
+
+  return style([properties, data.customStyle]);
+}
+
+function loadingColor(data) {
+  if (data.plain) {
+    return data.color ? data.color : '#c9c9c9';
+  }
+
+  if (data.type === 'default') {
+    return '#c9c9c9';
+  }
+
+  return '#fff';
+}
+
+module.exports = {
+  rootStyle: rootStyle,
+  loadingColor: loadingColor,
+};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
wxcomponents/vant/dist/button/index.wxss


+ 37 - 0
wxcomponents/vant/dist/calendar/calendar.vue

@@ -0,0 +1,37 @@
+<template>
+<uni-shadow-root class="vant-dist-calendar-calendar"><view class="van-calendar">
+  <header :title="title" :showTitle="showTitle" :subtitle="subtitle" :showSubtitle="showSubtitle" :firstDayOfWeek="firstDayOfWeek" @click-subtitle="onClickSubtitle">
+    <slot name="title" slot="title"></slot>
+  </header>
+
+  <scroll-view class="van-calendar__body" scroll-y :scroll-into-view="scrollIntoView">
+    <month v-for="(item,index) in (computed.getMonths(minDate, maxDate))" :key="item.index" :id="'month'+(index)" class="month" :data-date="item" :date="item" :type="type" :color="color" :minDate="minDate" :maxDate="maxDate" :showMark="showMark" :formatter="formatter" :rowHeight="rowHeight" :currentDate="currentDate" :showSubtitle="showSubtitle" :allowSameDay="allowSameDay" :showMonthTitle="index !== 0 || !showSubtitle" :firstDayOfWeek="firstDayOfWeek" @click="onClickDay"></month>
+  </scroll-view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <slot name="footer"></slot>
+  </view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <van-button v-if="showConfirm" round block type="danger" :color="color" custom-class="van-calendar__confirm" :disabled="computed.getButtonDisabled(type, currentDate, minRange)" nativeType="text" @click="onConfirm">
+      {{
+        computed.getButtonDisabled(type, currentDate, minRange)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/dist/calendar/calendar'
+
+Component({})
+
+export default global['__wxComponents']['vant/dist/calendar/calendar']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 68 - 0
wxcomponents/vant/dist/calendar/calendar.wxml

@@ -0,0 +1,68 @@
+<view class="van-calendar">
+  <header
+    title="{{ title }}"
+    showTitle="{{ showTitle }}"
+    subtitle="{{ subtitle }}"
+    showSubtitle="{{ showSubtitle }}"
+    firstDayOfWeek="{{ firstDayOfWeek }}"
+    bind:click-subtitle="onClickSubtitle"
+  >
+    <slot name="title" slot="title"></slot>
+  </header>
+
+  <scroll-view
+    class="van-calendar__body"
+    scroll-y
+    scroll-into-view="{{ scrollIntoView }}"
+  >
+    <month
+      wx:for="{{ computed.getMonths(minDate, maxDate) }}"
+      wx:key="index"
+      id="month{{ index }}"
+      class="month"
+      data-date="{{ item }}"
+      date="{{ item }}"
+      type="{{ type }}"
+      color="{{ color }}"
+      minDate="{{ minDate }}"
+      maxDate="{{ maxDate }}"
+      showMark="{{ showMark }}"
+      formatter="{{ formatter }}"
+      rowHeight="{{ rowHeight }}"
+      currentDate="{{ currentDate }}"
+      showSubtitle="{{ showSubtitle }}"
+      allowSameDay="{{ allowSameDay }}"
+      showMonthTitle="{{ index !== 0 || !showSubtitle }}"
+      firstDayOfWeek="{{ firstDayOfWeek }}"
+      bind:click="onClickDay"
+    />
+  </scroll-view>
+
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <slot name="footer"></slot>
+  </view>
+
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <van-button
+      wx:if="{{ showConfirm }}"
+      round
+      block
+      type="danger"
+      color="{{ color }}"
+      custom-class="van-calendar__confirm"
+      disabled="{{ computed.getButtonDisabled(type, currentDate, minRange) }}"
+      nativeType="text"
+      bind:click="onConfirm"
+    >
+      {{
+        computed.getButtonDisabled(type, currentDate, minRange)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
+  </view>
+</view>

+ 1 - 0
wxcomponents/vant/dist/calendar/components/header/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 37 - 0
wxcomponents/vant/dist/calendar/components/header/index.js

@@ -0,0 +1,37 @@
+import { VantComponent } from '../../../common/component';
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        subtitle: String,
+        showTitle: Boolean,
+        showSubtitle: Boolean,
+        firstDayOfWeek: {
+            type: Number,
+            observer: 'initWeekDay',
+        },
+    },
+    data: {
+        weekdays: [],
+    },
+    created() {
+        this.initWeekDay();
+    },
+    methods: {
+        initWeekDay() {
+            const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
+            const firstDayOfWeek = this.data.firstDayOfWeek || 0;
+            this.setData({
+                weekdays: [
+                    ...defaultWeeks.slice(firstDayOfWeek, 7),
+                    ...defaultWeeks.slice(0, firstDayOfWeek),
+                ],
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});

+ 3 - 0
wxcomponents/vant/dist/calendar/components/header/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 64 - 0
wxcomponents/vant/dist/calendar/components/header/index.vue

@@ -0,0 +1,64 @@
+<template>
+<uni-shadow-root class="vant-dist-calendar-components-header-index"><view class="van-calendar__header">
+  <block v-if="showTitle">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view v-if="showSubtitle" class="van-calendar__header-subtitle" @click="onClickSubtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view v-for="(item,index) in (weekdays)" :key="item.index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/dist/calendar/components/header/index'
+import { VantComponent } from '../../../common/component';
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        subtitle: String,
+        showTitle: Boolean,
+        showSubtitle: Boolean,
+        firstDayOfWeek: {
+            type: Number,
+            observer: 'initWeekDay',
+        },
+    },
+    data: {
+        weekdays: [],
+    },
+    created() {
+        this.initWeekDay();
+    },
+    methods: {
+        initWeekDay() {
+            const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
+            const firstDayOfWeek = this.data.firstDayOfWeek || 0;
+            this.setData({
+                weekdays: [
+                    ...defaultWeeks.slice(firstDayOfWeek, 7),
+                    ...defaultWeeks.slice(0, firstDayOfWeek),
+                ],
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});
+export default global['__wxComponents']['vant/dist/calendar/components/header/index']
+</script>
+<style platform="mp-weixin">
+@import '../../../common/index.css';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}
+</style>

+ 16 - 0
wxcomponents/vant/dist/calendar/components/header/index.wxml

@@ -0,0 +1,16 @@
+<view class="van-calendar__header">
+  <block wx:if="{{ showTitle }}">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle" bind:tap="onClickSubtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view>

+ 1 - 0
wxcomponents/vant/dist/calendar/components/header/index.wxss

@@ -0,0 +1 @@
+@import '../../../common/index.wxss';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}

+ 6 - 0
wxcomponents/vant/dist/calendar/components/month/index.d.ts

@@ -0,0 +1,6 @@
+export interface Day {
+    date: Date;
+    type: string;
+    text: number;
+    bottomInfo?: string;
+}

+ 154 - 0
wxcomponents/vant/dist/calendar/components/month/index.js

@@ -0,0 +1,154 @@
+import { VantComponent } from '../../../common/component';
+import { getMonthEndDay, compareDay, getPrevDay, getNextDay, } from '../../utils';
+VantComponent({
+    props: {
+        date: {
+            type: null,
+            observer: 'setDays',
+        },
+        type: {
+            type: String,
+            observer: 'setDays',
+        },
+        color: String,
+        minDate: {
+            type: null,
+            observer: 'setDays',
+        },
+        maxDate: {
+            type: null,
+            observer: 'setDays',
+        },
+        showMark: Boolean,
+        rowHeight: null,
+        formatter: {
+            type: null,
+            observer: 'setDays',
+        },
+        currentDate: {
+            type: null,
+            observer: 'setDays',
+        },
+        firstDayOfWeek: {
+            type: Number,
+            observer: 'setDays',
+        },
+        allowSameDay: Boolean,
+        showSubtitle: Boolean,
+        showMonthTitle: Boolean,
+    },
+    data: {
+        visible: true,
+        days: [],
+    },
+    methods: {
+        onClick(event) {
+            const { index } = event.currentTarget.dataset;
+            const item = this.data.days[index];
+            if (item.type !== 'disabled') {
+                this.$emit('click', item);
+            }
+        },
+        setDays() {
+            const days = [];
+            const startDate = new Date(this.data.date);
+            const year = startDate.getFullYear();
+            const month = startDate.getMonth();
+            const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
+            for (let day = 1; day <= totalDay; day++) {
+                const date = new Date(year, month, day);
+                const type = this.getDayType(date);
+                let config = {
+                    date,
+                    type,
+                    text: day,
+                    bottomInfo: this.getBottomInfo(type),
+                };
+                if (this.data.formatter) {
+                    config = this.data.formatter(config);
+                }
+                days.push(config);
+            }
+            this.setData({ days });
+        },
+        getMultipleDayType(day) {
+            const { currentDate } = this.data;
+            if (!Array.isArray(currentDate)) {
+                return '';
+            }
+            const isSelected = (date) => currentDate.some((item) => compareDay(item, date) === 0);
+            if (isSelected(day)) {
+                const prevDay = getPrevDay(day);
+                const nextDay = getNextDay(day);
+                const prevSelected = isSelected(prevDay);
+                const nextSelected = isSelected(nextDay);
+                if (prevSelected && nextSelected) {
+                    return 'multiple-middle';
+                }
+                if (prevSelected) {
+                    return 'end';
+                }
+                return nextSelected ? 'start' : 'multiple-selected';
+            }
+            return '';
+        },
+        getRangeDayType(day) {
+            const { currentDate, allowSameDay } = this.data;
+            if (!Array.isArray(currentDate)) {
+                return '';
+            }
+            const [startDay, endDay] = currentDate;
+            if (!startDay) {
+                return '';
+            }
+            const compareToStart = compareDay(day, startDay);
+            if (!endDay) {
+                return compareToStart === 0 ? 'start' : '';
+            }
+            const compareToEnd = compareDay(day, endDay);
+            if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
+                return 'start-end';
+            }
+            if (compareToStart === 0) {
+                return 'start';
+            }
+            if (compareToEnd === 0) {
+                return 'end';
+            }
+            if (compareToStart > 0 && compareToEnd < 0) {
+                return 'middle';
+            }
+            return '';
+        },
+        getDayType(day) {
+            const { type, minDate, maxDate, currentDate } = this.data;
+            if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
+                return 'disabled';
+            }
+            if (type === 'single') {
+                return compareDay(day, currentDate) === 0 ? 'selected' : '';
+            }
+            if (type === 'multiple') {
+                return this.getMultipleDayType(day);
+            }
+            /* istanbul ignore else */
+            if (type === 'range') {
+                return this.getRangeDayType(day);
+            }
+            return '';
+        },
+        getBottomInfo(type) {
+            if (this.data.type === 'range') {
+                if (type === 'start') {
+                    return '开始';
+                }
+                if (type === 'end') {
+                    return '结束';
+                }
+                if (type === 'start-end') {
+                    return '开始/结束';
+                }
+            }
+        },
+    },
+});

+ 3 - 0
wxcomponents/vant/dist/calendar/components/month/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 192 - 0
wxcomponents/vant/dist/calendar/components/month/index.vue


+ 39 - 0
wxcomponents/vant/dist/calendar/components/month/index.wxml

@@ -0,0 +1,39 @@
+<wxs src="./index.wxs" module="computed"></wxs>
+<wxs src="../../../wxs/utils.wxs" module="utils" />
+
+<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
+  <view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
+    {{ computed.formatMonthTitle(date) }}
+  </view>
+
+  <view wx:if="{{ visible }}" class="van-calendar__days">
+    <view wx:if="{{ showMark }}" class="van-calendar__month-mark">
+      {{ computed.getMark(date) }}
+    </view>
+
+    <view
+      wx:for="{{ days }}"
+      wx:key="index"
+      style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color, firstDayOfWeek) }}"
+      class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
+      data-index="{{ index }}"
+      bindtap="onClick"
+    >
+      <view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="width: {{ rowHeight }}px; height: {{ rowHeight }}px; background: {{ color }}">
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+
+      <view wx:else>
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+    </view>
+  </view>
+</view>

+ 71 - 0
wxcomponents/vant/dist/calendar/components/month/index.wxs

@@ -0,0 +1,71 @@
+/* eslint-disable */
+var utils = require('../../utils.wxs');
+
+function getMark(date) {
+  return getDate(date).getMonth() + 1;
+}
+
+var ROW_HEIGHT = 64;
+
+function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
+  var style = [];
+  var current = getDate(date).getDay() || 7;
+  var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
+               current === 7 && firstDayOfWeek === 0 ? 0 :
+               (current - firstDayOfWeek);
+
+  if (index === 0) {
+    style.push(['margin-left', (100 * offset) / 7 + '%']);
+  }
+
+  if (rowHeight !== ROW_HEIGHT) {
+    style.push(['height', rowHeight + 'px']);
+  }
+
+  if (color) {
+    if (
+      type === 'start' ||
+      type === 'end' ||
+      type === 'start-end' ||
+      type === 'multiple-selected' ||
+      type === 'multiple-middle'
+    ) {
+      style.push(['background', color]);
+    } else if (type === 'middle') {
+      style.push(['color', color]);
+    }
+  }
+
+  return style
+    .map(function(item) {
+      return item.join(':');
+    })
+    .join(';');
+}
+
+function formatMonthTitle(date) {
+  date = getDate(date);
+  return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
+}
+
+function getMonthStyle(visible, date, rowHeight) {
+  if (!visible) {
+    date = getDate(date);
+
+    var totalDay = utils.getMonthEndDay(
+      date.getFullYear(),
+      date.getMonth() + 1
+    );
+    var offset = getDate(date).getDay();
+    var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
+
+    return 'padding-bottom:' + padding + 'px';
+  }
+}
+
+module.exports = {
+  getMark: getMark,
+  getDayStyle: getDayStyle,
+  formatMonthTitle: formatMonthTitle,
+  getMonthStyle: getMonthStyle
+};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
wxcomponents/vant/dist/calendar/components/month/index.wxss


+ 1 - 0
wxcomponents/vant/dist/calendar/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 356 - 0
wxcomponents/vant/dist/calendar/index.js

@@ -0,0 +1,356 @@
+import { VantComponent } from '../common/component';
+import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
+import Toast from '../toast/toast';
+import { requestAnimationFrame } from '../common/utils';
+const initialMinDate = getToday().getTime();
+const initialMaxDate = (() => {
+    const now = getToday();
+    return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
+})();
+const getTime = (date) => date instanceof Date ? date.getTime() : date;
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        color: String,
+        show: {
+            type: Boolean,
+            observer(val) {
+                if (val) {
+                    this.initRect();
+                    this.scrollIntoView();
+                }
+            },
+        },
+        formatter: null,
+        confirmText: {
+            type: String,
+            value: '确定',
+        },
+        confirmDisabledText: {
+            type: String,
+            value: '确定',
+        },
+        rangePrompt: String,
+        showRangePrompt: {
+            type: Boolean,
+            value: true,
+        },
+        defaultDate: {
+            type: null,
+            value: getToday().getTime(),
+            observer(val) {
+                this.setData({ currentDate: val });
+                this.scrollIntoView();
+            },
+        },
+        allowSameDay: Boolean,
+        type: {
+            type: String,
+            value: 'single',
+            observer: 'reset',
+        },
+        minDate: {
+            type: Number,
+            value: initialMinDate,
+        },
+        maxDate: {
+            type: Number,
+            value: initialMaxDate,
+        },
+        position: {
+            type: String,
+            value: 'bottom',
+        },
+        rowHeight: {
+            type: null,
+            value: ROW_HEIGHT,
+        },
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        poppable: {
+            type: Boolean,
+            value: true,
+        },
+        showMark: {
+            type: Boolean,
+            value: true,
+        },
+        showTitle: {
+            type: Boolean,
+            value: true,
+        },
+        showConfirm: {
+            type: Boolean,
+            value: true,
+        },
+        showSubtitle: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        maxRange: {
+            type: null,
+            value: null,
+        },
+        minRange: {
+            type: Number,
+            value: 1,
+        },
+        firstDayOfWeek: {
+            type: Number,
+            value: 0,
+        },
+        readonly: Boolean,
+    },
+    data: {
+        subtitle: '',
+        currentDate: null,
+        scrollIntoView: '',
+    },
+    watch: {
+        minDate() {
+            this.initRect();
+        },
+        maxDate() {
+            this.initRect();
+        },
+    },
+    created() {
+        this.setData({
+            currentDate: this.getInitialDate(this.data.defaultDate),
+        });
+    },
+    mounted() {
+        if (this.data.show || !this.data.poppable) {
+            this.initRect();
+            this.scrollIntoView();
+        }
+    },
+    methods: {
+        reset() {
+            this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) });
+            this.scrollIntoView();
+        },
+        initRect() {
+            if (this.contentObserver != null) {
+                this.contentObserver.disconnect();
+            }
+            const contentObserver = this.createIntersectionObserver({
+                thresholds: [0, 0.1, 0.9, 1],
+                observeAll: true,
+            });
+            this.contentObserver = contentObserver;
+            contentObserver.relativeTo('.van-calendar__body');
+            contentObserver.observe('.month', (res) => {
+                if (res.boundingClientRect.top <= res.relativeRect.top) {
+                    // @ts-ignore
+                    this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+                }
+            });
+        },
+        limitDateRange(date, minDate = null, maxDate = null) {
+            minDate = minDate || this.data.minDate;
+            maxDate = maxDate || this.data.maxDate;
+            if (compareDay(date, minDate) === -1) {
+                return minDate;
+            }
+            if (compareDay(date, maxDate) === 1) {
+                return maxDate;
+            }
+            return date;
+        },
+        getInitialDate(defaultDate = null) {
+            const { type, minDate, maxDate, allowSameDay } = this.data;
+            if (!defaultDate)
+                return [];
+            const now = getToday().getTime();
+            if (type === 'range') {
+                if (!Array.isArray(defaultDate)) {
+                    defaultDate = [];
+                }
+                const [startDay, endDay] = defaultDate || [];
+                const startDate = getTime(startDay || now);
+                const start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : getPrevDay(new Date(maxDate)).getTime());
+                const date = getTime(endDay || now);
+                const end = this.limitDateRange(date, allowSameDay ? date : getNextDay(new Date(minDate)).getTime());
+                return [start, end];
+            }
+            if (type === 'multiple') {
+                if (Array.isArray(defaultDate)) {
+                    return defaultDate.map((date) => this.limitDateRange(date));
+                }
+                return [this.limitDateRange(now)];
+            }
+            if (!defaultDate || Array.isArray(defaultDate)) {
+                defaultDate = now;
+            }
+            return this.limitDateRange(defaultDate);
+        },
+        scrollIntoView() {
+            requestAnimationFrame(() => {
+                const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
+                if (!currentDate)
+                    return;
+                // @ts-ignore
+                const targetDate = type === 'single' ? currentDate : currentDate[0];
+                const displayed = show || !poppable;
+                if (!targetDate || !displayed) {
+                    return;
+                }
+                const months = getMonths(minDate, maxDate);
+                months.some((month, index) => {
+                    if (compareMonth(month, targetDate) === 0) {
+                        this.setData({ scrollIntoView: `month${index}` });
+                        return true;
+                    }
+                    return false;
+                });
+            });
+        },
+        onOpen() {
+            this.$emit('open');
+        },
+        onOpened() {
+            this.$emit('opened');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClosed() {
+            this.$emit('closed');
+        },
+        onClickDay(event) {
+            if (this.data.readonly) {
+                return;
+            }
+            let { date } = event.detail;
+            const { type, currentDate, allowSameDay } = this.data;
+            if (type === 'range') {
+                // @ts-ignore
+                const [startDay, endDay] = currentDate;
+                if (startDay && !endDay) {
+                    const compareToStart = compareDay(date, startDay);
+                    if (compareToStart === 1) {
+                        const { days } = this.selectComponent('.month').data;
+                        days.some((day, index) => {
+                            const isDisabled = day.type === 'disabled' &&
+                                getTime(startDay) < getTime(day.date) &&
+                                getTime(day.date) < getTime(date);
+                            if (isDisabled) {
+                                ({ date } = days[index - 1]);
+                            }
+                            return isDisabled;
+                        });
+                        this.select([startDay, date], true);
+                    }
+                    else if (compareToStart === -1) {
+                        this.select([date, null]);
+                    }
+                    else if (allowSameDay) {
+                        this.select([date, date], true);
+                    }
+                }
+                else {
+                    this.select([date, null]);
+                }
+            }
+            else if (type === 'multiple') {
+                let selectedIndex;
+                // @ts-ignore
+                const selected = currentDate.some((dateItem, index) => {
+                    const equal = compareDay(dateItem, date) === 0;
+                    if (equal) {
+                        selectedIndex = index;
+                    }
+                    return equal;
+                });
+                if (selected) {
+                    // @ts-ignore
+                    const cancelDate = currentDate.splice(selectedIndex, 1);
+                    this.setData({ currentDate });
+                    this.unselect(cancelDate);
+                }
+                else {
+                    // @ts-ignore
+                    this.select([...currentDate, date]);
+                }
+            }
+            else {
+                this.select(date, true);
+            }
+        },
+        unselect(dateArray) {
+            const date = dateArray[0];
+            if (date) {
+                this.$emit('unselect', copyDates(date));
+            }
+        },
+        select(date, complete) {
+            if (complete && this.data.type === 'range') {
+                const valid = this.checkRange(date);
+                if (!valid) {
+                    // auto selected to max range if showConfirm
+                    if (this.data.showConfirm) {
+                        this.emit([
+                            date[0],
+                            getDayByOffset(date[0], this.data.maxRange - 1),
+                        ]);
+                    }
+                    else {
+                        this.emit(date);
+                    }
+                    return;
+                }
+            }
+            this.emit(date);
+            if (complete && !this.data.showConfirm) {
+                this.onConfirm();
+            }
+        },
+        emit(date) {
+            this.setData({
+                currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
+            });
+            this.$emit('select', copyDates(date));
+        },
+        checkRange(date) {
+            const { maxRange, rangePrompt, showRangePrompt } = this.data;
+            if (maxRange && calcDateNum(date) > maxRange) {
+                if (showRangePrompt) {
+                    Toast({
+                        context: this,
+                        message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+                    });
+                }
+                this.$emit('over-range');
+                return false;
+            }
+            return true;
+        },
+        onConfirm() {
+            if (this.data.type === 'range' &&
+                !this.checkRange(this.data.currentDate)) {
+                return;
+            }
+            wx.nextTick(() => {
+                // @ts-ignore
+                this.$emit('confirm', copyDates(this.data.currentDate));
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});

+ 10 - 0
wxcomponents/vant/dist/calendar/index.json

@@ -0,0 +1,10 @@
+{
+  "component": true,
+  "usingComponents": {
+    "header": "./components/header/index",
+    "month": "./components/month/index",
+    "van-button": "../button/index",
+    "van-popup": "../popup/index",
+    "van-toast": "../toast/index"
+  }
+}

+ 384 - 0
wxcomponents/vant/dist/calendar/index.vue

@@ -0,0 +1,384 @@
+<template>
+<uni-shadow-root class="vant-dist-calendar-index"><van-popup v-if="poppable" :custom-class="'van-calendar__popup--'+(position)" close-icon-class="van-calendar__close-icon" :show="show" :round="round" :position="position" :closeable="showTitle || showSubtitle" :close-on-click-overlay="closeOnClickOverlay" :safe-area-inset-bottom="safeAreaInsetBottom" @enter="onOpen" @close="onClose" @after-enter="onOpened" @after-leave="onClosed">
+  <include src="./calendar.wxml"></include>
+</van-popup>
+
+<include v-else src="./calendar.wxml"></include>
+
+<van-toast id="van-toast"></van-toast></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs><wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+const __wxTemplateComponentProps = {}
+import __wxTemplateComponent0 from './calendar.vue'
+
+import Header from './components/header/index.vue'
+import Month from './components/month/index.vue'
+import VanButton from '../button/index.vue'
+import VanPopup from '../popup/index.vue'
+import VanToast from '../toast/index.vue'
+global['__wxVueOptions'] = {components:{'header': Header,'month': Month,'van-button': VanButton,'van-popup': VanPopup,'van-toast': VanToast,}}
+
+global['__wxRoute'] = 'vant/dist/calendar/index'
+import { VantComponent } from '../common/component';
+import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
+import Toast from '../toast/toast';
+import { requestAnimationFrame } from '../common/utils';
+const initialMinDate = getToday().getTime();
+const initialMaxDate = (() => {
+    const now = getToday();
+    return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
+})();
+const getTime = (date) => date instanceof Date ? date.getTime() : date;
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        color: String,
+        show: {
+            type: Boolean,
+            observer(val) {
+                if (val) {
+                    this.initRect();
+                    this.scrollIntoView();
+                }
+            },
+        },
+        formatter: null,
+        confirmText: {
+            type: String,
+            value: '确定',
+        },
+        confirmDisabledText: {
+            type: String,
+            value: '确定',
+        },
+        rangePrompt: String,
+        showRangePrompt: {
+            type: Boolean,
+            value: true,
+        },
+        defaultDate: {
+            type: null,
+            value: getToday().getTime(),
+            observer(val) {
+                this.setData({ currentDate: val });
+                this.scrollIntoView();
+            },
+        },
+        allowSameDay: Boolean,
+        type: {
+            type: String,
+            value: 'single',
+            observer: 'reset',
+        },
+        minDate: {
+            type: Number,
+            value: initialMinDate,
+        },
+        maxDate: {
+            type: Number,
+            value: initialMaxDate,
+        },
+        position: {
+            type: String,
+            value: 'bottom',
+        },
+        rowHeight: {
+            type: null,
+            value: ROW_HEIGHT,
+        },
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        poppable: {
+            type: Boolean,
+            value: true,
+        },
+        showMark: {
+            type: Boolean,
+            value: true,
+        },
+        showTitle: {
+            type: Boolean,
+            value: true,
+        },
+        showConfirm: {
+            type: Boolean,
+            value: true,
+        },
+        showSubtitle: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        maxRange: {
+            type: null,
+            value: null,
+        },
+        minRange: {
+            type: Number,
+            value: 1,
+        },
+        firstDayOfWeek: {
+            type: Number,
+            value: 0,
+        },
+        readonly: Boolean,
+    },
+    data: {
+        subtitle: '',
+        currentDate: null,
+        scrollIntoView: '',
+    },
+    watch: {
+        minDate() {
+            this.initRect();
+        },
+        maxDate() {
+            this.initRect();
+        },
+    },
+    created() {
+        this.setData({
+            currentDate: this.getInitialDate(this.data.defaultDate),
+        });
+    },
+    mounted() {
+        if (this.data.show || !this.data.poppable) {
+            this.initRect();
+            this.scrollIntoView();
+        }
+    },
+    methods: {
+        reset() {
+            this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) });
+            this.scrollIntoView();
+        },
+        initRect() {
+            if (this.contentObserver != null) {
+                this.contentObserver.disconnect();
+            }
+            const contentObserver = this.createIntersectionObserver({
+                thresholds: [0, 0.1, 0.9, 1],
+                observeAll: true,
+            });
+            this.contentObserver = contentObserver;
+            contentObserver.relativeTo('.van-calendar__body');
+            contentObserver.observe('.month', (res) => {
+                if (res.boundingClientRect.top <= res.relativeRect.top) {
+                    // @ts-ignore
+                    this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+                }
+            });
+        },
+        limitDateRange(date, minDate = null, maxDate = null) {
+            minDate = minDate || this.data.minDate;
+            maxDate = maxDate || this.data.maxDate;
+            if (compareDay(date, minDate) === -1) {
+                return minDate;
+            }
+            if (compareDay(date, maxDate) === 1) {
+                return maxDate;
+            }
+            return date;
+        },
+        getInitialDate(defaultDate = null) {
+            const { type, minDate, maxDate, allowSameDay } = this.data;
+            if (!defaultDate)
+                return [];
+            const now = getToday().getTime();
+            if (type === 'range') {
+                if (!Array.isArray(defaultDate)) {
+                    defaultDate = [];
+                }
+                const [startDay, endDay] = defaultDate || [];
+                const startDate = getTime(startDay || now);
+                const start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : getPrevDay(new Date(maxDate)).getTime());
+                const date = getTime(endDay || now);
+                const end = this.limitDateRange(date, allowSameDay ? date : getNextDay(new Date(minDate)).getTime());
+                return [start, end];
+            }
+            if (type === 'multiple') {
+                if (Array.isArray(defaultDate)) {
+                    return defaultDate.map((date) => this.limitDateRange(date));
+                }
+                return [this.limitDateRange(now)];
+            }
+            if (!defaultDate || Array.isArray(defaultDate)) {
+                defaultDate = now;
+            }
+            return this.limitDateRange(defaultDate);
+        },
+        scrollIntoView() {
+            requestAnimationFrame(() => {
+                const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
+                if (!currentDate)
+                    return;
+                // @ts-ignore
+                const targetDate = type === 'single' ? currentDate : currentDate[0];
+                const displayed = show || !poppable;
+                if (!targetDate || !displayed) {
+                    return;
+                }
+                const months = getMonths(minDate, maxDate);
+                months.some((month, index) => {
+                    if (compareMonth(month, targetDate) === 0) {
+                        this.setData({ scrollIntoView: `month${index}` });
+                        return true;
+                    }
+                    return false;
+                });
+            });
+        },
+        onOpen() {
+            this.$emit('open');
+        },
+        onOpened() {
+            this.$emit('opened');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClosed() {
+            this.$emit('closed');
+        },
+        onClickDay(event) {
+            if (this.data.readonly) {
+                return;
+            }
+            let { date } = event.detail;
+            const { type, currentDate, allowSameDay } = this.data;
+            if (type === 'range') {
+                // @ts-ignore
+                const [startDay, endDay] = currentDate;
+                if (startDay && !endDay) {
+                    const compareToStart = compareDay(date, startDay);
+                    if (compareToStart === 1) {
+                        const { days } = this.selectComponent('.month').data;
+                        days.some((day, index) => {
+                            const isDisabled = day.type === 'disabled' &&
+                                getTime(startDay) < getTime(day.date) &&
+                                getTime(day.date) < getTime(date);
+                            if (isDisabled) {
+                                ({ date } = days[index - 1]);
+                            }
+                            return isDisabled;
+                        });
+                        this.select([startDay, date], true);
+                    }
+                    else if (compareToStart === -1) {
+                        this.select([date, null]);
+                    }
+                    else if (allowSameDay) {
+                        this.select([date, date], true);
+                    }
+                }
+                else {
+                    this.select([date, null]);
+                }
+            }
+            else if (type === 'multiple') {
+                let selectedIndex;
+                // @ts-ignore
+                const selected = currentDate.some((dateItem, index) => {
+                    const equal = compareDay(dateItem, date) === 0;
+                    if (equal) {
+                        selectedIndex = index;
+                    }
+                    return equal;
+                });
+                if (selected) {
+                    // @ts-ignore
+                    const cancelDate = currentDate.splice(selectedIndex, 1);
+                    this.setData({ currentDate });
+                    this.unselect(cancelDate);
+                }
+                else {
+                    // @ts-ignore
+                    this.select([...currentDate, date]);
+                }
+            }
+            else {
+                this.select(date, true);
+            }
+        },
+        unselect(dateArray) {
+            const date = dateArray[0];
+            if (date) {
+                this.$emit('unselect', copyDates(date));
+            }
+        },
+        select(date, complete) {
+            if (complete && this.data.type === 'range') {
+                const valid = this.checkRange(date);
+                if (!valid) {
+                    // auto selected to max range if showConfirm
+                    if (this.data.showConfirm) {
+                        this.emit([
+                            date[0],
+                            getDayByOffset(date[0], this.data.maxRange - 1),
+                        ]);
+                    }
+                    else {
+                        this.emit(date);
+                    }
+                    return;
+                }
+            }
+            this.emit(date);
+            if (complete && !this.data.showConfirm) {
+                this.onConfirm();
+            }
+        },
+        emit(date) {
+            this.setData({
+                currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
+            });
+            this.$emit('select', copyDates(date));
+        },
+        checkRange(date) {
+            const { maxRange, rangePrompt, showRangePrompt } = this.data;
+            if (maxRange && calcDateNum(date) > maxRange) {
+                if (showRangePrompt) {
+                    Toast({
+                        context: this,
+                        message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+                    });
+                }
+                this.$emit('over-range');
+                return false;
+            }
+            return true;
+        },
+        onConfirm() {
+            if (this.data.type === 'range' &&
+                !this.checkRange(this.data.currentDate)) {
+                return;
+            }
+            wx.nextTick(() => {
+                // @ts-ignore
+                this.$emit('confirm', copyDates(this.data.currentDate));
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});
+export default global['__wxComponents']['vant/dist/calendar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,90%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}
+</style>

+ 26 - 0
wxcomponents/vant/dist/calendar/index.wxml

@@ -0,0 +1,26 @@
+<wxs src="./index.wxs" module="computed" />
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<import src="./calendar.wxml" />
+
+<van-popup
+  wx:if="{{ poppable }}"
+  custom-class="van-calendar__popup--{{ position }}"
+  close-icon-class="van-calendar__close-icon"
+  show="{{ show }}"
+  round="{{ round }}"
+  position="{{ position }}"
+  closeable="{{ showTitle || showSubtitle }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
+  bind:enter="onOpen"
+  bind:close="onClose"
+  bind:after-enter="onOpened"
+  bind:after-leave="onClosed"
+>
+  <include src="./calendar.wxml" />
+</van-popup>
+
+<include wx:else src="./calendar.wxml" />
+
+<van-toast id="van-toast" />

+ 37 - 0
wxcomponents/vant/dist/calendar/index.wxs

@@ -0,0 +1,37 @@
+/* eslint-disable */
+var utils = require('./utils.wxs');
+
+function getMonths(minDate, maxDate) {
+  var months = [];
+  var cursor = getDate(minDate);
+
+  cursor.setDate(1);
+
+  do {
+    months.push(cursor.getTime());
+    cursor.setMonth(cursor.getMonth() + 1);
+  } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
+
+  return months;
+}
+
+function getButtonDisabled(type, currentDate, minRange) {
+  if (currentDate == null) {
+    return true;
+  }
+
+  if (type === 'range') {
+    return !currentDate[0] || !currentDate[1];
+  }
+
+  if (type === 'multiple') {
+    return currentDate.length < minRange;
+  }
+
+  return !currentDate;
+}
+
+module.exports = {
+  getMonths: getMonths,
+  getButtonDisabled: getButtonDisabled
+};

+ 1 - 0
wxcomponents/vant/dist/calendar/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,90%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}

+ 12 - 0
wxcomponents/vant/dist/calendar/utils.d.ts

@@ -0,0 +1,12 @@
+export declare const ROW_HEIGHT = 64;
+export declare function formatMonthTitle(date: Date): string;
+export declare function compareMonth(date1: Date | number, date2: Date | number): 0 | 1 | -1;
+export declare function compareDay(day1: Date | number, day2: Date | number): 0 | 1 | -1;
+export declare function getDayByOffset(date: Date, offset: number): Date;
+export declare function getPrevDay(date: Date): Date;
+export declare function getNextDay(date: Date): Date;
+export declare function getToday(): Date;
+export declare function calcDateNum(date: [Date, Date]): number;
+export declare function copyDates(dates: Date | Date[]): Date | Date[];
+export declare function getMonthEndDay(year: number, month: number): number;
+export declare function getMonths(minDate: number, maxDate: number): number[];

+ 83 - 0
wxcomponents/vant/dist/calendar/utils.js

@@ -0,0 +1,83 @@
+export const ROW_HEIGHT = 64;
+export function formatMonthTitle(date) {
+    if (!(date instanceof Date)) {
+        date = new Date(date);
+    }
+    return `${date.getFullYear()}年${date.getMonth() + 1}月`;
+}
+export function compareMonth(date1, date2) {
+    if (!(date1 instanceof Date)) {
+        date1 = new Date(date1);
+    }
+    if (!(date2 instanceof Date)) {
+        date2 = new Date(date2);
+    }
+    const year1 = date1.getFullYear();
+    const year2 = date2.getFullYear();
+    const month1 = date1.getMonth();
+    const month2 = date2.getMonth();
+    if (year1 === year2) {
+        return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+    }
+    return year1 > year2 ? 1 : -1;
+}
+export function compareDay(day1, day2) {
+    if (!(day1 instanceof Date)) {
+        day1 = new Date(day1);
+    }
+    if (!(day2 instanceof Date)) {
+        day2 = new Date(day2);
+    }
+    const compareMonthResult = compareMonth(day1, day2);
+    if (compareMonthResult === 0) {
+        const date1 = day1.getDate();
+        const date2 = day2.getDate();
+        return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
+    }
+    return compareMonthResult;
+}
+export function getDayByOffset(date, offset) {
+    date = new Date(date);
+    date.setDate(date.getDate() + offset);
+    return date;
+}
+export function getPrevDay(date) {
+    return getDayByOffset(date, -1);
+}
+export function getNextDay(date) {
+    return getDayByOffset(date, 1);
+}
+export function getToday() {
+    const today = new Date();
+    today.setHours(0, 0, 0, 0);
+    return today;
+}
+export function calcDateNum(date) {
+    const day1 = new Date(date[0]).getTime();
+    const day2 = new Date(date[1]).getTime();
+    return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
+}
+export function copyDates(dates) {
+    if (Array.isArray(dates)) {
+        return dates.map((date) => {
+            if (date === null) {
+                return date;
+            }
+            return new Date(date);
+        });
+    }
+    return new Date(dates);
+}
+export function getMonthEndDay(year, month) {
+    return 32 - new Date(year, month - 1, 32).getDate();
+}
+export function getMonths(minDate, maxDate) {
+    const months = [];
+    const cursor = new Date(minDate);
+    cursor.setDate(1);
+    do {
+        months.push(cursor.getTime());
+        cursor.setMonth(cursor.getMonth() + 1);
+    } while (compareMonth(cursor, maxDate) !== 1);
+    return months;
+}

+ 25 - 0
wxcomponents/vant/dist/calendar/utils.wxs

@@ -0,0 +1,25 @@
+/* eslint-disable */
+function getMonthEndDay(year, month) {
+  return 32 -  getDate(year, month - 1, 32).getDate();
+}
+
+function compareMonth(date1, date2) {
+  date1 = getDate(date1);
+  date2 = getDate(date2);
+
+  var year1 = date1.getFullYear();
+  var year2 = date2.getFullYear();
+  var month1 = date1.getMonth();
+  var month2 = date2.getMonth();
+
+  if (year1 === year2) {
+    return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+  }
+
+  return year1 > year2 ? 1 : -1;
+}
+
+module.exports = {
+  getMonthEndDay: getMonthEndDay,
+  compareMonth: compareMonth
+};

+ 1 - 0
wxcomponents/vant/dist/card/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 49 - 0
wxcomponents/vant/dist/card/index.js

@@ -0,0 +1,49 @@
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: [
+        'num-class',
+        'desc-class',
+        'thumb-class',
+        'title-class',
+        'price-class',
+        'origin-price-class',
+    ],
+    mixins: [link],
+    props: {
+        tag: String,
+        num: String,
+        desc: String,
+        thumb: String,
+        title: String,
+        price: {
+            type: String,
+            observer: 'updatePrice',
+        },
+        centered: Boolean,
+        lazyLoad: Boolean,
+        thumbLink: String,
+        originPrice: String,
+        thumbMode: {
+            type: String,
+            value: 'aspectFit',
+        },
+        currency: {
+            type: String,
+            value: '¥',
+        },
+    },
+    methods: {
+        updatePrice() {
+            const { price } = this.data;
+            const priceArr = price.toString().split('.');
+            this.setData({
+                integerStr: priceArr[0],
+                decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
+            });
+        },
+        onClickThumb() {
+            this.jumpLink('thumbLink');
+        },
+    },
+});

+ 6 - 0
wxcomponents/vant/dist/card/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-tag": "../tag/index"
+  }
+}

+ 105 - 0
wxcomponents/vant/dist/card/index.vue

@@ -0,0 +1,105 @@
+<template>
+<uni-shadow-root class="vant-dist-card-index"><view class="custom-class van-card">
+  <view :class="utils.bem('card__header', { center: centered })">
+    <view class="van-card__thumb" @click="onClickThumb">
+      <image v-if="thumb" :src="thumb" :mode="thumbMode" :lazy-load="lazyLoad" class="van-card__img thumb-class"></image>
+      <slot v-else name="thumb"></slot>
+      <van-tag v-if="tag" mark type="danger" custom-class="van-card__tag">
+        {{ tag }}
+      </van-tag>
+      <slot v-else name="tag"></slot>
+    </view>
+
+    <view :class="'van-card__content '+(utils.bem('card__content', { center: centered }))">
+      <view>
+        <view v-if="title" class="van-card__title title-class">{{ title }}</view>
+        <slot v-else name="title"></slot>
+
+        <view v-if="desc" class="van-card__desc desc-class">{{ desc }}</view>
+        <slot v-else name="desc"></slot>
+
+        <slot name="tags"></slot>
+      </view>
+
+      <view class="van-card__bottom">
+        <slot name="price-top"></slot>
+        <view v-if="price || price === 0" class="van-card__price price-class">
+          <text>{{ currency }}</text>
+          <text class="van-card__price-integer">{{ integerStr }}</text>
+          <text class="van-card__price-decimal">{{ decimalStr }}</text>
+        </view>
+        <slot v-else name="price"></slot>
+        <view v-if="originPrice || originPrice === 0" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
+        <slot v-else name="origin-price"></slot>
+        <view v-if="num" class="van-card__num num-class">x {{ num }}</view>
+        <slot v-else name="num"></slot>
+        <slot name="bottom"></slot>
+      </view>
+    </view>
+  </view>
+
+  <view class="van-card__footer">
+    <slot name="footer"></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanTag from '../tag/index.vue'
+global['__wxVueOptions'] = {components:{'van-tag': VanTag}}
+
+global['__wxRoute'] = 'vant/dist/card/index'
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: [
+        'num-class',
+        'desc-class',
+        'thumb-class',
+        'title-class',
+        'price-class',
+        'origin-price-class',
+    ],
+    mixins: [link],
+    props: {
+        tag: String,
+        num: String,
+        desc: String,
+        thumb: String,
+        title: String,
+        price: {
+            type: String,
+            observer: 'updatePrice',
+        },
+        centered: Boolean,
+        lazyLoad: Boolean,
+        thumbLink: String,
+        originPrice: String,
+        thumbMode: {
+            type: String,
+            value: 'aspectFit',
+        },
+        currency: {
+            type: String,
+            value: '¥',
+        },
+    },
+    methods: {
+        updatePrice() {
+            const { price } = this.data;
+            const priceArr = price.toString().split('.');
+            this.setData({
+                integerStr: priceArr[0],
+                decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
+            });
+        },
+        onClickThumb() {
+            this.jumpLink('thumbLink');
+        },
+    },
+});
+export default global['__wxComponents']['vant/dist/card/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}
+</style>

+ 56 - 0
wxcomponents/vant/dist/card/index.wxml

@@ -0,0 +1,56 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="custom-class van-card">
+  <view class="{{ utils.bem('card__header', { center: centered }) }}">
+    <view class="van-card__thumb" bind:tap="onClickThumb">
+      <image
+        wx:if="{{ thumb }}"
+        src="{{ thumb }}"
+        mode="{{ thumbMode }}"
+        lazy-load="{{ lazyLoad }}"
+        class="van-card__img thumb-class"
+      />
+      <slot wx:else name="thumb" />
+      <van-tag
+        wx:if="{{ tag }}"
+        mark
+        type="danger"
+        custom-class="van-card__tag"
+      >
+        {{ tag }}
+      </van-tag>
+      <slot wx:else name="tag" />
+    </view>
+
+    <view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
+      <view>
+        <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
+        <slot wx:else name="title" />
+
+        <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
+        <slot wx:else name="desc" />
+
+        <slot name="tags" />
+      </view>
+
+      <view class="van-card__bottom">
+        <slot name="price-top" />
+        <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">
+          <text>{{ currency }}</text>
+          <text class="van-card__price-integer">{{ integerStr }}</text>
+          <text class="van-card__price-decimal">{{ decimalStr }}</text>
+        </view>
+        <slot wx:else name="price" />
+        <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
+        <slot wx:else name="origin-price" />
+        <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
+        <slot wx:else  name="num" />
+        <slot name="bottom" />
+      </view>
+    </view>
+  </view>
+
+  <view class="van-card__footer">
+    <slot name="footer" />
+  </view>
+</view>

+ 1 - 0
wxcomponents/vant/dist/card/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}

+ 1 - 0
wxcomponents/vant/dist/cascader/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 208 - 0
wxcomponents/vant/dist/cascader/index.js

@@ -0,0 +1,208 @@
+import { VantComponent } from '../common/component';
+var FieldName;
+(function (FieldName) {
+    FieldName["TEXT"] = "text";
+    FieldName["VALUE"] = "value";
+    FieldName["CHILDREN"] = "children";
+})(FieldName || (FieldName = {}));
+const defaultFieldNames = {
+    text: FieldName.TEXT,
+    value: FieldName.VALUE,
+    children: FieldName.CHILDREN,
+};
+VantComponent({
+    props: {
+        title: String,
+        value: {
+            type: String,
+        },
+        placeholder: {
+            type: String,
+            value: '请选择',
+        },
+        activeColor: {
+            type: String,
+            value: '#1989fa',
+        },
+        options: {
+            type: Array,
+            value: [],
+        },
+        swipeable: {
+            type: Boolean,
+            value: false,
+        },
+        closeable: {
+            type: Boolean,
+            value: true,
+        },
+        showHeader: {
+            type: Boolean,
+            value: true,
+        },
+        closeIcon: {
+            type: String,
+            value: 'cross',
+        },
+        fieldNames: {
+            type: Object,
+            value: defaultFieldNames,
+            observer: 'updateFieldNames',
+        },
+    },
+    data: {
+        tabs: [],
+        activeTab: 0,
+        textKey: FieldName.TEXT,
+        valueKey: FieldName.VALUE,
+        childrenKey: FieldName.CHILDREN,
+        innerValue: '',
+    },
+    watch: {
+        options() {
+            this.updateTabs();
+        },
+        value(newVal) {
+            this.updateValue(newVal);
+        },
+    },
+    created() {
+        this.updateTabs();
+    },
+    methods: {
+        updateValue(val) {
+            if (val !== undefined) {
+                const values = this.data.tabs.map((tab) => tab.selected && tab.selected[this.data.valueKey]);
+                if (values.indexOf(val) > -1) {
+                    return;
+                }
+            }
+            this.innerValue = val;
+            this.updateTabs();
+        },
+        updateFieldNames() {
+            const { text = 'text', value = 'value', children = 'children', } = this.data.fieldNames || defaultFieldNames;
+            this.setData({
+                textKey: text,
+                valueKey: value,
+                childrenKey: children,
+            });
+        },
+        getSelectedOptionsByValue(options, value) {
+            for (let i = 0; i < options.length; i++) {
+                const option = options[i];
+                if (option[this.data.valueKey] === value) {
+                    return [option];
+                }
+                if (option[this.data.childrenKey]) {
+                    const selectedOptions = this.getSelectedOptionsByValue(option[this.data.childrenKey], value);
+                    if (selectedOptions) {
+                        return [option, ...selectedOptions];
+                    }
+                }
+            }
+        },
+        updateTabs() {
+            const { options } = this.data;
+            const { innerValue } = this;
+            if (!options.length) {
+                return;
+            }
+            if (innerValue !== undefined) {
+                const selectedOptions = this.getSelectedOptionsByValue(options, innerValue);
+                if (selectedOptions) {
+                    let optionsCursor = options;
+                    const tabs = selectedOptions.map((option) => {
+                        const tab = {
+                            options: optionsCursor,
+                            selected: option,
+                        };
+                        const next = optionsCursor.find((item) => item[this.data.valueKey] === option[this.data.valueKey]);
+                        if (next) {
+                            optionsCursor = next[this.data.childrenKey];
+                        }
+                        return tab;
+                    });
+                    if (optionsCursor) {
+                        tabs.push({
+                            options: optionsCursor,
+                            selected: null,
+                        });
+                    }
+                    this.setData({
+                        tabs,
+                    });
+                    wx.nextTick(() => {
+                        this.setData({
+                            activeTab: tabs.length - 1,
+                        });
+                    });
+                    return;
+                }
+            }
+            this.setData({
+                tabs: [
+                    {
+                        options,
+                        selected: null,
+                    },
+                ],
+            });
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClickTab(e) {
+            const { index: tabIndex, title } = e.detail;
+            this.$emit('click-tab', { title, tabIndex });
+            this.setData({
+                activeTab: tabIndex,
+            });
+        },
+        // 选中
+        onSelect(e) {
+            const { option, tabIndex } = e.currentTarget.dataset;
+            if (option && option.disabled) {
+                return;
+            }
+            const { valueKey, childrenKey } = this.data;
+            let { tabs } = this.data;
+            tabs[tabIndex].selected = option;
+            if (tabs.length > tabIndex + 1) {
+                tabs = tabs.slice(0, tabIndex + 1);
+            }
+            if (option[childrenKey]) {
+                const nextTab = {
+                    options: option[childrenKey],
+                    selected: null,
+                };
+                if (tabs[tabIndex + 1]) {
+                    tabs[tabIndex + 1] = nextTab;
+                }
+                else {
+                    tabs.push(nextTab);
+                }
+                wx.nextTick(() => {
+                    this.setData({
+                        activeTab: tabIndex + 1,
+                    });
+                });
+            }
+            this.setData({
+                tabs,
+            });
+            const selectedOptions = tabs.map((tab) => tab.selected).filter(Boolean);
+            const value = option[valueKey];
+            const params = {
+                value,
+                tabIndex,
+                selectedOptions,
+            };
+            this.innerValue = value;
+            this.$emit('change', params);
+            if (!option[childrenKey]) {
+                this.$emit('finish', params);
+            }
+        },
+    },
+});

+ 8 - 0
wxcomponents/vant/dist/cascader/index.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-tab":  "../tab/index",
+    "van-tabs": "../tabs/index"
+  }
+}

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác