瀏覽代碼

feat: 完成 书籍分类 相关逻辑和请求

YuJing 1 月之前
父節點
當前提交
fef68625e8

+ 1 - 1
features/feature/src/main/ets/apis/BookListApi.ets

@@ -30,7 +30,7 @@ class BookListApi {
   }
 
   /**
-   * @description 获取所有的主题分类集合
+   * @description 获取所有的书籍主题分类集合
    * @method GET
    */
   getAllThemes(): Promise<Array<BookListTypeList>>{

+ 5 - 5
features/feature/src/main/ets/components/BuilderIndex.ets

@@ -1,5 +1,5 @@
 import { yTRouter } from "basic"
-import { BookListItem } from "../model/BookModelIndex"
+import { BookItem, BookListItem } from "../model/BookModelIndex"
 import { CustomTextStyle } from "../style/CustomTextStyle"
 
 // 标签Item
@@ -61,7 +61,7 @@ export function bookListItemComp(item: RepeatItem<BookListItem>){
 
 // 书籍Item
 @Builder
-export function bookItemComp(title: string, onClick: () => void){
+export function bookItemComp(item: RepeatItem<BookItem>, onClick: () => void){
   Row({space: 11}){
     Image($r('[basic].media.png_TopRecommend'))
       .width(86)
@@ -69,10 +69,10 @@ export function bookItemComp(title: string, onClick: () => void){
       .borderRadius(12)
 
     Column({space: 3}){
-      Text(title)
+      Text(item.item?.bookTitle)
         .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
 
-      Text('豆瓣平均分9.2分推荐!红红火火恍恍惚惚哈哈哈哈哈给红红火火恍恍惚惚哈哈哈...')
+      Text(item.item?.bookSubtitle)
         .width('100%')
         .attributeModifier(new CustomTextStyle({size: 12, weight: 400, color: '#FF555555'}))
 
@@ -81,8 +81,8 @@ export function bookItemComp(title: string, onClick: () => void){
 
       Row(){
         Row({space: 13}){
+          tagItemComp(`${item.item.minAge}-${item.item.maxAge}岁`, '#FFFC9911', '#FFFFF5E7')
           tagItemComp('情绪价值', '#FF4EB1EF', '#FFEDF7FD')
-          tagItemComp('3-8岁', '#FFFC9911', '#FFFFF5E7')
         }
 
         Image(true ? $r('[basic].media.icon_deerIncrease') : $r('[basic].media.icon_reduce'))

+ 1 - 1
features/feature/src/main/ets/model/BookModelIndex.ets

@@ -127,7 +127,7 @@ export class BookListTypeList {
   /** 排序 */
   sort?: string;
   /** 分类名称 */
-  typeName?: string;
+  bookListTypeName?: string;
   /** 创建人 */
   createBy?: string;
   /** 创建时间 */

+ 23 - 7
features/feature/src/main/ets/model/Query.ets

@@ -14,7 +14,8 @@ abstract class Query{
   }
 }
 
-// 搜索书单
+
+/** 搜索书单 */
 export class searchBookListQuery extends Query{
   /** 书单类型ID **/
   bookListTypeId?: string
@@ -22,16 +23,31 @@ export class searchBookListQuery extends Query{
   key?: string
 }
 
-// 搜索书籍
+
+/** 搜索书籍 */
+@ObservedV2
 export class searchBookQuery extends Query {
   /** 搜索关键词 */
-  key?: string;
+  @Trace key?: string;
   /** 最大适读年龄 */
-  maxAge?: number;
+  @Trace maxAge?: number;
   /** 最小适读年龄 */
-  minAge?: number;
+  @Trace minAge?: number;
   /** 排序方式 */
-  sort?: number;
+  @Trace sort: number = 0;
   /** 分类ID */
-  typeId?: number;
+  @Trace typeId?: string;
+
+
+  clone(): searchBookQuery {
+    return {
+      pageNum: this.pageNum,
+      pageSize: this.pageSize,
+      key: this.key,
+      maxAge: this.maxAge,
+      minAge: this.minAge,
+      sort: this.sort,
+      typeId: this.typeId
+    } as ESObject
+  }
 }

+ 24 - 2
features/feature/src/main/ets/model/Storage.ets

@@ -1,5 +1,5 @@
 import { bookListApi } from "../apis/BookListApi"
-import { BookListTypeItem } from "./BookModelIndex"
+import { BookListTypeItem, BookListTypeList } from "./BookModelIndex"
 
 // 搜索记录缓存
 @ObservedV2
@@ -9,7 +9,7 @@ export class HistoryStorage{
 
 // 书单分类
 @ObservedV2
-export class BookCategoriesStorage{
+export class BookListCategoriesStorage{
   @Trace bookList: BookListTypeItem[] = []
 
   constructor() {
@@ -29,3 +29,25 @@ export class BookCategoriesStorage{
   }
 }
 
+// 书籍分类
+@ObservedV2
+export class BookCategoryStorage{
+  @Trace list: BookListTypeList[] = []
+
+  constructor() {
+    if(this.list.length == 0){
+      this.init()
+    }
+  }
+
+  async init(){
+    let ans = await bookListApi.getAllThemes()
+    if(ans.length == 0) return
+
+    ans.sort((a, b) => a.sort! > b.sort! ? 1 : -1)
+    this.list = []
+    this.list.push({ bookListTypeName: "全部" }, ...ans)
+    console.log(`书籍分类 = ${JSON.stringify(this.list)}`)
+  }
+}
+

+ 2 - 1
features/feature/src/main/ets/pages/BookList/BookListDetailPage.ets

@@ -81,7 +81,8 @@ struct BookListDetailPage {
               ForEach(new Array(10).fill('0'), (item: string, index) => {
                 ListItem(){
                   Column(){
-                    bookItemComp('我不愿嫉妒', () => { this.vm.increaseIndex = index })
+                    // todo 完善书籍组件
+                    // bookItemComp('我不愿嫉妒', () => { this.vm.increaseIndex = index })
                   }.alignItems(HorizontalAlign.End).justifyContent(FlexAlign.End)
                 }
                 .margin({top: 8})

+ 2 - 2
features/feature/src/main/ets/pages/viewModel/BookListViewModel.ets

@@ -2,7 +2,7 @@ import { AppStorageV2 } from "@kit.ArkUI"
 import { bookListApi } from "../../apis/BookListApi"
 import { BookListItem } from "../../model/BookModelIndex"
 import { searchBookListQuery } from "../../model/Query"
-import { BookCategoriesStorage } from "../../model/Storage"
+import { BookListCategoriesStorage } from "../../model/Storage"
 
 @ObservedV2
 export class BookListViewModel{
@@ -15,7 +15,7 @@ export class BookListViewModel{
   @Trace sortType: number = 0
 
   // 分类列表
-  bookCategories: BookCategoriesStorage = AppStorageV2.connect(BookCategoriesStorage, () => new BookCategoriesStorage())!
+  bookCategories: BookListCategoriesStorage = AppStorageV2.connect(BookListCategoriesStorage, () => new BookListCategoriesStorage())!
   // 分类列表控制器
   categoryControl: Scroller = new Scroller()
   // 书单查询器

+ 19 - 12
features/feature/src/main/ets/view/SecondView.ets

@@ -2,6 +2,8 @@ import { DeerSearch } from '../components/DeerSearch'
 import { SecondViewModel } from './viewModel/SecondViewModel'
 import { CustomTextStyle } from '../style/CustomTextStyle'
 import { bookItemComp } from '../components/BuilderIndex'
+import { BookItem, BookListTypeList } from '../model/BookModelIndex'
+import { cert } from '@kit.DeviceCertificateKit'
 
 @ComponentV2
 export struct SecondView {
@@ -11,7 +13,7 @@ export struct SecondView {
     Column(){
       Row({space: 12}){
         Row({space: 6}){
-          Text('年龄选择')
+          Text(this.vm.ageRange || '年龄选择')
             .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
 
           Image($r('[basic].media.icon_expension'))
@@ -20,10 +22,12 @@ export struct SecondView {
             .rotate({ angle: this.vm.openAgeDialog ? 180 : 0 })
             .animation({duration: 200, curve: Curve.Smooth})
         }
+        .width(120)
         .borderRadius(18)
+        .padding({top: 8, bottom: 8})
         .backgroundColor('#FFFECF2F')
+        .justifyContent(FlexAlign.Center)
         .border({width: 2, color: '#FF000000'})
-        .padding({left: 15, top: 8, right: 15, bottom: 8})
         .bindMenu(this.ageSelect())
         .onClick(() => { if(!this.vm.openAgeDialog) this.vm.openAgeDialog = true })
 
@@ -42,10 +46,10 @@ export struct SecondView {
               Row(){
                 Row(){
                   List({space: 22, scroller: this.vm.categoryControl}){
-                    ForEach(this.vm.categoryList, (item: string, index) => {
+                    ForEach(this.vm.categoryList.list, (item: BookListTypeList, index) => {
                       ListItem(){
                         Column(){
-                          Text(item)
+                          Text(item.bookListTypeName)
                             .zIndex(99)
                             .onClick(() => { this.vm.changeCategory(index) })
                             .attributeModifier(new CustomTextStyle({size: 16, weight: 600, color: this.vm.categoryIndex == index ? '#FF111111' : '#FF777777'}))
@@ -87,8 +91,8 @@ export struct SecondView {
                       .borderRadius(15)
                       .padding({left: 12, top: 5, right: 12, bottom: 5})
                       .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
-                      .border({width: 2, color: this.vm.sortType == index ? '#FF000000' : Color.Transparent})
-                      .backgroundColor(this.vm.sortType == index ? '#FFFECF2F' : Color.Transparent)
+                      .border({width: 2, color: this.vm.query?.sort == index ? '#FF000000' : Color.Transparent})
+                      .backgroundColor(this.vm.query?.sort == index ? '#FFFECF2F' : Color.Transparent)
                       .onClick(() => { this.vm.changeSortType(index) })
                   })
                 }
@@ -125,8 +129,8 @@ export struct SecondView {
                 ListItem()
 
                 Repeat(this.vm.bookList)
-                  .each((item) => {
-                    bookItemComp(item.item, () => {})
+                  .each((item: RepeatItem<BookItem>) => {
+                    bookItemComp(item, () => {})
                   })
               }
               .width("100%")
@@ -177,9 +181,9 @@ export struct SecondView {
                 .justifyContent(FlexAlign.SpaceBetween)
 
                 Grid(){
-                  ForEach(this.vm.categoryList, (item: string, index: number) => {
+                  ForEach(this.vm.categoryList.list, (item: BookListTypeList, index: number) => {
                     GridItem(){
-                      Text(item)
+                      Text(item.bookListTypeName)
                         .width('100%')
                         .borderRadius(18)
                         .textAlign(TextAlign.Center)
@@ -197,7 +201,7 @@ export struct SecondView {
                 .rowsGap(14)
                 .columnsGap(23)
                 .margin({top: 13})
-                .maxCount(Math.abs(this.vm.categoryList.length/3))
+                .maxCount(Math.abs(this.vm.categoryList?.list?.length/3))
                 .columnsTemplate('repeat(3, 1fr)')
               }
               .width("100%")
@@ -232,9 +236,12 @@ export struct SecondView {
   @Builder
   ageSelect(){
     Column({space: 17}){
-      ForEach(['0-2岁', '3-6岁', '7-10岁', '10岁+'], (item: string, index) => {
+      ForEach(this.vm.ageList, (item: string, index: number) => {
         Text(item)
           .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
+          .onClick(() => {
+            this.vm.changeAgeRange(index)
+          })
       })
     }
     .margin(-4)

+ 69 - 9
features/feature/src/main/ets/view/viewModel/SecondViewModel.ets

@@ -1,18 +1,19 @@
 import { YTAvoid } from "basic"
+import { AppStorageV2 } from "@kit.ArkUI"
+import { BookCategoryStorage } from "../../model/Storage"
+import { searchBookQuery } from "../../model/Query"
+import { bookListApi } from "../../apis/BookListApi"
+import { PageResponse } from "../../model/PageResponse"
+import { BookItem } from "../../model/BookModelIndex"
 
 @ObservedV2
 export class SecondViewModel{
   @Trace safeTop: number = AppStorage.get(YTAvoid.SAFE_TOP_KEY) as number
 
-  // 分类列表
-  @Trace categoryList: string[] = ['全部', '精品主题', '名家大师', '国际获奖', '经典系列', '畅销榜P', '权威推荐', '月度推荐']
   // 书单列表
-  @Trace bookList: string[] = ['书单1', '书单2', '书单3', '书单4', '书单5', '书单6', '书单7', '书单8', '书单9', '书单10', '书单11', '书单12', '书单13', '书单14', '书单15', '书单16', '书单17']
-
+  @Trace bookList: BookItem[] = []
   // 分类索引
   @Trace categoryIndex: number = 0
-  // 排序方式 0 - 最新 1 - 最热
-  @Trace sortType: number = 0
   // 是否已读
   @Trace isRead: boolean = false
   // 显示模式 0 - 列表 1 - 封面
@@ -22,20 +23,48 @@ export class SecondViewModel{
   @Trace openAgeDialog: boolean = false
   // 选择类型弹窗是否已打开
   @Trace openTypeDialog: boolean = false
+  // 查询参数
+  @Trace query: searchBookQuery = new searchBookQuery()
+  // 年龄范围
+  @Trace ageRange: string = ''
 
+  // 列表控制器
   categoryControl: Scroller = new Scroller()
+  // 分类列表
+  categoryList: BookCategoryStorage = AppStorageV2.connect(BookCategoryStorage, () => new BookCategoryStorage())!
+
+  ageList: string[] = ['年龄选择', '0-2岁', '3-6岁', '7-10岁', '10岁+']
+
+
+  constructor() {
+    this.changeCategory(0)
+  }
 
   // 更改选中的分类
   changeCategory(index: number, toIndex: boolean = false) {
+    if(index == this.categoryIndex && index !=+ 0) return
+
     this.categoryIndex = index
     if (toIndex) {
       this.categoryControl.scrollToIndex(index)
     }
+
+    if(index == 0){
+      this.query.typeId = undefined
+    } else {
+      this.query.typeId = this.categoryList.list[index].id
+    }
+
+    this.getBookList()
   }
 
-  // 更改排序方式
+  // 更改排序方式 - 热度、最新
   changeSortType(index: number) {
-    this.sortType = index
+    if (this.query.sort == index)
+      return
+
+    this.query.sort = index
+    this.getBookList()
   }
 
   // 切换已读模式
@@ -43,13 +72,44 @@ export class SecondViewModel{
     this.isRead = !this.isRead
   }
 
-  // 改变显示模式
+  // 改变显示模式 封面和列表模式的切换
   changeShowMode() {
     this.showMode = this.showMode == 0 ? 1 : 0
   }
 
+  // 切换年龄范围
+  changeAgeRange(index: number) {
+    this.ageRange = this.ageList[index]
+
+    if(index == 0) {
+      this.query.minAge = undefined
+      this.query.maxAge = undefined
+    } else if(index == 1) {
+      this.query.minAge = 0
+      this.query.maxAge = 2
+    } else if(index == 2) {
+      this.query.minAge = 3
+      this.query.maxAge = 6
+    } else if(index == 3) {
+      this.query.minAge = 7
+      this.query.maxAge = 10
+    } else if(index == 4) {
+      this.query.minAge = 10
+      this.query.maxAge = undefined
+    }
+  }
+
   // 开启选择分类弹窗
   openCategoryDialog() {
+    if(this.categoryList.list.length == 0) return
+
     this.openTypeDialog = !this.openTypeDialog
   }
+
+  // 获取书籍列表
+  async getBookList() {
+    let ans: PageResponse<BookItem> = await bookListApi.searchBooks(this.query.clone())
+    this.bookList = ans.list ?? []
+    console.log(`获取书籍列表 = ${JSON.stringify(this.bookList)}`)
+  }
 }