Explorar el Código

问卷管理和评价管理的列表页添加卡片滚动加载功能

lm hace 1 mes
padre
commit
b6f1b16b5d

+ 111 - 68
src/components/questionnaireCard/QuestionnaireCard.vue

@@ -1,74 +1,82 @@
 <template>
-    <div
-        class="card_item">
-        <!-- 顶部区域:图标 + 标题 -->
-        <div class="card_header">
-            <!-- 模拟图片中的文档图标 -->
-             <span class="card_img">
-                <img :src="questionnaireCardIcon" alt=""/>
-             </span>
-            <span class="card_title two_line_ellipsis">{{ questionnaire.title }}</span>
-
-            <el-switch
-                :model-value="Boolean(questionnaire.openStatus)"
-                v-if="showSwitch"
-                @change="(newVal)=>HandleOnOffChange(newVal,questionnaire.openStatus,questionnaire)"
-                style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #bbbbbb"
-            />
-        </div>
+    <div>
+        <div  class="questionnaire_list">
+            <div v-for="questionnaire in questionnaireList" 
+                :key="questionnaire.id"  class="card_item">
+                <!-- 顶部区域:图标 + 标题 -->
+                <div class="card_header">
+                    <!-- 模拟图片中的文档图标 -->
+                    <span class="card_img">
+                        <img :src="questionnaireCardIcon" alt=""/>
+                    </span>
+                    <span class="card_title two_line_ellipsis">{{ questionnaire.title }}</span>
 
-        <!-- 中间区域:元数据 (分数、创建人、状态、时间) -->
-        <div class="card_meta">
-            <div class="meta_row">
-                <!-- 问卷总分 -->
-                <span  v-if="cardType == 'questionnareManage'" class="score_text icon_text">
-                    <img :src="scoreIcon" alt="">
-                    {{ questionnaire.assessmentScore }}分</span>
-                
-                <!-- 创建者 -->
-                <span class="creator_text icon_text">
-                    <img :src="peopleIcon" alt="">
-                    {{questionnaire.teacherName}}</span>
-                <!-- 评价类型 -->
-                <span class="icon_text" v-if="cardType == 'reviewManage'">
-                    <img :src="questionnaire.evaluationType === 0 ? onlineDektopIcon : writeLineIcon" alt="">
-                    {{ typeNumToName(questionnaire.evaluationType).title }}
-                </span>
-                <!-- 状态文本:根据 cardStatus 动态变色 -->
-                <span :class="['status_text','icon_text', statusNumToName(questionnaire.cardStatus)?.themeClass ,'']"
-                    :style="{color:statusNumToName(questionnaire.cardStatus)?.iconColor}">
-                    <RightCircle :style="{'--icon-color':statusNumToName(questionnaire.cardStatus)?.iconColor }" />
-                    {{ statusNumToName(questionnaire.cardStatus)?.title  }}
-                </span>
-            </div>
-            <div class="time_row icon_text">
-                <!-- 评价管理的 线下答卷 不显示 时间 -->
-                <template v-if="cardType == 'questionnareManage' || 
-                    cardType == 'reviewManage' && questionnaire.evaluationType === 0">
-                    <img :src="timeIcon" alt="">
-                    {{ questionnaire.time }}
-                </template>
-            </div>
-        </div>
+                    <el-switch
+                        :model-value="Boolean(questionnaire.openStatus)"
+                        v-if=" questionnaire.evaluationType === 0 ? true : false"
+                        @change="(newVal)=>HandleOnOffChange(newVal,questionnaire.openStatus,questionnaire)"
+                        style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #bbbbbb"
+                    />
+                </div>
+
+                <!-- 中间区域:元数据 (分数、创建人、状态、时间) -->
+                <div class="card_meta">
+                    <div class="meta_row">
+                        <!-- 问卷总分 -->
+                        <span  v-if="cardType == 'questionnareManage'" class="score_text icon_text">
+                            <img :src="scoreIcon" alt="">
+                            {{ questionnaire.assessmentScore }}分</span>
+                        
+                        <!-- 创建者 -->
+                        <span class="creator_text icon_text">
+                            <img :src="peopleIcon" alt="">
+                            {{questionnaire.teacherName}}</span>
+                        <!-- 评价类型 -->
+                        <span class="icon_text" v-if="cardType == 'reviewManage'">
+                            <img :src="questionnaire.evaluationType === 0 ? onlineDektopIcon : writeLineIcon" alt="">
+                            {{ typeNumToName(questionnaire.evaluationType).title }}
+                        </span>
+                        <!-- 状态文本:根据 cardStatus 动态变色 -->
+                        <span :class="['status_text','icon_text', statusNumToName(questionnaire.cardStatus)?.themeClass ,'']"
+                            :style="{color:statusNumToName(questionnaire.cardStatus)?.iconColor}">
+                            <RightCircle :style="{'--icon-color':statusNumToName(questionnaire.cardStatus)?.iconColor }" />
+                            {{ statusNumToName(questionnaire.cardStatus)?.title  }}
+                        </span>
+                    </div>
+                    <div class="time_row icon_text">
+                        <!-- 评价管理的 线下答卷 不显示 时间 -->
+                        <template v-if="cardType == 'questionnareManage' || 
+                            cardType == 'reviewManage' && questionnaire.evaluationType === 0">
+                            <img :src="timeIcon" alt="">
+                            {{ questionnaire.time }}
+                        </template>
+                    </div>
+                </div>
 
-        <div class="page_solid_line"></div>
+                <div class="page_solid_line"></div>
 
-        <!-- 底部区域:操作按钮 -->
-        <div class="card_footer">
-            <slot name="default" :row="questionnaire"></slot>
+                <!-- 底部区域:操作按钮 -->
+                <div class="card_footer">
+                    <slot name="default" :row="questionnaire"></slot>
+                </div>
+            </div>
+        </div>
+        <div class="load_more" @click=" Number(pageSize || 0) >= Number(totalNum || 0)? '' : emit('loadMorePage')">
+            {{ Number(pageSize || 0) >= Number(totalNum || 0) ? '没有更多了' : '加载更多' }}
         </div>
     </div>
 </template>
 
 
 <script setup lang="ts">
+import {watch} from 'vue'
+
 import peopleIcon from '@/assets/evaluateTeaching/people_icon.png'
 import timeIcon from '@/assets/evaluateTeaching/time_icon.png'
 import writeLineIcon from '@/assets/evaluateTeaching/write_line_icon.png'
 import onlineDektopIcon from '@/assets/evaluateTeaching/online_desktop.png'
 import questionnaireCardIcon from '@/assets/evaluateTeaching/questionnaire_card_icon.png'
 import scoreIcon from '@/assets/evaluateTeaching/score_icon.png'
-
 import RightCircle from '@/assets/evaluateTeaching/RightCircle.vue'
 
 
@@ -83,7 +91,6 @@ interface QuestionnaireItm {
     evaluationType?:Number|String,  //卡片类型
     status?:Boolean,
 }
