2025-04-01 09:03:51 +08:00

904 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="center-box">
<view class="box flex justify-center align-items flex-column">
<view class="search flex align-items" style="width: 99%;">
<u-navbar :title="navbarTitle" :border="false" :placeholder="true" :autoBack="false" :is-back="false" :leftIcon="none">
<view class="" slot="center">
<u-search class="u-search" v-model="keywords" placeholder="请输入搜索内容" :showAction="false"
@change="search()"></u-search>
</view>
</u-navbar>
</view>
<!-- 推荐课程 -->
<view class="hot flex flex-column" :style="{ marginTop: capsuleHeight()}">
<view class="hot-top flex align-items ">
<image src="/static/index/Subtract.png" mode=""
style="width: 16rpx; height: 22rpx;margin: 0 8rpx 0 32rpx;"></image>
<span>优质课程陪您成长~</span>
</view>
<view class="content flex align-items" style="background: none;overflow-y: hidden;">
<view class=" ovr flex align-items" style="align-items: self-start;" v-for="(item,index) in Tjlist"
:key="index">
<view class="hot-center justify-start flex flex-column" style="align-items: flex-start;"
@click="detail(item.id)">
<image :src="item.headimage" mode=""
style="width: 308rpx; height: 168rpx;border-radius: 20rpx;"></image>
<span class="jita white-space">{{item.title}}</span>
<span class="price" v-if="item.feel == 0">¥{{item.price}}</span>
<span class="price" v-if="item.feel == 1">公益</span>
<view class="mingePos flex justify-center align-items">
<image src="/static/index/fire.png" mode=""
style="width: 22rpx;height: 24rpx;margin: 0 8rpx 0 12rpx;">
</image>
<span class="minge">{{ Number(item.sign_num + item.virtual_num)}} /
{{item.limit_num}}</span>
</view>
</view>
</view>
</view>
<!-- <view class="" v-else>
<u-empty mode="list" icon="http://cdn.uviewui.com/uview/empty/list.png">
</u-empty>
</view> -->
</view>
<!-- 标签 -->
<view class="tabs">
<view v-for="(tab, index) in list" :key="index" :class="['tab-item', { active: current === index }]"
@click="handleClick(index)">
{{ tab.name }}
</view>
</view>
<!-- 课程 -->
<view class="totalClass flex flex-column">
<!-- <view class="total-top flex align-items space-between">
<image src="../../static/center/TotalClass.png" mode="" style="width: 168rpx;height: 48rpx;">
</image>
</view> -->
<!-- <view v-if="LoadingShow" class="flex justify-center align-items" style="height: 300rpx;">
加载中...
</view> -->
<view class="totalBox flex align-items flex-column">
<view class="flex align-items flex-column w-100 bbb" v-for="(item,index) in hotList" :key="index"
@click="detail(item.id)">
<view class="top flex align-items" style="justify-content: space-around;margin-top: 24rpx;">
<view class="left">
<image :src="item.headimage" mode=""
style="width: 240rpx; height: 196rpx;border-radius: 12rpx 12rpx 12rpx 12rpx;">
</image>
</view>
<view class="right flex flex-column " style="align-items: self-start;">
<span class="title white-space">{{item.title}}</span>
<view class=" row flex flex align-items">
<span
class="remen flex justify-center align-items">{{item.classes_type_name}}</span>
<span
style="background: #FFF1ED;color: #FF4810;margin-left:8rpx; max-width: 170rpx;"
class="remen flex justify-center align-items">
<span class="white-space">{{item.shop.name}}</span>
</span>
</view>
<view class="flex flex-column pos">
<view class=" time flex align-items white-space">
<image src="../../static/index/clock.png" mode=""
style="width: 24rpx;height: 24rpx;"></image>
<span class="white-space" style="margin-left: 8rpx;">{{item.start_time_text}}
</span>
</view>
<view class="address flex align-items white-space">
<image src="../../static/index/address.png" mode=""
style="width: 24rpx;height: 24rpx;"></image>
<span class="white-space"
style="margin-left: 8rpx; width: 220rpx;">{{item.address_detail}}</span>
</view>
<span class=" ab flex align-items" v-if="item.feel == 0" style="">
<span class="m">¥</span>
<span class="money">{{item.price}}</span>
</span>
<span class="ab no flex align-items" v-if="item.feel == 1">公益</span>
</view>
</view>
</view>
<span style="width: 626rpx;height: 2rpx;background: #EEEEEE;margin: 32rpx 0 0 0;"></span>
<view class="bottom flex align-items">
<view class="flex align-items">
<span class="flex align-items" style="width: 200rpx;">
<u-avatar-group :urls="item.unpaid_user_data"
:extraValue="item.unpaid_user_data.length - 5" keyName="head_image" size="24"
gap="0.4"></u-avatar-group>
</span>
<view class="number flex align-items">
{{'已报名: ' + Number(item.sign_num + item.virtual_num)}}/{{item.limit_num}}
</view>
</view>
<span class="part flex justify-center align-items">
报名参加
</span>
</view>
</view>
</view>
<!-- <view class="" v-else>
<u-empty mode="list" icon="http://cdn.uviewui.com/uview/empty/list.png">
</u-empty>
</view> -->
<view class="more flex flex-column align-items">
<span class="line-lone"></span>
<span class="line-erect"></span>
</view>
</view>
<view class="footer flex">
<u-loadmore :status="loadStatus" />
</view>
</view>
<tab-bar :tabBarShow="1"></tab-bar>
</view>
</template>
<script>
// import FilterMenu from "./myFilterMenu/index.vue"
// import {menuOption} from "@/common/menuOptions.js"
import {
updateStaticData
} from '@/common/data.js';
export default {
// components: {
// FilterMenu
// },
data() {
return {
value1: 1,
options1: [{
label: '默认排序',
value: 1,
},
{
label: '距离优先',
value: 2,
},
{
label: '价格优先',
value: 3,
}
],
selectedLabel: '选项1',
selectedValue: 1,
searchValue: '',
value: 0,
range: [{
value: 0,
text: "篮球"
},
{
value: 1,
text: "足球"
},
{
value: 2,
text: "游泳"
},
],
list: [{
name: '全部课程'
},
{
name: '文化艺术'
},
{
name: '职业发展'
},
{
name: '社会融入'
},
{
name: '形势政策'
},
],
current: 0,
menuOption: {},
unread_number: '',
listQuery: {
priceStart: '',
priceEnd: ''
},
LoadingShow: true,
page: 1,
limit: 10,
tjShow: true,
keywords: '',
hotList: [],
Tjlist: [],
staticData: [],
loadStatus: 'loading',
district: '', //县区
classes_label_ids: '', //热门
classes_cate_ids: '', //标签
classes_type: '14,15,16,17', //类型
last_page: 0
}
},
onLoad() {
uni.hideTabBar()
},
onShow() {
this.resetLists()
// this.fetchAndUpdateStaticData()
this.getTjlList()
this.getTotalList()
},
onReachBottom() {
if (this.page < this.last_page) {
this.page++;
this.getTotalList();
}
},
methods: {
handleDropdownChange(value) {
const selectedItem = this.menuList.find(item => item.value === value);
if (selectedItem) {
this.selectedLabel = selectedItem.label;
this.selectedValue = selectedItem.value;
}
},
// 获取胶囊高度
capsuleHeight() {
console.log(uni.getMenuButtonBoundingClientRect())
if (uni?.getMenuButtonBoundingClientRect()) {
return `${uni.getMenuButtonBoundingClientRect().height + uni.getMenuButtonBoundingClientRect().top + 26}rpx`;
} else {
return `180rpx`;
}
},
handleClick(index) {
this.current = index;
if (index == 0) {
this.classes_type = "14,15,16,17"
} else if (index == 1) {
this.classes_type = '15'
} else if (index == 2) {
this.classes_type = '16'
} else if (index == 3) {
this.classes_type = '17'
} else if (index == 3) {
this.classes_type = '14'
}
this.hotList = []
this.getTotalList()
},
handleSearch(value) {
this.keywords = value
this.search()
},
// 重置列表
resetLists() {
this.page = 1;
this.hotList = []
this.loadStatus = 'loading'
},
// 搜索
search() {
if (this.keywords == '') {
this.tjShow = true
} else {
this.tjShow = false
}
this.resetLists()
this.getTotalList()
},
// 获取报名详情
getPeople(id) {
return uni.$u.http.get('/api/school/classes/people', {
params: {
id: id,
have_real: 1
}
}).then(res => {
if (res.code == 1) {
return res.data.unpaid_user_data;
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
throw new Error(res.msg); // 抛出错误以便 catch 捕获
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
throw error; // 抛出错误以便 catch 捕获
});
},
// 全部课程
getTotalList() {
uni.$u.http.get('/api/school/classes/classes_list', {
params: {
page: this.page,
limit: this.limit,
order: 'normal',
has_shop: 1,
is_expire: 2,
keywords: this.keywords,
district: this.district, //县区
// classes_label_ids: this.classes_label_ids, //热门
// classes_cate_ids: this.classes_cate_ids, //标签
classes_type: this.classes_type //类型
}
}).then(res => {
if (res.code == 1) {
// setTimeout(() => {
// this.LoadingShow = false; // 数据加载完成关闭loading
// }, 100); // 模拟2秒的加载时间
this.last_page = res.data.list.last_page
const dataLiat = [...this.hotList, ...res.data.list.data]
const promises = dataLiat.map(item => {
return this.getPeople(item.id).then(peopleData => {
item.unpaid_user_data = peopleData;
}).catch(error => {
console.error(`Failed to get people data for id ${item.id}:`,
error);
});
});
// 等待所有异步操作完成
Promise.all(promises).then(() => {
this.hotList = dataLiat;
}).catch(error => {
console.error('Error in fetching people data:', error);
});
this.loadStatus = this.hotList.length >= res.data.list.total ? 'nomore' :
'loading';
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
this.loadStatus = 'nomore';
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
this.loadStatus = 'nomore';
});
},
// 获取推荐课程
getTjlList() {
uni.$u.http.get('/api/school/classes/classes_list', {
params: {
page: 1,
limit: 10,
order: 'recommend',
is_expire: 2
}
}).then(res => {
if (res.code == 1) {
this.Tjlist = res.data.list.data
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
resethandle(index) {
this.listQuery = {}
},
jump() {
uni.navigateTo({
url: '/pages/center/list',
success: res => {},
fail: () => {},
complete: () => {}
});
},
detail(id) {
uni.navigateTo({
url: "/pages/center/detail?id=" + id
})
},
onClickMenuIndex(props) {
console.log('onClickMenuIndex', props)
},
//关闭
onClose(e) {
console.log('onClose', e)
},
onOpen() {
console.log('onOpen')
},
//确认搜索
onSearch(e) {
console.log('onSearch', e)
},
handleConfirm(data) {
console.log('确认选择的数据:', data);
this.classes_cate_ids = data.classes_cate_ids.join(',')
this.classes_label_ids = data.classes_label_ids.join(',')
this.district = data.district.join(',')
this.classes_type = data.classes_type.join(',')
this.resetLists()
this.getTotalList()
// 进一步处理 selectedData
// 例如,发送到服务器或更新本地状态
}
}
}
</script>
<style lang="scss" scoped>
.center-box {
width: 750rpx;
min-height: 100vh;
background: #F2F2F2;
}
.box {
width: 690rpx;
padding: 0 30rpx 0rpx 30rpx;
border-radius: 0px 0px 0px 0px;
}
.white-space {
overflow: hidden;
/* 确保超出容器的文本被隐藏 */
white-space: nowrap;
/* 确保文本在一行内显示 */
text-overflow: ellipsis;
/* 使用省略号表示被截断的文本 */
width: 100%;
}
.search {
margin-top: 27rpx;
width: 690rpx;
height: 64rpx;
background: #FFFFFF;
// box-shadow: 2rpx 2rpx 0rpx 0rpx rgba(0, 0, 0, 0.4);
// border-radius: 8rpx 8rpx 8rpx 8rpx;
// border: 2rpx solid #008CFF;
.dashed {
image {
width: 52rpx;
height: 52rpx;
}
}
.line-search {
width: 2rpx;
height: 42rpx;
background: #008CFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
}
.input {
// border: 4rpx solid #EAEAEA;
padding-left: 12rpx;
height: 100%;
width: 78%;
}
/deep/ .input-placeholder {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #C0C0C0;
line-height: 32rpx;
text-align: left;
font-style: normal;
text-transform: none;
}
.searchBtn {
width: 128rpx;
height: 64rpx;
background: #008CFF;
border-radius: 5rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
display: flex;
justify-content: center;
align-items: center;
}
}
.w-100 {
width: 100%;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.align-items {
align-items: center;
}
.flex-column {
flex-flow: column;
}
.justify-start {
justify-content: start;
}
.hot {
width: 100%;
}
.totalClass {
width: 100%;
.total-top {
padding-bottom: 12rpx;
border-bottom: 2rpx solid #008CFF;
}
}
.totalBox {
// height: 462rpx;
// overflow-x: auto;
/* 允许横向滚动 */
// white-space: nowrap;
width: 690rpx;
.bbb {
background: #FFFFFF;
margin-top: 24rpx;
border-radius: 20rpx;
}
.right {
margin-left: 24rpx;
width: 338rpx;
.title {
width: 338rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 800;
font-size: 34rpx;
color: #343434;
}
.row {
margin: 10rpx 0 26rpx 0;
.remen {
// width: 136rpx;
height: 40rpx;
background: #EBFAF5;
border-radius: 4rpx 4rpx 4rpx 4rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #14BC84;
line-height: 28rpx;
padding: 2rpx 8rpx;
}
.line-colum {
width: 1rpx;
height: 32rpx;
background: #7A7A7A;
margin: 0 13rpx;
}
.name {
width: 110rpx;
height: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 26rpx;
color: #7A7A7A;
line-height: 32rpx;
margin-left: 12rpx;
}
}
.line-row {
width: 338rpx;
height: 1rpx;
background: #E4E4E4;
}
.jigou {
width: 312rpx;
// height: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 26rpx;
color: #7A7A7A;
margin: 4rpx 0 14rpx 0;
}
.time {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 26rpx;
color: #A4A4A4;
line-height: 30rpx;
}
.address {
width: 350rpx;
height: 40rpx;
margin-top: 8rpx;
span {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 26rpx;
color: #A4A4A4;
line-height: 30rpx;
}
}
}
.bottom {
margin: 32rpx 0 32rpx 0;
width: 626rpx;
.number {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 26rpx;
color: #222222;
line-height: 30rpx;
width: 242rpx;
margin-left: 42rpx;
}
.text {
font-family: PingFang SC, PingFang SC;
font-weight: 800;
font-size: 26rpx;
color: #7A7A7A;
}
.money {
width: 150rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 800;
font-size: 36rpx;
color: #FF2323;
justify-content: flex-end;
}
}
.ovr {
width: 312rpx;
background: #FFFFFF;
border-radius: 20rpx 20rpx 20rpx 20rpx;
margin-top: 18rpx;
margin-right: 24rpx;
}
}
.more {
margin-top: 62rpx;
.line-lone {
width: 260rpx;
height: 1rpx;
background: #008CFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
}
.line-erect {
margin-top: 16rpx;
width: 80rpx;
height: 1rpx;
background: #008CFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
}
}
.hot {
.hot-top {
width: 278rpx;
height: 44rpx;
background: linear-gradient(90deg, #FDF850 0%, #85EE9C 100%);
border-radius: 200rpx 200rpx 200rpx 200rpx;
span {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #000000;
}
}
.ovr {
width: 308rpx;
height: 304rpx;
background: #FFFFFF;
border-radius: 16rpx 16rpx 16rpx 16rpx;
margin-right: 30rpx;
}
.content {
margin-top: 30rpx;
}
.jita {
width: 244rpx;
height: 44rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 30rpx;
color: #000000;
margin: 24rpx 32rpx 8rpx 32rpx;
}
.price {
width: 212rpx;
height: 36rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #FF4810;
margin-left: 32rpx;
}
.hot-center {
position: relative;
}
.mingePos {
min-width: 118rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.7);
border-radius: 8rpx 8rpx 8rpx 8rpx;
position: absolute;
top: 40%;
right: 3%;
display: flex;
align-items: center;
span {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #FFFFFF;
}
}
}
.footer {
margin: 120rpx 0 40rpx 0;
font-weight: 500;
font-size: 24rpx;
color: #BCBCBC;
line-height: 32rpx;
}
.u-search {
display: flex;
flex-direction: row;
align-items: center;
}
.tabs {
display: flex;
overflow-x: auto;
margin-top: 64rpx;
-webkit-overflow-scrolling: touch;
/* 优化滚动效果 */
}
.tab-item {
flex: 0 0 auto;
text-align: center;
margin-right: 40rpx;
position: relative;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 30rpx;
color: #222222;
}
.tab-item.active {
background-image: url("/static/center/footer.png");
background-repeat: no-repeat;
background-position: bottom;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 32rpx;
color: #222222;
}
.pos {
position: relative;
.ab {
position: absolute;
right: 0%;
bottom: 0%;
}
.m {
width: 28rpx;
height: 42rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 28rpx;
color: #FF4810;
}
.money {
width: 68rpx;
font-family: D-DIN-PRO, D-DIN-PRO;
font-weight: bold;
font-size: 36rpx;
color: #FF4810;
}
.no {
width: 64rpx;
height: 48rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 32rpx;
color: #FF4810;
line-height: 38rpx;
}
}
.part {
width: 176rpx;
height: 64rpx;
background: #BEEE03;
border-radius: 200rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 28rpx;
color: #222222;
line-height: 33rpx;
}
</style>