Commit e2ac3edf by huangzhi

feat: 已购和首页

parent 1842bd1a
......@@ -7,6 +7,9 @@ module.exports = {
sourceType: 'module',
allowImportExportEverywhere: true,
},
globals: {
uni: 'readonly',
},
// 此项指定环境的全局变量,下面的配置指定为浏览器环境
env: {
browser: true,
......
......@@ -6,10 +6,11 @@ let h2Prefix
let ydlH5Prefix
if (isDevelopment) {
// hostPrefix = 'https://testnewm.ydl.com'
// apiPrefix = 'https://testapi.ydl.com'
hostPrefix = 'https://newm-test.ydl.com' // 下云
apiPrefix = 'https://api-test.ydl.com' // 下云
hostPrefix = 'https://testnewm.ydl.com'
// hostPrefix = 'http://192.168.211.138'
apiPrefix = 'https://testapi.ydl.com'
// hostPrefix = 'https://newm-test.ydl.com' // 下云
// apiPrefix = 'https://api-test.ydl.com' // 下云
h2Prefix = 'https://h2.yidianling.com'
ydlH5Prefix = 'https://testh5.ydl.com'
} else {
......
......@@ -54,7 +54,7 @@
"quickapp" : {},
/* 快应用特有相关 */
"mp-weixin" : {
"appid" : "",
"appid" : "wx1106c32a36d87d49",
"setting" : {
"urlCheck" : false,
"es6" : false,
......
<template>
<div class="empty">
<img src="//static.ydlcdn.com/m/images/m/course/rectangle.svg"/>
<p>{{text || '暂无数据'}}</p>
</div>
</template>
<script>
export default {
name: 'Empty',
props: ['text'],
}
</script>
<style lang="less" scoped>
.empty {
text-align: center;
p {
margin-top: 12px;
color: #999;
font-size: 13px;
text-align: center;
}
}
</style>
\ No newline at end of file
<template>
<view class="container home">
<!-- 筛选条件 -->
<screen-box
:url-params="urlParams"
:allow-home-scroll.sync="allowHomeScroll"
@screenDoctor="onScreenDoctor"
></screen-box>
<!-- 专家列表 -->
<scroll-view
v-if="doctorArr.length"
class="consult-list box-c"
:scroll-y="allowHomeScroll"
:refresher-enabled="true"
:refresher-triggered="scrollBottomRefresher"
:refresher-threshold="100"
@refresherrefresh="onRefresh"
@scrolltolower="handleScrollBottom"
>
<block
v-for="item in doctorArr"
:key="item.uid"
>
<doctor-item
:data-item="item"
:item="item"
:is-login="isLogin"
:current-doctor="currentDoctor.confidedId"
:play-status="playStatus"
@tap="toDetail(item)"
@player="playAudio"
/>
</block>
<view class="load-more">{{ !paging.hasMore ? '没有更多了~' : '加载中...' }}</view>
</scroll-view>
<view
v-else
class="no-data"
>
<view v-if="isLoaded">
<image
mode="aspectFill"
class="icon-find"
src="https://static.ydlcdn.com/weixin/image/home/no_data.png"
/>
<view class="c-666">未搜索到对应专家,请查询其他条件试试</view>
</view>
<view v-else>加载中...</view>
</view>
<view
v-if="playStatus"
class="player"
>
<view class="player-content">
<view
class="buy-list"
@scroll="handleScroll($event)"
>
<template v-if="initFinish">
<template v-if="courseList.length > 0">
<view
class="close-player"
@click="closePlayer"
v-for="(course, index) in courseList"
:key="index"
class="item-wrap"
@click="onPageToOrderDetail(course)"
>
<img
class="player-icon"
src="https://static.ydlcdn.com/mini/mini_confide/confide_icon_close.png"
alt=""
/>
</view>
<view class="player-info">
<image
class="player-cover"
mode="aspectFill"
:src="currentDoctor.confidedIcon"
/>
<view>
<view class="player-title">壹点倾诉,心灵寄语</view>
<view class="player-user">
<text class="player-user-name">{{ currentDoctor.confidedName }}</text>
<text
v-show="playStartTime && playEndTime"
class="player-user-time"
>
{{ playStartTime }} / {{ playEndTime }}
</text>
<view class="item-header">
<text class="item-header-left">
<text class="item-header-title">订单号:</text>
<text class="item-header-num">{{ course.orderId }}</text>
<img
class="item-header-img"
src="//static.ydlcdn.com/m/images/m/course/ico_kcml_lock@3x.png"
/>
</text>
<text
:class="{
'item-header-right': true,
'item-header-right-blue': index === 0,
}"
>
拼团中
</text>
</view>
<view class="item-content">
<view class="item-content-img">
<img src="//pic.ydlcdn.com/K4RBkeK5zx.jpg" />
</view>
<view class="item-content-info">
<view class="item-content-info-row-first">
<text class="row-first-title">12天重塑你的安全感,让恋爱不再患得患失</text>
<text class="row-first-money">¥299</text>
</view>
<view class="item-content-info-row-second">
<text class="row-second-time">
{{
course.paymentTime
? dayjs(course.paymentTime).format('YYYY-MM-DD HH:mm:ss')
: ''
}}
</text>
<text class="row-second-money">
实付款:
<text class="row-second-money-num">¥199</text>
</text>
</view>
</view>
</view>
<view class="item-footer">
<text
class="item-footer-btn"
type="default"
@click="handleCourseItemClick($event, course)"
>
查看商品
</text>
</view>
</view>
<view
class="pause-player"
@click="pausePlayer"
>
<img
class="player-icon"
:src="
isPausePlay
? 'https://static.ydlcdn.com/mini/mini_confide/confide_icon_play.png'
: 'https://static.ydlcdn.com/mini/mini_confide/confide_icon_pause.png'
"
alt=""
/>
</view>
</view>
</view>
</template>
<empty v-else></empty>
</template>
</view>
</template>
<script>
/* eslint-disable no-undef */
import ScreenBox from '@/components/expert-screen'
import DoctorItem from '@/components/expert-item'
import { setTrackData } from '@/utils/util'
const innerAudioContext = uni.createInnerAudioContext()
import Empty from './Empty.vue'
import { throttle } from 'lodash'
import dayjs from 'dayjs'
import { hostPrefix } from '@/config.js'
// import { Toast } from 'vant'
// 页面跳转
const navTo = url => {
const newUrl = `${hostPrefix}/h5-course/${url}`
uni.navigateTo({
url: `/pages/web/web?loadUrl=${encodeURIComponent(newUrl)}`,
})
}
export default {
name: 'ExpertPage',
name: 'BuyList',
components: {
ScreenBox,
DoctorItem,
Empty,
},
props: {
keywords: {
type: String,
default: '',
},
// 是否展示学习进度
showProgress: {
type: Boolean,
default: false,
},
},
data() {
return {
allowHomeScroll: true,
scrollBottomRefresher: false,
fromOpenId: '', // 从分享进入时所携带分享人的openid
isLoaded: false,
isFixed: true,
statistics: null,
doctorArr: [],
userInfo: {}, // 用户信息
paging: {
hasMore: true,
extras: null,
},
preScreen: {}, // 筛选信息
isLogin: false,
urlParams: {},
currentDoctor: {},
playStatus: false,
isPausePlay: false,
playStartTime: '',
playEndTime: '',
dayjs,
pageNo: 1,
pageSize: 10,
moreStatus: 'nomore',
courseList: [{}, {}],
// todo 应该是 false
initFinish: true,
}
},
onLoad(options) {
// 进入小程序判断是否携带参数
if (options && options.searchWord) {
this.urlParams = options
this.preScreen.keywords = options.searchWord
}
this.init()
// 咨询师列表访问埋点
setTrackData({
events: [
{
event_id: 'page_visit',
event_custom_properties: {
part: 'listener_list_page ',
position: '',
element: '',
},
},
],
})
},
onPullDownRefresh() {
this.onRefresh()
watch: {
keywords: {
handler() {
// todo
// this.refresh();
},
immediate: true,
},
},
methods: {
// 下拉刷新
onRefresh() {
// 开启下拉刷新
this.scrollBottomRefresher = true
this.paging.extras = null
this.init()
setTimeout(() => {
// 停止下拉刷新
uni.stopPullDownRefresh()
this.scrollBottomRefresher = false
}, 1000)
},
handleScrollBottom() {
// 滚动到底部加载更多数据
if (!this.paging.hasMore) return
this.getData()
// 查看订单详情 todo
onPageToOrderDetail({ id = 111 }) {
navTo(`my/orderDetail/${id}`)
},
init() {
this.getData(true)
const accessToken = uni.getStorageSync('accessToken')
this.isLogin = !!accessToken
},
onLoginEvent(e) {
if (e.detail.accessToken) {
this.isLogin = true
}
// 课程卡片点击,跳转课程详情 todo
handleCourseItemClick(e, { id = 111 }) {
e.stopPropagation()
navTo(`detail/${id}`)
},
onScreenDoctor(e = {}) {
// 筛选组件回调
this.preScreen = e
this.paging = {
hasMore: true,
}
uni.pageScrollTo({
scrollTop: 0,
})
this.getData(true)
// 刷新列表,提供给父组件搜索过滤调用
refresh() {
this.initFinish = false
this.moreStatus = 'nomore'
this.courseList = []
this.pageNo = 1
this.getCourseList()
},
async getData(isReset) {
let { doctorArr } = this
// dmp接口入参配置
const res = await this.$request
.get('smart-rank/v1/search-adapter/listeners', {
params: {
...this.preScreen,
extras: this.paging ? this.paging.extras || null : null, // 分页参数,将上一页返回的 extras 传到这里,没有上一页则不传
},
})
.finally(() => (this.loading = false))
const { body } = res
if (isReset) {
doctorArr = []
// 获取课程列表
async getCourseList() {
try {
// todo
// this.moreStatus === 'loading';
// Toast.loading('加载中...');
// const {total, list} = await this.$http.post('/course/v1/orders/pay/query', {
// pageNo: this.pageNo,
// pageSize: this.pageSize,
// title: this.keywords || '',
// });
// Toast.clear();
// this.courseList = [...this.courseList, ...list];
// this.courseList.map(item => {
// item.salesPrice = item.money;
// item.originPrice = 0;
// })
// this.initFinish = true;
// this.moreStatus = this.courseList.length < total ? "more" : "nomore";
} catch (e) {
console.log(e)
}
this.doctorArr = doctorArr.concat(body)
// 接口返回数据并且长度大于每页条数,可滚动加载
this.paging.hasMore = !!(Array.isArray(body) && body.length > 9)
this.paging.extras = res.extras
this.isLoaded = true
},
// 跳转详情页
toDetail(e) {
if (!e.confidedId) {
return uni.showToast('专家数据错误')
}
uni.navigateTo({
url: `/pages/confide/confide?listenerId=${e.confidedId}`,
})
},
onShareAppMessage() {
const openId = this.$store.state.user.openId
setTrackData({
events: [
{
event_id: 'common_click',
event_custom_properties: {
part: 'listener_list_page',
position: 'top_column',
element: 'share_friends',
},
},
],
})
return {
title: '倾诉师推荐',
path: `/pages/home/home?fromOpenId=${openId}${
this.preScreen.keywords ? '&searchWord=' + this.preScreen.keywords : ''
}`,
}
},
onShareTimeline() {
setTrackData({
events: [
{
event_id: 'common_click',
event_custom_properties: {
part: 'listener_list_page',
position: 'top_column',
element: 'share_moments',
},
},
],
})
return {
title: '倾诉师推荐-壹点灵心理',
query: {
fromOpenId: this.$store.state.user.openId,
searchWord: this.preScreen.keywords,
},
}
},
// 格式化音频时长
formatTime: function (s) {
let t = ''
s = Math.floor(s)
if (s > -1) {
const min = Math.floor(s / 60) % 60
const sec = s % 60
if (min < 10) {
t += '0'
// 上拉加载下一页
handleScroll: throttle(
function (e) {
const { scrollHeight, offsetHeight, scrollTop } = e.target
const height = scrollHeight - offsetHeight - scrollTop
const scrollThreshold = 100
if (height <= scrollThreshold) {
if (this.moreStatus === 'more') {
this.pageNo = this.pageNo + 1
this.getCourseList()
}
}
t += min + ':'
if (sec < 10) {
t += '0'
}
t += sec
}
return t
},
closePlayer() {
this.playStatus = false
innerAudioContext.stop()
},
pausePlayer() {
if (!this.isPausePlay) {
innerAudioContext.pause()
} else {
innerAudioContext.play()
}
this.isPausePlay = !this.isPausePlay
},
// 播放音频
playAudio(item) {
var audioUrl = item.confideVoice
this.currentDoctor = item
if (item.isPlayer) {
this.playStatus = false
this.isPausePlay = false
innerAudioContext.stop()
return
}
this.playStatus = true
this.isPausePlay = false
innerAudioContext.stop()
innerAudioContext.autoplay = false
innerAudioContext.src = audioUrl
innerAudioContext.play()
innerAudioContext.onPlay(() => {
console.log('开始播放', innerAudioContext.duration)
setTimeout(() => {
// 设置音频总时长
this.playEndTime = this.formatTime(Math.ceil(innerAudioContext.duration))
}, 300)
})
innerAudioContext.onTimeUpdate(() => {
// 音频跟新时若总时长未获取则重新获取
if (!this.playEndTime) {
this.playEndTime = this.formatTime(Math.ceil(innerAudioContext.duration))
}
console.log('更新播放', innerAudioContext.duration)
// 跟新音频播放时长
this.playStartTime = this.formatTime(Math.ceil(innerAudioContext.currentTime))
})
innerAudioContext.onError(res => {
console.log(res.errMsg, '播放出错', res.errCode)
this.playStatus = false
})
innerAudioContext.onPause(() => {
console.log('播放暂停')
})
innerAudioContext.onEnded(() => {
console.log('播放结束')
this.playStatus = false
this.isPausePlay = false
this.playStartTime = '00:00'
})
},
},
300,
{ leading: true },
),
},
}
</script>
<style lang="less" scoped>
.home {
position: relative;
background: #fff;
padding: 94px 0 0 0;
.buy-list {
background: #f8f8f8;
height: 100%;
}
.consult-list {
width: 100%;
height: 100%;
}
.icon-find {
width: 100%;
}
.no-data,
.load-more {
text-align: center;
padding: 20px;
}
.player {
position: fixed;
width: 100%;
bottom: 60px;
left: 0;
padding: 16px;
&-content {
width: 100%;
color: #fff;
background: rgba(0, 0, 0, 0.8);
border-radius: 8px;
padding: 8px 20px 8px 8px;
display: flex;
align-items: center;
.player-cover {
width: 40px;
height: 40px;
margin-right: 12px;
border-radius: 4px;
overflow: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: none;
.item-wrap {
background: #fff;
// border-bottom: 10px solid rgb(249, 249, 249);
margin: 0 10px;
margin-top: 10px;
border-radius: 12px;
padding: 12px 12px 16px 12px;
.item-header {
display: flex;
justify-content: space-between;
border-bottom: 1px solid rgb(249, 249, 249);
padding-bottom: 8px;
.item-header-img {
height: 15px;
vertical-align: middle;
}
.item-header-right-blue {
color: #1698ff;
}
}
}
.player-info {
width: 100%;
display: flex;
align-items: center;
}
.player-title {
font-size: 16px;
line-height: 20px;
margin-bottom: 4px;
}
.player-user {
display: flex;
font-size: 12px;
line-height: 16px;
color: rgba(255, 255, 255, 0.6);
&-name {
::after {
content: '';
border-right: 0.5px solid rgba(255, 255, 255, 0.9);
height: 8px;
padding-right: 8px;
margin-right: 8px;
.item-content {
display: flex;
justify-content: space-between;
/* height: 65px; */
margin-top: 8px;
.item-content-img {
img {
height: 57px;
width: 46px;
}
}
.item-content-info {
flex: 1;
padding-left: 8px;
.item-content-info-row-first {
display: flex;
justify-content: space-between;
font-size: 14px;
font-weight: 500;
.row-first-title {
max-width: 175px;
}
}
.item-content-info-row-second {
display: flex;
justify-content: space-between;
/* line-height: 100%; */
align-items: center;
margin-top: 1px;
.row-second-time {
font-size: 12px;
color: #999999;
.row-second-money {
.row-second-money-num {
font-weight: 500;
}
}
}
}
}
}
}
.close-player {
margin-right: 8px;
.player-icon {
width: 32px;
height: 32px;
vertical-align: middle;
.item-footer {
display: flex;
flex-direction: row-reverse;
margin-top: 17px;
button {
height: 30px;
width: 68px;
padding: 0;
border-radius: 5px;
font-size: 13px;
}
}
}
.player-icon {
width: 16px;
height: 16px;
vertical-align: middle;
}
}
</style>
......@@ -20,12 +20,14 @@
src="https://static.ydlcdn.com/mini/mini_consult/pic_default_avatar.png"
@click="handleLoginClick"
/>
<text
v-if="isLogin"
class="user-name"
>
{{ userInfo.nickName }}
</text>
<view v-if="isLogin">
<text class="user-name-phone">
{{ userInfo.nickName }}
</text>
<text class="user-name-phone">
{{ userPhoneTxt }}
</text>
</view>
<view
v-else
@click="handleLoginClick"
......@@ -70,7 +72,7 @@
</template>
<script>
import { hostPrefix, h2Prefix } from '@/config'
import { hostPrefix } from '@/config'
import { setTrackData } from '@/utils/util'
export default {
......@@ -79,26 +81,6 @@ export default {
return {
menus: [
{
icon: '/static/icon_order.png',
label: '我的订单',
callback: () => {
this.handleSendMenuTrackData('我的订单')
this.navigateToOrder()
},
},
{
icon: '/static/icon_help_center.png',
label: '帮助中心',
callback: () => {
this.handleSendMenuTrackData('帮助中心')
uni.navigateTo({
url: `/pages/web/web?title=帮助中心&loadUrl=${encodeURIComponent(
`${h2Prefix}/help/list/12`,
)}`,
})
},
},
{
icon: '/static/icon_custom_service.png',
label: '联系客服',
callback: () => {
......@@ -142,6 +124,13 @@ export default {
isLogin() {
return this.$store.getters.isLogin
},
// 混淆手机号码
userPhoneTxt() {
if (this.userInfo.phone) {
return String(this.userInfo.phone).replace(/(.{3})(.{4})(.+$)/, '$1****$3')
}
return ''
},
},
mounted() {
// 页面访问埋点
......@@ -243,6 +232,14 @@ export default {
font-size: 18px;
margin-bottom: 4px;
}
.user-name-phone {
margin-left: 16px;
color: #000000;
font-weight: 400;
font-size: 15px;
margin-bottom: 4px;
display: block;
}
.login-tips {
margin-left: 16px;
......
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