package-match.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <template>
  2. <view class="pm-wrap">
  3. <view class="pm-header">
  4. <text class="pm-title">推荐方案</text>
  5. <text class="pm-sub">根据你的情况,我们推荐以下方案</text>
  6. </view>
  7. <view class="pm-loading" v-if="loading">加载中...</view>
  8. <view class="pm-empty" v-else-if="packages.length === 0">暂无推荐方案</view>
  9. <view class="pm-list" v-else>
  10. <view class="pm-card" v-for="p in packages" :key="getKey(p)">
  11. <view class="pm-card-top">
  12. <text class="pm-card-name">{{ p.name }}</text>
  13. <text class="pm-card-price" v-if="p.price">¥{{ p.price }}</text>
  14. </view>
  15. <text class="pm-card-desc" v-if="p.description">{{ p.description }}</text>
  16. <view class="pm-card-meta" v-if="p.validityDays">
  17. <text class="pm-card-meta-text">有效期:{{ p.validityDays }}天</text>
  18. </view>
  19. <view class="pm-card-badges" v-if="p.badges && p.badges.length > 0">
  20. <text class="pm-badge" v-for="(b, i) in p.badges" :key="getBadgeKey(i)">{{ b }}</text>
  21. </view>
  22. <view class="pm-card-btn" @click="goDetail(p)">
  23. <text class="pm-card-btn-text">查看套餐详情</text>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. </template>
  29. <script>
  30. import { getProblemPackageDetail } from '../../utils/api.js'
  31. export default {
  32. data() {
  33. return {
  34. code: '',
  35. packages: [],
  36. loading: false
  37. }
  38. },
  39. onLoad(options) {
  40. this.code = (options && options.code) || ''
  41. this.loadPackages()
  42. },
  43. methods: {
  44. getBadgeKey: function(i) { return 'b' + i },
  45. getKey(p) {
  46. return p.id || p.code || Math.random()
  47. },
  48. loadPackages() {
  49. var self = this
  50. self.loading = true
  51. uni.showLoading({ title: '加载中...', mask: true })
  52. // 从问题域关联的推荐产品获取套餐列表
  53. var api = require('../../utils/api.js')
  54. var getDomainList = api.getProblemDomainList
  55. getDomainList().then(function(res) {
  56. uni.hideLoading()
  57. self.loading = false
  58. var list = res && res.data
  59. if (Array.isArray(list)) {
  60. var found = null
  61. for (var i = 0; i < list.length; i++) {
  62. if (list[i].code === self.code) {
  63. found = list[i]
  64. break
  65. }
  66. }
  67. if (found && found.recommended_product_ids) {
  68. var ids = String(found.recommended_product_ids).split(',').filter(function(s) { return s.trim() })
  69. // 每个ID调用详情接口
  70. self.loadPackageDetails(ids)
  71. } else {
  72. self.packages = self.getDefaultPackages()
  73. }
  74. } else {
  75. self.packages = self.getDefaultPackages()
  76. }
  77. }).catch(function() {
  78. uni.hideLoading()
  79. self.loading = false
  80. self.packages = self.getDefaultPackages()
  81. })
  82. },
  83. loadPackageDetails(ids) {
  84. if (ids.length === 0) {
  85. this.packages = this.getDefaultPackages()
  86. return
  87. }
  88. var self = this
  89. var results = []
  90. var loaded = 0
  91. ids.forEach(function(id) {
  92. getProblemPackageDetail(id).then(function(res) {
  93. loaded++
  94. var data = res && res.data
  95. if (data) {
  96. results.push(data)
  97. }
  98. if (loaded >= ids.length) {
  99. self.packages = results.length > 0 ? results : self.getDefaultPackages()
  100. }
  101. }).catch(function() {
  102. loaded++
  103. if (loaded >= ids.length) {
  104. self.packages = results.length > 0 ? results : self.getDefaultPackages()
  105. }
  106. })
  107. })
  108. },
  109. getDefaultPackages() {
  110. return [
  111. { id: 0, name: '标准方案', description: '包含基础检测与评估', price: 199, validityDays: 30, badges: ['推荐'] },
  112. { id: 1, name: '进阶方案', description: '含深度检测与个性化方案', price: 399, validityDays: 60, badges: ['热门'] },
  113. { id: 2, name: '全面方案', description: '全维度检测+定制任务+专家咨询', price: 699, validityDays: 90, badges: ['全面'] }
  114. ]
  115. },
  116. goDetail(p) {
  117. uni.navigateTo({
  118. url: '/pages/problem/package-detail?packageId=' + (p.id || '') + '&code=' + this.code
  119. })
  120. }
  121. }
  122. }
  123. </script>
  124. <style scoped>
  125. .pm-wrap {
  126. min-height: 100vh;
  127. background: #FFF7ED;
  128. padding: 40rpx 32rpx;
  129. box-sizing: border-box;
  130. }
  131. .pm-header {
  132. margin-bottom: 32rpx;
  133. }
  134. .pm-title {
  135. display: block;
  136. font-size: 38rpx;
  137. font-weight: bold;
  138. color: #333;
  139. text-align: center;
  140. }
  141. .pm-sub {
  142. display: block;
  143. font-size: 26rpx;
  144. color: #999;
  145. text-align: center;
  146. margin-top: 10rpx;
  147. }
  148. .pm-loading, .pm-empty {
  149. text-align: center;
  150. font-size: 28rpx;
  151. color: #999;
  152. padding: 80rpx 0;
  153. }
  154. .pm-card {
  155. background: #fff;
  156. border-radius: 24rpx;
  157. padding: 32rpx;
  158. margin-bottom: 24rpx;
  159. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
  160. }
  161. .pm-card-top {
  162. display: flex;
  163. justify-content: space-between;
  164. align-items: center;
  165. margin-bottom: 12rpx;
  166. }
  167. .pm-card-name {
  168. font-size: 32rpx;
  169. font-weight: 600;
  170. color: #333;
  171. }
  172. .pm-card-price {
  173. font-size: 36rpx;
  174. font-weight: bold;
  175. color: #F97316;
  176. }
  177. .pm-card-desc {
  178. display: block;
  179. font-size: 26rpx;
  180. color: #999;
  181. margin-bottom: 12rpx;
  182. }
  183. .pm-card-meta {
  184. margin-bottom: 12rpx;
  185. }
  186. .pm-card-meta-text {
  187. font-size: 24rpx;
  188. color: #999;
  189. }
  190. .pm-card-badges {
  191. display: flex;
  192. flex-wrap: wrap;
  193. margin-bottom: 16rpx;
  194. }
  195. .pm-badge {
  196. font-size: 22rpx;
  197. color: #F97316;
  198. background: rgba(249, 115, 22, 0.1);
  199. padding: 4rpx 16rpx;
  200. border-radius: 20rpx;
  201. margin-right: 12rpx;
  202. }
  203. .pm-card-btn {
  204. background: #FFF7ED;
  205. border: 2rpx solid #F97316;
  206. border-radius: 36rpx;
  207. padding: 18rpx 0;
  208. text-align: center;
  209. }
  210. .pm-card-btn:active {
  211. background: #FED7AA;
  212. }
  213. .pm-card-btn-text {
  214. color: #F97316;
  215. font-size: 28rpx;
  216. font-weight: 600;
  217. }
  218. </style>