-
 interface StatusItm {
   statusFlag:Number | String,
   title:String,
@@ -94,15 +101,14 @@ interface TypeItm {
   type:Number | String,
   title:String,
 }
-
  // questionnareManage (问卷管理) | reviewManage (评价管理) |  
 type CardType = 'questionnareManage' | 'reviewManage'
 
 
 
 const props = defineProps({
-    questionnaire:{
-        type:Object as ()=>QuestionnaireItm,
+    questionnaireList:{
+        type:Array as ()=>QuestionnaireItm[],
         requried:true,
     },
     cardStatusMsg:{  //卡片状态信息
@@ -116,19 +122,23 @@ const props = defineProps({
         type:String as ()=>CardType,  
         required:true
     },
-    showSwitch:{
-        type:Boolean,
-        default:false
-    }
+    scrollAimDom:{  // 监听的目标滚动元素
+        type:Object
+    },
+    pageSize:{
+        type:Number,
+        default:0
+    },
+    totalNum:{
+        type:Number,
+        default:0
+    },
 })
 
-const emit = defineEmits(['switchOnOff'])
+const emit = defineEmits(['switchOnOff','loadMorePage'])
 // 处理卡片的开关状态
 const HandleOnOffChange = (newVal,oldVal,row)=>{
-    // console.log('newVal',newVal,'oldVal',oldVal)
-    // if(Boolean(newVal) !== Boolean(oldVal)){
-        emit('switchOnOff',{id:row.id,onOffVal:newVal })
-    // }
+    emit('switchOnOff',{id:row.id,onOffVal:newVal })
 }
 const statusNumToName=(status:String|Number|null|undefined)=>{
   let result =  props?.cardStatusMsg?.find(item=>item.statusFlag === status)
@@ -153,10 +163,32 @@ const typeNumToName=(type:String|Number|null|undefined)=>{
     }
   }
 }
+const HandleCourseScroll = (e)=>{
+    let totalHeight = e.target.scrollHeight  //总高度
+    let scrollTop = e.target.scrollTop   //滚动高度
+    let pageHeight = e.target.clientHeight // 客户端高度
+    console.log('totalHeight',totalHeight)
+    console.log('当前高度',scrollTop + pageHeight)
+
+    // 滚动到底部 且 页面还有数据
+    if(scrollTop + pageHeight >= (totalHeight - 5) && props?.totalNum > props?.pageSize){
+        emit('loadMorePage')
+    }
+}
+
+watch(()=>props.scrollAimDom,(newDom)=>{
+    console.log('新dom',newDom)
+    if(newDom){
+        newDom?.addEventListener('scroll',(e)=>HandleCourseScroll(e))
+    }
+},{immediate:true,flush:'post'})
+
 </script>
 
 
 <style lang="scss" scoped>
+
+
 /* 单个卡片样式 */
 .card_item {
     width: 325px; /* 固定宽度以匹配图片比例 */
@@ -256,4 +288,15 @@ const typeNumToName=(type:String|Number|null|undefined)=>{
         }
     }
 }
+
+.load_more{
+    text-align: center;
+    color: #999;
+    margin-top: 20px;
+    font-size: 14px;
+    &:hover{
+        cursor: pointer;
+    }
+}
+
 </style>

+ 81 - 42
src/views/reviewManagement/ReviewManagement.vue

@@ -1,5 +1,5 @@
 <template>
-    <div  ref="courseDom" class="main_container">
+    <div  ref="scrollDom" class="main_container">
         <div  class="page_item end_item">
             <div class="page_search">
                 <div class="search_content">
@@ -32,37 +32,36 @@
             <div class="page_jg_20"></div>
 
             <!-- 视图展示数据 -->
-            <div v-if="defaultViewMode == 'view' && questionnaireList?.length > 0" 
-                class="questionnaire_list">
-                <template  
-                    v-for="questionnaire in questionnaireList" 
-                    :key="questionnaire.id" 
-                >
-                    <QuestionnaireCard 
-                        :cardStatusMsg="reviewManageCardStatusMsg" 
-                        :cardTypeMsg="reviewManageTaskTypeMsg"
-                        :questionnaire="questionnaire"
-                        cardType="reviewManage"
-                        :showSwitch="questionnaire.evaluationType === 0 ? true : false"
-                        @switchOnOff="HandleCardSwitchOnOff"
-                    >
-                        <template #default="{row}">
-                            <el-button @click="GoToQuestionnaireReviewDetail(row)"  class="button_background">查看详情</el-button>
-                            <el-button 
-                                :class="['button_border']"
-                                @click="OpenQuestionnaireDialog(row)"    
-                            >编辑</el-button>
-
-                            <!-- row.status 0 可以删除/修改    1 不可以 删除/修改 -->
-                            <el-button 
-                                :class="[!row.status  ? 'delete_button_border' : 'is-disabled' ]"
-                                @click="!row.status  ? OpenDeleteDialog(row)  : '' "
-                            >删除</el-button>
-                        </template>
-                    </QuestionnaireCard>
+            <QuestionnaireCard 
+                v-if="defaultViewMode == 'view' && questionnaireList?.length > 0"
+                :questionnaireList="questionnaireList"
+                :cardStatusMsg="reviewManageCardStatusMsg" 
+                :cardTypeMsg="reviewManageTaskTypeMsg"
+                cardType="reviewManage"
+                @switchOnOff="HandleCardSwitchOnOff"
+
+                :pageSize="pageSize" 
+                :totalNum="totalNum"
+                :scrollAimDom="scrollDom"
+                @loadMorePage="LoadMoreQuestionnaireTaskList"
+
+
+
+            >
+                <template #default="{row}">
+                    <el-button @click="GoToQuestionnaireReviewDetail(row)"  class="button_background">查看详情</el-button>
+                    <el-button 
+                        :class="['button_border']"
+                        @click="OpenQuestionnaireDialog(row)"    
+                    >编辑</el-button>
+
+                    <!-- row.status 0 可以删除/修改    1 不可以 删除/修改 -->
+                    <el-button 
+                        :class="[!row.status  ? 'delete_button_border' : 'is-disabled' ]"
+                        @click="!row.status  ? OpenDeleteDialog(row)  : '' "
+                    >删除</el-button>
                 </template>
-                
-            </div>
+            </QuestionnaireCard>
             <!-- 列表展示数据 -->
             <Table v-else-if="defaultViewMode == 'list'"
                 :currentPage="currentPage" 
@@ -70,6 +69,7 @@
                 :totalNum="totalNum"
                 :tableData="questionnaireList"
                 :tableColumns="questionnaireTableColumns"
+                @paginationChange="HandlePaginationChange"
             >
                 <template #num="{currentIndex}">
                     {{ currentIndex + pageSize * (currentPage - 1)}}
@@ -199,7 +199,7 @@ interface QuestionnaireItm {
 const router = useRouter()
 
 // 1. 视图模式切换
-const defaultViewMode = ref('list')
+const defaultViewMode = ref('view')
 const  HandleTabChage = (val)=>{    
     console.log('当前模式',val)
     defaultViewMode.value = val
@@ -255,16 +255,9 @@ const currentPage = ref(1)
 const totalNum = ref(0)
 const pageSize = ref(20)
 const questionnaireList = ref<QuestionnaireItm[]>([]);
-// 问卷开关切换
-const HandleCardSwitchOnOff = async(params)=>{
-    console.log('当前传递的参数---params',params)
-    const {id,onOffVal} = params
-    let res = await oppenOrCloseQuestionnaireTaskApi(id,onOffVal ? 1 : 0)
-    if(res?.code == 200){
-        // 重新查询表列
-        await GetQuestionnaireTaskList()
-    }
-}
+const addMoreUnit = ref(10)  //加载更多时,每次添加的量
+const scrollDom = ref()  //目标滚动元素
+
 // 、获取问卷任务列表
 const GetQuestionnaireTaskList = async ()=>{
     console.log('获取到的查询参数',searchParams.value)
@@ -287,9 +280,55 @@ const GetQuestionnaireTaskList = async ()=>{
                 time:item.evaluationStartDatetime + ' 至 ' + item.evaluationEndDatetime
             }
         })
+        totalNum.value = res.data.total
+    }
+
+
+    // 获取完表格数据后,查看页面是否在滚动
+    let domTotalHeight = scrollDom.value?.scrollHeight || 0
+    let domClientHeight = scrollDom.value?.clientHeight || 0
+    // 如果初始高度没有占满,就加载更多内容
+    console.log('domTotalHeight',domTotalHeight,'domClientHeight',domClientHeight)
+
+    if(domTotalHeight <= domClientHeight && totalNum.value > pageSize.value){
+        console.log('emit-——more了')
+        await LoadMoreQuestionnaireTaskList()
     }
+
 }
 
+
+// 表格分页切换
+const HandlePaginationChange = async (params)=>{
+    const {type, val} = params
+    if(type == 'currentPage'){
+        currentPage.value = val
+        await GetQuestionnaireTaskList()
+    }
+}
+
+// 加载更多页面数据
+const LoadMoreQuestionnaireTaskList= async()=>{
+    if(defaultViewMode.value == 'view'){
+        pageSize.value += addMoreUnit.value
+        await GetQuestionnaireTaskList()
+    }
+}
+
+
+// 问卷开关切换
+const HandleCardSwitchOnOff = async(params)=>{
+    console.log('当前传递的参数---params',params)
+    const {id,onOffVal} = params
+    let res = await oppenOrCloseQuestionnaireTaskApi(id,onOffVal ? 1 : 0)
+    if(res?.code == 200){
+        // 重新查询表列
+        await GetQuestionnaireTaskList()
+    }
+}
+
+
+
 // 跳转问卷评价详情页
 const GoToQuestionnaireReviewDetail = (row)=>{
     router.push(`/main/reviewManagementDetail/evaluationData?id=${row.id}`)

+ 57 - 28
src/views/surveyManagement/SurveyManagement.vue

@@ -1,5 +1,5 @@
 <template>
-    <div  ref="courseDom" class="main_container">
+    <div  ref="scrollDom" class="main_container">
         <div  class="page_item end_item">
             <div class="page_search">
                 <div class="search_content">
@@ -23,32 +23,30 @@
             <div class="page_jg_20"></div>
 
             <!-- 视图展示数据 -->
-            <div v-if="defaultViewMode == 'view' && questionnaireList?.length > 0" 
-                class="questionnaire_list">
-                <template  
-                    v-for="questionnaire in questionnaireList" 
-                    :key="questionnaire.id" 
-                >
-                    <QuestionnaireCard 
-                        :questionnaire="questionnaire"
-                        :cardStatusMsg="surveyManagementCardStatusMsg"
-                        cardType="questionnareManage"
-                    >
-                        <template #default="{row}">
-                            <el-button 
-                                :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'button_background']"
-                                @click="Number(row.useStatus) === 1 ?  '' : GoToCreateQuestionnaire(row)"    
-                            >编辑</el-button>
-                            <el-button class="button_border" @click="GoToPreviewQuestionnaire(row)">预览</el-button>
-                            <el-button class="button_refresh" @click="CopyQuestionnaire(row)">复制</el-button>
-                            <el-button 
-                                :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'delete_button_border']"
-                                @click="Number(row.useStatus) === 1 ?  '' : OpenDeleteDialog(row)"
-                            >删除</el-button>
-                        </template>
-                    </QuestionnaireCard>
+            <QuestionnaireCard 
+                v-if="defaultViewMode == 'view' && questionnaireList?.length > 0"
+                :questionnaireList="questionnaireList"
+                :cardStatusMsg="surveyManagementCardStatusMsg"
+                cardType="questionnareManage"
+                :pageSize="pageSize" 
+                :totalNum="totalNum"
+                :scrollAimDom="scrollDom"
+                @loadMorePage="LoadMoreQuestionnaireList"
+
+            >
+                <template #default="{row}">
+                    <el-button 
+                        :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'button_background']"
+                        @click="Number(row.useStatus) === 1 ?  '' : GoToCreateQuestionnaire(row)"    
+                    >编辑</el-button>
+                    <el-button class="button_border" @click="GoToPreviewQuestionnaire(row)">预览</el-button>
+                    <el-button class="button_refresh" @click="CopyQuestionnaire(row)">复制</el-button>
+                    <el-button 
+                        :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'delete_button_border']"
+                        @click="Number(row.useStatus) === 1 ?  '' : OpenDeleteDialog(row)"
+                    >删除</el-button>
                 </template>
-            </div>
+            </QuestionnaireCard>
 
 
             <!-- 列表展示数据 -->
@@ -58,6 +56,7 @@
                 :totalNum="totalNum"
                 :tableData="questionnaireList"
                 :tableColumns="questionnaireTableColumns"
+                @paginationChange="HandlePaginationChange"
             >
                 <template #num="{currentIndex}">
                     {{ currentIndex + pageSize * (currentPage - 1)}}
@@ -131,7 +130,7 @@ interface QuestionnaireItm {
 const router = useRouter()
 
 // 1. 视图模式切换
-const defaultViewMode = ref('list')
+const defaultViewMode = ref('view')
 const  HandleTabChage = (val)=>{    
     defaultViewMode.value = val
 }
@@ -143,8 +142,10 @@ const currentPage = ref(1)
 const totalNum = ref(0)
 const pageSize = ref(20)
 const questionnaireList = ref<QuestionnaireItm[]>([]);
+const addMoreUnit = ref(10)  //加载更多时,每次添加的量
+const scrollDom = ref()  //目标滚动元素
 
-
+// 获取问卷列表数据
 const GetQuestionnaireList = async ()=>{
     let params = {
         pageNum:currentPage.value,
@@ -161,9 +162,37 @@ const GetQuestionnaireList = async ()=>{
                 title:itm.assessmentTitle,
             }
         })
+        totalNum.value = res.data.total
+    }
+
+    
+    // 获取完表格数据后,查看页面是否在滚动
+    let domTotalHeight = scrollDom.value?.scrollHeight || 0
+    let domClientHeight = scrollDom.value?.clientHeight || 0
+    // 如果初始高度没有占满,就加载更多内容
+    console.log('domTotalHeight',domTotalHeight,'domClientHeight',domClientHeight)
+
+    if(domTotalHeight <= domClientHeight && totalNum.value > pageSize.value){
+        console.log('emit-——more了')
+        await LoadMoreQuestionnaireList()
     }
 }
 
+// 表格分页切换
+const HandlePaginationChange = async (params)=>{
+    const {type, val} = params
+    if(type == 'currentPage'){
+        currentPage.value = val
+        await GetQuestionnaireList()
+    }
+}
+// 加载更多页面数据
+const LoadMoreQuestionnaireList= async()=>{
+    if(defaultViewMode.value == 'view'){
+        pageSize.value += addMoreUnit.value
+        await GetQuestionnaireList()
+    }
+}
 
 // 2. 跳转创建问卷 /修改文件 
 const GoToCreateQuestionnaire = (row?:any)=>{