普兆健康管家前端代码仓库
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.

275 lines
6.7 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. props: {
  49. id: {
  50. type: String | Number,
  51. default: null,
  52. }
  53. },
  54. data() {
  55. return {
  56. id: null,
  57. current: 0,
  58. summaryData: {},
  59. productList: [],
  60. observer: null,
  61. }
  62. },
  63. async onLoad(arg) {
  64. const { id } = arg
  65. this.id = id
  66. await this.fetchReportData(id)
  67. this.$nextTick(() => {
  68. this.observeElement()
  69. })
  70. },
  71. unmounted() {
  72. this.observer.disconnect()
  73. },
  74. methods: {
  75. async fetchReportData(id) {
  76. try {
  77. const result = await this.$fetch('getReportDetail', { id })
  78. const {
  79. score,
  80. scoreDetail,
  81. json,
  82. productList,
  83. } = result
  84. let detail = JSON.parse(json)?.filter(item => ['0', '1'].includes(item.type))
  85. console.log('detail', detail)
  86. this.summaryData = {
  87. score: parseInt(score),
  88. scoreDetail: JSON.parse(scoreDetail).map(item => ({ name: item.name, score: parseInt(item.score) })),
  89. detail,
  90. }
  91. this.productList = productList
  92. console.log('summaryData', this.summaryData)
  93. console.log('productList', this.productList)
  94. } catch (err) {
  95. }
  96. },
  97. observeElement() {
  98. this.observer = uni.createIntersectionObserver(this, { observeAll: true, thresholds: [0.5] });
  99. this.observer.relativeTo('.swiper').observe('.swiper-item', res => {
  100. let current = 0
  101. if (res.intersectionRatio > 0.5) {
  102. current = res.id === 'home' ? 0 : this.productList.findIndex(item => item.id === res.id)
  103. } else if (res.intersectionRatio > 0) {
  104. current = res.id === 'home' ? 0 : this.productList.findIndex(item => item.id === res.id) + 1
  105. if (res.boundingClientRect.left > 0) {
  106. current -= 1
  107. } else {
  108. current += 1
  109. }
  110. }
  111. this.current = current
  112. })
  113. },
  114. getIsShowTips(index, current) {
  115. return current == index + 1 && current < this.productList.length
  116. },
  117. jumpToReportDetail() {
  118. this.$utils.navigateTo(`/pages_order/report/detail/index?id=${this.id}`)
  119. },
  120. jumpToNutritionProgram() {
  121. this.$utils.navigateTo(`/pages_order/report/nutritionProgram/index?id=${this.id}`)
  122. },
  123. },
  124. }
  125. </script>
  126. <style scoped lang="scss">
  127. .page__view {
  128. width: 100vw;
  129. min-height: 100vh;
  130. background-color: $uni-bg-color;
  131. position: relative;
  132. }
  133. .swiper {
  134. display: flex;
  135. overflow: auto;
  136. scroll-snap-type: x mandatory;
  137. width: 100vw;
  138. // height: calc(100vh * 640 / 882);
  139. height: auto;
  140. margin-top: 32rpx;
  141. &::-webkit-scrollbar{
  142. width: 0;
  143. height: 0;
  144. }
  145. }
  146. $tips-height: 108rpx;
  147. .swiper-item {
  148. position: relative;
  149. display: flex;
  150. justify-content: center;
  151. flex-shrink: 0;
  152. scroll-snap-align: center;
  153. scroll-snap-stop: always;
  154. $swiper-width: calc(100vw * 300 / 375);
  155. width: $swiper-width;
  156. // height: 100%;
  157. // height: auto;
  158. // height: 1186rpx;
  159. height: 1162rpx;
  160. margin-left: 32rpx;
  161. padding-bottom: $tips-height;
  162. // box-sizing: border-box;
  163. .content {
  164. position: relative;
  165. width: 100%;
  166. height: 100%;
  167. width: calc(100% - 8rpx * 2);
  168. height: calc(100% - 8rpx * 2);
  169. background-image: linear-gradient(#F2EDFF, #FCFEFE);
  170. border: 8rpx solid #F9F7FF;
  171. border-radius: 64rpx;
  172. }
  173. &.with-tips {
  174. .content {
  175. height: calc(100% - 8rpx);
  176. border-bottom: none;
  177. border-bottom-left-radius: 0;
  178. border-bottom-right-radius: 0;
  179. }
  180. }
  181. &-home {
  182. width: calc(100vw * 322 / 375);
  183. // height: 1320rpx;
  184. // height: auto;
  185. .content {
  186. overflow-y: auto;
  187. }
  188. }
  189. &:last-child {
  190. margin-right: calc((100vw - #{$swiper-width}) / 2);
  191. }
  192. }
  193. .footer {
  194. position: absolute;
  195. left: 0;
  196. bottom: 0;
  197. width: 100%;
  198. height: $tips-height;
  199. font-family: PingFang SC;
  200. font-weight: 400;
  201. font-size: 28rpx;
  202. line-height: 1.5;
  203. color: #252545;
  204. background: #E5E4EB;
  205. border-bottom-left-radius: 64rpx;
  206. border-bottom-right-radius: 64rpx;
  207. &-icon {
  208. width: 40rpx;
  209. height: 40rpx;
  210. margin-right: 16rpx;
  211. }
  212. }
  213. .bottom {
  214. width: 100%;
  215. position: fixed;
  216. left: 0;
  217. bottom: 0;
  218. }
  219. .bar {
  220. padding: 24rpx 40rpx;
  221. padding-bottom: calc(env(safe-area-inset-bottom) + 24rpx);
  222. background: #FFFFFF;
  223. column-gap: 32rpx;
  224. margin-top: 16rpx;
  225. .btn {
  226. flex: 1;
  227. font-family: PingFang SC;
  228. font-size: 36rpx;
  229. font-weight: 500;
  230. line-height: 1;
  231. padding: 14rpx 0;
  232. border: 2rpx solid #252545;
  233. border-radius: 41rpx;
  234. &.highlight {
  235. padding: 16rpx 0;
  236. color: #FFFFFF;
  237. background-image: linear-gradient(to right, #4B348F, #845CFA);
  238. border: none;
  239. }
  240. }
  241. }
  242. </style>