| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- <template>
- <div class="app-container">
- <!-- 没有数据提示 -->
- <div v-if="campList.length === 0 && !leftLoading" class="no-data">
- <span>—— 没有数据 ——</span>
- </div>
- <el-container v-else>
- <!-- 左侧区域 -->
- <el-aside width="360px" class="left-aside">
- <!-- 顶部区域 -->
- <!-- 训练营列表 -->
- <div class="camp-list" ref="campList" @scroll="handleScroll" v-loading="leftLoading">
- <div
- v-for="(item, index) in campList"
- :key="index"
- class="camp-item"
- :class="{ 'active': activeCampIndex === index }"
- @click="selectCamp(index)"
- >
- <div class="camp-content">
- <div class="camp-title">
- <i class="el-icon-s-flag camp-icon"></i>
- {{ item.trainingCampName }}
- </div>
- <div class="camp-info">
- <span>序号:{{ item.orderNumber }}</span>
- <span>最新营期开课:{{ item.recentDate || '-' }}</span>
- </div>
- </div>
- </div>
- <!-- 底部加载更多提示 -->
- <div v-if="loadingMore" class="loading-more">
- <i class="el-icon-loading"></i>
- <span>加载中...</span>
- </div>
- <!-- 所有数据加载完毕提示 -->
- <div v-if="campList.length > 0 && !loadingMore" class="no-more-data">
- <span>—— 已加载全部训练营 ——</span>
- </div>
- </div>
- </el-aside>
- <!-- 右侧区域 -->
- <el-main><userCourseStatic ref="userCourseStatic" /></el-main>
- </el-container>
- </div>
- </template>
- <script>
- import { listCamp} from "@/api/course/userCourseCamp";
- import userCourseStatic from './userCourseStatic.vue';
- export default {
- name: "userCoursePeriod",
- components: {
- userCourseStatic
- },
- data() {
- return {
- // 加载更多状态
- loadingMore: false,
- // 激活的训练营索引
- activeCampIndex: null,
- // 训练营列表
- campList: [],
- // 遮罩层
- loading: true,
- updateDateOpen: false,
- // 左侧遮罩层
- leftLoading: true,
- // 左侧查询参数
- leftQueryParams: {
- pageNum: 1,
- pageSize: 10,
- hasNextPage: false,
- scs: 'order_number(desc),training_camp_id(desc)',
- trainingCampName: null,
- userId:null,
- },
- };
- },
- created() {
- // this.getLeftList();
- },
- methods: {
- getDetails(orderId) {
- this.userId=orderId;
- this.leftQueryParams.userId=orderId;
- this.getLeftList();
- },
- /** 查询左侧列表 */
- getLeftList() {
- this.leftLoading = true;
- // 重置页码和加载更多状态
- this.leftQueryParams.pageNum = 1;
- this.loadingMore = false;
- // 训练营数据
- listCamp(this.leftQueryParams).then(response => {
- if (response && response.code === 200) {
- this.campList = response.data.list || [];
- this.leftQueryParams.hasNextPage = response.data.hasNextPage;
- this.activeCampIndex = this.campList.length > 0 ? 0 : null;
- this.selectCamp(this.activeCampIndex);
- // 如果当前显示的列表高度不足以触发滚动,但还有更多数据,自动加载下一页
- this.$nextTick(() => {
- const scrollEl = this.$refs.campList;
- if (scrollEl && this.leftQueryParams.hasNextPage && scrollEl.scrollHeight <= scrollEl.clientHeight) {
- this.loadMoreCamps();
- }
- });
- } else {
- this.$message.error(response.msg || '获取训练营列表失败');
- this.campList = [];
- this.leftQueryParams.hasNextPage = false;
- }
- this.leftLoading = false;
- }).catch(error => {
- console.error('获取训练营列表失败:', error);
- this.$message.error('获取训练营列表失败');
- this.campList = [];
- this.leftQueryParams.hasNextPage = false;
- this.leftLoading = false;
- });
- },
- /** 选中训练营 */
- selectCamp(index) {
- if(index == null || index == undefined) return;
- this.activeCampIndex = index;
- // 加载对应的训练营营期数据
- const selectedCamp = this.campList[index];
- console.log(this.userId)
- this.$refs.userCourseStatic.getDetails(selectedCamp,this.userId);
- // this.queryParams.trainingCampId = selectedCamp.trainingCampId;
- // this.getList();
- },
- /** 处理滚动事件,实现滚动到底部加载更多 */
- handleScroll() {
- // 如果正在节流中或者正在加载中,则不处理
- if (this.scrollThrottle || this.loadingMore) return;
- // 设置节流,200ms内不再处理滚动事件
- this.scrollThrottle = true;
- setTimeout(() => {
- this.scrollThrottle = false;
- }, 200);
- const scrollEl = this.$refs.campList;
- if (!scrollEl) return;
- // 判断是否滚动到底部:滚动高度 + 可视高度 >= 总高度 - 30(添加30px的容差,提前触发加载)
- const isBottom = scrollEl.scrollTop + scrollEl.clientHeight >= scrollEl.scrollHeight - 30;
- // 如果滚动到底部,且有下一页数据,且当前不在加载中,则加载更多
- if (isBottom && this.leftQueryParams.hasNextPage && !this.leftLoading && !this.loadingMore) {
- this.loadMoreCamps();
- }
- },
- /** 加载更多训练营数据 */
- loadMoreCamps() {
- // 已在加载中,防止重复加载
- if (this.leftLoading || this.loadingMore) return;
- // 设置加载状态
- this.loadingMore = true;
- // 页码加1
- this.leftQueryParams.pageNum += 1;
- // 加载下一页数据
- listCamp(this.leftQueryParams).then(response => {
- if (response && response.code === 200) {
- // 将新数据追加到列表中
- const newList = response.data.list || [];
- if (newList.length > 0) {
- this.campList = [...this.campList, ...newList];
- }
- // 更新是否有下一页的标志
- this.leftQueryParams.hasNextPage = response.data.hasNextPage;
- // 如果当前显示的列表高度不足以触发滚动,但还有更多数据,自动加载下一页
- this.$nextTick(() => {
- const scrollEl = this.$refs.campList;
- if (scrollEl && this.leftQueryParams.hasNextPage && scrollEl.scrollHeight <= scrollEl.clientHeight) {
- // 延迟一点再加载下一页,避免过快加载
- setTimeout(() => {
- this.loadMoreCamps();
- }, 300);
- }
- });
- } else {
- this.$message.error(response.msg || '加载更多训练营失败');
- }
- this.loadingMore = false;
- }).catch(error => {
- console.error('加载更多训练营失败:', error);
- this.$message.error('加载更多训练营失败');
- this.loadingMore = false;
- });
- },
- },
- };
- </script>
- <style scoped>
- .left-aside {
- background-color: #fff;
- border-right: 1px solid #EBEEF5;
- padding: 0;
- display: flex;
- flex-direction: column;
- height: 800px;
- }
- .left-header {
- padding: 10px;
- border-bottom: 1px solid #EBEEF5;
- }
- .left-header-top {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 10px;
- }
- .search-btn {
- width: 50%;
- height: 36px;
- background-color: #409EFF;
- color: white;
- border: none;
- }
- .search-input-wrapper {
- margin-bottom: 10px;
- }
- .sort-wrapper {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- }
- .sort-label {
- width: 70px;
- font-size: 14px;
- font-weight: 600;
- color: #909399;
- }
- .sort-select {
- margin-left: 10px;
- width: 280px;
- }
- .color-wrapper {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- }
- .color-label {
- width: 70px;
- color: #606266;
- }
- .color-hint {
- margin-left: 10px;
- color: #606266;
- font-size: 12px;
- }
- .color-help {
- margin-left: 5px;
- color: #909399;
- cursor: pointer;
- }
- .hint-text {
- color: #606266;
- font-size: 12px;
- margin-top: 5px;
- }
- .camp-list {
- flex: 1;
- overflow-y: auto;
- padding: 3px;
- }
- .camp-item {
- margin-bottom: 5px;
- padding: 15px;
- background-color: #ffffff;
- position: relative;
- cursor: pointer;
- display: flex;
- justify-content: space-between;
- border: 1px solid #eaedf2;
- }
- .camp-item:last-child {
- margin-bottom: 0;
- }
- .camp-item:hover {
- background-color: #f5f9ff;
- }
- .camp-item.active {
- background-color: #eaf4ff;
- border-left: 1px solid #75b8fc;
- }
- .camp-content {
- flex: 1;
- padding-right: 10px;
- }
- .camp-title {
- font-weight: bold;
- font-size: 16px;
- margin-bottom: 8px;
- color: #333;
- display: flex;
- align-items: center;
- }
- .camp-icon {
- font-size: 16px;
- margin-right: 6px;
- color: #409EFF;
- }
- .camp-info {
- display: flex;
- justify-content: space-between;
- margin-bottom: 8px;
- font-size: 12px;
- color: #c4c1c1;
- line-height: 1.5;
- }
- .camp-stats {
- display: flex;
- justify-content: space-between;
- font-size: 12px;
- color: #666;
- background-color: #f5f9ff;
- padding: 6px 10px;
- border-radius: 4px;
- line-height: 1.5;
- }
- .stat-item {
- display: flex;
- align-items: center;
- }
- .stat-item i {
- margin-right: 4px;
- font-size: 14px;
- color: #409EFF;
- }
- .camp-actions {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: flex-end;
- gap: 8px;
- border-left: 1px dashed #eaedf2;
- padding-left: 12px;
- min-width: 50px;
- }
- .action-btn {
- padding: 2px 5px;
- font-size: 12px;
- border-radius: 4px;
- transition: all 0.2s;
- }
- .action-btn:hover {
- background-color: rgba(255, 255, 255, 0.8);
- }
- .delete-btn {
- color: #f56c6c;
- }
- .delete-btn:hover {
- background-color: rgba(245, 108, 108, 0.1);
- }
- .copy-btn {
- color: #409EFF;
- }
- .copy-btn:hover {
- background-color: rgba(64, 158, 255, 0.1);
- }
- .warning-icon {
- color: #E6A23C;
- font-size: 16px;
- margin-left: 5px;
- }
- .el-main {
- padding: 10px;
- }
- /* 添加训练营表单样式 */
- .drawer-footer {
- /* position: absolute; */
- bottom: 0;
- left: 0;
- right: 0;
- padding: 20px;
- background: #fff;
- text-align: right;
- border-top: 1px solid #e8e8e8;
- }
- .el-input-number {
- width: 100%;
- }
- /* 加载更多样式 */
- .loading-more {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 12px 0;
- color: #909399;
- font-size: 14px;
- }
- .loading-more i {
- margin-right: 5px;
- font-size: 16px;
- }
- /* 无更多数据提示 */
- .no-more-data {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 12px 0;
- color: #c0c4cc;
- font-size: 13px;
- }
- .no-more-data span {
- position: relative;
- display: flex;
- align-items: center;
- }
- /* 添加没有数据提示的样式 */
- .no-data {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh; /* 让提示居中,覆盖整个页面 */
- font-size: 18px;
- color: #c0c4cc;
- background-color: #f5f5f5;
- }
- </style>
|