feat: ai陪练样式

This commit is contained in:
杨航
2025-10-30 14:09:55 +08:00
parent 0c553b0b26
commit f00bfcd21a
9 changed files with 1004 additions and 80 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ ENV = 'development.yh'
VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
# VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
+5 -5
View File
@@ -70,7 +70,7 @@
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.course-item-box {
padding:12rpx 15rpx 8rpx;
overflow: hidden;
@@ -135,8 +135,8 @@
box-sizing: border-box;
font-size: 20rpx;
background-color: #fff;
color: #ffa150;
border: 2rpx solid #ffa150;
color: #06f;
border: 2rpx solid #06f;
padding: 0 20rpx;
border-radius: 8rpx;
margin-right: 20rpx;
@@ -148,8 +148,8 @@
box-sizing: border-box;
&.active-tag {
background-color: #ffa150;
color: #fff;
// background-color: #ffa150;
color: #ffa150;
border: 2rpx solid #ffa150;
}
}
+10 -1
View File
@@ -378,7 +378,7 @@
{
"path": "pages/pointsAndRank/badge",
"style": {
"navigationBarTitleText": "徽章列表",
"navigationBarTitleText": "徽章",
"app-plus": {
"titleNView": false
}
@@ -438,6 +438,15 @@
"animationType": "fade-in"
}
}
},
{
"path": "pages/sparring/index",
"style": {
"navigationBarTitleText": "AI陪练",
"app-plus": {
"titleNView": false
}
}
}
],
"tabBar": {
+16 -8
View File
@@ -26,8 +26,14 @@
showFilterList = !showFilterList
activeTagPop = activeTag
}
">筛选
<uv-icon class="filter-icon" name="list" />
">
<!-- 筛选 -->
<!-- <uv-icon class="filter-icon" name="list" /> -->
<image
class="filter-icon"
src="@/static/images/course/filter.png"
></image>
</view>
<view :class="['filter-list', showFilterList ? 'show' : '']">
<scroll-view :scroll-y="true" class="scroll-box-tags">
@@ -577,10 +583,10 @@
.tabs-view {
background: #ffffff;
margin-top: 23rpx;
margin-top: 8rpx;
border-radius: 23rpx;
padding: 6rpx 10rpx 12rpx;
margin-bottom: 15rpx;
// margin-bottom: 15rpx;
}
.list-view {
@@ -716,7 +722,7 @@
right: 0;
top: 0;
height: 83rpx;
width: 120rpx;
width: 80rpx;
line-height: 83rpx;
font-size: 26rpx;
background: #fff;
@@ -724,14 +730,16 @@
text-align: center;
box-shadow: -4rpx 0 6rpx rgba(0, 0, 0, 0.05);
white-space: nowrap;
padding-right: 30rpx;
// padding-right: 30rpx;
box-sizing: border-box;
.filter-icon {
// display: inline-block;
width: 32rpx;
height: 32rpx;
font-size: 26rpx;
position: absolute;
right: 15rpx;
right: 24rpx;
top: 50%;
transform: translateY(-50%);
}
@@ -740,7 +748,7 @@
.tags-view {
height: 84rpx;
display: block;
padding: 15rpx 120rpx 15rpx 20rpx;
padding: 15rpx 80rpx 15rpx 20rpx;
box-sizing: border-box;
white-space: nowrap;
border-bottom: 2rpx solid #eee;
+68 -65
View File
@@ -6,15 +6,8 @@
<image src="@/static/images/index/bg.png" class="bg_img"></image>
<view class="fixed_search_div" v-show="opacity" :style="{ opacity: opacity }">
<view class="fixed_search_input_div" @click="goto_search_page">
<uv-input
shape="circle"
:customStyle="fixedCustomStyles"
placeholderStyle="color:#999999;font-size:26rpx"
placeholder="请输入关键字"
suffixIcon="search"
:suffixIconStyle="suffixIconStyle"
:readonly="true"
></uv-input>
<uv-input shape="circle" :customStyle="fixedCustomStyles" placeholderStyle="color:#999999;font-size:26rpx"
placeholder="请输入关键字" suffixIcon="search" :suffixIconStyle="suffixIconStyle" :readonly="true"></uv-input>
</view>
<view class="message_div" @click="common.navigateTo('/pages/messageNotification/index')">
<image src="@/static/images/index/message_b.png" class="message_img"></image>
@@ -31,16 +24,9 @@
</view>
<!-- 搜索框 -->
<view class="search_div">
<uv-input
shape="circle"
@click="goto_search_page"
:customStyle="customStyles"
:placeholderStyle="placeholderStyle"
placeholder="请输入关键字"
suffixIcon="search"
:suffixIconStyle="suffixIconStyle"
:readonly="true"
></uv-input>
<uv-input shape="circle" @click="goto_search_page" :customStyle="customStyles"
:placeholderStyle="placeholderStyle" placeholder="请输入关键字" suffixIcon="search"
:suffixIconStyle="suffixIconStyle" :readonly="true"></uv-input>
<view class="message_div" @click="common.navigateTo('/pages/messageNotification/index')">
<image src="@/static/images/index/message.png" class="message_img"></image>
<view class="message_text">消息</view>
@@ -72,37 +58,24 @@
<view class="item">
<view class="top">本年学习时长</view>
<view class="bottom">
<uv-count-to
:startVal="statistics_data['startStdtTmLen']"
:endVal="statistics_data['stdtTmLen']"
:useEasing="true"
:decimals="1"
ref="stdtTmLenRef"
></uv-count-to>
<uv-count-to :startVal="statistics_data['startStdtTmLen']" :endVal="statistics_data['stdtTmLen']"
:useEasing="true" :decimals="1" ref="stdtTmLenRef"></uv-count-to>
h
</view>
</view>
<view class="item">
<view class="top">本年陪练次数</view>
<view class="bottom">
<uv-count-to
:startVal="statistics_data['starAccmPracticeCnt']"
:endVal="statistics_data['accmPracticeCnt']"
:useEasing="true"
ref="accmPracticeCntRef"
></uv-count-to>
<uv-count-to :startVal="statistics_data['starAccmPracticeCnt']"
:endVal="statistics_data['accmPracticeCnt']" :useEasing="true" ref="accmPracticeCntRef"></uv-count-to>
<span class="number"></span>
</view>
</view>
<view class="item">
<view class="top">本年考试次数</view>
<view class="bottom">
<uv-count-to
:startVal="statistics_data['startAccmExamCnt']"
:endVal="statistics_data['accmExamCnt']"
:useEasing="true"
ref="accmExamCntRef"
></uv-count-to>
<uv-count-to :startVal="statistics_data['startAccmExamCnt']" :endVal="statistics_data['accmExamCnt']"
:useEasing="true" ref="accmExamCntRef"></uv-count-to>
<span class="number"></span>
</view>
@@ -116,15 +89,12 @@
<image class="icon" src="@/static/images/index/navigation_course.png"></image>
<view class="title">AI学习</view>
</view>
<view
class="item"
@click="common.navigateTo('/pages/index/dialog', { animationType: 'slide-in-bottom' })"
>
<view class="item" @click="common.navigateTo('/pages/index/dialog', { animationType: 'slide-in-bottom' })">
<image class="icon" src="@/static/images/index/navigation_question_answering.png"></image>
<view class="title">AI问答</view>
</view>
<view class="item">
<view class="item" @click="common.navigateTo('/pages/sparring/index')">
<image class="icon" src="@/static/images/index/navigation_ai.png"></image>
<view class="title">AI陪练</view>
</view>
@@ -138,7 +108,7 @@
<image class="icon" src="@/static/images/index/navigation_examination.png"></image>
<view class="title">考试中心</view>
</view>
<view class="item" @click="common.navigateTo('/pages/competition/index')">
<image class="icon" src="@/static/images/index/navigation_practice.png"></image>
<view class="title">竞赛练习</view>
@@ -156,9 +126,9 @@
<classScroll :ref="(el) => (classScrollRef[0] = el)" name="hot_class"></classScroll>
<classScroll :ref="(el) => (classScrollRef[1] = el)" name="recommend_class"></classScroll>
<classScroll :ref="(el) => (classScrollRef[2] = el)" name="new_class"></classScroll>
<!-- <view class="hot_class_div">
<!-- <view class="hot_class_div">
<scroll-view class="scroll-view" :scroll-x="true" :show-scrollbar="false">
<view class="scroll-view-item" v-for="(item, index) in hot_class_list" :key="index">
<view class="item_div">
@@ -187,7 +157,7 @@
</view>
</scroll-view>
</view> -->
<view class="bottom_line">
<uv-divider text="我是有底线的" lineColor="#9cB0DC" :hairline="true"></uv-divider>
</view>
@@ -197,14 +167,39 @@
</template>
<script setup>
import { computed, nextTick, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { onShow, onPageScroll, onLoad, onHide } from '@dcloudio/uni-app';
import { customStyles, fixedCustomStyles, placeholderStyle, suffixIconStyle } from './index.js';
import { getUserInfo } from '@/common/common';
import {
computed,
nextTick,
onBeforeMount,
onMounted,
reactive,
ref
} from 'vue';
import {
onShow,
onPageScroll,
onLoad,
onHide
} from '@dcloudio/uni-app';
import {
customStyles,
fixedCustomStyles,
placeholderStyle,
suffixIconStyle
} from './index.js';
import {
getUserInfo
} from '@/common/common';
import common from '@/common/common';
import { setMascot } from '@/common/mascot.js';
import { getStatisticsData } from '@/api/index.js';
import { noticeMessageCount } from '@/api/messageNotification.js';
import {
setMascot
} from '@/common/mascot.js';
import {
getStatisticsData
} from '@/api/index.js';
import {
noticeMessageCount
} from '@/api/messageNotification.js';
import classScroll from './components/class_scroll.vue';
const scrollTop = ref(0);
const no_read_message_num = ref(0);
@@ -230,7 +225,7 @@
if (scrollTop.value <= 130) return 0;
return Math.min(3, (scrollTop.value - 130) / 30);
});
const bgOpacity = computed(() => {
return `rgba(246,248,255,${opacity.value})`;
});
@@ -241,9 +236,9 @@
});
// 滚动消息
const notice_text = ref(['绿色金融政策解析与商业银行绿色水水水水水水水水水水水水水', '绿色金融政策解析与商业银行红色']);
const mascotInfo = ref({});
const statistics_data = reactive({
stdtTmLen: 0, // 学习
accmPracticeCnt: 0, // 训练
@@ -252,7 +247,7 @@
startAccmPracticeCnt: 0, // 起始训练
startAccmExamCnt: 0, // 起始考试
request_time: 0, // 上次请求时间
init: function () {
init: function() {
// 初始化统计数据
const index_statistics_data = common.getValue('statistics_data'); // 获取缓存
if (index_statistics_data) {
@@ -261,7 +256,7 @@
this.accmExamCnt = index_statistics_data.accmExamCnt;
}
},
get_statistics_data: async function () {
get_statistics_data: async function() {
try {
const time_now = Date.now();
let statistics_data = common.getValue('statistics_data') || {};
@@ -283,7 +278,9 @@
}
// 解构赋值获取最新值
const { accmExamCnt = 0, accmPracticeCnt = 0, stdtTmLen = 0 } = statistics_data;
const {
accmExamCnt = 0, accmPracticeCnt = 0, stdtTmLen = 0
} = statistics_data;
// 更新数据并触发动画
if (stdtTmLen !== this.stdtTmLen) {
@@ -307,12 +304,12 @@
}
}
});
// 进入搜索页
const goto_search_page = () => {
common.navigateTo('/pages/search/search?from=index');
};
onLoad(() => {
statistics_data['init'](); // 初始化数据
// 检测如果没设置吉祥物,跳转到吉祥物界面
@@ -339,7 +336,7 @@
nextTick(() => {
classScrollRef.value.forEach((item) => item?.get_data());
});
noticeMessageCount().then((res) => {
no_read_message_num.value = res.body;
});
@@ -396,6 +393,7 @@
width: 200rpx;
height: 150rpx;
}
// margin-right: 22rpx;
}
@@ -430,6 +428,7 @@
.button_div {
display: flex;
justify-content: space-between;
.button {
text-align: center;
line-height: 62rpx;
@@ -534,10 +533,12 @@
flex-direction: column;
align-items: center;
min-width: 60rpx;
.message_img {
width: 32rpx;
height: 36rpx;
}
.message_text {
margin-top: 4rpx;
font-family: PingFangSC, PingFang SC;
@@ -556,9 +557,11 @@
border-radius: 10rpx;
color: #ffffff;
}
.message_num_big {
right: 0rpx;
}
.message_num_small {
right: 8rpx;
min-width: 24rpx;
@@ -731,4 +734,4 @@
flex-direction: column;
background-color: #f6f8ff;
}
</style>
</style>
@@ -0,0 +1,150 @@
<template>
<view class="sparring-info" @click="clickItem">
<view class="cont-box">
<ImagePreview class="img-box" :imgId="itemInfo.imgId" :isCache="true" width="225" height="170" mode="scaleToFill">
</ImagePreview>
<view class="item-title">{{itemInfo.crsName}}</view>
<scroll-view class="item-tags" :scroll-x="true">
<view class="item-tag-view">
<view :class="['item-tag', this.activeTag.includes(item.tagId)?'active-tag':'']" v-for="item in tagsShowList">
{{item.tagName}}</view>
</view>
</scroll-view>
<view class="item-publish">截至时间{{itemInfo.mtTime}}</view>
<view class="item-num">陪练次数{{itemInfo.accmStdyCnt}}人次</view>
</view>
</view>
</template>
<script >
import ImagePreview from '@/components/image-preview/image-preview.vue'
export default {
name: "sparring-item",
components: {
ImagePreview
},
props: {
itemInfo: {
type: Object,
default: () => ({
crsName: '',
tagCataList: [],
publicTime: "",
learnedNum: ''
})
},
activeTag: {
default: () => [],
type: Array
}
},
data() {
return {
};
},
watch: {
activeTag: {
handler() {},
deep: true,
immediate: true
}
},
computed: {
tagsShowList() {
if (!this.activeTag) return this.itemInfo.tagCataList || []
let _arr = (this.itemInfo.tagCataList || []).filter(t => this.activeTag.includes(t.tagId))
let _arr1 = (this.itemInfo.tagCataList || []).filter(t => !this.activeTag.includes(t.tagId))
return _arr.concat(_arr1)
}
},
methods: {
clickItem() {
this.$emit('clickItem', this.itemInfo)
}
}
}
</script>
<style lang="scss" scoped>
.sparring-info {
padding:12rpx 15rpx 8rpx;
overflow: hidden;
.item-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 44rpx;
font-size: 29rpx;
font-weight: 500;
margin-bottom: 10rpx;
padding: 20rpx 20rpx 0;
box-sizing: border-box;
}
.cont-box {
width: 100%;
box-sizing: border-box;
padding: 0 0 20rpx;
float: left;
border-radius: 16rpx;
overflow: hidden;
background-color: #fff;
border: 2rpx solid #f1f1f1;
.img-box {
width: 100%;
height: 180rpx;
}
.item-tags {
margin-bottom: 14rpx;
padding: 0 20rpx;
box-sizing: border-box;
.item-tag-view {
white-space: nowrap;
height: 44rpx;
.item-tag {
height: 38rpx;
line-height: 34rpx;
box-sizing: border-box;
font-size: 20rpx;
background-color: #fff;
color: #06f;
border: 2rpx solid #06f;
padding: 0 20rpx;
border-radius: 8rpx;
margin-right: 20rpx;
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200rpx;
box-sizing: border-box;
&.active-tag {
// background-color: #ffa150;
color: #ffa150;
border: 2rpx solid #ffa150;
}
}
}
}
.item-publish,
.item-num {
padding: 0 20rpx;
height: 32rpx;
line-height: 32rpx;
font-size: 20rpx;
color: rgb(102, 102, 102);
margin-top: 6rpx;
white-space: nowrap;
}
.item-publish {
margin-top: 0rpx;
}
}
}
</style>
+745
View File
@@ -0,0 +1,745 @@
<template>
<view class="sparring-center max_page">
<view class="top-bg"></view>
<view class="bot-bg"></view>
<view class="sparring-center-body">
<view class="body-title">
<!-- @click="test.testApi" -->
<uv-icon class="arrow-icon" name="arrow-left" @click="common.switchTab('/pages/index/index')" />
AI陪练
</view>
<view class="input-view" @click="toSearchPage">
<uv-input shape="circle" placeholderStyle="color:#999999;font-size:28rpx;" placeholder="请输入陪练名称"
suffixIcon="search" :customStyle="customStyle" :suffixIconStyle="suffixIconStyle" :readonly="true">
</uv-input>
</view>
<view class="tabs-view">
<uv-tabs :list="tabList" @click="changeTab" :scrollable="false" active-style="font-weight:bold; color:#000;"
class="font_pf my_tabs"
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight: '500' }"
:activeStyle="{ color: '#333333', fontSize: '30rpx', fontWeight: '600' }"
></uv-tabs>
<uv-tabs :list="tabList" @click="changeTabSec" :scrollable="true" active-style="font-weight:bold; color:#000;"
class="font_pf my_tabs2"
:inactive-style="{ color: '#333333', fontSize: '24rpx', fontWeight: '500' }"
:activeStyle="{ color: '#0066FF', fontSize: '24rpx', fontWeight: '500' }"
:lineColor="`url(${LineBg}) 2% 2%`"></uv-tabs>
</view>
<view class="list-view">
<view class="filter-btn" @click="
() => {
showFilterList = !showFilterList
activeTagPop = activeTag
}
">
<!-- 筛选 -->
<!-- <uv-icon class="filter-icon" name="list" /> -->
<image
class="filter-icon"
src="@/static/images/course/filter.png"
></image>
</view>
<view :class="['filter-list', showFilterList ? 'show' : '']">
<scroll-view :scroll-y="true" class="scroll-box-tags">
<view class="filter-type" v-for="item in tagsTree" :key="item.value">
<!-- .filter(t=>(t.children||[]).length>0) -->
<view class="filter-type-title">{{ item.label }}</view>
<scroll-view :scroll-x="true" class="filter-type-list">
<view :class="['filter-type-item', activeTagPop.includes(itemT.value) ? 'is-active' : '']"
v-for="itemT in item.children || []" @click="chooseTagPop(itemT)">
{{ itemT.label }}
</view>
</scroll-view>
</view>
</scroll-view>
<view class="btns-box">
<view class="btn-sub cencle-btn" @click="showFilterList = false">取消</view>
<view class="btn-sub" @click="changeChooseTagsList">筛选</view>
</view>
</view>
<view :class="['model-filter-list', showFilterList ? 'show' : '']" @click="showFilterList = false"></view>
<uv-scroll-list class="tags-view" :indicator="false">
<uv-tags text="全部" bgColor="#f6f8fa" :borderColor="activeTag.length === 0 ? '#06f' : '#f6f8fa'"
:color="activeTag.length === 0 ? '#06f' : '#333'"
:class="activeTag.length === 0 ? 'tags-item active-tags-item' : 'tags-item'" size="medium"
:type="activeTag.length === 0 ? 'primary' : 'info'" @click="chooseTag({ value: '' })"></uv-tags>
<uv-tags :text="item.label" v-for="item in tagsList" :key="item.value" size="medium" :bgColor="'#f6f8fa'"
:borderColor="activeTag.includes(item.value) ? '#06f' : '#f6f8fa'"
:color="activeTag.includes(item.value) ? '#06f' : '#333'" @click="chooseTag(item)"
:class="activeTag.includes(item.value) ? 'tags-item active-tags-item' : 'tags-item'"></uv-tags>
</uv-scroll-list>
<view class="sparring-list">
<view class="sparring-list-body">
<scroll-view :class="['right-sparring-list', getActiveItemClass()]" :scroll-y="true"
@scrolltolower="getMoreList()">
<view class="sparring-item-box" v-for="item in sparringList">
<SparringItem :itemInfo="item" :activeTag="activeTag"
@clickItem="toCourseDetail(item)" />
</view>
<view class="loading-box" v-show="loading">
<CommonLoading color="#06f" class="loading-val" />
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import SparringItem from './components/sparring-item.vue'
import common from '@/common/common'
import { LineBg } from '@/enum.js';
import {
getPrdLineTypeListApi,
getTraTagListApi,
getCourseTypeListApi,
queryCrsInfoByCatalogApi,
queryCrsInfoByPrdLineApi,
queryCrsInfoByLastnewApi,
queryCrsInfoByPopularApi,
queryCrsInfoByRecmdApi
} from '@/api/course.js'
import {
onMounted,
onActivated,
ref,
computed,
onUnmounted
} from 'vue'
import {
onShow
} from '@dcloudio/uni-app'
import {
useSocketStore
} from '@/store/socket.js'
const socketStore = useSocketStore()
const customStyle = {
backgroundColor: '#fff',
paddingLeft: '40rpx',
height: '60rpx',
paddingTop: '5px',
paddingBottom: '5px',
border: 'none'
}
const suffixIconStyle = {
color: '#2c8ef2',
fontSize: '40rpx'
}
const tabsCustomStyle = {
backgroundColor: '#ffffff',
borderRadius: '23rpx'
}
const tabList = [{
name: '全部'
}, {
name: '热门'
}, {
name: '最新'
}, {
name: '推荐'
}, {
name: '生产线'
}]
const activeTab = ref('全部')
const activeCourseType = ref('')
const activePrdlineType = ref('')
const activeTag = ref([])
const sparringTypeList = ref([])
const sparringPrdlineList = ref([])
const tagsTree = ref([])
const showFilterList = ref(false)
const {
statusBarHeight
} = uni.getWindowInfo()
const pageTopPadding = computed(() => statusBarHeight + 'px')
const activeTagPop = ref([])
const chooseTagPop = item => {
if (!item.value) {
activeTagPop.value = []
return
}
activeTagPop.value = activeTagPop.value.filter(t => !!t)
if (activeTagPop.value.includes(item.value)) {
activeTagPop.value = activeTagPop.value.filter(t => t !== item.value)
} else {
activeTagPop.value.push(item.value)
}
}
// 点击标签
const chooseTag = item => {
if (!item.value) {
activeTag.value = []
} else {
activeTag.value = activeTag.value.filter(t => !!t)
if (activeTag.value.includes(item.value)) {
activeTag.value = activeTag.value.filter(t => t !== item.value)
} else {
activeTag.value.push(item.value)
}
}
pageObj.value.page = 1
pageObj.value.total = 0
getMoreList(1)
// showFilterList.value = false
}
const activeLeftIndex = ref(-1)
const getActiveItemClass = () => {
let _class = ''
if ('生产线' === activeTab.value) {
_class = activeLeftIndex.value === 0 ? 'no-radius' : ''
} else if ('全部' === activeTab.value) {
_class = activeLeftIndex.value === 0 ? 'no-radius' : ''
}
return _class
}
// 点击生产线分类
const changePrdLine = (item, index) => {
activePrdlineType.value = item.value === activePrdlineType.value ? '' : item.value
activeLeftIndex.value = index
getMoreList(1)
}
// 点击课程分类
const changeCourseType = (item, index) => {
activeCourseType.value = item.value === activeCourseType.value ? '' : item.value
activeLeftIndex.value = index
getMoreList(1)
}
const showTypeName = computed(() => {
return (activeTab.value === '全部' && activeCourseType.value === '') || (activeTab.value === '生产线' &&
activePrdlineType.value === '')
})
const tagsList = computed(() => {
let _arr = []
tagsTree.value.forEach(t => {
let _tarr = t.children || []
_arr = _arr.concat(_tarr)
})
let _reqList = _arr.filter(t => t.required === 'Y')
let _reqListN = _arr.filter(t => t.required === 'N')
return _reqList.concat(_reqListN)
})
const changeChooseTagsList = () => {
showFilterList.value = false
activeTag.value = activeTagPop.value
pageObj.value.page = 1
pageObj.value.total = 0
getMoreList(1)
}
const sparringListBase = ref([])
const sparringList = computed(() => {
return sparringListBase.value
})
const pageObj = ref({
page: 1,
limit: 20,
total: 0
})
const getMoreList = flag => {
console.log(activeTab.value)
if (!flag) {
if (pageObj.value.total <= pageObj.value.page * pageObj.value.limit) return
pageObj.value.page += 1
} else {
sparringListBase.value = []
pageObj.value.page = 1
}
pageObj.value.total = 0
loading.value = true
switch (activeTab.value) {
case '全部':
queryCrsInfoByCatalogApi({
...pageObj.value,
tagId: activeTag.value.join(','),
catalogId: activeCourseType.value
})
.then(res => {
sparringListBase.value = sparringListBase.value.concat(res.body || [])
pageObj.value.total = res.total
})
.finally(() => {
loading.value = false
})
break
case '热门':
queryCrsInfoByPopularApi({
...pageObj.value,
tagId: activeTag.value.join(',')
})
.then(res => {
sparringListBase.value = res.body || []
})
.finally(() => {
loading.value = false
})
break
case '最新':
queryCrsInfoByLastnewApi({
...pageObj.value,
tagId: activeTag.value.join(',')
})
.then(res => {
sparringListBase.value = res.body || []
})
.finally(() => {
loading.value = false
})
break
case '推荐':
queryCrsInfoByRecmdApi({
...pageObj.value,
tagId: activeTag.value.join(',')
})
.then(res => {
sparringListBase.value = sparringListBase.value.concat(res.body || [])
pageObj.value.total = res.total
})
.finally(() => {
loading.value = false
})
break
case '生产线':
queryCrsInfoByPrdLineApi({
...pageObj.value,
tagId: activeTag.value.join(','),
prdLineId: activePrdlineType.value
})
.then(res => {
sparringListBase.value = sparringListBase.value.concat(res.body || [])
pageObj.value.total = res.total
})
.finally(() => {
loading.value = false
})
break
}
}
const loading = ref(false)
const changeTab = item => {
if (!item) return
sparringListBase.value = []
activeTab.value = item.name
activeLeftIndex.value = -1
activeTag.value = []
pageObj.value.page = 1
pageObj.value.total = 0
// activeTag.value = ''
activeCourseType.value = ''
activePrdlineType.value = ''
loading.value = true
queryCrsInfoByCatalogApi(pageObj.value)
.then(res => {
sparringListBase.value = res.body || []
pageObj.value.total = res.total
})
.finally(() => {
loading.value = false
})
}
const changeTabSec = () => {
}
// 跳转搜索页
const toSearchPage = () => {
common.navigateTo('/pages/search/search?from=sparring')
}
// 跳转 课程详情
const toCourseDetail = item => {
common.navigateTo('/pages/sparringDetail/index?crsNum=' + item.crsNum + '&crsId=' + item.crsId)
// common.navigateTo('/pages/sparring/study?crsNum=' + item.crsNum)
}
onMounted(() => {
getCourseTypeListApi().then(res => {
sparringTypeList.value = res.body || []
})
getPrdLineTypeListApi().then(res => {
sparringPrdlineList.value = res.body || []
})
getTraTagListApi().then(res => {
tagsTree.value = res.body || []
})
changeTab({
name: '全部'
})
uni.$on('refresh_sparring_list', () => {
changeTab({
name: activeTab.value || '全部'
})
})
})
onUnmounted(() => {
uni.$off('refresh_sparring_list')
})
onActivated(() => {
// 重新获取标签信息
getTraTagListApi().then(res => {
tagsTree.value = res.body || []
})
changeTab({
name: activeTab.value || '全部'
})
})
onShow(() => {
changeTab({
name: activeTab.value || '全部'
})
socketStore.closeSocket()
})
</script>
<style lang="scss" scoped>
.my_tabs2 {
// 解决这个圆角的图片,开穿透
:deep(.uv-tabs__wrapper__nav__line) {
height: 30rpx !important;
left: 42rpx;
background-size: 24rpx !important;
background-repeat: no-repeat !important;
}
:deep(.uv-tabs__wrapper__nav__item){
padding: 0 30rpx !important;
}
}
.sparring-center {
position: relative;
display: flex;
flex-direction: column;
.top-bg {
background-color: #fff;
background: linear-gradient(16deg, rgba(234, 246, 255, 0) 0%, #c3e6ff 100%);
height: 480rpx;
width: 100%;
}
.bot-bg {
background-color: #fff;
background: linear-gradient(136deg, rgba(234, 246, 255, 0) 0%, #c3e6ff 100%);
width: 100%;
flex: 1;
}
.sparring-center-body {
position: absolute;
overflow: hidden;
left: 0;
top: 0;
height: 100%;
width: 100%;
padding: 0;
box-sizing: border-box;
display: flex;
flex-direction: column;
padding-top: v-bind(pageTopPadding);
// padding-top: var(--status-bar-height);
.body-title {
height: 90rpx;
// background-color: red;
text-align: center;
font-size: 33rpx;
padding-top: 10rpx;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: relative;
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 36rpx;
top: 20rpx;
color: #000;
}
}
.input-view {
padding: 0 15rpx;
}
.tabs-view {
background: #ffffff;
border-radius: 23rpx 23rpx 0 0;
padding: 6rpx 10rpx 12rpx;
margin: 20rpx 15rpx 0;
}
.list-view {
flex: 1;
overflow: hidden;
// margin-bottom: 15rpx;
margin: 0rpx 15rpx 0;
background: #ffffff;
// border-radius: 23rpx;
display: flex;
flex-direction: column;
position: relative;
.filter-list {
position: absolute;
top: 84rpx;
left: 0;
width: 100%;
height: 588rpx;
padding-bottom: 80rpx;
overflow-y: hidden;
z-index: 15;
background-color: #f9f9f9;
box-shadow: 0rpx 12rpx 20rpx rgba(160, 160, 160, 0.25);
border-radius: 0 0 0rpx 0rpx;
box-sizing: border-box;
position: relative;
.scroll-box-tags {
height: 508rpx;
padding: 0rpx 25rpx;
box-sizing: border-box;
}
.filter-type {
padding: 10rpx 0;
box-sizing: border-box;
.filter-type-title {
font-size: 29rpx;
line-height: 40rpx;
margin-bottom: 15rpx;
color: #000;
}
.filter-type-list {
overflow: hidden;
.filter-type-item {
// width: calc(25% - 18rpx);
display: inline-block;
font-size: 29rpx;
box-sizing: border-box;
padding: 0 20rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
text-align: center;
float: left;
margin-right: 24rpx;
height: 65rpx;
line-height: 65rpx;
background-color: #f1f3f8;
border-radius: 6rpx;
margin-bottom: 20rpx;
&:nth-child(4n) {
margin-right: 24rpx;
}
&.is-active {
color: #06f;
}
}
}
&+.filter-type {
margin-top: 20rpx;
}
}
.btns-box {
height: 80rpx;
position: absolute;
background-color: #fff;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
padding-top: 10rpx;
.btn-sub {
display: inline-block;
text-align: center;
background-color: #06f;
height: 60rpx;
line-height: 58rpx;
border: 1rpx solid #06f;
padding: 0 40rpx;
color: #fff;
border-radius: 8rpx;
&.cencle-btn {
background-color: #fff;
color: #06f;
margin-right: 40rpx;
}
}
}
}
.model-filter-list {
position: fixed;
width: calc(100vw - 33rpx);
height: 80vh;
overflow: hidden;
top: 500rpx;
left: 17rpx;
z-index: 1;
background-color: rgba(0, 0, 0, 0.2);
}
.filter-list,
.model-filter-list {
display: none;
&.show {
display: block;
}
}
.filter-btn {
position: absolute;
right: 0;
top: 0;
height: 83rpx;
width: 80rpx;
line-height: 83rpx;
font-size: 26rpx;
background: #fff;
z-index: 2;
text-align: center;
box-shadow: -4rpx 0 6rpx rgba(0, 0, 0, 0.05);
white-space: nowrap;
// padding-right: 30rpx;
box-sizing: border-box;
.filter-icon {
// display: inline-block;
width: 32rpx;
height: 32rpx;
font-size: 26rpx;
position: absolute;
right: 24rpx;
top: 50%;
transform: translateY(-50%);
}
}
.tags-view {
height: 84rpx;
display: block;
padding: 15rpx 80rpx 15rpx 20rpx;
box-sizing: border-box;
white-space: nowrap;
// border-bottom: 2rpx solid #eee;
.tags-item {
margin-right: 30rpx;
display: inline-block;
&.active-tags-item {
position: relative;
overflow: hidden;
border-radius: 4rpx;
overflow: hidden;
&::before {
content: '';
display: block;
width: 40rpx;
height: 40rpx;
position: absolute;
right: -20rpx;
bottom: -20rpx;
transform: rotateZ(-45deg);
background-color: #06f;
overflow: hidden;
z-index: 10;
}
&::after {
content: '';
display: block;
width: 8rpx;
height: 4rpx;
position: absolute;
right: 3rpx;
bottom: 8rpx;
transform: rotateZ(-45deg);
border-left: 1px solid #fff;
border-bottom: 1px solid #fff;
z-index: 11;
}
}
::v-deep .uv-tags {
padding: 0 20rpx;
.uv-tags__text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200rpx;
}
}
}
}
.sparring-list {
display: flex;
flex: 1;
overflow: hidden;
background-color: #f1f5fa;
margin-top: 12rpx;
.sparring-list-body {
height: 100%;
display: flex;
flex: 1;
overflow: hidden;
.right-sparring-list {
flex: 1;
overflow-y: auto;
background-color: #fff;
// margin: 0 10rpx;
&.no-radius {
border-radius: 0rpx 0 0 0;
}
.sparring-item-box{
width: 50%;
float: left;
// background-color: #f1f1f1;
// margin-bottom: 16rpx;
&:nth-child(2n-1){
// margin-right: 16rpx;
}
}
}
}
}
}
.loading-box {
width: 100%;
height: 100rpx;
position: relative;
.loading-val {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
}
}
</style>
+9
View File
@@ -54,5 +54,14 @@
}
}
},
{
"path": "pages/sparring/index",
"style": {
"navigationBarTitleText": "AI陪练",
"app-plus": {
"titleNView": false
}
}
},
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B