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 { common } from '@kit.AbilityKit';
import { router } from '@kit.ArkUI';
import { ArticleCardView, FeedCardView, UserModel } from '@ohos/mine';
import { LoadingFailedView, LoadingView, NoneContentView } from '@ohos/uicomponents';
import {
  BreakpointType,
  BreakpointTypeEnum,
  CommonConstants,
  EventTypeEnum,
  LazyDataSource,
  LearningResource,
  LoadingStatus,
  Logger,
  ObservedArray,
  ResourcesType
} from '@ohos/utils';
import { DiscoverModel } from '../model/DiscoverModel';
import { SearchBar } from '../components/SearchBar';

const TAG = '[SearchResultView]';
const context = (getContext(this) as common.UIAbilityContext);

@Entry({ routeName: 'SearchResultView' })
@Component
export struct SearchResultView {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD;
  @State searchValue: string = '';
  @State userModel: UserModel = UserModel.getInstance();
  @State discoverModel: DiscoverModel = DiscoverModel.getInstance();
  @State @Watch('userOperationChanged') collectedIds: ObservedArray<string> = this.userModel.collectedIds;
  @State @Watch('userOperationChanged') likedIds: ObservedArray<string> = this.userModel.likedIds;
  @State isFocus: boolean = false;
  @State @Watch('userOperationChanged') searchList: LazyDataSource<LearningResource> =
    this.discoverModel.techArticleDataSource;

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

  aboutToAppear() {
    this.dynamicLoading();
  }

  // After a user likes and collects favorites, the article list data needs to be updated.
  userOperationChanged() {
    this.searchList.dataArray.forEach((item: LearningResource) => {
      item.isCollected = this.collectedIds.some((id: string) => id === item.id);
      item.isLiked = this.likedIds.some((id: string) => id === item.id);
    });
  }

  handleSearch(item: string): void {
    this.searchValue = item;
    this.discoverModel.search(item);
  }

  jumpDetail(item: LearningResource): void {
    router.pushNamedRoute({
      name: 'DiscoverArticleDetailView',
      params:
      new Object({
        articleDetail: item,
        onDestinationBack: () => {
          router.back();
          return false;
        }
      })
    });
  }

  @Builder
  ResultList() {
    List({ space: CommonConstants.SPACE_12 }) {
      LazyForEach(this.searchList, (content: LearningResource) => {
        ListItem() {
          if (content.type === ResourcesType.ARTICLE) {
            ArticleCardView({
              articleItem: content,
              onCollected: (articleItem: LearningResource) => {
                context.eventHub.emit(EventTypeEnum.COLLECTED, {
                  resourceId: articleItem.id,
                  resourceType: articleItem.type,
                  actionValue: !articleItem.isCollected
                })
              },
              onLiked: (articleItem: LearningResource) => {
                context.eventHub.emit(EventTypeEnum.LIKED, {
                  resourceId: articleItem.id,
                  resourceType: articleItem.type,
                  actionValue: !articleItem.isLiked
                })
              },
            })
              .reuseId('article')
          } else {
            FeedCardView({
              articleItem: content
            })
              .reuseId('feed')
          }
        }
        .borderRadius($r('app.float.xxl_border_radius'))
        .margin({ right: this.currentBreakpoint === BreakpointTypeEnum.SM ? 0 : $r('app.float.md_padding_margin') })
        .onClick(() => this.jumpDetail(content))
      }, (item: LearningResource) => item.id)
    }
    .cachedCount(3)
    .padding({
      left: $r('app.float.lg_padding_margin'),
      right: $r('app.float.lg_padding_margin'),
    })
    .margin({
      bottom: $r('app.float.lg_padding_margin')
    })
    .lanes(new BreakpointType({
      sm: CommonConstants.SM_COLUMN_COUNT,
      md: CommonConstants.MD_COLUMN_COUNT,
      lg: CommonConstants.LG_COLUMN_COUNT
    }).getValue(this.currentBreakpoint))
    .width(CommonConstants.FULL_PERCENT)
    .layoutWeight(1)
    .scrollBar(BarState.Off)
  }

  build() {
    NavDestination() {
      Column() {
        SearchBar({
          enableKeyboardOnFocus: false,
          searchValue: this.searchValue,
          onSearch: (value) => this.handleSearch(value),
          onBack: () => {
            router.replaceNamedRoute({ name: 'SearchView' });
          }
        })
          .padding({
            left: $r('app.float.lg_padding_margin'),
            right: $r('app.float.lg_padding_margin')
          })

        if (this.discoverModel.searchLoadingStatus === LoadingStatus.LOADING) {
          LoadingView()
        } else if (this.discoverModel.searchLoadingStatus === LoadingStatus.FAILED) {
          LoadingFailedView(() => this.handleSearch(this.searchValue))
        } else if (this.discoverModel.searchLoadingStatus === LoadingStatus.SUCCESS
          && this.discoverModel.searchResultDataSource.totalCount() === 0) {
          NoneContentView($r('app.media.ic_search_empty'), $r('app.string.no_search_result'))
        } else {
          this.ResultList()
        }
      }
      .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
      .padding({
        top: AppStorage.get<number>('statusBarHeight'),
      })
      .width(CommonConstants.FULL_PERCENT)
      .height(CommonConstants.FULL_PERCENT)
    }
    .hideTitleBar(true)
    .onReady((cxt: NavDestinationContext) => {
      let params = router.getParams() as Record<string, string>;
      this.searchValue = params.searchValue as string;
    })
    .onBackPressed(() => {
      router.replaceNamedRoute({ name: 'SearchView' });
      return true;
    })
  }
}