ith5 4 месяцев назад
Родитель
Сommit
88ceac753c
4 измененных файлов с 277 добавлено и 232 удалено
  1. 14 0
      src/app.scss
  2. 164 159
      src/components/post-list/index.tsx
  3. 41 11
      src/pages/index/index.scss
  4. 58 62
      src/pages/index/index.tsx

+ 14 - 0
src/app.scss

@@ -2,4 +2,18 @@
 @tailwind components;
 @tailwind utilities;
 
+// 全局样式,移除默认边距和状态栏留白
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+page {
+  margin: 0;
+  padding: 0;
+  height: 100vh;
+  overflow: hidden;
+}
+
 // 您的自定义样式可以在这里添加

+ 164 - 159
src/components/post-list/index.tsx

@@ -8,10 +8,11 @@ import {
   ImagePreview,
   Toast,
   PullToRefresh,
+  Sticky,
 } from "@nutui/nutui-react-taro";
 import MoreButton from "../fllower-button";
 import { circlePostListApi } from "../../api/post";
-import { useEffect, useState, useCallback } from "react";
+import { useEffect, useState, useCallback, useRef } from "react";
 import { strSlice } from "../../utils/index";
 import { followApi, interactionApi, unfollowApi } from "../../api/interaction";
 import { Dialog } from "@nutui/nutui-react-taro";
@@ -22,7 +23,7 @@ const PostList = () => {
   const [showPreview, setShowPreview] = useState(false);
   const [init, setInit] = useState(0);
   const [mediaUrl, setMediaUrl] = useState<any[]>([]);
-
+  const containerTopRef = useRef(null);
   // 分页相关状态
   const [currentPage, setCurrentPage] = useState(1);
   const [hasMore, setHasMore] = useState(true);
@@ -163,183 +164,187 @@ const PostList = () => {
     <ScrollView
       scrollY
       className="post-list-scroll"
-      style={{ height: "100%" }}
+      style={{ height: "calc(100vh - 50px)" }}
       onScrollToLower={handleLoadMore}
-      lowerThreshold={100}
+      lowerThreshold={200}
     >
-      <PullToRefresh onRefresh={handleRefresh}>
-        <View className="post-list bg-[#f8f8f8]">
-          {postList.map((item: any, index: number) => {
-            return (
+      {/* <PullToRefresh onRefresh={handleRefresh}> */}
+      <View className="post-list bg-[#f8f8f8]">
+        {postList.map((item: any, index: number) => {
+          return (
+            <View
+              key={item.id}
+              className="post-list-item  bg-[#fff] p-[10px] mb-[10px]"
+            >
               <View
-                key={item.id}
-                className="post-list-item  bg-[#fff] p-[10px] mb-[10px]"
+                className="flex items-center justify-between"
+                onClick={() => {
+                  navigateTo({
+                    url: `/pages/self/index?id=${item.user_id}`,
+                  });
+                }}
               >
-                <View
-                  className="flex items-center justify-between"
-                  onClick={() => {
-                    navigateTo({ url: `/pages/self/index?id=${item.user_id}` });
-                  }}
-                >
-                  <View className="flex items-center">
-                    <View
-                      className="w-[40px] h-[40px] rounded-[50%] bg-[#000] overflow-hidden bg-cover bg-center"
-                      style={{
-                        backgroundImage: item.user.avatar_url
-                          ? `url('${item.user.avatar_url}')`
-                          : "none",
-                      }}
-                    ></View>
-                    <View className="ml-[5px]">
-                      <View className="text-[14px] font-[800] text-[#9c9dee]">
-                        {item.user.nickname || item.user.username || "微信用户"}
-                      </View>
-                      {item.user.is_official ? (
-                        <View className="text-[12px] text-[#949494]">
-                          《心动女友》官方账号
-                        </View>
-                      ) : (
-                        <></>
-                      )}
-                    </View>
-                  </View>
-                  <View className="flex items-center">
-                    <View
-                      className="flex items-center justify-center mr-[12px] text-[12px] bg-[#f8f8f8] text-[#949494] rounded-[20px] h-[25px] w-[60px] text-center"
-                      onClick={(e) => {
-                        e.stopPropagation();
-                        handleFollowClick(item.user_id, item.is_followed);
-                      }}
-                    >
-                      {item.is_followed ? <></> : <Plus color="#1874d0" />}
-                      <Text>{item.is_followed ? "已关注" : "关注"}</Text>
+                <View className="flex items-center">
+                  <View
+                    className="w-[40px] h-[40px] rounded-[50%] bg-[#000] overflow-hidden bg-cover bg-center"
+                    style={{
+                      backgroundImage: item.user.avatar_url
+                        ? `url('${item.user.avatar_url}')`
+                        : "none",
+                    }}
+                  ></View>
+                  <View className="ml-[5px]">
+                    <View className="text-[14px] font-[800] text-[#9c9dee]">
+                      {item.user.nickname || item.user.username || "微信用户"}
                     </View>
                     {item.user.is_official ? (
-                      <></>
+                      <View className="text-[12px] text-[#949494]">
+                        《心动女友》官方账号
+                      </View>
                     ) : (
-                      <MoreButton
-                        postIndex={index}
-                        followeeId={item.user_id}
-                        postId={item.id}
-                        postItem={item}
-                        onClick={handleMoreClick}
-                      />
+                      <></>
                     )}
                   </View>
                 </View>
-                <View
-                  onClick={() =>
-                    navigateTo({ url: `/pages/detail/index?id=${item.id}` })
-                  }
-                >
-                  <View className="text-[14px] text-[#333] pt-[20px]">
-                    {strSlice(item.content, 100)}
-                    {item.content.length > 100 && (
-                      <Text className="text-[#1874d0]">全文</Text>
-                    )}
+                <View className="flex items-center">
+                  <View
+                    className="flex items-center justify-center mr-[12px] text-[12px] bg-[#f8f8f8] text-[#949494] rounded-[20px] h-[25px] w-[60px] text-center"
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      handleFollowClick(item.user_id, item.is_followed);
+                    }}
+                  >
+                    {item.is_followed ? <></> : <Plus color="#1874d0" />}
+                    <Text>{item.is_followed ? "已关注" : "关注"}</Text>
                   </View>
-                  <View className="mt-[10px]">
-                    <Grid
-                      columns={item.media_url.length < 3 ? 2 : 3} // 这里,如果图片小于3张,则columns为2,如果图片大于等于3张,则columns为3
-                      gap={7}
-                      style={
-                        {
-                          "--nutui-grid-item-content-padding": "0px",
-                          "--nutui-grid-item-content-margin": "0px",
-                          "--nutui-grid-border-color": "transparent",
-                        } as any
-                      }
-                    >
-                      {item.media_url.map((ite: any, index: number) => {
-                        return (
-                          <GridItem>
-                            <Image
-                              width="100%"
-                              height="100px"
-                              src={ite.src}
-                              mode="widthFix"
-                              onClick={(e) => {
-                                e.preventDefault();
-                                e.stopPropagation();
-                                setMediaUrl(item.media_url);
-                                setInit(index + 1);
+                  {item.user.is_official ? (
+                    <></>
+                  ) : (
+                    <MoreButton
+                      postIndex={index}
+                      followeeId={item.user_id}
+                      postId={item.id}
+                      postItem={item}
+                      onClick={handleMoreClick}
+                    />
+                  )}
+                </View>
+              </View>
+              <View
+                onClick={() =>
+                  navigateTo({ url: `/pages/detail/index?id=${item.id}` })
+                }
+              >
+                <View className="text-[14px] text-[#333] pt-[20px]">
+                  {strSlice(item.content, 100)}
+                  {item.content.length > 100 && (
+                    <Text className="text-[#1874d0]">全文</Text>
+                  )}
+                </View>
+                <View className="mt-[10px]">
+                  <Grid
+                    columns={item.media_url.length < 3 ? 2 : 3} // 这里,如果图片小于3张,则columns为2,如果图片大于等于3张,则columns为3
+                    gap={7}
+                    style={
+                      {
+                        "--nutui-grid-item-content-padding": "0px",
+                        "--nutui-grid-item-content-margin": "0px",
+                        "--nutui-grid-border-color": "transparent",
+                      } as any
+                    }
+                  >
+                    {item.media_url.map((ite: any, index: number) => {
+                      return (
+                        <GridItem>
+                          <Image
+                            src={ite.src}
+                            mode={
+                              item.media_url.length === 1
+                                ? "scaleToFill"
+                                : "scaleToFill"
+                            }
+                            onClick={(e) => {
+                              e.preventDefault();
+                              e.stopPropagation();
+                              setMediaUrl(item.media_url);
+                              setInit(index + 1);
 
-                                setShowPreview(true);
-                              }}
-                            />
-                          </GridItem>
-                        );
-                      })}
-                    </Grid>
+                              setShowPreview(true);
+                            }}
+                          />
+                        </GridItem>
+                      );
+                    })}
+                  </Grid>
+                </View>
+                <View className="mt-[10px] pl-[20px] pr-[20px] flex items-center justify-between">
+                  <View className="flex items-center">
+                    <Message size={16} color="#949494" />
+                    <Text className="ml-[5px] text-[16px] text-[#949494]">
+                      {item.comment_count}
+                    </Text>
                   </View>
-                  <View className="mt-[10px] pl-[20px] pr-[20px] flex items-center justify-between">
-                    <View className="flex items-center">
-                      <Message size={16} color="#949494" />
-                      <Text className="ml-[5px] text-[16px] text-[#949494]">
-                        {item.comment_count}
-                      </Text>
-                    </View>
-                    <View
-                      className="flex items-center"
-                      onClick={(e) => {
-                        e.stopPropagation();
-                        handleInteraction(
-                          item.id,
-                          item.interaction_type === "praise"
-                            ? "dispraise"
-                            : "praise"
-                        );
-                      }}
-                    >
-                      {item.interaction_type === "praise" ? (
-                        <HeartFill size={16} color="#ec4342" />
-                      ) : (
-                        <Heart size={16} color="#949494" />
-                      )}
-                      <Text className="ml-[5px] text-[16px] text-[#949494]">
-                        {item.like_count}
-                      </Text>
-                    </View>
+                  <View
+                    className="flex items-center"
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      handleInteraction(
+                        item.id,
+                        item.interaction_type === "praise"
+                          ? "dispraise"
+                          : "praise"
+                      );
+                    }}
+                  >
+                    {item.interaction_type === "praise" ? (
+                      <HeartFill size={16} color="#ec4342" />
+                    ) : (
+                      <Heart size={16} color="#949494" />
+                    )}
+                    <Text className="ml-[5px] text-[16px] text-[#949494]">
+                      {item.like_count}
+                    </Text>
                   </View>
                 </View>
               </View>
-            );
-          })}
-
-          {/* 空状态提示 */}
-          {postList.length === 0 && !loading && (
-            <View className="flex flex-col items-center justify-center py-[50px]">
-              <Text className="text-[#999] text-[14px]">暂无帖子</Text>
             </View>
-          )}
+          );
+        })}
 
-          {/* 加载更多提示 */}
-          {hasMore && (
-            <View className="p-[20px] text-center">
-              <Text className="text-[14px] text-[#999]">
-                {loading ? "加载中..." : "上拉加载更多"}
-              </Text>
-            </View>
-          )}
+        {/* 空状态提示 */}
+        {postList.length === 0 && !loading && (
+          <View className="flex flex-col items-center justify-center py-[50px]">
+            <Text className="text-[#999] text-[14px]">暂无帖子</Text>
+          </View>
+        )}
 
-          {!hasMore && postList.length > 0 && (
-            <View className="p-[20px] text-center">
-              <Text className="text-[14px] text-[#999]">没有更多了</Text>
-            </View>
-          )}
+        {/* 加载更多提示 */}
+        {hasMore && (
+          <View className="p-[20px] text-center">
+            <Text className="text-[14px] text-[#999]">
+              {loading ? "加载中..." : "上拉加载更多"}
+            </Text>
+          </View>
+        )}
+
+        {!hasMore && postList.length > 0 && (
+          <View className="p-[20px] text-center">
+            <Text className="text-[14px] text-[#999]">没有更多了</Text>
+          </View>
+        )}
 
-          <ImagePreview
-            images={mediaUrl}
-            visible={showPreview}
-            defaultValue={init}
-            onClose={() => setShowPreview(false)}
-            indicator
-          />
-          <Toast id="follow_success" />
-          <Toast id="load_error" />
-          <Dialog id="followed_dialog" />
-        </View>
-      </PullToRefresh>
+        <ImagePreview
+          images={mediaUrl}
+          visible={showPreview}
+          defaultValue={init}
+          onClose={() => setShowPreview(false)}
+          indicator
+        />
+        <Toast id="follow_success" />
+        <Toast id="load_error" />
+        <Dialog id="followed_dialog" />
+      </View>
+      {/* </PullToRefresh> */}
     </ScrollView>
   );
 };

+ 41 - 11
src/pages/index/index.scss

@@ -14,23 +14,53 @@
 }
 
 .index-header {
-  background-image: url("https://img1.baidu.com/it/u=1184275824,54771083&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=667");
+  // background-image: url("https://img1.baidu.com/it/u=1184275824,54771083&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=667");
   background-size: cover;
   background-position: center;
   background-repeat: no-repeat;
   color: #fff;
-  width: calc(100vw - 20px);
-  &::before {
-    content: "";
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    background-color: rgba(0, 0, 0, 0.5);
-  }
+  width: 100%;
+  // &::before {
+  //   content: "";
+  //   position: absolute;
+  //   top: 0;
+  //   left: 0;
+  //   width: 100%;
+  //   height: 100%;
+  //   background-color: rgba(0, 0, 0, 0.5);
+  // }
 }
 
 .index-content {
   height: calc(100vh - 60px);
 }
+
+// 页面滚动容器
+.page-scroll {
+  width: 100%;
+}
+
+// 页面内容容器
+.page-content {
+  position: relative;
+  min-height: calc(100vh + 130px); // 最小高度 = 视窗高度 + 蓝色区域高度
+}
+
+// 可滚动的横幅区域
+.scrollable-banner {
+  // 这个区域可以正常滚动,不需要特殊样式
+}
+
+// PostList容器样式
+.post-list-container {
+  position: sticky;
+  top: 350px; // 当外层ScrollView滚动时,PostList吸顶到ScrollView顶部
+  z-index: 10; // 确保在内容之上,但在头部导航栏之下
+  background-color: #fff;
+  width: 100%; // 确保宽度占满
+
+  // PostList内部的ScrollView
+  .post-list-scroll {
+    width: 100% !important;
+  }
+}

+ 58 - 62
src/pages/index/index.tsx

@@ -1,16 +1,16 @@
-import { View, Text } from "@tarojs/components";
+import { View, Text, ScrollView } from "@tarojs/components";
 import { Plus, User } from "@nutui/icons-react-taro";
 import { getStorageSync, navigateTo } from "@tarojs/taro";
 import PostList from "../../components/post-list";
 
 import "./index.scss";
-import { Image } from "@nutui/nutui-react-taro";
+import { Image, Sticky, Tabs } from "@nutui/nutui-react-taro";
 import { useEffect, useState } from "react";
 import { getCircleInfoApi } from "../../api/circle";
