Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
ydl-group-course
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
黄志
ydl-group-course
Commits
c1dbe7b8
Commit
c1dbe7b8
authored
Feb 20, 2023
by
yewills
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 初始出来的项目接入业务后,修改的代码
parent
3fc4f2db
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1290 additions
and
126 deletions
+1290
-126
README.md
README.md
+2
-36
package.json
package.json
+2
-0
App.vue
src/App.vue
+30
-2
audio-play.vue
src/components/audio-play.vue
+26
-0
phone-login.vue
src/components/phone-login.vue
+3
-2
config.js
src/config.js
+12
-2
main.js
src/main.js
+2
-0
manifest.json
src/manifest.json
+36
-33
pages.json
src/pages.json
+56
-9
home.vue
src/pages/home/home.vue
+448
-24
my.vue
src/pages/my/my.vue
+278
-9
request.js
src/plugins/request.js
+11
-4
user.js
src/store/modules/user.js
+43
-3
common.scss
src/style/common.scss
+273
-0
enums.js
src/utils/enums.js
+65
-0
util.js
src/utils/util.js
+3
-2
No files found.
README.md
View file @
c1dbe7b8
#
uniapp-project
#
拼团小程序
## Project setup
```
...
...
@@ -57,21 +57,6 @@ npm run prepare
响应拦截中有未登录处理,错误处理等。
```
javascript
// Promise 写法
this
.
$request
.
get
(
'xxx'
).
then
(
res
=>
{})
// async/await 写法
const
res
=
await
this
.
$request
.
post
(
'xxx'
)
// 传参
const
params
=
{}
this
.
$request
.
get
(
'xxx'
,
{
params
})
this
.
$request
.
post
(
'xxx'
,
params
)
```
## 登录
提供了
`phone-login`
组件,用来调用手机号授权登录
...
...
@@ -80,26 +65,7 @@ this.$request.post('xxx', params)
## 埋点
目前前端的埋点库还不支持小程序,所以在
`utils/util.js`
里面封装了一个埋点请求,
`sendTrackData`
.
埋点封装的函数中的
`app_name`
参数需要根据实际项目定义填写进去。
埋点示例如下:
```
javascript
setTrackData
({
events
:
[
{
event_id
:
'page_visit'
,
event_custom_properties
:
{
part
:
'xxx'
,
position
:
''
,
element
:
''
,
},
},
],
})
```
目前前端的埋点库还不支持小程序,所以在
`utils/util.js`
里面封装了一个埋点请求,
`sendTrackData`
## 代码风格
...
...
package.json
View file @
c1dbe7b8
...
...
@@ -73,7 +73,9 @@
"
axios
"
:
"^0.27.2"
,
"
axios-adapter-uniapp
"
:
"^0.1.4"
,
"
core-js
"
:
"^3.6.5"
,
"
dayjs
"
:
"^1.11.7"
,
"
flyio
"
:
"^0.6.2"
,
"
lodash
"
:
"^4.17.21"
,
"
uview-ui
"
:
"^2.0.35"
,
"
vue
"
:
"^2.6.11"
,
"
vuex
"
:
"^3.2.0"
...
...
src/App.vue
View file @
c1dbe7b8
<
script
>
import
{
setTrackData
}
from
'@/utils/util'
export
default
{
onLaunch
:
function
()
{
console
.
log
(
'App Launch'
)
onLaunch
:
function
(
e
)
{
console
.
log
(
'App Launch'
,
e
)
// 获取openId
if
(
!
this
.
$store
.
state
.
user
.
openId
)
{
this
.
$store
.
dispatch
(
'user/getOpenId'
)
}
// 小程序launch埋点
const
part
=
{
'pages/home/home'
:
'listener_list_page'
,
'pages/confide/confide'
:
`listener_detail_
${
e
.
query
.
listenerId
}
`
,
}
if
(
part
[
e
.
path
])
{
setTrackData
({
events
:
[
{
event_id
:
'app_activation'
,
event_custom_properties
:
{
part
:
part
[
e
.
path
],
position
:
''
,
element
:
''
,
traffic_source_type
:
e
.
query
.
fromOpenId
?
3
:
''
,
// 3代表小程序分享流量,空代表自然流量
traffic_source
:
e
.
query
.
fromOpenId
||
''
,
},
},
],
})
}
},
onShow
:
function
()
{
console
.
log
(
'App Show'
)
...
...
@@ -14,6 +41,7 @@ export default {
<
style
lang=
"scss"
>
@import
'uview-ui/index.scss'
;
@import
'@/style/common.scss'
;
uni-page-body
,
html
,
body
{
...
...
src/components/audio-play.vue
0 → 100644
View file @
c1dbe7b8
<
template
>
<view>
<audio
style=
"text-align: left"
:src=
"current.src"
:poster=
"current.poster"
:name=
"current.name"
:author=
"current.author"
:action=
"audioAction"
controls
></audio>
</view>
</
template
>
<
script
>
export
default
{
props
:
{
audioSrc
:
{
type
:
String
,
required
:
true
,
},
},
}
</
script
>
<
style
></
style
>
src/components/phone-login.vue
View file @
c1dbe7b8
...
...
@@ -23,10 +23,10 @@ export default {
}
},
async
mounted
()
{
// 获取最新code
if
(
!
this
.
$store
.
state
.
user
.
code
)
{
this
.
uniLogin
()
}
else
{
// eslint-disable-next-line
uni
.
checkSession
({
success
:
res
=>
{
if
(
res
.
errMsg
!==
'checkSession:ok'
)
{
...
...
@@ -37,10 +37,12 @@ export default {
}
},
methods
:
{
// 获取手机号
async
getPhoneNumber
({
detail
:
{
errMsg
,
encryptedData
,
iv
}
})
{
if
(
errMsg
===
'getPhoneNumber:ok'
)
{
try
{
this
.
loading
=
true
// 登录
await
this
.
$store
.
dispatch
(
'user/login'
,
{
encryptedData
,
iv
,
...
...
@@ -54,7 +56,6 @@ export default {
this
.
loading
=
false
}
}
else
{
// eslint-disable-next-line
uni
.
showToast
({
title
:
'获取手机号失败'
,
duration
:
3000
,
...
...
src/config.js
View file @
c1dbe7b8
...
...
@@ -2,16 +2,26 @@ const isDevelopment = process.env.NODE_ENV === 'development'
let
hostPrefix
let
apiPrefix
let
h2Prefix
let
ydlH5Prefix
if
(
isDevelopment
)
{
hostPrefix
=
'https://testnewm.ydl.com'
apiPrefix
=
'https://testapi.ydl.com'
// hostPrefix = 'https://testnewm.ydl.com'
// 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
{
hostPrefix
=
'https://m.ydl.com'
apiPrefix
=
'https://api.ydl.com'
h2Prefix
=
'https://h2.yidianling.com'
ydlH5Prefix
=
'https://h5.ydl.com'
}
module
.
exports
=
{
hostPrefix
,
apiPrefix
,
h2Prefix
,
ydlH5Prefix
,
}
src/main.js
View file @
c1dbe7b8
...
...
@@ -3,11 +3,13 @@ import App from '@/App'
import
store
from
'@/store'
import
request
from
'@/plugins/request.js'
import
uView
from
'uview-ui'
import
dayjs
from
'dayjs'
Vue
.
config
.
productionTip
=
false
Vue
.
prototype
.
$store
=
store
Vue
.
prototype
.
$request
=
request
Vue
.
prototype
.
$dayjs
=
dayjs
Vue
.
use
(
uView
)
...
...
src/manifest.json
View file @
c1dbe7b8
{
"name"
:
""
,
"appid"
:
""
,
"description"
:
""
,
"versionName"
:
"1.0.0"
,
"versionCode"
:
"100"
,
"transformPx"
:
false
,
"app-plus"
:
{
/*
5
+App特有相关
*/
"usingComponents"
:
true
,
"splashscreen"
:
{
"alwaysShowBeforeRender"
:
true
,
"waiting"
:
true
,
"autoclose"
:
true
,
"delay"
:
0
"name"
:
"壹点拼团"
,
"appid"
:
""
,
"description"
:
""
,
"versionName"
:
"1.0.0"
,
"versionCode"
:
"100"
,
"transformPx"
:
false
,
"app-plus"
:
{
/*
5
+App特有相关
*/
"usingComponents"
:
true
,
"splashscreen"
:
{
"alwaysShowBeforeRender"
:
true
,
"waiting"
:
true
,
"autoclose"
:
true
,
"delay"
:
0
},
"modules"
:
{
/*
模块配置
*/
},
"distribute"
:
{
/*
应用发布信息
*/
"android"
:
{
/*
android打包配置
*/
"permissions"
:
[
"<uses-permission android:name=
\"
android.permission.CHANGE_NETWORK_STATE
\"
/>"
,
"modules"
:
{},
/*
模块配置
*/
"distribute"
:
{
/*
应用发布信息
*/
"android"
:
{
/*
android打包配置
*/
"permissions"
:
[
"<uses-permission android:name=
\"
android.permission.CHANGE_NETWORK_STATE
\"
/>"
,
"<uses-permission android:name=
\"
android.permission.MOUNT_UNMOUNT_FILESYSTEMS
\"
/>"
,
"<uses-permission android:name=
\"
android.permission.READ_CONTACTS
\"
/>"
,
"<uses-permission android:name=
\"
android.permission.VIBRATE
\"
/>"
,
...
...
@@ -42,23 +45,23 @@
"<uses-permission android:name=
\"
android.permission.WRITE_SETTINGS
\"
/>"
]
},
"ios"
:
{
/*
ios打包配置
*/
},
"sdkConfigs"
:
{
/*
SDK配置
*/
}
"ios"
:
{},
/*
ios打包配置
*/
"sdkConfigs"
:
{}
}
},
"quickapp"
:
{
/*
快应用特有相关
*/
/*
SDK配置
*/
"quickapp"
:
{},
/*
快应用特有相关
*/
"mp-weixin"
:
{
"appid"
:
""
,
"setting"
:
{
"urlCheck"
:
false
,
"es6"
:
false
,
"postcss"
:
true
,
"minified"
:
true
},
"mp-weixin"
:
{
/*
微信小程序特有相关
*/
"appid"
:
"wx1106c32a36d87d49"
,
"setting"
:
{
"urlCheck"
:
false
},
"usingComponents"
:
true
"usingComponents"
:
true
},
"mp-alipay"
:
{
"usingComponents"
:
true
...
...
src/pages.json
View file @
c1dbe7b8
...
...
@@ -4,25 +4,68 @@
},
"pages"
:
[
{
"path"
:
"pages/home/home"
,
"style"
:
{
"path"
:
"pages/home/home"
,
"style"
:
{
"navigationBarTitleText"
:
"首页"
,
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"pages/my/my"
,
"style"
:
"path"
:
"pages/home/expert-search"
,
"style"
:
{
"navigationBarTitleText"
:
"搜索"
,
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"pages/my/my"
,
"style"
:
{
"navigationStyle"
:
"custom"
,
"navigationBarTextStyle"
:
"black"
,
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"pages/web/web"
,
"style"
:
{
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"pages/login/login"
,
"style"
:
{
"navigationStyle"
:
"custom"
,
"navigationBarTextStyle"
:
"black"
,
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"pages/order/order"
,
"style"
:
{
"navigationBarTitleText"
:
"我的订单"
,
"enablePullDownRefresh"
:
true
,
"onReachBottomDistance"
:
50
}
},
{
"path"
:
"pages/confide/confide"
,
"style"
:
{
"navigationStyle"
:
"custom"
,
"navigationBarTextStyle"
:
"black"
,
"enablePullDownRefresh"
:
false
}
},
{
"navigationBarTitleText"
:
"我的"
,
"path"
:
"pages/pay/pay"
,
"style"
:
{
"navigationBarTitleText"
:
"支付"
,
"enablePullDownRefresh"
:
false
}
}
],
"globalStyle"
:
{
"navigationBarTextStyle"
:
"black"
,
"navigationBarTitleText"
:
"壹点
灵心理咨询
"
,
"navigationBarTitleText"
:
"壹点
拼团
"
,
"navigationBarBackgroundColor"
:
"#ffffff"
,
"backgroundColor"
:
"#ffffff"
,
"backgroundTextStyle"
:
"dark"
...
...
@@ -35,11 +78,15 @@
"list"
:
[
{
"text"
:
"首页"
,
"pagePath"
:
"pages/home/home"
"pagePath"
:
"pages/home/home"
,
"iconPath"
:
"/static/tab_home.png"
,
"selectedIconPath"
:
"/static/tab_home_selected.png"
},
{
"text"
:
"我的"
,
"pagePath"
:
"pages/my/my"
"pagePath"
:
"pages/my/my"
,
"iconPath"
:
"/static/tab_my.png"
,
"selectedIconPath"
:
"/static/tab_my_selected.png"
}
]
}
...
...
src/pages/home/home.vue
View file @
c1dbe7b8
<
template
>
<view
class=
"content"
>
<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
class=
"logo"
src=
"/static/logo.png"
></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=
"close-player"
@
click=
"closePlayer"
>
<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>
<text
class=
"title"
>
{{
title
}}
</text>
<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>
</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>
</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
()
export
default
{
name
:
'HomePage'
,
name
:
'ExpertPage'
,
components
:
{
ScreenBox
,
DoctorItem
,
},
data
()
{
return
{
title
:
'Hello'
,
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
:
''
,
}
},
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
()
},
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
()
},
init
()
{
this
.
getData
(
true
)
const
accessToken
=
uni
.
getStorageSync
(
'accessToken'
)
this
.
isLogin
=
!!
accessToken
},
onLoginEvent
(
e
)
{
if
(
e
.
detail
.
accessToken
)
{
this
.
isLogin
=
true
}
},
onScreenDoctor
(
e
=
{})
{
// 筛选组件回调
this
.
preScreen
=
e
this
.
paging
=
{
hasMore
:
true
,
}
uni
.
pageScrollTo
({
scrollTop
:
0
,
})
this
.
getData
(
true
)
},
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
=
[]
}
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'
}
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'
})
},
},
onLoad
()
{},
methods
:
{},
}
</
script
>
<
style
lang=
"less"
scoped
>
.content
{
.home
{
position
:
relative
;
background
:
#fff
;
padding
:
94px
0
0
0
;
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
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
}
.logo
{
height
:
200
rpx
;
width
:
200
rpx
;
margin
:
200
rpx
auto
50
rpx
auto
;
}
.player-cover
{
width
:
40px
;
height
:
40px
;
margin-right
:
12px
;
border-radius
:
4px
;
}
}
.text-area
{
.player-info
{
width
:
100%
;
display
:
flex
;
justify-content
:
center
;
}
align-items
:
center
;
}
.player-title
{
font-size
:
16px
;
line-height
:
20px
;
margin-bottom
:
4px
;
}
.title
{
font-size
:
36
rpx
;
color
:
#8f8f94
;
.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
;
}
}
}
.close-player
{
margin-right
:
8px
;
.player-icon
{
width
:
32px
;
height
:
32px
;
vertical-align
:
middle
;
}
}
.player-icon
{
width
:
16px
;
height
:
16px
;
vertical-align
:
middle
;
}
}
</
style
>
src/pages/my/my.vue
View file @
c1dbe7b8
<
template
>
<view>
<phone-login></phone-login>
<view
class=
"my-page"
>
<u-navbar
title=
"我的"
left-icon=
" "
:title-style=
"
{ 'font-weight': 'bold', 'font-size': '18px' }"
fixed
placeholder
bg-color="transparent"
>
</u-navbar>
<view
class=
"user-info"
>
<image
v-if=
"userInfo.head"
class=
"head-image"
:src=
"userInfo.head"
/>
<image
v-else
class=
"head-image"
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-else
@
click=
"handleLoginClick"
>
<text
class=
"user-name"
>
未登录
</text>
<text
class=
"login-tips"
>
点此登录
</text>
</view>
</view>
<view
class=
"list-box"
>
<template
v-for=
"menu in menus"
>
<view
v-if=
"!menu.needLogin || isLogin"
:key=
"menu.label"
class=
"list-item"
@
click=
"handleMenuItemClick(menu)"
>
<image
:src=
"menu.icon"
class=
"item-icon"
/>
<text
class=
"item-label"
>
{{
menu
.
label
}}
</text>
<image
src=
"/static/icon_arrow_right.png"
class=
"arrow-right"
/>
</view>
</
template
>
</view>
<u-modal
:show=
"logoutVisible"
confirm-text=
"退出登录"
:show-cancel-button=
"true"
width=
"72vw"
@
cancel=
"logoutVisible = false"
@
confirm=
"handleLogoutConfirm"
>
<view
class=
"slot-content"
>
<view
class=
"logout-tip-text"
>
是否退出登录?
</view>
</view>
</u-modal>
</view>
</template>
<
script
>
import
PhoneLogin
from
'@/components/phone-login.vue'
import
{
hostPrefix
,
h2Prefix
}
from
'@/config'
import
{
setTrackData
}
from
'@/utils/util'
export
default
{
name
:
'MyPage'
,
components
:
{
PhoneLogin
,
},
data
()
{
return
{}
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
:
()
=>
{
this
.
handleSendMenuTrackData
(
'联系客服'
)
uni
.
makePhoneCall
({
phoneNumber
:
'4007651010'
,
})
},
},
{
icon
:
'/static/icon_introduction.png'
,
label
:
'壹点灵介绍'
,
callback
:
()
=>
{
this
.
handleSendMenuTrackData
(
'壹点灵介绍'
)
uni
.
navigateTo
({
url
:
`/pages/web/web?title=壹点灵介绍&loadUrl=
${
encodeURIComponent
(
`
${
hostPrefix
}
/about`
,
)}
`
,
})
},
},
{
icon
:
'/static/icon_logout.png'
,
label
:
'退出登录'
,
needLogin
:
true
,
callback
:
()
=>
{
this
.
handleSendMenuTrackData
(
'退出登录'
)
this
.
logoutVisible
=
true
},
},
],
logoutVisible
:
false
,
}
},
computed
:
{
// 用户基本信息
userInfo
()
{
return
this
.
$store
.
getters
.
userInfo
},
// 是否登录
isLogin
()
{
return
this
.
$store
.
getters
.
isLogin
},
},
mounted
()
{
// 页面访问埋点
setTrackData
({
events
:
[
{
event_id
:
'page_visit'
,
event_custom_properties
:
{
part
:
'ydl_user_my_page'
,
position
:
''
,
element
:
''
,
},
},
],
})
},
methods
:
{
// 菜单项的埋点
handleSendMenuTrackData
(
content
)
{
setTrackData
({
events
:
[
{
event_id
:
'content_click'
,
event_custom_properties
:
{
part
:
'ydl_user_my_page'
,
position
:
'other_list'
,
element
:
'other_column'
,
content
,
},
},
],
})
},
// 登录点击事件
handleLoginClick
()
{
setTrackData
({
events
:
[
{
event_id
:
'common_click'
,
event_custom_properties
:
{
part
:
'ydl_user_my_page'
,
position
:
'avatar_column'
,
element
:
'login'
,
},
},
],
})
this
.
handleLogin
()
},
// 跳转登录
handleLogin
()
{
uni
.
navigateTo
({
url
:
'/pages/login/login'
,
})
},
// 菜单点击
handleMenuItemClick
({
callback
})
{
callback
&&
callback
()
},
// 退出登录
handleLogoutConfirm
()
{
this
.
logoutVisible
=
false
this
.
$store
.
commit
(
'user/setUserInfo'
,
{})
this
.
$store
.
commit
(
'user/setCode'
,
''
)
this
.
$store
.
commit
(
'user/setUid'
,
''
)
this
.
$store
.
commit
(
'user/setAccessToken'
,
''
)
},
// 跳转订单
navigateToOrder
()
{
if
(
!
this
.
isLogin
)
{
this
.
handleLogin
()
return
}
uni
.
navigateTo
({
url
:
'/pages/order/order'
,
})
},
},
methods
:
{},
}
</
script
>
<
style
></
style
>
<
style
lang=
"less"
scoped
>
.my-page
{
height
:
100%
;
background
:
linear-gradient
(
to
bottom
,
#f3faff
0%
,
#f7f7f7
70%
,
#f7f7f7
100%
);
.user-info
{
padding
:
20px
20px
29px
;
display
:
flex
;
align-items
:
center
;
.head-image
{
width
:
60px
;
height
:
60px
;
border-radius
:
50%
;
}
.user-name
{
margin-left
:
16px
;
color
:
#000000
;
font-weight
:
500
;
font-size
:
18px
;
margin-bottom
:
4px
;
}
.login-tips
{
margin-left
:
16px
;
display
:
block
;
font-size
:
15px
;
color
:
#6ec8f9
;
line-height
:
21px
;
}
}
.list-box
{
padding
:
0
16px
;
.list-item
{
padding
:
0
16px
;
height
:
60px
;
display
:
flex
;
align-items
:
center
;
border-radius
:
8px
;
background-color
:
#ffffff
;
margin-top
:
16px
;
.item-icon
{
width
:
24px
;
height
:
24px
;
margin-right
:
7px
;
}
.item-label
{
color
:
#000000
;
font-weight
:
400
;
font-size
:
16px
;
flex
:
1
;
}
.arrow-right
{
width
:
12px
;
height
:
13px
;
}
}
}
.logout-tip-text
{
font-size
:
4.8vw
;
line-height
:
1.4
;
}
/* modal 弹窗按钮样式 */
.u-modal__button-group__wrapper__text
{
font-size
:
4.8vw
!important
;
}
}
</
style
>
src/plugins/request.js
View file @
c1dbe7b8
...
...
@@ -32,10 +32,14 @@ service.interceptors.response.use(async res => {
store
.
dispatch
(
'user/uniLogin'
)
}
if
(
res
.
status
===
200
&&
res
.
data
)
{
// 有些接口处理逻辑中可能需要根据code进行判断,这里根据raw字段返回全部的数据
if
(
res
.
config
&&
res
.
config
.
raw
)
return
Promise
.
resolve
(
res
.
data
)
const
code
=
+
res
.
data
.
code
if
(
code
===
200
)
{
// 默认返回的是data字段
return
Promise
.
resolve
(
res
.
data
.
data
)
}
else
if
(
code
===
401
)
{
// 未登录,清除用户信息
clearUserInfo
()
uni
.
showToast
({
title
:
'请先登录'
,
...
...
@@ -43,6 +47,7 @@ service.interceptors.response.use(async res => {
})
return
Promise
.
reject
(
new
Error
(
'unlogin'
))
}
else
if
(
// code重复使用或者过期,需要重新获取code
code
===
40029
||
code
===
40163
||
(
res
.
data
.
errMsg
||
res
.
data
.
msg
).
includes
(
'40029'
)
||
...
...
@@ -50,26 +55,28 @@ service.interceptors.response.use(async res => {
)
{
clearUserInfo
()
uni
.
showToast
({
title
:
'
code已
过期,请重新登录'
,
title
:
'
登录
过期,请重新登录'
,
icon
:
'none'
,
})
store
.
dispatch
(
'user/uniLogin'
)
return
Promise
.
reject
(
new
Error
(
'unlogin'
))
}
else
{
if
(
res
.
data
.
errMsg
||
res
.
data
.
msg
)
{
// 错误提示
if
(
res
.
data
.
msg
||
res
.
data
.
errMsg
)
{
// 错误统一处理
uni
.
showToast
({
title
:
res
.
data
.
errMsg
||
res
.
data
.
m
sg
,
title
:
res
.
data
.
msg
||
res
.
data
.
errM
sg
,
icon
:
'none'
,
})
}
return
Promise
.
reject
(
res
.
data
.
errMsg
||
res
.
data
.
m
sg
)
return
Promise
.
reject
(
res
.
data
.
msg
||
res
.
data
.
errM
sg
)
}
}
else
{
return
Promise
.
reject
(
res
)
}
})
// 清除用户信息
const
clearUserInfo
=
()
=>
{
store
.
commit
(
'user/setUserInfo'
,
{})
store
.
commit
(
'user/setCode'
,
''
)
...
...
src/store/modules/user.js
View file @
c1dbe7b8
/* eslint-disable no-undef */
// import request from '@/plugins/request'
import
request
from
'@/plugins/request'
export
default
{
namespaced
:
true
,
...
...
@@ -9,6 +8,7 @@ export default {
code
:
uni
.
getStorageSync
(
'code'
)
||
''
,
uid
:
uni
.
getStorageSync
(
'uid'
)
||
''
,
accessToken
:
uni
.
getStorageSync
(
'accessToken'
)
||
''
,
openId
:
uni
.
getStorageSync
(
'openId'
)
||
''
,
}
},
mutations
:
{
...
...
@@ -28,6 +28,10 @@ export default {
uni
.
setStorageSync
(
'accessToken'
,
data
)
state
.
accessToken
=
data
},
setOpenId
(
state
,
data
)
{
uni
.
setStorageSync
(
'openId'
,
data
)
state
.
openId
=
data
},
},
actions
:
{
uniLogin
({
commit
})
{
...
...
@@ -50,8 +54,44 @@ export default {
},
login
({
commit
},
{
code
,
encryptedData
,
iv
})
{
return
new
Promise
(
async
(
resolve
,
reject
)
=>
{
// TODO 调用登录接口,设置store数据
const
appId
=
uni
.
getAccountInfoSync
().
miniProgram
.
appId
try
{
const
res
=
await
request
.
post
(
`/mini/wx/user/
${
appId
}
/getToken`
,
{
code
,
encryptedData
,
iv
,
},
{
clearCode
:
true
,
},
)
const
{
uid
,
accessToken
,
openId
}
=
res
commit
(
'setUid'
,
uid
)
commit
(
'setAccessToken'
,
accessToken
)
commit
(
'setOpenId'
,
openId
)
resolve
()
}
catch
(
e
)
{
reject
(
e
)
}
})
},
getOpenId
({
commit
})
{
uni
.
login
({
async
success
(
res
)
{
const
appId
=
uni
.
getAccountInfoSync
().
miniProgram
.
appId
try
{
const
result
=
await
request
.
get
(
`/mini/wx/user/
${
appId
}
/login?code=
${
res
.
code
}
`
)
const
{
openid
}
=
result
commit
(
'setOpenId'
,
openid
)
commit
(
'setCode'
,
''
)
}
catch
(
e
)
{}
},
fail
(
e
)
{
console
.
log
(
e
,
'<<<<<<<<获取code失败原因'
)
commit
(
'setCode'
,
''
)
},
})
},
},
...
...
src/style/common.scss
0 → 100644
View file @
c1dbe7b8
page
{
font-size
:
24rpx
;
line-height
:
1
.4
;
font-family
:
'Helvetica Neue'
,
Helvetica
,
'PingFang SC'
,
'Hiragino Sans GB'
,
'Microsoft YaHei'
,
Arial
,
sans-serif
;
background-color
:
#fff
;
color
:
#000
;
-webkit-overflow-scrolling
:
touch
;
-webkit-font-smoothing
:
subpixel-antialiased
;
}
@font-face
{
font-style
:
normal
;
font-weight
:
400
;
font-family
:
'DINCondBold'
;
src
:
url('https://static.ydlcdn.com/weixin/font/DINCond-Bold/DINCond-Bold.ttf')
format
(
'ttf'
)
,
url('https://static.ydlcdn.com/weixin/font/DINCond-Bold/DINCond-Bold.woff')
format
(
'woff'
);
}
.DINCond-Bold
{
}
.container
{
width
:
100%
;
box-sizing
:
border-box
;
}
view
,
scroll-view
,
text
,
checkbox-group
,
checkbox
,
label
,
button
,
input
{
box-sizing
:
border-box
;
}
.box-c
{
padding-left
:
32rpx
;
padding-right
:
32rpx
;
}
.dix
{
display
:
flex
;
}
.alc
{
align-items
:
center
;
}
.jcc
{
justify-content
:
center
;
}
.flexs0
{
flex-shrink
:
0
;
}
.flex1
{
flex
:
1
;
}
.flex2
{
flex
:
2
;
}
.flex3
{
flex
:
3
;
}
.dib
{
display
:
inline-block
;
}
.vm
{
vertical-align
:
middle
;
}
.vt
{
vertical-align
:
top
;
}
.vb
{
vertical-align
:
bottom
;
}
.ff-db
{
font-family
:
'DINCondBold'
;
}
.c-3d
{
color
:
#3d3d3d
;
}
.c-24
{
color
:
#242424
;
}
.c-666
{
color
:
#666
;
}
.c-black
{
color
:
#000
;
}
.fs30
{
font-size
:
30rpx
;
}
.fs32
{
font-size
:
32rpx
;
}
.fs36
{
font-size
:
36rpx
;
}
.fs38
{
font-size
:
38rpx
;
}
.fs40
{
font-size
:
40rpx
;
}
.pl10
{
padding-left
:
10rpx
;
}
.pl20
{
padding-left
:
20rpx
;
}
.pr20
{
padding-right
:
20rpx
;
}
.pt30
{
padding-top
:
30rpx
;
}
.pt50
{
padding-top
:
50rpx
;
}
.pb2
{
padding-bottom
:
2rpx
;
}
.pb4
{
padding-bottom
:
4rpx
;
}
.pb8
{
padding-bottom
:
8rpx
;
}
.pb30
{
padding-bottom
:
30rpx
;
}
.mt6
{
margin-top
:
6rpx
;
}
.mt8
{
margin-top
:
8rpx
;
}
.mt9
{
margin-top
:
9rpx
;
}
.mt10
{
margin-top
:
10rpx
;
}
.mt12
{
margin-top
:
12rpx
;
}
.mr20
{
margin-right
:
20rpx
;
}
.mr8
{
margin-right
:
8rpx
;
}
.mr10
{
margin-right
:
10rpx
;
}
.ml2
{
margin-left
:
2rpx
;
}
.ml4
{
margin-left
:
4rpx
;
}
.ml6
{
margin-left
:
6rpx
;
}
.mr2
{
margin-right
:
2rpx
;
}
.ml20
{
margin-left
:
20rpx
;
}
.ml30
{
margin-left
:
30rpx
;
}
.mxw120
{
max-width
:
120rpx
;
}
.w180
{
width
:
180rpx
;
}
.tr
{
text-align
:
right
;
}
.b
{
font-weight
:
bold
;
}
.f500
{
font-weight
:
500
;
}
.y-btn
{
color
:
#ffffff
;
border
:
none
;
}
button
:
:
after
{
border
:
none
;
}
.y-btn_primary
{
background
:
linear-gradient
(
to
right
,
#23b2fa
,
#1da0f2
);
}
.y-btn_default
{
color
:
#999
;
background
:
#f7f7f7
;
border
:
1rpx
solid
#e0e0e0
;
}
.y-icon-star
{
width
:
22rpx
;
height
:
22rpx
;
}
.y-check
{
position
:
absolute
;
left
:
-9999px
;
}
.weui-dialog__btn
{
display
:
block
;
flex
:
1
;
color
:
#576b95
;
border-radius
:
0
;
line-height
:
3
;
text-decoration
:
none
;
-webkit-tap-highlight-color
:
rgba
(
0
,
0
,
0
,
0
);
position
:
relative
;
}
.weui-dialog__btn.default
{
}
.weui-dialog__btn.primary
{
color
:
#fff
;
background
:
linear-gradient
(
to
right
,
#4db4f5
,
#157dd5
);
}
.weui-dialog
{
position
:
fixed
;
z-index
:
5000
;
width
:
80%
;
max-width
:
300px
;
top
:
50%
;
left
:
50%
;
font-size
:
32rpx
;
-webkit-transform
:
translate
(
-50%
,
-50%
);
transform
:
translate
(
-50%
,
-50%
);
background-color
:
#ffffff
;
text-align
:
center
;
border-radius
:
5px
;
overflow
:
hidden
;
}
.weui-dialog__bd
{
padding-top
:
70rpx
;
padding-bottom
:
60rpx
;
text-align
:
center
;
}
.weui-dialog__ft
{
display
:
flex
;
}
.weui-mask
{
position
:
fixed
;
z-index
:
1000
;
top
:
0
;
right
:
0
;
left
:
0
;
bottom
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0
.6
);
}
.ellipsis
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
word-break
:
break-word
;
}
.ellipsis2
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
word-break
:
break-word
;
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
-webkit-line-clamp
:
2
;
}
src/utils/enums.js
0 → 100644
View file @
c1dbe7b8
export
const
tabs
=
[
{
name
:
'排序'
,
id
:
1
,
},
{
name
:
'性别年龄'
,
id
:
2
,
},
{
name
:
'擅长方向'
,
id
:
3
,
},
]
export
const
sortLib
=
{
title
:
'排序'
,
data
:
[
{
name
:
'综合排序'
,
id
:
1
,
},
{
name
:
'人气从高到低'
,
id
:
2
,
},
{
name
:
'时间从新到旧'
,
id
:
3
,
},
],
}
export
const
sexType
=
{
title
:
'性别筛选'
,
data
:
[
{
id
:
1
,
name
:
'只看男生'
},
{
id
:
2
,
name
:
'只看女生'
},
],
}
export
const
ageType
=
{
title
:
'年龄筛选'
,
data
:
[
{
id
:
0
,
name
:
'50后'
},
{
id
:
1
,
name
:
'60后'
},
{
id
:
2
,
name
:
'70后'
},
{
id
:
3
,
name
:
'80后'
},
{
id
:
4
,
name
:
'90后'
},
{
id
:
5
,
name
:
'00后'
},
],
}
export
const
goodDirection
=
{
title
:
'擅长方向'
,
data
:
[
{
id
:
1
,
name
:
'恋爱情感'
},
{
id
:
2
,
name
:
'婚姻家庭'
},
{
id
:
4
,
name
:
'情绪压力'
},
{
id
:
5
,
name
:
'亲子教育'
},
{
id
:
7
,
name
:
'职场发展'
},
{
id
:
8
,
name
:
'人际社交'
},
{
id
:
9
,
name
:
'个人成长'
},
],
}
src/utils/util.js
View file @
c1dbe7b8
...
...
@@ -29,8 +29,9 @@ export const setTrackData = ({ events = [], beforeEvent = null }) => {
const
result
=
request
.
post
(
'/dmp-event/v1/events/bulk'
,
{
app_name
:
''
,
// 应用名称,根据实际项目定义填写
os_type
:
4
,
// 操作系统类型,小程序
// todo
app_name
:
'todo_ydllisten'
,
// 应用名称
os_type
:
4
,
// 操作系统类型
time
:
Date
.
now
(),
os
:
res
.
system
,
os_version
:
res
.
version
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment