PageComponent.ets 14 KB
import { BottomNavi, CommonConstants, CompStyle, ViewType } from 'wdConstant';
import { EmitterEventId, EmitterUtils, Logger, NetworkUtil } from 'wdKit';
import { EmptyComponent, WDViewDefaultType } from '../view/EmptyComponent';
import PageModel from '../../viewmodel/PageModel';
import { autoRefresh, onActionEnd, onActionStart, onActionUpdate } from '../../utils/PullDownRefresh';
import LoadMoreLayout from './LoadMoreLayout';
import { CompParser } from '../CompParser';
import { CompDTO, PageTrackBean } from 'wdBean';
import PageHelper from '../../viewmodel/PageHelper';
import { channelSkeleton } from '../skeleton/channelSkeleton'
import { ProcessUtils } from 'wdRouter/Index';
import PageAdModel from '../../viewmodel/PageAdvModel';
import PageNoMoreLayout from './PageNoMoreLayout';
import { NoMoreBean } from './NoMoreBean';
import { RefreshLayoutBean } from '../refresh/RefreshLayoutBean';
import RefreshLayout from '../refresh/RefreshLayout';
import { GrayManageModel } from '../../viewmodel/GrayManageModel';
import { onlyWifiLoadImg } from '../../utils/lazyloadImg';

const TAG = 'PageComponent';

