Commit 615421ac by zhengxiao

feat(custom): 课程首页

parent 55fd03cc
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
<view class="course-list"> <view class="course-list">
<view <view
class="course-item"
v-for="(item, index) in showCourseList" v-for="(item, index) in showCourseList"
:key="index" :key="index"
class="course-item"
> >
<image <image
class="course-img" class="course-img"
...@@ -20,18 +20,22 @@ ...@@ -20,18 +20,22 @@
mode="aspectFill" mode="aspectFill"
/> />
<view class="course-info"> <view class="course-info">
<view class="course-title">{{item.title}}</view> <view class="course-title">{{ item.title }}</view>
<view class="course-desc">{{item.desc}}</view> <view class="course-desc">{{ item.desc }}</view>
<view class="course-meta"> <view class="course-meta">
<text class="enroll-count">{{item.enrollCount}}人已报名</text> <text class="enroll-count">{{ item.enrollCount }}人已报名</text>
<button class="study-btn">去学习</button> <button class="study-btn">去学习</button>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view v-if="courseList.length > 2" class="show-more" @tap="toggleShowMore"> <view
<text>{{isExpanded ? '收起合集' : '展开更多'}}</text> v-if="courseList.length > 2"
class="show-more"
@tap="toggleShowMore"
>
<text>{{ isExpanded ? '收起' : '展开更多' }}</text>
<text :class="['arrow', isExpanded ? 'up' : '']"></text> <text :class="['arrow', isExpanded ? 'up' : '']"></text>
</view> </view>
</view> </view>
...@@ -43,141 +47,153 @@ export default { ...@@ -43,141 +47,153 @@ export default {
props: { props: {
title: { title: {
type: String, type: String,
required: true required: true,
}, },
subtitle: { subtitle: {
type: String, type: String,
required: true required: true,
}, },
studyCount: { studyCount: {
type: Number, type: Number,
required: true required: true,
}, },
courseList: { courseList: {
type: Array, type: Array,
default: () => [] default: () => [],
} },
}, },
data() { data() {
return { return {
isExpanded: false isExpanded: false,
} }
}, },
computed: { computed: {
showCourseList() { showCourseList() {
return this.isExpanded ? this.courseList : this.courseList.slice(0, 2) return this.isExpanded ? this.courseList : this.courseList.slice(0, 2)
} },
}, },
methods: { methods: {
toggleShowMore() { toggleShowMore() {
this.isExpanded = !this.isExpanded this.isExpanded = !this.isExpanded
} },
} },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.section-block { .section-block {
margin: 20rpx; margin: 12px;
padding: 30rpx; padding: 12px 10px;
background: #fff; background: #fff;
border-radius: 16rpx; border-radius: 16px;
.block-header { .block-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: center;
margin-bottom: 24rpx; margin-bottom: 16px;
.left { .left {
.title { .title {
font-size: 32rpx; color: #242424;
font-weight: 500; font-weight: 600;
color: #333; font-size: 16px;
margin-bottom: 8rpx; margin-bottom: 1px;
display: block; display: block;
line-height: 22px;
} }
.desc { .desc {
font-size: 24rpx; color: #999999;
color: #999; font-weight: 400;
font-size: 12px;
line-height: 17px;
} }
} }
.study-count { .study-count {
font-size: 24rpx; display: flex;
color: #999; align-items: center;
background: #F5F6F8; border-radius: 13px;
padding: 8rpx 16rpx; background: linear-gradient(270deg, rgba(255, 244, 221, 1) 0%, rgba(255, 255, 255, 0) 100%);
border-radius: 20rpx; color: #B5985F;
font-weight: 400;
font-size: 12px;
padding: 5px 10px;
} }
} }
.course-list { .course-list {
.course-item { .course-item {
display: flex; display: flex;
padding: 24rpx 0; margin-bottom: 18px;
border-bottom: 1rpx solid #EBEDF0;
&:last-child { &:last-child {
border-bottom: none; margin-bottom: 0;
} }
.course-img { .course-img {
width: 160rpx; width: 64px;
height: 160rpx; height: 79px;
border-radius: 12rpx; margin-right: 8px;
margin-right: 20rpx; border-radius: 4px;
background: #F5F6F8; background-color: #d8d8d8;
} }
.course-info { .course-info {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between;
.course-title { .course-title {
font-size: 28rpx; color: #000000;
font-weight: 500; font-weight: 500;
color: #333; font-size: 14px;
margin-bottom: 8rpx; line-height: 20px;
// 单行
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.course-desc { .course-desc {
font-size: 24rpx; color: #000000;
color: #999; font-weight: 400;
margin-bottom: 20rpx; font-size: 12px;
line-height: 12px;
margin-top: 6px;
// 单行
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.course-meta { .course-meta {
flex: 1;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: flex-end;
.enroll-count { .enroll-count {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
display: flex; display: flex;
align-items: center; align-items: center;
&::before {
content: '';
display: inline-block;
width: 24rpx;
height: 24rpx;
// background: url('/static/icons/user.png') no-repeat center/cover;
margin-right: 8rpx;
}
} }
.study-btn { .study-btn {
font-size: 26rpx; margin: 0;
color: #666; display: flex;
background: #F5F6F8; align-items: center;
padding: 8rpx 24rpx; justify-content: center;
border-radius: 24rpx; width: 60px;
border: none; height: 25px;
border-radius: 12.5px;
background-color: rgba(0, 146, 255, 0.1);
color: #0092FF;
font-weight: 500;
font-size: 12px;
padding: 0;
} }
} }
} }
......
...@@ -2,12 +2,10 @@ ...@@ -2,12 +2,10 @@
<view class="container"> <view class="container">
<!-- 顶部搜索区域 - 添加安全区域 --> <!-- 顶部搜索区域 - 添加安全区域 -->
<view class="search-area"> <view class="search-area">
<!-- 使用微信小程序的胶囊高度适配 --> <!-- 使用计算后的总导航栏高度 -->
<view <view
class="status-bar" class="status-bar"
:style="{ :style="{ height: totalNavHeight + 'px' }"
height: statusBarHeight + 'px',
}"
></view> ></view>
<view class="search-tags"> <view class="search-tags">
<text class="tag">体系化专业课程</text> <text class="tag">体系化专业课程</text>
...@@ -46,7 +44,11 @@ ...@@ -46,7 +44,11 @@
<view class="vip-tips"> <view class="vip-tips">
<view class="left-content"> <view class="left-content">
<view class="tag-wrapper"> <view class="tag-wrapper">
<image class="tag-bg" src="/static/images/tag-bg.png" mode="aspectFit" /> <image
class="tag-bg"
src="/static/images/tag-bg.png"
mode="aspectFit"
/>
<text class="tag-text">免费资料</text> <text class="tag-text">免费资料</text>
</view> </view>
<view class="text-content"> <view class="text-content">
...@@ -63,10 +65,8 @@ ...@@ -63,10 +65,8 @@
<view class="career-section"> <view class="career-section">
<view class="section-header"> <view class="section-header">
<view class="title-wrapper"> <view class="title-wrapper">
<view class="title-bar"></view>
<text class="title">执业入驻</text> <text class="title">执业入驻</text>
</view> </view>
<text class="subtitle">心理咨询执业培养计划</text>
</view> </view>
<!-- 切换按钮组 --> <!-- 切换按钮组 -->
...@@ -77,39 +77,60 @@ ...@@ -77,39 +77,60 @@
:key="index" :key="index"
:class="['tab-item', currentTab === index ? 'active' : '']" :class="['tab-item', currentTab === index ? 'active' : '']"
@tap="switchTab(index)" @tap="switchTab(index)"
>{{ tab }}</view> >
{{ tab }}
</view> </view>
<view class="slider" :style="{ transform: `translateX(${currentTab * 100}%)` }"></view> </view>
<view
class="slider"
:style="{ transform: `translateX(${currentTab * 100}%)` }"
></view>
</view> </view>
<!-- 内容区域 --> <!-- 内容区域 -->
<swiper <swiper
class="content-swiper" class="content-swiper"
:current="currentTab" :current="currentTab"
:autoplay="true"
@change="handleSwiperChange" @change="handleSwiperChange"
> >
<swiper-item v-for="(tab, index) in tabs" :key="index"> <swiper-item
v-for="(tab, index) in tabs"
:key="index"
>
<view class="consultant-card"> <view class="consultant-card">
<view class="card-title">心理咨询师一对一从业规划</view> <!-- <view class="card-title">心理咨询师一对一从业规划</view>
<view class="card-subtitle">专业老师1v1教你入行</view> <view class="card-subtitle">专业老师1v1教你入行</view>
<view class="card-features"> <view class="card-features">
<view class="feature-item"> <view class="feature-item">
<image src="/static/icons/doc.png" mode="aspectFit" /> <image
src="/static/icons/doc.png"
mode="aspectFit"
/>
<text>入行资料</text> <text>入行资料</text>
</view> </view>
<view class="feature-item"> <view class="feature-item">
<image src="/static/icons/group.png" mode="aspectFit" /> <image
src="/static/icons/group.png"
mode="aspectFit"
/>
<text>社群加餐</text> <text>社群加餐</text>
</view> </view>
<view class="feature-item"> <view class="feature-item">
<image src="/static/icons/guide.png" mode="aspectFit" /> <image
src="/static/icons/guide.png"
mode="aspectFit"
/>
<text>学习指导</text> <text>学习指导</text>
</view> </view>
<view class="feature-item"> <view class="feature-item">
<image src="/static/icons/plan.png" mode="aspectFit" /> <image
src="/static/icons/plan.png"
mode="aspectFit"
/>
<text>职业规划</text> <text>职业规划</text>
</view> </view>
</view> </view> -->
<view class="card-footer"> <view class="card-footer">
<text class="footer-text">壹点灵成长规划师,1V1教你入行</text> <text class="footer-text">壹点灵成长规划师,1V1教你入行</text>
<button class="consult-btn">立即咨询</button> <button class="consult-btn">立即咨询</button>
...@@ -125,24 +146,24 @@ ...@@ -125,24 +146,24 @@
<course-block <course-block
title="权威证书" title="权威证书"
subtitle="收获成功道路的通行证" subtitle="收获成功道路的通行证"
:studyCount="2.1" :study-count="2.1"
:courseList="certificateList" :course-list="certificateList"
></course-block> ></course-block>
<!-- 咨询伦理系列 --> <!-- 咨询伦理系列 -->
<course-block <course-block
title="咨询伦理系列" title="咨询伦理系列"
subtitle="专业伦理规范指导" subtitle="专业伦理规范指导"
:studyCount="1.8" :study-count="1.8"
:courseList="ethicsList" :course-list="ethicsList"
></course-block> ></course-block>
<!-- 认知行为系列 --> <!-- 认知行为系列 -->
<course-block <course-block
title="认知行为系列" title="认知行为系列"
subtitle="CBT理论与实操" subtitle="CBT理论与实操"
:studyCount="1.8" :study-count="1.8"
:courseList="cbtList" :course-list="cbtList"
></course-block> ></course-block>
</view> </view>
</view> </view>
...@@ -154,7 +175,7 @@ import courseBlock from '@/components/course-block.vue' ...@@ -154,7 +175,7 @@ import courseBlock from '@/components/course-block.vue'
export default { export default {
name: 'HomePage', name: 'HomePage',
components: { components: {
courseBlock // 直接使用对象形式注册组件 courseBlock, // 直接使用对象形式注册组件
}, },
data() { data() {
return { return {
...@@ -163,26 +184,28 @@ export default { ...@@ -163,26 +184,28 @@ export default {
courseList: [], courseList: [],
bannerList: [], bannerList: [],
statusBarHeight: 0, statusBarHeight: 0,
currentTab: 1, // 默认选中"成为咨询师" navBarHeight: 0,
totalNavHeight: 0,
currentTab: 0,
tabs: ['入行分析', '成为咨询师', '咨询师进阶'], tabs: ['入行分析', '成为咨询师', '咨询师进阶'],
certificateList: [ certificateList: [
{ {
title: '社会心理服务中级·人社部能建中心', title: '社会心理服务中级·人社部能建中心',
desc: '解开关系中的结,告别恨、消耗...', desc: '解开关系中的结,告别恨、消耗...',
enrollCount: 3240, enrollCount: 3240,
image: '/static/images/course-placeholder.png' image: '/static/images/course-placeholder.png',
}, },
{ {
title: '社会心理服务中级·人社部能建中心', title: '社会心理服务中级·人社部能建中心',
desc: '解开关系中的结,告别恨、消耗...', desc: '解开关系中的结,告别恨、消耗...',
enrollCount: 3240, enrollCount: 3240,
image: '/static/images/course-placeholder.png' image: '/static/images/course-placeholder.png',
}, },
{ {
title: '社会心理服务中级·人社部能建中心', title: '社会心理服务中级·人社部能建中心',
desc: '解开关系中的结,告别恨、消耗...', desc: '解开关系中的结,告别恨、消耗...',
enrollCount: 3240, enrollCount: 3240,
image: '/static/images/course-placeholder.png' image: '/static/images/course-placeholder.png',
}, },
// ... 其他证书课程 // ... 其他证书课程
], ],
...@@ -191,7 +214,7 @@ export default { ...@@ -191,7 +214,7 @@ export default {
title: '咨询伦理基础课程', title: '咨询伦理基础课程',
desc: '建立专业伦理意识,提升职业素养...', desc: '建立专业伦理意识,提升职业素养...',
enrollCount: 2156, enrollCount: 2156,
image: '/static/images/course-placeholder.png' image: '/static/images/course-placeholder.png',
}, },
// ... 其他伦理课程 // ... 其他伦理课程
], ],
...@@ -200,17 +223,26 @@ export default { ...@@ -200,17 +223,26 @@ export default {
title: 'CBT理论基础与应用', title: 'CBT理论基础与应用',
desc: '认知行为疗法的核心理论与技术...', desc: '认知行为疗法的核心理论与技术...',
enrollCount: 1892, enrollCount: 1892,
image: '/static/images/course-placeholder.png' image: '/static/images/course-placeholder.png',
}, },
// ... 其他CBT课程 // ... 其他CBT课程
] ],
} }
}, },
onLoad() { onLoad() {
this.getCourseList() this.getCourseList()
// 获取系统信息设置状态栏高度 // 获取系统信息和胶囊按钮位置信息
const systemInfo = wx.getSystemInfoSync() const systemInfo = uni.getSystemInfoSync()
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
// 状态栏高度
this.statusBarHeight = systemInfo.statusBarHeight this.statusBarHeight = systemInfo.statusBarHeight
// 胶囊高度(包含上下边距)
this.navBarHeight =
(menuButtonInfo.top - systemInfo.statusBarHeight) * 2 + menuButtonInfo.height
// 总高度 = 状态栏高度 + 胶囊高度
this.totalNavHeight = this.statusBarHeight + this.navBarHeight
}, },
methods: { methods: {
getCourseList() { getCourseList() {
...@@ -224,15 +256,15 @@ export default { ...@@ -224,15 +256,15 @@ export default {
}, },
handleSwiperChange(e) { handleSwiperChange(e) {
this.currentTab = e.detail.current this.currentTab = e.detail.current
} },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.container { .container {
min-height: 100vh; min-height: 100vh;
background: #f5f5f5; background: #f0f2f4;
} }
.search-area { .search-area {
...@@ -279,7 +311,7 @@ export default { ...@@ -279,7 +311,7 @@ export default {
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.05); box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.05);
&.dark { &.dark {
background: #4A5B67; background: #4a5b67;
} }
} }
...@@ -344,7 +376,7 @@ export default { ...@@ -344,7 +376,7 @@ export default {
.action-text { .action-text {
font-size: 26rpx; font-size: 26rpx;
color: #666; color: #666;
background: #F5F6F8; background: #f5f6f8;
padding: 12rpx 24rpx; padding: 12rpx 24rpx;
border-radius: 30rpx; border-radius: 30rpx;
} }
...@@ -352,63 +384,57 @@ export default { ...@@ -352,63 +384,57 @@ export default {
} }
.career-section { .career-section {
margin: 20rpx; margin: 12px;
background: #fff; background: #fff;
border-radius: 16rpx; border-radius: 12px;
padding: 30rpx; padding: 12px;
.section-header { .section-header {
margin-bottom: 24rpx; margin-bottom: 12px;
.title-wrapper { .title-wrapper {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12rpx; margin-bottom: 9px;
margin-bottom: 8rpx;
.title-bar {
width: 6rpx;
height: 32rpx;
background: #333;
border-radius: 3rpx;
}
.title { .title {
font-size: 32rpx; font-size: 16px;
font-weight: 500; font-weight: 600;
color: #333; color: #242424;
} }
} }
.subtitle {
font-size: 24rpx;
color: #999;
}
} }
.career-tabs { .career-tabs {
position: relative; position: relative;
background: #F7F8FA; border-radius: 18px;
border-radius: 12rpx; // padding: 4px;
padding: 8rpx; margin-bottom: 10px;
margin-bottom: 24rpx; height: 36px;
background: #f2f2f8;
box-sizing: border-box;
.tab-items { .tab-items {
display: flex; display: flex;
position: relative; position: relative;
z-index: 1; z-index: 1;
align-items: center;
height: 36px;
box-sizing: border-box;
} }
.tab-item { .tab-item {
flex: 1; flex: 1;
text-align: center; text-align: center;
padding: 16rpx 0; color: #212123;
font-size: 28rpx; font-weight: 400;
color: #666; font-size: 13px;
position: relative; position: relative;
z-index: 2; z-index: 2;
transition: color 0.3s; transition: color 0.3s;
display: flex;
align-items: center;
justify-content: center;
&.active { &.active {
color: #333; color: #333;
font-weight: 500; font-weight: 500;
...@@ -417,14 +443,14 @@ export default { ...@@ -417,14 +443,14 @@ export default {
.slider { .slider {
position: absolute; position: absolute;
left: 8rpx; left: 4px;
top: 8rpx; top: 4px;
width: calc(33.33% - 6rpx); width: calc(33.33% - 3px);
height: calc(100% - 16rpx); height: calc(100% - 8px);
background: #fff; background: #fff;
border-radius: 8rpx; border-radius: 16px;
transition: transform 0.3s ease; transition: transform 0.3s ease;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
} }
} }
...@@ -433,71 +459,83 @@ export default { ...@@ -433,71 +459,83 @@ export default {
.consultant-card { .consultant-card {
height: 100%; height: 100%;
background: #F7F8FA; background: #f7f8fa;
border-radius: 12rpx; border-radius: 12rpx;
padding: 30rpx; // padding: 30rpx;
.card-title { // .card-title {
font-size: 36rpx; // font-size: 36rpx;
font-weight: bold; // font-weight: bold;
color: #333; // color: #333;
margin-bottom: 8rpx; // margin-bottom: 8rpx;
} // }
.card-subtitle { // .card-subtitle {
font-size: 26rpx; // font-size: 26rpx;
color: #666; // color: #666;
margin-bottom: 40rpx; // margin-bottom: 40rpx;
} // }
.card-features { // .card-features {
display: grid; // display: grid;
grid-template-columns: repeat(4, 1fr); // grid-template-columns: repeat(4, 1fr);
gap: 20rpx; // gap: 20rpx;
margin-bottom: 40rpx; // margin-bottom: 40rpx;
.feature-item { // .feature-item {
display: flex; // display: flex;
flex-direction: column; // flex-direction: column;
align-items: center; // align-items: center;
gap: 8rpx; // gap: 8rpx;
image { // image {
width: 64rpx; // width: 64rpx;
height: 64rpx; // height: 64rpx;
background: #fff; // background: #fff;
border-radius: 16rpx; // border-radius: 16rpx;
padding: 12rpx; // padding: 12rpx;
} // }
text { // text {
font-size: 24rpx; // font-size: 24rpx;
color: #666; // color: #666;
} // }
} // }
} // }
.card-footer { .card-footer {
position: absolute;
height: 51px;
width: calc(100% - 25px);
bottom: 18px;
left: 13px;
border-radius: 8px;
background-color: #ffffff;
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
background: #fff; justify-content: space-between;
padding: 24rpx; padding: 0 10px;
border-radius: 8rpx;
.footer-text { .footer-text {
font-size: 28rpx; color: #1e2842;
color: #333;
font-weight: 500; font-weight: 500;
font-size: 14px;
// 单行溢出隐藏
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.consult-btn { .consult-btn {
background: #333; height: 29px;
color: #fff; line-height: 29px;
font-size: 26rpx; border-radius: 8px;
padding: 12rpx 32rpx; background-color: #212123;
border-radius: 30rpx; min-width: 87px;
border: none; text-align: center;
padding: 0 10px;
color: #ffffff;
font-weight: 600;
font-size: 12px;
margin: 0;
} }
} }
} }
...@@ -536,7 +574,7 @@ export default { ...@@ -536,7 +574,7 @@ export default {
.study-count { .study-count {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
background: #F5F6F8; background: #f5f6f8;
padding: 8rpx 16rpx; padding: 8rpx 16rpx;
border-radius: 20rpx; border-radius: 20rpx;
} }
...@@ -546,7 +584,7 @@ export default { ...@@ -546,7 +584,7 @@ export default {
.course-item { .course-item {
display: flex; display: flex;
padding: 24rpx 0; padding: 24rpx 0;
border-bottom: 1rpx solid #EBEDF0; border-bottom: 1rpx solid #ebedf0;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
...@@ -557,7 +595,7 @@ export default { ...@@ -557,7 +595,7 @@ export default {
height: 160rpx; height: 160rpx;
border-radius: 12rpx; border-radius: 12rpx;
margin-right: 20rpx; margin-right: 20rpx;
background: #F5F6F8; background: #f5f6f8;
} }
.course-info { .course-info {
...@@ -603,7 +641,7 @@ export default { ...@@ -603,7 +641,7 @@ export default {
.study-btn { .study-btn {
font-size: 26rpx; font-size: 26rpx;
color: #666; color: #666;
background: #F5F6F8; background: #f5f6f8;
padding: 8rpx 24rpx; padding: 8rpx 24rpx;
border-radius: 24rpx; border-radius: 24rpx;
border: none; border: none;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment