c77fb700创建于 2025年1月16日历史提交
/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { promptAction, router } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { BreakpointType, BreakpointTypeEnum, CommonConstants, LearningResource, Logger } from '@ohos/utils';
import { DiscoverModel, HotListItem } from '../model/DiscoverModel';
import { RECOMMEND_THEME, SearchBar } from '../components/SearchBar';
import { SearchHistory } from '../components/SearchHistory';

const TAG = '[SearchPage]';
const DISCOVER_ITEM_LINE_HEIGHT = 20;
const MAIN_PAGE_INDEX = 1;

@Entry({ routeName: 'SearchView' })
@Component
export struct SearchView {
  @StorageProp('currentBreakpoint') currentBreakpoint: BreakpointTypeEnum = BreakpointTypeEnum.MD;
  @State discoverModel: DiscoverModel = DiscoverModel.getInstance();
  @State searchValue: string = '';

  dynamicLoading(): void {
    try {
      import('./SearchResultView');
      import('@ohos/mine/src/main/ets/views/DiscoverArticleDetailView');
    } catch (err) {
      Logger.error(TAG, 'dynamicLoading error:' + err);
    }
  }

  aboutToAppear(): void {
    this.dynamicLoading();
    this.discoverModel.getSearchHistory();
  }

  handleSearch(item: string): void {
    this.searchValue = item;
    this.discoverModel.search(this.searchValue);
    router.pushNamedRoute({
      name: 'SearchResultView',
      params: new Object({ searchValue: item })
    })
  }

  jumpToDetail(item: HotListItem): void {
    router.pushNamedRoute({
      name: 'DiscoverArticleDetailView',
      params: new Object({
        articleDetail: item
      })
    });
  }

  // Confirm dialog
  confirmDeleteHistory(): void {
    promptAction.showDialog({
      message: $r('app.string.confirm_delete_search_history'),
      buttons: [
        {
          text: $r('app.string.cancel'),
          color: $r('sys.color.ohos_id_color_text_secondary')
        },
        {
          text: $r('app.string.sure'),
          color: $r('sys.color.ohos_id_color_text_secondary')
        }
      ],
      isModal: true,
      alignment: DialogAlignment.Center
    }, (err: BusinessError, data: promptAction.ShowDialogSuccessResponse) => {
      if (err) {
        Logger.info(TAG, `Show Dialog failed.Cause: ${err.message}.`);
        return;
      }
      if (data.index === 1) {
        this.discoverModel.clearSearchHistory();
        Logger.info(TAG, 'Delete search history success.')
      }
    });
  }

  build() {
    NavDestination() {
      Column() {
        // Search area
        SearchBar({
          enableKeyboardOnFocus: true,
          searchValue: this.searchValue,
          onSearch: (value) => this.handleSearch(value),
          onBack: () => {
            router.back(MAIN_PAGE_INDEX);
            return false;
          }
        })
          .margin({
            left: new BreakpointType<Length>({
              sm: $r('app.float.lg_padding_margin'),
              md: $r('app.float.xxl_padding_margin'),
              lg: $r('app.float.xxxl_padding_margin'),
            }).getValue(this.currentBreakpoint),
            right: new BreakpointType<Length>({
              sm: $r('app.float.lg_padding_margin'),
              md: $r('app.float.xxl_padding_margin'),
              lg: $r('app.float.xxxl_padding_margin'),
            }).getValue(this.currentBreakpoint)
          })

        List({ space: CommonConstants.SPACE_4 }) {
          if (this.discoverModel.searchHistory.length > 0) {
            ListItem() {
              SearchHistory({
                data: this.discoverModel.searchHistory,
                title: $r('app.string.search_history'),
                onClickIcon: () => this.confirmDeleteHistory(),
                onClickText: (item: string) => this.handleSearch(item)
              })
            }
            .padding({
              left: new BreakpointType<Length>({
                sm: $r('app.float.lg_padding_margin'),
                md: $r('app.float.xxl_padding_margin'),
                lg: $r('app.float.xxxl_padding_margin'),
              }).getValue(this.currentBreakpoint),
              right: new BreakpointType<Length>({
                sm: $r('app.float.lg_padding_margin'),
                md: $r('app.float.xxl_padding_margin'),
                lg: $r('app.float.xxxl_padding_margin'),
              }).getValue(this.currentBreakpoint)
            })
          }

          ListItem() {
            searchDiscover(this.currentBreakpoint, (text) => this.handleSearch(text))
          }
          .padding({
            left: new BreakpointType<Length>({
              sm: $r('app.float.lg_padding_margin'),
              md: $r('app.float.xxl_padding_margin'),
              lg: $r('app.float.xxxl_padding_margin'),
            }).getValue(this.currentBreakpoint),
            right: new BreakpointType<Length>({
              sm: $r('app.float.lg_padding_margin'),
              md: $r('app.float.xxl_padding_margin'),
              lg: $r('app.float.xxxl_padding_margin'),
            }).getValue(this.currentBreakpoint)
          })

          ListItem() {
            if (this.discoverModel.hotList.length > 0) {
              Column() {
                hotCard(this.discoverModel.hotList, this.currentBreakpoint, (item) => this.jumpToDetail(item))
              }
              .padding($r('app.float.lg_padding_margin'))
              .borderRadius($r('app.float.lg_border_radius'))
              .margin({
                left: new BreakpointType<Length>({
                  sm: $r('app.float.lg_padding_margin'),
                  md: $r('app.float.xxl_padding_margin'),
                  lg: $r('app.float.xxxl_padding_margin'),
                }).getValue(this.currentBreakpoint),
                right: new BreakpointType<Length>({
                  sm: $r('app.float.lg_padding_margin'),
                  md: $r('app.float.xxl_padding_margin'),
                  lg: $r('app.float.xxxl_padding_margin'),
                }).getValue(this.currentBreakpoint)
              })
              .backgroundColor($r('app.color.article_background_color'))
            }
          }
        }
        .width(CommonConstants.FULL_PERCENT)
        .layoutWeight(1)
        .scrollBar(BarState.Off)
        .margin({ bottom: $r('app.float.lg_padding_margin') })
      }
      .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
      .padding({ top: AppStorage.get<number>('statusBarHeight') })
      .height(CommonConstants.FULL_PERCENT)
      .width(CommonConstants.FULL_PERCENT)
    }
    .hideTitleBar(true)
    .onBackPressed(() => {
      return true;
    })
  }
}

