四零语境前端代码仓库
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.

320 lines
6.6 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="search-container">
  3. <!-- 顶部搜索栏 -->
  4. <view class="search-header">
  5. <uv-search
  6. v-model="searchKeyword"
  7. placeholder="请输入内容"
  8. :show-action="true"
  9. action-text="搜索"
  10. :action-style="{
  11. color: '#fff',
  12. backgroundColor: '#06DADC',
  13. borderRadius: '198rpx',
  14. width: '100rpx',
  15. height: '64rpx',
  16. textAlign: 'center',
  17. fontSize: '26rpx',
  18. lineHeight: '64rpx',
  19. }"
  20. @search="handleSearch"
  21. @custom="handleSearch"
  22. @clear="handleSearch"
  23. ></uv-search>
  24. <!-- 分类标签栏 -->
  25. <view class="category-tabs">
  26. <scroll-view scroll-x class="tab-scroll">
  27. <view class="tab-list">
  28. <view
  29. v-for="(tab, index) in categoryTabs"
  30. :key="index"
  31. class="tab-item"
  32. :class="{ active: currentTab === index }"
  33. @click="switchTab(index)"
  34. >
  35. {{ tab.title }}
  36. </view>
  37. </view>
  38. </scroll-view>
  39. </view>
  40. </view>
  41. <!-- 搜索结果列表 -->
  42. <view class="search-results">
  43. <view
  44. v-for="(book, index) in list"
  45. :key="index"
  46. class="book-item"
  47. @click="goToDetail(book)"
  48. >
  49. <view class="book-cover">
  50. <image :src="book.booksImg" mode="aspectFill"></image>
  51. </view>
  52. <view class="book-info">
  53. <view class="book-title">{{ book.booksName }}</view>
  54. <view class="book-author">{{ book.booksAuthor }}</view>
  55. <view class="book-meta">
  56. <view class="book-duration">
  57. <image src="/static/play-icon.png" mode="aspectFill" class="book-icon"></image>
  58. <text>{{ book.duration }}</text>
  59. </view>
  60. <view class="book-membership" :class="classMap[book.vipInfo.title]">
  61. {{ book.vipInfo.title }}
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. <uv-loading-icon text="加载中" textSize="30rpx" v-if="isLoading" ></uv-loading-icon>
  67. <uv-empty v-else-if="list.length === 0" ></uv-empty>
  68. </view>
  69. </view>
  70. </template>
  71. <script>
  72. import MixinList from '@/mixins/list.js'
  73. export default {
  74. mixins: [MixinList],
  75. data() {
  76. return {
  77. mixinListApi: 'book.list',
  78. // 自定义onShow
  79. mixinListConfig: {
  80. customOnShow: true,
  81. },
  82. searchKeyword: '',
  83. label : '',
  84. currentTab: 0,
  85. categoryTabs: [ ],
  86. // 类型引射表
  87. classMap: {
  88. '蕾朵会员': 'book-membership-premium',
  89. '盛放会员': 'book-membership-vip',
  90. '萌芽会员': 'book-membership-basic',
  91. },
  92. bookList: [
  93. ]
  94. }
  95. },
  96. methods: {
  97. mixinSetParams(){
  98. const params = {
  99. category: this.categoryTabs[this.currentTab].id,
  100. }
  101. if(this.label){
  102. params.label = this.label
  103. }
  104. if(this.searchKeyword){
  105. params.title = this.searchKeyword
  106. }
  107. return params
  108. },
  109. handleSearch() {
  110. // console.log('搜索:', this.searchKeyword)
  111. this.list = []
  112. this.initPage()
  113. this.getList(true)
  114. // 这里添加搜索逻辑
  115. },
  116. switchTab(index) {
  117. this.currentTab = index
  118. // console.log('切换分类:', this.categoryTabs[index])
  119. this.list = []
  120. this.initPage()
  121. this.getList(true)
  122. // 这里添加分类切换逻辑
  123. },
  124. goToDetail(book) {
  125. uni.navigateTo({
  126. url: '/subPages/home/directory?id=' + book.id
  127. })
  128. },
  129. // 获取书籍分类
  130. async getCategory() {
  131. const categoryRes = await this.$api.book.category()
  132. if (categoryRes.code === 200){
  133. this.categoryTabs = categoryRes.result.map(item => ({
  134. title:item.title,
  135. id: item.id
  136. }))
  137. }
  138. },
  139. },
  140. onLoad(options) {
  141. if (options.label){
  142. this.label = options.label
  143. }
  144. },
  145. async onShow() {
  146. await this.getCategory()
  147. this.getList()
  148. }
  149. }
  150. </script>
  151. <style scoped lang="scss">
  152. .search-container {
  153. background: #fff;
  154. min-height: 100vh;
  155. }
  156. .search-header {
  157. padding: 10rpx 32rpx 6rpx;
  158. background: #fff;
  159. position: sticky;
  160. top: 0;
  161. left: 0;
  162. right: 0;
  163. }
  164. .category-tabs {
  165. background: #fff;
  166. // border-bottom: 1rpx solid #f0f0f0;
  167. .tab-scroll {
  168. white-space: nowrap;
  169. }
  170. .tab-list {
  171. display: flex;
  172. padding: 0 32rpx;
  173. }
  174. .tab-item {
  175. flex-shrink: 0;
  176. padding: 24rpx 22rpx;
  177. font-size: 32rpx;
  178. color: $secondary-text-color;
  179. position: relative;
  180. &.active {
  181. color: $primary-text-color;
  182. font-weight: 600;
  183. &::after {
  184. content: '';
  185. position: absolute;
  186. bottom: 0;
  187. left: 50%;
  188. transform: translateX(-50%);
  189. width: 22rpx;
  190. height: 4rpx;
  191. background: $primary-text-color;
  192. border-radius: 2rpx;
  193. }
  194. }
  195. }
  196. }
  197. .search-results {
  198. padding: 32rpx;
  199. display: flex;
  200. flex-direction: column;
  201. gap: 32rpx;
  202. }
  203. .book-item {
  204. display: flex;
  205. align-items: center;
  206. // border-bottom: 1rpx solid #f5f5f5;
  207. background: #F8F8F8;
  208. // width: 686rpx;
  209. height: 212rpx;
  210. gap: 16rpx;
  211. border-radius: 16rpx;
  212. padding: 0rpx 16rpx;
  213. &:last-child {
  214. border-bottom: none;
  215. }
  216. .book-cover {
  217. width: 136rpx;
  218. height: 180rpx;
  219. border-radius: 16rpx;
  220. overflow: hidden;
  221. margin-right: 16rpx;
  222. image {
  223. width: 100%;
  224. height: 100%;
  225. }
  226. }
  227. .book-info {
  228. flex: 1;
  229. display: flex;
  230. flex-direction: column;
  231. justify-content: space-between;
  232. }
  233. .book-title {
  234. font-size: 32rpx;
  235. font-weight: 600;
  236. color: $primary-text-color;
  237. line-height: 48rpx;
  238. letter-spacing: 0;
  239. margin-bottom: 12rpx;
  240. overflow: hidden;
  241. text-overflow: ellipsis;
  242. }
  243. .book-author {
  244. font-size: 24rpx;
  245. color: $secondary-text-color;
  246. margin-bottom: 16rpx;
  247. overflow: hidden;
  248. text-overflow: ellipsis;
  249. white-space: nowrap;
  250. }
  251. .book-meta {
  252. display: flex;
  253. align-items: center;
  254. justify-content: space-between;
  255. }
  256. .book-duration {
  257. display: flex;
  258. align-items: center;
  259. font-size: 22rpx;
  260. color: #999;
  261. .book-icon{
  262. width: 18rpx;
  263. height: 18rpx;
  264. }
  265. text {
  266. margin-left: 8rpx;
  267. }
  268. }
  269. .book-membership {
  270. padding: 8rpx 16rpx;
  271. border-radius: 8rpx;
  272. font-size: 24rpx;
  273. color: #211508;
  274. }
  275. }
  276. .book-membership-premium {
  277. background: #E9F1FF;
  278. border: 2rpx solid #C4DAFF
  279. }
  280. .book-membership-vip {
  281. background: #FFF4E9;
  282. border: 2rpx solid #FFE2C4
  283. }
  284. .book-membership-basic {
  285. background: #FFE9E9;
  286. border: 2rpx solid #FFDBC4
  287. }
  288. </style>