my-feedback.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <view class="mf-page">
  3. <view class="mf-list" v-if="list.length > 0">
  4. <view class="mf-item" v-for="(item, idx) in list" :key="item.id">
  5. <view class="mf-item-head">
  6. <text class="mf-badge" :class="badgeClass(item)">{{ typeText(item) }}</text>
  7. <text class="mf-time">{{ formatTime(item.createdAt) }}</text>
  8. </view>
  9. <text class="mf-content">{{ item.content }}</text>
  10. <view class="mf-answer">
  11. <text class="mf-answer-label">解答</text>
  12. <text class="mf-answer-text" v-if="isAnswered(item)">{{ item.aiAnswer }}</text>
  13. <text class="mf-answer-text mf-answer-muted" v-else-if="isPending(item)">解答生成中,请稍后刷新查看</text>
  14. <text class="mf-answer-text mf-answer-muted" v-else>解答暂不可用</text>
  15. </view>
  16. </view>
  17. </view>
  18. <view class="mf-empty" v-else-if="!loading">
  19. <text class="mf-empty-icon">💬</text>
  20. <text class="mf-empty-text">还没有提交过反馈</text>
  21. <text class="mf-empty-hint">在健康报告详情页可以向我们提出疑问或建议</text>
  22. </view>
  23. <view class="mf-loading" v-else>
  24. <text class="mf-loading-text">加载中...</text>
  25. </view>
  26. </view>
  27. </template>
  28. <script>
  29. import { getMyReportFeedbacks } from '../../utils/api.js'
  30. export default {
  31. data: function() {
  32. return {
  33. list: [],
  34. loading: false,
  35. reportId: null
  36. }
  37. },
  38. onLoad: function(options) {
  39. if (options && options.reportId) {
  40. this.reportId = Number(options.reportId)
  41. }
  42. },
  43. onShow: function() {
  44. this.loadList()
  45. },
  46. onPullDownRefresh: function() {
  47. var self = this
  48. this.loadList(function() {
  49. uni.stopPullDownRefresh()
  50. })
  51. },
  52. methods: {
  53. loadList: function(done) {
  54. var self = this
  55. this.loading = true
  56. var payload = {}
  57. if (this.reportId) payload.reportId = this.reportId
  58. getMyReportFeedbacks(payload).then(function(res) {
  59. if (res.code === 200) {
  60. self.list = res.data || []
  61. } else {
  62. uni.showToast({ title: res.message || '加载失败', icon: 'none' })
  63. }
  64. }).catch(function() {
  65. uni.showToast({ title: '加载失败', icon: 'none' })
  66. }).then(function() {
  67. self.loading = false
  68. if (done) done()
  69. })
  70. },
  71. typeText: function(item) {
  72. return item.feedbackType === 'suggestion' ? '建议' : '疑问'
  73. },
  74. badgeClass: function(item) {
  75. return item.feedbackType === 'suggestion' ? 'mf-badge-suggestion' : 'mf-badge-question'
  76. },
  77. isAnswered: function(item) {
  78. return item.aiStatus === 'answered' && !!item.aiAnswer
  79. },
  80. isPending: function(item) {
  81. return item.aiStatus === 'pending'
  82. },
  83. formatTime: function(v) {
  84. if (!v) return ''
  85. var s = String(v)
  86. if (s.length >= 19) return s.substring(0, 19).replace('T', ' ')
  87. return s.substring(0, 10)
  88. }
  89. }
  90. }
  91. </script>
  92. <style scoped>
  93. .mf-page {
  94. min-height: 100vh;
  95. background: #F7F8FA;
  96. padding: 20rpx;
  97. box-sizing: border-box;
  98. }
  99. .mf-item {
  100. background: #fff;
  101. border-radius: 16rpx;
  102. padding: 24rpx;
  103. margin-bottom: 20rpx;
  104. }
  105. .mf-item-head {
  106. display: flex;
  107. justify-content: space-between;
  108. align-items: center;
  109. margin-bottom: 14rpx;
  110. }
  111. .mf-badge {
  112. font-size: 22rpx;
  113. padding: 4rpx 16rpx;
  114. border-radius: 20rpx;
  115. }
  116. .mf-badge-question {
  117. color: #4A9BD7;
  118. background: #EAF4FC;
  119. }
  120. .mf-badge-suggestion {
  121. color: #E6A23C;
  122. background: #FDF4E7;
  123. }
  124. .mf-time {
  125. font-size: 22rpx;
  126. color: #bbb;
  127. }
  128. .mf-content {
  129. display: block;
  130. font-size: 28rpx;
  131. color: #333;
  132. line-height: 1.6;
  133. word-break: break-all;
  134. margin-bottom: 18rpx;
  135. }
  136. .mf-answer {
  137. background: #F5FAFE;
  138. border-radius: 12rpx;
  139. padding: 18rpx;
  140. }
  141. .mf-answer-label {
  142. display: block;
  143. font-size: 22rpx;
  144. color: #10B981;
  145. margin-bottom: 8rpx;
  146. }
  147. .mf-answer-text {
  148. font-size: 26rpx;
  149. color: #333;
  150. line-height: 1.7;
  151. word-break: break-all;
  152. }
  153. .mf-answer-muted {
  154. color: #999;
  155. }
  156. .mf-empty {
  157. padding: 160rpx 60rpx 0;
  158. display: flex;
  159. flex-direction: column;
  160. align-items: center;
  161. }
  162. .mf-empty-icon {
  163. font-size: 80rpx;
  164. margin-bottom: 24rpx;
  165. }
  166. .mf-empty-text {
  167. font-size: 30rpx;
  168. color: #666;
  169. margin-bottom: 12rpx;
  170. }
  171. .mf-empty-hint {
  172. font-size: 24rpx;
  173. color: #aaa;
  174. text-align: center;
  175. line-height: 1.6;
  176. }
  177. .mf-loading {
  178. padding: 160rpx 0;
  179. display: flex;
  180. justify-content: center;
  181. }
  182. .mf-loading-text {
  183. font-size: 26rpx;
  184. color: #999;
  185. }
  186. </style>