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