@Component
export struct PageComponent {
  @State private pageModel: PageModel = new PageModel();
  @State private pageAdvModel: PageAdModel = new PageAdModel();
  @State timer: number = -1
  navIndex: number = 0;
  pageId: string = "";
  channelId: string = "";
  isMourning: boolean = false // 是否国殇
  @Link @Watch('onChange') currentTopNavSelectedIndex: number
  // 自动刷新通知
  @Prop @Watch('onAutoRefresh') autoRefresh: number = 0
  private listScroller: Scroller = new Scroller();
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Up | PanDirection.Down })
  needload: boolean = true;
  // page相关埋点数据,各组件需要,自行取用
  // @Provide  暂不能用Provide、Consume,(别的用到组件样式的页面,都需要加provide,否则会crash,暂不用这种方案。待优化)
  /**
   * @deprecated
   */
  private pageTrackBean: PageTrackBean = new PageTrackBean()
  // 国殇灰度管理
  GrayManage: SubscribedAbstractProperty<GrayManageModel> =  AppStorage.link<GrayManageModel>('GrayManage')
  @State netStatus: number | undefined = undefined // 存储网络状态
  bottomNavi:BottomNavi = BottomNavi.NEWS
  @Prop scrollBgHeight:number = 0
  onHideBgImage?: (isShow:boolean) => void;

  build() {
    Column() {
      if (this.pageModel.viewType == ViewType.LOADING) {
        this.LoadingLayout()
      } else if (this.pageModel.viewType == ViewType.LOADED) {
        this.ListLayout()
      } else if (this.pageModel.viewType == ViewType.EMPTY || this.pageModel.viewType == ViewType.NoNetwork) {
        //缺省页
        EmptyComponent({
          emptyType: this.pageModel.viewType == ViewType.EMPTY ? this.pageModel.emptyType : this.pageModel.NoNetwork,
          emptyButton: true,
          retry: () => {
            this.pageModel.viewType = ViewType.LOADING;
            this.getData()
            // this.pageModel.pageId = this.pageId;
            // this.pageModel.groupId = this.pageId;
            // this.pageModel.channelId = this.channelId;
            // this.pageModel.currentPage = 1;
            // this.pageModel.pageTotalCompSize = 0;
            // this.listScroller.scrollToIndex(0)
            // autoRefresh(this.pageModel, this.pageAdvModel)
          }
        })
          .backgroundColor(Color.White)
          .margin({
            left: 6,
            right: 6
          })
          .borderRadius(4)
          .grayscale(this.isMourning ? 1 : 0)
      }
    }
    .width(CommonConstants.FULL_PARENT)
    .height(CommonConstants.FULL_PARENT)
    // .onTouch((event: TouchEvent | undefined) => {
    //   if (event) {
    //     if (this.pageModel.viewType === ViewType.LOADED) {
    //       listTouchEvent(this.pageModel, this.pageAdvModel, event);
    //     }
    //   }
    // })
    // 对接新的下拉刷新手势,替换touch事件
    .parallelGesture(
      PanGesture(this.panOption)
        .onActionStart((event?: GestureEvent) => {
          onActionStart(this.pageModel, this.pageAdvModel, event)
        })
        .onActionUpdate((event?: GestureEvent) => {
          onActionUpdate(this.pageModel, this.pageAdvModel, event)
        })
        .onActionEnd(() => {
          onActionEnd(this.pageModel, this.pageAdvModel)
        })
    )

  }

  @Builder
  ListLayout() {

    RelativeContainer() {
      List({ scroller: this.listScroller }) {
        // 下拉刷新
        ListItem() {
          RefreshLayout({
            refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.load,
              this.pageModel.offsetY)
          })
        }
        .grayscale(this.isMourning ? 1 : 0)

        LazyForEach(this.pageModel.compList, (compDTO: CompDTO, compIndex: number) => {
          ListItem() {
            Column() {
              CompParser(
                {
                  pageModel: this.pageModel,
                  nextCompDTO: compIndex === this.pageModel.compList.getDataArray().length - 1 ? new CompDTO() : this.pageModel.compList.get(compIndex + 1) as CompDTO,
                  compDTO: compDTO,
                  compIndex: compIndex,
                  pageId: this.pageId,
                  bottomNavi:this.bottomNavi
                }
              )
            }
          }.margin({
            left: compDTO.compStyle === CompStyle.Zh_Single_Row_04 ? 0 : 6,
            right: (compDTO.compStyle === CompStyle.Zh_Single_Row_05 || compDTO.compStyle === CompStyle.Zh_Single_Row_02 ||
              compDTO.compStyle === CompStyle.Zh_Single_Row_04) ? 0 : 6
          })
          .grayscale(this.isMourning && compIndex < 8 ? 1 : 0)
          .borderRadius({
            topLeft:compIndex === 0 ? $r('app.float.image_border_radius'):0,
            topRight:compIndex === 0 ? $r('app.float.image_border_radius'):0
          })
        },
          (compDTO: CompDTO, compIndex: number) => JSON.stringify(compDTO))

        // 加载更多
        ListItem() {
          if (this.pageModel.hasMore) {
            LoadMoreLayout({ isVisible: this.pageModel.isVisiblePullUpLoad })
          } else {
            PageNoMoreLayout({ noMoreBean: new NoMoreBean(this.pageModel.pageInfo.baselineCopywriting) })
          }
        }
        .grayscale(this.isMourning ? 1 : 0)
      }
      .edgeEffect(EdgeEffect.None)
      .scrollBar(BarState.Off)
      .cachedCount(5)
      .height(CommonConstants.FULL_PARENT)
      .onScrollIndex((start: number, end: number) => {
        // Listen to the first index of the current list.
        this.pageModel.startIndex = start;
        // 包含了 头尾item,判断时需要考虑+2
        this.pageModel.endIndex = end;
      })
      .id('page_list')
      .onDidScroll(() => {
        if(this.scrollBgHeight === 0){
          return
        }
        let y  = this.listScroller.currentOffset().yOffset

        if (this.onHideBgImage !== undefined ) {
          if( y - this.scrollBgHeight > 0){
            this.onHideBgImage(true)
          }else{
            this.onHideBgImage(false)
          }
        }
      })

      // 挂角广告
      this.pageHornAd()

    }.layoutWeight(1)
  }

  @Builder
  LoadingLayout() {
    channelSkeleton()
      .margin({
        left: 6,
        right: 6
      })
      .borderRadius(4)
      .backgroundColor(Color.White)
      .grayscale(this.isMourning ? 1 : 0)
    // CustomRefreshLoadLayout({
    //   refreshBean: new RefreshLayoutBean(true,
    //     $r('app.media.ic_pull_up_load'), $r('app.string.pull_up_load_text'), this.pageModel.pullDownRefreshHeight)
    // })
  }

  /**
   *  页面挂角广告
   */
  @Builder
  pageHornAd() {

    if (this.pageAdvModel.isShowAds) {
      if (this.pageAdvModel.pageCornerAdv.matInfo != null && this.pageAdvModel.pageCornerAdv.matInfo.linkType != '2') {
        // 广告中心的挂角广告
        this.drawPageCornerAdvView(1, 1 == this.pageAdvModel.isRightAdv)
      } else if (this.pageAdvModel.pageCornerContentInfo.advert != null && this.pageAdvModel.pageCornerContentInfo.advert.objectType != '6') {
        // 展现中心的挂角广告业务
        this.drawPageCornerAdvView(2, 1 == this.pageAdvModel.isRightAdv)
      }
    }

  }

  /**
   * 绘制页面挂角
   *
   * @param type  1:广告中心的挂角广告;2:展现中心的挂角广告
   * @param isRightCorne   true:右挂角;false:左挂角
   */
  @Builder
  drawPageCornerAdvView(type: number, isRightCorne: boolean) {
    // 页面左挂角
    Image(type === 1 ? this.pageAdvModel.pageCornerAdv.matInfo.matImageUrl[0]
      : this.pageAdvModel.pageCornerContentInfo.advert.displayUrl)
      .width($r('app.float.vp_80'))
      .height($r('app.float.vp_80'))
      .id("left_iv")
      .alignRules({
        bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
        left: { anchor: isRightCorne ? "" : '__container__', align: HorizontalAlign.Start },
        right: { anchor: isRightCorne ? '__container__' : "", align: HorizontalAlign.End },
      })
      .margin({
        bottom: "65vp",
        left: isRightCorne ? 0 : $r('app.float.card_comp_pagePadding_lf'),
        right: isRightCorne ? $r('app.float.card_comp_pagePadding_lf') : 0,

      })
      .onClick(() => {
        if (type === 1) {
          // 广告业务跳转
          ProcessUtils.openAdvDetail(this.pageAdvModel.pageCornerAdv.matInfo);
        } else {
          // 展现中心的业务跳转
          ProcessUtils.advJumpMainPage(this.pageAdvModel.pageCornerContentInfo.advert)
        }
      })
      .grayscale(this.GrayManage.get().isMourning() ? 1 : 0)
    // 关闭按钮
    Image($r('app.media.icon_adv_horn_close'))
      .id('left_close')
      .width($r('app.float.vp_16'))
      .alignRules({
        top: { anchor: 'left_iv', align: VerticalAlign.Top },
        left: { anchor: isRightCorne ? '' : 'left_iv', align: HorizontalAlign.Start },
        right: { anchor: isRightCorne ? 'left_iv' : '', align: HorizontalAlign.End },
      })
      .offset({
        x: isRightCorne ? 10 : -10,
        y: isRightCorne ? -10 : -10
      })
      .onClick(() => {
        // 关闭挂角广告
        this.pageAdvModel.isShowAds = false;

      })
      .grayscale(this.GrayManage.get().isMourning() ? 1 : 0)

    if (type == 1) {
      Text($r('app.string.comp_advertisement'))
        .width($r('app.float.vp_28'))
        .height($r('app.float.vp_16'))
        .fontSize($r('app.float.font_size_10'))
        .fontColor(Color.White)
        .id('left_tag')
        .alignRules({
          bottom: { anchor: 'left_iv', align: VerticalAlign.Bottom },
          left: { anchor: isRightCorne ? '' : 'left_iv', align: HorizontalAlign.Start },
          right: { anchor: isRightCorne ? 'left_iv' : '', align: HorizontalAlign.End },
        })
        .textAlign(TextAlign.Center)
        .backgroundColor($r('app.color.res_color_general_000000_30'))
        .borderRadius({
          topLeft: $r('app.float.vp_2'),
          topRight: $r('app.float.vp_2'),
          bottomLeft: $r('app.float.vp_2'),
          bottomRight: $r('app.float.vp_2')
        })
        .grayscale(this.GrayManage.get().isMourning() ? 1 : 0)
    }

  }

  aboutToAppear() {
    // 选中tab,才请求数据。拦截大量接口请求
    if (this.navIndex === this.currentTopNavSelectedIndex) {
      this.getData();
      this.needload = false;
      // console.log(TAG, 'aboutToAppear onAutoRefresh111 ' + this.needload)
    }

    //人民号推荐 监听登录事件(刷新页面)
    EmitterUtils.receiveEvent(EmitterEventId.LOGIN_SUCCESS, () => {
      if(this.navIndex === this.currentTopNavSelectedIndex && this.bottomNavi == BottomNavi.PEOPLE){
        this.listScroller.scrollEdge(Edge.Top)
        this.pageModel.viewType = ViewType.LOADING;
        this.getData()
      }
    })

  }

  onChange() {
    // console.log(TAG, `onChangezz id: ${this.pageId} , ${this.channelId} , ${this.navIndex} , navIndex: ${this.currentTopNavSelectedIndex}`);
    // 注册监听网络连接
    if(this.bottomNavi == BottomNavi.VIDEO){
      this.netStatus = undefined
      let netStatus = NetworkUtil.isNetConnected()
      if (netStatus) {
        if (this.navIndex === this.currentTopNavSelectedIndex) {
          // console.log(TAG, 'page onAutoRefresh111 ' + this.needload)
          if (this.needload) {
            this.getData();
          }
          this.needload = false;
        }
      } else {
        this.pageModel.viewType = ViewType.NoNetwork;
      }
    }else{
      if (this.navIndex === this.currentTopNavSelectedIndex) {
        // console.log(TAG, 'page onAutoRefresh111 ' + this.needload)
        if (this.needload) {
          this.getData();
        }else{
          let netStatus = NetworkUtil.isNetConnected()
          if(this.pageModel.emptyType === WDViewDefaultType.WDViewDefaultType_NoNetwork && netStatus ){
            this.onAutoRefresh()
          }
        }
        this.needload = false;
      }
    }

  }

  async onAutoRefresh() {
    if (this.navIndex != this.currentTopNavSelectedIndex) {
      return
    }
    // 当前页面,自动刷新数据
    Logger.debug(TAG, 'page onAutoRefresh ' + this.autoRefresh)
    this.listScroller.scrollToIndex(0)
    autoRefresh(this.pageModel, this.pageAdvModel)
  }

  getData() {
    if (this.timer) {
      clearTimeout(this.timer)
    }
    this.timer = setTimeout(async () => {
      Logger.info(TAG, `getData id: ${this.pageId} , ${this.channelId} , navIndex: ${this.currentTopNavSelectedIndex}`);
      this.pageModel.pageId = this.pageId;
      this.pageModel.groupId = this.pageId;
      this.pageModel.channelId = this.channelId;
      this.pageModel.currentPage = 1;
      this.pageModel.pageTotalCompSize = 0;
      this.pageModel.loadImg = await onlyWifiLoadImg()
      PageHelper.getInitCacheData(this.pageModel, this.pageAdvModel).then(() => {
        this.pageTrackBean.pageId = this.pageId
        this.pageTrackBean.pageName = this.pageModel.pageInfo.name
      })
      PageHelper.getInitData(this.pageModel, this.pageAdvModel).then(() => {
        this.pageTrackBean.pageId = this.pageId
        this.pageTrackBean.pageName = this.pageModel.pageInfo.name
      })
    }, 100)
  }
}