Commit 7375eeb9 authored by jyx's avatar jyx

更新首页UI

parent c78d0055
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
this.globalData.bottomSafePadding = Math.max(res.screenHeight - res.safeArea.bottom, 12); this.globalData.bottomSafePadding = Math.max(res.screenHeight - res.safeArea.bottom, 12);
// #endif // #endif
try { try {
let value = uni.getStorageSync('token') || ''; let value = uni.getStorageSync('TOKEN') || '';
let inviteUId = uni.getStorageSync('inviteUId') || ''; let inviteUId = uni.getStorageSync('inviteUId') || '';
if (!inviteUId && options.query.inviteUId) { if (!inviteUId && options.query.inviteUId) {
......
// export default {
// created() {
// //#ifdef MP-WEIXIN
// wx.showShareMenu({
// withShareTicket: true,
// menus: ['shareAppMessage', 'shareTimeline']
// });
// //#endif
// },
// }
export default { export default {
data() { data() {
......
import Label from "./Label"; import Label from "./Label";
export default class Book { export default class Book {
constructor(param) { constructor(param) {
const { const {
id, id,
title, title,
avatar, avatar,
summary, summary,
author, author,
isStick, isStick,
isOriginal, isOriginal,
isPublish, isPublish,
content, content,
username, username,
userAvatar, userAvatar,
quantity, quantity,
commentCount, commentCount,
likeCount, likeCount,
collectCount, collectCount,
isCollect, isCollect,
commentContent, commentContent,
categoryName, categoryName,
categoryId, categoryId,
createTime, createTime,
tagList, tagList,
isUnlock, isUnlock,
free, bookLegumes,
charge, lockRate,
bookLegumes, shortis,
lockRate articleChapterList,
} = param || {} freeNum,
this.id = id; carouselUrl,
this.title = title; isChecked
this.avatar = avatar || "/static/images/logo.png"; } = param || {}
this.summary = summary; this.id = id;
this.tagList = tagList ? tagList.map(item => { this.title = title;
return new Label(item) this.avatar = avatar || "/static/images/logo.png";
}).sort((a, b) => { this.summary = summary;
return a.sort - b.sort this.tagList = tagList ? tagList.map(item => {
}) : []; return new Label(item)
this.author = author; }).sort((a, b) => {
this.isStick = isStick; return a.sort - b.sort
this.isOriginal = isOriginal; }) : [];
this.isPublish = isPublish; this.author = author;
this.content = content; this.isStick = isStick;
this.username = username; this.isOriginal = isOriginal;
this.userAvatar = userAvatar; this.isPublish = isPublish;
this.quantity = quantity; this.content = content;
this.commentContent = commentContent; this.username = username;
this.commentCount = commentCount this.userAvatar = userAvatar;
this.likeCount = likeCount; this.quantity = quantity;
this.collectCount = collectCount; this.commentContent = commentContent;
this.isCollect = isCollect; this.commentCount = commentCount
this.categoryName = categoryName; this.likeCount = likeCount;
this.categoryId = categoryId; this.collectCount = collectCount;
this.createTime = createTime; this.isCollect = isCollect;
this.isUnlock = isUnlock; this.categoryName = categoryName;
this.charge = charge; this.categoryId = categoryId;
this.free = free; this.createTime = createTime;
this.bookLegumes = bookLegumes; this.isUnlock = isUnlock;
this.lockRate = lockRate; this.bookLegumes = bookLegumes;
} this.lockRate = lockRate;
this.shortis = shortis;
this.freeNum = freeNum;
this.carouselUrl = carouselUrl;
this.isChecked = isChecked;
this.articleChapterList = articleChapterList;
}
} }
\ No newline at end of file
import Book from "../../../common/models/Book"; import Book from "../models/Book.js";
import { import {
getTimeDesc getTimeDesc
} from "../../../common/utils/timeUtil"; } from "../utils/timeUtil";
export default class BookshelfBookItem extends Book { export default class BookshelfBookItem extends Book {
constructor(param) { constructor(param) {
super(param || {}) super(param || {})
const { const {
lastReadTime lastReadTime
} = param || {} } = param || {}
this.lastReadTime = lastReadTime || ""; this.lastReadTime = lastReadTime || "";
this.lastReadTimeDesc = lastReadTime ? getTimeDesc(lastReadTime) : ""; this.lastReadTimeDesc = lastReadTime ? getTimeDesc(lastReadTime) : "";
} }
} }
\ No newline at end of file
...@@ -167,7 +167,7 @@ function collectionBook(isCollected, bookId, callback) { ...@@ -167,7 +167,7 @@ function collectionBook(isCollected, bookId, callback) {
apiPOST({ apiPOST({
url, url,
data: { data: {
articleId:bookId articleId: bookId
}, },
callback callback
}) })
...@@ -284,6 +284,14 @@ function getBookBeanPackData(callback) { ...@@ -284,6 +284,14 @@ function getBookBeanPackData(callback) {
}) })
} }
function getCollects(callback) {
apiPOST({
url: "/book/collectList",
data: {},
callback
})
}
/** /**
* 解锁书籍 * 解锁书籍
...@@ -299,7 +307,43 @@ function buyBookWithBookBean(bookId, callback) { ...@@ -299,7 +307,43 @@ function buyBookWithBookBean(bookId, callback) {
callback callback
}) })
} }
/**
* 获取推荐书籍
* @param {Object} flag
* @param {Object} quantity
*/
function getRecommendV1(flag, quantity, callback) {
apiPOST({
url: `/book/recommendv1`,
data: {
flag: flag,
quantity: quantity
},
callback
})
}
/**
* 猜你喜欢
* @param {Object} flag
*/
function getArticleLike(quantity, callback) {
apiPOST({
url: `/book/articleLike`,
data: {
quantity: quantity
},
callback
})
}
module.exports = { module.exports = {
getRecommendV1,
getArticleLike,
getCollects,
getOpens, getOpens,
getReadTimeCount, getReadTimeCount,
startCountReadTime, startCountReadTime,
......
const { const {
ENUM_SEARCH_TYPE, ENUM_SEARCH_TYPE,
ENUM_MESSAGE_PAGE_TYPE ENUM_MESSAGE_PAGE_TYPE
} = require("../../static/enums/enum_value"); } = require("../../static/enums/enum_value");
// 搜索页面 // 搜索页面
function gotoBookSearchPage(searchType = ENUM_SEARCH_TYPE.WAREHOUSE, keyword) { function gotoBookSearchPage(searchType = ENUM_SEARCH_TYPE.WAREHOUSE, keyword) {
uni.navigateTo({ uni.navigateTo({
url: `/page-subs/sub_A/book-search/book-search`, url: `/page-subs/sub_A/book-search/book-search`,
success: (res) => { success: (res) => {
res.eventChannel.emit("openBookSearchPage", { res.eventChannel.emit("openBookSearchPage", {
keyword, keyword,
searchType searchType
}) })
} }
}) })
} }
// 文章详情 // 文章详情
function gotoBookContentPage(bookId) { function gotoBookContentPage(bookId, shortis) {
uni.navigateTo({ if (shortis && shortis == 0) {
url: `/page-subs/sub_A/book-content/book-content`, gotoShortBookContentPage(bookId)
success: (res) => { } else {
res.eventChannel.emit("openBookContentPage", { gotoLongBookContentPage(bookId)
bookId }
}) }
}
}) // 短篇文章详情
} function gotoShortBookContentPage(bookId) {
// 短篇小说
// 文章封面 uni.navigateTo({
function gotoBookCoverPage(bookId) { url: `/page-subs/sub_A/book-content/book-content`,
return; success: (res) => {
uni.navigateTo({ res.eventChannel.emit("openBookContentPage", {
url: `/page-subs/sub_A/book-cover/book-cover`, bookId
success: (res) => { })
res.eventChannel.emit("openBookCoverPage", { }
bookId })
}) }
}
}) // 长篇文章详情
} function gotoLongBookContentPage(bookId) {
uni.navigateTo({
// vip申请 url: `/page-subs/sub_A/book-long-content/book-long-content`,
function gotoVIPApplyPage() { success: (res) => {
uni.navigateTo({ res.eventChannel.emit("openBookContentPage", {
url: `/pagesA//vipPay/vipPay`, bookId
}) })
} }
})
// 用户编辑 }
function gotoUserEditPage(userInfo) {
uni.navigateTo({ // 文章封面
url: `/page-subs/sub_B/user-edit/user-edit`, function gotoBookCoverPage(bookId) {
success: (res) => { return;
res.eventChannel.emit("openUserEditPage", { uni.navigateTo({
userInfo url: `/page-subs/sub_A/book-cover/book-cover`,
}) success: (res) => {
} res.eventChannel.emit("openBookCoverPage", {
}) bookId
} })
}
module.exports = { })
/** sub_A */ }
gotoBookSearchPage,
gotoBookContentPage, // vip申请
gotoBookCoverPage, function gotoVIPApplyPage() {
uni.navigateTo({
/** sub_B */ url: `/pagesA//vipPay/vipPay`,
gotoVIPApplyPage, })
gotoUserEditPage, }
// 用户编辑
function gotoUserEditPage(userInfo) {
uni.navigateTo({
url: `/page-subs/sub_B/user-edit/user-edit`,
success: (res) => {
res.eventChannel.emit("openUserEditPage", {
userInfo
})
}
})
}
module.exports = {
/** sub_A */
gotoBookSearchPage,
gotoBookContentPage,
gotoBookCoverPage,
/** sub_B */
gotoVIPApplyPage,
gotoUserEditPage,
} }
\ No newline at end of file
...@@ -247,8 +247,7 @@ function saveToken(token) { ...@@ -247,8 +247,7 @@ function saveToken(token) {
function readToken() { function readToken() {
if (!LOCAL_TOKEN) { if (!LOCAL_TOKEN) {
// LOCAL_TOKEN = readStorage(KEY_STORAGE_TOKEN) LOCAL_TOKEN = readStorage(KEY_STORAGE_TOKEN)
LOCAL_TOKEN = readStorage('token')
} }
return LOCAL_TOKEN; return LOCAL_TOKEN;
} }
......
<template>
<view class="banneritem">
<swiper :autoplay="true" :interval="2000" :duration="500">
<swiper-item @click="handleBanner(item)" v-for='(item, index) in bannerList' :key='index'
style="border-radius: 20rpx;">
<image class="banner-img" :src="item.carouselUrl" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
</template>
<script>
import {
gotoBookContentPage
} from '../../common/services/page-route.js';
import {
getRecommendV1
} from "../../common/services/index.js"
import BookshelfBookItem from '../../common/models/BookshelfBookItem.js';
import SystemInfoMixin from "../../common/mixins/system-info-mixin.js"
export default {
mixins: [SystemInfoMixin],
data() {
return {
bannerList: []
};
},
methods: {
handleBanner(e) {
gotoBookContentPage(e.id, e.shortis)
},
initData() {
this.refreshList();
},
// 刷新数据列表
refreshList() {
getRecommendV1('carousel', 10, (success, data) => {
if (success) {
this.changeData(data)
}
})
},
changeData(e) {
this.bannerList = e.records.map(item => {
return new BookshelfBookItem(item)
})
},
}
}
</script>
<style lang="scss">
.banneritem {
margin: 20rpx 30rpx 0 30rpx;
// height: 310rpx;
.banner-img {
height: 320rpx;
}
}
</style>
\ No newline at end of file
<template> <template>
<view class="book-list-item" @click="tapItem"> <view class="book-list-item" @click="tapItem">
<view class="cover-box item"> <view class="cover-box item">
<!-- <image v-show="imageError" class="cover" src="/static/images/image_error.png" mode="aspectFill"></image> -->
<image class="cover" :src="item.avatar" mode="aspectFill"></image> <image class="cover" :src="item.avatar" mode="aspectFill"></image>
</view> </view>
<view class="c-flex_column"> <view class="c-flex_column">
<view class="c-flex_row row" style="justify-content: space-between;padding-left:20rpx;"> <view class="c-flex_row row" style="justify-content: space-between;">
<view class="c-flex_column c-justify_center item"> <view class="c-flex_column c-justify_center item">
<view class="title"> <view class="title">
{{item.title}} {{item.title?item.title:''}}
</view> </view>
</view> </view>
<view class="close-button item" v-if='showClose'> <view class="close-button item" v-if='showClose'>
...@@ -17,9 +16,9 @@ ...@@ -17,9 +16,9 @@
</view> </view>
</view> </view>
<view class="c-flex_row row"> <view class="c-flex_row row">
<view class="c-flex_column c-justify_between content c-flex_1 item"> <view class="c-flex_column c-justify_between c-flex_1 item">
<view class="desc row"> <view class="desc row">
{{item.summary}} {{item.summary?item.summary:''}}
</view> </view>
<view class="c-flex_row c-align_center label-box row"> <view class="c-flex_row c-align_center label-box row">
<slot name="footer"> <slot name="footer">
...@@ -60,7 +59,11 @@ ...@@ -60,7 +59,11 @@
watch: {}, watch: {},
computed: { computed: {
showCategory: function() { showCategory: function() {
return this.item.categoryName if (this.item && this.item.categoryName) {
return true
} else {
return false
}
}, },
showErrorImage: function() { showErrorImage: function() {
return this.imageError; return this.imageError;
...@@ -96,10 +99,10 @@ ...@@ -96,10 +99,10 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.book-list-item { .book-list-item {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
padding: 20rpx 40rpx; padding: 20rpx 20rpx;
.row { .row {
margin-bottom: 20rpx; margin-bottom: 20rpx;
...@@ -121,6 +124,9 @@ ...@@ -121,6 +124,9 @@
font-size: 32rpx; font-size: 32rpx;
font-weight: 700; font-weight: 700;
color: #333; color: #333;
overflow: hidden;
white-space: nowrap; //单行显示
text-overflow: ellipsis; //超出部分省略号显示
} }
.close-button { .close-button {
...@@ -150,7 +156,7 @@ ...@@ -150,7 +156,7 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
font-size: 26rpx; font-size: 26rpx;
...@@ -158,13 +164,17 @@ ...@@ -158,13 +164,17 @@
} }
.label-box { .label-box {
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: row;
overflow: auto;
.label { .label {
padding: 5rpx 10rpx; padding: 5rpx 10rpx;
font-size: 20rpx; font-size: 20rpx;
margin-right: 20rpx; margin-right: 20rpx;
border-radius: 10rpx; border-radius: 10rpx;
flex-shrink: 0;
display: inline-block;
} }
.label-color-1 { .label-color-1 {
...@@ -173,8 +183,8 @@ ...@@ -173,8 +183,8 @@
} }
.label-color-2 { .label-color-2 {
color: #3d99fd; color: #F1413C;
background: #d8ebff; background: #FEF3F3;
} }
.label-color-3 { .label-color-3 {
...@@ -186,8 +196,8 @@ ...@@ -186,8 +196,8 @@
.cover-box { .cover-box {
.cover { .cover {
width: 150rpx; width: 165rpx;
height: 200rpx; height: 220rpx;
border-radius: 15rpx; border-radius: 15rpx;
} }
} }
......
<template>
<view class="cover-box" @click="tapItem">
<image v-if="!last" class="cover" :style="'height:'+ coverHeight + 'rpx;'" :src="item.avatar" mode="aspectFill">
</image>
<image v-else class="cover" :style="'height:'+ coverHeight + 'rpx;'"
src="https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/bg_book_more.png" mode="scaleToFill"></image>
<view class="title" v-if="!last">
{{item.title}}
</view>
<view class="c-flex_row c-align_center label-box" v-if="!last">
<slot name="footer">
<view class="label label-color-1" v-if='showCategory'>
{{item.categoryName}}
</view>
<view class="label label-color-2" v-for='(label, labelIndex) in item.tagList' :key='labelIndex'>
{{label.name}}
</view>
</slot>
</view>
</view>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: function() {
return {}
}
},
last: {
type: Boolean,
default: false
},
coverHeight: {
type: Number,
default: 220
}
},
data: function() {
return {
imageError: true
}
},
watch: {},
computed: {
showCategory: function() {
return this.item.categoryName
},
showErrorImage: function() {
return this.imageError;
},
hideErrorImage: function() {
return !this.imageError
}
},
methods: {
tapItem() {
this.$emit("tapItem", {
detail: {
data: this.item
}
})
},
loadImage() {
this.imageError = false;
},
errorImage() {
this.imageError = true
}
}
}
</script>
<style lang="scss" scoped>
.cover-box {
display: flex;
flex-direction: column;
.title {
width: 100%;
font-size: 26rpx;
margin-top: 10rpx;
color: #383B3D;
height: 70rpx;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; //元素几行显示
-webkit-box-orient: vertical;
}
.cover {
width: 100%;
border-radius: 15rpx;
}
.label-box {
margin-top: 6rpx;
display: flex;
flex-direction: row;
overflow: auto;
.label {
padding: 5rpx 10rpx;
font-size: 20rpx;
margin-right: 20rpx;
border-radius: 10rpx;
flex-shrink: 0;
display: inline-block;
}
.label-color-1 {
background: #faefe6;
color: #cc6008;
}
.label-color-2 {
color: #F1413C;
background: #FEF3F3;
}
.label-color-3 {
background: #ff8787;
color: #ff3737;
}
}
}
</style>
\ No newline at end of file
<template>
<view class="book-list-item" @click="tapItem">
<view class="cover-box">
<image class="cover" :src="item.avatar" mode="aspectFill"></image>
</view>
<view class="c-flex_column">
<view class="c-flex_row row" style="justify-content: space-between;">
<view class="c-flex_column c-justify_center item">
<view class="title">
{{item.title?item.title:''}}
</view>
</view>
</view>
<view class="c-flex_row row">
<view class="c-flex_column c-justify_between c-flex_1 item">
<view class="desc row">
{{item.summary?item.summary:''}}
</view>
<view class="label-box row">
<slot name="footer">
<view class="label label-color-1" v-if='showCategory'>
{{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>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: function() {
return {}
}
}
},
data: function() {
return {
imageError: true
}
},
watch: {},
computed: {
showCategory: function() {
if (this.item && this.item.categoryName) {
return true
} else {
return false
}
},
showErrorImage: function() {
return this.imageError;
},
hideErrorImage: function() {
return !this.imageError
}
},
methods: {
tapItem() {
this.$emit("tapItem", {
detail: {
data: this.item
}
})
},
loadImage() {
this.imageError = false;
},
errorImage() {
this.imageError = true
}
}
}
</script>
<style lang="scss" scoped>
.book-list-item {
display: flex;
flex-direction: row;
// padding: 20rpx 20rpx;
.row {
margin-bottom: 20rpx;
}
.row:last-child {
margin-bottom: 0;
}
.item {
width: 140rpx;
}
.title {
width: 100%;
font-size: 26rpx;
margin-top: 10rpx;
color: #383B3D;
height: 70rpx;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; //元素几行显示
-webkit-box-orient: vertical;
}
.desc {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
font-size: 26rpx;
color: #999
}
.label-box {
display: flex;
flex-direction: row;
overflow: auto;
.label {
padding: 5rpx 10rpx;
font-size: 20rpx;
margin-right: 20rpx;
border-radius: 10rpx;
flex-shrink: 0;
display: inline-block;
}
.label-color-1 {
background: #faefe6;
color: #cc6008;
}
.label-color-2 {
color: #F1413C;
background: #FEF3F3;
}
.label-color-3 {
background: #ff8787;
color: #ff3737;
}
}
}
.cover-box {
margin-right: 20rpx;
.cover {
width: 165rpx;
height: 260rpx;
border-radius: 15rpx;
}
}
</style>
\ No newline at end of file
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
<view class="search-box" @click="search"> <view class="search-box" @click="search">
<view class="search-zone c-flex_row c-align_center"> <view class="search-zone c-flex_row c-align_center">
<view class="item"> <view class="item">
<uni-icons type='search' size='28' color="#e5e5e5"></uni-icons> <uni-icons type='search' size='26' color="#949CA4"></uni-icons>
</view> </view>
<input class="item c-flex_1" placeholder="搜索书名/作者名" disabled /> <input class="item c-flex_1" placeholder="搜索书名/作者名" disabled />
<view class="mbutton item"> <!-- <view class="mbutton item">
搜索 搜索
</view> </view> -->
</view> </view>
</view> </view>
</template> </template>
...@@ -39,17 +39,19 @@ ...@@ -39,17 +39,19 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.search-box { .search-box {
background: transparent; background: transparent;
padding: 10rpx 20rpx; padding: 10rpx 30rpx;
.search-zone { .search-zone {
width: 100%; // width: 100%;
border: solid 1rpx #FFE2E2;
border-radius: 35rpx; border-radius: 35rpx;
background: #fff; background: #fff;
padding: 4rpx; padding: 4rpx;
font-size: 28rpx; font-size: 28rpx;
.item { .item {
margin-left: 20rpx; margin-left: 20rpx;
color: #949CA4;
} }
.mbutton { .mbutton {
......
<template>
<scroll-view scroll-y style="height: 100%;">
<book-search-box id='search'></book-search-box>
<Banner ref='banner'></Banner>
<RecommendList ref='recommendList1' :listType="1"></RecommendList>
<RecommendList ref='recommendList2' :listType="2"></RecommendList>
<view style="height: 20rpx;"></view>
</scroll-view>
</template>
<script>
import {
gotoBookContentPage
} from '../../common/services/page-route'
import {
getFirstShow
} from "./services/index.js"
import RecommendList from "../recommend-list/recommend-list.vue";
import Banner from "../banner/banner.vue";
import SystemInfoMixin from "../../common/mixins/system-info-mixin.js"
export default {
mixins: [SystemInfoMixin],
components: {
RecommendList,
Banner
},
data() {
return {
listHeight: 0
};
},
onReady() {
// this.initHeight();
this.initData();
},
onShow() {},
onUnload() {
// 移除监听
removeUserInfoChangeWatch(this);
},
methods: {
show() {
this.getFirstShowData();
},
hide() {
},
getFirstShowData() {
getFirstShow((success, data) => {
if (success) {
setTimeout(() => {
// 匹配用户直接跳转小说
if (data.articleMsg != null) {
gotoBookContentPage(data.articleMsg.id, data.articleMsg.shortis);
}
}, 800);
}
})
},
initData() {
this.refreshList();
},
// 刷新数据列表
refreshList() {
let ref2 = this.$refs.recommendList1;
if (ref2) {
ref2.refreshList();
}
let banner = this.$refs.banner;
if (banner) {
banner.refreshList();
}
let ref = this.$refs.recommendList2;
if (ref) {
ref.refreshList();
}
},
initHeight() {
const query = uni.createSelectorQuery().in(this);
query.exec((res) => {
let result = 0;
res.forEach(item => {
result = result + item.height;
})
this.listHeight = this.windowHeight - result;
})
},
}
}
</script>
<style lang="scss">
</style>
\ No newline at end of file
<template>
<view class="bookshelf">
<read-time-count-row id='count' ref='timeCount'></read-time-count-row>
<view class="bookitem" v-if="dataList.length>0">
<book-list-item2 class="item" v-for='(item, index) in dataList' :key='index' :item='item'
:last="index>=dataList.length-1" @tapItem='tapItem($event, index)' @close='tapClose($event, index)'>
</book-list-item2>
</view>
<c-shelf-empty v-else></c-shelf-empty>
</view>
</template>
<script>
import common from '@/mixins/common';
import {
getCollects,
} from "../../../common/services/index.js"
import {
gotoBookContentPage
} from '../../../common/services/page-route';
import BookshelfBookItem from '../../../common/models/BookshelfBookItem.js';
export default {
mixins: [common],
props: {
height: {
type: Number,
default: 0
},
},
data: function() {
return {
dataList: [],
}
},
methods: {
refreshList() {
getCollects((success, data) => {
if (success) {
this.changeData(data)
}
})
this.refreshTimeCount()
},
refreshTimeCount() {
let ref = this.$refs.timeCount;
if (ref) {
ref.refresh()
}
},
changeData(e) {
this.dataList = e.records.map(item => {
return new BookshelfBookItem(item)
})
this.dataList.push({})
},
tapItem(e, index) {
if (index >= this.dataList.length - 1) {
uni.$emit('goWareHouse')
return
}
gotoBookContentPage(e.detail.data.id, e.detail.data.shortis)
}
}
}
</script>
<style lang="scss" scoped>
.bookshelf {
display: flex;
flex-direction: column;
border-radius: 20rpx;
background-color: white;
margin: 30rpx;
.bookitem {
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding-left: 20rpx;
.item {
width: 22%;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.item:last-child {
margin-bottom: 0;
margin-right: 0;
}
}
}
</style>
\ No newline at end of file
import {
apiGET,
apiPOST
} from "../../../common/utils/apiRequest.js"
function getFirstShow(callback) {
apiPOST({
url: "/book/firstArticle",
callback
})
}
module.exports = {
getFirstShow
}
\ No newline at end of file
<template> <template>
<z-paging> <scroll-view scroll-y style="height: 100%;">
<c-navi id='navi'></c-navi> <BookshelfList ref='bookList' v-on:showEditBarR="showEditBarR"></BookshelfList>
<book-search-box id='search' :searchType='searchType'></book-search-box> <RecommendList ref='recommendList' :listType="0"></RecommendList>
<read-time-count-row id='count' ref='timeCount' @resize='resizeTimeCount'></read-time-count-row> <view style="height: 20rpx;"></view>
<BookshelfList ref='bookList' :height='listHeight'></BookshelfList> </scroll-view>
<c-login></c-login>
</z-paging>
</template> </template>
<script> <script>
import BookshelfList from "./components/bookshelf-list.vue"; import BookshelfList from "./components/bookshelf-list.vue";
import RecommendList from "../recommend-list/recommend-list.vue";
import SystemInfoMixin from "../../common/mixins/system-info-mixin.js" import SystemInfoMixin from "../../common/mixins/system-info-mixin.js"
import {
watchUserInfoChange,
removeUserInfoChangeWatch
} from "../../common/services/userServices.js";
import {
ENUM_SEARCH_TYPE
} from "../../static/enums/enum_value";
import { import {
removeCollectionChangeWatch, removeCollectionChangeWatch,
watchCollectionChange watchCollectionChange
...@@ -25,30 +17,27 @@ ...@@ -25,30 +17,27 @@
export default { export default {
mixins: [SystemInfoMixin], mixins: [SystemInfoMixin],
components: { components: {
BookshelfList BookshelfList,
RecommendList
}, },
data() { data() {
return { return {
searchType: ENUM_SEARCH_TYPE.BOOKSHELF,
listHeight: 0 listHeight: 0
}; };
}, },
onReady() { onReady() {
this.initHeight(); this.initData();
// 监听用户变动
watchUserInfoChange((info) => {
if (info.userInfo) {
this.initData();
}
}, this)
// 监听收藏变动 // 监听收藏变动
watchCollectionChange(() => { watchCollectionChange(() => {
this.refreshList(); this.refreshCollect();
}, this); }, this);
}, },
onShow() { onShow() {
// 更新阅读时间统计 // 更新阅读时间统计
this.refreshTimeCount(); let ref = this.$refs.bookList;
if (ref) {
ref.refreshTimeCount();
}
}, },
onUnload() { onUnload() {
// 移除监听 // 移除监听
...@@ -56,56 +45,33 @@ ...@@ -56,56 +45,33 @@
removeCollectionChangeWatch(this); removeCollectionChangeWatch(this);
}, },
methods: { methods: {
show() { show() {
this.$refs.timeCount.refresh() let ref = this.$refs.bookList;
if (ref) {
this.initHeight(); ref.refreshTimeCount();
// 监听用户变动 }
watchUserInfoChange((info) => {
if (info.userInfo) {
this.initData();
}
}, this)
// 监听收藏变动
watchCollectionChange(() => {
this.refreshList();
}, this);
}, },
hide() { hide() {
},
resizeTimeCount() {
this.initHeight();
}, },
initData() { initData() {
this.refreshList(); this.refreshCollect();
this.refreshBook();
}, },
// 初始化刷新 refreshCollect() {
initRefresh() {
let ref = this.$refs.bookList;
if (ref) {
ref.initRefresh();
}
},
// 刷新数据列表
refreshList() {
let ref = this.$refs.bookList; let ref = this.$refs.bookList;
if (ref) { if (ref) {
ref.refreshList(); ref.refreshList();
} }
}, },
refreshTimeCount() { refreshBook() {
let ref = this.$refs.timeCount; let ref = this.$refs.recommendList;
if (ref) { if (ref) {
ref.refresh(); ref.refreshList();
} }
}, },
initHeight() { initHeight() {
const query = uni.createSelectorQuery().in(this); const query = uni.createSelectorQuery().in(this);
query.select("#navi").boundingClientRect();
query.select("#search").boundingClientRect();
query.select("#count").boundingClientRect();
query.select("#count").boundingClientRect();
query.exec((res) => { query.exec((res) => {
let result = 0; let result = 0;
res.forEach(item => { res.forEach(item => {
...@@ -114,6 +80,18 @@ ...@@ -114,6 +80,18 @@
this.listHeight = this.windowHeight - result; this.listHeight = this.windowHeight - result;
}) })
}, },
showEditBarR(b) {
this.$emit("showEditBarH", b);
},
fullChoice() {
this.$refs.bookList.fullChoice()
},
noChoice() {
this.$refs.bookList.noChoice()
},
deleteCollect() {
this.$refs.bookList.deleteCollect()
},
} }
} }
</script> </script>
......
<template> <template>
<view> <view class="bookshelf">
<c-list ref='list' :showShelfEmpty="true" flag='bookshelf' :needLogin="true" :height="height" url='/book/collectList' <view class="topitem">
:param="requestParam" @change='changeData' method="POST"> <read-time-count-row id='count' ref='timeCount'></read-time-count-row>
<book-list-item v-for='(item, index) in dataList' :key='index' :item='item' <view @click="showEditBar = !showEditBar">
@tapItem='tapItem($event, index)' @close='tapClose($event, index)'> <image v-if="showEditBar" mode="widthFix" src="@/static/images/close.png">
<template v-slot:footer> </image>
<view class="c-flex_row c-aligns_center"> <image v-else mode="widthFix" src="@/static/images/edit.png">
<uni-icons type='calendar' size="16" color="#999"></uni-icons> </image>
<view class="info"> </view>
{{item.lastReadTime}} 前阅读过 </view>
</view> <view class="bookitem" v-if="dataList.length>0">
</view> <shelf-list-item class="item" v-for='(item, index) in dataList' :key='index' :item='item'
</template> :last="index>=dataList.length-1" @tapItem='tapItem($event, index)' @cbClick='cbClick(index)'
</book-list-item> :showChecked="showEditBar" v-on:showEditBarR="showEditBarR">
</c-list> </shelf-list-item>
</view> </view>
</template> <c-shelf-empty v-else></c-shelf-empty>
</view>
<script> </template>
import {
gotoBookContentPage <script>
} from '../../../common/services/page-route'; import SystemInfoMixin from "../../../common/mixins/system-info-mixin.js"
import { import ShelfListItem from "./shelf-list-item.vue";
isEmpty
} from '../../../common/utils/util'; import ReadTimeCountRow from "@/components/read-time-count-row/read-time-count-row.vue";
import BookshelfBookItem from '../models/BookshelfBookItem';
import { import {
collectionBook, getCollects
noticeCollectionListChange } from "../../../common/services/index.js"
} from "../../../common/services/index.js" import {
export default { gotoBookContentPage
props: { } from '../../../common/services/page-route';
height: {
type: Number, import BookshelfBookItem from '../../../common/models/BookshelfBookItem.js';
default: 0
}, import {
}, collectionBook,
data: function() { noticeCollectionListChange
return { } from "../../../common/services/index.js"
dataList: [],
} export default {
}, mixins: [SystemInfoMixin],
computed: { props: {
requestParam: function() { height: {
return {} type: Number,
} default: 0
}, },
methods: { },
initRefresh() { components: {
if (isEmpty(this.dataList)) { ShelfListItem,
this.refreshList(); ReadTimeCountRow
} },
}, data: function() {
refreshList() { return {
let ref = this.$refs.list; dataList: [],
if (ref) { bookMore: 'https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/bg_book_more.png',
ref.onPullRefreshing(); isEditStyle: false,
} showEditBar: false
}, }
changeData(e) { },
console.log(e) watch: {
this.dataList = e.detail.data.map(item => { showEditBar: {
return new BookshelfBookItem(item) handler(newValue, oldValue) {
}) this.$emit("showEditBarR", newValue)
}, }
tapItem(e, index) { },
gotoBookContentPage(e.detail.data.id) },
}, methods: {
tapClose(e, index) { refreshList() {
let item = e.detail.data; getCollects((success, data) => {
uni.showModal({ if (success) {
title: "确认移除", this.changeData(data)
content: `是否确认从书架中移除《${item.title}》`, }
success: (res) => { })
if (res.confirm) { this.refreshTimeCount()
collectionBook(false, item.id, (success, data) => { },
if (success) { refreshTimeCount() {
this.dataList.splice(index, 1); let ref = this.$refs.timeCount;
this.$forceUpdate(); if (ref) {
noticeCollectionListChange(item.id, false); ref.refresh()
} }
}) },
} changeData(e) {
this.dataList = e.records.map(item => {
} return new BookshelfBookItem(item)
}) })
} if (this.dataList.length > 0) {
} this.dataList.push(
} new BookshelfBookItem({}))
</script> }
},
<style lang="scss" scoped> tapItem(e, index) {
.info { if (index >= this.dataList.length - 1) {
font-size: 26rpx; uni.$emit('goWareHouse')
color: #999; return
margin-left: 10rpx; }
}
gotoBookContentPage(e.detail.data.id, e.detail.data.shortis)
},
showEditBarR(e) {
this.showEditBar = e
},
changeEditStyle(e) {
this.isEditStyle = e
if (!this.isEditStyle) {
this.noChoice()
}
},
cbClick(index) {
let newData = this.dataList[index]
newData.isChecked = !newData.isChecked
this.$set(this.dataList, index, newData)
},
longClick(index) {
this.isEditStyle = true
this.dataList[index].isChecked = true
},
fullChoice() {
for (let i = 0; i < this.dataList.length; i++) {
this.dataList[i].isChecked = true
}
},
noChoice() {
for (let i = 0; i < this.dataList.length; i++) {
this.dataList[i].isChecked = false
}
},
deleteCollect() {
let str = ''
for (let i = 0; i < this.dataList.length; i++) {
if (this.dataList[i].isChecked) {
if (this.dataList[i].id) {
str += (this.dataList[i].id + ',')
}
}
}
collectionBook(false, str, (success, data) => {
if (success) {
this.showEditBar = false
this.refreshList()
// noticeCollectionListChange('', false)
}
})
},
}
}
</script>
<style lang="scss" scoped>
.bookshelf {
display: flex;
flex-direction: column;
border-radius: 20rpx;
background-color: white;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.1);
margin: 30rpx;
.topitem {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 30rpx;
image {
width: 50rpx;
height: 50rpx;
}
}
.bookitem {
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding-left: 20rpx;
.item {
width: 30%;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.item:last-child {
// margin-bottom: 0;
// margin-right: 0;
}
}
}
</style> </style>
\ No newline at end of file
<template>
<view class="cover-box" @click.stop="tapItem" @longpress.stop="longClick">
<!-- <image v-show="imageError" class="cover" src="/static/images/image_error.png" mode="aspectFill"></image> -->
<image v-if="!last" class="cover" :src="item.avatar" mode="aspectFill">
</image>
<image v-else class="cover" src="https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/bg_book_more.png"
mode="scaleToFill"></image>
<view class="title" v-if="!last">
{{item.title}}
</view>
<view class="c-flex_row c-align_center label-box" v-if="!last">
<slot name="footer">
<view class="label label-color-1" v-if='showCategory'>
{{item.categoryName}}
</view>
<view class="label label-color-2" v-for='(label, labelIndex) in item.tagList' :key='labelIndex'>
{{label.name}}
</view>
</slot>
</view>
<view v-if="isEditStyle && !last" @click.stop="cbClick" style="position: absolute;background: #000000; opacity: 0.6;width: 92%;height: 96%;top: 0;border-radius:20rpx;
padding-left: 20rpx;padding-top: 20rpx;">
<image v-if="item.isChecked" src="@/static/images/ic_selected.png" style="width: 50rpx;height: 50rpx;" />
<image v-else src="@/static/images/ic_unselected.png" style="width: 50rpx;height: 50rpx;" />
</view>
</view>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: function() {
return {}
}
},
last: {
type: Boolean,
default: false
},
showChecked: {
type: Boolean,
default: false
}
},
computed: {
showCategory: function() {
return this.item.categoryName
},
showErrorImage: function() {
return this.imageError;
},
hideErrorImage: function() {
return !this.imageError
}
},
watch: {
showChecked: {
handler(newValue, oldValue) {
this.isEditStyle = newValue
}
},
isEditStyle: {
handler(newValue, oldValue) {
this.$emit("showEditBarR", newValue)
}
},
},
data() {
return {
isEditStyle: false
};
},
methods: {
longClick() {
if (!this.isEditStyle) {
this.isEditStyle = true
this.cbClick()
}
},
tapItem() {
this.$emit("tapItem", {
detail: {
data: this.item
}
})
},
loadImage() {
this.imageError = false;
},
errorImage() {
this.imageError = true
},
changeEditStyle(e) {
this.isEditStyle = e
},
cbClick() {
this.$emit("cbClick")
}
}
}
</script>
<style lang="scss" scoped>
.cover-box {
display: flex;
flex-direction: column;
position: relative;
.title {
width: 100%;
font-size: 26rpx;
margin-top: 10rpx;
color: #383B3D;
height: 70rpx;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; //元素几行显示
-webkit-box-orient: vertical;
}
.cover {
width: 100%;
height: 300rpx;
border-radius: 15rpx;
}
.label-box {
margin-top: 6rpx;
display: flex;
flex-direction: row;
overflow: auto;
.label {
padding: 5rpx 10rpx;
font-size: 20rpx;
margin-right: 20rpx;
border-radius: 10rpx;
flex-shrink: 0;
display: inline-block;
}
.label-color-1 {
background: #faefe6;
color: #cc6008;
}
.label-color-2 {
color: #F1413C;
background: #FEF3F3;
}
.label-color-3 {
background: #ff8787;
color: #ff3737;
}
}
}
</style>
\ No newline at end of file
module.exports = {} import {
\ No newline at end of file apiGET,
apiPOST
} from "../../../common/utils/apiRequest.js"
module.exports = {
}
\ No newline at end of file
<template> <template>
<scroll-view class="c-list" :style="[scrollStyle]" scroll-y :refresher-enabled='ableRefresh' <scroll-view class="c-list" :style="[scrollStyle]" scroll-y :refresher-enabled='ableRefresh'
refresher-threshold='100' :enable-flex='true' :refresher-triggered='refreshTrigger' @refresherrefresh='refresh' refresher-default-style="black" refresher-threshold='100' :enable-flex='true'
@scrolltolower='onLoadMore'> :refresher-triggered='refreshTrigger' @refresherrefresh='refresh' @scrolltolower='onLoadMore'>
<view class="content" :style="[contentStyle]"> <view class="content" :style="[contentStyle]">
<template v-if='showCover'> <template v-if='showCover'>
<slot name="cover"></slot> <slot name="cover"></slot>
</template> </template>
<template v-else-if='showEmpty'> <template v-else-if='showEmpty'>
<c-shelf-empty v-if="showShelfEmpty"></c-shelf-empty> <c-shelf-empty v-if="showShelfEmpty"></c-shelf-empty>
<c-search-empty v-if="showSearchEmpty"></c-search-empty>
<c-empty v-else></c-empty> <c-empty v-else></c-empty>
</template> </template>
<template v-else> <template v-else>
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
</template> </template>
</view> </view>
<uni-load-more v-if='ableLoadMore' :status="loadMoreStatus.value" :contentText="loadMoreContentText" <uni-load-more v-if='ableLoadMore' :status="loadMoreStatus.value" :contentText="loadMoreContentText"
iconType="snow"></uni-load-more> iconType="circle"></uni-load-more>
</scroll-view> </scroll-view>
</template> </template>
...@@ -68,6 +69,10 @@ ...@@ -68,6 +69,10 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
showSearchEmpty: {
type: Boolean,
default: false
},
/** 初始数据源 */ /** 初始数据源 */
sources: { sources: {
type: Array, type: Array,
...@@ -274,7 +279,7 @@ ...@@ -274,7 +279,7 @@
} }
}, },
/** customeRequst 不会使用的接口*/ /** customeRequst 不会使用的接口*/
requestData() { requestData(noLoading) {
if (this.needLogin && !this.userInfo) { if (this.needLogin && !this.userInfo) {
this.loading = false; this.loading = false;
this.closeTrigger(); this.closeTrigger();
...@@ -299,7 +304,9 @@ ...@@ -299,7 +304,9 @@
header: this.header || {}, header: this.header || {},
callback: (success, data) => { callback: (success, data) => {
this.loading = false; this.loading = false;
this.closeTrigger(); if (!noLoading) {
this.closeTrigger();
}
if (success) { if (success) {
let rows = data.records; let rows = data.records;
let total = data.total; let total = data.total;
......
...@@ -114,43 +114,37 @@ ...@@ -114,43 +114,37 @@
getPhoneNumber() { getPhoneNumber() {
this.ttLoging(); this.ttLoging();
}, },
ttLoging() { ttLoging() {
var that = this; var that = this;
var obj = tt.getLaunchOptionsSync() var obj = wx.getLaunchOptionsSync()
var bookId = ''; var bookId = '';
var thirdParam = ''; var thirdParam = '';
var tips2 = ''; var tips2 = '';
// 抖音feed页参数 // 抖音feed页参数
thirdParam = JSON.stringify(obj.query); thirdParam = JSON.stringify(obj.query);
bookId = obj.query.book_id ?? '' bookId = obj.query.book_id ?? ''
tips2 = obj.query.tips2 ?? '' tips2 = obj.query.tips2 ?? ''
if (this.tips1 == 'mints_book' || tips2 == 'mints_book') { if (this.tips1 == 'mints_book' || tips2 == 'mints_book') {
this.slotParam = JSON.stringify(obj.query); this.slotParam = JSON.stringify(obj.query);
this.$refs.select.open('center'); this.$refs.select.open('center');
} }
tt.login({ wx.login({
force: true, force: true,
success(res) { success(res) {
login({ login({
vedioId: bookId, vedioId: bookId,
code: res.code, code: res.code,
anonymousCode: res.anonymousCode, thirdParam: thirdParam
thirdParam: thirdParam })
}) },
}, fail(res) {},
fail(res) { });
// 登录授权失败
uni.navigateTo({
url: `/pages/warehouse/warehousetemp`,
})
},
});
} }
} }
} }
...@@ -216,7 +210,7 @@ ...@@ -216,7 +210,7 @@
} }
.info { .info {
height: 100rpx; height: 100rpx;
color: #fff; color: #fff;
line-height: 100rpx; line-height: 100rpx;
font-size: 30rpx; font-size: 30rpx;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
props: { props: {
title: { title: {
type: String, type: String,
default: "逸想小说阁" default: "河狸小故事"
} }
}, },
data() { data() {
......
<template>
<view class="c-empty">
<image class='empty-image' :src='emptyImg'>
</image>
<slot></slot>
</view>
</template>
<script>
export default {
name: "c-shelf-empty",
data() {
return {
emptyImg: "https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/bg_search_data.png"
}
},
}
</script>
<style lang="scss" scoped>
.c-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 400rpx;
.empty-image {
width: 324rpx;
height: 184rpx;
}
}
</style>
\ No newline at end of file
<template> <template>
<view class="c-empty"> <view class="c-empty">
<view class="empty-title"> <image class='empty-image' :src='emptyImg'>
</image>
<!-- <view class="empty-title">
暂未添加到书架 暂未添加到书架
</view> </view> -->
<view class="empty-button" @click="goWareHouse"> <view class="empty-button" @click="goWareHouse">
去书 去书城看看
</view> </view>
<slot></slot> <slot></slot>
</view> </view>
...@@ -15,11 +17,11 @@ ...@@ -15,11 +17,11 @@
name: "c-shelf-empty", name: "c-shelf-empty",
data() { data() {
return { return {
emptyImg: "https://mints-pkg.oss-cn-beijing.aliyuncs.com/pkg/img/bg_book_data.png"
}; }
}, },
methods: { methods: {
goWareHouse() { goWareHouse() {
uni.$emit('goWareHouse') uni.$emit('goWareHouse')
// uni.switchTab({ // uni.switchTab({
// url: '/pages/warehouse/warehouse' // url: '/pages/warehouse/warehouse'
...@@ -36,20 +38,26 @@ ...@@ -36,20 +38,26 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
height: 800rpx; height: 400rpx;
.empty-title { .empty-title {
color: #999; color: #999;
font-size: 26rpx; font-size: 26rpx;
margin-bottom: 40rpx; margin-bottom: 20rpx;
}
.empty-image {
width: 240rpx;
height: 240rpx;
} }
.empty-button { .empty-button {
margin-top: 30rpx;
font-size: 30rpx; font-size: 30rpx;
border: 1px solid #FECF02;
padding: 10rpx 40rpx; padding: 10rpx 40rpx;
border-radius: 30rpx; border-radius: 30rpx;
color: #FECF02; color: white;
background: linear-gradient(90deg, #F1413C, #FD6864);
} }
} }
</style> </style>
\ No newline at end of file
<template> <template>
<view> <view style="z-index: 999;">
<uni-popup type="bottom" ref="coinPop" :maskClick="false" :isMaskClick="false"> <uni-popup type="bottom" ref="coinPop" :maskClick="false" :isMaskClick="false">
<view style="position: relative;"> <view style="position: relative;">
<view v-if="agreeFlag" <view v-if="agreeFlag"
...@@ -17,23 +16,28 @@ ...@@ -17,23 +16,28 @@
<view class="body" style="width: 100%;height: 100%;background-color: white;"> <view class="body" style="width: 100%;height: 100%;background-color: white;">
<scroll-view scroll-y> <scroll-view scroll-y>
<view style="display: flex;flex-direction: column;align-items: flex-end;"> <view style="display: flex;flex-direction: column;">
<view style="display: flex;flex-direction: row;"> <view style="display: flex;flex-direction: row;">
<view @click="handleAgree" style="margin-top: 12rpx;margin-right: 10rpx;">付费须知></view> <view v-if="agreementDto != null" @click="handleUnsign"
<image @click="handleClickClose" style="margin-top: 12rpx;margin-left: 10rpx;">自动续费管理></view>
style="width: 30rpx;height: 30rpx;display: flex;align-items: right;margin-top: 20rpx;margin-right: 20rpx;margin-bottom: 10rpx;"
src="@/static/index/ic_quit_white.png"></image> <view style="margin-top: 12rpx;margin-left: auto;display: flex;flex-direction: row;">
<view @click="handleAgree" style="margin-right: 10rpx;">付费须知></view>
<image @click="handleClickClose"
style="width: 30rpx;height: 30rpx;display: flex;align-items: right;margin-top: 20rpx;margin-left: auto;margin-right: 20rpx;margin-bottom: 10rpx;"
src="@/static/index/ic_quit_white.png"></image>
</view>
</view> </view>
</view> </view>
<view class="section"> <view class="section">
<view class="pack-box"> <view class="pack-box">
<view class="pack-item" <view class="pack-item" :class="[{active: index==selectedIndex}]"
:class="[{active: index==selectedIndex}]" v-for='(item, index) in vipList' v-for='(item, index) in vipList' :key='index' @click="choosePack(item, index)">
:key='index' @click="choosePack(item, index)">
<view style="display: flex;flex-direction: column;align-items: center;"> <view style="display: flex;flex-direction: column;align-items: center;">
<view class="price row"> <view class="price row">
{{item.firstPayPrice}} {{item.firstPayPrice<=0 ? '免费试用' : item.firstPayPrice+'元'}}
</view> </view>
<view class="name row" v-if="item.title!=null&&item.title!=''"> <view class="name row" v-if="item.title!=null&&item.title!=''">
...@@ -58,6 +62,10 @@ ...@@ -58,6 +62,10 @@
</view> </view>
</view> </view>
<text class="trialStyle" v-show="hintText!=null&&hintText!=''">
{{hintText}}
</text>
<view style="display: flex;flex-direction: column;align-items: center;"> <view style="display: flex;flex-direction: column;align-items: center;">
<view style="font-size: 24rpx;color: gray;margin-top: 16rpx;margin-bottom: 18rpx;"> <view style="font-size: 24rpx;color: gray;margin-top: 16rpx;margin-bottom: 18rpx;">
订单中如有疑问,请在个人中心联系客服</view> 订单中如有疑问,请在个人中心联系客服</view>
...@@ -75,7 +83,8 @@ ...@@ -75,7 +83,8 @@
<script> <script>
import common from '@/mixins/common'; import common from '@/mixins/common';
import { import {
message message,
navigateTo
} from '@/utils/fun'; } from '@/utils/fun';
export default { export default {
name: 'coinPopup', name: 'coinPopup',
...@@ -100,6 +109,8 @@ ...@@ -100,6 +109,8 @@
selectedIndex: 0, selectedIndex: 0,
agreeFlag: false, agreeFlag: false,
userBean: {}, userBean: {},
agreementDto: null,
hintText: '',
os: 'android', os: 'android',
titleText: '超多精彩小说一键解锁', titleText: '超多精彩小说一键解锁',
showClone: false showClone: false
...@@ -115,12 +126,12 @@ ...@@ -115,12 +126,12 @@
let that = this; let that = this;
this.$refs.coinPop.open('bottom'); this.$refs.coinPop.open('bottom');
if (tt.getSystemInfoSync().platform === 'ios') { if (wx.getSystemInfoSync().platform === 'ios') {
this.os = 'ios'; this.os = 'ios';
} }
this.post({ this.post({
url: '/vip/getVipProducts', url: '/vip/getVipProducts/cyc',
data: { data: {
bookId: that.vedioId bookId: that.vedioId
}, },
...@@ -130,7 +141,7 @@ ...@@ -130,7 +141,7 @@
}) => { }) => {
this.vipList = data.list; this.vipList = data.list;
if (data.list != null) { if (data.list != null) {
// this.selectedIndex = data.list[0].activityType; this.hintText = this.vipList[0].trailRemark;
for (let i = 0; i < data.list.length; i++) { for (let i = 0; i < data.list.length; i++) {
if (data.list[i].activityType == 1) { if (data.list[i].activityType == 1) {
this.selectedIndex = i; this.selectedIndex = i;
...@@ -142,15 +153,28 @@ ...@@ -142,15 +153,28 @@
}); });
this.post({ this.post({
url: '/user/baseMsg', url: '/vip/getOrderList',
showLoading: false, showLoading: false,
success: ({ success: ({
data data
}) => { }) => {
this.userBean = data; console.log("agreement=", data.agreement);
if (data.agreement == undefined) {
console.log("agreement=22222");
this.agreementDto = null;
} else {
this.agreementDto = data.agreement;
}
} }
}); });
}, },
handleUnsign() {
if (this.agreementDto) {
let params = JSON.stringify(this.agreementDto)
navigateTo(`/pagesA/unsign/unsign?params=` + params)
}
},
handleAgree() { handleAgree() {
this.agreeFlag = true this.agreeFlag = true
}, },
...@@ -165,96 +189,82 @@ ...@@ -165,96 +189,82 @@
}, },
choosePack(item, index) { choosePack(item, index) {
this.selectedIndex = index; this.selectedIndex = index;
if (this.vipList[this.selectedIndex].trailRemark != null) {
this.hintText = this.vipList[this.selectedIndex].trailRemark;
} else {
this.hintText = '';
}
this.handlePay(); this.handlePay();
}, },
handlePay() { handlePay() {
let that = this;
var vipBean = this.vipList[this.selectedIndex];
if (this.os == 'ios') { if (this.os == 'ios') {
message.notify('iOS暂不支持购买'); message.notify('暂不支持ios系统~');
return } else {
} this.post({
url: '/vip/getVipPayParams/wechat',
data: {
pid: vipBean.pid,
payChannel: 'WEIXIN'
},
showLoading: true,
success: ({
data
}) => {
if (vipBean.firstPayPrice == 0) {
//签约
that.wxSign(data, vipBean.largeType);
} else {
//普通支付
that.wxPay(data, vipBean.largeType);
}
}
});
}
},
wxPay(wxData, largeType) {
let wxParams = wxData.params;
let that = this; let that = this;
let vipBean = this.vipList[this.selectedIndex]; // 发起微信支付
wx.requestPayment({
// 抖音支付 timeStamp: wxParams.timeStamp,
this.post({ nonceStr: wxParams.nonceStr,
url: '/vip/getVipPayParams/douyin', package: wxParams.packageStr,
data: { signType: wxParams.signType,
bookId: that.vedioId, paySign: wxParams.paySign,
os: that.os, success(res) {
pid: vipBean.pid that.queryOrderStatus(largeType, wxData.tidStr);
}, },
showLoading: true, fail(res) {}
success: ({ })
data
}) => {
that.ttPrePay(data, vipBean.largeType);
}
});
}, },
ttPrePay(ttData, largeType) { wxSign(wxData, largeType) {
if (!tt.canIUse('requestOrder')) { let wxParams = wxData.params;
message.notify('请升级抖音APP版本.');
return
}
uni.showLoading({
title: '加载中...'
});
let that = this; let that = this;
tt.requestOrder({ // 发起微信签约
data: ttData.params.data, wx.navigateToMiniProgram({
byteAuthorization: ttData.params.byteAuthorization, appId: "wxbd687630cd02ce1d",
path: 'pages/index/index',
extraData: wxData.params,
success(res) { success(res) {
that.ttPay(largeType, res.orderId, ttData); console.log("wxSign suc=", res);
if (res.return_code == 'SUCCESS') {
console.log("wxSign suc1111");
// 成功跳转到签约小程序
that.queryOrderStatus(largeType, wxData.tidStr);
} else {
// 签约失败
console.log("wxSign fail22222");
}
}, },
fail(res) { fail(res) {
uni.hideLoading(); // 未成功跳转到签约小程序
console.log('ttPrePay', res.errMsg); console.log("wxSign fail=3333", res);
// message.notify(res.errMsg);
},
});
},
ttPay(largeType, oid, ttData) {
uni.hideLoading();
if (!tt.canIUse('getOrderPayment')) {
message.notify('请升级抖音APP版本!');
return
}
let that = this;
if (this.os == 'ios') {
if (!tt.canIUse('getOrderPayment.object.imId')) {
message.notify('请升级抖音APP版本~');
return
} }
})
tt.getOrderPayment({
orderId: oid,
imId: ttData.imId,
success(res) {
that.queryOrderStatus(largeType, ttData.tidStr);
},
fail(res) {
console.log('ios pay', res.errMsg);
// message.notify(res.errMsg);
},
});
} else {
tt.getOrderPayment({
orderId: oid,
success(res) {
that.queryOrderStatus(largeType, ttData.tidStr);
},
fail(res) {
console.log('android pay', res.errMsg);
// message.notify(res.errMsg);
},
});
}
}, },
queryOrderStatus(largeType, tid) { queryOrderStatus(largeType, tid) {
let that = this; let that = this;
...@@ -309,7 +319,7 @@ ...@@ -309,7 +319,7 @@
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
.active { .active {
background-color: #f4c98b !important; background-color: #f4c98b !important;
border: 6rpx solid #fd5350 !important; border: 6rpx solid #fd5350 !important;
} }
...@@ -337,7 +347,7 @@ ...@@ -337,7 +347,7 @@
} }
.name { .name {
width: calc(90%); width: calc(90%);
text-align: center; text-align: center;
font-size: 29rpx; font-size: 29rpx;
color: #333; color: #333;
...@@ -386,4 +396,16 @@ ...@@ -386,4 +396,16 @@
} }
} }
} }
.trialStyle {
display: flex;
align-items: center;
font-size: 30rpx;
color: darkgray;
margin-left: 20rpx;
margin-right: 20rpx;
word-wrap: break-word;
word-break: break-all;
white-space: pre-line;
}
</style> </style>
\ No newline at end of file
This diff is collapsed.
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
<image @click="onClose" style="width: 50rpx; height: 50rpx;margin-left:auto;margin-right: 30rpx; <image @click="onClose" style="width: 50rpx; height: 50rpx;margin-left:auto;margin-right: 30rpx;
margin-bottom: 30rpx;" src="https://mints-web.oss-cn-beijing.aliyuncs.com/images/ic_close_white.png"></image> margin-bottom: 30rpx;" src="https://mints-web.oss-cn-beijing.aliyuncs.com/images/ic_close_white.png"></image>
<view class="content"> <view class="content">
<button class="button1" type="default" size="default" @click="tapMakePhoneCall">客服电话</button> <button class="button1" type="default" size="default"
<button class="button2" open-type="im" data-im-id="93264117800">客服在线</button> @click="tapMakePhoneCall">客服电话:400-096-9950</button>
<!-- <button class="button2" open-type="im" data-im-id="93264117800">客服在线</button> -->
</view> </view>
</view> </view>
</uni-popup> </uni-popup>
...@@ -14,6 +15,8 @@ ...@@ -14,6 +15,8 @@
</template> </template>
<script> <script>
// import uniPopuo from 'uniPopuo'
export default { export default {
name: 'kefuPopup', name: 'kefuPopup',
props: { props: {
...@@ -35,9 +38,9 @@ ...@@ -35,9 +38,9 @@
this.$refs.kefuPop.close('bottom'); this.$refs.kefuPop.close('bottom');
this.$emit('close'); this.$emit('close');
}, },
tapMakePhoneCall() { tapMakePhoneCall() {
let that=this let that = this
tt.makePhoneCall({ wx.makePhoneCall({
phoneNumber: "4000969950", phoneNumber: "4000969950",
success(res) { success(res) {
// 调用成功 makePhoneCall:ok // 调用成功 makePhoneCall:ok
......
<template> <template>
<view class="c-flex_row c-aligns_center c-justify_between read-time-count-row"> <view class="c-flex_row c-aligns_center c-justify_between read-time-count-row">
<view class="c-flex_column c-aligns_center"> <view class="c-flex_row c-aligns_center">
<view class="title"> <!-- <view class="label">
今日阅读时间 <view class="title">
</view> 今日<br>已读
<view class="value" v-if='count.count'> </view>
<view class="count" v-if='count.hour'> </view> -->
<view class="count-value">{{count.hour}}</view> <image class="labelimg" src="../../static/images/readtext.png"></image>
<view class="count-unit">小时</view> <!-- <view class="value" v-if='count.count'> -->
</view> <view class="value">
<view class="count" v-if='count.minute'> <view class="count">
<view class="count-value">{{count.minute}}</view> <view class="count-value">{{count.hour ?count.hour:'00'}}</view>
<view class="count-unit">分钟</view> <view class="count-unit">小时</view>
</view> </view>
<view class="count" v-if='count.second'> <view class="count">
<view class="count-value">{{count.second}}</view> <view class="count-value">{{count.minute?count.minute:'00'}}</view>
<view class="count-unit"></view> <view class="count-unit"></view>
</view> </view>
</view> <view class="count">
<view class="value" v-else> <view class="count-value">{{count.second?count.second:'00'}}</view>
<view class="count"> <view class="count-unit"></view>
<view class="count-value" style="color: #ffffff00;"> </view>
0 </view>
</view> <!-- <view class="value" v-else>
<view class="count-unit"> <view class="count">
尚未开始 <view class="count-value" style="color: #ffffff00;">
</view> 0
</view> </view>
</view> <view class="count-unit">
</view> 尚未开始
<view class="c-flex_column c-aligns_center"> </view>
<slot name="right"></slot> </view>
</view> </view> -->
</view> </view>
</template> <view class="c-flex_column c-aligns_center">
<slot name="right"></slot>
<script> </view>
import ReadCount from '../../common/models/ReadCount'; </view>
import { </template>
getReadTimeCount
} from '../../common/services'; <script>
export default { import ReadCount from '../../common/models/ReadCount';
name: "read-time-count-row", import {
props: {}, getReadTimeCount
data() { } from '../../common/services';
return { export default {
count: { name: "read-time-count-row",
count: 1, props: {},
hour: 0, data() {
minute: 0, return {
second: 0 count: {
} count: 1,
}; hour: 0,
}, minute: 0,
mounted() { second: 0
this.refresh(); }
}, };
methods: { },
refresh() { mounted() {
this.count = new ReadCount({ this.refresh();
count: getReadTimeCount() },
}) methods: {
this.$nextTick(() => { refresh() {
this.$emit("resize"); this.count = new ReadCount({
}) count: getReadTimeCount()
}, })
} this.$nextTick(() => {
} this.$emit("resize");
</script> })
},
<style lang="scss"> }
.read-time-count-row { }
padding: 20rpx 40rpx; </script>
.title { <style lang="scss">
font-size: 28rpx; .read-time-count-row {
color: #333; padding: 20rpx;
margin-bottom: 20rpx; padding-left: 0;
}
.labelimg {
.value { margin-top: 10rpx;
display: flex; margin-right: 20rpx;
flex-direction: row; width: 65rpx;
align-items: center; height: 70rpx;
}
.count {
display: flex; .value {
flex-direction: row; display: flex;
margin-right: 10rpx; flex-direction: row;
font-size: 24rpx;
color: #333; .count {
position: relative;
.count-value { margin-right: 15rpx;
color: #007aff; font-size: 24rpx;
font-size: 38rpx; background-color: #FEF3F3;
font-weight: 700; border-radius: 10rpx;
height: 40rpx; width: 90rpx;
line-height: 40rpx; height: 90rpx;
} color: #383B3D;
.count-unit { .count-value {
margin-left: 8rpx; position: absolute;
height: 40rpx; top: 42%;
line-height: 40rpx; left: 50%;
} transform: translate(-50%, -50%);
} color: #383B3D;
} font-size: 46rpx;
} font-weight: 700;
}
.count-unit {
font-size: 20rpx;
position: absolute;
left: 50%;
transform: translate(-50%);
bottom: 4rpx;
}
}
}
}
</style> </style>
\ No newline at end of file
<template>
<view class="recommendlist">
<view class="booklabel">
<view class="title">{{title}}</view>
<view class="flex">
<image class="img" src="@/static/images/change.png"></image>
<view class="change" @click="refreshList">换一换</view>
</view>
</view>
<view class="rowitem" v-if="listType==0">
<!-- 猜你喜欢 -->
<book-list-item2 class="item" v-for='(item, index) in dataList' :key='index' :item='item'
@tapItem='tapItem($event, index)'>
</book-list-item2>
</view>
<view class="columnitem" v-else-if="listType==1">
<!-- 热门推荐-首页 -->
<book-list-item :item='dataList[0]' :showClose='false' @tapItem='tapItem($event, index)'>
</book-list-item>
<view class="rowitem">
<book-list-item2 class="item" :item='item' v-if="index!=0" v-for='(item, index) in dataList'
:key='index' @tapItem='tapItem($event, index)'>
</book-list-item2>
</view>
</view>
<view class="rowitem" v-else-if="listType==2">
<!-- 新书推荐 -->
<book-list-item3 class="item2" v-for='(item, index) in dataList' :key='index' :item='item'
:showClose='false' @tapItem='tapItem($event, index)'>
</book-list-item3>
</view>
<view class="columnitem" v-else-if="listType==3">
<!-- 热门推荐-搜索页 -->
<book-list-item v-for='(item, index) in dataList' :key='index' :item='item'
@tapItem='tapItem($event, index)' :showClose='false'>
</book-list-item>
</view>
</view>
</template>
<script>
import common from '@/mixins/common';
import {
getRecommendV1,
getArticleLike
} from "../../common/services/index.js"
import {
gotoBookContentPage
} from '../../common/services/page-route.js';
import BookshelfBookItem from '../../common/models/BookshelfBookItem.js';
import BookListItem from "@/components/book-list-item/book-list-item.vue";
import BookListItem2 from "@/components/book-list-item2/book-list-item2.vue";
import BookListItem3 from "@/components/book-list-item3/book-list-item3.vue";
export default {
mixins: [common],
components: {
BookListItem,
BookListItem2,
BookListItem3
},
props: {
listType: {
type: Number,
default: 0
}
},
data: function() {
return {
dataList: [],
title: '猜你喜欢',
flag: 'hot'
}
},
mounted() {
if (this.listType == 0) {
this.flag = 'like'
this.title = '猜你喜欢'
} else if (this.listType == 1 || this.listType == 3) {
this.flag = 'hot'
this.title = '热门推荐'
} else if (this.listType == 2) {
this.flag = 'newbook'
this.title = '新书推荐'
}
},
methods: {
refreshList() {
if (this.listType == 0) {
getArticleLike(8, (success, data) => {
if (success) {
this.changeData(data)
}
})
} else if (this.listType == 1) {
getRecommendV1(this.flag, 5, (success, data) => {
if (success) {
this.changeData(data)
}
})
} else if (this.listType == 2) {
getRecommendV1(this.flag, 8, (success, data) => {
if (success) {
this.changeData(data)
}
})
} else if (this.listType == 3) {
getRecommendV1(this.flag, 8, (success, data) => {
if (success) {
this.changeData(data)
}
})
}
},
changeData(e) {
this.dataList = e.records.map(item => {
return new BookshelfBookItem(item)
})
},
tapItem(e, index) {
gotoBookContentPage(e.detail.data.id, e.detail.data.shortis)
},
}
}
</script>
<style lang="scss" scoped>
.recommendlist {
display: flex;
flex-direction: column;
border-radius: 20rpx;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.1);
background-color: white;
margin: 30rpx;
margin-bottom: 0;
.booklabel {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100rpx;
line-height: 100rpx;
padding: 0 20rpx;
.title {
font-weight: 500;
font-size: 34rpx;
color: #383B3D;
}
.img {
margin-right: 10rpx;
width: 30rpx;
height: 26rpx;
}
.change {
font-weight: 400;
font-size: 24rpx;
color: #A5A5AD;
}
}
.columnitem {
display: flex;
flex-direction: column;
}
.rowitem {
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding-left: 20rpx;
.item2 {
width: 47%;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.item:last-child {
margin-right: 0;
}
.item {
width: 22%;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.item:last-child {
// margin-bottom: 0;
margin-right: 0;
}
}
}
</style>
\ No newline at end of file
<!-- 底部弹窗(分享) -->
<template>
<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper-box" @click.stop="clear">
<slot />
</view>
</uni-transition>
</view>
</template>
<script>
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @event {Function} change 打开关闭弹窗触发,e={show: false}
*/
export default {
name: 'UniPopup',
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
type: {
type: String,
default: 'center'
},
// maskClick
maskClick: {
type: Boolean,
default: true
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
maskClass: {
'position': 'fixed',
'bottom': 0,
'top': 0,
'left': 0,
'right': 0,
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
},
transClass: {
'position': 'fixed',
'left': 0,
'right': 0,
}
}
},
watch: {
type: {
handler: function(newVal) {
switch (this.type) {
case 'top':
this.ani = ['slide-top']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
}
break
case 'bottom':
this.ani = ['slide-bottom']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
'bottom': 0
}
break
case 'center':
this.ani = ['zoom-out', 'fade']
this.transClass = {
'position': 'fixed',
/* #ifndef APP-NVUE */
'display': 'flex',
'flexDirection': 'column',
/* #endif */
'bottom': 0,
'left': 0,
'right': 0,
'top': 0,
'justifyContent': 'center',
'alignItems': 'center'
}
break
}
},
immediate: true
}
},
created() {
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation()
},
open() {
this.showPopup = true
this.$nextTick(() => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.showTrans = true
}, 50);
})
this.$emit('change', {
show: true
})
},
close(type) {
this.showTrans = false
this.$nextTick(() => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.$emit('change', {
show: false
})
this.showPopup = false
}, 300)
})
},
onTap() {
if (!this.maskClick) return
this.close()
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup {
position: fixed;
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
bottom: 0;
left: 0;
right: 0;
/* #ifndef APP-NVUE */
z-index: 99999999999;
/* #endif */
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
opacity: 0;
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.uni-top-mask {
opacity: 1;
}
.uni-bottom-mask {
opacity: 1;
}
.uni-center-mask {
opacity: 1;
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
}
.top {
top: 0;
left: 0;
right: 0;
transform: translateY(-500px);
}
.bottom {
bottom: 0;
left: 0;
right: 0;
transform: translateY(500px);
}
.center {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
bottom: 0;
left: 0;
right: 0;
top: 0;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0;
}
.uni-popup__wrapper-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
}
.content-ani {
// transition: transform 0.3s;
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.uni-top-content {
transform: translateY(0);
}
.uni-bottom-content {
transform: translateY(0);
}
.uni-center-content {
transform: scale(1);
opacity: 1;
}
</style>
<template> <template>
<scroll-view class="bar-box" scroll-x id='box' :scroll-into-view="scrollId"> <scroll-view class="bar-box" scroll-x id='box' :scroll-into-view="scrollId">
<view v-if='showEmpty' class="tab-item"> <!-- <view v-if='showEmpty' class="tab-item">
<view class="title"> <view class="title">
暂无分类数据 暂无分类数据
</view> </view>
</view> </view> -->
<view v-else :id="'item_'+index" class="tab-item" :class="{'tab-item-selected': item.selected}" <view :id="'item_'+index" class="tab-item" :class="{'tab-item-selected': item.selected}"
v-for="(item, index) in tabs" :key='item.name' @click="tapTab(index)"> v-for="(item, index) in tabs" :key='item.name' @click="tapTab(index)">
<view class="title"> <view class="title">
{{item.name}} {{item.name}}
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</template> </template>
<script> <script>
import { import {
isEmpty isEmpty
} from '../../../common/utils/util'; } from '../../../common/utils/util';
class Tab { class Tab {
constructor(param) { constructor(param) {
const { const {
name, name,
selected = false, selected = false,
data data
} = param || {} } = param || {}
this.name = name; this.name = name;
this.selected = selected; this.selected = selected;
this.data = data; this.data = data;
} }
} }
export default { export default {
props: { props: {
range: { range: {
type: Array, type: Array,
default: function() { default: function() {
return [] return []
} }
}, },
rangeKey: { rangeKey: {
type: String, type: String,
default: "name" default: "name"
}, },
current: { current: {
type: Number, type: Number,
default: 0 default: 0
} }
}, },
data: function() { data: function() {
return { return {
tabs: [], tabs: [],
tabIndex: 0, tabIndex: 0,
scrollId: null scrollId: null
} }
}, },
computed: { computed: {
showEmpty: function() { showEmpty: function() {
return isEmpty(this.tabs); return isEmpty(this.tabs);
}, },
tabValueChange: function() { tabValueChange: function() {
const { const {
range, range,
rangeKey, rangeKey,
tabIndex tabIndex
} = this; } = this;
return { return {
range, range,
rangeKey, rangeKey,
tabIndex tabIndex
} }
}, },
}, },
watch: { watch: {
tabValueChange: { tabValueChange: {
handler: function(n) { handler: function(n) {
let range = n.range; let range = n.range;
let rangeKey = n.rangeKey; let rangeKey = n.rangeKey;
let tabIndex = n.tabIndex; let tabIndex = n.tabIndex;
if (range) { if (range) {
this.tabs = range.map((item, index) => { this.tabs = range.map((item, index) => {
return new Tab({ return new Tab({
name: typeof item == 'object' ? item[rangeKey] : item, name: typeof item == 'object' ? item[rangeKey] : item,
selected: index == tabIndex, selected: index == tabIndex,
data: item data: item
}) })
}) })
} else { } else {
this.tabs = []; this.tabs = [];
} }
}, },
deep: true, deep: true,
immediate: true immediate: true
}, },
current: { current: {
handler: function(n) { handler: function(n) {
this.tabIndex = n; this.tabIndex = n;
}, },
immediate: true immediate: true
}, },
tabIndex: { tabIndex: {
handler: function(n) { handler: function(n) {
this.scrollId = `item_${n}` this.scrollId = `item_${n}`
}, },
}, },
tabs: { tabs: {
handler: function(n) { handler: function(n) {
this.$nextTick(() => { this.$nextTick(() => {
this.$emit("ready") this.$emit("ready")
}) })
}, },
immediate: true, immediate: true,
deep: true deep: true
} }
}, },
methods: { methods: {
tapTab(index) { tapTab(index) {
if (this.tabIndex != index) { if (this.tabIndex != index) {
this.tabIndex = index; this.tabIndex = index;
this.$emit("change", { this.$emit("change", {
index: index, index: index,
value: this.tabs[index].data value: this.tabs[index].data
}) })
} }
} }
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.bar-box { .bar-box {
white-space: nowrap; margin: 20rpx 0;
padding: 0 20rpx; white-space: nowrap;
width: calc(100% - 40rpx); padding: 0 20rpx;
} width: calc(100% - 40rpx);
}
.tab-item {
display: inline-flex; .tab-item {
flex-direction: column; display: inline-flex;
align-items: center; flex-direction: column;
justify-content: center; align-items: center;
padding: 25rpx 20rpx; justify-content: center;
font-size: 30rpx; border-radius: 30rpx;
background: transparent; padding: 8rpx 16rpx;
color: #888; font-size: 30rpx;
background: #EEEEEE;
.title { color: #6B6B6B;
min-width: 80rpx; margin: 0 16rpx;
text-align: center;
} .title {
} min-width: 80rpx;
text-align: center;
.tab-item:first-child { }
padding-left: 0; }
}
.tab-item:first-child {
.tab-item:last-child { margin-left: 0;
padding-right: 0; }
}
.tab-item:last-child {
.tab-item-selected { margin-right: 0;
font-size: 36rpx; }
font-weight: 700;
color: #333 .tab-item-selected {
} background: #F1413C;
color: white;
}
</style> </style>
\ No newline at end of file
<template> <template>
<view> <view>
<c-list ref='list' flag='warehouse' method="POST" :height="height" url='/book/articleList/' :param="requestParam" <c-list ref='list' flag='warehouse' method="POST" :height="height" url='/book/articleList/'
@change='changeData'> :param="requestParam" @change='changeData'>
<book-list-item v-for='(item, index) in dataList' :key='index' :item='item' :showClose='false' <book-list-item v-for='(item, index) in dataList' :key='index' :item='item' :showClose='false'
@tapItem='tapItem($event, index)' @close='tapClose($event, index)'> @tapItem='tapItem($event, index)' @close='tapClose($event, index)'>
</book-list-item> </book-list-item>
</c-list> </c-list>
</view> </view>
</template> </template>
<script> <script>
import { import {
gotoBookContentPage gotoBookContentPage
} from '../../../common/services/page-route'; } from '../../../common/services/page-route';
import { import {
isEmpty isEmpty
} from '../../../common/utils/util' } from '../../../common/utils/util'
import WarehouseBookItem from '../models/WarehouseBookItem.js'; import WarehouseBookItem from '../models/WarehouseBookItem.js';
export default { import CList from "@/components/c-list/c-list.vue";
components: {},
props: { export default {
height: { components: {
type: Number, CList
default: 0 },
}, props: {
category: { height: {
type: Object, type: Number,
default: function() { default: 0
return {} },
} category: {
}, type: Object,
}, default: function() {
data: function() { return {}
return { }
dataList: [], },
} },
}, data: function() {
computed: { return {
requestParam: function() { dataList: [],
return { }
categoryId: this.category.value },
} computed: {
} requestParam: function() {
}, return {
watch: {}, categoryId: this.category.value
methods: { }
initRefresh() { }
if (isEmpty(this.dataList)) { },
this.refreshList(); watch: {},
} methods: {
}, initRefresh() {
refreshList() { if (isEmpty(this.dataList)) {
this.$nextTick(() => { this.refreshList();
let ref = this.$refs.list; }
if (ref) { },
ref.onPullRefreshing(); refreshList() {
} this.$nextTick(() => {
}) let ref = this.$refs.list;
}, if (ref) {
changeData(e) { ref.requestData(1);
this.dataList = e.detail.data.map(item => { }
return new WarehouseBookItem(item) })
}) },
}, changeData(e) {
tapItem(e, index) { this.dataList = e.detail.data.map(item => {
gotoBookContentPage(e.detail.data.id) return new WarehouseBookItem(item)
}, })
tapClose(e, index) { },
// TODO 仓库点击关闭按钮,弹窗选择关闭原因 tapItem(e, index) {
uni.showModal({ gotoBookContentPage(e.detail.data.id, e.detail.data.shortis)
title: "不喜欢", },
content: `是否确认减少推荐此类书籍?` tapClose(e, index) {
}) // TODO 仓库点击关闭按钮,弹窗选择关闭原因
} uni.showModal({
} title: "不喜欢",
} content: `是否确认减少推荐此类书籍?`
</script> })
}
<style> }
}
</script>
<style>
</style> </style>
\ No newline at end of file
import { import {
apiGET, apiGET,
apiPOST apiPOST
} from "../../../common/utils/apiRequest.js" } from "../../../common/utils/apiRequest.js"
function getCategorys(callback) { function getCategorys(callback) {
apiPOST({ apiPOST({
url: "/book/categoryList/", url: "/book/categoryList/",
callback callback
}) })
} }
function getFirstShow(callback) {
apiPOST({ module.exports = {
url: "/book/firstArticle", getCategorys
callback
})
}
module.exports = {
getCategorys,
getFirstShow
} }
\ No newline at end of file
<template> <template>
<z-paging> <scroll-view scroll-y style="height: 100%;">
<c-navi id='navi'></c-navi>
<book-search-box id='search'></book-search-box>
<CategoryBar id='category' :range='categorys' :current='currentIndex' @change='changeCategory' <CategoryBar id='category' :range='categorys' :current='currentIndex' @change='changeCategory'
@ready='readyCategory'></CategoryBar> @ready='readyCategory'></CategoryBar>
<view :style="[listStyle]" v-if='showEmpty'> <view :style="[listStyle]" v-if='showEmpty'>
...@@ -12,25 +10,24 @@ ...@@ -12,25 +10,24 @@
@change="changeSwiper"> @change="changeSwiper">
<swiper-item v-for='(item, index) in categorys' :key='index'> <swiper-item v-for='(item, index) in categorys' :key='index'>
<WarehouseList :ref="`bookList${index}`" :category='item' :height='listHeight'></WarehouseList> <WarehouseList :ref="`bookList${index}`" :category='item' :height='listHeight'></WarehouseList>
<!-- <WarehouseList ref="bookList" :category='item' :height='listHeight'></WarehouseList> -->
</swiper-item> </swiper-item>
</swiper> </swiper>
</view> </view>
<c-login></c-login> <view style="height: 20rpx;"></view>
</z-paging> </scroll-view>
</template> </template>
<script> <script>
import CategoryBar from "./components/category-bar.vue"; import CategoryBar from "./components/category-bar.vue";
import WarehouseList from "./components/warehouse-list.vue"; import WarehouseList from "./components/warehouse-list.vue";
import CEmpty from "@/components/c-empty/c-empty.vue";
import SystemInfoMixin from "../../common/mixins/system-info-mixin.js"; import SystemInfoMixin from "../../common/mixins/system-info-mixin.js";
import Category from "./models/Category.js"; import Category from "./models/Category.js";
import { import {
gotoBookContentPage gotoBookContentPage
} from '../../common/services/page-route' } from '../../common/services/page-route'
import { import {
getCategorys, getCategorys
getFirstShow
} from "./services/index.js" } from "./services/index.js"
import { import {
isEmpty isEmpty
...@@ -42,7 +39,8 @@ ...@@ -42,7 +39,8 @@
mixins: [SystemInfoMixin], mixins: [SystemInfoMixin],
components: { components: {
CategoryBar, CategoryBar,
WarehouseList WarehouseList,
CEmpty
}, },
data() { data() {
return { return {
...@@ -51,8 +49,9 @@ ...@@ -51,8 +49,9 @@
currentIndex: 0, currentIndex: 0,
}; };
}, },
onLoad(options) { onLoad(options) {},
onReady() {
this.getCategoryData()
}, },
computed: { computed: {
showEmpty: function() { showEmpty: function() {
...@@ -60,7 +59,7 @@ ...@@ -60,7 +59,7 @@
}, },
listStyle: function() { listStyle: function() {
return { return {
height: `${this.listHeight}px` height: `${this.listHeight}px`,
} }
}, },
categroyChange: function() { categroyChange: function() {
...@@ -79,53 +78,20 @@ ...@@ -79,53 +78,20 @@
handler: function(n, o) { handler: function(n, o) {
setTimeout(() => { setTimeout(() => {
this.$refs[`bookList${n.currentIndex}`][0].initRefresh(); this.$refs[`bookList${n.currentIndex}`][0].initRefresh();
}, 500) }, 300)
// this.$nextTick(() => {
// // this.$refs[`bookList${n.currentIndex}`][0].initRefresh();
// let ref = this.$refs.bookList;
// if (ref) {
// ref[n.currentIndex].initRefresh();
// }
// })
}, },
deep: true deep: true
} }
}, },
methods: { methods: {
show() { show() {
this.getFirstShowData();
this.getCategoryData();
if (wx.setVisualEffectOnCapture) {
wx.setVisualEffectOnCapture({
visualEffect: 'hidden',
success: (res) => {
},
})
}
}, },
hide() { hide() {
}, },
readyCategory() { readyCategory() {
setTimeout(() => { setTimeout(() => {
this.initHeight() this.initHeight()
}, 300) }, 300)
},
getFirstShowData(){
getFirstShow((success, data) => {
if (success) {
setTimeout(() => {
// 匹配用户直接跳转小说
if (data.articleMsg != null) {
gotoBookContentPage(data.articleMsg.id);
}
}, 800);
}
})
}, },
getCategoryData() { getCategoryData() {
getCategorys((success, data) => { getCategorys((success, data) => {
...@@ -151,7 +117,9 @@ ...@@ -151,7 +117,9 @@
query.exec((res) => { query.exec((res) => {
let result = 0; let result = 0;
res.forEach(item => { res.forEach(item => {
result = result + item.height; if (item) {
result = result + item.height;
}
}) })
this.listHeight = this.windowHeight - result - (this.windowHeight * 0.1); this.listHeight = this.windowHeight - result - (this.windowHeight * 0.1);
}) })
......
<template>
<view style="padding-top: 50rpx;">
<profile-header :userInfo='userInfo'></profile-header>
<CategoryBar id='category' :range='categorys' :current='currentIndex' @change='changeCategory'
@ready='readyCategory'></CategoryBar>
<view :style="[listStyle]" v-if='showEmpty'>
<c-empty emptyTitle="暂无数据"></c-empty>
</view>
<view :style="[listStyle]" v-else>
<swiper :style="[listStyle]" :indicator-dots="false" :autoplay="false" :current="currentIndex"
@change="changeSwiper">
<swiper-item v-for='(item, index) in categorys' :key='index'>
<WarehouseList ref='bookList' :category='item' :height='listHeight'></WarehouseList>
</swiper-item>
</swiper>
</view>
<c-login></c-login>
</view>
</template>
<script>
import ProfileHeader from "./components/profile-headertemp.vue";
import {
watchUserInfoChange,
refreshUserInfo
} from "../../common/services/userServices.js"
import CategoryBar from "./components/category-bar.vue";
import WarehouseList from "./components/warehouse-list.vue";
import SystemInfoMixin from "../../common/mixins/system-info-mixin.js";
import Category from "./models/Category.js";
import {
getCategorys
} from "./services/index.js"
import {
isEmpty
} from "../../common/utils/util";
import {
readStorage,
saveStorage
} from '../../common/utils/storageUtil';
export default {
mixins: [SystemInfoMixin],
components: {
CategoryBar,
ProfileHeader,
WarehouseList
},
data() {
return {
userInfo: null,
listHeight: 0,
categorys: [],
currentIndex: 0
};
},
onLoad() {
this.getCategoryData();
watchUserInfoChange((info) => {
this.userInfo = info.userInfo
}, this);
},
onShow() {
this.refreshUserData();
},
computed: {
showEmpty: function() {
return isEmpty(this.categorys);
},
listStyle: function() {
return {
height: `${this.listHeight}px`
}
},
categroyChange: function() {
const {
categorys,
currentIndex
} = this;
return {
categorys,
currentIndex
}
}
},
watch: {
categroyChange: {
handler: function(n, o) {
this.$nextTick(() => {
let ref = this.$refs.bookList;
if (ref) {
ref[n.currentIndex].initRefresh();
}
})
},
deep: true
}
},
methods: {
readyCategory() {
setTimeout(() => {
this.initHeight()
}, 300)
},
getCategoryData() {
getCategorys((success, data) => {
if (success) {
let result = data ? data.map(item => {
return new Category(item)
}).sort((a, b) => {
return a.sort - b.sort
}) : [];
result.unshift(new Category({
name: "全部",
id: ""
}))
this.categorys = result;
}
})
},
initHeight() {
const query = uni.createSelectorQuery().in(this);
// query.select("#navi").boundingClientRect();
// query.select("#search").boundingClientRect();
query.select("#category").boundingClientRect();
query.exec((res) => {
let result = 0;
res.forEach(item => {
result = result + item.height;
})
this.listHeight = this.windowHeight - result;
})
},
changeCategory(e) {
this.changeCurrent(e.index);
},
changeSwiper(e) {
this.changeCurrent(e.detail.current);
},
changeCurrent(index) {
if (index != this.currentIndex) {
this.currentIndex = index;
}
},
refreshUserData() {
if (this.userInfo) {
refreshUserInfo();
}
}
}
}
</script>
<style lang="scss">
.name {
font-size: 34rpx;
font-weight: 700;
}
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<view class="read" id="read">
<view class="read-content" :class="'read-content'+index" :style="elStyle" v-for="(item,index) in list"
:key="index" @click="toClick">
{{item.content}}
</view>
<!-- <view class="read-content" :style="elStyle" @click="toNext">{{content}}</view>
<view class="read-content-next" :style="elStyle">{{contentNext}}</view> -->
<view class="top-info" v-if="setShow">
<view class="top-info-item">
<text text="上一章" block align="center" v-if="partInfo.previousPartNum != -1"
@tap.native.stop="toPrePart">上一章
</text>
</view>
<view class="top-info-item">
<!-- <u-button type="default" size="mini" plain shape="circle" text="目录" @tap.native.stop="toMenu">
</u-button> -->
<text text="目录" align="center" @tap.native.stop="toMenu">目录</text>
</view>
<view class="top-info-item">
<text text="下一章" align="center" v-if="partInfo.nextPartNum != -1" @tap.native.stop="toNextPart">下一章
</text>
</view>
</view>
<view class="bottom-info" v-if="setShow">
<view class="bottom-info-item">
<text text="设置" prefixIcon="setting" size="17" lineHeight="20" :iconStyle="{fontSize: '20px'}"
align="center" @tap.native.stop="toSet">设置</text>
</view>
<view class="bottom-info-item">
<text text="|" align="center" size="17" color="#dadada">|</text>
</view>
<view class="bottom-info-item">
<text text="返回书城" prefixIcon="home" size="17" lineHeight="20" align="center"
:iconStyle="{fontSize: '20px'}" @tap.native.stop="toHome">返回书城</text>
</view>
</view>
<view class="bottom-info font-style" v-if="setStyleShow">
<view class="item">
<view class="item-title">
字号
</view>
<view class="item-cont">
<view class="item-cont-item" @click="setFontSize(1)">
-
</view>
<view class="item-cont-item" @click="setFontSize(2)">
+
</view>
</view>
</view>
<view class="item">
<view class="item-title">
背景
</view>
<view class="item-cont">
<view class="item-cont-item" :class="curColor==item?'active':''" @click="setBgColor(item)"
v-for="(item,index) in colors" :key="index" :style="'background-color:'+item+';'">
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import datas from "./data.js"
export default {
data() {
return {
content: "22222",
contentPre: "11111",
contentNext: "3333",
list: [],
colors: [
"#F1FAFA",
"#e8ffe8",
"#e8e8ff",
"#8080c0",
],
curColor: "#F1FAFA",
setShow: false,
setStyleShow: false,
isStart: true,
isEnd: false,
width: 0,
height: 0,
start: 0,
end: 0,
length: 0,
heightOffset: 16,
styleObj: {
fontSize: 16,
lineHeight: 1
},
elStyle: "",
partInfo: {
previousPartNum: 1,
nextPartNum: 1
}
};
},
mounted() {
this.$nextTick(() => {
this.init()
})
},
methods: {
setFontSize(flag) {
//-
if (flag == 1) {
if (this.styleObj.fontSize < 10) {
return;
}
this.styleObj.fontSize -= 1;
} else { //+
if (this.styleObj.fontSize > 40) {
return;
}
this.styleObj.fontSize += 1;
}
this.init()
},
setBgColor(color) {
this.curColor = color;
this.setStyle()
},
toSet() {
console.log("设置")
this.setStyleShow = true;
this.setShow = false;
},
toPrePart() {
console.log("上一章节")
},
toNextPart() {
console.log("下一章节")
},
toHome() {
console.log("返回首页")
},
toMenu() {
// this.$refs.parts.open();
console.log("显示目录")
},
toClick(e) {
if (this.setStyleShow || this.setShow) {
this.setStyleShow = false;
this.setShow = false;
return;
}
const width = this.width;
const x = e.detail.x;
if (x < width / 3) {
this.toPre()
} else if (x > (width / 3) * 2) {
this.toNext()
} else {
this.setShow = !this.setShow;
}
},
toPre() {
if (this.isStart) {
uni.showToast({
title: "已经是第一页了",
icon: "none"
})
return;
}
this.start -= this.length;
this.setContent()
},
toNext() {
if (this.isEnd) {
uni.showToast({
title: "已经是最后一页了",
icon: "none"
})
return;
}
this.start += this.length;
this.setContent()
// console.log(this.start, this.list)
},
init() {
console.log(111111111, this.content)
const query = uni.createSelectorQuery().in(this);
const el = query.select("#read").boundingClientRect(data => {
console.log(11111, data)
const width = data.width - 20;
const height = data.height - 20;
this.width = width;
this.height = height;
let lineHeight = ((this.styleObj.fontSize) * this.styleObj.lineHeight) + this.heightOffset;
let lineNum = parseInt(height / lineHeight) - 1;
let fonts = parseInt(width / (this.styleObj.fontSize));
let allFonts = lineNum * fonts;
this.length = allFonts;
console.log("--->>>", allFonts, fonts, lineNum, height, lineHeight)
this.setStyle()
this.setContent()
}).exec();
},
setContent() {
this.list = []
let cont0 = "";
let cont1 = datas.substr(this.start, this.length);
let cont2 = datas.substr(this.start + this.length, this.length);
if (cont1.length < this.length) {
this.isEnd = true;
} else {
this.isEnd = false;
}
if (this.start != 0) {
this.isStart = false;
cont0 = datas.substr(this.start - this.length, this.length)
} else {
this.isStart = true;
}
this.list.push({
index: 0,
content: cont0
})
this.list.push({
index: 1,
content: cont1
})
this.list.push({
index: 2,
content: cont2
})
},
setStyle() {
let fontSize = this.styleObj.fontSize;
let lineHeight = (((this.styleObj.fontSize) * this.styleObj.lineHeight) + this.heightOffset);
this.elStyle = `font-size: ${fontSize}px;line-height: ${lineHeight}px;background-color:${this.curColor};`;
// console.log(1,this.elStyle)
}
},
}
</script>
<style lang="scss">
page {
width: 100%;
height: 100%;
}
</style>
<style lang="scss" scoped>
* {
box-sizing: border-box;
}
.read {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
box-sizing: border-box;
&-content {
padding: 20rpx;
width: 100%;
height: 100%;
box-sizing: border-box;
position: absolute;
background-color: #f5ebdc;
}
&-content0 {
z-index: 1;
}
&-content1 {
z-index: 20;
}
&-content2 {
z-index: 10;
}
}
.top-info {
position: fixed;
top: 0rpx;
left: 0rpx;
display: flex;
background-color: #fff;
height: 90rpx;
border-bottom: 1px solid #dadada;
width: 100%;
z-index: 999;
&-item {
padding: 10rpx 0rpx;
flex: 1;
text-align: center;
}
}
.bottom-info {
position: absolute;
box-sizing: border-box;
bottom: 0rpx;
left: 0rpx;
display: flex;
background-color: #fff;
height: 210rpx;
padding: 50rpx 30rpx;
border-top: 1px solid #dadada;
width: 100%;
z-index: 999;
&-item {
padding: 10rpx 0rpx;
flex: 1;
text-align: center;
}
}
.font-style {
height: 400rpx;
flex-direction: column;
}
.item {
display: flex;
padding: 20rpx;
height: 150rpx;
line-height: 110rpx;
&-title {
width: 140rpx;
}
&-cont {
width: calc(100% - 140rpx);
display: flex;
&-item {
flex: 1;
background-color: #d8ebf5;
height: 100rpx;
border-radius: 60rpx;
margin-right: 30rpx;
text-align: center;
font-size: 60rpx;
line-height: 90rpx;
color: #03a9f4;
}
.active {
border: 1px solid #03a9f4;
}
}
}
</style>
...@@ -80,7 +80,6 @@ export default { ...@@ -80,7 +80,6 @@ export default {
// navigateTo('user/login?redirect=' + encodeURIComponent(redirect)); // navigateTo('user/login?redirect=' + encodeURIComponent(redirect));
}, },
logout() { logout() {
uni.removeStorageSync('token');
}, },
post(options) { post(options) {
options = Object.assign({ options = Object.assign({
......
...@@ -179,7 +179,7 @@ ...@@ -179,7 +179,7 @@
onShareAppMessage() { onShareAppMessage() {
let result = { let result = {
title: this.bookData.title, title: this.bookData.title,
imageUrl: this.bookData.cover, imageUrl: this.bookData.cover,
path: '/pages/loading?shareId=' path: '/pages/loading?shareId='
} }
return result; return result;
...@@ -261,7 +261,7 @@ ...@@ -261,7 +261,7 @@
this.bookData = new BookDetail(data); this.bookData = new BookDetail(data);
// console.log('bookData=' + JSON.stringify(this.bookData)); // console.log('bookData=' + JSON.stringify(this.bookData));
} }
}, 1000) }, 100)
}) })
}, },
paySuccess() { paySuccess() {
......
<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
<template>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
<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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -90,7 +90,6 @@ ...@@ -90,7 +90,6 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
background: #fff;
font-size: 28rpx; font-size: 28rpx;
.item { .item {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment