Bläddra i källkod

```
feat(app): 添加无限滚动加载功能并优化首页布局

- 在App.vue中添加v-infinite-scroll指令实现无限滚动加载
- 重构router-view使用v-slot插槽并添加组件引用
- 隐藏首页底部导航栏
- 重构Home.vue页面布局,添加左侧介绍区域和用户统计
- 实现loadMore方法支持分页加载更多数据
- 添加图片资源:allyinqing.png、aigongzuoliu.png、userTotal.png
- 优化轮播图样式,设置固定高度和左边距

fix(workflowTrade): 修复需求状态按钮样式问题

- 根据申请状态动态设置按钮类型,结束状态显示危险样式

feat(LearnNote): 优化学习笔记页面显示

- 为封面图片添加独立CSS类名
- 隐藏个人笔记项的学习按钮
- 在列表开头插入个人笔记项,使用用户头像作为封面

style(styles): 添加行高样式类

- 新增.line_height30样式类,行高设置为30px
```

zhangningning 1 vecka sedan
förälder
incheckning
6a50a062c4

+ 26 - 4
src/App.vue

@@ -1,9 +1,13 @@
 <template>
-  <div id="app" :class="{
+  <div id="app" 
+  :class="{
     'isHomePage': $route.path === '/' || $route.path === '/index',
     vipHomePage: $route.path === '/member',
     isScroll: appStore.isScroll,
-  }">
+  }"
+   v-infinite-scroll="scrollLoad" infinite-scroll-disabled="false" infinite-scroll-distance="0"
+   :infinite-scroll-immediate="false"
+  >
     <ElConfigProvider :locale="langStore.elLocale">
     <el-container style="min-height: 100vh;">
       <el-header class="box_shadow_card">
@@ -45,10 +49,15 @@
       <div style="height: 60px;"></div>
       <div class="header-bj" v-if="$route.path === '/member'"></div>
       <el-main class="container">
-        <router-view />
+        <router-view v-slot="{ Component }">
+          <component
+            :is="Component"
+            ref="routerChildRef" 
+          />
+        </router-view>
       </el-main>
       
-      <el-footer>
+      <el-footer v-if="!['/index'].includes($route.path)">
         <div class="footer-content" >
           <p> 
             <span class="cursor-pointer" @click="router.push({name:'Agreement',query:{type:'service_agreement'}})">
@@ -184,6 +193,19 @@ onUnmounted(() => {
 
 
 provide('openLoginDialog', openLoginDialog);
+
+// 无限滚动加载
+const routerChildRef = ref(null);
+const scrollLoad = () => {
+  console.log('触发滚动加载',routerChildRef.value)
+  nextTick(() => {
+    const routerChild = routerChildRef.value;
+    
+    if (routerChild && typeof routerChild.loadMore === 'function') {
+      routerChild.loadMore();
+    }
+  });
+};
 </script>
 
 <style lang="scss">

BIN
src/assets/imgs/aigongzuoliu.png


BIN
src/assets/imgs/allyinqing.png


BIN
src/assets/imgs/userTotal.png


+ 65 - 28
src/pages/Home.vue

@@ -1,23 +1,25 @@
 <template>
   <div class="home-page">
     <div class="banner flex-center">
-      <el-carousel :height="carouselHeight" style="width: 100%;">
-        <el-carousel-item v-for="(item,index) in 3" :key="index">
-          <img
-            :src="`https://baomiai.oss-cn-shanghai.aliyuncs.com/static/banner-0${index+1}.png`"
-            class="carousel-image"
-            @load="onImageLoad"
-          />
-        </el-carousel-item>
-        <!-- <el-carousel-item>
-          <img
-            :src="bannerImage"
-            class="carousel-image"
-            @load="onImageLoad"
-          />
-        </el-carousel-item> -->
-        
-      </el-carousel>
+      <div class="flex-between" style="width:100%">
+        <div class="flex_1 flex-column-start-between" >
+          <img :src="allyinqing" alt="" style="height:40px">
+          <img :src="aigongzuoliu" alt="" style="height:186px">
+          <div class="font_size24 line_height30">
+            一站式发现、交易与运行自动化工作流。连接n8n、Coze、Dify 等主流平台,释放生产力潜能。
+          </div>
+          <img :src="userTotal" alt="" style="height:52px">
+        </div>
+        <el-carousel height="522px" style="width: 777px;">
+          <el-carousel-item v-for="(item,index) in 3" :key="index">
+            <img
+              :src="`https://baomiai.oss-cn-shanghai.aliyuncs.com/static/banner-0${index+1}.png?v=0.0.1`"
+              class="carousel-image"
+              @load="onImageLoad"
+            />
+          </el-carousel-item>
+        </el-carousel>
+      </div>
     </div>
     <!-- 中间搜索区域 -->
     <div class="workflow-container">
@@ -82,6 +84,9 @@
 
 <script setup>
 import searchIcon from '@/assets/imgs/search.png'
+import allyinqing from '@/assets/imgs/allyinqing.png'
+import aigongzuoliu from '@/assets/imgs/aigongzuoliu.png'
+import userTotal from '@/assets/imgs/userTotal.png'
 import addIcon from '@/assets/imgs/add.png'
 import n8Icon from '@/assets/imgs/8n8.png'
 import cozeIcon from '@/assets/imgs/coze.png'
@@ -95,16 +100,18 @@ import { getCategoryListTree } from '@/api/category.js'
 import { getPublishList } from '@/api/publish.js'
 
 
-import { onMounted,ref, inject } from 'vue'
+import { onMounted,ref, inject, reactive } from 'vue'
 import { useRouter } from 'vue-router'
 import { useI18n } from 'vue-i18n' 
 const { t } = useI18n() // 获取t函数// 导入useI18n
 const categoryListTree = ref([])
 
+
 onMounted(() => {
   console.log('Home mounted')
   getCategoryListTreeFn();
-  getList();
+  // getList();
+  loadMore();
 })
 
 const router = useRouter()
@@ -165,17 +172,42 @@ const getCategoryListTreeFn = () => {
 };
 
 // 查询寻找工作流列表
-const getList = async (type) => {
-  const res = await getPublishList({
-    pageNum: 1,
-    pageSize: 8,
-    orderByColumn: 'publishId',
-    isAsc: 'desc'
-  })
+const searchFom = reactive({
+  pageNum: 0,
+  pageSize: 8,
+  orderByColumn: 'publishId',
+  isAsc: 'desc'
+})
+const total = ref(0); 
+const hasLoadedAll = ref(false);
+// const getList = async (type) => {
+//   const res = await getPublishList(searchFom)
+//   if(res.code === 200){
+//     list.value = res.rows || [];
+//   }
+// };
+const loadMore = async () => {
+  // 如果已经加载完所有数据,则不再请求
+  if (hasLoadedAll.value) {
+    return;
+  }
+ 
+  searchFom.pageNum += 1;
+  const res = await getPublishList(searchFom)
   if(res.code === 200){
-    list.value = res.rows || [];
+    list.value = [...list.value, ...res.rows || []];
+    total.value = res.total || 0;
+    // 判断是否已加载完所有数据
+    if (list.value.length >= total.value) {
+      hasLoadedAll.value = true;
+    }
   }
 };
+
+defineExpose({
+  loadMore
+});
+
 </script>
 
 <style lang="scss">
@@ -186,7 +218,8 @@ const getList = async (type) => {
   min-height: 600px;
   .carousel-image {
     width: 100%;
-    height: auto;
+    height: 522px;
+    margin-left: 20px;
     // object-fit: cover; // 保持比例填充整个容器
     // object-position: center; // 居中显示
   }
@@ -350,9 +383,13 @@ $height-btn: 50px;
   }
 }
 .home-page{
+  // height: calc(100vh - 60px);
+  // overflow: auto;
   .course-list{
     margin-top: 70px;
     margin-bottom: 140px;
+    // height: calc(100vh - 60px - 140px);
+    // overflow: auto;
   }
 }
 </style>

+ 16 - 3
src/pages/LearnNote/LearnNote.vue

@@ -12,11 +12,11 @@
           @click="selectedItem = item"
           :class="{'active': item.courseId === selectedItem.courseId}"
           v-for="item in list" :key="item.courseId">
-            <img :src="item.coverImageUrl" alt="" style="width: 160px; height: 90px;" class="border_radius_8 bg_color_f5">
+            <img :src="item.coverImageUrl" alt="" class="coverImageUrl border_radius_8 bg_color_f5">
             <div class="flex_1 ml20">
               <div class="font_size18 bold">{{ item.courseTitle }}</div>
               <div class="font_size14 line2 gray mt10">{{ item.courseIntro }}</div>
-              <div class="flex-center-flex-end mt10">
+              <div class="flex-center-flex-end mt10" v-if="item.courseId!=-1">
                 <div class="gap5 gradient border_radius_4 cursor-pointer xuexi" @click.stop.prevent="goDetail(item)">
                   <img :src="playIcon" alt="" style="width:13px;height:15px">
                   <div>{{$t('common.lijixuexi')}}</div>
@@ -72,7 +72,16 @@ const getList = async () => {
     loading.close();
     if(res.code === 200){
       console.log(res)
-      list.value = res.rows || [];
+      // list.value = res.rows || [];
+      list.value = [
+        {
+          courseId:'-1',
+          courseTitle:'个人笔记',
+          coverImageUrl:appStore.userInfo?.userAvatar || '',
+          courseIntro:''
+        },
+        ...res.rows
+      ]
       if(list.value.length > 0){
         selectedItem.value = list.value[0]
       }
@@ -105,6 +114,10 @@ const goDetail = (item) => {
     &.active{
       background-color: rgba(45, 113, 255, 0.10) ;
     }
+    .coverImageUrl{
+      width: 160px;
+      height: 90px;
+    }
   }
   .xuexi{
     color: #ffffff;

+ 3 - 1
src/pages/workflowTrade/workflowTrade.vue

@@ -83,7 +83,9 @@
           <div  @click="goworkflowTradeDetail(item)" class="cursor-pointer">
             <div class="flex-between">
               <div class="gap10">
-                <el-button type="primary" v-if="applyStatusInfo[item.applyStatus]">
+                <el-button 
+                :type="item.applyStatus == 2 ? 'danger' : 'primary'" 
+                v-if="applyStatusInfo[item.applyStatus]">
                   {{item.applyStatus === '1' ? $t('workflowTrade.demandStatusSignUping') : $t('workflowTrade.demandStatusEnded')}}
                 </el-button>
                 <div class="bold font_size30">{{item.title}}</div>

+ 4 - 0
src/styles/index.scss

@@ -718,6 +718,10 @@ wx-image {
 	font-size: 13px;
 }
 
+.line_height30 {
+	line-height: 30px;
+}
+
 .line_height26 {
 	line-height: 26px;
 }