package-match.vue 5.7 KB

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