Przeglądaj źródła

健康宣教和通知管理

张田田 3 miesięcy temu
rodzic
commit
83c4d132c2

+ 1 - 1
miniprogram/module/article/components/science-card/science-card.wxml

@@ -3,7 +3,7 @@
   <view class="border-gradient" wx:if="{{index}}">
     <!--边框-->
   </view>
-  <!--<image class="cover" src="{{item.briefImg}}" mode="aspectFill" fade-in /> -->
+  <image class="cover" src="{{item.briefImg}}" mode="aspectFill" fade-in />
   <view class="content">
     <text class="title" max-lines="3" overflow="ellipsis">{{item.title}}</text>
      <text class="description-2" max-lines="1" overflow="ellipsis" wx:if="{{item.pushTime}}">发布时间:{{item.pushTime}}</text>

+ 14 - 4
miniprogram/module/article/components/waterfall-card/waterfall-card.scss

@@ -7,14 +7,24 @@
   overflow: hidden;
   margin-bottom: 0;
   box-sizing: border-box;
-  width: 100%;
+  width: 98%;
+
+  .cover-wrapper {
+    width: 100%;
+    min-height: 120px;
+    max-height: 260px;
+    overflow: hidden;
+    border-radius: 12px 12px 0 0;
+    position: relative;
+  }
 
   .cover {
     width: 100%;
     height: auto;
+    min-height: 120px;
+    max-height: 260px;
     display: block;
-    border-radius: 12px 12px 0 0;
-    /* 图片等宽,高度自适应,实现不等高效果 */
+    /* 图片等宽,高度自适应,最小高度120px,最大高度260px,保持原始宽高比,实现不等高效果 */
   }
 
   .content {
@@ -26,7 +36,7 @@
   }
 
   .title {
-    font-size: 16px;
+    font-size: 15px;
     color: #191919;
     line-height: 1.5;
     margin-bottom: 5px;

+ 3 - 1
miniprogram/module/article/components/waterfall-card/waterfall-card.wxml

@@ -1,6 +1,8 @@
 <!--module/article/components/waterfall-card/waterfall-card.wxml-->
 <view class="waterfall-card-item" id="{{item.id}}" bind:tap="toInfoPage">
-  <image class="cover" src="{{item.briefImg}}" mode="widthFix" fade-in lazy-load />
+  <view class="cover-wrapper">
+    <image class="cover" src="{{item.briefImg}}" mode="widthFix" fade-in lazy-load />
+  </view>
   <view class="content">
     <text class="title">{{item.title}}</text>
     <view class="meta-info">

+ 1 - 1
miniprogram/module/article/pages/science-list/science-list.ts

@@ -25,7 +25,7 @@ Component({
       cursorColor: '#929292',
       iconColor: '#929292',
       focus: false,
-      placeholder: '输入搜索名称',
+      placeholder: '搜索名称',
     },
     title: '',
     dataset: [] as AnyObject[],

+ 27 - 8
miniprogram/pages/home/home.scss

@@ -329,7 +329,7 @@ $scale: 0.5;
 }
 
 .science-list-wrapper {
-  padding: 0 20px;
+  padding: 0 10px;
 
   .list-title {
     display: flex;
@@ -360,15 +360,34 @@ $scale: 0.5;
 
   .waterfall-container {
     display: flex;
-    flex-wrap: wrap;
-    // gap: 12px;
+    gap: 3px;
     margin-top: 12px;
-    justify-content: space-between;
 
-    waterfall-card {
-      width: calc(50% - 3px);
-      box-sizing: border-box;
-      margin-bottom: 12px;
+    .waterfall-column {
+      flex: 1;
+      display: flex;
+      flex-direction: column;
+
+      waterfall-card {
+        width: 100%;
+        box-sizing: border-box;
+        margin-bottom: 10px;
+      }
+    }
+  }
+
+  .loading-more {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 20px 0;
+    margin-top: 12px;
+
+    .loading-text {
+      font-size: 14px;
+      color: #8C8C8C;
+      margin-top: 8px;
     }
   }
 }

+ 182 - 29
miniprogram/pages/home/home.ts

@@ -66,6 +66,14 @@ Page({
     sheet: false,
 
     scienceList: [] as AnyArray,
+    leftColumnList: [] as AnyArray,
+    rightColumnList: [] as AnyArray,
+    scienceListPage: 1,
+    scienceListSize: 10,
+    scienceListTotal: 0,
+    scienceListLoading: false,
+    scienceListHasMore: true,
+    refreshing: false,
 
     _loaded: false,
 
@@ -398,23 +406,18 @@ Page({
           showCancel: false,
           confirmText: `重新加载`,
         })
-        .catch(() => { });
+        .catch(() => {});
       await this.load(true);
       return;
     }
 
     if (!this.data._loaded) {
       this.loadScienceList();
-      // useLocation()
-      //   .then((location) => {
-      //     this.setData({ location });
-      //   })
-      //   .catch(() => {});
       getSolarTerms()
         .then((solarTerms) => {
           this.setData({ solarTerms });
         })
-        .catch(() => { });
+        .catch(() => {});
       this.setData({ _loaded: true });
     }
   },
@@ -473,12 +476,6 @@ Page({
       this.setData({
         statusList: arr2,
       });
-
-      // if (!data?.healthAnalysisReportId) {
-      //   this.setData({
-      //     isShowComplete: true,
-      //   });
-      // }
     } catch (error: any) {
       wx.showToast({
         title: error.errMsg || "加载失败",
@@ -597,15 +594,17 @@ Page({
     (<any>this).applyAnimatedStyle(".fab-2", () => {
       "worklet";
       return {
-        transform: `translateX(${-offset.value}px) translateY(${-offset.value / 2
-          }px)`,
+        transform: `translateX(${-offset.value}px) translateY(${
+          -offset.value / 2
+        }px)`,
       };
     });
     (<any>this).applyAnimatedStyle(".fab-3", () => {
       "worklet";
       return {
-        transform: `translateX(${-offset.value}px) translateY(${offset.value / 2
-          }px)`,
+        transform: `translateX(${-offset.value}px) translateY(${
+          offset.value / 2
+        }px)`,
       };
     });
     (<any>this).applyAnimatedStyle(".fab-4", () => {
@@ -684,12 +683,171 @@ Page({
     this.setData({ position: {}, sheet: false });
   },
 
-  async loadScienceList() {
+  async loadScienceList(reset = false) {
+    // 如果正在加载,直接返回(防止重复请求)
+    if (this.data.scienceListLoading) {
+      return;
+    }
+
+    // 如果没有更多数据且不是重置,直接返回
+    if (!reset && !this.data.scienceListHasMore) {
+      return;
+    }
+
+    // 重置分页信息
+    if (reset) {
+      this.setData({
+        scienceListPage: 1,
+        scienceListHasMore: true,
+        scienceList: [],
+        leftColumnList: [],
+        rightColumnList: [],
+      });
+    }
+
+    this.setData({ scienceListLoading: true });
+
     try {
-      const { data } = await getShortScienceList();
-      this.setData({ scienceList: data });
-      console.log(data, "data===scienceList");
-    } catch (error) { }
+      const page = reset ? 1 : this.data.scienceListPage;
+      const {
+        data,
+        total,
+        page: currentPage,
+      } = await getShortScienceList(page, this.data.scienceListSize);
+
+      const newList = reset ? data : [...this.data.scienceList, ...data];
+      const hasMore = newList.length < total;
+
+      this.setData({
+        scienceList: newList,
+        scienceListTotal: total,
+        scienceListPage: currentPage + 1,
+        scienceListHasMore: hasMore,
+        scienceListLoading: false,
+      });
+
+      // 分配卡片到两列,实现瀑布流布局
+      this.distributeCardsToColumns(newList, reset);
+    } catch (error) {
+      this.setData({ scienceListLoading: false });
+      wx.showToast({
+        title: "加载失败,请重试",
+        icon: "none",
+      });
+    }
+  },
+
+  // 下拉刷新
+  async onRefreshScienceList() {
+    this.setData({ refreshing: true });
+    await this.loadScienceList(true);
+    this.setData({ refreshing: false });
+  },
+
+  // 上拉加载更多
+  onLoadMoreScienceList() {
+    if (this.data.scienceListHasMore && !this.data.scienceListLoading) {
+      this.loadScienceList(false);
+    }
+  },
+
+  // 将卡片分配到两列,实现瀑布流布局
+  distributeCardsToColumns(list: AnyArray, reset = false) {
+    // 如果是重置,使用空数组;否则过滤出新增的卡片
+    const itemsToDistribute = reset
+      ? list
+      : list.filter(
+          (item: any) =>
+            !this.data.leftColumnList.some(
+              (existing: any) => existing.id === item.id
+            ) &&
+            !this.data.rightColumnList.some(
+              (existing: any) => existing.id === item.id
+            )
+        );
+
+    if (itemsToDistribute.length === 0) return;
+
+    // 计算当前两列的高度(重置时两列已为空,高度为0)
+    let leftHeight = reset
+      ? 0
+      : this.data.leftColumnList.reduce(
+          (sum: number, item: any) => sum + this.estimateCardHeight(item),
+          0
+        );
+
+    let rightHeight = reset
+      ? 0
+      : this.data.rightColumnList.reduce(
+          (sum: number, item: any) => sum + this.estimateCardHeight(item),
+          0
+        );
+
+    // 追加新卡片到较短的列(重置时从空数组开始)
+    const leftColumn = reset ? [] : [...this.data.leftColumnList];
+    const rightColumn = reset ? [] : [...this.data.rightColumnList];
+
+    // 智能分配:总是将卡片放到当前高度较短的列
+    itemsToDistribute.forEach((item: any) => {
+      const estimatedHeight = this.estimateCardHeight(item);
+
+      if (leftHeight <= rightHeight) {
+        leftColumn.push(item);
+        leftHeight += estimatedHeight;
+      } else {
+        rightColumn.push(item);
+        rightHeight += estimatedHeight;
+      }
+    });
+
+    this.setData({
+      leftColumnList: leftColumn,
+      rightColumnList: rightColumn,
+    });
+  },
+
+  // 预估卡片高度(基于内容特征,更准确的预估)
+  estimateCardHeight(item: any): number {
+    let height = 0;
+
+    if (item.briefImg) {
+      const imgMinHeight = 120;
+      const imgMaxHeight = 260;
+      const imgHeightRange = imgMaxHeight - imgMinHeight;
+      const idHash = item.id
+        ? String(item.id)
+            .split("")
+            .reduce((acc: number, char: string) => acc + char.charCodeAt(0), 0)
+        : 0;
+      const imgHeight = imgMinHeight + (idHash % imgHeightRange);
+      height += imgHeight;
+    }
+
+    // 内容区域
+    const title = item.title || "";
+    const titleLength = title.length;
+    const charsPerLine = 12;
+    const titleLines = Math.min(Math.ceil(titleLength / charsPerLine), 3);
+    const titleHeight = titleLines * 24;
+
+    const contentPadding = 24;
+    const metaHeight = 40;
+
+    height += titleHeight + contentPadding + metaHeight;
+
+    height += 12;
+
+    height += 4;
+
+    if (!item.briefImg) {
+      const minContentHeight =
+        titleHeight + contentPadding + metaHeight + 12 + 4;
+      if (height < minContentHeight) {
+        height = minContentHeight;
+      }
+    }
+
+    return Math.round(height);
   },
 
   observerPatient(model: { patientId: string; sex: "0" | "1" }) {
@@ -703,7 +861,6 @@ Page({
 
     getPatientDescription(model).then((patientDescription) => {
       this.setData({ patientDescription });
-      // wx.setStorageSync("patientPhone", patientDescription.phone);
     });
 
     // 获取未处理随访列表
@@ -736,18 +893,16 @@ Page({
         icon: "success",
         duration: 1500,
       });
-      // 无感刷新调养计划,保持展开状态
       await this.refreshCareListsWithState();
     }
   },
 
-  // 无感刷新调养计划,保持展开状态和媒体加载状态
   async refreshCareListsWithState() {
     // 保存当前的展开状态
     const currentExpandedStates = this.data.displayList.map((item: any) => ({
       id: item.id,
       expanded: item.expanded,
-      carouselMediaList: item.carouselMediaList, // 保存媒体列表,避免重新加载
+      carouselMediaList: item.carouselMediaList,
     }));
 
     // 获取新数据
@@ -759,7 +914,6 @@ Page({
           (state) => state.id === item.id
         );
         if (oldItem && oldItem.carouselMediaList) {
-          // 保持原有的媒体列表,避免重新加载
           item.carouselMediaList = oldItem.carouselMediaList;
         } else {
           item.carouselMediaList = [];
@@ -824,8 +978,7 @@ Page({
    * 轮播组件进入/退出全屏时,隐藏/显示底部 tabbar,防止遮挡视频进度条
    */
   onCarouselFullscreenChange(e: { detail?: { fullScreen?: boolean } }) {
-    console.log(e, "全屏模式");
-    const fullScreen = !!(e.detail?.fullScreen);
+    const fullScreen = !!e.detail?.fullScreen;
     this.setData({
       tabbarHidden: fullScreen,
     });

+ 23 - 2
miniprogram/pages/home/home.wxml

@@ -3,7 +3,16 @@
 
   <t-navbar title="中医健康管家" t-class-title="nav-title" />
 
-  <scroll-view class="page-scroll__container" type="list" scroll-y style="height: {{pageHeight}};">
+  <scroll-view 
+    class="page-scroll__container" 
+    type="list" 
+    scroll-y 
+    style="height: {{pageHeight}};"
+    refresher-enabled="{{true}}"
+    refresher-triggered="{{refreshing}}"
+    bindrefresherrefresh="onRefreshScienceList"
+    bindscrolltolower="onLoadMoreScienceList"
+    lower-threshold="100">
     <view class="follow-container">
       <view class="follow-box" bind:tap="showFollowPopup">
         <image src="../../assets/bg/icon_notice@3x.png" mode="heightFix" class="notice-icon" />
@@ -125,7 +134,19 @@
         </view>
       </view>
       <view class="waterfall-container">
-        <waterfall-card wx:for="{{scienceList}}" wx:key="id" item="{{item}}" index="{{index}}"></waterfall-card>
+        <view class="waterfall-column">
+          <waterfall-card wx:for="{{leftColumnList}}" wx:key="id" item="{{item}}" index="{{index}}"></waterfall-card>
+        </view>
+        <view class="waterfall-column">
+          <waterfall-card wx:for="{{rightColumnList}}" wx:key="id" item="{{item}}" index="{{index}}"></waterfall-card>
+        </view>
+      </view>
+      <view class="loading-more" wx:if="{{scienceListLoading}}">
+        <t-loading theme="circular" size="32px" color="#2d92fd" />
+        <text class="loading-text">加载中...</text>
+      </view>
+      <view class="loading-more" wx:elif="{{scienceListHasMore === false}}">
+        <text class="loading-text">没有更多了</text>
       </view>
       <!--<science-card wx:for="{{scienceList}}" wx:key="id" item="{{item}}" index="{{index}}"></science-card>-->
     </view>