// Search discover
@Builder
function searchDiscover(currentBreakpoint: BreakpointTypeEnum, onClickText: (text: string) => void) {
  Column() {
    Row() {
      Text($r('app.string.search_discovery'))
        .fontSize($r('app.float.default_font_size'))
        .fontWeight(FontWeight.Bold)
        .fontColor($r('sys.color.ohos_id_color_text_secondary'))
    }
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Start)
    .height($r('app.float.search_group_height'))
    .width(CommonConstants.FULL_PERCENT)

    List() {
      ForEach(RECOMMEND_THEME, (item: string) => {
        ListItem() {
          Text(item)
            .fontSize($r('app.float.md_font_size'))
            .fontColor($r('sys.color.ohos_id_color_text_secondary'))
            .lineHeight(DISCOVER_ITEM_LINE_HEIGHT)
        }
        .margin({
          bottom: $r('app.float.md_padding_margin')
        })
        .onClick(() => onClickText(item))
      })
    }
    .lanes(new BreakpointType({
      sm: CommonConstants.MD_COLUMN_COUNT,
      md: CommonConstants.MD_COLUMN_COUNT,
      lg: CommonConstants.LG_COLUMN_COUNT
    }).getValue(currentBreakpoint))
    .scrollBar(BarState.Off)
  }
  .width(CommonConstants.FULL_PERCENT)
}

// Hot card
@Builder
function hotCard(list: HotListItem[], currentBreakpoint: BreakpointTypeEnum, jump: (item: HotListItem) => void) {
  Text($r('app.string.hmos_world_hot_list'))
    .fontSize($r('app.float.xl_font_size'))
    .fontWeight(FontWeight.Medium)
    .lineHeight($r('app.float.xl_line_height'))
    .fontColor($r('sys.color.ohos_id_color_text_primary'))
    .width(CommonConstants.FULL_PERCENT)
    .margin({ bottom: $r('app.float.sm_padding_margin') })

  List({ space: currentBreakpoint === BreakpointTypeEnum.SM ? 0 : CommonConstants.SPACE_4 }) {
    ForEach(list.slice(0, new BreakpointType({
      sm: 6,
      md: 8,
      lg: 9
    }).getValue(currentBreakpoint)), (item: HotListItem) => {
      ListItem() {
        Row() {
          Text(item.rank.toString())
            .width($r('app.float.lg_font_size'))
            .fontSize($r('app.float.large_text_size'))
            .fontWeight(item.rank < 4 ? FontWeight.Bold : FontWeight.Normal)
            .fontColor(item.rank < 4 ? $r('sys.color.ohos_id_color_text_primary_activated') :
            $r('sys.color.ohos_id_color_tertiary'))
          Image(item.headerImageUrl)
            .margin({ left: $r('app.float.xs_padding_margin') })
            .borderRadius($r('app.float.xxs_border_radius'))
            .height($r('app.float.view_count_icon_width'))
            .width($r('app.float.article_hots_height'))
          Column() {
            Text(item.title)
              .maxLines(1)
              .fontSize($r('app.float.md_font_size'))
              .lineHeight($r('app.float.md_line_height'))
              .fontWeight(FontWeight.Normal)
              .fontColor($r('sys.color.ohos_id_color_text_primary'))
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .width('100%')
            Text(item.title)
              .margin({ top: $r('app.float.xxs_padding_margin') })
              .maxLines(1)
              .fontSize($r('app.float.sm_font_size'))
              .lineHeight($r('app.float.sm_line_height'))
              .fontWeight(FontWeight.Normal)
              .fontColor($r('sys.color.ohos_id_color_tertiary'))
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .width('100%')
          }
          .layoutWeight(1)
          .padding({
            left: $r('app.float.md_padding_margin'),
            right: currentBreakpoint === BreakpointTypeEnum.SM ? $r('app.float.lg_padding_margin') :
            $r('app.float.xxl_padding_margin')
          })
        }
        .onClick(() => jump(item))
        .height($r('app.float.hot_card_item_height'))
      }
      .padding({ right: $r('app.float.lg_padding_margin') })
    }, (item: LearningResource) => item.id)
  }
  .scrollBar(BarState.Off)
  .lanes(new BreakpointType({
    sm: CommonConstants.SM_COLUMN_COUNT,
    md: CommonConstants.MD_COLUMN_COUNT,
    lg: CommonConstants.LG_COLUMN_COUNT
  }).getValue(currentBreakpoint))
}