Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
U
uniapp_vedio
Project
Project
Details
Activity
Releases
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
android
uniapp_vedio
Commits
2187139f
Commit
2187139f
authored
Jan 02, 2025
by
jyx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
删除无用代码,代码优化
parent
7f2ac0a7
Changes
40
Show whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
58 additions
and
6692 deletions
+58
-6692
index.js
vedio/common/services/index.js
+5
-2
c-login.vue
vedio/components/c-login/c-login.vue
+0
-232
popup.vue
vedio/components/popup/popup.vue
+0
-91
read-time-count-row.vue
vedio/components/read-time-count-row/read-time-count-row.vue
+1
-1
book-content.vue
vedio/page-subs/sub_A/book-content/book-content.vue
+0
-347
bean-pop.vue
vedio/page-subs/sub_A/book-content/components/bean-pop.vue
+0
-354
detail-bottom.vue
...page-subs/sub_A/book-content/components/detail-bottom.vue
+0
-205
detail-buy.vue
vedio/page-subs/sub_A/book-content/components/detail-buy.vue
+0
-493
detail-content.vue
...age-subs/sub_A/book-content/components/detail-content.vue
+0
-161
detail-new-buy.vue
...age-subs/sub_A/book-content/components/detail-new-buy.vue
+0
-282
detail-thumb.vue
.../page-subs/sub_A/book-content/components/detail-thumb.vue
+0
-150
detail-warn.vue
...o/page-subs/sub_A/book-content/components/detail-warn.vue
+0
-38
recommend-pop.vue
...page-subs/sub_A/book-content/components/recommend-pop.vue
+0
-351
setting-pop.vue
...o/page-subs/sub_A/book-content/components/setting-pop.vue
+0
-164
vip-pop.vue
vedio/page-subs/sub_A/book-content/components/vip-pop.vue
+0
-320
BookDetail.js
vedio/page-subs/sub_A/book-content/models/BookDetail.js
+0
-34
ContentFormat.js
vedio/page-subs/sub_A/book-content/models/ContentFormat.js
+0
-16
index.js
vedio/page-subs/sub_A/book-content/services/index.js
+0
-111
book-cover.vue
vedio/page-subs/sub_A/book-cover/book-cover.vue
+0
-46
header.vue
vedio/page-subs/sub_A/book-cover/components/header.vue
+0
-8
book-long-content.vue
...o/page-subs/sub_A/book-long-content/book-long-content.vue
+0
-303
bean-pop.vue
...page-subs/sub_A/book-long-content/components/bean-pop.vue
+0
-325
catalogue-pop.vue
...subs/sub_A/book-long-content/components/catalogue-pop.vue
+0
-158
detail-bottom.vue
...subs/sub_A/book-long-content/components/detail-bottom.vue
+0
-212
detail-buy.vue
...ge-subs/sub_A/book-long-content/components/detail-buy.vue
+0
-493
detail-content.vue
...ubs/sub_A/book-long-content/components/detail-content.vue
+0
-267
detail-new-buy.vue
...ubs/sub_A/book-long-content/components/detail-new-buy.vue
+0
-282
detail-thumb.vue
...-subs/sub_A/book-long-content/components/detail-thumb.vue
+0
-150
detail-warn.vue
...e-subs/sub_A/book-long-content/components/detail-warn.vue
+0
-38
recommend-pop.vue
...subs/sub_A/book-long-content/components/recommend-pop.vue
+0
-351
setting-pop.vue
...e-subs/sub_A/book-long-content/components/setting-pop.vue
+0
-164
vip-pop.vue
.../page-subs/sub_A/book-long-content/components/vip-pop.vue
+0
-320
BookDetail.js
vedio/page-subs/sub_A/book-long-content/models/BookDetail.js
+0
-16
CatalogueList.js
...page-subs/sub_A/book-long-content/models/CatalogueList.js
+0
-16
ContentFormat.js
...page-subs/sub_A/book-long-content/models/ContentFormat.js
+0
-19
index.js
vedio/page-subs/sub_A/book-long-content/services/index.js
+0
-130
pages.json
vedio/pages.json
+0
-18
readerRecord.vue
vedio/pagesD/readerRecord/readerRecord.vue
+0
-10
storage-keys.js
vedio/static/keys/storage-keys.js
+0
-4
novelManager.js
vedio/utils/novelManager.js
+52
-10
No files found.
vedio/common/services/index.js
View file @
2187139f
...
...
@@ -54,6 +54,7 @@ let startReadTime = null; // 开始阅读时间
*/
function
startCountReadTime
()
{
startReadTime
=
new
Date
();
console
.
log
(
'AAAAAA---startCountReadTime------->'
)
}
/**
* 停止阅读计时
...
...
@@ -79,6 +80,8 @@ function endCountReadTime() {
count
=
endReadTime
.
getTime
()
-
dayStart
.
getTime
();
}
startReadTime
=
null
;
console
.
log
(
'AAAAAA---endCountReadTime------->'
+
count
)
setReadTimeCount
(
count
);
}
...
...
vedio/components/c-login/c-login.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
"pop"
type=
"center"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"login-content"
>
<view
class=
"close-button"
@
click
.
stop=
"tapMask"
>
<view
class=
"icon-box"
>
<uni-icons
type=
'closeempty'
size=
"24"
color=
"#cc6008"
></uni-icons>
</view>
</view>
<view
class=
"welcome-msg"
>
快速登录
</view>
<view
class=
"login-button"
>
<image
class=
"logo"
src=
"/static/images/logo.png"
mode=
"scaleToFill"
></image>
<view
class=
"info"
>
授权登录
</view>
<button
class=
"c-button_clear cover-button"
@
click=
"getPhoneNumber"
></button>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../common/mixins/system-info-mixin.js"
;
import
{
addNormalNotificationObserver
,
postNotification
,
removeNotificationObserver
}
from
"../../common/utils/notificationCenter.js"
;
import
{
px2rpx
}
from
"../../common/utils/util.js"
;
import
{
KEY_NOTIFICATION_LOGIN_SHOW
,
KEY_NOTIFICATION_LOGIN_SUCCESS
}
from
"../../static/keys/notification-keys.js"
import
{
login
,
logout
}
from
"../../common/services/userServices.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
name
:
"c-login"
,
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
isShareLink
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
showPop
:
false
,
};
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
mounted
()
{
addNormalNotificationObserver
(
KEY_NOTIFICATION_LOGIN_SHOW
,
(
info
)
=>
{
if
(
this
.
showPop
!=
info
.
show
)
{
this
.
showPop
=
info
.
show
}
},
this
);
addNormalNotificationObserver
(
KEY_NOTIFICATION_LOGIN_SUCCESS
,
()
=>
{
this
.
showPop
=
false
;
},
this
)
},
destroyed
()
{
removeNotificationObserver
(
KEY_NOTIFICATION_LOGIN_SUCCESS
,
this
);
removeNotificationObserver
(
KEY_NOTIFICATION_LOGIN_SHOW
,
this
);
},
methods
:
{
open
()
{
this
.
$refs
.
pop
.
open
();
},
close
()
{
this
.
$refs
.
pop
.
close
();
postNotification
(
KEY_NOTIFICATION_LOGIN_SHOW
,
{
show
:
false
})
},
tapMask
()
{
logout
(()
=>
{},
true
);
this
.
showPop
=
false
;
postNotification
(
KEY_NOTIFICATION_LOGIN_SHOW
,
{
show
:
false
})
},
getPhoneNumber
()
{
this
.
ttLoging
();
},
ttLoging
()
{
var
that
=
this
;
var
obj
=
wx
.
getLaunchOptionsSync
()
var
bookId
=
''
;
var
thirdParam
=
''
;
var
tips2
=
''
;
// 抖音feed页参数
thirdParam
=
JSON
.
stringify
(
obj
.
query
);
bookId
=
obj
.
query
.
book_id
??
''
tips2
=
obj
.
query
.
tips2
??
''
if
(
this
.
tips1
==
'mints_book'
||
tips2
==
'mints_book'
)
{
this
.
slotParam
=
JSON
.
stringify
(
obj
.
query
);
this
.
$refs
.
select
.
open
(
'center'
);
}
wx
.
login
({
force
:
true
,
success
(
res
)
{
login
({
vedioId
:
bookId
,
code
:
res
.
code
,
thirdParam
:
thirdParam
})
},
fail
(
res
)
{
},
});
}
}
}
</
script
>
<
style
lang=
"scss"
>
.login-content
{
position
:
relative
;
width
:
500rpx
;
height
:
300rpx
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
background-color
:
#fff
;
border-radius
:
20rpx
;
overflow
:
hidden
;
.close-button
{
position
:
absolute
;
width
:
220rpx
;
height
:
220rpx
;
top
:
0
;
right
:
0
;
transform
:
translate
(
50%
,
-50%
);
background
:
#faefe6
;
z-index
:
2
;
border-radius
:
50%
;
.icon-box
{
position
:
absolute
;
left
:
30%
;
bottom
:
30%
;
transform
:
translate
(
-50%
,
50%
);
}
}
.welcome-msg
{
font-size
:
36rpx
;
color
:
#333
;
font-weight
:
700
;
}
.login-button
{
position
:
relative
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
center
;
height
:
100rpx
;
line-height
:
100rpx
;
margin-top
:
30rpx
;
width
:
400rpx
;
background
:
black
;
color
:
#fff
;
border-radius
:
20rpx
;
.logo
{
width
:
60rpx
;
height
:
60rpx
;
border-radius
:
30rpx
;
border
:
2rpx
solid
#fff
;
}
.info
{
height
:
100rpx
;
color
:
#fff
;
line-height
:
100rpx
;
font-size
:
30rpx
;
margin-left
:
20rpx
;
}
.cover-button
{
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
z-index
:
2
;
background
:
transparent
;
}
}
}
</
style
>
\ No newline at end of file
vedio/components/popup/popup.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
:class=
"'popup-mask ' + (showClone ? 'popup-mask-active' : '')"
@
click
.
stop
.
prevent=
""
>
<view
class=
"popup-content"
>
<view
class=
"popup-body"
><slot></slot></view>
<icons
v-if=
"close"
icon=
"close"
size=
"64"
color=
"white"
@
click=
"handleClose"
/>
</view>
</view>
</
template
>
<
script
>
export
default
{
name
:
'popup'
,
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
close
:
{
type
:
Boolean
,
default
:
true
}
},
data
()
{
return
{
showClone
:
false
};
},
methods
:
{
handleClose
()
{
this
.
showClone
=
false
;
this
.
$emit
(
'close'
);
}
},
watch
:
{
show
:
{
handler
:
function
(
newVal
,
oldVal
)
{
this
.
showClone
=
newVal
;
},
immediate
:
true
}
}
};
</
script
>
<
style
lang=
"scss"
>
.popup
{
position
:
fixed
;
z-index
:
1002
;
left
:
75rpx
;
right
:
75rpx
;
top
:
50%
;
padding
:
0
;
display
:
none
;
transform
:
translate
(
0
,
-50%
);
backface-visibility
:
hidden
;
&
-content
{
position
:
relative
;
top
:
50%
;
transform
:
translateY
(
-50%
);
text-align
:
center
;
}
&
-body
{
border-radius
:
32rpx
;
// overflow: hidden;
// background-color: #323231;
margin-bottom
:
40rpx
;
position
:
relative
;
z-index
:
-1
;
}
&
-mask
{
position
:
fixed
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
z-index
:
999
;
background-color
:
rgba
(
0
,
0
,
0
,
0
.8
);
opacity
:
0
;
transform
:
scale3d
(
1
,
1
,
0
);
transition
:
all
0
.3s
;
padding
:
77rpx
;
&
-active
{
opacity
:
1
;
transform
:
scale3d
(
1
,
1
,
1
);
}
}
}
</
style
>
vedio/components/read-time-count-row/read-time-count-row.vue
View file @
2187139f
vedio/page-subs/sub_A/book-content/book-content.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<z-paging
:style=
"[bgStyle]"
>
<c-empty
v-if=
'showEmpty'
></c-empty>
<template
v-else
>
<detail-warn></detail-warn>
<detail-thumb
:detail=
'bookData'
@
tapThumb=
'tapThumb'
></detail-thumb>
<detail-content
@
tapVip=
'tapPayPop'
:detail=
'bookData'
:userInfo=
'userInfo'
></detail-content>
<detail-new-buy
v-if=
"bookData.isUnlock==0 && !isVip()"
:showVipOpen=
"1"
:showBeanOpen=
"0"
:detail=
'bookData'
:userInfo=
'userInfo'
@
unlockBook=
'unlockBook'
@
tapVip=
'tapVipPop'
@
tapBean=
'tapBeanPop'
></detail-new-buy>
<detail-bottom
:detail=
'bookData'
:userInfo=
'userInfo'
@
tapBottomItem=
'tapBottomItem'
></detail-bottom>
<setting-pop
:show=
'showSetting'
@
close=
'closePop'
></setting-pop>
<!--
<vip-pop
v-if=
"bookData.isUnlock==0 && !isVip()"
:show=
'showVip'
@
close=
'closeVipPop'
></vip-pop>
<bean-pop
v-if=
"bookData.isUnlock==0 && userInfo.bookLegumes
<bookData
.
bookLegumes
"
:show=
'showBean'
@
close=
'closeBeanPop'
></bean-pop>
-->
<recommend-pop
:show=
'showRecommend'
@
close=
'closeRecommendPop'
:bookId=
"bookId"
></recommend-pop>
<coin-popup
v-if=
"bookData.isUnlock==0 && !isVip()"
:show=
"showVip"
@
close=
"closeVipPop"
:vedioId=
"bookData.id"
@
paySuccess=
"paySuccess"
>
</coin-popup>
</
template
>
<c-login
:isShareLink=
"true"
></c-login>
<popup
:show=
"showMoibleLogin"
@
close=
"showMoibleLogin=false"
>
<view>
<button
open-type=
"getPhoneNumber"
@
getphonenumber=
"MygetPhonenumber"
>
<view>
请先绑定手机号
</view>
<view
style=
"color:green;"
>
去绑定
</view>
</button>
</view>
</popup>
</z-paging>
</template>
<
script
>
import
{
isEmpty
}
from
"../../../common/utils/util.js"
;
import
BookDetail
from
"./models/BookDetail.js"
;
import
{
getBookDetailData
,
watchContentFormatChange
,
removeContentFormatChangeWatch
,
addReadRecord
}
from
"./services/index.js"
import
{
collectionBook
}
from
"../../../common/services/index.js"
import
DetailWarn
from
"./components/detail-warn.vue"
;
import
DetailThumb
from
"./components/detail-thumb.vue"
;
import
DetailContent
from
"./components/detail-content.vue"
;
import
DetailBottom
from
"./components/detail-bottom.vue"
;
import
DetailNewBuy
from
"./components/detail-new-buy.vue"
;
import
config
from
"../../../config/index.js"
;
import
SettingPop
from
"./components/setting-pop.vue"
;
import
VipPop
from
"./components/vip-pop.vue"
;
import
BeanPop
from
"./components/bean-pop.vue"
;
import
RecommendPop
from
"./components/recommend-pop.vue"
;
import
SystemInfoMixin
from
"../../../common/mixins/system-info-mixin.js"
;
import
{
gotoBookCoverPage
}
from
"../../../common/services/page-route.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
refreshUserInfo
,
postPhone
}
from
"../../../common/services/userServices.js"
import
{
noticeCollectionListChange
,
startCountReadTime
,
endCountReadTime
,
getOpens
}
from
"../../../common/services/index.js"
import
{
saveStorage
,
readStorage
}
from
"../../../common/utils/storageUtil.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
components
:
{
DetailWarn
,
DetailThumb
,
DetailContent
,
DetailNewBuy
,
DetailBottom
,
SettingPop
,
VipPop
,
BeanPop
,
RecommendPop
,
},
data
()
{
return
{
bookId
:
null
,
bookData
:
null
,
backgroundColor
:
"#fff"
,
showSetting
:
false
,
showVip
:
false
,
showBean
:
false
,
showRecommend
:
false
,
userInfo
:
null
,
showVipOpen
:
0
,
showBeanOpen
:
0
,
showMoibleLogin
:
false
,
mobileLoginLock
:
false
,
};
},
onLoad
(
options
)
{
if
(
options
.
bookId
)
{
// 非navigate进入,读取path参数
this
.
bookId
=
options
.
bookId
;
}
else
{
// navigate 进入,接受channel传参
const
eventChannel
=
this
.
getOpenerEventChannel
();
eventChannel
.
on
(
"openBookContentPage"
,
(
info
)
=>
{
this
.
bookId
=
info
.
bookId
;
})
}
this
.
mobileLoginLock
=
readStorage
(
"KEY_NEED_PHONE"
)
},
onReady
()
{
// 监听样式变动
watchContentFormatChange
((
data
)
=>
{
let
result
=
data
.
getFormatValue
();
if
(
this
.
backgroundColor
!=
result
.
backgroundColor
)
{
this
.
backgroundColor
=
result
.
backgroundColor
}
},
this
)
// 监听用户变动
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
// 用户已登录需要记录阅读记录
if
(
info
.
userInfo
&&
this
.
bookId
)
{
addReadRecord
(
this
.
bookId
)
}
if
(
this
.
isVip
()
&&
this
.
bookData
)
{
this
.
unlockBook
()
}
// 用户变动,需要刷新数据
this
.
$nextTick
(()
=>
{
this
.
refreshBookData
(
this
.
bookId
)
})
},
this
)
// 绑定分享参数
// #ifdef MP-WEIXIN
wx
.
onCopyUrl
(()
=>
{
return
{
query
:
`bookId=
${
this
.
bookData
.
id
}
`
}
})
// #endif
},
onShow
()
{
refreshUserInfo
();
// 开始记录阅读时长
startCountReadTime
();
},
onHide
()
{
// 停止记录阅读时长
endCountReadTime
();
},
onUnload
()
{
// 停止记录阅读时长,部分情况下页面无法响应onHide事件
endCountReadTime
();
// 移除监听
removeContentFormatChangeWatch
(
this
);
removeUserInfoChangeWatch
(
this
);
// 取消绑定分享参数
// #ifdef MP-WEIXIN
wx
.
offCopyUrl
()
// #endif
},
onPullDownRefresh
()
{},
// 文章分享
onShareAppMessage
()
{
let
result
=
{
title
:
this
.
bookData
.
title
,
imageUrl
:
this
.
bookData
.
cover
,
path
:
'/pages/loading?shareId='
}
return
result
;
},
computed
:
{
showEmpty
:
function
()
{
return
isEmpty
(
this
.
bookData
)
},
bgStyle
:
function
()
{
let
height
=
300
;
if
(
this
.
windowHeight
)
{
height
=
this
.
windowHeight
;
}
return
{
minHeight
:
`
${
height
}
px`
,
position
:
"relative"
,
background
:
this
.
backgroundColor
}
}
},
watch
:
{
bookData
:
{
handler
:
function
(
n
)
{
if
(
n
)
{
uni
.
setNavigationBarTitle
({
title
:
`阅读:
${
n
.
title
}
`
})
}
}
}
},
methods
:
{
async
MygetPhonenumber
(
e
)
{
console
.
log
(
e
.
detail
.
code
)
// 动态令牌
console
.
log
(
e
.
detail
.
errMsg
)
// 回调信息(成功失败都会返回)
console
.
log
(
e
.
detail
.
errno
)
// 错误码(失败时返回)
this
.
showMoibleLogin
=
false
if
(
e
.
detail
.
code
==
undefined
||
e
.
detail
.
code
==
''
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
e
.
detail
.
errMsg
})
return
}
var
params
=
{
userId
:
this
.
userInfo
.
userid
,
code
:
e
.
detail
.
code
,
}
postPhone
(
params
,
(
success
,
result
)
=>
{
if
(
success
)
{
saveStorage
(
"KEY_NEED_PHONE"
,
false
);
this
.
mobileLoginLock
=
false
this
.
tapPayPop
()
}
else
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"网络错误!"
})
}
})
},
// 解锁回调
unlockBook
()
{
this
.
$set
(
this
.
bookData
,
"isUnlock"
,
true
);
},
// 文章数据刷新
refreshBookData
(
bookId
)
{
getBookDetailData
(
bookId
,
(
success
,
data
)
=>
{
// uni.stopPullDownRefresh();
if
(
success
)
{
data
.
isUnlock
=
1
this
.
bookData
=
new
BookDetail
(
data
);
// console.log('bookData=' + JSON.stringify(this.bookData));
}
})
},
paySuccess
()
{
// this.$set(this.bookData, "isUnlock", true);
},
// 点击底部按钮
tapBottomItem
(
e
)
{
let
flag
=
e
.
detail
.
flag
;
switch
(
flag
)
{
case
'like'
:
// 点赞
break
;
case
'collection'
:
// 收藏
let
target
=
!
this
.
bookData
.
isCollect
;
collectionBook
(
target
,
this
.
bookId
,
(
success
,
data
)
=>
{
if
(
success
)
{
this
.
$set
(
this
.
bookData
,
'isCollect'
,
target
);
noticeCollectionListChange
(
this
.
bookId
,
target
);
}
})
break
;
case
'setting'
:
// 设置
this
.
showSetting
=
true
;
break
;
default
:
break
;
}
},
isVip
()
{
if
(
this
.
userInfo
!=
null
&&
this
.
userInfo
.
memberExpirationDate
>
0
)
{
return
true
;
}
return
false
;
},
tapPayPop
()
{
if
(
this
.
showVipOpen
!=
1
&&
this
.
showBeanOpen
==
1
)
{
this
.
tapBeanPop
()
return
}
this
.
tapVipPop
()
},
// 展示充值VIP弹框
tapVipPop
()
{
// if (this.mobileLoginLock) {
// this.showMoibleLogin = true
// return
// }
this
.
showVip
=
true
;
},
// 展示充值书豆弹框
tapBeanPop
()
{
if
(
this
.
mobileLoginLock
)
{
this
.
showMoibleLogin
=
true
return
}
this
.
showBean
=
true
;
},
// 关闭设置弹窗
closePop
(
e
)
{
this
.
showSetting
=
false
;
},
// 关闭会员弹窗
closeVipPop
(
e
)
{
this
.
showVip
=
false
;
setTimeout
(()
=>
{
this
.
showRecommend
=
true
;
},
300
);
},
// 关闭书豆弹窗
closeBeanPop
(
e
)
{
this
.
showBean
=
false
;
setTimeout
(()
=>
{
this
.
showRecommend
=
true
;
},
300
);
},
// 关闭推荐弹窗
closeRecommendPop
(
e
)
{
this
.
showRecommend
=
false
;
},
// 点击封面,暂无
tapThumb
(
e
)
{
gotoBookCoverPage
(
this
.
bookData
.
id
);
}
}
}
</
script
>
<
style
lang=
"scss"
>
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/bean-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'beanpop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
充值书豆,订阅全本
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packData'
:key='index' @click="choosePack(item, index)">
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"cut-down"
v-if=
'item.giveNumber'
>
赠送
{{
item
.
giveNumber
}}
书豆
</view>
</view>
</view>
</view>
<view
class=
"section"
>
<button
class=
"c-button_clear c-button-size_lg c-button-width_full apply-button"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapPay"
>
立即购买
</button>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
getBookBeanPackData
,
getOpenId
,
getPayInfo
,
ENUM_PAY_TYPE
}
from
"../../../../common/services/index.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
userInfo
:
null
,
packData
:
[],
selectedIndex
:
0
,
loading
:
false
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
beanCount
:
function
()
{
if
(
this
.
userInfo
)
return
this
.
userInfo
.
bookLegumes
;
return
0
;
}
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onReady
()
{
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
},
this
)
},
onUnload
()
{
removeUserInfoChangeWatch
(
this
);
},
mounted
()
{
this
.
requestPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
beanpop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
beanpop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
requestPackData
()
{
getBookBeanPackData
((
success
,
data
)
=>
{
uni
.
stopPullDownRefresh
()
if
(
success
)
{
this
.
packData
=
data
.
map
(
item
=>
{
return
new
BookBeanPack
(
item
)
})
}
})
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packData
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
},
ENUM_PAY_TYPE
.
BEAN
.
value
)
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
// uni.requestPayment({
// timeStamp: payInfo.timeStamp,
// nonceStr: payInfo.nonceStr,
// package: payInfo.packageStr,
// signType: payInfo.signType,
// paySign: payInfo.paySign,
// success: (res) => {
// if (typeof successCB == 'function') successCB(res);
// },
// fail: (error) => {
// this.loading = false;
// }
// })
// 头条支付
if
(
!
tt
.
canIUse
(
'requestOrder'
))
{
toastMessage
(
'请升级抖音APP版本!'
)
return
}
if
(
!
tt
.
canIUse
(
'getOrderPayment'
))
{
toastMessage
(
'请升级抖音APP版本~'
)
return
}
tt
.
requestOrder
({
data
:
payInfo
.
params
.
data
,
byteAuthorization
:
payInfo
.
params
.
byteAuthorization
,
success
(
res
)
{
tt
.
getOrderPayment
({
orderId
:
res
.
oid
,
success
(
res2
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res2
);
},
fail
(
res2
)
{
console
.
log
(
'android=ttPay res.errMsg'
,
res2
)
},
});
},
fail
(
res
)
{
console
.
log
(
'requestOrder res.errMsg'
,
res
)
},
});
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'购买成功'
)
refreshUserInfo
();
})
})
})
})
}
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-bottom.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-bottom"
:style=
"[bottomStyle]"
>
<view
class=
"fixed-bottom"
:style=
"[fixedBottomStyle,
{backgroundColor:backgroundColor}]">
<!--
<view
class=
"bottom-item"
@
click=
"tapItem('like')"
>
<uni-icons
:type=
'likeIcon.type'
customPrefix=
"readiconfont"
:color=
'likeIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: likeIcon.color}">
赞
</view>
</view>
-->
<!--
<view
class=
"bottom-item"
@
click=
"tapItem('diss')"
>
<uni-icons
:type=
'dissIcon.type'
customPrefix=
"readiconfont"
:color=
'dissIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: dissIcon.color}">
踩
</view>
</view>
-->
<view
class=
"bottom-item"
@
click=
"tapItem('collection')"
>
<uni-icons
:type=
'collectionIcon.type'
customPrefix=
"readiconfont"
:color=
'collectionIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: collectionIcon.color}">
{{
collectionIcon
.
title
}}
</view>
</view>
<view
class=
"bottom-item"
@
click=
"tapItem('setting')"
>
<uni-icons
type=
'icon-setting'
customPrefix=
"readiconfont"
color=
'#333'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: '#333'}">
设置
</view>
</view>
<view
class=
"bottom-item"
>
<uni-icons
type=
'icon-share'
customPrefix=
"readiconfont"
color=
'#333'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: '#333'}">
分享
</view>
<button
class=
"c-button_clear cover-button"
open-type=
"share"
></button>
</view>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlaceholderStyle]"
></view>
</view>
</
template
>
<
script
>
import
{
watchContentFormatChange
,
removeContentFormatChangeWatch
}
from
"../services/index.js"
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
import
{
showLoginView
}
from
"../../../../common/services/userServices.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
}
},
data
:
function
()
{
return
{
height
:
`100`
,
backgroundColor
:
`#fff`
}
},
mounted
()
{
// 监听样式变动
watchContentFormatChange
((
data
)
=>
{
let
result
=
data
.
getFormatValue
();
if
(
this
.
backgroundColor
!=
result
.
backgroundColor
)
{
this
.
backgroundColor
=
result
.
backgroundColor
}
},
this
)
},
destroyed
()
{
removeContentFormatChangeWatch
(
this
);
},
computed
:
{
fixedBottomStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
bottom
:
`
${
height
}
rpx`
}
},
safePlaceholderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
bottomStyle
:
function
()
{
let
height
=
100
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
likeIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isLike
?
'icon-like'
:
'icon-unlike'
,
color
:
this
.
detail
.
isLike
?
'#FECF02'
:
"#333"
}
},
dissIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isDiss
?
'icon-diss'
:
'icon-undiss'
,
color
:
this
.
detail
.
isDiss
?
'#FECF02'
:
"#333"
}
},
collectionIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isCollect
?
'icon-collection'
:
'icon-uncollection'
,
color
:
this
.
detail
.
isCollect
?
'#FECF02'
:
"#333"
,
title
:
this
.
detail
.
isCollect
?
"已收藏"
:
"收藏"
}
}
},
methods
:
{
tapItem
(
flag
)
{
if
(
flag
==
'collection'
&&
!
this
.
userInfo
)
{
showLoginView
();
return
;
}
this
.
$emit
(
"tapBottomItem"
,
{
detail
:
{
flag
,
item
:
this
.
detail
}
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-bottom
{
position
:
relative
;
height
:
100rpx
;
.fixed-bottom
{
position
:
fixed
;
background
:
#fff
;
bottom
:
0
;
left
:
0
;
right
:
0
;
height
:
100rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
.bottom-item
{
position
:
relative
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
height
:
100%
;
// width: 33.3333333333%;
flex
:
1
;
.title
{
font-size
:
24rpx
;
margin-top
:
10rpx
;
}
.cover-button
{
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
transparent
;
z-index
:
2
;
}
}
}
.safe-placeholder
{
position
:
fixed
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
#fff
;
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-buy.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-buy"
>
<view
class=
"book-card"
>
<view
class=
"cover-box"
>
<image
class=
"cover"
:src=
"detail.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"info-box"
>
<view
class=
"row"
>
<view
class=
"book-title"
>
{{
detail
.
title
}}
</view>
<view
class=
"book-value"
>
{{
bookBeanCount
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"desc"
>
{{
detail
.
summary
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"c-flex_row c-align_center"
>
<uni-icons
type=
'icon-author'
custom-prefix=
"readiconfont"
size=
'20'
color=
'#378eff'
></uni-icons>
<view
class=
"book-author"
>
{{
detail
.
author
}}
</view>
</view>
<view
class=
"buy-button disable-button"
v-if=
'detail.isUnlock'
>
已购买
</view>
<view
class=
"buy-button"
@
click=
"tapBuy"
v-else
>
购买
</view>
</view>
</view>
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packList'
:key='index' @click="choosePack(item, index)">
<template
v-if=
'item.isBeanPack'
>
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"cut-down"
v-if=
'item.giveNumber'
>
赠送
{{
item
.
giveNumber
}}
书豆
</view>
</
template
>
<
template
v-else
>
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"origin row"
v-if=
'item.originalPrice'
>
原价:
{{
item
.
originalPrice
}}
</view>
<view
class=
"cut-down"
v-if=
'item.cutDown'
>
立省
{{
item
.
cutDown
}}
元
</view>
</
template
>
</view>
</view>
<view
class=
"warn-box"
>
<view
class=
"warn-p"
>
1.目前充值会员暂不支持退款,一经购买不可退换
</view>
<view
class=
"warn-p"
>
2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作
</view>
<view
class=
"warn-p"
>
3.充值一般在5分钟内到账,如未到账请提供支付截图在"我的"页面联系客服
</view>
<view
class=
"warn-p"
>
4.之前充值账户请登录后继续阅读
</view>
</view>
</view>
</template>
<
script
>
import
Pack
from
"../../../../common/models/Pack.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
getPackData
,
getOpenId
,
getPayInfo
,
getBookBeanPackData
,
ENUM_PAY_TYPE
,
buyBookWithBookBean
}
from
"../../../../common/services/index.js"
;
import
{
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastHide
,
toastLoading
,
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
}
},
data
:
function
()
{
return
{
packList
:
[],
vipPackList
:
[],
beanPackList
:
[],
selectedIndex
:
0
,
loading
:
false
,
imageError
:
true
}
},
computed
:
{
bookBeanCount
:
function
()
{
return
this
.
detail
&&
this
.
detail
.
bookLegumes
?
`
${
this
.
detail
.
bookLegumes
}
书豆`
:
"免费"
},
payButtonTitle
:
function
()
{
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
return
(
pack
instanceof
Pack
)
?
"购买会员"
:
"购买书豆并解锁本书"
},
packChange
:
function
()
{
const
{
vipPackList
,
beanPackList
}
=
this
;
return
{
vipPackList
,
beanPackList
}
}
},
watch
:
{
packChange
:
{
handler
:
function
(
n
)
{
this
.
packList
=
this
.
getPackList
(
n
.
vipPackList
,
n
.
beanPackList
);
},
deep
:
true
}
},
mounted
()
{
this
.
refreshPackData
();
},
methods
:
{
loadImage
()
{
this
.
imageError
=
false
},
errorImage
()
{
this
.
imageError
=
true
},
refreshPackData
()
{
// getPackData((success, data) => {
// if (success) {
// this.vipPackList = data.map(item => {
// let result = new Pack(item);
// result.isBeanPack = false;
// return result;
// })
// }
// })
getBookBeanPackData
((
success
,
data
)
=>
{
if
(
success
)
{
this
.
beanPackList
=
data
.
map
(
item
=>
{
let
result
=
new
BookBeanPack
(
item
);
result
.
isBeanPack
=
true
;
return
result
;
})
}
})
},
getPackList
(
vipPackList
,
beanPackList
)
{
let
vip
=
vipPackList
||
[];
let
bean
=
beanPackList
||
[];
return
[
...
vip
,
...
bean
];
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
this
.
tapPay
();
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
},
(
pack
instanceof
Pack
)
?
ENUM_PAY_TYPE
.
VIP
.
value
:
ENUM_PAY_TYPE
.
BEAN
.
value
)
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
uni
.
requestPayment
({
timeStamp
:
payInfo
.
timeStamp
,
nonceStr
:
payInfo
.
nonceStr
,
package
:
payInfo
.
packageStr
,
signType
:
payInfo
.
signType
,
paySign
:
payInfo
.
paySign
,
success
:
(
res
)
=>
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'会员购买成功'
)
refreshUserInfo
();
})
})
})
})
}
},
tapBuy
()
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
uni
.
showModal
({
title
:
"余额不足"
,
content
:
`当前余额:
${
this
.
userInfo
.
bookLegumes
}
, 请前往充值`
,
showCancel
:
false
,
confirmText
:
"知道了"
})
return
;
}
toastLoading
(
"购买中"
);
buyBookWithBookBean
(
this
.
detail
.
id
,
(
success
,
data
)
=>
{
toastHide
();
if
(
success
)
{
this
.
$emit
(
"unlockBook"
)
}
})
},
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-buy
{
display
:
flex
;
flex-direction
:
column
;
.book-card
{
margin
:
20rpx
;
padding
:
20rpx
;
background
:
#fdf6f0
;
border-radius
:
20rpx
;
display
:
flex
;
flex-direction
:
row
;
.cover-box
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
.cover
{
width
:
140rpx
;
height
:
180rpx
;
border-radius
:
15rpx
;
}
}
.info-box
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
margin-left
:
20rpx
;
.row
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
space-between
;
}
.row
:last-child
{}
.book-title
{
color
:
#333
;
font-size
:
36rpx
;
font-weight
:
700
;
}
.book-value
{
color
:
goldenrod
;
font-size
:
40rpx
;
font-weight
:
700
;
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
24rpx
;
color
:
#999
}
.book-author
{
color
:
#999
;
font-size
:
28rpx
;
}
.buy-button
{
background
:
#caad9c
;
color
:
#333
;
height
:
60rpx
;
line-height
:
60rpx
;
width
:
180rpx
;
text-align
:
center
;
border-radius
:
10rpx
;
font-size
:
30rpx
;
color
:
#fff
;
}
.disable-button
{
background
:
#ededed
;
color
:
#888
;
}
}
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.warn-box
{
color
:
#956244
;
font-size
:
26rpx
;
display
:
flex
;
flex-direction
:
column
;
padding
:
30rpx
;
.warn-p
{
margin-bottom
:
15rpx
;
}
.warn-p
:last-child
{
margin-bottom
:
0
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-content.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-content"
>
<template
v-if=
'showVIPContent'
>
<view
class=
"content-paragraph"
:style=
"[contentStyle]"
v-for=
'(item, index) in contentSources'
:key=
'index'
>
{{
item
}}
</view>
</
template
>
<
template
v-else
>
<view
class=
"content-paragraph"
:style=
"[contentStyle]"
v-for=
'(item, index) in preContentSources'
:key=
"index"
>
{{
item
}}
</view>
<view
class=
"limit-button-box"
@
click=
"tapVip"
>
{{
limitButtonTitle
}}
</view>
</
template
>
</view>
</template>
<
script
>
import
{
watchContentFormatChange
,
removeContentFormatChangeWatch
}
from
"../services/index.js"
import
{
showLoginView
}
from
"../../../../common/services/userServices.js"
import
{
gotoVIPApplyPage
}
from
"../../../../common/services/page-route.js"
import
User
from
"../../../../common/models/User.js"
;
export
default
{
props
:
{
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
},
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
}
},
data
:
function
()
{
return
{
user
:
null
,
fontSize
:
`18px`
,
PRECENT_VALUE
:
40
}
},
mounted
()
{
watchContentFormatChange
((
data
)
=>
{
let
result
=
data
.
getFormatValue
();
if
(
this
.
fontSize
!=
result
.
fontSize
)
{
this
.
fontSize
=
result
.
fontSize
}
},
this
)
},
destroyed
()
{
removeContentFormatChangeWatch
(
this
);
},
watch
:
{
userInfo
:
{
handler
:
function
(
n
)
{
if
(
n
)
{
this
.
user
=
new
User
(
n
)
}
else
{
this
.
user
=
null
}
},
deep
:
true
,
immediate
:
true
}
},
computed
:
{
contentSources
:
function
()
{
return
[...
this
.
detail
.
free
,
...
this
.
detail
.
charge
];
},
preContentSources
:
function
()
{
return
this
.
detail
&&
this
.
detail
.
free
?
[...
this
.
detail
.
free
]
:
[];
},
limitButtonTitle
:
function
()
{
let
result
=
`后续内容更精彩`
;
if
(
!
this
.
user
)
{
result
=
`
${
result
}
,点击登录后继续阅读`
;
}
else
if
(
!
this
.
user
.
isVip
())
{
result
=
`
${
result
}
,充值后继续阅读`
}
result
=
`
${
result
}
~`
;
return
result
;
},
contentStyle
:
function
()
{
return
{
fontSize
:
this
.
fontSize
}
},
showVIPContent
:
function
()
{
return
(
this
.
user
&&
this
.
user
.
isVip
())
||
this
.
detail
.
isUnlock
}
},
methods
:
{
tapLimitButton
()
{
if
(
!
this
.
user
)
{
showLoginView
()
}
else
if
(
!
this
.
user
.
isVip
())
{
gotoVIPApplyPage
()
}
},
tapVip
()
{
let
isIOS
=
wx
.
getSystemInfoSync
().
platform
;
if
(
isIOS
===
'ios'
)
{
uni
.
showToast
({
title
:
'暂不支持IOS系统'
,
icon
:
'none'
})
return
}
// 展示充值VIP弹框
this
.
$emit
(
'tapVip'
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-content
{
paading
:
20rpx
30rpx
;
margin
:
20rpx
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.content-paragraph
{
text-indent
:
1em
;
word-wrap
:
break-word
;
word-break
:
break-all
;
white-space
:
normal
;
line-height
:
1
.5em
;
margin-bottom
:
1em
;
color
:
#333
;
}
.content-paragraph
:last-child
{
margin-bottom
:
0
;
}
.limit-button-box
{
text-indent
:
0
;
height
:
120rpx
;
line-height
:
120rpx
;
text-align
:
center
;
color
:
goldenrod
;
font-size
:
28rpx
;
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-new-buy.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-buy"
>
<view
class=
"book-card"
>
<view
class=
"line-box"
>
<view
class=
"line"
></view>
<view
class=
"text"
>
全本订阅超优惠
</view>
<view
class=
"line"
></view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"text-box"
>
<view
class=
"text1"
>
全本特价:
</view>
<view
class=
"text2"
>
{{
bookBeanCount
}}
</view>
<view
class=
"text1"
>
书豆
</view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"text-box"
style=
"margin-top: 20rpx;"
>
<view
class=
"text1"
>
账户余额:
</view>
<view
class=
"text2"
>
{{
bookAllBeanCount
}}
</view>
<view
class=
"text1"
>
书豆
</view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"section"
style=
"margin-top: 30rpx;"
>
<button
class=
"btn1"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapBeanBtn"
>
{{
bookBeanText
}}
</button>
</view>
<view
v-if=
"!isVip() && (showVipOpen==1)"
class=
"section"
style=
"margin-top: 30rpx;"
>
<button
class=
"btn2"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapVip"
>
开通会员,免费阅读本书
</button>
</view>
</view>
<view
class=
"warn-box"
>
<view
class=
"warn-p"
>
1.目前充值会员暂不支持退款,一经购买不可退换
</view>
<view
class=
"warn-p"
>
2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作
</view>
<view
class=
"warn-p"
>
3.充值一般在5分钟内到账,如未到账请提供支付截图在"我的"页面联系客服
</view>
<view
class=
"warn-p"
>
4.之前充值账户请登录后继续阅读
</view>
</view>
</view>
</
template
>
<
script
>
import
Pack
from
"../../../../common/models/Pack.js"
;
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
showLoginView
,
}
from
"../../../../common/services/userServices.js"
import
{
buyBookWithBookBean
}
from
"../../../../common/services/index.js"
;
import
{
toastHide
,
toastLoading
,
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
},
showVipOpen
:
{
type
:
Number
,
default
:
1
},
showBeanOpen
:
{
type
:
Number
,
default
:
1
}
},
data
:
function
()
{
return
{
selectedIndex
:
0
,
loading
:
false
,
imageError
:
true
}
},
computed
:
{
bookBeanText
:
function
()
{
if
(
this
.
userInfo
&&
this
.
detail
)
{
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
return
'余额不足,立即充值'
}
}
return
'全本订阅'
;
},
bookAllBeanCount
:
function
()
{
if
(
this
.
userInfo
)
return
this
.
userInfo
.
bookLegumes
return
0
;
},
bookBeanCount
:
function
()
{
return
this
.
detail
&&
this
.
detail
.
bookLegumes
?
`
${
this
.
detail
.
bookLegumes
}
`
:
"免费"
},
},
mounted
()
{
},
methods
:
{
isVip
()
{
if
(
this
.
userInfo
!=
null
&&
this
.
userInfo
.
memberFlag
)
{
let
cDate
=
new
Date
();
cDate
=
cDate
.
getTime
();
return
this
.
userInfo
.
memberExpirationDate
>=
cDate
;
}
return
false
;
},
tapBeanBtn
()
{
let
isIOS
=
wx
.
getSystemInfoSync
().
platform
;
if
(
isIOS
===
'ios'
)
{
uni
.
showToast
({
title
:
'暂不支持IOS系统'
,
icon
:
'none'
})
return
}
if
(
this
.
userInfo
&&
this
.
detail
)
{
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
this
.
tapBean
()
return
}
}
this
.
tapBuy
()
},
tapVip
()
{
let
isIOS
=
wx
.
getSystemInfoSync
().
platform
;
if
(
isIOS
===
'ios'
)
{
uni
.
showToast
({
title
:
'暂不支持IOS系统'
,
icon
:
'none'
})
return
}
// 展示充值VIP弹框
this
.
$emit
(
'tapVip'
)
},
tapBean
()
{
// 展示充值书豆弹框
this
.
$emit
(
'tapBean'
)
},
tapBuy
()
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
uni
.
showModal
({
title
:
"余额不足"
,
content
:
`当前余额:
${
this
.
userInfo
.
bookLegumes
}
, 请前往充值`
,
showCancel
:
false
,
confirmText
:
"知道了"
})
return
;
}
toastLoading
(
"购买中"
);
buyBookWithBookBean
(
this
.
detail
.
id
,
(
success
,
data
)
=>
{
toastHide
();
if
(
success
)
{
this
.
$emit
(
"unlockBook"
)
}
})
},
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-buy
{
display
:
flex
;
flex-direction
:
column
;
.book-card
{
margin
:
20rpx
;
padding
:
20rpx
;
// background: #fdf6f0;
// border-radius: 20rpx;
display
:
flex
;
flex-direction
:
column
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.btn1
{
color
:
white
;
background-image
:
linear-gradient
(
90deg
,
pink
,
#DCBD3B
);
width
:
100%
;
height
:
80rpx
;
text-align
:
center
;
border-radius
:
80rpx
;
line-height
:
80rpx
;
}
.btn2
{
color
:
#DCBD3B
;
border
:
#DCBD3B
solid
1rpx
;
width
:
100%
;
text-align
:
center
;
border-radius
:
80rpx
;
height
:
80rpx
;
line-height
:
80rpx
;
}
}
.line-box
{
display
:
flex
;
flex-direction
:
row
;
padding
:
30rpx
;
flex-wrap
:
wrap
;
align-items
:
center
;
.line
{
width
:
30%
;
background-color
:
lightgray
;
height
:
1rpx
;
}
.text
{
text-align
:
center
;
width
:
36%
;
color
:
lightgray
;
font-size
:
26rpx
;
}
}
.text-box
{
display
:
flex
;
flex-direction
:
row
;
.text1
{
font-size
:
24rpx
;
color
:
black
;
}
.text2
{
padding
:
0
10rpx
;
font-size
:
24rpx
;
color
:
#DCBD3B
;
}
}
}
.warn-box
{
color
:
#956244
;
font-size
:
26rpx
;
display
:
flex
;
flex-direction
:
column
;
padding
:
30rpx
;
.warn-p
{
margin-bottom
:
15rpx
;
}
.warn-p
:last-child
{
margin-bottom
:
0
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-thumb.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-thumb"
@
click=
"tapThumb"
>
<view
class=
"content"
>
<view
class=
"cover-box item"
>
<image
class=
"cover"
:src=
"detail.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"info-box item"
>
<view
class=
"row"
>
<view
class=
"title"
>
{{
detail
.
title
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"desc"
>
{{
detail
.
summary
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"author-box"
>
<uni-icons
type=
'icon-author'
custom-prefix=
"readiconfont"
size=
'20'
color=
'#378eff'
></uni-icons>
<view
class=
"name"
>
{{
detail
.
author
}}
</view>
</view>
</view>
</view>
</view>
</view>
</
template
>
<
script
>
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
}
},
data
:
function
()
{
return
{
imageError
:
true
}
},
methods
:
{
tapThumb
()
{
this
.
$emit
(
'tapThumb'
,
{
detail
:
{
data
:
this
.
detail
}
})
},
loadImage
()
{
this
.
imageError
=
false
},
errorImage
()
{
this
.
imageError
=
true
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
page
{
background
:
#fff
;
}
.detail-thumb
{
padding
:
15rpx
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.content
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
border-radius
:
18rpx
;
background
:
#f5f5f5
;
padding
:
20rpx
;
.row
{
margin-bottom
:
20rpx
;
}
.row
:last-child
{
margin-bottom
:
0
;
}
.item
{
margin-right
:
20rpx
;
}
.item
:last-child
{
margin-right
:
0
;
}
.cover-box
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
.cover
{
width
:
140rpx
;
height
:
180rpx
;
border-radius
:
15rpx
;
}
}
.info-box
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
.title
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
24rpx
;
color
:
#999
}
.author-box
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
height
:
50rpx
;
line-height
:
50rpx
;
.name
{
font-size
:
26rpx
;
color
:
#378eff
;
margin-left
:
15rpx
;
}
}
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/detail-warn.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
v-if=
"false"
class=
"detail-warn"
>
<view
class=
"content"
>
<uni-icons
type=
'chatboxes'
size=
"20"
color=
"#aa8062"
></uni-icons>
<view
class=
"value"
>
"本故事纯属虚构,仅供娱乐,无不良引导"
</view>
</view>
</view>
</
template
>
<
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-warn
{
padding
:
15rpx
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.content
{
height
:
100rpx
;
line-height
:
100rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
border-radius
:
18rpx
;
background
:
#f4e9eb
;
color
:
#aa8062
;
padding
:
0
30rpx
;
.value
{
font-size
:
28rpx
;
margin-left
:
15rpx
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/recommend-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'recommendpop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
99%读过这本书的人还在读
</view>
<view
class=
"book-list-item"
v-for=
'(item, index) in dataList'
:key=
'index'
:item=
'item'
@
click=
"tapItem(item)"
>
<view
class=
"cover-box item"
>
<image
v-if=
"item.avatar===''"
class=
"cover"
src=
"/static/images/logo.png"
mode=
"aspectFill"
>
</image>
<image
v-else
class=
"cover"
:src=
"item.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"c-flex_column"
>
<view
class=
"c-flex_row c-justify_between row"
>
<view
class=
"c-flex_column c-justify_center item"
>
<view
class=
"title2"
>
{{
item
.
title
}}
</view>
</view>
</view>
<view
class=
"c-flex_row row"
>
<view
class=
"c-flex_column c-justify_between content c-flex_1 item"
>
<view
class=
"desc row"
>
{{
item
.
summary
}}
</view>
<view
class=
"c-flex_row c-align_center label-box row"
>
<slot
name=
"footer"
>
<view
class=
"label label-color-1"
v-if=
"item.categoryName!=null&&item.categoryName!=''"
>
{{
item
.
categoryName
}}
</view>
<view
class=
"label label-color-2"
v-for=
'(label, labelIndex) in item.tagList'
:key=
'labelIndex'
>
{{
label
.
name
}}
</view>
</slot>
</view>
</view>
</view>
</view>
<view
style=
"display: flex;margin: auto;width: 200rpx;"
>
<button
class=
"btn2"
>
去阅读
</button>
</view>
</view>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
{
gotoBookContentPage
}
from
'../../../../common/services/page-route'
import
{
getBookRecommendData
}
from
"../services/index.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
bookId
:
{
type
:
[
Number
,
String
],
default
:
0
}
},
data
:
function
()
{
return
{
showPop
:
false
,
dataList
:
[]
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
}
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onUnload
()
{},
mounted
()
{
this
.
requestPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
recommendpop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
recommendpop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
requestPackData
()
{
getBookRecommendData
(
this
.
bookId
,
(
success
,
data
)
=>
{
if
(
success
)
{
this
.
dataList
=
data
.
records
;
}
})
},
tapItem
(
item
)
{
// 在C页面内 navigateBack,将返回A页面
uni
.
navigateBack
({
delta
:
2
});
gotoBookContentPage
(
item
.
wechatRecord
.
wxId
,
item
.
id
);
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#DCBD3B
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
.book-list-item
{
display
:
flex
;
flex-direction
:
row
;
padding-top
:
14rpx
;
padding-bottom
:
14rpx
;
.row
{
margin-bottom
:
20rpx
;
}
.row
:last-child
{
margin-bottom
:
0
;
}
.item
{
margin-right
:
20rpx
;
}
.item
:last-child
{
margin-right
:
0
;
}
.title
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.close-button
{
border-radius
:
10rpx
;
border
:
2rpx
solid
#999
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
width
:
40rpx
;
height
:
30rpx
;
position
:
relative
;
.cover
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
width
:
70rpx
;
height
:
70rpx
;
transform
:
translate
(
-50%
,
-50%
);
z-index
:
2
;
background
:
transparent
;
}
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
26rpx
;
color
:
#999
}
.label-box
{
flex-wrap
:
wrap
;
.label
{
padding
:
5rpx
10rpx
;
font-size
:
20rpx
;
margin-right
:
20rpx
;
border-radius
:
10rpx
;
}
.label-color-1
{
background
:
#faefe6
;
color
:
#cc6008
;
}
.label-color-2
{
color
:
#3d99fd
;
background
:
#d8ebff
;
}
.label-color-3
{
background
:
#ff8787
;
color
:
#ff3737
;
}
}
}
.cover-box
{
.cover
{
width
:
150rpx
;
height
:
200rpx
;
border-radius
:
15rpx
;
}
}
.title2
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.btn2
{
color
:
#d98c5c
;
border
:
#DCBD3B
solid
1rpx
;
width
:
140rpx
;
font-size
:
24rpx
;
text-align
:
center
;
border-radius
:
80rpx
;
height
:
40rpx
;
line-height
:
40rpx
;
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/setting-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'pop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
change=
'change'
>
<view
class=
"setting-box"
>
<view
class=
"row"
>
<view
class=
"title"
>
字体大小
</view>
<view
class=
"zone"
>
<view
class=
"c-flex_1"
>
<slider
min=
"14"
max=
"24"
step=
'1'
:value=
'currentContentFormat.fontSize'
:show-value=
"true"
@
change=
'changeFontSize'
>
</slider>
</view>
</view>
</view>
<view
class=
"row"
>
<view
class=
"title"
>
背景颜色
</view>
<view
class=
"zone"
>
<view
class=
"color-item"
:class=
"
{'selected-color': item.value==currentContentFormat.backgroundColor}"
:style="[item.style]" v-for='(item, index) in colorList' :key="index"
@click="chooseColor(item.value)">
</view>
</view>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
import
{
saveContentFormat
,
readContentFormat
}
from
"../services/index.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
colorList
:
[],
currentContentFormat
:
{},
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
mounted
()
{
this
.
initColorList
();
this
.
currentContentFormat
=
readContentFormat
()
},
methods
:
{
open
()
{
this
.
$refs
.
pop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
pop
.
close
();
},
change
(
e
)
{
if
(
this
.
showPop
==
e
.
show
)
return
;
this
.
showPop
=
e
.
show
},
initColorList
()
{
this
.
colorList
=
[
"#fff"
,
"#e7e7e7"
,
"#d4e0c6"
,
"#ccd8e4"
,
"#f9d4d4"
,
"#b1b1b1"
].
map
(
item
=>
{
return
{
style
:
{
background
:
item
},
value
:
item
}
})
},
changeFontSize
(
e
)
{
let
fontSize
=
e
.
detail
.
value
;
this
.
currentContentFormat
.
fontSize
=
fontSize
;
saveContentFormat
(
this
.
currentContentFormat
);
},
chooseColor
(
color
)
{
this
.
currentContentFormat
.
backgroundColor
=
color
;
saveContentFormat
(
this
.
currentContentFormat
);
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
padding
:
20rpx
;
background
:
#fff
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.row
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
padding
:
20rpx
;
.title
{
font-size
:
30rpx
;
font-weight
:
700
;
margin-bottom
:
20rpx
;
}
.zone
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
space-around
;
.color-item
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
40rpx
;
border
:
2rpx
solid
#999
;
}
.selected-color
{
width
:
100rpx
;
height
:
100rpx
;
border-radius
:
50rpx
;
border
:
5rpx
solid
#ff2525
;
}
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/components/vip-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'vippop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
开通会员,继续阅读
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packList'
:key='index' @click="choosePack(item, index)">
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"origin row"
v-if=
'item.originalPrice'
>
原价:
{{
item
.
originalPrice
}}
</view>
<view
class=
"cut-down"
v-if=
'item.cutDown'
>
立省
{{
item
.
cutDown
}}
元
</view>
</view>
</view>
</view>
<view
class=
"section"
>
<button
class=
"c-button_clear c-button-size_lg c-button-width_full apply-button"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapPay"
>
立即开通
</button>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
Pack
from
"../../../../common/models/Pack.js"
;
import
{
getPackData
,
getOpenId
,
getPayInfo
}
from
"../../../../common/services/index.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
packList
:
[],
selectedIndex
:
0
,
loading
:
false
,
userInfo
:
null
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onReady
()
{
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
},
this
)
},
onUnload
()
{
removeUserInfoChangeWatch
(
this
);
},
mounted
()
{
this
.
refrehsPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
vippop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
vippop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
refrehsPackData
()
{
// getPackData((success, data) => {
// this.packList = data.map(item => {
// return new Pack(item);
// })
// })
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
})
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
uni
.
requestPayment
({
timeStamp
:
payInfo
.
timeStamp
,
nonceStr
:
payInfo
.
nonceStr
,
package
:
payInfo
.
packageStr
,
signType
:
payInfo
.
signType
,
paySign
:
payInfo
.
paySign
,
success
:
(
res
)
=>
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'会员购买成功'
)
refreshUserInfo
();
})
})
})
})
}
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-content/models/BookDetail.js
deleted
100644 → 0
View file @
7f2ac0a7
import
Book
from
"../../../../common/models/Book"
;
export
default
class
BookDetail
extends
Book
{
constructor
(
param
)
{
super
(
param
);
const
{
contentMd
,
freeMd
,
chargeMd
,
}
=
param
||
{}
this
.
contentMd
=
contentMd
;
this
.
freeMd
=
freeMd
;
this
.
chargeMd
=
chargeMd
;
let
result
=
contentMd
?
contentMd
.
replace
(
/<
[^
>
]
+>/g
,
""
)
:
""
;
result
=
result
.
split
(
"
\n
"
);
this
.
content
=
result
.
filter
(
item
=>
{
return
item
.
split
(
/
[\t\r\f\n\s]
*/g
).
join
(
""
);
});
let
result2
=
freeMd
?
freeMd
.
replace
(
/<
[^
>
]
+>/g
,
""
)
:
""
;
result2
=
result2
.
split
(
"
\n
"
);
this
.
free
=
result2
.
filter
(
item
=>
{
return
item
.
split
(
/
[\t\r\f\n\s]
*/g
).
join
(
""
);
});
let
result3
=
chargeMd
?
chargeMd
.
replace
(
/<
[^
>
]
+>/g
,
""
)
:
""
;
result3
=
result3
.
split
(
"
\n
"
);
this
.
charge
=
result3
.
filter
(
item
=>
{
return
item
.
split
(
/
[\t\r\f\n\s]
*/g
).
join
(
""
);
});
console
.
log
(
'param------'
,
param
)
}
}
\ No newline at end of file
vedio/page-subs/sub_A/book-content/models/ContentFormat.js
deleted
100644 → 0
View file @
7f2ac0a7
export
default
class
ContentFormat
{
constructor
(
param
)
{
const
{
fontSize
,
backgroundColor
}
=
param
||
{}
this
.
fontSize
=
fontSize
;
this
.
backgroundColor
=
backgroundColor
;
}
getFormatValue
()
{
return
{
fontSize
:
`
${
this
.
fontSize
}
px`
,
backgroundColor
:
this
.
backgroundColor
}
}
}
\ No newline at end of file
vedio/page-subs/sub_A/book-content/services/index.js
deleted
100644 → 0
View file @
7f2ac0a7
import
{
addNormalNotificationObserver
,
postNotification
,
removeNotificationObserver
}
from
"../../../../common/utils/notificationCenter"
;
import
{
readStorage
,
saveStorage
}
from
"../../../../common/utils/storageUtil"
;
import
ContentFormat
from
"../models/ContentFormat"
;
import
{
apiGET
,
apiPOST
}
from
"../../../../common/utils/apiRequest.js"
/** 获取文章详情
* @param {Object} bookId
* @param {Object} callback
*/
function
getBookDetailData
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/info`
,
data
:
{
id
:
bookId
},
callback
})
}
/** 获取推荐文章
* @param {Object} bookId
* @param {Object} callback
*/
function
getBookRecommendData
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/recommend`
,
data
:
{
id
:
bookId
},
callback
})
}
/** 添加阅读记录
* @param {Object} bookId
* @param {Object} callback
*/
function
addReadRecord
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/addReadRecord`
,
data
:
{
articleId
:
bookId
},
callback
})
}
// 样式设置
const
KEY_STORAGE_CONTENT_FORMAT
=
"KEY_SOTRAGE_CONTENT_FORMAT"
;
const
KEY_NOTIFICATION_CONTENT_FORMAT_CHANGE
=
"KEY_NOTIFICATION_CONTENT_FORMAT_CHANGE"
;
function
saveContentFormat
(
format
)
{
let
result
=
readContentFormat
();
Object
.
keys
(
format
).
forEach
(
key
=>
{
let
value
=
format
[
key
];
result
[
key
]
=
value
||
result
[
key
];
})
saveStorage
(
KEY_STORAGE_CONTENT_FORMAT
,
result
);
notifyContentFormatChange
(
new
ContentFormat
(
result
));
}
function
readContentFormat
()
{
let
result
=
readStorage
(
KEY_STORAGE_CONTENT_FORMAT
);
if
(
result
)
{
result
=
new
ContentFormat
(
result
);
}
else
{
result
=
new
ContentFormat
({
fontSize
:
17
,
backgroundColor
:
"#fff"
})
}
return
result
;
}
function
notifyContentFormatChange
(
format
)
{
postNotification
(
KEY_NOTIFICATION_CONTENT_FORMAT_CHANGE
,
format
);
}
function
watchContentFormatChange
(
fn
,
observer
)
{
if
(
typeof
fn
==
'function'
)
fn
.
call
(
observer
,
readContentFormat
());
addNormalNotificationObserver
(
KEY_NOTIFICATION_CONTENT_FORMAT_CHANGE
,
(
data
)
=>
{
if
(
typeof
fn
==
'function'
)
fn
.
call
(
observer
,
data
);
},
observer
)
}
function
removeContentFormatChangeWatch
(
observer
)
{
removeNotificationObserver
(
KEY_NOTIFICATION_CONTENT_FORMAT_CHANGE
,
observer
);
}
module
.
exports
=
{
getBookDetailData
,
getBookRecommendData
,
addReadRecord
,
/**
* content format
*/
saveContentFormat
,
readContentFormat
,
notifyContentFormatChange
,
watchContentFormatChange
,
removeContentFormatChangeWatch
}
\ No newline at end of file
vedio/page-subs/sub_A/book-cover/book-cover.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view>
<c-login></c-login>
</view>
</
template
>
<
script
>
export
default
{
data
()
{
return
{
bookId
:
null
,
bookCoverData
:
null
};
},
onReady
()
{
const
eventChannel
=
this
.
getOpenerEventChannel
();
eventChannel
.
on
(
"openBookCoverPage"
,
(
info
)
=>
{
this
.
bookId
=
info
.
bookId
})
},
watch
:
{
bookId
:
function
(
n
)
{
if
(
n
)
{
this
.
$nextTick
(()
=>
{
uni
.
startPullDownRefresh
({
})
})
}
}
},
onPullDownRefresh
()
{
this
.
refreshBookCoverData
(
this
.
bookId
)
},
methods
:
{
refreshBookCoverData
(
bookId
)
{
}
}
}
</
script
>
<
style
lang=
"scss"
>
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-cover/components/header.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
</
template
>
<
script
>
</
script
>
<
style
>
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/book-long-content.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
:style=
"[bgStyle]"
>
<c-empty
v-if=
'showEmpty'
></c-empty>
<template
v-else
>
<detail-content
ref=
"content"
:detail=
'bookData'
@
tabVip2=
"tapVipPop"
@
changeCurrent=
"changeCurrent"
></detail-content>
<detail-bottom
:detail=
'bookData'
:userInfo=
'userInfo'
@
tapBottomItem=
'tapBottomItem'
></detail-bottom>
<setting-pop
:show=
'showSetting'
@
close=
'closePop'
></setting-pop>
<catalogue-pop
:detail=
'bookData'
:show=
'showCatalogue'
@
close=
'closeCataPop'
:current=
"current"
@
tabVip=
'tapVipPop'
></catalogue-pop>
<!--
<vip-pop
v-if=
"bookData.isUnlock==0 && !isVip()"
:show=
'showVip'
@
close=
'closeVipPop'
></vip-pop>
<bean-pop
v-if=
"bookData.isUnlock==0 && userInfo.bookLegumes
<bookData
.
bookLegumes
"
:show=
'showBean'
@
close=
'closeBeanPop'
></bean-pop>
-->
<recommend-pop
:show=
'showRecommend'
@
close=
'closeRecommendPop'
:bookId=
"bookId"
></recommend-pop>
<coin-popup
v-if=
"bookData.isUnlock==0 && !isVip()"
:show=
"showVip"
@
close=
"closeVipPop"
:vedioId=
"bookData.id"
>
</coin-popup>
</
template
>
</view>
</template>
<
script
>
import
{
isEmpty
}
from
"../../../common/utils/util.js"
;
import
BookDetail
from
"./models/BookDetail.js"
;
import
{
getBookDetailData
,
addReadRecord
}
from
"./services/index.js"
import
{
collectionBook
}
from
"../../../common/services/index.js"
import
DetailWarn
from
"./components/detail-warn.vue"
;
import
DetailThumb
from
"./components/detail-thumb.vue"
;
import
DetailContent
from
"./components/detail-content.vue"
;
import
DetailBottom
from
"./components/detail-bottom.vue"
;
import
DetailNewBuy
from
"./components/detail-new-buy.vue"
;
import
config
from
"../../../config/index.js"
;
import
SettingPop
from
"./components/setting-pop.vue"
;
import
CataloguePop
from
"./components/catalogue-pop.vue"
;
import
VipPop
from
"./components/vip-pop.vue"
;
import
BeanPop
from
"./components/bean-pop.vue"
;
import
RecommendPop
from
"./components/recommend-pop.vue"
;
import
SystemInfoMixin
from
"../../../common/mixins/system-info-mixin.js"
;
import
{
gotoBookCoverPage
}
from
"../../../common/services/page-route.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
refreshUserInfo
,
postPhone
}
from
"../../../common/services/userServices.js"
import
{
noticeCollectionListChange
,
startCountReadTime
,
endCountReadTime
,
getOpens
}
from
"../../../common/services/index.js"
import
{
saveStorage
,
readStorage
}
from
"../../../common/utils/storageUtil.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
components
:
{
DetailWarn
,
DetailThumb
,
DetailContent
,
DetailNewBuy
,
DetailBottom
,
SettingPop
,
VipPop
,
BeanPop
,
RecommendPop
,
CataloguePop
},
data
()
{
return
{
bookId
:
null
,
bookData
:
null
,
showSetting
:
false
,
showCatalogue
:
false
,
showVip
:
false
,
showBean
:
false
,
showRecommend
:
false
,
userInfo
:
null
,
showVipOpen
:
0
,
showBeanOpen
:
0
,
current
:
1
};
},
onLoad
(
options
)
{
if
(
options
.
bookId
)
{
// 非navigate进入,读取path参数
this
.
bookId
=
options
.
bookId
;
}
else
{
// navigate 进入,接受channel传参
const
eventChannel
=
this
.
getOpenerEventChannel
();
eventChannel
.
on
(
"openBookContentPage"
,
(
info
)
=>
{
this
.
bookId
=
info
.
bookId
;
})
}
},
onReady
()
{
// 监听用户变动
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
// 用户已登录需要记录阅读记录
if
(
info
.
userInfo
&&
this
.
bookId
)
{
addReadRecord
(
this
.
bookId
)
}
if
(
this
.
isVip
()
&&
this
.
bookData
)
{
this
.
paySuccess
()
}
// // 用户变动,需要刷新数据
// this.$nextTick(() => {
// uni.startPullDownRefresh({})
// })
},
this
)
this
.
$nextTick
(()
=>
{
uni
.
startPullDownRefresh
({})
})
// 绑定分享参数
// #ifdef MP-WEIXIN
wx
.
onCopyUrl
(()
=>
{
return
{
query
:
`bookId=
${
this
.
bookData
.
id
}
`
}
})
// #endif
},
onShow
()
{
refreshUserInfo
();
// 开始记录阅读时长
startCountReadTime
();
},
onHide
()
{
// 停止记录阅读时长
endCountReadTime
();
},
onUnload
()
{
// 停止记录阅读时长,部分情况下页面无法响应onHide事件
endCountReadTime
();
// 移除监听
removeUserInfoChangeWatch
(
this
);
// 取消绑定分享参数
// #ifdef MP-WEIXIN
wx
.
offCopyUrl
()
// #endif
},
onPullDownRefresh
()
{
this
.
refreshBookData
(
this
.
bookId
)
},
// 文章分享
onShareAppMessage
()
{
let
result
=
{
title
:
this
.
bookData
.
title
,
imageUrl
:
this
.
bookData
.
cover
,
type
:
config
.
env
==
'Prod'
?
0
:
config
.
env
==
'Dev'
?
1
:
2
,
path
:
`/page-subs/sub_A/book-long-content/book-long-content?bookId=
${
this
.
bookData
.
id
}
`
}
return
result
;
},
computed
:
{
showEmpty
:
function
()
{
return
isEmpty
(
this
.
bookData
)
},
bgStyle
:
function
()
{
let
height
=
300
;
if
(
this
.
windowHeight
)
{
height
=
this
.
windowHeight
;
}
return
{
minHeight
:
`
${
height
}
px`
,
position
:
"relative"
,
}
}
},
watch
:
{
bookData
:
{
handler
:
function
(
n
)
{
if
(
n
)
{
uni
.
setNavigationBarTitle
({
title
:
`阅读:
${
n
.
title
}
`
})
}
}
}
},
methods
:
{
// 解锁回调
paySuccess
()
{
this
.
$set
(
this
.
bookData
,
"isUnlock"
,
1
);
this
.
$set
(
this
.
bookData
,
"freeNum"
,
this
.
bookData
.
articleChapterList
.
length
);
this
.
$refs
.
content
.
reloadChapterinfoData
()
},
// 文章数据刷新
refreshBookData
(
bookId
)
{
// getOpens((success, data) => {
// this.showBeanOpen = data.openBeans
// this.showVipOpen = data.openVips
// })
getBookDetailData
(
bookId
,
(
success
,
data
)
=>
{
uni
.
stopPullDownRefresh
();
if
(
success
)
{
if
(
data
.
isUnlock
)
{
data
.
freeNum
=
data
.
articleChapterList
.
length
}
this
.
bookData
=
new
BookDetail
(
data
);
console
.
log
(
'bookData='
+
JSON
.
stringify
(
this
.
bookData
));
}
})
},
// 点击底部按钮
tapBottomItem
(
e
)
{
let
flag
=
e
.
detail
.
flag
;
switch
(
flag
)
{
case
'like'
:
// 点赞
break
;
case
'collection'
:
// 收藏
let
target
=
!
this
.
bookData
.
isCollect
;
collectionBook
(
target
,
this
.
bookId
,
(
success
,
data
)
=>
{
if
(
success
)
{
this
.
$set
(
this
.
bookData
,
'isCollect'
,
target
);
noticeCollectionListChange
(
this
.
bookId
,
target
);
}
})
break
;
case
'setting'
:
// 设置
this
.
showSetting
=
true
;
break
;
case
'catalogue'
:
// 目录
this
.
showCatalogue
=
true
;
break
;
default
:
break
;
}
},
isVip
()
{
if
(
this
.
userInfo
!=
null
&&
this
.
userInfo
.
memberExpirationDate
>
0
)
{
return
true
;
}
return
false
;
},
tapPayPop
()
{
if
(
this
.
showVipOpen
!=
1
&&
this
.
showBeanOpen
==
1
)
{
this
.
tapBeanPop
()
return
}
this
.
tapVipPop
()
},
// 展示充值VIP弹框
tapVipPop
()
{
this
.
showVip
=
true
;
},
// 展示充值书豆弹框
tapBeanPop
()
{
this
.
showBean
=
true
;
},
// 关闭设置弹窗
closePop
(
e
)
{
this
.
showSetting
=
false
;
},
// 关闭目录弹窗
closeCataPop
(
e
)
{
this
.
showCatalogue
=
false
;
},
// 关闭会员弹窗
closeVipPop
(
e
)
{
this
.
showVip
=
false
;
if
(
this
.
bookData
.
isUnlock
==
0
)
{
setTimeout
(()
=>
{
this
.
showRecommend
=
true
;
},
300
);
}
},
// 关闭书豆弹窗
closeBeanPop
(
e
)
{
this
.
showBean
=
false
;
// setTimeout(() => {
// this.showRecommend = true;
// }, 300);
},
// 关闭推荐弹窗
closeRecommendPop
(
e
)
{
this
.
showRecommend
=
false
;
},
changeCurrent
(
current
)
{
this
.
current
=
current
}
}
}
</
script
>
<
style
lang=
"scss"
>
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/bean-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'beanpop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
充值书豆,订阅全本
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packData'
:key='index' @click="choosePack(item, index)">
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"cut-down"
v-if=
'item.giveNumber'
>
赠送
{{
item
.
giveNumber
}}
书豆
</view>
</view>
</view>
</view>
<view
class=
"section"
>
<button
class=
"c-button_clear c-button-size_lg c-button-width_full apply-button"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapPay"
>
立即购买
</button>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
getBookBeanPackData
,
getOpenId
,
getPayInfo
,
ENUM_PAY_TYPE
}
from
"../../../../common/services/index.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
userInfo
:
null
,
packData
:
[],
selectedIndex
:
0
,
loading
:
false
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
beanCount
:
function
()
{
if
(
this
.
userInfo
)
return
this
.
userInfo
.
bookLegumes
;
return
0
;
}
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onReady
()
{
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
},
this
)
},
onUnload
()
{
removeUserInfoChangeWatch
(
this
);
},
mounted
()
{
this
.
requestPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
beanpop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
beanpop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
requestPackData
()
{
getBookBeanPackData
((
success
,
data
)
=>
{
uni
.
stopPullDownRefresh
()
if
(
success
)
{
this
.
packData
=
data
.
map
(
item
=>
{
return
new
BookBeanPack
(
item
)
})
}
})
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packData
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
},
ENUM_PAY_TYPE
.
BEAN
.
value
)
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
uni
.
requestPayment
({
timeStamp
:
payInfo
.
timeStamp
,
nonceStr
:
payInfo
.
nonceStr
,
package
:
payInfo
.
packageStr
,
signType
:
payInfo
.
signType
,
paySign
:
payInfo
.
paySign
,
success
:
(
res
)
=>
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'购买成功'
)
refreshUserInfo
();
})
})
})
})
}
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/catalogue-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'pop'
type=
"left"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
@
click=
"tapMask"
>
<scroll-view
scroll-y
style=
"background-color: white;width: 400rpx;max-width: 400rpx;"
@
click
.
stop=
""
>
<view
class=
"setting-box"
>
<block
v-for=
'(item, index) in catalogueList'
:key=
'index'
:item=
'item'
>
<view
@
click
.
stop=
"changeCatalogue(item.chapterNum)"
>
<view
style=
"display: flex;flex-direction: row;justify-content: space-between;align-items: center;"
>
<text
class=
"text"
:style=
"
{'width: 350rpx;color': item.chapterNum==currentCatalogue?'#f00':'#000'}">
第
{{
item
.
chapterNum
}}
章
{{
item
.
chapterName
}}
</text>
<image
v-if=
"(index+1)>detail.freeNum"
style=
"width: 30rpx;height: 30rpx;"
src=
"https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/lock.png"
></image>
</view>
<view
style=
"background-color: gainsboro;height: 1rpx;width: 400rpx;margin: 20rpx 0;"
>
</view>
</view>
</block>
</view>
</scroll-view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
import
CatalogueList
from
"../models/CatalogueList.js"
;
import
{
saveContentFormat
,
readContentFormat
}
from
"../services/index.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
detail
:
{
type
:
Object
,
default
:
0
},
current
:
{
type
:
Number
,
default
:
0
}
},
data
:
function
()
{
return
{
showPop
:
false
,
catalogueList
:
[],
currentContentFormat
:
{},
currentCatalogue
:
1
}
},
computed
:
{},
watch
:
{
current
:
function
(
n
)
{
if
(
n
!=
this
.
currentCatalogue
)
{
this
.
changeCatalogue
(
n
)
}
},
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
mounted
()
{
this
.
initColorList
();
this
.
currentContentFormat
=
readContentFormat
()
for
(
let
i
in
this
.
currentContentFormat
.
catalogueList
)
{
if
(
this
.
currentContentFormat
.
catalogueList
[
i
].
id
==
this
.
detail
.
id
)
{
// 处理特殊情况,下标错误
let
current_e
=
this
.
currentContentFormat
.
catalogueList
[
i
].
catalogue
if
(
!
this
.
detail
.
isUnlock
&&
current_e
>
this
.
detail
.
freeNum
)
{
this
.
currentCatalogue
=
this
.
detail
.
freeNum
return
}
this
.
currentCatalogue
=
current_e
}
}
},
methods
:
{
open
()
{
this
.
$refs
.
pop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
pop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
initColorList
()
{
this
.
catalogueList
=
this
.
detail
.
articleChapterList
},
changeCatalogue
(
e
)
{
if
(
e
>
this
.
detail
.
freeNum
)
{
this
.
tabVip
()
this
.
close
()
return
}
var
hasCatalogue
=
false
for
(
let
i
in
this
.
currentContentFormat
.
catalogueList
)
{
if
(
this
.
currentContentFormat
.
catalogueList
[
i
].
id
==
this
.
detail
.
id
)
{
this
.
currentContentFormat
.
catalogueList
[
i
].
catalogue
=
e
hasCatalogue
=
true
}
}
if
(
!
hasCatalogue
)
{
this
.
currentContentFormat
.
catalogueList
.
push
({
id
:
this
.
detail
.
id
,
catalogue
:
e
})
}
this
.
currentCatalogue
=
e
saveContentFormat
(
this
.
currentContentFormat
);
this
.
close
()
},
tabVip
()
{
setTimeout
(()
=>
{
this
.
$emit
(
'tabVip'
)
},
1000
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
padding
:
40rpx
;
// background: #fff;
height
:
100vh
;
.title
{
font-size
:
34rpx
;
font-weight
:
700
;
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-bottom.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-bottom"
:style=
"[bottomStyle]"
>
<view
class=
"fixed-bottom"
:style=
"[fixedBottomStyle,
{backgroundColor:backgroundColor}]">
<!--
<view
class=
"bottom-item"
@
click=
"tapItem('like')"
>
<uni-icons
:type=
'likeIcon.type'
customPrefix=
"readiconfont"
:color=
'likeIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: likeIcon.color}">
赞
</view>
</view>
-->
<!--
<view
class=
"bottom-item"
@
click=
"tapItem('diss')"
>
<uni-icons
:type=
'dissIcon.type'
customPrefix=
"readiconfont"
:color=
'dissIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: dissIcon.color}">
踩
</view>
</view>
-->
<view
class=
"bottom-item"
@
click=
"tapItem('catalogue')"
>
<uni-icons
type=
'icon-uncollection'
customPrefix=
"readiconfont"
color=
'#333'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: '#333'}">
目录
</view>
</view>
<!--
<view
class=
"bottom-item"
@
click=
"tapItem('collection')"
>
<uni-icons
:type=
'collectionIcon.type'
customPrefix=
"readiconfont"
:color=
'collectionIcon.color'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: collectionIcon.color}">
{{
collectionIcon
.
title
}}
</view>
</view>
-->
<view
class=
"bottom-item"
@
click=
"tapItem('setting')"
>
<uni-icons
type=
'icon-setting'
customPrefix=
"readiconfont"
color=
'#333'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: '#333'}">
设置
</view>
</view>
<view
class=
"bottom-item"
>
<uni-icons
type=
'icon-share'
customPrefix=
"readiconfont"
color=
'#333'
size=
'20'
></uni-icons>
<view
class=
"title"
:style=
"
{color: '#333'}">
分享
</view>
<button
class=
"c-button_clear cover-button"
open-type=
"share"
></button>
</view>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlaceholderStyle]"
></view>
</view>
</
template
>
<
script
>
import
{
watchContentFormatChange
,
removeContentFormatChangeWatch
}
from
"../services/index.js"
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
import
{
showLoginView
}
from
"../../../../common/services/userServices.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
}
},
data
:
function
()
{
return
{
height
:
`100`
,
backgroundColor
:
`#fff`
}
},
mounted
()
{
// 监听样式变动
watchContentFormatChange
((
data
)
=>
{
let
result
=
data
.
getFormatValue
();
if
(
this
.
backgroundColor
!=
result
.
backgroundColor
)
{
this
.
backgroundColor
=
result
.
backgroundColor
}
},
this
)
},
destroyed
()
{
removeContentFormatChangeWatch
(
this
);
},
computed
:
{
fixedBottomStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
bottom
:
`
${
height
}
rpx`
}
},
safePlaceholderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
bottomStyle
:
function
()
{
let
height
=
100
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
likeIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isLike
?
'icon-like'
:
'icon-unlike'
,
color
:
this
.
detail
.
isLike
?
'#FECF02'
:
"#333"
}
},
dissIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isDiss
?
'icon-diss'
:
'icon-undiss'
,
color
:
this
.
detail
.
isDiss
?
'#FECF02'
:
"#333"
}
},
collectionIcon
:
function
()
{
return
{
type
:
this
.
detail
.
isCollect
?
'icon-collection'
:
'icon-uncollection'
,
color
:
this
.
detail
.
isCollect
?
'#FECF02'
:
"#333"
,
title
:
this
.
detail
.
isCollect
?
"已收藏"
:
"收藏"
}
}
},
methods
:
{
tapItem
(
flag
)
{
if
(
flag
==
'collection'
&&
!
this
.
userInfo
)
{
showLoginView
();
return
;
}
this
.
$emit
(
"tapBottomItem"
,
{
detail
:
{
flag
,
item
:
this
.
detail
}
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-bottom
{
position
:
absolute
;
height
:
100rpx
;
bottom
:
0
;
.fixed-bottom
{
position
:
fixed
;
background
:
transparent
;
bottom
:
0
;
left
:
0
;
right
:
0
;
height
:
100rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
.bottom-item
{
position
:
relative
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
height
:
100%
;
// width: 33.3333333333%;
flex
:
1
;
.title
{
font-size
:
24rpx
;
margin-top
:
10rpx
;
}
.cover-button
{
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
transparent
;
z-index
:
2
;
}
}
}
.safe-placeholder
{
position
:
fixed
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
#fff
;
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-buy.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-buy"
>
<view
class=
"book-card"
>
<view
class=
"cover-box"
>
<image
class=
"cover"
:src=
"detail.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"info-box"
>
<view
class=
"row"
>
<view
class=
"book-title"
>
{{
detail
.
title
}}
</view>
<view
class=
"book-value"
>
{{
bookBeanCount
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"desc"
>
{{
detail
.
summary
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"c-flex_row c-align_center"
>
<uni-icons
type=
'icon-author'
custom-prefix=
"readiconfont"
size=
'20'
color=
'#378eff'
></uni-icons>
<view
class=
"book-author"
>
{{
detail
.
author
}}
</view>
</view>
<view
class=
"buy-button disable-button"
v-if=
'detail.isUnlock'
>
已购买
</view>
<view
class=
"buy-button"
@
click=
"tapBuy"
v-else
>
购买
</view>
</view>
</view>
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packList'
:key='index' @click="choosePack(item, index)">
<template
v-if=
'item.isBeanPack'
>
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"cut-down"
v-if=
'item.giveNumber'
>
赠送
{{
item
.
giveNumber
}}
书豆
</view>
</
template
>
<
template
v-else
>
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"origin row"
v-if=
'item.originalPrice'
>
原价:
{{
item
.
originalPrice
}}
</view>
<view
class=
"cut-down"
v-if=
'item.cutDown'
>
立省
{{
item
.
cutDown
}}
元
</view>
</
template
>
</view>
</view>
<view
class=
"warn-box"
>
<view
class=
"warn-p"
>
1.目前充值会员暂不支持退款,一经购买不可退换
</view>
<view
class=
"warn-p"
>
2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作
</view>
<view
class=
"warn-p"
>
3.充值一般在5分钟内到账,如未到账请提供支付截图在"我的"页面联系客服
</view>
<view
class=
"warn-p"
>
4.之前充值账户请登录后继续阅读
</view>
</view>
</view>
</template>
<
script
>
import
Pack
from
"../../../../common/models/Pack.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
getPackData
,
getOpenId
,
getPayInfo
,
getBookBeanPackData
,
ENUM_PAY_TYPE
,
buyBookWithBookBean
}
from
"../../../../common/services/index.js"
;
import
{
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastHide
,
toastLoading
,
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
}
},
data
:
function
()
{
return
{
packList
:
[],
vipPackList
:
[],
beanPackList
:
[],
selectedIndex
:
0
,
loading
:
false
,
imageError
:
true
}
},
computed
:
{
bookBeanCount
:
function
()
{
return
this
.
detail
&&
this
.
detail
.
bookLegumes
?
`
${
this
.
detail
.
bookLegumes
}
书豆`
:
"免费"
},
payButtonTitle
:
function
()
{
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
return
(
pack
instanceof
Pack
)
?
"购买会员"
:
"购买书豆并解锁本书"
},
packChange
:
function
()
{
const
{
vipPackList
,
beanPackList
}
=
this
;
return
{
vipPackList
,
beanPackList
}
}
},
watch
:
{
packChange
:
{
handler
:
function
(
n
)
{
this
.
packList
=
this
.
getPackList
(
n
.
vipPackList
,
n
.
beanPackList
);
},
deep
:
true
}
},
mounted
()
{
this
.
refreshPackData
();
},
methods
:
{
loadImage
()
{
this
.
imageError
=
false
},
errorImage
()
{
this
.
imageError
=
true
},
refreshPackData
()
{
getPackData
((
success
,
data
)
=>
{
if
(
success
)
{
this
.
vipPackList
=
data
.
map
(
item
=>
{
let
result
=
new
Pack
(
item
);
result
.
isBeanPack
=
false
;
return
result
;
})
}
})
getBookBeanPackData
((
success
,
data
)
=>
{
if
(
success
)
{
this
.
beanPackList
=
data
.
map
(
item
=>
{
let
result
=
new
BookBeanPack
(
item
);
result
.
isBeanPack
=
true
;
return
result
;
})
}
})
},
getPackList
(
vipPackList
,
beanPackList
)
{
let
vip
=
vipPackList
||
[];
let
bean
=
beanPackList
||
[];
return
[
...
vip
,
...
bean
];
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
this
.
tapPay
();
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
},
(
pack
instanceof
Pack
)
?
ENUM_PAY_TYPE
.
VIP
.
value
:
ENUM_PAY_TYPE
.
BEAN
.
value
)
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
uni
.
requestPayment
({
timeStamp
:
payInfo
.
timeStamp
,
nonceStr
:
payInfo
.
nonceStr
,
package
:
payInfo
.
packageStr
,
signType
:
payInfo
.
signType
,
paySign
:
payInfo
.
paySign
,
success
:
(
res
)
=>
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'会员购买成功'
)
refreshUserInfo
();
})
})
})
})
}
},
tapBuy
()
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
uni
.
showModal
({
title
:
"余额不足"
,
content
:
`当前余额:
${
this
.
userInfo
.
bookLegumes
}
, 请前往充值`
,
showCancel
:
false
,
confirmText
:
"知道了"
})
return
;
}
toastLoading
(
"购买中"
);
buyBookWithBookBean
(
this
.
detail
.
id
,
(
success
,
data
)
=>
{
toastHide
();
if
(
success
)
{
this
.
$emit
(
"unlockBook"
)
}
})
},
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-buy
{
display
:
flex
;
flex-direction
:
column
;
.book-card
{
margin
:
20rpx
;
padding
:
20rpx
;
background
:
#fdf6f0
;
border-radius
:
20rpx
;
display
:
flex
;
flex-direction
:
row
;
.cover-box
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
.cover
{
width
:
140rpx
;
height
:
180rpx
;
border-radius
:
15rpx
;
}
}
.info-box
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
margin-left
:
20rpx
;
.row
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
space-between
;
}
.row
:last-child
{}
.book-title
{
color
:
#333
;
font-size
:
36rpx
;
font-weight
:
700
;
}
.book-value
{
color
:
goldenrod
;
font-size
:
40rpx
;
font-weight
:
700
;
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
24rpx
;
color
:
#999
}
.book-author
{
color
:
#999
;
font-size
:
28rpx
;
}
.buy-button
{
background
:
#caad9c
;
color
:
#333
;
height
:
60rpx
;
line-height
:
60rpx
;
width
:
180rpx
;
text-align
:
center
;
border-radius
:
10rpx
;
font-size
:
30rpx
;
color
:
#fff
;
}
.disable-button
{
background
:
#ededed
;
color
:
#888
;
}
}
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.warn-box
{
color
:
#956244
;
font-size
:
26rpx
;
display
:
flex
;
flex-direction
:
column
;
padding
:
30rpx
;
.warn-p
{
margin-bottom
:
15rpx
;
}
.warn-p
:last-child
{
margin-bottom
:
0
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-content.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"pages"
>
<yingbing-text-reader
ref=
"reader"
:total-chapter=
"detail.articleChapterList.length"
:preloadable=
"isPreload"
:background=
"background"
:fontSize=
"fontSize"
:lineGap=
"30"
:color=
"color"
:page-type=
"pageType"
bottomGap=
"60"
:footerShow=
"false"
:loadPageNum=
"2"
@
change=
"handleChange"
@
loadmore=
"handleLoadmore"
>
<template
v-if=
"!detail.isUnlock"
:slot=
"`vip:$
{catalogue}`">
<view
class=
"slots"
>
<view
class=
"line-box"
>
<view
class=
"line"
></view>
<view
class=
"text"
>
全本订阅超优惠
</view>
<view
class=
"line"
></view>
</view>
<view
class=
"section"
>
<button
class=
"btn2"
:disabled=
"false"
:loading=
"false"
@
click=
"tapVip"
>
开通会员,免费阅读本书
</button>
</view>
<view
class=
"warn-box"
>
<view
class=
"warn-p"
>
1.目前充值会员暂不支持退款,一经购买不可退换
</view>
<view
class=
"warn-p"
>
2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作
</view>
<view
class=
"warn-p"
>
3.充值一般在5分钟内到账,如未到账请提供支付截图在"我的"页面联系客服
</view>
<view
class=
"warn-p"
>
4.之前充值账户请登录后继续阅读
</view>
</view>
</view>
</
template
>
<!-- <template v-for="(item, index) in chapters" :slot="`end:${item.index}`">
<view class="slots">第{{item.index}}章节阅读完成提示页</view>
</template> -->
</yingbing-text-reader>
</view>
</template>
<
script
>
import
{
watchContentFormatChange
,
removeContentFormatChangeWatch
,
getChapterinfoData
}
from
"../services/index.js"
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
}
},
data
()
{
return
{
pageType
:
'real'
,
split
:
''
,
background
:
'#fff'
,
color
:
'#333'
,
fontSize
:
18
,
pageType
:
'cover'
,
catalogue
:
1
,
isFisrt
:
true
,
isPreload
:
false
}
},
destroyed
()
{
removeContentFormatChangeWatch
(
this
);
},
mounted
()
{
// 监听样式变动
watchContentFormatChange
((
data
)
=>
{
let
result
=
data
.
getFormatValue
();
if
(
this
.
fontSize
!=
result
.
fontSize
)
{
this
.
fontSize
=
parseInt
(
result
.
fontSize
.
substring
(
0
,
2
))
}
if
(
this
.
background
!=
result
.
backgroundColor
)
{
this
.
background
=
result
.
backgroundColor
}
let
resultCatalogue
=
this
.
catalogue
for
(
let
i
in
result
.
catalogueList
)
{
if
(
result
.
catalogueList
[
i
].
id
==
this
.
detail
.
id
)
{
resultCatalogue
=
result
.
catalogueList
[
i
].
catalogue
}
}
if
(
!
this
.
detail
.
isUnlock
&&
resultCatalogue
>
this
.
detail
.
freeNum
)
{
this
.
catalogue
=
3
}
else
{
if
(
this
.
catalogue
!=
resultCatalogue
)
{
this
.
catalogue
=
resultCatalogue
this
.
refreshChapterinfoData
(
this
.
catalogue
)
}
}
if
(
this
.
isFisrt
)
{
this
.
isFisrt
=
false
this
.
isPreload
=
true
this
.
refreshChapterinfoData
(
this
.
catalogue
)
}
},
this
)
},
methods
:
{
reloadChapterinfoData
()
{
this
.
isPreload
=
true
this
.
refreshChapterinfoData
()
},
// 文章数据刷新
refreshChapterinfoData
(
chapterId
=
this
.
catalogue
)
{
this
.
catalogue
=
chapterId
let
id
=
this
.
detail
.
articleChapterList
[
chapterId
-
1
].
id
getChapterinfoData
(
this
.
detail
.
id
,
id
,
(
success
,
data
)
=>
{
if
(
success
)
{
this
.
changeChapterinfo
(
chapterId
,
data
.
contentMd
)
}
})
},
changeChapterinfo
(
chapterId
,
content
)
{
this
.
chapters
=
[
this
.
getChapter
(
chapterId
,
content
)]
this
.
$refs
.
reader
.
change
({
chapters
:
this
.
chapters
,
title
:
this
.
detail
.
title
,
current
:
chapterId
,
start
:
1
})
},
handleChange
(
e
)
{
console
.
log
(
'change'
,
e
);
if
(
this
.
catalogue
!=
e
.
detail
.
index
)
{
this
.
catalogue
=
e
.
detail
.
index
if
(
this
.
detail
.
isUnlock
)
{
this
.
changeCurrent
()
}
else
if
(
!
this
.
detail
.
isUnlock
&&
this
.
catalogue
<
this
.
detail
.
freeNum
)
{
this
.
changeCurrent
()
}
}
},
handleLoadmore
(
current
,
callback
)
{
if
(
current
>
this
.
detail
.
freeNum
||
current
>
this
.
detail
.
articleChapterList
.
length
)
{
if
(
!
this
.
detail
.
isUnlock
&&
current
==
this
.
detail
.
freeNum
+
1
)
{
callback
(
'success'
,
this
.
getChapter
(
current
))
return
}
callback
(
'fail'
)
return
}
let
id
=
this
.
detail
.
articleChapterList
[
current
-
1
].
id
getChapterinfoData
(
this
.
detail
.
id
,
id
,
(
success
,
data
)
=>
{
if
(
success
)
{
callback
(
'success'
,
this
.
getChapter
(
current
,
data
.
contentMd
))
return
}
callback
(
'fail'
)
})
},
getChapter
(
index
,
content
)
{
const
showVip
=
!
this
.
detail
.
isUnlock
&&
index
>
this
.
detail
.
freeNum
return
{
title
:
'第'
+
index
+
'章'
,
content
:
content
,
frontSlots
:
showVip
?
[
'vip'
]
:
[],
// backSlots: ['end'],
index
:
index
,
isStart
:
index
==
1
,
isEnd
:
index
==
this
.
detail
.
articleChapterList
.
length
}
},
tapVip
()
{
setTimeout
(()
=>
{
this
.
$emit
(
'tabVip2'
)
},
200
)
},
changeCurrent
()
{
setTimeout
(()
=>
{
this
.
$emit
(
'changeCurrent'
,
this
.
catalogue
)
},
200
)
},
}
}
</
script
>
<
style
lang=
"scss"
>
.pages
{
/* #ifdef APP-NVUE */
flex
:
1
;
/* #endif */
/* #ifndef APP-NVUE */
width
:
100vw
;
height
:
100vh
;
/* #endif */
}
.slots
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
.section
{
width
:
80%
;
margin-top
:
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.btn2
{
color
:
#DCBD3B
;
border
:
#DCBD3B
solid
1rpx
;
width
:
100%
;
text-align
:
center
;
border-radius
:
80rpx
;
height
:
80rpx
;
line-height
:
80rpx
;
}
}
.line-box
{
width
:
80%
;
display
:
flex
;
flex-direction
:
row
;
flex-wrap
:
wrap
;
align-items
:
center
;
.line
{
width
:
30%
;
background-color
:
lightgray
;
height
:
1rpx
;
}
.text
{
text-align
:
center
;
width
:
36%
;
color
:
lightgray
;
font-size
:
26rpx
;
}
}
.warn-box
{
color
:
#956244
;
font-size
:
26rpx
;
display
:
flex
;
flex-direction
:
column
;
padding
:
30rpx
;
.warn-p
{
margin-bottom
:
15rpx
;
}
.warn-p
:last-child
{
margin-bottom
:
0
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-new-buy.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-buy"
>
<view
class=
"book-card"
>
<view
class=
"line-box"
>
<view
class=
"line"
></view>
<view
class=
"text"
>
全本订阅超优惠
</view>
<view
class=
"line"
></view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"text-box"
>
<view
class=
"text1"
>
全本特价:
</view>
<view
class=
"text2"
>
{{
bookBeanCount
}}
</view>
<view
class=
"text1"
>
书豆
</view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"text-box"
style=
"margin-top: 20rpx;"
>
<view
class=
"text1"
>
账户余额:
</view>
<view
class=
"text2"
>
{{
bookAllBeanCount
}}
</view>
<view
class=
"text1"
>
书豆
</view>
</view>
<view
v-if=
"showBeanOpen==1"
class=
"section"
style=
"margin-top: 30rpx;"
>
<button
class=
"btn1"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapBeanBtn"
>
{{
bookBeanText
}}
</button>
</view>
<view
v-if=
"!isVip() && (showVipOpen==1)"
class=
"section"
style=
"margin-top: 30rpx;"
>
<button
class=
"btn2"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapVip"
>
开通会员,免费阅读本书
</button>
</view>
</view>
<view
class=
"warn-box"
>
<view
class=
"warn-p"
>
1.目前充值会员暂不支持退款,一经购买不可退换
</view>
<view
class=
"warn-p"
>
2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作
</view>
<view
class=
"warn-p"
>
3.充值一般在5分钟内到账,如未到账请提供支付截图在"我的"页面联系客服
</view>
<view
class=
"warn-p"
>
4.之前充值账户请登录后继续阅读
</view>
</view>
</view>
</
template
>
<
script
>
import
Pack
from
"../../../../common/models/Pack.js"
;
import
BookBeanPack
from
"../../../../common/models/BookBeanPack.js"
import
{
showLoginView
,
}
from
"../../../../common/services/userServices.js"
import
{
buyBookWithBookBean
}
from
"../../../../common/services/index.js"
;
import
{
toastHide
,
toastLoading
,
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
},
userInfo
:
{
type
:
Object
,
default
:
function
()
{
return
null
}
},
showVipOpen
:
{
type
:
Number
,
default
:
1
},
showBeanOpen
:
{
type
:
Number
,
default
:
1
}
},
data
:
function
()
{
return
{
selectedIndex
:
0
,
loading
:
false
,
imageError
:
true
}
},
computed
:
{
bookBeanText
:
function
()
{
if
(
this
.
userInfo
&&
this
.
detail
)
{
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
return
'余额不足,立即充值'
}
}
return
'全本订阅'
;
},
bookAllBeanCount
:
function
()
{
if
(
this
.
userInfo
)
return
this
.
userInfo
.
bookLegumes
return
0
;
},
bookBeanCount
:
function
()
{
return
this
.
detail
&&
this
.
detail
.
bookLegumes
?
`
${
this
.
detail
.
bookLegumes
}
`
:
"免费"
},
},
mounted
()
{
},
methods
:
{
isVip
()
{
if
(
this
.
userInfo
!=
null
&&
this
.
userInfo
.
memberFlag
)
{
let
cDate
=
new
Date
();
cDate
=
cDate
.
getTime
();
return
this
.
userInfo
.
memberExpirationDate
>=
cDate
;
}
return
false
;
},
tapBeanBtn
()
{
let
isIOS
=
wx
.
getSystemInfoSync
().
platform
;
if
(
isIOS
===
'ios'
)
{
uni
.
showToast
({
title
:
'暂不支持IOS系统'
,
icon
:
'none'
})
return
}
if
(
this
.
userInfo
&&
this
.
detail
)
{
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
this
.
tapBean
()
return
}
}
this
.
tapBuy
()
},
tapVip
()
{
let
isIOS
=
wx
.
getSystemInfoSync
().
platform
;
if
(
isIOS
===
'ios'
)
{
uni
.
showToast
({
title
:
'暂不支持IOS系统'
,
icon
:
'none'
})
return
}
// 展示充值VIP弹框
this
.
$emit
(
'tapVip'
)
},
tapBean
()
{
// 展示充值书豆弹框
this
.
$emit
(
'tapBean'
)
},
tapBuy
()
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
userInfo
.
bookLegumes
<
this
.
detail
.
bookLegumes
)
{
uni
.
showModal
({
title
:
"余额不足"
,
content
:
`当前余额:
${
this
.
userInfo
.
bookLegumes
}
, 请前往充值`
,
showCancel
:
false
,
confirmText
:
"知道了"
})
return
;
}
toastLoading
(
"购买中"
);
buyBookWithBookBean
(
this
.
detail
.
id
,
(
success
,
data
)
=>
{
toastHide
();
if
(
success
)
{
this
.
$emit
(
"unlockBook"
)
}
})
},
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-buy
{
display
:
flex
;
flex-direction
:
column
;
.book-card
{
margin
:
20rpx
;
padding
:
20rpx
;
// background: #fdf6f0;
// border-radius: 20rpx;
display
:
flex
;
flex-direction
:
column
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.btn1
{
color
:
white
;
background-image
:
linear-gradient
(
90deg
,
pink
,
#DCBD3B
);
width
:
100%
;
height
:
80rpx
;
text-align
:
center
;
border-radius
:
80rpx
;
line-height
:
80rpx
;
}
.btn2
{
color
:
#DCBD3B
;
border
:
#DCBD3B
solid
1rpx
;
width
:
100%
;
text-align
:
center
;
border-radius
:
80rpx
;
height
:
80rpx
;
line-height
:
80rpx
;
}
}
.line-box
{
display
:
flex
;
flex-direction
:
row
;
padding
:
30rpx
;
flex-wrap
:
wrap
;
align-items
:
center
;
.line
{
width
:
30%
;
background-color
:
lightgray
;
height
:
1rpx
;
}
.text
{
text-align
:
center
;
width
:
36%
;
color
:
lightgray
;
font-size
:
26rpx
;
}
}
.text-box
{
display
:
flex
;
flex-direction
:
row
;
.text1
{
font-size
:
24rpx
;
color
:
black
;
}
.text2
{
padding
:
0
10rpx
;
font-size
:
24rpx
;
color
:
#DCBD3B
;
}
}
}
.warn-box
{
color
:
#956244
;
font-size
:
26rpx
;
display
:
flex
;
flex-direction
:
column
;
padding
:
30rpx
;
.warn-p
{
margin-bottom
:
15rpx
;
}
.warn-p
:last-child
{
margin-bottom
:
0
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-thumb.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
class=
"detail-thumb"
@
click=
"tapThumb"
>
<view
class=
"content"
>
<view
class=
"cover-box item"
>
<image
class=
"cover"
:src=
"detail.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"info-box item"
>
<view
class=
"row"
>
<view
class=
"title"
>
{{
detail
.
title
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"desc"
>
{{
detail
.
summary
}}
</view>
</view>
<view
class=
"row"
>
<view
class=
"author-box"
>
<uni-icons
type=
'icon-author'
custom-prefix=
"readiconfont"
size=
'20'
color=
'#378eff'
></uni-icons>
<view
class=
"name"
>
{{
detail
.
author
}}
</view>
</view>
</view>
</view>
</view>
</view>
</
template
>
<
script
>
export
default
{
props
:
{
detail
:
{
type
:
Object
,
default
:
function
()
{
return
{}
}
}
},
data
:
function
()
{
return
{
imageError
:
true
}
},
methods
:
{
tapThumb
()
{
this
.
$emit
(
'tapThumb'
,
{
detail
:
{
data
:
this
.
detail
}
})
},
loadImage
()
{
this
.
imageError
=
false
},
errorImage
()
{
this
.
imageError
=
true
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
page
{
background
:
#fff
;
}
.detail-thumb
{
padding
:
15rpx
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.content
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
border-radius
:
18rpx
;
background
:
#f5f5f5
;
padding
:
20rpx
;
.row
{
margin-bottom
:
20rpx
;
}
.row
:last-child
{
margin-bottom
:
0
;
}
.item
{
margin-right
:
20rpx
;
}
.item
:last-child
{
margin-right
:
0
;
}
.cover-box
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
.cover
{
width
:
140rpx
;
height
:
180rpx
;
border-radius
:
15rpx
;
}
}
.info-box
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
.title
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
24rpx
;
color
:
#999
}
.author-box
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
height
:
50rpx
;
line-height
:
50rpx
;
.name
{
font-size
:
26rpx
;
color
:
#378eff
;
margin-left
:
15rpx
;
}
}
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/detail-warn.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<view
v-if=
"false"
class=
"detail-warn"
>
<view
class=
"content"
>
<uni-icons
type=
'chatboxes'
size=
"20"
color=
"#aa8062"
></uni-icons>
<view
class=
"value"
>
"本故事纯属虚构,仅供娱乐,无不良引导"
</view>
</view>
</view>
</
template
>
<
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
.detail-warn
{
padding
:
15rpx
30rpx
;
display
:
flex
;
flex-direction
:
column
;
.content
{
height
:
100rpx
;
line-height
:
100rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
border-radius
:
18rpx
;
background
:
#f4e9eb
;
color
:
#aa8062
;
padding
:
0
30rpx
;
.value
{
font-size
:
28rpx
;
margin-left
:
15rpx
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/recommend-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'recommendpop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
99%读过这本书的人还在读
</view>
<view
class=
"book-list-item"
v-for=
'(item, index) in dataList'
:key=
'index'
:item=
'item'
@
click=
"tapItem(item)"
>
<view
class=
"cover-box item"
>
<image
v-if=
"item.avatar===''"
class=
"cover"
src=
"/static/images/logo.png"
mode=
"aspectFill"
>
</image>
<image
v-else
class=
"cover"
:src=
"item.avatar"
mode=
"aspectFill"
></image>
</view>
<view
class=
"c-flex_column"
>
<view
class=
"c-flex_row c-justify_between row"
>
<view
class=
"c-flex_column c-justify_center item"
>
<view
class=
"title2"
>
{{
item
.
title
}}
</view>
</view>
</view>
<view
class=
"c-flex_row row"
>
<view
class=
"c-flex_column c-justify_between content c-flex_1 item"
>
<view
class=
"desc row"
>
{{
item
.
summary
}}
</view>
<view
class=
"c-flex_row c-align_center label-box row"
>
<slot
name=
"footer"
>
<view
class=
"label label-color-1"
v-if=
"item.categoryName!=null&&item.categoryName!=''"
>
{{
item
.
categoryName
}}
</view>
<view
class=
"label label-color-2"
v-for=
'(label, labelIndex) in item.tagList'
:key=
'labelIndex'
>
{{
label
.
name
}}
</view>
</slot>
</view>
</view>
</view>
</view>
<view
style=
"display: flex;margin: auto;width: 200rpx;"
>
<button
class=
"btn2"
>
去阅读
</button>
</view>
</view>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
{
gotoBookContentPage
}
from
'../../../../common/services/page-route'
import
{
getBookRecommendData
}
from
"../services/index.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
bookId
:
{
type
:
[
Number
,
String
],
default
:
0
}
},
data
:
function
()
{
return
{
showPop
:
false
,
dataList
:
[]
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
}
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onUnload
()
{},
mounted
()
{
this
.
requestPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
recommendpop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
recommendpop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
requestPackData
()
{
getBookRecommendData
(
this
.
bookId
,
(
success
,
data
)
=>
{
if
(
success
)
{
this
.
dataList
=
data
.
records
;
}
})
},
tapItem
(
item
)
{
// 在C页面内 navigateBack,将返回A页面
uni
.
navigateBack
({
delta
:
2
});
gotoBookContentPage
(
item
.
wechatRecord
.
wxId
,
item
.
id
);
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#DCBD3B
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
.book-list-item
{
display
:
flex
;
flex-direction
:
row
;
padding-top
:
14rpx
;
padding-bottom
:
14rpx
;
.row
{
margin-bottom
:
20rpx
;
}
.row
:last-child
{
margin-bottom
:
0
;
}
.item
{
margin-right
:
20rpx
;
}
.item
:last-child
{
margin-right
:
0
;
}
.title
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.close-button
{
border-radius
:
10rpx
;
border
:
2rpx
solid
#999
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
width
:
40rpx
;
height
:
30rpx
;
position
:
relative
;
.cover
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
width
:
70rpx
;
height
:
70rpx
;
transform
:
translate
(
-50%
,
-50%
);
z-index
:
2
;
background
:
transparent
;
}
}
.desc
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
font-size
:
26rpx
;
color
:
#999
}
.label-box
{
flex-wrap
:
wrap
;
.label
{
padding
:
5rpx
10rpx
;
font-size
:
20rpx
;
margin-right
:
20rpx
;
border-radius
:
10rpx
;
}
.label-color-1
{
background
:
#faefe6
;
color
:
#cc6008
;
}
.label-color-2
{
color
:
#3d99fd
;
background
:
#d8ebff
;
}
.label-color-3
{
background
:
#ff8787
;
color
:
#ff3737
;
}
}
}
.cover-box
{
.cover
{
width
:
150rpx
;
height
:
200rpx
;
border-radius
:
15rpx
;
}
}
.title2
{
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.btn2
{
color
:
#d98c5c
;
border
:
#DCBD3B
solid
1rpx
;
width
:
140rpx
;
font-size
:
24rpx
;
text-align
:
center
;
border-radius
:
80rpx
;
height
:
40rpx
;
line-height
:
40rpx
;
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/setting-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'pop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
change=
'change'
>
<view
class=
"setting-box"
>
<view
class=
"row"
>
<view
class=
"title"
>
字体大小
</view>
<view
class=
"zone"
>
<view
class=
"c-flex_1"
>
<slider
min=
"14"
max=
"24"
step=
'1'
:value=
'currentContentFormat.fontSize'
:show-value=
"true"
@
change=
'changeFontSize'
>
</slider>
</view>
</view>
</view>
<view
class=
"row"
>
<view
class=
"title"
>
背景颜色
</view>
<view
class=
"zone"
>
<view
class=
"color-item"
:class=
"
{'selected-color': item.value==currentContentFormat.backgroundColor}"
:style="[item.style]" v-for='(item, index) in colorList' :key="index"
@click="chooseColor(item.value)">
</view>
</view>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
import
{
saveContentFormat
,
readContentFormat
}
from
"../services/index.js"
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
colorList
:
[],
currentContentFormat
:
{},
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
mounted
()
{
this
.
initColorList
();
this
.
currentContentFormat
=
readContentFormat
()
},
methods
:
{
open
()
{
this
.
$refs
.
pop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
pop
.
close
();
},
change
(
e
)
{
if
(
this
.
showPop
==
e
.
show
)
return
;
this
.
showPop
=
e
.
show
},
initColorList
()
{
this
.
colorList
=
[
"#fff"
,
"#e7e7e7"
,
"#d4e0c6"
,
"#ccd8e4"
,
"#f9d4d4"
,
"#b1b1b1"
].
map
(
item
=>
{
return
{
style
:
{
background
:
item
},
value
:
item
}
})
},
changeFontSize
(
e
)
{
let
fontSize
=
e
.
detail
.
value
;
this
.
currentContentFormat
.
fontSize
=
fontSize
;
saveContentFormat
(
this
.
currentContentFormat
);
},
chooseColor
(
color
)
{
this
.
currentContentFormat
.
backgroundColor
=
color
;
saveContentFormat
(
this
.
currentContentFormat
);
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
padding
:
20rpx
;
background
:
#fff
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.row
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
padding
:
20rpx
;
.title
{
font-size
:
30rpx
;
font-weight
:
700
;
margin-bottom
:
20rpx
;
}
.zone
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
space-around
;
.color-item
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
40rpx
;
border
:
2rpx
solid
#999
;
}
.selected-color
{
width
:
100rpx
;
height
:
100rpx
;
border-radius
:
50rpx
;
border
:
5rpx
solid
#ff2525
;
}
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/components/vip-pop.vue
deleted
100644 → 0
View file @
7f2ac0a7
<
template
>
<uni-popup
ref=
'vippop'
type=
"bottom"
:is-mask-click=
'false'
:safe-area=
'false'
@
maskClick=
'tapMask'
>
<view
class=
"setting-box"
>
<view
class=
"section"
>
<view
class=
"title"
>
开通会员,继续阅读
</view>
<view
class=
"pack-box"
>
<view
class=
"pack-item"
:class=
"[
{active: index==selectedIndex}]" v-for='(item, index) in packList'
:key='index' @click="choosePack(item, index)">
<view
class=
"name row"
>
{{
item
.
title
}}
</view>
<view
class=
"price row"
>
¥
{{
item
.
price
}}
</view>
<view
class=
"origin row"
v-if=
'item.originalPrice'
>
原价:
{{
item
.
originalPrice
}}
</view>
<view
class=
"cut-down"
v-if=
'item.cutDown'
>
立省
{{
item
.
cutDown
}}
元
</view>
</view>
</view>
</view>
<view
class=
"section"
>
<button
class=
"c-button_clear c-button-size_lg c-button-width_full apply-button"
:disabled=
"loading"
:loading=
"loading"
@
click=
"tapPay"
>
立即开通
</button>
</view>
<view
class=
"safe-placeholder"
:style=
"[safePlacehoderStyle]"
>
</view>
</view>
</uni-popup>
</
template
>
<
script
>
import
SystemInfoMixin
from
"../../../../common/mixins/system-info-mixin.js"
;
import
Pack
from
"../../../../common/models/Pack.js"
;
import
{
getPackData
,
getOpenId
,
getPayInfo
}
from
"../../../../common/services/index.js"
;
import
PayInfo
from
"../../../../common/models/PayInfo.js"
import
{
watchUserInfoChange
,
removeUserInfoChangeWatch
,
showLoginView
,
refreshUserInfo
}
from
"../../../../common/services/userServices.js"
import
{
toastMessage
}
from
"../../../../common/utils/toastUtil.js"
;
import
{
px2rpx
}
from
"../../../../common/utils/util.js"
;
export
default
{
mixins
:
[
SystemInfoMixin
],
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
}
},
data
:
function
()
{
return
{
showPop
:
false
,
packList
:
[],
selectedIndex
:
0
,
loading
:
false
,
userInfo
:
null
}
},
computed
:
{
safePlacehoderStyle
:
function
()
{
let
height
=
0
;
if
(
this
.
bottomSafeHeight
)
{
height
=
height
+
px2rpx
(
this
.
bottomSafeHeight
)
}
return
{
height
:
`
${
height
}
rpx`
}
},
},
watch
:
{
show
:
function
(
n
)
{
this
.
showPop
=
n
;
},
showPop
:
function
(
n
,
o
)
{
if
(
n
==
o
)
return
;
if
(
n
)
{
this
.
open
();
}
else
{
this
.
close
();
}
}
},
onReady
()
{
watchUserInfoChange
((
info
)
=>
{
this
.
userInfo
=
info
.
userInfo
;
},
this
)
},
onUnload
()
{
removeUserInfoChangeWatch
(
this
);
},
mounted
()
{
this
.
refrehsPackData
();
},
methods
:
{
open
()
{
this
.
$refs
.
vippop
.
open
();
},
close
()
{
this
.
$emit
(
'close'
)
this
.
$refs
.
vippop
.
close
();
},
tapMask
()
{
this
.
showPop
=
false
;
},
refrehsPackData
()
{
getPackData
((
success
,
data
)
=>
{
this
.
packList
=
data
.
map
(
item
=>
{
return
new
Pack
(
item
);
})
})
},
choosePack
(
item
,
index
)
{
this
.
selectedIndex
=
index
;
},
tapPay
()
{
let
isIOS
=
uni
.
getSystemInfoSync
().
platform
==
"ios"
&&
false
if
(
isIOS
)
{
uni
.
showModal
({
title
:
"提示"
,
content
:
"由于相关规范,iOS功能暂不可用"
})
}
else
{
if
(
!
this
.
userInfo
)
{
uni
.
showModal
({
title
:
"登录"
,
content
:
"购买前请前往登录系统"
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
showLoginView
()
}
}
})
return
;
}
if
(
this
.
loading
)
return
;
let
pack
=
this
.
packList
[
this
.
selectedIndex
];
this
.
loading
=
true
;
let
sysLoginFn
=
(
successCB
)
=>
{
uni
.
login
({
provider
:
"weixin"
,
onlyAuthorize
:
true
,
success
:
(
res
)
=>
{
if
(
res
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
}
else
{
this
.
loading
=
false
;
}
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
let
getOpenIdFn
=
(
code
,
successCB
)
=>
{
getOpenId
(
code
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
data
);
}
else
{
this
.
loading
=
false
;
}
})
}
let
getPayInfoFn
=
(
openId
,
successCB
)
=>
{
getPayInfo
(
pack
.
id
,
pack
.
price
,
openId
,
(
success
,
data
)
=>
{
if
(
success
)
{
if
(
typeof
successCB
==
'function'
)
successCB
(
new
PayInfo
(
data
));
}
else
{
this
.
loading
=
false
;
}
})
}
let
payOrderFn
=
(
payInfo
,
successCB
)
=>
{
uni
.
requestPayment
({
timeStamp
:
payInfo
.
timeStamp
,
nonceStr
:
payInfo
.
nonceStr
,
package
:
payInfo
.
packageStr
,
signType
:
payInfo
.
signType
,
paySign
:
payInfo
.
paySign
,
success
:
(
res
)
=>
{
if
(
typeof
successCB
==
'function'
)
successCB
(
res
);
},
fail
:
(
error
)
=>
{
this
.
loading
=
false
;
}
})
}
sysLoginFn
((
code
)
=>
{
getOpenIdFn
(
code
.
code
,
(
openId
)
=>
{
getPayInfoFn
(
openId
,
(
payInfo
)
=>
{
payOrderFn
(
payInfo
,
(
data
)
=>
{
this
.
loading
=
false
;
toastMessage
(
'会员购买成功'
)
refreshUserInfo
();
})
})
})
})
}
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.setting-box
{
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
padding-top
:
20rpx
;
border-top-left-radius
:
15rpx
;
border-top-right-radius
:
15rpx
;
.section
{
padding
:
0
30rpx
;
display
:
flex
;
flex-direction
:
column
;
background
:
#fff
;
.title
{
margin
:
10rpx
auto
;
font-size
:
32rpx
;
font-weight
:
700
;
color
:
#333
;
}
.pack-box
{
margin-top
:
25rpx
;
margin-left
:
40rpx
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
flex-wrap
:
wrap
;
.active
{
border
:
6rpx
solid
#fd5350
!
important
;
}
.pack-item
{
margin-bottom
:
25rpx
;
margin-right
:
40rpx
;
width
:
calc
(
31%
-
40rpx
);
height
:
200rpx
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
background
:
#f5f5f5
;
border
:
6rpx
solid
#f5f5f5
;
border-radius
:
10rpx
;
position
:
relative
;
.row
{
margin
:
8rpx
15rpx
;
marign-bottom
:
0
;
}
.row
:last-child
{
margin-bottom
:
8rpx
;
}
.name
{
font-size
:
26rpx
;
font-weight
:
700
;
color
:
#333
;
}
.price
{
font-size
:
30rpx
;
color
:
#fd5350
;
font-weight
:
700
;
}
.origin
{
font-size
:
22rpx
;
color
:
#333
;
text-decoration
:
line-through
;
}
.cut-down
{
position
:
absolute
;
top
:
0
;
right
:
0
;
color
:
#fff
;
background
:
#ff502f
;
font-size
:
22rpx
;
border-radius
:
15rpx
;
height
:
30rpx
;
line-height
:
30rpx
;
padding
:
0
10rpx
;
transform
:
translate
(
0
,
-50%
);
}
}
}
.apply-button
{
border-radius
:
50rpx
;
background
:
#e8c8ae
;
color
:
#8d5a29
;
margin
:
30rpx
auto
;
}
}
}
</
style
>
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/models/BookDetail.js
deleted
100644 → 0
View file @
7f2ac0a7
import
Book
from
"../../../../common/models/Book"
;
export
default
class
BookDetail
extends
Book
{
constructor
(
param
)
{
super
(
param
);
const
{
contentMd
}
=
param
||
{}
this
.
contentMd
=
contentMd
;
let
result
=
contentMd
?
contentMd
.
replace
(
/<
[^
>
]
+>/g
,
""
)
:
""
;
result
=
result
.
split
(
"
\n
"
);
this
.
content
=
result
.
filter
(
item
=>
{
return
item
.
split
(
/
[\t\r\f\n\s]
*/g
).
join
(
""
);
});
}
}
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/models/CatalogueList.js
deleted
100644 → 0
View file @
7f2ac0a7
export
default
class
CatalogueList
{
constructor
(
param
)
{
const
{
id
,
catalogue
,
}
=
param
||
{}
this
.
id
=
id
;
this
.
catalogue
=
catalogue
;
}
getFormatValue
()
{
return
{
id
:
this
.
id
,
catalogue
:
this
.
catalogue
}
}
}
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/models/ContentFormat.js
deleted
100644 → 0
View file @
7f2ac0a7
export
default
class
ContentFormat
{
constructor
(
param
)
{
const
{
fontSize
,
backgroundColor
,
catalogueList
,
}
=
param
||
{}
this
.
fontSize
=
fontSize
;
this
.
catalogueList
=
catalogueList
;
this
.
backgroundColor
=
backgroundColor
;
}
getFormatValue
()
{
return
{
fontSize
:
`
${
this
.
fontSize
}
px`
,
backgroundColor
:
this
.
backgroundColor
,
catalogueList
:
this
.
catalogueList
}
}
}
\ No newline at end of file
vedio/page-subs/sub_A/book-long-content/services/index.js
deleted
100644 → 0
View file @
7f2ac0a7
import
{
addNormalNotificationObserver
,
postNotification
,
removeNotificationObserver
}
from
"../../../../common/utils/notificationCenter"
;
import
{
readStorage
,
saveStorage
}
from
"../../../../common/utils/storageUtil"
;
import
ContentFormat
from
"../models/ContentFormat"
;
import
{
apiGET
,
apiPOST
}
from
"../../../../common/utils/apiRequest.js"
import
CatalogueList
from
"../models/CatalogueList"
;
/** 获取文章详情
* @param {Object} bookId
* @param {Object} callback
*/
function
getBookDetailData
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/info`
,
data
:
{
id
:
bookId
},
callback
})
}
/** 获取章节数据
* @param {Object} bookId
* @param {Object} chapterId
* @param {Object} callback
*/
function
getChapterinfoData
(
bookId
,
chapterId
,
callback
)
{
apiPOST
({
url
:
`/book/chapterinfo`
,
data
:
{
articleId
:
bookId
,
chapterId
:
chapterId
,
},
callback
})
}
/** 获取推荐文章
* @param {Object} bookId
* @param {Object} callback
*/
function
getBookRecommendData
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/recommend`
,
data
:
{
id
:
bookId
},
callback
})
}
/** 添加阅读记录
* @param {Object} bookId
* @param {Object} callback
*/
function
addReadRecord
(
bookId
,
callback
)
{
apiPOST
({
url
:
`/book/addReadRecord`
,
data
:
{
articleId
:
bookId
},
callback
})
}
// 样式设置
const
KEY_STORAGE_LONG_CONTENT_FORMAT
=
"KEY_STORAGE_LONG_CONTENT_FORMAT"
;
const
KEY_NOTIFICATION_LONG_CONTENT_FORMAT_CHANGE
=
"KEY_NOTIFICATION_LONG_CONTENT_FORMAT_CHANGE"
;
function
saveContentFormat
(
format
)
{
let
result
=
readContentFormat
();
Object
.
keys
(
format
).
forEach
(
key
=>
{
let
value
=
format
[
key
];
result
[
key
]
=
value
||
result
[
key
];
})
saveStorage
(
KEY_STORAGE_LONG_CONTENT_FORMAT
,
result
);
notifyContentFormatChange
(
new
ContentFormat
(
result
));
}
function
readContentFormat
(
id
)
{
let
result
=
readStorage
(
KEY_STORAGE_LONG_CONTENT_FORMAT
);
if
(
result
)
{
result
=
new
ContentFormat
(
result
);
}
else
{
result
=
new
ContentFormat
({
fontSize
:
17
,
backgroundColor
:
"#fff"
,
catalogueList
:
[]
// 章节列表
})
}
return
result
;
}
function
notifyContentFormatChange
(
format
)
{
postNotification
(
KEY_NOTIFICATION_LONG_CONTENT_FORMAT_CHANGE
,
format
);
}
function
watchContentFormatChange
(
fn
,
observer
)
{
if
(
typeof
fn
==
'function'
)
fn
.
call
(
observer
,
readContentFormat
());
addNormalNotificationObserver
(
KEY_NOTIFICATION_LONG_CONTENT_FORMAT_CHANGE
,
(
data
)
=>
{
if
(
typeof
fn
==
'function'
)
fn
.
call
(
observer
,
data
);
},
observer
)
}
function
removeContentFormatChangeWatch
(
observer
)
{
removeNotificationObserver
(
KEY_NOTIFICATION_LONG_CONTENT_FORMAT_CHANGE
,
observer
);
}
module
.
exports
=
{
getBookDetailData
,
getBookRecommendData
,
addReadRecord
,
getChapterinfoData
,
/**
* content format
*/
saveContentFormat
,
readContentFormat
,
notifyContentFormatChange
,
watchContentFormatChange
,
removeContentFormatChangeWatch
}
\ No newline at end of file
vedio/pages.json
View file @
2187139f
...
...
@@ -55,24 +55,6 @@
"navigationBarTitleText"
:
"书籍搜索"
,
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"book-content/book-content"
,
"style"
:
{
"navigationBarTitleText"
:
"阅读"
,
"enablePullDownRefresh"
:
true
}
},
{
"path"
:
"book-long-content/book-long-content"
,
"style"
:
{
"navigationBarTitleText"
:
"阅读"
,
"enablePullDownRefresh"
:
true
}
},
{
"path"
:
"book-cover/book-cover"
,
"style"
:
{
"navigationBarTitleText"
:
"封面"
,
"enablePullDownRefresh"
:
false
}
}]
},
{
"root"
:
"pagesD"
,
...
...
vedio/pagesD/readerRecord/readerRecord.vue
View file @
2187139f
...
...
@@ -82,16 +82,6 @@
},
handleInfo
(
item
)
{
gotoBookContentPage
(
item
.
wechatRecord
.
wxId
,
item
.
id
)
// var bookId = item.id;
// uni.navigateTo({
// url: `/page-subs/sub_A/book-content/book-content`,
// success: (res) => {
// res.eventChannel.emit("openBookContentPage", {
// bookId
// })
// }
// })
},
handleXing
(
item
)
{
var
that
=
this
;
...
...
vedio/static/keys/storage-keys.js
deleted
100644 → 0
View file @
7f2ac0a7
module
.
exports
=
{
}
\ No newline at end of file
vedio/utils/novelManager.js
View file @
2187139f
...
...
@@ -2,11 +2,16 @@ import {
apiPOST
}
from
"../common/utils/apiRequest.js"
import
{
startCountReadTime
,
endCountReadTime
}
from
"@/common/services/index.js"
var
novelPlugin
=
requirePlugin
(
"novel-plugin"
);
// 点击按钮触发此函数跳转到播放器页面
function
navigateToNovel
(
wxId
,
customId
)
{
wx
.
redirect
To
({
wx
.
navigate
To
({
url
:
`plugin-private://wx293c4b6097a8a4d0/pages/novel/index?bookId=
${
wxId
}
&customServerParams=
${
customId
}
`
})
}
...
...
@@ -26,17 +31,22 @@ const proto = {
})
const
customId
=
nm
.
getCustomServerParams
()
this
.
getContent
(
customId
).
then
(
res
=>
{
// 设置章节信息
nm
.
setContents
({
contents
:
res
.
chapter
})
// 设置书架状态
nm
.
setBookshelfStatus
({
bookshelfStatus
:
res
.
status
})
this
.
bookshelfStatus
=
res
.
status
// 调整分享参数
nm
.
setShareParams
({
title
:
'xxx'
,
imageUrl
:
'xxx'
title
:
res
.
title
,
imageUrl
:
res
.
imageUrl
})
})
nm
.
onUserTriggerEvent
((
obj
)
=>
{
...
...
@@ -45,11 +55,40 @@ const proto = {
//开始阅读书籍时
if
(
obj
.
event_id
===
'start_read'
)
{
this
.
nm_report
(
customId
)
// 开始记录阅读时长
startCountReadTime
()
}
//点击“加入书架”
if
(
obj
.
event_id
===
'click_addbookshelf'
)
{
if
(
this
.
bookshelfStatus
==
0
)
{
this
.
bookshelfStatus
=
1
this
.
nm_collect
(
customId
)
}
else
{
this
.
bookshelfStatus
=
0
this
.
nm_uncollect
(
customId
)
}
nm
.
setBookshelfStatus
({
bookshelfStatus
:
this
.
bookshelfStatus
})
}
//插件页 onShow 生命周期
if
(
obj
.
event_id
===
'page_show'
)
{
// 开始记录阅读时长
startCountReadTime
()
}
//插件页 onHide 生命周期
if
(
obj
.
event_id
===
'page_hide'
)
{
// 停止记录阅读时长
endCountReadTime
()
}
//插件页 onUnload 生命周期
if
(
obj
.
event_id
===
'page_unload'
)
{
// 停止记录阅读时长,部分情况下页面无法响应onHide事件
endCountReadTime
()
}
})
},
...
...
@@ -65,7 +104,10 @@ const proto = {
if
(
success
)
{
resolve
({
chapter
:
data
.
wechatRecord
.
wxChapter
chapter
:
data
.
wechatRecord
.
wxChapter
,
status
:
data
.
isCollect
,
title
:
data
.
title
,
imageUrl
:
data
.
avatar
})
}
else
{
reject
(
''
)
...
...
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