-import config from "../../config";
 
 function Index() {
   const [circleData, setCircleData] = useState<any>(null);
+  const [tab1value, setTab1value] = useState<string | number>("0");
   const [userInfo, setUserInfo] = useState<any>(null);
   const getUserInfo = () => {
     const userInfo = getStorageSync("User");
@@ -24,12 +24,10 @@ function Index() {
   }, []);
   return (
     <View className="index">
-      <View
-        className="index-header fixed top-0 left-0 right-0 z-20 h-[60px] w-full flex items-center justify-between px-[10px]"
-        style={{ backgroundImage: `url(${circleData?.icon_url})` }}
-      >
+      {/* 头部导航栏 - 移出page-content容器 */}
+      <View className="index-header bg-[#6069d9] fixed top-0 left-0 right-0 z-20 h-[50px] w-full flex items-center justify-between px-[10px]">
         <View className="flex items-center relative z-40">
-          <View className="w-[50px] h-[50px] bg-[#fff] rounded-[10px] overflow-hidden">
+          <View className="w-[30px] h-[30px] bg-[#fff] rounded-[50%] overflow-hidden">
             <Image
               src={circleData?.icon_url}
               width="100%"
@@ -37,71 +35,69 @@ function Index() {
               mode="aspectFill"
             />
           </View>
-          <Text className="text-[16px] font-[800] text-[#fff] ml-[10px]">
-            {circleData?.name}
-          </Text>
+          <View>
+            <View className="text-[13px] font-[800] text-[#fff] ml-[10px]">
+              {circleData?.name}
+            </View>
+            <View className="text-[12px] text-[#ccc] ml-[10px]">
+              3400人在线
+            </View>
+          </View>
         </View>
-        {/* <View
-          className="flex items-center relative z-40"
+        <View
           onClick={() => {
             navigateTo({ url: "/pages/self/index" });
           }}
         >
-          <User size={24} />
-        </View> */}
+          <User size={20} />
+        </View>
       </View>
 
-      <View className="index-content absolute top-[60px] left-0 right-0 bottom-0 z-20 rounded-[30px] overflow-hidden">
-        <View className="h-25 p-[10px] flex ">
-          {userInfo?.is_vip ? (
-            <>
-              <View
-                className="w-[22%] pt-[10px] mr-[10px] pb-[10px] pl-[5px] border-[1rpx] border-solid border-[#e0e0e0] rounded-[5px] shadow-[0_15px_10px_-16px_rgba(0,0,0,0.3)]"
-                onClick={() => {
-                  // window.location.href = `${config.TARO_ACT_HOST}/jifen/exchange?vip_code=${userInfo?.vip_code}`;
-                  navigateTo({ url: "/pages/act/index" });
-                }}
-              >
-                <View className="text-[14px] font-[800] text-[#333]">
-                  福利中心
-                </View>
-                <View className="text-[12px] text-[#949494]">登录领奖</View>
-              </View>
-            </>
-          ) : (
-            <></>
-          )}
-
-          {/* <View className="w-[22%] pt-[10px] pb-[10px] pl-[5px] border-[1rpx] border-solid border-[#e0e0e0]  rounded-[5px] shadow-[0_15px_10px_-16px_rgba(0,0,0,0.3)]">
-            <View className="text-[14px] font-[800] text-[#333]">游戏攻略</View>
-            <View className="text-[12px] text-[#949494]">最新资讯</View>
-          </View>
-          <View className="w-[22%] pt-[10px] pb-[10px] pl-[5px] border-[1rpx] border-solid border-[#e0e0e0]  rounded-[5px] shadow-[0_15px_10px_-16px_rgba(0,0,0,0.3)]">
-            <View className="text-[14px] font-[800] text-[#333]">组队开黑</View>
-            <View className="text-[12px] text-[#949494]">寻找队友</View>
-          </View> */}
-          <View
-            className="w-[22%] pt-[10px] pb-[10px] pl-[5px] border-[1rpx] border-solid border-[#e0e0e0]  rounded-[5px] shadow-[0_15px_10px_-16px_rgba(0,0,0,0.3)]"
-            onClick={() => {
-              navigateTo({ url: "/pages/self/index" });
-            }}
-          >
-            <View className="text-[14px] font-[800] text-[#333]">个人中心</View>
-            <View className="text-[12px] text-[#949494]">我的信息</View>
+      {/* 页面内容 - 使用ScrollView控制整个页面滚动 */}
+      <View
+        className="page-scroll"
+        // scrollY
+        // style={{ height: "calc(100vh - 50px)" }}
+      >
+        <View className="page-content">
+          <View className="scrollable-banner h-[100px] pb-[10px] bg-[#6069d9] pt-[60px] flex items-center justify-around">
+            <View
+              className="text-[#fff] w-[100px] h-[30px] flex items-center justify-center text-center text-[14px] font-[800] px-[10px] bg-[#5258acf0] "
+              onClick={() => {
+                navigateTo({ url: "/pages/act/index" });
+              }}
+            >
+              积分中心
+            </View>
+            <View className="text-[#fff] w-[100px] h-[30px] flex items-center justify-center text-center text-[14px] font-[800] px-[10px] bg-[#5258acf0]">
+              礼包中心
+            </View>
           </View>
-        </View>
 
-        <PostList />
-        {/* <TabbarCom /> */}
-        <View
-          className="fixed bottom-[50px] right-[20px] w-[50px] h-[50px] bg-[#6069d9] rounded-[50%] z-10 justify-center items-center flex "
-          onClick={() => {
-            navigateTo({ url: "/pages/publish/index" });
-          }}
-        >
-          <Plus color="#fff" size={50} style={{ marginLeft: "-2px" }} />
+          <Sticky threshold={50}>
+            <Tabs
+              value={tab1value}
+              align="left"
+              onChange={(value) => {
+                setTab1value(value);
+              }}
+            >
+              <Tabs.TabPane title="最新">
+                <PostList />
+              </Tabs.TabPane>
+            </Tabs>
+          </Sticky>
         </View>
       </View>
+
+      <View
+        className="fixed bottom-[50px] right-[20px] w-[50px] h-[50px] bg-[#6069d9] rounded-[50%] z-10 justify-center items-center flex "
+        onClick={() => {
+          navigateTo({ url: "/pages/publish/index" });
+        }}
+      >
+        <Plus color="#fff" size={50} style={{ marginLeft: "-2px" }} />
+      </View>
     </View>
   );
 }