browsing-history.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <template>
  2. <view class="container">
  3. <!-- 顶部导航栏 -->
  4. <view class="header">
  5. <view class="back-btn" @click="goBack">
  6. <text class="back-icon">←</text>
  7. </view>
  8. <text class="header-title">浏览记录</text>
  9. <view class="clear-btn" @click="handleClear">
  10. <text class="clear-text">清空</text>
  11. </view>
  12. </view>
  13. <!-- 浏览记录列表 -->
  14. <scroll-view class="scroll-content" scroll-y>
  15. <view class="history-list">
  16. <view
  17. class="history-item"
  18. v-for="(item, index) in historyList"
  19. :key="index"
  20. @click="goToBookDetail(item)"
  21. >
  22. <image class="book-cover" :src="item.image" mode="aspectFill" :lazy-load="true"></image>
  23. <view class="book-info">
  24. <text class="book-title">{{ item.title }}</text>
  25. <text class="book-time">{{ item.time }}</text>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="empty-state" v-if="historyList.length === 0">
  30. <text class="empty-text">暂无浏览记录</text>
  31. </view>
  32. </scroll-view>
  33. </view>
  34. </template>
  35. <script>
  36. import { getBrowsingHistory, clearBrowsingHistory } from '../../utils/api.js'
  37. export default {
  38. data() {
  39. return {
  40. historyList: [],
  41. userInfo: null,
  42. isLoading: false
  43. }
  44. },
  45. onLoad() {
  46. // 获取用户信息
  47. try {
  48. const userInfo = uni.getStorageSync('userInfo')
  49. if (userInfo && userInfo.id) {
  50. this.userInfo = userInfo
  51. // 加载浏览记录
  52. this.loadBrowsingHistory()
  53. } else {
  54. uni.showToast({
  55. title: '请先登录',
  56. icon: 'none'
  57. })
  58. setTimeout(() => {
  59. uni.navigateBack()
  60. }, 1500)
  61. }
  62. } catch (e) {
  63. console.error('获取用户信息失败', e)
  64. }
  65. },
  66. methods: {
  67. goBack() {
  68. uni.navigateBack()
  69. },
  70. async loadBrowsingHistory() {
  71. if (!this.userInfo || !this.userInfo.id) {
  72. return
  73. }
  74. try {
  75. this.isLoading = true
  76. const res = await getBrowsingHistory(this.userInfo.id)
  77. if (res && res.code === 200 && res.data) {
  78. this.historyList = res.data.map(item => ({
  79. id: item.bookId,
  80. title: item.title || '未知书籍',
  81. image: item.image || 'https://via.placeholder.com/200x300?text=No+Image',
  82. time: item.time || ''
  83. }))
  84. } else {
  85. this.historyList = []
  86. }
  87. } catch (e) {
  88. console.error('加载浏览记录失败', e)
  89. this.historyList = []
  90. } finally {
  91. this.isLoading = false
  92. }
  93. },
  94. handleClear() {
  95. if (!this.userInfo || !this.userInfo.id) {
  96. return
  97. }
  98. uni.showModal({
  99. title: '提示',
  100. content: '确定要清空所有浏览记录吗?',
  101. success: async (res) => {
  102. if (res.confirm) {
  103. try {
  104. uni.showLoading({
  105. title: '清空中...',
  106. mask: true
  107. })
  108. const result = await clearBrowsingHistory(this.userInfo.id)
  109. uni.hideLoading()
  110. if (result && result.code === 200) {
  111. this.historyList = []
  112. uni.showToast({
  113. title: '已清空',
  114. icon: 'success'
  115. })
  116. } else {
  117. uni.showToast({
  118. title: result.message || '清空失败',
  119. icon: 'none'
  120. })
  121. }
  122. } catch (e) {
  123. uni.hideLoading()
  124. console.error('清空浏览记录失败', e)
  125. uni.showToast({
  126. title: '清空失败,请重试',
  127. icon: 'none'
  128. })
  129. }
  130. }
  131. }
  132. })
  133. },
  134. goToBookDetail(item) {
  135. if (!item || !item.id) {
  136. uni.showToast({
  137. title: '书籍信息不完整',
  138. icon: 'none'
  139. })
  140. return
  141. }
  142. uni.navigateTo({
  143. url: `/pages/book-detail/book-detail?bookId=${item.id}`
  144. })
  145. }
  146. }
  147. }
  148. </script>
  149. <style scoped>
  150. .container {
  151. width: 100%;
  152. height: 100vh;
  153. background-color: #FFFFFF;
  154. display: flex;
  155. flex-direction: column;
  156. padding-top: 30px;
  157. box-sizing: border-box;
  158. }
  159. .header {
  160. display: flex;
  161. align-items: center;
  162. justify-content: space-between;
  163. padding: 20rpx 30rpx;
  164. background-color: #FFFFFF;
  165. border-bottom: 1rpx solid #E0E0E0;
  166. position: relative;
  167. }
  168. .back-btn {
  169. width: 60rpx;
  170. height: 60rpx;
  171. display: flex;
  172. align-items: center;
  173. justify-content: center;
  174. }
  175. .back-icon {
  176. font-size: 40rpx;
  177. color: #333333;
  178. font-weight: bold;
  179. }
  180. .header-title {
  181. position: absolute;
  182. left: 50%;
  183. transform: translateX(-50%);
  184. font-size: 36rpx;
  185. font-weight: bold;
  186. color: #333333;
  187. }
  188. .clear-btn {
  189. width: 80rpx;
  190. height: 60rpx;
  191. display: flex;
  192. align-items: center;
  193. justify-content: center;
  194. }
  195. .clear-text {
  196. font-size: 28rpx;
  197. color: #666666;
  198. }
  199. .scroll-content {
  200. flex: 1;
  201. width: 100%;
  202. padding: 20rpx 30rpx;
  203. }
  204. .history-list {
  205. display: flex;
  206. flex-direction: column;
  207. }
  208. .history-item {
  209. display: flex;
  210. align-items: center;
  211. padding: 30rpx 0;
  212. border-bottom: 1rpx solid #F0F0F0;
  213. }
  214. .history-item:last-child {
  215. border-bottom: none;
  216. }
  217. .book-cover {
  218. width: 160rpx;
  219. height: 220rpx;
  220. border-radius: 8rpx;
  221. margin-right: 30rpx;
  222. flex-shrink: 0;
  223. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
  224. background-color: #F5F5F5;
  225. }
  226. .book-info {
  227. flex: 1;
  228. display: flex;
  229. flex-direction: column;
  230. justify-content: center;
  231. min-width: 0;
  232. }
  233. .book-title {
  234. font-size: 32rpx;
  235. font-weight: bold;
  236. color: #333333;
  237. margin-bottom: 20rpx;
  238. overflow: hidden;
  239. text-overflow: ellipsis;
  240. white-space: nowrap;
  241. }
  242. .book-time {
  243. font-size: 24rpx;
  244. color: #999999;
  245. }
  246. .empty-state {
  247. padding: 200rpx 0;
  248. text-align: center;
  249. }
  250. .empty-text {
  251. font-size: 28rpx;
  252. color: #999999;
  253. }
  254. </style>