普兆健康管家前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
6.6 KiB

2 months ago
  1. <template>
  2. <view class="page__view">
  3. <navbar title="检测报告" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" />
  4. <view class="main">
  5. <view id="swiper" class="swiper">
  6. <view id="home" :class="['swiper-item', 'swiper-item-home', current == 0 ? 'with-tips' : '']">
  7. <view class="content">
  8. <resultSummary :data="summaryData"></resultSummary>
  9. </view>
  10. <view v-if="current == 0" class="flex footer">
  11. <image class="footer-icon" src="@/pages_order/static/report/arrow-left.png" mode="widthFix"></image>
  12. <text>向左滑动卡片查看推荐补剂及原因</text>
  13. </view>
  14. </view>
  15. <view :id="item.id" :class="['swiper-item', getIsShowTips(index, current) ? 'with-tips' : '']"
  16. v-for="(item, index) in productList"
  17. :key="item.id"
  18. >
  19. <view class="content">
  20. <tonicCard :data="item" :index="index"></tonicCard>
  21. </view>
  22. <view v-if="getIsShowTips(index, current)" class="flex footer">
  23. <image class="footer-icon" src="@/pages_order/static/report/arrow-left.png" mode="widthFix"></image>
  24. <text>向左滑动卡片查看推荐补剂及原因</text>
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="bottom">
  30. <indicator :current="current" :length="productList.length + 1"></indicator>
  31. <view class="flex bar">
  32. <button class="flex btn" @click="jumpToReportDetail">详细报告</button>
  33. <button class="flex btn highlight" @click="jumpToNutritionProgram">查看营养方案</button>
  34. </view>
  35. </view>
  36. </view>
  37. </template>
  38. <script>
  39. import indicator from '@/components/home/indicator.vue'
  40. import resultSummary from './resultSummary.vue'
  41. import tonicCard from './tonicCard.vue'
  42. export default {
  43. components: {
  44. indicator,
  45. resultSummary,
  46. tonicCard,
  47. },
  48. data() {
  49. return {
  50. id: null,
  51. current: 0,
  52. summaryData: {},
  53. productList: [],
  54. observer: null,
  55. }
  56. },
  57. async onLoad(arg) {
  58. const { id } = arg
  59. this.id = id
  60. await this.fetchReportData(id)
  61. this.$nextTick(() => {
  62. this.observeElement()
  63. })
  64. },
  65. unmounted() {
  66. this.observer.disconnect()
  67. },
  68. methods: {
  69. async fetchReportData(id) {
  70. try {
  71. const result = await this.$fetch('getReportDetail', { id })
  72. const {
  73. score,
  74. scoreDetail,
  75. json,
  76. productList,
  77. } = result
  78. let detail = JSON.parse(json)?.filter(item => ['0', '1'].includes(item.type))
  79. console.log('detail', detail)
  80. this.summaryData = {
  81. score: parseInt(score),
  82. scoreDetail: JSON.parse(scoreDetail).map(item => ({ name: item.name, score: parseInt(item.score) })),
  83. detail,
  84. }
  85. this.productList = productList
  86. console.log('summaryData', this.summaryData)
  87. console.log('productList', this.productList)
  88. } catch (err) {
  89. }
  90. },
  91. observeElement() {
  92. this.observer = uni.createIntersectionObserver(this, { observeAll: true, thresholds: [0.5] });
  93. this.observer.relativeTo('.swiper').observe('.swiper-item', res => {
  94. let current = 0
  95. if (res.intersectionRatio > 0.5) {
  96. current = res.id === 'home' ? 0 : this.productList.findIndex(item => item.id === res.id)
  97. } else if (res.intersectionRatio > 0) {
  98. current = res.id === 'home' ? 0 : this.productList.findIndex(item => item.id === res.id) + 1
  99. if (res.boundingClientRect.left > 0) {
  100. current -= 1
  101. } else {
  102. current += 1
  103. }
  104. }
  105. this.current = current
  106. })
  107. },
  108. getIsShowTips(index, current) {
  109. return current == index + 1 && current < this.productList.length
  110. },
  111. jumpToReportDetail() {
  112. this.$utils.navigateTo(`/pages_order/report/detail/index?id=${this.id}`)
  113. },
  114. jumpToNutritionProgram() {
  115. this.$utils.navigateTo(`/pages_order/report/nutritionProgram/index?id=${this.id}`)
  116. },
  117. },
  118. }
  119. </script>
  120. <style scoped lang="scss">
  121. .page__view {
  122. width: 100vw;
  123. min-height: 100vh;
  124. background-color: $uni-bg-color;
  125. position: relative;
  126. }
  127. .swiper {
  128. display: flex;
  129. overflow: auto;
  130. scroll-snap-type: x mandatory;
  131. width: 100vw;
  132. // height: calc(100vh * 640 / 882);
  133. height: auto;
  134. margin-top: 32rpx;
  135. &::-webkit-scrollbar{
  136. width: 0;
  137. height: 0;
  138. }
  139. }
  140. $tips-height: 108rpx;
  141. .swiper-item {
  142. position: relative;
  143. display: flex;
  144. justify-content: center;
  145. flex-shrink: 0;
  146. scroll-snap-align: center;
  147. scroll-snap-stop: always;
  148. $swiper-width: calc(100vw * 300 / 375);
  149. width: $swiper-width;
  150. // height: 100%;
  151. // height: auto;
  152. // height: 1186rpx;
  153. height: 1162rpx;
  154. margin-left: 32rpx;
  155. padding-bottom: $tips-height;
  156. // box-sizing: border-box;
  157. .content {
  158. position: relative;
  159. width: 100%;
  160. height: 100%;
  161. width: calc(100% - 8rpx * 2);
  162. height: calc(100% - 8rpx * 2);
  163. background-image: linear-gradient(#F2EDFF, #FCFEFE);
  164. border: 8rpx solid #F9F7FF;
  165. border-radius: 64rpx;
  166. }
  167. &.with-tips {
  168. .content {
  169. height: calc(100% - 8rpx);
  170. border-bottom: none;
  171. border-bottom-left-radius: 0;
  172. border-bottom-right-radius: 0;
  173. }
  174. }
  175. &-home {
  176. width: calc(100vw * 322 / 375);
  177. // height: 1320rpx;
  178. // height: auto;
  179. .content {
  180. overflow-y: auto;
  181. }
  182. }
  183. &:last-child {
  184. margin-right: calc((100vw - #{$swiper-width}) / 2);
  185. }
  186. }
  187. .footer {
  188. position: absolute;
  189. left: 0;
  190. bottom: 0;
  191. width: 100%;
  192. height: $tips-height;
  193. font-family: PingFang SC;
  194. font-weight: 400;
  195. font-size: 28rpx;
  196. line-height: 1.5;
  197. color: #252545;
  198. background: #E5E4EB;
  199. border-bottom-left-radius: 64rpx;
  200. border-bottom-right-radius: 64rpx;
  201. &-icon {
  202. width: 40rpx;
  203. height: 40rpx;
  204. margin-right: 16rpx;
  205. }
  206. }
  207. .bottom {
  208. width: 100%;
  209. position: fixed;
  210. left: 0;
  211. bottom: 0;
  212. }
  213. .bar {
  214. padding: 24rpx 40rpx;
  215. padding-bottom: calc(env(safe-area-inset-bottom) + 24rpx);
  216. background: #FFFFFF;
  217. column-gap: 32rpx;
  218. margin-top: 16rpx;
  219. .btn {
  220. flex: 1;
  221. font-family: PingFang SC;
  222. font-size: 36rpx;
  223. font-weight: 500;
  224. line-height: 1;
  225. padding: 14rpx 0;
  226. border: 2rpx solid #252545;
  227. border-radius: 41rpx;
  228. &.highlight {
  229. padding: 16rpx 0;
  230. color: #FFFFFF;
  231. background-image: linear-gradient(to right, #4B348F, #845CFA);
  232. border: none;
  233. }
  234. }
  235. }
  236. </style>