Compare commits

...

No commits in common. "main" and "master" have entirely different histories.
main ... master

896 changed files with 118417 additions and 2 deletions

24
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,24 @@
{
// launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version" : "0.0",
"configurations" : [
{
"app-plus" : {
"launchtype" : "local"
},
"default" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"playground" : "custom",
"type" : "uni-app:app-ios"
},
{
"playground" : "custom",
"type" : "uni-app:app-android"
}
]
}

23
App.vue Normal file
View File

@ -0,0 +1,23 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
@import "@/uni_modules/uview-ui/index.scss";
/*每个页面公共css */
uni-page-body,
html,
body {
height: 100%;
}
</style>

View File

@ -1,2 +0,0 @@
# app_ancientSayings

View File

@ -0,0 +1,78 @@
<template>
<view class="_book_content">
<view class="book_box">
<view class="book_box_image">
<image class="is_image" :src="bookImage"></image>
</view>
<view class="book_box_title">
{{bookName}}
</view>
<view class="book_box_tips">
{{bookTips}}
</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookTips: {
type: String,
default: ''
},
bookName: {
type: String,
default: ''
},
bookImage: {
type: String,
default: ''
}
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
._book_content {
width: 100%;
.book_box {
width: 100%;
.book_box_image {
width: 100%;
height: 266rpx;
}
.book_box_title {
width: 100%;
font-size: 34rpx;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 600;
line-height: 1;
margin-top: 16rpx;
}
.book_box_tips {
font-size: 26rpx;
color: #999999;
line-height: 1;
margin-top: 16rpx;
}
}
}
</style>

View File

@ -0,0 +1,196 @@
<template>
<view class="commBookLeftRigth_content">
<view>
<view class="commBookLeftRigth_book_box">
<view class="commBookLeftRigth_content_left">
<image class="is_image" :src="bookImage"></image>
</view>
<view class="commBookLeftRigth_content_right">
<view class="_content_right_title">{{bookName}}</view>
<view class="_content_right_tips">{{bookTips}}</view>
<view class="_content_right_introduction">{{bookIntroduction}}</view>
</view>
</view>
<view class="_book_operate_all">
<view v-if="bookcase == 1" :class="['operate_all_add_bookshelf', 'active' ]">
已加入书架
</view>
<view v-else :class="['operate_all_add_bookshelf']" @tap="addBookshelf">
加入书架
</view>
<view class="operate_all_start_read" @tap="toNovelReading">
开始阅读
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookTips: {
type: String,
default: ''
},
bookName: {
type: String,
default: ''
},
bookImage: {
type: String,
default: ''
},
bookIntroduction: {
type: String,
default: ''
},
bookId: {
type: [Number, String],
default: ''
},
bookcase: {
type: [Number, String],
default: ''
},
},
data() {
return {
addBookshelfFlag: false
}
},
methods: {
addBookshelf() {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
const data = {
sid: this.bookId,
}
uni.$u.http.post('/addBookshelf', data, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
this.$emit('addBookshelf', this.bookId);
uni.showToast({
title: '加入成功',
icon: 'none'
})
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
toNovelReading() {
const bookId = this.bookId;
uni.navigateTo({
url: `/pages/novelReading/novelReading?sid=${bookId}`
})
}
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
}
.commBookLeftRigth_content {
width: 100%;
.commBookLeftRigth_book_box {
width: 100%;
display: flex;
.commBookLeftRigth_content_left {
width: 200rpx;
height: 266rpx;
flex: 0 0 auto;
border-radius: 8rpx;
overflow: hidden;
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
}
.commBookLeftRigth_content_right {
flex: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 10rpx 0 10rpx 20rpx;
overflow: hidden;
._content_right_title {
font-size: 34rpx;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._content_right_tips {
font-size: 30rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._content_right_introduction {
font-size: 30rpx;
color: #999999;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
}
}
._book_operate_all {
width: 100%;
display: flex;
justify-content: space-between;
margin-top: 26rpx;
.operate_all_add_bookshelf {
width: 296rpx;
height: 88rpx;
line-height: 88rpx;
background-color: #FFEDF0;
border-radius: 20rpx;
font-size: 30rpx;
color: #FF728F;
font-weight: 500;
text-align: center;
}
.operate_all_add_bookshelf.active {
background: #F1F1F1;
color: #666666;
}
.operate_all_start_read {
width: 358rpx;
height: 88rpx;
line-height: 88rpx;
background-color: #FF728F;
border-radius: 20rpx;
font-size: 30rpx;
color: #FFFFFF;
font-weight: 500;
text-align: center;
}
}
}
</style>

View File

@ -0,0 +1,99 @@
<template>
<view class="commBookLeftRigth_content">
<view class="commBookLeftRigth_content_left">
<image class="is_image" :src="bookImage"></image>
</view>
<view class="commBookLeftRigth_content_right">
<view class="_content_right_title">{{bookName}}</view>
<view class="_content_right_tips">{{bookTips}}</view>
<view class="_content_right_introduction">{{bookIntroduction}}</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookTips: {
type: String,
default: ''
},
bookName: {
type: String,
default: ''
},
bookImage: {
type: String,
default: ''
},
bookIntroduction: {
type: String,
default: ''
}
},
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
border-radius: 12rpx;
}
.commBookLeftRigth_content {
width: 100%;
display: flex;
.commBookLeftRigth_content_left {
width: 200rpx;
height: 266rpx;
flex: 0 0 auto;
border-radius: 12rpx;
}
.commBookLeftRigth_content_right {
flex: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 10rpx 0 10rpx 20rpx;
overflow: hidden;
._content_right_title {
font-size: 34rpx;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._content_right_tips {
font-size: 30rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._content_right_introduction {
font-size: 30rpx;
color: #999999;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
</style>

View File

@ -0,0 +1,28 @@
<template>
<view class="commFooter_content">
{{footerTips}}
</view>
</template>
<script>
export default {
name:'commFooter',
props :{
footerTips:{
type: String,
default:'到底啦,不要再划了~'
}
}
}
</script>
<style lang="scss">
.commFooter_content {
display: flex;
justify-content: center;
width: 100%;
font-size: 24rpx;
color: #999999;
line-height: 1;
}
</style>

View File

@ -0,0 +1,174 @@
<template>
<view class="commNavBar_content">
<uni-nav-bar :border="false" :statusBar="true" leftWidth="0" rightWidth="0" height="80rpx" :fixed="false"
backgroundColor="transparent">
<view class="nav_bar_box">
<view class="nav_bar_box_left">
<view class="_box_left_list">
<view class="_left_list_item" v-for="m in navBarList" :key="m.id" @tap="navBarClick"
:data-id="m.id">
<view :class="['_left_list_item_box', navBarActive == m.id ? 'active':'']">
<view :class="['_list_item_name', navBarActive==m.id ? 'active' :'']">{{m.name}}
</view>
<view class="_list_item_iamge" v-if="navBarActive == m.id">
<image class="is_image" src="../../static/images/nav-bar_Vector.png"></image>
</view>
</view>
</view>
</view>
</view>
<view class="nav_bar_box_right" @tap="toBooksSearchList">
<view class="_box_right_search" >
<view class="_search_iamge">
<image class="is_image" src="/static/images/nav_bar_search.png"></image>
</view>
<view class="_search_tips">
搜索小说
</view>
</view>
</view>
</view>
</uni-nav-bar>
<view class="commNavBar_bag" />
</view>
</template>
<script>
export default {
name: 'commNavBar',
props: {
navBarList: {
type: Array,
default: []
},
navBarActive: {
type: String,
default: ''
}
},
data() {
return {}
},
methods: {
navBarClick(event) {
this.$emit('navBarClick', event)
},
toBooksSearchList() {
uni.navigateTo({
url: '/pages/booksSearchList/booksSearchList'
})
}
},
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
::v-deep.uni-navbar {
position: relative;
z-index: 2;
padding-bottom: 32rpx;
// .uni-navbar__content {
// padding-bottom: 32rpx;
// }
}
.commNavBar_bag {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 400rpx;
background: linear-gradient(to bottom, #FFC7D3 0%, #FFEBEE 50%, #fff 100%);
}
.commNavBar_content {
width: 100%;
.nav_bar_box {
width: 100%;
display: flex;
align-items: center;
height: 100%;
.nav_bar_box_left {
// height: ;
._box_left_list {
display: flex;
align-items: center;
._left_list_item {
// padding-right: 20;
display: flex;
align-items: center;
width: 120rpx;
._left_list_item_box {
._list_item_name {
font-size: 30rpx;
color: #666666;
line-height: 1;
}
._list_item_name.active {
font-size: 38rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
._list_item_iamge {
width: 30rpx;
height: 8rpx;
}
}
._left_list_item_box.active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
height: 54rpx;
}
}
}
}
.nav_bar_box_right {
display: flex;
align-items: center;
flex: 1;
height: 100%;
background-color: #fff;
border-radius: 40rpx;
box-sizing: border-box;
padding: 38rpx;
._box_right_search {
display: flex;
align-items: center;
._search_iamge {
width: 30rpx;
height: 30rpx;
}
._search_tips {
font-size: 26rpx;
color: #BBBBBB;
margin-left: 20rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<view class="commVipInfo_content">
<view class="vip_info_box">
<view class="vip_info_box_left">
<view class="vip_info_sculpture">
<image class="is_image" src="/static/images/myInfo/default_sculpture.png" />
</view>
<view class="vip_whether_tips_box">
<view class="vip_whether_tips">
<view class="vip_whether_tips_test">
尊贵的VIP会员
</view>
<view class="vip_whether_tips_icon">
<image src="/static/images/myInfo/VIP_whether.png" class="is_image" />
</view>
</view>
<view class="vip_time_tips">尊享无限时书城免费畅读</view>
</view>
</view>
<view class="vip_info_box_right">
<view class="vip_info_renew">续费</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'commVipInfo',
data() {
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
}
.commVipInfo_content {
width: 100%;
.vip_info_box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 142rpx;
padding: 0 40rpx;
background: url('/static/images/member_vip_bg.png') no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
.vip_info_box_left {
display: flex;
align-items: center;
.vip_info_sculpture {
width: 68rpx;
height: 68rpx;
margin-right: 16rpx;
}
.vip_whether_tips_box {
display: flex;
flex-direction: column;
justify-center: center;
.vip_whether_tips {
display: flex;
align-items: center;
.vip_whether_tips_test {
font-size: 36rpx;
font-weight: 700;
color: #fff;
line-height: 1.2;
}
.vip_whether_tips_icon {
width: 36rpx;
height: 36rpx;
margin-left: 8rpx;
}
}
.vip_time_tips {
font-size: 24rpx;
color: #fff;
line-height: 1;
margin-top: 16rpx;
}
}
}
.vip_info_box_right {
.vip_info_renew {
display: flex;
justify-content: center;
align-items: center;
padding: 0 30rpx;
border-radius: 34rpx;
height: 68rpx;
background-color: rgba(255, 255, 255, 0.65);
font-size: 28rpx;
color: #E0385B;
line-height: 1;
}
}
}
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<view class="_book_content">
<view class="book_box">
<view class="book_box_image">
<image class="is_image" :src="bookImage"></image>
</view>
<view class="book_box_title">
{{bookName}}
</view>
<view class="book_box_tips">
{{bookTips}}
</view>
</view>
</view>
</template>
<script>
export default {
name: 'originalBoolItem',
props: {
bookTips: {
type: String,
default: ''
},
bookName: {
type: String,
default: ''
},
bookImage: {
type: String,
default: ''
}
},
data() {
return {
}
},
}
</script>
<style lang="scss" scoped>
.is_image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
._book_content {
width: 100%;
.book_box {
width: 100%;
.book_box_image {
width: 100%;
height: 204rpx;
}
.book_box_title {
width: 100%;
font-size: 32rpx;
color: #1A1A1A;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-weight: 600;
// line-height: 1;
margin-top: 16rpx;
}
.book_box_tips {
font-size: 26rpx;
color: #999999;
line-height: 1;
margin-top: 16rpx;
}
}
}
</style>

12
config/index.js Normal file
View File

@ -0,0 +1,12 @@
// const baseUrl = 'https://console-mock.apipost.cn';
// export default baseUrl;
const config = {
baseUrl: `https://qjnovelweb.qinjiuxiaoshuo.com`, /*, 根域名 */
header: {
'Content-Type': 'application/x-www-form-urlencoded;'
}
}
export default config

20
index.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

15
libs/config/config.js Normal file
View File

@ -0,0 +1,15 @@
// 此版本发布于2022-04-19
let version = '1.8.6';
export default {
v: version,
version: version,
// 主题名称
type: [
'primary',
'success',
'info',
'error',
'warning'
]
}

20
libs/config/zIndex.js Normal file
View File

@ -0,0 +1,20 @@
// uniapp在H5中各API的z-index值如下
/**
* actionsheet: 999
* modal: 999
* navigate: 998
* tabbar: 998
* toast: 999
*/
export default {
toast: 10090,
noNetwork: 10080,
// popup包含popupactionsheetkeyboardpicker的值
popup: 10075,
mask: 10070,
navbar: 980,
topTips: 975,
sticky: 970,
indexListSticky: 965,
}

155
libs/css/color.scss Normal file
View File

@ -0,0 +1,155 @@
.u-type-primary-light {
color: $u-type-primary-light;
}
.u-type-warning-light {
color: $u-type-warning-light;
}
.u-type-success-light {
color: $u-type-success-light;
}
.u-type-error-light {
color: $u-type-error-light;
}
.u-type-info-light {
color: $u-type-info-light;
}
.u-type-primary-light-bg {
background-color: $u-type-primary-light;
}
.u-type-warning-light-bg {
background-color: $u-type-warning-light;
}
.u-type-success-light-bg {
background-color: $u-type-success-light;
}
.u-type-error-light-bg {
background-color: $u-type-error-light;
}
.u-type-info-light-bg {
background-color: $u-type-info-light;
}
.u-type-primary-dark {
color: $u-type-primary-dark;
}
.u-type-warning-dark {
color: $u-type-warning-dark;
}
.u-type-success-dark {
color: $u-type-success-dark;
}
.u-type-error-dark {
color: $u-type-error-dark;
}
.u-type-info-dark {
color: $u-type-info-dark;
}
.u-type-primary-dark-bg {
background-color: $u-type-primary-dark;
}
.u-type-warning-dark-bg {
background-color: $u-type-warning-dark;
}
.u-type-success-dark-bg {
background-color: $u-type-success-dark;
}
.u-type-error-dark-bg {
background-color: $u-type-error-dark;
}
.u-type-info-dark-bg {
background-color: $u-type-info-dark;
}
.u-type-primary-disabled {
color: $u-type-primary-disabled;
}
.u-type-warning-disabled {
color: $u-type-warning-disabled;
}
.u-type-success-disabled {
color: $u-type-success-disabled;
}
.u-type-error-disabled {
color: $u-type-error-disabled;
}
.u-type-info-disabled {
color: $u-type-info-disabled;
}
.u-type-primary {
color: $u-type-primary;
}
.u-type-warning {
color: $u-type-warning;
}
.u-type-success {
color: $u-type-success;
}
.u-type-error {
color: $u-type-error;
}
.u-type-info {
color: $u-type-info;
}
.u-type-primary-bg {
background-color: $u-type-primary;
}
.u-type-warning-bg {
background-color: $u-type-warning;
}
.u-type-success-bg {
background-color: $u-type-success;
}
.u-type-error-bg {
background-color: $u-type-error;
}
.u-type-info-bg {
background-color: $u-type-info;
}
.u-main-color {
color: $u-main-color;
}
.u-content-color {
color: $u-content-color;
}
.u-tips-color {
color: $u-tips-color;
}
.u-light-color {
color: $u-light-color;
}

176
libs/css/common.scss Normal file
View File

@ -0,0 +1,176 @@
.u-relative,
.u-rela {
position: relative;
}
.u-absolute,
.u-abso {
position: absolute;
}
// nvue不能用标签命名样式不能放在微信组件中否则微信开发工具会报警告无法使用标签名当做选择器
/* #ifndef APP-NVUE */
image {
display: inline-block;
}
// 在weex也即nvue中所有元素默认为border-box
view,
text {
box-sizing: border-box;
}
/* #endif */
.u-font-xs {
font-size: 22rpx;
}
.u-font-sm {
font-size: 26rpx;
}
.u-font-md {
font-size: 28rpx;
}
.u-font-lg {
font-size: 30rpx;
}
.u-font-xl {
font-size: 34rpx;
}
.u-flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
.u-flex-wrap {
flex-wrap: wrap;
}
.u-flex-nowrap {
flex-wrap: nowrap;
}
.u-col-center {
align-items: center;
}
.u-col-top {
align-items: flex-start;
}
.u-col-bottom {
align-items: flex-end;
}
.u-row-center {
justify-content: center;
}
.u-row-left {
justify-content: flex-start;
}
.u-row-right {
justify-content: flex-end;
}
.u-row-between {
justify-content: space-between;
}
.u-row-around {
justify-content: space-around;
}
.u-text-left {
text-align: left;
}
.u-text-center {
text-align: center;
}
.u-text-right {
text-align: right;
}
.u-flex-col {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
// 定义flex等分
@for $i from 0 through 12 {
.u-flex-#{$i} {
flex: $i;
}
}
// 定义字体(px)单位小于20都为px单位字体
@for $i from 9 to 20 {
.u-font-#{$i} {
font-size: $i + px;
}
}
// 定义字体(rpx)单位大于或等于20的都为rpx单位字体
@for $i from 20 through 40 {
.u-font-#{$i} {
font-size: $i + rpx;
}
}
// 定义内外边距历遍1-80
@for $i from 0 through 80 {
// 只要双数和能被5除尽的数
@if $i % 2 == 0 or $i % 5 == 0 {
// 得出u-margin-30或者u-m-30
.u-margin-#{$i}, .u-m-#{$i} {
margin: $i + rpx!important;
}
// 得出u-padding-30或者u-p-30
.u-padding-#{$i}, .u-p-#{$i} {
padding: $i + rpx!important;
}
@each $short, $long in l left, t top, r right, b bottom {
// 缩写版结果如 u-m-l-30
// 定义外边距
.u-m-#{$short}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-p-#{$short}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
// 完整版结果如u-margin-left-30
// 定义外边距
.u-margin-#{$long}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-padding-#{$long}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
}
}
}
// 重置nvue的默认关于flex的样式
.u-reset-nvue {
flex-direction: row;
align-items: center;
}

View File

@ -0,0 +1,7 @@
// 定义混入指令用于在非nvue环境下的flex定义因为nvue没有display属性会报错
@mixin vue-flex($direction: row) {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: $direction;
/* #endif */
}

8
libs/css/style.h5.scss Normal file
View File

@ -0,0 +1,8 @@
/* H5的时候隐藏滚动条 */
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}

72
libs/css/style.mp.scss Normal file
View File

@ -0,0 +1,72 @@
/* start--微信小程序编译后页面有组件名的元素,特别处理--start */
/* #ifdef MP-WEIXIN || MP-QQ */
u-td, u-th {
flex: 1;
align-self: stretch;
}
.u-td {
height: 100%;
}
u-icon {
display: inline-flex;
align-items: center;
}
// 各家小程序宫格组件外层设置为100%避免受到父元素display: flex;的影响
u-grid {
width: 100%;
flex: 0 0 100%;
}
// 避免小程序线条组件因为父组件display: flex;而失效
u-line {
flex: 1;
}
u-switch {
display: inline-flex;
align-items: center;
}
u-dropdown {
flex: 1;
}
/* #endif */
/* end-微信小程序编译后页面有组件名的元素,特别处理--end */
/* #ifdef MP-QQ || MP-TOUTIAO */
// 需要做这一切额外的兼容都是因为TX的无能
u-icon {
line-height: 0;
}
/* #endif */
/* start--头条小程序编译后页面有组件名的元素,特别处理--start */
// 由于头条小程序不支持直接组件名形式写样式目前只能在写组件的时候给组件加上对应的类名
/* #ifdef MP-TOUTIAO */
.u-td, .u-th, .u-tr {
flex: 1;
align-self: stretch;
}
.u-row, .u-col {
flex: 1;
align-self: stretch;
}
// 避免小程序线条组件因为父组件display: flex;而失效
.u-line {
flex: 1;
}
.u-dropdown {
flex: 1;
}
/* #endif */
/* end-头条小程序编译后页面有组件名的元素,特别处理--end */

3
libs/css/style.nvue.scss Normal file
View File

@ -0,0 +1,3 @@
.nvue {
font-size: 24rpx;
}

175
libs/css/style.vue.scss Normal file
View File

@ -0,0 +1,175 @@
page {
color: $u-main-color;
font-size: 28rpx;
}
/* start--去除webkit的默认样式--start */
.u-fix-ios-appearance {
-webkit-appearance:none;
}
/* end--去除webkit的默认样式--end */
/* start--icon图标外层套一个view让其达到更好的垂直居中的效果--start */
.u-icon-wrap {
display: flex;
align-items: center;
}
/* end-icon图标外层套一个view让其达到更好的垂直居中的效果--end */
/* start--iPhoneX底部安全区定义--start */
.safe-area-inset-bottom {
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
/* end-iPhoneX底部安全区定义--end */
/* start--各种hover点击反馈相关的类名-start */
.u-hover-class {
// background-color: #f7f8f9!important;
opacity: 0.6;
}
.u-cell-hover {
background-color: #f7f8f9!important;
}
/* end--各种hover点击反馈相关的类名--end */
/* start--文本行数限制--start */
.u-line-1 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.u-line-2 {
-webkit-line-clamp: 2;
}
.u-line-3 {
-webkit-line-clamp: 3;
}
.u-line-4 {
-webkit-line-clamp: 4;
}
.u-line-5 {
-webkit-line-clamp: 5;
}
.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box; // 弹性伸缩盒
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
}
/* end--文本行数限制--end */
/* start--Retina 屏幕下的 1px 边框--start */
.u-border,
.u-border-bottom,
.u-border-left,
.u-border-right,
.u-border-top,
.u-border-top-bottom {
position: relative
}
.u-border-bottom:after,
.u-border-left:after,
.u-border-right:after,
.u-border-top-bottom:after,
.u-border-top:after,
.u-border:after {
/* #ifndef APP-NVUE */
content: ' ';
/* #endif */
position: absolute;
left: 0;
top: 0;
pointer-events: none;
box-sizing: border-box;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
// 多加0.1%能解决有时候边框缺失的问题
width: 199.8%;
height: 199.7%;
transform: scale(0.5, 0.5);
border: 0 solid $u-border-color;
z-index: 2;
}
.u-border-top:after {
border-top-width: 1px
}
.u-border-left:after {
border-left-width: 1px
}
.u-border-right:after {
border-right-width: 1px
}
.u-border-bottom:after {
border-bottom-width: 1px
}
.u-border-top-bottom:after {
border-width: 1px 0
}
.u-border:after {
border-width: 1px
}
/* end--Retina 屏幕下的 1px 边框--end */
/* start--clearfix--start */
.u-clearfix:after,
.clearfix:after {
/* #ifndef APP-NVUE */
content: '';
/* #endif */
display: table;
clear: both
}
/* end--clearfix--end */
/* start--高斯模糊tabbar底部处理--start */
.u-blur-effect-inset {
width: 750rpx;
height: var(--window-bottom);
background-color: #FFFFFF;
}
/* end--高斯模糊tabbar底部处理--end */
/* start--提升H5端uni.toast()的层级避免被uView的modal等遮盖--start */
/* #ifdef H5 */
uni-toast {
z-index: 10090;
}
uni-toast .uni-toast {
z-index: 10090;
}
/* #endif */
/* end--提升H5端uni.toast()的层级避免被uView的modal等遮盖--end */
/* start--去除button的所有默认样式--start */
.u-reset-button {
padding: 0;
font-size: inherit;
line-height: inherit;
background-color: transparent;
color: inherit;
}
.u-reset-button::after {
border: none;
}
/* end--去除button的所有默认样式--end */

18
libs/function/$parent.js Normal file
View File

@ -0,0 +1,18 @@
// 获取父组件的参数因为支付宝小程序不支持provide/inject的写法
// this.$parent在非H5中可以准确获取到父组件但是在H5中需要多次this.$parent.$parent.xxx
// 这里默认值等于undefined有它的含义因为最顶层元素(组件)的$parent就是undefined意味着不传name
// 值(默认为undefined),就是查找最顶层的$parent
export default function $parent(name = undefined) {
let parent = this.$parent;
// 通过while历遍这里主要是为了H5需要多层解析的问题
while (parent) {
// 父组件
if (parent.$options && parent.$options.name !== name) {
// 如果组件的name不相等继续上一级寻找
parent = parent.$parent;
} else {
return parent;
}
}
return false;
}

8
libs/function/addUnit.js Normal file
View File

@ -0,0 +1,8 @@
import validation from './test.js';
// 添加单位如果有rpx%px等单位结尾或者值为auto直接返回否则加上rpx单位结尾
export default function addUnit(value = 'auto', unit = 'rpx') {
value = String(value);
// 用uView内置验证规则中的number判断是否为数值
return validation.number(value) ? `${value}${unit}` : value;
}

5
libs/function/bem.js Normal file
View File

@ -0,0 +1,5 @@
function bem(name, conf) {
}
module.exports.bem = bem;

37
libs/function/color.js Normal file
View File

@ -0,0 +1,37 @@
// 为了让用户能够自定义主题会逐步弃用此文件各颜色通过css提供
// 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20)
let color = {
primary: "#2979ff",
primaryDark: "#2b85e4",
primaryDisabled: "#a0cfff",
primaryLight: "#ecf5ff",
bgColor: "#f3f4f6",
info: "#909399",
infoDark: "#82848a",
infoDisabled: "#c8c9cc",
infoLight: "#f4f4f5",
warning: "#ff9900",
warningDark: "#f29100",
warningDisabled: "#fcbd71",
warningLight: "#fdf6ec",
error: "#fa3534",
errorDark: "#dd6161",
errorDisabled: "#fab6b6",
errorLight: "#fef0f0",
success: "#19be6b",
successDark: "#18b566",
successDisabled: "#71d5a1",
successLight: "#dbf1e1",
mainColor: "#303133",
contentColor: "#606266",
tipsColor: "#909399",
lightColor: "#c0c4cc",
borderColor: "#e4e7ed"
}
export default color;

View File

@ -0,0 +1,134 @@
/**
* 求两个颜色之间的渐变值
* @param {string} startColor 开始的颜色
* @param {string} endColor 结束的颜色
* @param {number} step 颜色等分的份额
* */
function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式
let startR = startRGB[0];
let startG = startRGB[1];
let startB = startRGB[2];
let endRGB = hexToRgb(endColor, false);
let endR = endRGB[0];
let endG = endRGB[1];
let endB = endRGB[2];
let sR = (endR - startR) / step; //总差值
let sG = (endG - startG) / step;
let sB = (endB - startB) / step;
let colorArr = [];
for (let i = 0; i < step; i++) {
//计算每一步的hex值
let hex = rgbToHex('rgb(' + Math.round((sR * i + startR)) + ',' + Math.round((sG * i + startG)) + ',' + Math.round((sB *
i + startB)) + ')');
colorArr.push(hex);
}
return colorArr;
}
// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
function hexToRgb(sColor, str = true) {
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
sColor = sColor.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
let sColorNew = "#";
for (let i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
//处理六位的颜色值
let sColorChange = [];
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
if(!str) {
return sColorChange;
} else {
return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`;
}
} else if (/^(rgb|RGB)/.test(sColor)) {
let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",")
return arr.map(val => Number(val));
} else {
return sColor;
}
};
// 将rgb表示方式转换为hex表示方式
function rgbToHex(rgb) {
let _this = rgb;
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
if (/^(rgb|RGB)/.test(_this)) {
let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
let strHex = "#";
for (let i = 0; i < aColor.length; i++) {
let hex = Number(aColor[i]).toString(16);
hex = String(hex).length == 1 ? 0 + '' + hex : hex; // 保证每个rgb的值为2位
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
if (strHex.length !== 7) {
strHex = _this;
}
return strHex;
} else if (reg.test(_this)) {
let aNum = _this.replace(/#/, "").split("");
if (aNum.length === 6) {
return _this;
} else if (aNum.length === 3) {
let numHex = "#";
for (let i = 0; i < aNum.length; i += 1) {
numHex += (aNum[i] + aNum[i]);
}
return numHex;
}
} else {
return _this;
}
}
/**
* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba2552552550.5字符串
* sHex为传入的十六进制的色值
* alpha为rgba的透明度
*/
function colorToRgba(color, alpha = 0.3) {
color = rgbToHex(color)
// 十六进制颜色值的正则表达式
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
/* 16进制颜色转为RGB格式 */
let sColor = color.toLowerCase()
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
var sColorNew = '#'
for (let i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
}
sColor = sColorNew
}
// 处理六位的颜色值
var sColorChange = []
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
}
// return sColorChange.join(',')
return 'rgba(' + sColorChange.join(',') + ',' + alpha + ')'
}
else {
return sColor
}
}
export default {
colorGradient,
hexToRgb,
rgbToHex,
colorToRgba
}

29
libs/function/debounce.js Normal file
View File

@ -0,0 +1,29 @@
let timeout = null;
/**
* 防抖原理一定时间内只有最后一次操作再过wait毫秒后才执行函数
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
function debounce(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout);
// 立即执行,此类情况一般用不到
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function() {
timeout = null;
}, wait);
if (callNow) typeof func === 'function' && func();
} else {
// 设置定时器当最后一次操作后timeout不会再被清除所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(function() {
typeof func === 'function' && func();
}, wait);
}
}
export default debounce

View File

@ -0,0 +1,23 @@
// 判断arr是否为一个数组返回一个bool值
function isArray (arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
// 深度克隆
function deepClone (obj) {
// 对常见的“非”值,直接返回原来值
if([null, undefined, NaN, false].includes(obj)) return obj;
if(typeof obj !== "object" && typeof obj !== 'function') {
//原始类型直接返回
return obj;
}
var o = isArray(obj) ? [] : {};
for(let i in obj) {
if(obj.hasOwnProperty(i)){
o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
}
}
return o;
}
export default deepClone;

View File

@ -0,0 +1,30 @@
import deepClone from "./deepClone";
// JS对象深度合并
function deepMerge(target = {}, source = {}) {
target = deepClone(target);
if (typeof target !== 'object' || typeof source !== 'object') return false;
for (var prop in source) {
if (!source.hasOwnProperty(prop)) continue;
if (prop in target) {
if (typeof target[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (typeof source[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (target[prop].concat && source[prop].concat) {
target[prop] = target[prop].concat(source[prop]);
} else {
target[prop] = deepMerge(target[prop], source[prop]);
}
}
}
} else {
target[prop] = source[prop];
}
}
return target;
}
export default deepMerge;

View File

@ -0,0 +1,47 @@
// 获取父组件的参数因为支付宝小程序不支持provide/inject的写法
// this.$parent在非H5中可以准确获取到父组件但是在H5中需要多次this.$parent.$parent.xxx
export default function getParent(name, keys) {
let parent = this.$parent;
// 通过while历遍这里主要是为了H5需要多层解析的问题
while (parent) {
// 父组件
if (parent.$options.name !== name) {
// 如果组件的name不相等继续上一级寻找
parent = parent.$parent;
} else {
let data = {};
// 判断keys是否数组如果传过来的是一个数组那么直接使用数组元素值当做键值去父组件寻找
if(Array.isArray(keys)) {
keys.map(val => {
data[val] = parent[val] ? parent[val] : '';
})
} else {
// 历遍传过来的对象参数
for(let i in keys) {
// 如果子组件有此值则用,无此值则用父组件的值
// 判断是否空数组,如果是,则用父组件的值,否则用子组件的值
if(Array.isArray(keys[i])) {
if(keys[i].length) {
data[i] = keys[i];
} else {
data[i] = parent[i];
}
} else if(keys[i].constructor === Object) {
// 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值
if(Object.keys(keys[i]).length) {
data[i] = keys[i];
} else {
data[i] = parent[i];
}
} else {
// 只要子组件有传值即使是false值也是“传值”了也需要覆盖父组件的同名参数
data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i];
}
}
}
return data;
}
}
return {};
}

41
libs/function/guid.js Normal file
View File

@ -0,0 +1,41 @@
/**
* 本算法来源于简书开源代码详见https://www.jianshu.com/p/fdbf293d0a85
* 全局唯一标识符uuidGlobally Unique Identifier,也称作 uuid(Universally Unique IDentifier)
* 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题
* 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱
* v-for的时候,推荐使用后端返回的id而不是循环的index
* @param {Number} len uuid的长度
* @param {Boolean} firstU 将返回的首字母置为"u"
* @param {Number} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
*/
function guid(len = 32, firstU = true, radix = null) {
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
let uuid = [];
radix = radix || chars.length;
if (len) {
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
let r;
// rfc4122标准要求返回的uuid中,某些位为固定的字符
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guid不能用作id或者class
if (firstU) {
uuid.shift();
return 'u' + uuid.join('');
} else {
return uuid.join('');
}
}
export default guid;

385
libs/function/md5.js Normal file
View File

@ -0,0 +1,385 @@
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
function hex_hmac_md5(k, d)
{ return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function b64_hmac_md5(k, d)
{ return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function any_hmac_md5(k, d, e)
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s)
{
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data)
{
var bkey = rstr2binl(key);
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
function rstr2hex(input)
{
try { hexcase } catch(e) { hexcase=0; }
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var output = "";
var x;
for(var i = 0; i < input.length; i++)
{
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F)
+ hex_tab.charAt( x & 0x0F);
}
return output;
}
/*
* Convert a raw string to a base-64 string
*/
function rstr2b64(input)
{
try { b64pad } catch(e) { b64pad=''; }
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var output = "";
var len = input.length;
for(var i = 0; i < len; i += 3)
{
var triplet = (input.charCodeAt(i) << 16)
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
return output;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
function rstr2any(input, encoding)
{
var divisor = encoding.length;
var i, j, q, x, quotient;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var dividend = Array(Math.ceil(input.length / 2));
for(i = 0; i < dividend.length; i++)
{
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. All remainders are stored for later
* use.
*/
var full_length = Math.ceil(input.length * 8 /
(Math.log(encoding.length) / Math.log(2)));
var remainders = Array(full_length);
for(j = 0; j < full_length; j++)
{
quotient = Array();
x = 0;
for(i = 0; i < dividend.length; i++)
{
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if(quotient.length > 0 || q > 0)
quotient[quotient.length] = q;
}
remainders[j] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
var output = "";
for(i = remainders.length - 1; i >= 0; i--)
output += encoding.charAt(remainders[i]);
return output;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
function str2rstr_utf8(input)
{
var output = "";
var i = -1;
var x, y;
while(++i < input.length)
{
/* Decode utf-16 surrogate pairs */
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
{
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
/* Encode output as utf-8 */
if(x <= 0x7F)
output += String.fromCharCode(x);
else if(x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if(x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if(x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
}
/*
* Encode a string as utf-16
*/
function str2rstr_utf16le(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF);
return output;
}
function str2rstr_utf16be(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
input.charCodeAt(i) & 0xFF);
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input)
{
var output = Array(input.length >> 2);
for(var i = 0; i < output.length; i++)
output[i] = 0;
for(var i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
return output;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input)
{
var output = "";
for(var i = 0; i < input.length * 32; i += 8)
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
return output;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
module.exports = {
md5 : function(str){
return hex_md5(str);
}
}

View File

@ -0,0 +1,58 @@
/**
* 对象转url参数
* @param {*} data,对象
* @param {*} isPrefix,是否自动加上"?"
*/
function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
let prefix = isPrefix ? '?' : ''
let _result = []
if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
for (let key in data) {
let value = data[key]
// 去掉为空的参数
if (['', undefined, null].indexOf(value) >= 0) {
continue;
}
// 如果值为数组,另行处理
if (value.constructor === Array) {
// e.g. {ids: [1, 2, 3]}
switch (arrayFormat) {
case 'indices':
// 结果: ids[0]=1&ids[1]=2&ids[2]=3
for (let i = 0; i < value.length; i++) {
_result.push(key + '[' + i + ']=' + value[i])
}
break;
case 'brackets':
// 结果: ids[]=1&ids[]=2&ids[]=3
value.forEach(_value => {
_result.push(key + '[]=' + _value)
})
break;
case 'repeat':
// 结果: ids=1&ids=2&ids=3
value.forEach(_value => {
_result.push(key + '=' + _value)
})
break;
case 'comma':
// 结果: ids=1,2,3
let commaStr = "";
value.forEach(_value => {
commaStr += (commaStr ? "," : "") + _value;
})
_result.push(key + '=' + commaStr)
break;
default:
value.forEach(_value => {
_result.push(key + '[]=' + _value)
})
}
} else {
_result.push(key + '=' + value)
}
}
return _result.length ? prefix + _result.join('&') : ''
}
export default queryParams;

10
libs/function/random.js Normal file
View File

@ -0,0 +1,10 @@
function random(min, max) {
if (min >= 0 && max > 0 && max >= min) {
let gab = max - min + 1;
return Math.floor(Math.random() * gab + min);
} else {
return 0;
}
}
export default random;

View File

@ -0,0 +1,7 @@
// 打乱数组
function randomArray(array = []) {
// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
return array.sort(() => Math.random() - 0.5);
}
export default randomArray

122
libs/function/route.js Normal file
View File

@ -0,0 +1,122 @@
/**
* 路由跳转方法该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
* 并且带有路由拦截功能
*/
class Router {
constructor() {
// 原始属性定义
this.config = {
type: 'navigateTo',
url: '',
delta: 1, // navigateBack页面后退时,回退的层数
params: {}, // 传递的参数
animationType: 'pop-in', // 窗口动画,只在APP有效
animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
intercept: false, // 是否需要拦截
}
// 因为route方法是需要对外赋值给另外的对象使用同时route内部有使用this会导致route失去上下文
// 这里在构造函数中进行this绑定
this.route = this.route.bind(this)
}
// 判断url前面是否有"/",如果没有则加上,否则无法跳转
addRootPath(url) {
return url[0] === '/' ? url : `/${url}`
}
// 整合路由参数
mixinParam(url, params) {
url = url && this.addRootPath(url)
// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
// 如果有url中有get参数转换后无需带上"?"
let query = ''
if (/.*\/.*\?.*=.*/.test(url)) {
// object对象转为get类型的参数
query = uni.$u.queryParams(params, false);
// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
return url += "&" + query
} else {
// 直接拼接参数因为此处url中没有后面的query参数也就没有"?/&"之类的符号
query = uni.$u.queryParams(params);
return url += query
}
}
// 对外的方法名称
async route(options = {}, params = {}) {
// 合并用户的配置和内部的默认配置
let mergeConfig = {}
if (typeof options === 'string') {
// 如果options为字符串则为route(url, params)的形式
mergeConfig.url = this.mixinParam(options, params)
mergeConfig.type = 'navigateTo'
} else {
mergeConfig = uni.$u.deepClone(options, this.config)
// 否则正常使用mergeConfig中的url和params进行拼接
mergeConfig.url = this.mixinParam(options.url, options.params)
}
if(params.intercept) {
this.config.intercept = params.intercept
}
// params参数也带给拦截器
mergeConfig.params = params
// 合并内外部参数
mergeConfig = uni.$u.deepMerge(this.config, mergeConfig)
// 判断用户是否定义了拦截器
if (typeof uni.$u.routeIntercept === 'function') {
// 定一个promise根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
const isNext = await new Promise((resolve, reject) => {
uni.$u.routeIntercept(mergeConfig, resolve)
})
// 如果isNext为true则执行路由跳转
isNext && this.openPage(mergeConfig)
} else {
this.openPage(mergeConfig)
}
}
// 执行路由跳转
openPage(config) {
// 解构参数
const {
url,
type,
delta,
animationType,
animationDuration
} = config
if (config.type == 'navigateTo' || config.type == 'to') {
uni.navigateTo({
url,
animationType,
animationDuration
});
}
if (config.type == 'redirectTo' || config.type == 'redirect') {
uni.redirectTo({
url
});
}
if (config.type == 'switchTab' || config.type == 'tab') {
uni.switchTab({
url
});
}
if (config.type == 'reLaunch' || config.type == 'launch') {
uni.reLaunch({
url
});
}
if (config.type == 'navigateBack' || config.type == 'back') {
uni.navigateBack({
delta
});
}
}
}
export default (new Router()).route

9
libs/function/sys.js Normal file
View File

@ -0,0 +1,9 @@
export function os() {
return uni.getSystemInfoSync().platform;
};
export function sys() {
return uni.getSystemInfoSync();
}

232
libs/function/test.js Normal file
View File

@ -0,0 +1,232 @@
/**
* 验证电子邮箱格式
*/
function email(value) {
return /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/.test(value);
}
/**
* 验证手机格式
*/
function mobile(value) {
return /^1[3-9]\d{9}$/.test(value)
}
/**
* 验证URL格式
*/
function url(value) {
return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
}
/**
* 验证日期格式
*/
function date(value) {
return !/Invalid|NaN/.test(new Date(value).toString())
}
/**
* 验证ISO类型的日期格式
*/
function dateISO(value) {
return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
}
/**
* 验证十进制数字
*/
function number(value) {
return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
}
/**
* 验证整数
*/
function digits(value) {
return /^\d+$/.test(value)
}
/**
* 验证身份证号码
*/
function idCard(value) {
return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value)
}
/**
* 是否车牌号
*/
function carNo(value) {
// 新能源车牌
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
// 旧车牌
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
if (value.length === 7) {
return creg.test(value);
} else if (value.length === 8) {
return xreg.test(value);
} else {
return false;
}
}
/**
* 金额,只允许2位小数
*/
function amount(value) {
//金额,只允许保留两位小数
return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
}
/**
* 中文
*/
function chinese(value) {
let reg = /^[\u4e00-\u9fa5]+$/gi;
return reg.test(value);
}
/**
* 只能输入字母
*/
function letter(value) {
return /^[a-zA-Z]*$/.test(value);
}
/**
* 只能是字母或者数字
*/
function enOrNum(value) {
//英文或者数字
let reg = /^[0-9a-zA-Z]*$/g;
return reg.test(value);
}
/**
* 验证是否包含某个值
*/
function contains(value, param) {
return value.indexOf(param) >= 0
}
/**
* 验证一个值范围[min, max]
*/
function range(value, param) {
return value >= param[0] && value <= param[1]
}
/**
* 验证一个长度范围[min, max]
*/
function rangeLength(value, param) {
return value.length >= param[0] && value.length <= param[1]
}
/**
* 是否固定电话
*/
function landline(value) {
let reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
return reg.test(value);
}
/**
* 判断是否为空
*/
function empty(value) {
switch (typeof value) {
case 'undefined':
return true;
case 'string':
if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
break;
case 'boolean':
if (!value) return true;
break;
case 'number':
if (0 === value || isNaN(value)) return true;
break;
case 'object':
if (null === value || value.length === 0) return true;
for (var i in value) {
return false;
}
return true;
}
return false;
}
/**
* 是否json字符串
*/
function jsonString(value) {
if (typeof value == 'string') {
try {
var obj = JSON.parse(value);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
return false;
}
/**
* 是否数组
*/
function array(value) {
if (typeof Array.isArray === "function") {
return Array.isArray(value);
} else {
return Object.prototype.toString.call(value) === "[object Array]";
}
}
/**
* 是否对象
*/
function object(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
/**
* 是否短信验证码
*/
function code(value, len = 6) {
return new RegExp(`^\\d{${len}}$`).test(value);
}
export default {
email,
mobile,
url,
date,
dateISO,
number,
digits,
idCard,
carNo,
amount,
chinese,
letter,
enOrNum,
contains,
range,
rangeLength,
empty,
isEmpty: empty,
jsonString,
landline,
object,
array,
code
}

32
libs/function/throttle.js Normal file
View File

@ -0,0 +1,32 @@
let timer, flag;
/**
* 节流原理在一定时间内只能触发一次
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
function throttle(func, wait = 500, immediate = true) {
if (immediate) {
if (!flag) {
flag = true;
// 如果是立即执行则在wait毫秒内开始时执行
typeof func === 'function' && func();
timer = setTimeout(() => {
flag = false;
}, wait);
}
} else {
if (!flag) {
flag = true
// 如果是非立即执行则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false
typeof func === 'function' && func();
}, wait);
}
}
};
export default throttle

View File

@ -0,0 +1,51 @@
// padStart 的 polyfill因为某些机型或情况还无法支持es7的padStart比如电脑版的微信小程序
// 所以这里做一个兼容polyfill的兼容处理
if (!String.prototype.padStart) {
// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
String.prototype.padStart = function(maxLength, fillString = ' ') {
if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError(
'fillString must be String')
let str = this
// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
if (str.length >= maxLength) return String(str)
let fillLength = maxLength - str.length,
times = Math.ceil(fillLength / fillString.length)
while (times >>= 1) {
fillString += fillString
if (times === 1) {
fillString += fillString
}
}
return fillString.slice(0, fillLength) + str;
}
}
// 其他更多是格式化有如下:
// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') {
// 如果为null,则格式化当前时间
if (!dateTime) dateTime = Number(new Date());
// 如果dateTime长度为10或者13则为秒和毫秒的时间戳如果超过13位则为其他的时间格式
if (dateTime.toString().length == 10) dateTime *= 1000;
let date = new Date(dateTime);
let ret;
let opt = {
"y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"h+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"s+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
export default timeFormat

47
libs/function/timeFrom.js Normal file
View File

@ -0,0 +1,47 @@
import timeFormat from '../../libs/function/timeFormat.js';
/**
* 时间戳转为多久之前
* @param String timestamp 时间戳
* @param String | Boolean format 如果为时间格式字符串超出一定时间范围返回固定的时间格式
* 如果为布尔值false无论什么时间都返回多久以前的格式
*/
function timeFrom(dateTime = null, format = 'yyyy-mm-dd') {
// 如果为null,则格式化当前时间
if (!dateTime) dateTime = Number(new Date());
// 如果dateTime长度为10或者13则为秒和毫秒的时间戳如果超过13位则为其他的时间格式
if (dateTime.toString().length == 10) dateTime *= 1000;
let timestamp = + new Date(Number(dateTime));
let timer = (Number(new Date()) - timestamp) / 1000;
// 如果小于5分钟,则返回"刚刚",其他以此类推
let tips = '';
switch (true) {
case timer < 300:
tips = '刚刚';
break;
case timer >= 300 && timer < 3600:
tips = parseInt(timer / 60) + '分钟前';
break;
case timer >= 3600 && timer < 86400:
tips = parseInt(timer / 3600) + '小时前';
break;
case timer >= 86400 && timer < 2592000:
tips = parseInt(timer / 86400) + '天前';
break;
default:
// 如果format为false则无论什么时间戳都显示xx之前
if(format === false) {
if(timer >= 2592000 && timer < 365 * 86400) {
tips = parseInt(timer / (86400 * 30)) + '个月前';
} else {
tips = parseInt(timer / (86400 * 365)) + '年前';
}
} else {
tips = timeFormat(timestamp, format);
}
}
return tips;
}
export default timeFrom;

9
libs/function/toast.js Normal file
View File

@ -0,0 +1,9 @@
function toast(title, duration = 1500) {
uni.showToast({
title: title,
icon: 'none',
duration: duration
})
}
export default toast

15
libs/function/trim.js Normal file
View File

@ -0,0 +1,15 @@
function trim(str, pos = 'both') {
if (pos == 'both') {
return str.replace(/^\s+|\s+$/g, "");
} else if (pos == "left") {
return str.replace(/^\s*/, '');
} else if (pos == 'right') {
return str.replace(/(\s*$)/g, "");
} else if (pos == 'all') {
return str.replace(/\s+/g, "");
} else {
return str;
}
}
export default trim

View File

@ -0,0 +1,35 @@
/**
* 根据主题type值,获取对应的图标
* @param String type 主题名称,primary|info|error|warning|success
* @param String fill 是否使用fill填充实体的图标
*/
function type2icon(type = 'success', fill = false) {
// 如果非预置值,默认为success
if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success';
let iconName = '';
// 目前(2019-12-12),info和primary使用同一个图标
switch (type) {
case 'primary':
iconName = 'info-circle';
break;
case 'info':
iconName = 'info-circle';
break;
case 'error':
iconName = 'close-circle';
break;
case 'warning':
iconName = 'error-circle';
break;
case 'success':
iconName = 'checkmark-circle';
break;
default:
iconName = 'checkmark-circle';
}
// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
if (fill) iconName += '-fill';
return iconName;
}
export default type2icon

64
libs/mixin/mixin.js Normal file
View File

@ -0,0 +1,64 @@
module.exports = {
data() {
return {}
},
onLoad() {
// getRect挂载到$u上因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
this.$u.getRect = this.$uGetRect
},
methods: {
// 查询节点信息
// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸为支付宝的bug(2020-07-21)
// 解决办法为在组件根部再套一个没有任何作用的view元素
$uGetRect(selector, all) {
return new Promise(resolve => {
uni.createSelectorQuery().
in(this)[all ? 'selectAll' : 'select'](selector)
.boundingClientRect(rect => {
if (all && Array.isArray(rect) && rect.length) {
resolve(rect)
}
if (!all && rect) {
resolve(rect)
}
})
.exec()
})
},
getParentData(parentName = '') {
// 避免在created中去定义parent变量
if(!this.parent) this.parent = false;
// 这里的本质原理是,通过获取父组件实例(也即u-radio-group的this)
// 将父组件this中对应的参数赋值给本组件(u-radio的this)的parentData对象中对应的属性
// 之所以需要这么做是因为所有端中头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
this.parent = this.$u.$parent.call(this, parentName);
if(this.parent) {
// 历遍parentData中的属性将parent中的同名属性赋值给parentData
Object.keys(this.parentData).map(key => {
this.parentData[key] = this.parent[key];
});
}
},
// 阻止事件冒泡
preventEvent(e) {
e && e.stopPropagation && e.stopPropagation()
}
},
onReachBottom() {
uni.$emit('uOnReachBottom')
},
beforeDestroy() {
// 判断当前页面是否存在parent和children一般在checkbox和checkbox-group父子联动的场景会有此情况
// 组件销毁时移除子组件在父组件children数组中的实例释放资源避免数据混乱
if(this.parent && uni.$u.test.array(this.parent.children)) {
// 组件销毁时移除父组件中的children数组中对应的实例
const childrenList = this.parent.children
childrenList.map((child, index) => {
// 如果相等,则移除
if(child === this) {
childrenList.splice(index, 1)
}
})
}
}
}

18
libs/mixin/mpShare.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
onLoad() {
// 设置默认的转发参数
this.$u.mpShare = {
title: '', // 默认为小程序名称
path: '', // 默认为当前页面路径
imageUrl: '' // 默认为当前页面的截图
}
},
onShareAppMessage() {
return this.$u.mpShare
},
// #ifdef MP-WEIXIN
onShareTimeline() {
return this.$u.mpShare
}
// #endif
}

169
libs/request/index.js Normal file
View File

@ -0,0 +1,169 @@
import deepMerge from "../function/deepMerge";
import validate from "../function/test";
class Request {
// 设置全局默认配置
setConfig(customConfig) {
// 深度合并对象,否则会造成对象深层属性丢失
this.config = deepMerge(this.config, customConfig);
}
// 主要请求部分
request(options = {}) {
// 检查请求拦截
if (this.interceptor.request && typeof this.interceptor.request === 'function') {
let tmpConfig = {};
let interceptorRequest = this.interceptor.request(options);
if (interceptorRequest === false) {
// 返回一个处于pending状态中的Promise来取消原promise避免进入then()回调
return new Promise(()=>{});
}
this.options = interceptorRequest;
}
options.dataType = options.dataType || this.config.dataType;
options.responseType = options.responseType || this.config.responseType;
options.url = options.url || '';
options.params = options.params || {};
options.header = Object.assign({}, this.config.header, options.header);
options.method = options.method || this.config.method;
return new Promise((resolve, reject) => {
options.complete = (response) => {
// 请求返回后隐藏loading(如果请求返回快的话可能会没有loading)
uni.hideLoading();
// 清除定时器如果请求回来了就无需loading
clearTimeout(this.config.timer);
this.config.timer = null;
// 判断用户对拦截返回数据的要求如果originalData为true返回所有的数据(response)到拦截器否则只返回response.data
if(this.config.originalData) {
// 判断是否存在拦截器
if (this.interceptor.response && typeof this.interceptor.response === 'function') {
let resInterceptors = this.interceptor.response(response);
// 如果拦截器不返回false就将拦截器返回的内容给this.$u.post的then回调
if (resInterceptors !== false) {
resolve(resInterceptors);
} else {
// 如果拦截器返回false意味着拦截器定义者认为返回有问题直接接入catch回调
reject(response);
}
} else {
// 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据
resolve(response);
}
} else {
if (response.statusCode == 200) {
if (this.interceptor.response && typeof this.interceptor.response === 'function') {
let resInterceptors = this.interceptor.response(response.data);
if (resInterceptors !== false) {
resolve(resInterceptors);
} else {
reject(response.data);
}
} else {
// 如果不是返回原始数据(originalData=false)且没有拦截器的情况下返回纯数据给then回调
resolve(response.data);
}
} else {
// 不返回原始数据的情况下服务器状态码不为200modal弹框提示
// if(response.errMsg) {
// uni.showModal({
// title: response.errMsg
// });
// }
reject(response)
}
}
}
// 判断用户传递的URL是否/开头,如果不是,加上/这里使用了uView的test.js验证库的url()方法
options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ?
options.url : '/' + options.url));
// 是否显示loading
// 加一个是否已有timer定时器的判断否则有两个同时请求的时候后者会清除前者的定时器id
// 而没有清除前者的定时器导致前者超时一直显示loading
if(this.config.showLoading && !this.config.timer) {
this.config.timer = setTimeout(() => {
uni.showLoading({
title: this.config.loadingText,
mask: this.config.loadingMask
})
this.config.timer = null;
}, this.config.loadingTime);
}
uni.request(options);
})
// .catch(res => {
// // 如果返回reject()不让其进入this.$u.post().then().catch()后面的catct()
// // 因为很多人都会忘了写后面的catch()导致报错捕获不到catch
// return new Promise(()=>{});
// })
}
constructor() {
this.config = {
baseUrl: '', // 请求的根域名
// 默认的请求头
header: {},
method: 'POST',
// 设置为json返回后uni.request会对数据进行一次JSON.parse
dataType: 'json',
// 此参数无需处理因为5+和支付宝小程序不支持默认为text即可
responseType: 'text',
showLoading: true, // 是否显示请求中的loading
loadingText: '请求中...',
loadingTime: 800, // 在此时间内请求还没回来的话就显示加载中动画单位ms
timer: null, // 定时器
originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明
loadingMask: true, // 展示loading的时候是否给一个透明的蒙层防止触摸穿透
}
// 拦截器
this.interceptor = {
// 请求前的拦截
request: null,
// 请求后的拦截
response: null
}
// get请求
this.get = (url, data = {}, header = {}) => {
return this.request({
method: 'GET',
url,
header,
data
})
}
// post请求
this.post = (url, data = {}, header = {}) => {
return this.request({
url,
method: 'POST',
header,
data
})
}
// put请求不支持支付宝小程序(HX2.6.15)
this.put = (url, data = {}, header = {}) => {
return this.request({
url,
method: 'PUT',
header,
data
})
}
// delete请求不支持支付宝和头条小程序(HX2.6.15)
this.delete = (url, data = {}, header = {}) => {
return this.request({
url,
method: 'DELETE',
header,
data
})
}
}
}
export default new Request

19
libs/store/index.js Normal file
View File

@ -0,0 +1,19 @@
// 暂时不用vuex模块方式实现将该方法直接放入到/store/index.js中
const module = {
actions: {
$uStore({rootState}, params) {
let nameArr = params.name.split('.');
if(nameArr.length >= 2) {
let obj = rootState[nameArr[0]];
for(let i = 1; i < nameArr.length - 1; i ++) {
obj = obj[nameArr[i]];
}
obj[nameArr[nameArr.length - 1]] = params.value;
} else {
rootState[params.name] = params.value;
}
}
}
}
export default module

1
libs/util/area.js Normal file

File diff suppressed because one or more lines are too long

1356
libs/util/async-validator.js Normal file

File diff suppressed because it is too large Load Diff

1
libs/util/city.js Normal file

File diff suppressed because one or more lines are too long

51
libs/util/emitter.js Normal file
View File

@ -0,0 +1,51 @@
/**
* 递归使用 call 方式this指向
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
function broadcast(componentName, eventName, params) {
// 循环子节点找到名称一样的子节点 否则 递归 当前子节点
this.$children.map(child=>{
if (componentName===child.$options.name) {
child.$emit.apply(child,[eventName].concat(params))
}else {
broadcast.apply(child,[componentName,eventName].concat(params))
}
})
}
export default {
methods: {
/**
* 派发 (向上查找) (一个)
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点
let name = parent.$options.name; // 获取当前组件实例的name
// 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点
// 循环出当前名称的一样的组件实例
while (parent && (!name||name!==componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
// 有节点表示当前找到了name一样的实例
if (parent) {
parent.$emit.apply(parent,[eventName].concat(params))
}
},
/**
* 广播 (向下查找) (广播多个)
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
broadcast(componentName, eventName, params) {
broadcast.call(this,componentName, eventName, params)
}
}
}

1
libs/util/province.js Normal file
View File

@ -0,0 +1 @@
var provinceData=[{"label":"北京市","value":"11"},{"label":"天津市","value":"12"},{"label":"河北省","value":"13"},{"label":"山西省","value":"14"},{"label":"内蒙古自治区","value":"15"},{"label":"辽宁省","value":"21"},{"label":"吉林省","value":"22"},{"label":"黑龙江省","value":"23"},{"label":"上海市","value":"31"},{"label":"江苏省","value":"32"},{"label":"浙江省","value":"33"},{"label":"安徽省","value":"34"},{"label":"福建省","value":"35"},{"label":"江西省","value":"36"},{"label":"山东省","value":"37"},{"label":"河南省","value":"41"},{"label":"湖北省","value":"42"},{"label":"湖南省","value":"43"},{"label":"广东省","value":"44"},{"label":"广西壮族自治区","value":"45"},{"label":"海南省","value":"46"},{"label":"重庆市","value":"50"},{"label":"四川省","value":"51"},{"label":"贵州省","value":"52"},{"label":"云南省","value":"53"},{"label":"西藏自治区","value":"54"},{"label":"陕西省","value":"61"},{"label":"甘肃省","value":"62"},{"label":"青海省","value":"63"},{"label":"宁夏回族自治区","value":"64"},{"label":"新疆维吾尔自治区","value":"65"},{"label":"台湾","value":"66"},{"label":"香港","value":"67"},{"label":"澳门","value":"68"}];export default provinceData;

29
main.js Normal file
View File

@ -0,0 +1,29 @@
import App from './App'
import uView from '@/uni_modules/uview-ui'
Vue.use(uView);
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
require('./utils/request/index')(app)
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App);
return {
app
}
}
// #endif

118
manifest.json Normal file
View File

@ -0,0 +1,118 @@
{
"name" : "古言小说",
"appid" : "__UNI__474F351",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"safearea" : {
//ioS
"background" : "#F5F6F9", //"#FFFFFF"
"bottom" : {
//
"offset" : "none|auto" // "none""auto""none"
}
},
"bounce" : "none", //
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
// "appstore" : "static/app_logo.png",
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png"
},
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification" : "unpackage/res/icons/20x20.png"
},
"appstore" : "unpackage/res/icons/1024x1024.png"
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
}

326
pages.json Normal file
View File

@ -0,0 +1,326 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
//
"path": "pages/initialization/initialization",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
//
"path": "pages/agreement/agreement",
"style": {
"navigationBarTitleText": "",
// "navigationStyle": "custom",
"app-plus": {
"bounce": "none" ,//
"safearea": {
//ioS
"background": "#FFFFFF", //"#FFFFFF"
"bottom": {
//
"offset": "auto" // "none""auto""none"
}
}
}
}
},
{
"path": "pages/bookCity/bookCity/index",
"style": {
"navigationBarTitleText": "书城",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/bookshelf/bookshelf/index",
"style": {
"navigationBarTitleText": "书架",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/login/login",
"style": {
//
"navigationBarTitleText": "",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/loginMobile/loginMobile",
"style": {
//
"navigationBarTitleText": "",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/classification/classification/index",
"style": {
"navigationBarTitleText": "分类",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/myInfo/myInfo/index",
"style": {
"navigationBarTitleText": "我的",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/myInfo/aboutMy/index",
"style": {
"navigationBarTitleText": "关于我们",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/myInfo/mySetUp/index",
"style": {
"navigationBarTitleText": "设置",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/myInfo/problemList/index",
"style": {
"navigationBarTitleText": "常见问题",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/myInfo/problemDetail/index",
"style": {
"navigationBarTitleText": "常见问题",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/voucherCenter/index",
"style": {
"navigationBarTitleText": "充值中心",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/readingRecords/index",
"style": {
"navigationBarTitleText": "阅读记录",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/signInBookCurrency/index",
"style": {
"navigationBarTitleText": "签到领取书币",
"navigationStyle": "custom",
"navigationBarTextStyle": "white",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/booksListAll/index",
"style": {
//
"navigationBarTitleText": "",
"app-plus": {
"bounce": "none" //
}
// "app-plus": {
// "safearea": { //ioS
// "background": "#FFFFFF", //"#FFFFFF"
// "bottom": { //
// "offset": "none" // "none""auto""none"
// }
// }
// }
// "app-plus": {
// "bottom": "0",
// "contentAdjust": "false",
// "bounce": "none",
// "safearea": {
// "bottom": "none"
// }
// }
}
},
{
"path": "pages/booksTheCharts/index",
"style": {
// booksTheCharts
"navigationBarTitleText": "",
// "navigationBarBackgroundColor": "transparent",
"navigationStyle": "custom",
// "app-plus": {
// "titleNView": {
// "backgroundColor": "transparent",
// "background": "transparent"
// }
// }
// "enablePullDownRefresh": false,
// "disableScroll": true,
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/voucherCenterDetail/index",
"style": {
"navigationBarTitleText": "充值记录",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/bookCoinDetail/bookCoinDetail",
"style": {
"navigationBarTitleText": "书币明细",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/giveCoinDetail/giveCoinDetail",
"style": {
"navigationBarTitleText": "赠币明细",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/booksSearchList/booksSearchList",
"style": {
"navigationBarTitleText": "搜索",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/novelReading/novelReading",
"style": {
//
"navigationBarTitleText": "",
"navigationStyle": "custom",
"app-plus": {
"bounce": "none"
},
// "enablePullDownRefresh": true
"enablePullDownRefresh": false
}
},
{
"path": "pages/booksReadingDetail/booksReadingDetail",
"style": {
//
"navigationBarTitleText": "",
"app-plus": {
"bounce": "none" //
}
}
},
{
"path": "pages/bookRecommendList/bookRecommendList",
"style": {
//
"navigationBarTitleText": "",
"app-plus": {
"bounce": "none" //
}
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {},
"easycom": {
// "autoscan": true,
"custom": {
// "^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
// "^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
// "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
"fui-(.*)": "firstui-uni/firstui/fui-$1/fui-$1.vue",
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
}
},
"tabBar": {
"backgroundColor": "#FFFFFF",
"borderStyle": "#F5F5F5",
"selectedColor": "#FF5000",
"iconWidth": "24px",
"color": "#666666",
"fontSize": "10px",
"height": "68px",
"list": [{
"pagePath": "pages/bookshelf/bookshelf/index",
"text": "书架",
"iconPath": "/static/images/tabbar/bookshelf.png",
"selectedIconPath": "/static/images/tabbar/bookshelfActive.png"
},
{
"pagePath": "pages/bookCity/bookCity/index",
"text": "书城",
"iconPath": "/static/images/tabbar/bookCity.png",
"selectedIconPath": "/static/images/tabbar/bookCityActive.png"
}, {
"pagePath": "pages/classification/classification/index",
"text": "分类",
"iconPath": "/static/images/tabbar/classification.png",
"selectedIconPath": "/static/images/tabbar/classificationActive.png"
},
{
"pagePath": "pages/myInfo/myInfo/index",
"text": "我的",
"iconPath": "/static/images/tabbar/myInfo.png",
"selectedIconPath": "/static/images/tabbar/myInfoActive.png"
}
]
}
}

View File

@ -0,0 +1,56 @@
<template>
<view class="agreement_content">
<web-view :webview-styles="webviewStyles" :src="webViewSrc"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
webviewStyles: {
progress: false
},
webViewType: '',
webViewSrc: ''
}
},
onLoad(options) {
const type = options.type;
const obj = {
//
'1': {
title: '《用户协议》',
src: `https://qjnovelweb.qinjiuxiaoshuo.com/UserAgreement.html`
},
//
'2': {
title: '《隐私协议》',
src: `https://qjnovelweb.qinjiuxiaoshuo.com/privacypolicy.html`
}
}
uni.setNavigationBarTitle({
title: obj[type].title
});
this.webViewSrc = obj[type].src;
this.webViewType = type;
},
onShow() {
},
methods: {
}
}
</script>
<style lang="scss">
.agreement_content {
position: relative;
width: 100%;
height: 100%;
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom);
}
</style>

View File

@ -0,0 +1,162 @@
<template>
<!-- -->
<view class="bookCity_content">
<CommNavBar :navBarList="navBarList" @navBarClick="handelCommNavBar" :navBarActive="navBarActive" />
<view class="bookCity_content_body">
<scroll-view scroll-y="true" class="scroll_y">
<view class="scroll_y_item">
<Home v-if="navBarActive == '1'" ref="bookCityHome" @handelRankingList="handelRankingList"
:explosiveDataList="explosiveDataList" :rankingDataList="rankingDataList"
:headerListActive="headerListActive" :popularityDataList="popularityDataList"
:originalDataList="originalDataList" :recommendDataList="recommendDataList"
:moreBooksList="moreBooksList" :swiperList="swiperList" :skeletonLoading="skeletonLoading" />
<Member v-if="navBarActive == '2'" />
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import CommNavBar from '@/components/commNavBar/index.vue'
import Home from '@/pages/bookCity/components/home/index.vue'
import Member from '@/pages/bookCity/components/member/index.vue'
import {
isGetSystemInfo
} from '@/utils/systemInfo.js'
import {
baseUrlImage
} from '@/utils/utils'
export default {
components: {
CommNavBar,
Home,
Member
},
data() {
return {
navBarList: [{
id: '1',
name: '首页'
},
// {
// id: '2',
// name: ''
// },
],
navBarActive: '1',
//
explosiveDataList: [],
//
rankingDataList: [],
rankingDataObj: {},
headerListActive: '1',
//
popularityDataList: [],
//
originalDataList: [],
//
recommendDataList: [],
//
moreBooksList: [],
swiperList: [],
skeletonLoading: false
}
},
onLoad() {},
onShow() {
// this.$nextTick(() => {
// this.$refs.bookCityHome.isGetIndex()
// })
this.isGetHomeIndex();
},
methods: {
handelCommNavBar(event) {
this.navBarActive = event.currentTarget.dataset.id
},
isGetHomeIndex() {
// this.skeletonLoading = true;
// uni.showLoading({
// title: '...'
// });
// uni.$u.post
const parameter = {
custom: {
token: true
}
}
uni.$u.http.post('/Index', {}, parameter).then((res) => {
// uni.hideLoading();
this.skeletonLoading = false;
if (res.status == 1) {
const {
ads,
module1,
charts1,
charts2,
charts3,
charts4,
module3,
module4,
module5,
module6
} = res.data;
this.swiperList = baseUrlImage(ads);
this.explosiveDataList = baseUrlImage(module1);
this.explosiveDataList = baseUrlImage(module1);
const rankingDataObj = {
'1': baseUrlImage(charts1),
'2': baseUrlImage(charts2),
'3': baseUrlImage(charts3),
'4': baseUrlImage(charts4)
}
this.rankingDataList = rankingDataObj[this.headerListActive];
this.rankingDataObj = rankingDataObj;
this.popularityDataList = baseUrlImage(module3);
this.originalDataList = baseUrlImage(module4);
this.recommendDataList = baseUrlImage(module5);
this.moreBooksList = baseUrlImage(module6);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
handelRankingList(event) {
const id = event.currentTarget.dataset.id;
this.headerListActive = id;
this.rankingDataList = this.rankingDataObj[id];
},
}
}
</script>
<style lang="scss">
.bookCity_content {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: hidden;
.bookCity_content_body {
flex: 1;
width: 100%;
height: 100%;
position: relative;
z-index: 2;
flex-shrink: 0;
.scroll_y {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
.scroll_y_item {}
}
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<view class="explosiveList_content">
<view class="_explosive_title">全网火爆</view>
<view class="_explosive_list">
<view class="_explosive_list_item" v-for="m in dataList" :key="m.id" @tap="toBooksReadingDetail(m)">
<view class="_explosive_list_item_box">
<CommBookItem :bookName="m.title" :bookTips="m.category_name" :bookImage="m.cover" />
</view>
</view>
</view>
</view>
</template>
<script>
import CommBookItem from '@/components/commBookItem/index.vue'
export default {
name: 'explosiveList',
components: {
CommBookItem
},
props: {
dataList: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {}
},
methods: {
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
page {
height: 100%;
}
.explosiveList_content {
width: 100%;
._explosive_title {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
._explosive_list {
width: 100%;
display: flex;
// justify-content: safe center;
flex-wrap: wrap;
._explosive_list_item {
width: 200rpx;
padding-top: 32rpx;
margin-left: 32rpx;
._explosive_list_item_box {
width: 100%;
}
}
._explosive_list_item:first-child {
margin-left: 0;
}
._explosive_list_item:nth-child(4n + 0) {
margin-left: 0;
}
}
}
</style>

View File

@ -0,0 +1,294 @@
<template>
<view class="bookCity_home_content">
<view class="my_x_skeleton" v-if="skeletonLoading">
<x-skeleton type="banner" :loading="skeletonLoading" class="step_swiper_skeleton"></x-skeleton>
<x-skeleton type="menu" :loading="skeletonLoading" class="step_operate_skeleton"
:configs="{'gridRows': 1,'gridColumns':4, 'textWidth': '40%'}"></x-skeleton>
<x-skeleton type="waterfall" :loading="skeletonLoading" class="step_explosive_skeleton"
:configs="{'gridRows': 1,'gridColumns':3, 'headWidth': '100%', 'headHeight':'266rpx','headBorderRadius':'8rpx','textRows':2 ,'textRowsGap':'20rpx','textWidth':['100%','80%']}"></x-skeleton>
<x-skeleton type="menu" :loading="skeletonLoading" class="step_ranking_skeleton"
:configs="{'gridRows': 1,'gridColumns':4, 'headWidth': '100%', 'headHeight':'70rpx','textShow':false,'headBorderRadius':'8rpx','gridColumnsGap':'20rpx','padding':'15px 15px 0 15px'}"></x-skeleton>
<x-skeleton type="menu" :loading="skeletonLoading" class="step_ranking_skeleton"
:configs="{'gridRows': 2,'gridColumns':2, 'headWidth': '130rpx', 'headHeight':'180rpx','headBorderRadius':'8rpx','gridColumnsGap':'20rpx','itemDirection':'row', 'textRows':3,'textWidth':['100%','80%','60%'],'textRowsGap':'20rpx','gridRowsGap':'32rpx'}"></x-skeleton>
<x-skeleton type="menu" :loading="skeletonLoading" class="step_ranking_skeleton"
:configs="{'gridRows': 1,'gridColumns':1, 'headWidth': '100%', 'headHeight':'82rpx','headBorderRadius':'8rpx','textShow':false,'padding':'0 15px 15px 15px'}"></x-skeleton>
</view>
<view class="home_content_box" v-if="!skeletonLoading">
<!-- 焦点图 -->
<view class="step_swiper">
<!-- style="height: 260rpx;" -->
<u-swiper :list="swiperList" keyName="cover" indicator indicatorMode="line" circular></u-swiper>
</view>
<!--九宫格操作列表 -->
<view class="step_operate">
<u-grid :border="false" col="4">
<u-grid-item v-for="(m,listIndex) in list" :key="listIndex" @click="toGridItemPath(m)">
<u-icon :name="m.name" :size="34" />
<text class="grid-text">{{m.title}}</text>
</u-grid-item>
</u-grid>
</view>
<!-- 全网火爆 -->
<view class="step_explosive">
<ExplosiveList :dataList="explosiveDataList" />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 榜单 -->
<view class="step_ranking_list">
<RankingList :dataList="rankingDataList" @handelRankingList="handelRankingList"
:headerListActive="headerListActive" />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 人气作品 -->
<view class="step_popularity_list">
<PopularityList isTitle="人气作品" :dataList="popularityDataList" />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 原创优选 -->
<view class="step_original_list">
<OriginalList :dataList="originalDataList" />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 书友推荐 -->
<view class="step_recommend_list">
<RecommendList :dataList="recommendDataList" />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 人气作品 -->
<view class="step_popularity_list step_more_list ">
<PopularityList isTitle="更多书籍" :dataList="moreBooksList" />
</view>
<!-- 底部 -->
<!-- <view class="step_footer">
<CommFooter />
</view> -->
</view>
</view>
</template>
<script>
import complete from '@/static/images/bookCity/complete.png';
import new_book from '@/static/images/bookCity/new_book.png';
import recharge from '@/static/images/bookCity/recharge.png';
import the_charts from '@/static/images/bookCity/the_charts.png';
import RankingList from './rankingList.vue'
import PopularityList from './popularityList.vue'
import ExplosiveList from './explosiveList.vue'
import OriginalList from './originalList.vue'
import RecommendList from './recommendList.vue'
import CommFooter from '@/components/commFooter/index.vue'
import config from '@/config/index';
import {
baseUrlImage
} from '@/utils/utils'
import {
myGetStorage,
} from '@/utils/storage/index.js';
export default {
components: {
RankingList,
PopularityList,
ExplosiveList,
OriginalList,
RecommendList,
CommFooter,
},
props: {
explosiveDataList: {
type: Array,
default: () => {
return [];
}
},
rankingDataList: {
type: Array,
default: () => {
return [];
}
},
headerListActive: {
type: String,
default: ''
},
popularityDataList: {
type: Array,
default: () => {
return [];
}
},
originalDataList: {
type: Array,
default: () => {
return [];
}
},
recommendDataList: {
type: Array,
default: () => {
return [];
}
},
moreBooksList: {
type: Array,
default: () => {
return [];
}
},
swiperList: {
type: Array,
default: () => {
return [];
}
},
skeletonLoading:{
type: Boolean,
default: () => {
return true;
}
}
},
data() {
return {
baseUrl: config.baseUrl,
list: [{
name: the_charts,
title: '榜单',
toPath: '/pages/booksTheCharts/index'
},
{
name: complete,
title: '完本',
toPath: '/pages/booksListAll/index',
type: 'complete'
},
{
name: new_book,
title: '新书',
toPath: '/pages/booksListAll/index',
type: 'new_book'
},
{
name: recharge,
title: '充值',
toPath: '/pages/voucherCenter/index',
type: 'recharge'
},
],
}
},
methods: {
toGridItemPath(row) {
const token = myGetStorage('token');
if (row.type == 'recharge' && !token) {
uni.navigateTo({
url: `/pages/login/login?to=3`
})
} else if (row.toPath) {
uni.navigateTo({
url: `${row.toPath}?titleType=${row.type}`
})
}
},
handelRankingList(event) {
this.$emit('handelRankingList', event)
// const id = event.currentTarget.dataset.id;
// this.headerListActive = id;
// this.rankingDataList = this.rankingDataObj[id];
},
}
}
</script>
<style lang="scss">
.bookCity_home_content {
// padding: 0 0 150rpx;
width: 100%;
box-sizing: border-box;
.my_x_skeleton {
.step_swiper_skeleton {
/deep/.x-skeleton__wrapper__head {
height: 260rpx !important;
}
}
.step_operate_skeleton {
/deep/.x-skeleton__wrapper__text {
display: flex;
justify-content: center;
}
}
}
.home_content_box {
.step_swiper {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
}
.step_operate {
width: 100%;
padding: 40rpx 32rpx;
box-sizing: border-box;
.grid-text {
font-size: 30rpx;
color: #222222;
}
}
.step_explosive {
width: 100%;
padding: 0 32rpx 32rpx;
box-sizing: border-box;
}
.step_ranking_list {
width: 100%;
padding: 40rpx;
box-sizing: border-box;
}
.step_popularity_list {
width: 100%;
padding: 40rpx;
box-sizing: border-box;
}
.step_original_list {
width: 100%;
padding: 40rpx;
box-sizing: border-box;
}
.step_recommend_list {
width: 100%;
padding: 40rpx;
box-sizing: border-box;
}
.step_footer {
width: 100%;
padding: 20rpx;
box-sizing: border-box;
}
.step_more_list {
margin-bottom: 32rpx;
}
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<view class="originalList_content">
<view class="originalList_content_header">
<view class="_content_headertitle">原创优选</view>
</view>
<view class="originalList_content_body">
<view class="_content_body_original_list">
<view class="_original_list_item" v-for="m in dataList" :key="m.id" @tap="toBooksReadingDetail(m)">
<OriginalBoolItem :bookName="m.title" :bookTips="m.category_name" :bookImage="m.cover" />
</view>
</view>
</view>
</view>
</template>
<script>
import OriginalBoolItem from '@/components/originalBoolItem/index.vue'
export default {
components: {
OriginalBoolItem,
},
props: {
dataList: {
type: Array,
default: []
},
},
data() {
return {
}
},
methods: {
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
.originalList_content {
width: 100%;
.originalList_content_header {
width: 100%;
._content_headertitle {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
}
.originalList_content_body {
width: 100%;
._content_body_original_list {
display: flex;
// justify-content: space-between;
flex-wrap: wrap;
width: 100%;
._original_list_item {
width: 150rpx;
margin-top: 32rpx;
margin-left: 20rpx;
}
._original_list_item:first-child {
margin-left: 0;
}
._original_list_item:nth-child(5n+0) {
margin-left: 0;
}
}
}
}
</style>

View File

@ -0,0 +1,67 @@
<template>
<view class="PopularityList_content">
<view class="PopularityList_header">
<view class="PopularityList_header_title">{{isTitle}}</view>
</view>
<view class="PopularityList_body">
<view class="PopularityList_body_item" v-for="m in dataList" :key="m.id" @tap="toBooksReadingDetail(m)">
<CommBookLeftRigth :bookTips="m.category_name" :bookName="m.title" :bookImage="m.cover" :bookIntroduction="m.intro"/>
</view>
</view>
</view>
</template>
<script>
import CommBookLeftRigth from '@/components/commBookLeftRigth/index.vue'
export default {
name:'PopularityList',
components: {
CommBookLeftRigth
},
props:{
dataList: {
type: Array,
default: []
},
isTitle: {
type: String,
default:''
}
},
data() {
return {
}
},
methods:{
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
.PopularityList_content {
width: 100%;
.PopularityList_header {
width: 100%;
.PopularityList_header_title {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
}
.PopularityList_body {
.PopularityList_body_item {
margin-top: 32rpx;
}
}
}
</style>

View File

@ -0,0 +1,242 @@
<template>
<view class="rankingList_content">
<view class="rankingList_header">
<scroll-view class="_header_list_scroll" scroll-x="true">
<view class="_header_list" v-for="m in headerList" :key="m.id" @tap="handelRankingList" :data-id="m.id">
<view :class="['_header_list_item',headerListActive == m.id ? 'active' : '']">
{{m.name}}
</view>
</view>
</scroll-view>
</view>
<view class="rankingList_body">
<view class="rankingList_body_box">
<view class="_body_box_book_list">
<view class="_book_list_item" v-for="(m,idx) in dataList" :key="m.id" @tap="toBooksReadingDetail(m)">
<view class="_book_list_item_left">
<image class="is_image" :src="m.cover"></image>
<view class="_book_list_item_ranking_icon">
<image class="is_image" :src="rankingIconList[idx]"></image>
</view>
</view>
<view class="_book_list_item_right">
<view class="_book_list_item_title">{{m.title}}</view>
<view class="_book_list_item_tips">{{m.category_name}}</view>
</view>
</view>
</view>
</view>
</view>
<view class="rankingList_more">
<view class="rankingList_more_btn" @tap="toBooksTheCharts">
查看全部
</view>
</view>
</view>
</template>
<script>
import ranking_one from '@/static/images/bookCity/ranking_one.png';
import ranking_two from '@/static/images/bookCity/ranking_two.png';
import ranking_three from '@/static/images/bookCity/ranking_three.png';
import ranking_four from '@/static/images/bookCity/ranking_four.png';
export default {
props: {
dataList: {
type: Array,
default: []
},
headerListActive: {
type: String,
default: ''
}
},
data() {
return {
headerList: [{
id: '1',
name: '人气榜'
},
{
id: '2',
name: '畅销榜'
},
{
id: '3',
name: '新书榜'
},
{
id: '4',
name: '完结榜'
},
],
rankingIconList: [
ranking_one,
ranking_two,
ranking_three,
ranking_four
]
}
},
methods: {
handelRankingList(event) {
this.$emit('handelRankingList', event);
},
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
toBooksTheCharts() {
uni.navigateTo({
url: `/pages/booksTheCharts/index?chartsType=${this.headerListActive}`
})
}
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
}
.rankingList_content {
width: 100%;
.rankingList_header {
width: 100%;
._header_list_scroll {
white-space: nowrap;
// width: 1000rpx;
._header_list {
// display: flex;
display: inline-block;
margin-left: 10rpx;
._header_list_item {
width: 160rpx;
height: 70rpx;
text-align: center;
line-height: 70rpx;
background-color: #F6F6F6;
border-radius: 8rpx;
color: #666666;
font-size: 30rpx;
}
._header_list_item.active {
color: #FC0538;
background-color: #FFDCE3;
}
}
._header_list:first-child {
margin-left: 0;
}
}
}
.rankingList_body {
width: 100%;
.rankingList_body_box {
width: 100%;
._body_box_book_list {
width: 100%;
display: flex;
flex-wrap: wrap;
._book_list_item {
display: flex;
width: 50%;
margin-top: 30rpx;
box-sizing: border-box;
._book_list_item_left {
position: relative;
width: 130rpx;
height: 180rpx;
flex: 0 0 auto;
z-index: 2;
border-radius: 8rpx;
overflow: hidden;
._book_list_item_ranking_icon {
position: absolute;
top: 0;
left: 0;
z-index: 3;
width: 38rpx;
height: 38rpx;
}
}
._book_list_item_right {
flex: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
margin-left: 16rpx;
overflow: hidden;
._book_list_item_title {
width: 100%;
font-size: 30rpx;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._book_list_item_tips {
width: 100%;
font-size: 26rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
._book_list_item:nth-child(2n) {
padding-left: 15rpx;
}
._book_list_item:nth-child(2n-1) {
padding-right: 15rpx;
}
}
}
}
.rankingList_more {
width: 100%;
margin-top: 32rpx;
.rankingList_more_btn {
width: 100%;
height: 82rpx;
border-radius: 16rpx;
background-color: #F1F1F1;
color: #666666;
font-size: 28rpx;
text-align: center;
line-height: 82rpx;
}
}
}
</style>

View File

@ -0,0 +1,78 @@
<template>
<view class="explosiveList_content">
<view class="_explosive_title">书友推荐</view>
<view class="_explosive_list">
<view class="_explosive_list_item" v-for="m in dataList" :key="m.id" @tap="toBooksReadingDetail(m)">
<view class="_explosive_list_item_box">
<CommBookItem :bookName="m.title" :bookTips="m.category_name" :bookImage="m.cover" />
</view>
</view>
</view>
</view>
</template>
<script>
import CommBookItem from '@/components/commBookItem/index.vue'
export default {
components: {
CommBookItem
},
props: {
dataList: {
type: Array,
default: []
},
},
data() {
return {
}
},
methods:{
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
.explosiveList_content {
width: 100%;
._explosive_title {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
._explosive_list {
width: 100%;
display: flex;
// justify-content: safe center;
flex-wrap: wrap;
._explosive_list_item {
width: 200rpx;
padding-top: 32rpx;
margin-left: 32rpx;
._explosive_list_item_box {
width: 100%;
}
}
._explosive_list_item:first-child {
margin-left: 0;
}
._explosive_list_item:nth-child(4n + 0) {
margin-left: 0;
}
}
}
</style>

View File

@ -0,0 +1,63 @@
<template>
<view class="member_content">
<view class="step_member_user_info">
<MemberUserInfo />
</view>
<!-- 会员专享 -->
<view class="step_member_exclusive">
<MemberExclusive />
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<!-- 为你推荐 -->
<view class="step_member_recommend">
<MemberRecommend />
</view>
</view>
</template>
<script>
import MemberUserInfo from './memberUserInfo.vue'
import MemberExclusive from './memberExclusive.vue'
import MemberRecommend from './memberRecommend.vue'
export default {
components: {
MemberExclusive,
MemberRecommend,
MemberUserInfo
},
data() {
return {
}
}
}
</script>
<style lang="scss">
.member_content {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
.step_member_user_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
}
.step_member_exclusive {
width: 100%;
padding: 0rpx 0 32rpx 32rpx;
box-sizing: border-box;
background-color: #ffffff;
}
.step_member_recommend {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
}
}
</style>

View File

@ -0,0 +1,96 @@
<template>
<view class="memberExclusive_content">
<view class="exclusive_content_header">
<view class="_header_title_all">
<view class="_title_all_vip_image">
<image class="is_image" src="/static/images/myInfo/VIP_active.png"></image>
</view>
<view class="_title_all_name">
会员专享
</view>
</view>
<view class="_header_tips">
会员免费阅读
</view>
</view>
<view class="exclusive_content_body">
<view class="_content_body_list">
<view class="_content_body_list_item" v-for="m in 6" :key="m">
<CommBookItem />
</view>
</view>
</view>
</view>
</template>
<script>
import CommBookItem from '@/components/commBookItem/index.vue';
export default {
components: {
CommBookItem
},
data() {
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
}
.memberExclusive_content {
width: 100%;
.exclusive_content_header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
box-sizing: border-box;
padding-right: 32rpx;
._header_title_all {
display: flex;
align-items: center;
._title_all_vip_image {
width: 48rpx;
height: 48rpx;
}
._title_all_name {
font-size: 36rpx;
color: #F45576;
line-height: 1;
margin-left: 8rpx;
font-weight: 600;
}
}
._header_tips {
font-size: 26rpx;
line-height: 1;
color: #666666;
}
}
.exclusive_content_body {
width: 100%;
._content_body_list {
display: flex;
flex-wrap: wrap;
._content_body_list_item {
width: 210rpx;
margin-right: 28rpx;
margin-top: 32rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,97 @@
<template>
<view class="memberRecommend_content">
<view class="recommend_content_header">
<view class="_header_title_all">
<view class="_title_all_vip_image">
<image class="is_image" src="/static/images/myInfo/VIP_active.png"></image>
</view>
<view class="_title_all_name">
为你推荐
</view>
</view>
<view class="_header_tips">
<!-- 会员免费阅读 -->
</view>
</view>
<view class="recommend_content_body">
<view class="_content_body_list">
<view class="_content_body_list_item" v-for="m in 8" :key="m">
<commBookItemThree />
</view>
</view>
</view>
</view>
</template>
<script>
import CommBookItem from '@/components/commBookItem/index.vue';
import commBookItemThree from '@/components/commBookItemThree/index.vue';
export default {
components: {
CommBookItem,
commBookItemThree
},
data() {
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
}
.memberRecommend_content {
width: 100%;
.recommend_content_header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
box-sizing: border-box;
padding-right: 32rpx;
._header_title_all {
display: flex;
align-items: center;
._title_all_vip_image {
width: 48rpx;
height: 48rpx;
}
._title_all_name {
font-size: 36rpx;
color: #F45576;
line-height: 1;
margin-left: 8rpx;
font-weight: 600;
}
}
._header_tips {
font-size: 26rpx;
line-height: 1;
color: #666666;
}
}
.recommend_content_body {
width: 100%;
._content_body_list {
display: flex;
flex-direction: column;
._content_body_list_item {
margin-top: 32rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<view class="memberUserInfo_centent">
<view class="member_tips_info">
<CommVipInfo />
</view>
</view>
</template>
<script>
import CommVipInfo from '@/components/commVipInfo/index.vue'
export default {
components: {
CommVipInfo
},
data() {
}
}
</script>
<style lang="scss">
.memberUserInfo_centent {
width: 100%;
.member_tips_info {
width: 100%;
// height: 134rpx;
// background: url('/static/images/bookCity/member_vip_bg.png') no-repeat;
// background-size: 100% 100%;
}
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<view class="bookCoinDetail_content">
<view class="_list_body">
<view class="_list_body_item">
<view class="_item_book_img">
<image class="is_image" src="/static/images/book_111.png"></image>
</view>
<view class="_item_book_title_other">
<view class="_item_book_title">
女主拿了反派剧本女主拿了反派剧本
</view>
<view class="_item_book_other_tips">
整本
</view>
<view class="_item_book_purchase_time">
购买时间2022.03.14
</view>
</view>
<view class="_item_book_coin_num">
<view class="_coin_num">
-6000书币
</view>
</view>
</view>
<view class="_list_body_item">
<view class="_item_book_img">
<image class="is_image" src="/static/images/book_111.png"></image>
</view>
<view class="_item_book_title_other">
<view class="_item_book_title">
女主拿了反派剧本女主拿了反派剧本
</view>
<view class="_item_book_other_tips">
整本
</view>
<view class="_item_book_purchase_time">
购买时间2022.03.14
</view>
</view>
<view class="_item_book_coin_num">
<view class="_coin_num">
-6000书币
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
.bookCoinDetail_content {
width: 100%;
._list_body {
width: 100%;
box-sizing: border-box;
padding: 32rpx;
._list_body_item {
display: flex;
justify-content: space-between;
width: 100%;
height: 212rpx;
overflow: hidden;
margin-bottom: 32rpx;
._item_book_img {
width: 160rpx;
height: 100%;
flex-shrink: 0;
}
._item_book_title_other {
flex: 1;
padding: 0 20rpx;
display: flex;
flex-direction: column;
justify-content: space-around;
overflow: hidden;
._item_book_title {
width: 100%;
font-size: 32rpx;
color: #1A1A1A;
line-height: 1;
white-space: nowrap; //
overflow: hidden; //
text-overflow: ellipsis; //
}
._item_book_other_tips {
font-size: 28rpx;
color: #999999;
line-height: 1;
}
._item_book_purchase_time {
font-size: 28rpx;
color: #999999;
line-height: 1;
white-space: nowrap; //
overflow: hidden; //
text-overflow: ellipsis; //
}
}
._item_book_coin_num {
display: flex;
align-items: center;
flex-shrink: 0;
._coin_num {
font-size: 32rpx;
color: #FF728F;
line-height: 1;
}
}
}
}
}
</style>

View File

@ -0,0 +1,236 @@
<template>
<view class="bookRecommendList_content">
<view class="bookRecommendList_header">
<view class="_header_chapter_num">
已完结 {{directoryCount}}
</view>
<view class="_header_chapter_all_list" @tap="handelChapterShow">
{{columnsLabel}}
<u-icon name="arrow-down" color="#666666" size="28rpx"></u-icon>
</view>
</view>
<view class="bookRecommendList_body">
<view class="chapter_list_box">
<view :class="[`_list_item`,]" v-for="m in directory" :key="m.id" @tap="handelDirectoryItem(m)">
<view :class="[`_item_name`,chapterorder == m.chapterorder ?'active':'']">
{{m.chaptername}}
</view>
<view v-if="m.isvip" class="_item_chapter_lock">
<image class="is_image" src="/static/images/chapter_lock.png"></image>
</view>
</view>
</view>
</view>
<view class="commFooter_box" v-if="commFooterFlag">
<CommFooter />
</view>
<u-picker :show="chapterShow" :columns="columns" @confirm="confirmChapterPicker" @cancel="cancelChapterPicker"
keyName="label"></u-picker>
</view>
</template>
<script>
import CommFooter from '@/components/commFooter/index.vue'
export default {
components: {
CommFooter
},
data() {
return {
columns: [],
chapterShow: false,
bookSid: '',
pageNum: 1,
startOrder: '',
directory: [],
directoryCount: 0,
columnsLabel: '',
commFooterFlag: false,
barTitle: '',
chapterorder: '',
directoryAll: {}
}
},
onLoad(options) {
this.bookSid = options.sid;
this.barTitle = options.t;
this.chapterorder = options.c;
},
onShow() {
const bookSid = this.bookSid;
const pageNum = this.pageNum;
const barTitle = this.barTitle;
uni.setNavigationBarTitle({
title: barTitle,
});
this.isGetDirectory(bookSid, pageNum)
},
onReachBottom() {
const bookSid = this.bookSid;
const pageNum = this.pageNum + 1;
this.pageNum = pageNum;
this.isGetDirectory(bookSid, pageNum)
},
methods: {
handelChapterShow() {
this.chapterShow = true;
},
handelDirectoryItem(row) {
const directoryAll = this.directoryAll;
let flag = true;
let chapterFlag = false;
Object.keys(directoryAll).forEach((m) => {
directoryAll[m].forEach((j) => {
if(flag) {
if (j.id != row.id && j.isvip == 1) {
chapterFlag = true;
}
if (j.id == row.id) {
flag = false
}
}
})
})
if(chapterFlag) {
uni.showToast({
icon: 'none',
title: '前面章节未解锁,暂不支持跳章节观看',
})
return;
}
uni.navigateTo({
url: `/pages/novelReading/novelReading?sid=${this.bookSid}&n=${this.barTitle}&id=${row.id}`
})
},
confirmChapterPicker(data) {
this.chapterShow = false;
const bookSid = this.bookSid;
const pageNum = 1;
this.startOrder = data.value[0].start;
this.columnsLabel = data.value[0].label;
this.pageNum = pageNum;
this.isGetDirectory(bookSid, pageNum)
},
cancelChapterPicker() {
this.chapterShow = false;
},
isGetDirectory(sid, page, startOrder) {
uni.showLoading({
title: '加载中...'
});
const data = {
sid,
page,
}
if (startOrder) {
data.startOrder = startOrder;
}
uni.$u.http.post('/getDirectory', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const directory = res.data.directory;
const stage = res.data.stage;
const directoryCount = res.data.directory_count;
let columnsLabel = ''
const columns = stage.map((m, idx) => {
if (idx === 0 && !startOrder) {
columnsLabel = `${m.start}-${m.end}`
}
return {
...m,
id: idx,
label: `${m.start}-${m.end}`
}
})
if (page == 1) {
this.directory = directory;
} else {
this.directory = [...this.directory, ...directory];
}
this.directoryAll = {
...this.directoryAll,
[columnsLabel]: directory
}
this.commFooterFlag = directory.length ? false : true;
this.columns = [columns];
this.directoryCount = directoryCount;
this.columnsLabel = columnsLabel;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
.bookRecommendList_content {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
.bookRecommendList_header {
display: flex;
justify-content: space-between;
._header_chapter_num {
font-size: 30rpx;
color: #666666;
line-height: 1;
}
._header_chapter_all_list {
display: flex;
align-items: center;
font-size: 30rpx;
color: #666666;
line-height: 1;
}
}
.bookRecommendList_body {
width: 100%;
margin-top: 20rpx;
.chapter_list_box {
width: 100%;
._list_item {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 120rpx;
border-bottom: 1rpx solid #F2F2F2;
._item_name {
font-size: 32rpx;
color: #333333;
line-height: 1;
}
._item_name.active {
color: #FF728F;
}
._item_chapter_lock {
width: 32rpx;
height: 32rpx;
}
}
}
}
.commFooter_box {
padding: 32rpx 0;
}
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<view class="booksListAll_content">
<view class="booksListAll_list">
<scroll-view scroll-y="true" class="scroll_y">
<view class="scroll_y_item">
<view class="booksListAll_list_item" v-for="m in booksList" :key="m.id"
@tap="toBooksReadingDetail(m)">
<CommBookLeftRigth :bookTips="m.category_name" :bookName="m.title" :bookImage="m.cover"
:bookIntroduction="m.intro" />
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import CommBookLeftRigth from '@/components/commBookLeftRigth/index.vue';
import {
baseUrlImage
} from '@/utils/utils'
export default {
components: {
CommBookLeftRigth
},
data() {
return {
booksList: []
}
},
onLoad(query) {
const titleType = query.titleType;
const barTitleObj = {
'complete': '完本书籍',
'new_book': '热门新书'
}
const barTitle = titleType ? barTitleObj[titleType] : '书籍列表'
uni.setNavigationBarTitle({
title: barTitle,
});
let httpUrl = ''
if (titleType == 'complete') {
httpUrl = '/getIntact'
} else if (titleType == 'new_book') {
httpUrl = '/getNewbook'
}
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
uni.$u.http.post(httpUrl, {}, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
module
} = res.data;
this.booksList = baseUrlImage(module);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
methods: {
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
.booksListAll_content {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 32rpx;
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom);
/* 兼容 iPhone X 及以上设备 */
.booksListAll_list {
width: 100%;
height: 100%;
position: relative;
.scroll_y {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
.scroll_y_item {
padding-bottom: 32rpx;
.booksListAll_list_item {
margin-bottom: 32rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<view class="bookBasicInfo_content">
<view class="bookBasicInfo_body">
<view class="bookBasicInfo_body_left">
<view class="book_cover_box">
<image class="is_image" :src="bookInfo.cover"></image>
</view>
</view>
<view class="bookBasicInfo_body_right">
<view class="book_title">
{{bookInfo.title}}
</view>
<view class="book_tips">
{{bookInfo.author}}
</view>
<!-- <view class="book_vip">
<view class="book_vip_txt">
开通VIP会员正版抢先看
</view>
</view> -->
<view class="book_type">
<view class="book_type_item">
{{bookInfo.category_name}}
</view>
<!-- <view class="book_type_item">
穿越
</view> -->
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookInfo: {
type: Object,
default: {
title: '',
author: '',
category_name: ''
}
}
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.bookBasicInfo_content {
width: 100%;
.bookBasicInfo_body {
display: flex;
width: 100%;
.bookBasicInfo_body_left {
.book_cover_box {
width: 210rpx;
height: 280rpx;
flex: 0 0 auto;
border-radius: 8rpx;
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
}
}
.bookBasicInfo_body_right {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 36rpx;
overflow: hidden;
.book_title {
font-size: 44rpx;
line-height: 1;
color: #1A1A1D;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.book_tips {
font-size: 28rpx;
color: #6E6E6E;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-top: 20rpx;
}
.book_vip {
display: flex;
margin-top: 20rpx;
.book_vip_txt {
padding: 0 20rpx;
height: 40rpx;
line-height: 40rpx;
background: linear-gradient(to left, #F2D4A8, #F6DEC2);
border-radius: 20rpx;
font-size: 24rpx;
color: #9A7C62;
}
}
.book_type {
display: flex;
margin-top: 10rpx;
.book_type_item {
padding: 0 20rpx;
height: 52rpx;
line-height: 52rpx;
background: #F3F3F3;
border-radius: 26rpx;
font-size: 24rpx;
color: #222222;
}
}
}
}
}
</style>

View File

@ -0,0 +1,126 @@
<template>
<view class="bookChapterInfo_content">
<view class="bookChapterInfo_body">
<view class="bookChapterInfo_header">
<view class="_header_title">
查看目录
</view>
<view class="_header_chapter" @tap="toBookRecommendList">
{{directoryCount}}
<u-icon name="arrow-right" color="#666666" size="26rpx" />
</view>
</view>
<view class="bookChapterInfo_list_box">
<view class="list_chapter_item" v-for="m in bookDirectory" :key="m.id">
<view class="chapter_item_name">
{{m.chaptername}}
</view>
</view>
</view>
<view class="_check_all_chapter" @tap="toBookRecommendList">
查看全部
</view>
</view>
</view>
</template>
<script>
export default {
props: {
directoryCount: {
type: Number,
default: 0,
},
bookDirectory: {
type: Array,
default: []
},
bookSid: {
type: String,
default: ''
},
bookInfo: {
type: Object,
default: {
title: '',
}
}
},
data() {
return {
}
},
methods: {
toBookRecommendList() {
uni.navigateTo({
url: `/pages/bookRecommendList/bookRecommendList?sid=${this.bookSid}&t=${this.bookInfo.title}`
})
}
}
}
</script>
<style lang="scss" scoped>
.bookChapterInfo_content {
width: 100%;
.bookChapterInfo_body {
width: 100%;
.bookChapterInfo_header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
._header_title {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
}
._header_chapter {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666666;
}
}
.bookChapterInfo_list_box {
margin-top: 20rpx;
.list_chapter_item {
display: flex;
align-items: center;
height: 106rpx;
border-bottom: 2rpx solid #E5E5E5;
.chapter_item_name {
font-size: 30rpx;
color: #222222;
line-height: 1;
}
}
.list_chapter_item:last-child {
border-bottom: none;
}
}
._check_all_chapter {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 88rpx;
background: #EEEEEE;
color: #444444;
font-size: 32rpx;
border-radius: 8rpx;
margin-top: 10rpx;
}
}
}
</style>

View File

@ -0,0 +1,109 @@
<template>
<view class="bookOtherInfo_content">
<view class="bookOtherInfo_body">
<view class="bookOtherInfo_item">
<view class="bookOtherInfo_top">
<view class="book_item_num">
{{bookInfo.score}}
</view>
<view class="book_item_tex">
评分
</view>
</view>
<view class="bookOtherInfo_bottom">
分数
</view>
</view>
<view class="bookOtherInfo_item">
<view class="bookOtherInfo_top">
<view class="book_item_num">
{{bookInfo.userNum}}
</view>
<view class="book_item_tex">
万人
</view>
</view>
<view class="bookOtherInfo_bottom">
在读
</view>
</view>
<view class="bookOtherInfo_item">
<view class="bookOtherInfo_top">
<view class="book_item_num">
{{bookInfo.size}}
</view>
<view class="book_item_tex">
万字
</view>
</view>
<view class="bookOtherInfo_bottom">
已完结
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookInfo: {
type: Object,
default: {
//
size: '',
//
score: '',
// 线
userNum: ''
}
}
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.bookOtherInfo_content {
width: 100%;
.bookOtherInfo_body {
display: flex;
justify-content: space-between;
width: 100%;
.bookOtherInfo_item {
.bookOtherInfo_top {
display: flex;
align-items: flex-end;
flex-wrap: nowrap;
.book_item_num {
font-size: 50rpx;
color: #1A1A1A;
line-height: 1;
font-weight: 600;
}
.book_item_tex {
margin-left: 4rpx;
color: #1A1A1A;
line-height: 1;
font-size: 28rpx;
}
}
.bookOtherInfo_bottom {
line-height: 1;
color: #666666;
font-size: 26rpx;
margin-top: 32rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<view class="bookRecommendInfo_content">
<view class="bookRecommendInfo_box">
<view class="_header_box">
<view class="_header_box_title">
推荐书籍
</view>
</view>
<view class="_body_list_box">
<view class="_body_list">
<view class="_body_list_item" v-for="m in recommendBooks" :key="m.id">
<view class="_item_book_over">
<image class="is_image" :src="m.cover"></image>
</view>
<view class="_item_book_name">
{{m.title}}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
recommendBooks: {
type: Array,
default: []
}
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.bookRecommendInfo_content {
width: 100%;
.bookRecommendInfo_box {
width: 100%;
._header_box {
width: 100%;
._header_box_title {
font-size: 36rpx;
color: #1A1A1A;
line-height: 1;
}
}
._body_list_box {
width: 100%;
._body_list {
width: 100%;
display: flex;
flex-wrap: wrap;
._body_list_item {
width: 202rpx;
margin-right: 32rpx;
._item_book_over {
width: 202rpx;
height: 270rpx;
border-radius: 8rpx;
margin-top: 30rpx;
}
._item_book_name {
width: 100%;
margin-top: 24rpx;
font-size: 30rpx;
line-height: 1;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
._body_list_item:nth-child(3n+0) {
margin-right: 0;
}
}
}
}
}
</style>

View File

@ -0,0 +1,72 @@
<template>
<view class="bookSynopsisInfo_content">
<view class="bookSynopsisInfo_body">
<view class="bookSynopsisInfo_title">
书籍简介
</view>
<view class="bookSynopsisInfo_box">
<u-read-more ref="uReadMore" showHeight="200rpx" fontSize="30rpx" :toggle="true" closeText="展开"
openText="收起" color="#FF728F">
<u-parse :content="bookInfo.intro" @load="load"></u-parse>
</u-read-more>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
bookInfo: {
type: Object,
default: {
intro: '',
}
}
},
data() {
return {
// content: '穿 '
}
},
methods: {
load() {
this.$refs.uReadMore.init();
}
}
}
</script>
<style lang="scss" scoped>
.bookSynopsisInfo_box::v-deep.u-read-more__content__inner {
span {
line-height: 1.8;
}
}
.bookSynopsisInfo_box::v-deep.u-read-more__toggle {
justify-content: flex-end;
.u-text__value {
font-size: 26rpx !important;
}
}
.bookSynopsisInfo_content {
width: 100%;
.bookSynopsisInfo_body {
width: 100%;
.bookSynopsisInfo_title {
color: #1A1A1A;
line-height: 1;
font-size: 36rpx;
}
.bookSynopsisInfo_box {
margin-top: 30rpx;
}
}
}
</style>

View File

@ -0,0 +1,262 @@
<template>
<view class="booksReadingDetail_content">
<view class="step_book_basic_info">
<view class="step_book_basic_info_comm">
<BookBasicInfo :bookInfo="bookInfo" />
</view>
</view>
<view class="step_book_other_info">
<view class="step_book_other_info_comm">
<BookOtherInfo :bookInfo="bookInfo" />
</view>
</view>
<view class="step_book_synopsis_info">
<view class="step_book_synopsis_info_comm">
<BookSynopsisInfo :bookInfo="bookInfo" />
</view>
</view>
<view class="step_book_chapter_info">
<view class="step_book_chapter_info_comm">
<BookChapterInfo :directoryCount="directoryCount" :bookDirectory="bookDirectory" :bookSid="bookSid"
:bookInfo="bookInfo" />
</view>
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<view class="step_book_recommend_info">
<view class="step_book_recommend_info_comm">
<BookRecommendInfo :recommendBooks="recommendBooks" :bookSid="bookSid" />
</view>
</view>
<view class="step_book_button_info">
<view class="step_book_button_info_comm">
<view v-if="!bookcase" class="_add_book_shelf" @tap="addBookshelf">
加入书架
</view>
<view v-else class="_add_book_shelf active">
已加书架
</view>
<view class="_start_read_book" @tap="toNovelReading">
开始阅读
</view>
</view>
</view>
</view>
</template>
<script>
import BookBasicInfo from './bookBasicInfo.vue';
import BookOtherInfo from './bookOtherInfo.vue';
import BookSynopsisInfo from './bookSynopsisInfo.vue';
import BookChapterInfo from './bookChapterInfo.vue';
import BookRecommendInfo from './bookRecommendInfo.vue';
import config from '@/config/index';
import {
baseUrlImage
} from '@/utils/utils'
export default {
components: {
BookBasicInfo,
BookOtherInfo,
BookSynopsisInfo,
BookChapterInfo,
BookRecommendInfo
},
data() {
return {
bookSid: '',
bookDirectory: [],
recommendBooks: [],
bookInfo: {},
directoryCount: 0,
bookcase: 0
}
},
onLoad(options) {
this.bookSid = options.sid
},
onShow() {
const bookSid = this.bookSid
uni.showLoading({
title: '加载中...'
});
const data = {
sid: bookSid,
}
uni.$u.http.post('/bookdetails', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const directory = res.data.directory;
const info = res.data.info;
const module = res.data.module;
const directory_count = res.data.directory_count;
const bookcase = res.data.bookcase;
this.bookDirectory = directory;
this.recommendBooks = baseUrlImage(module);
this.directoryCount = directory_count;
this.bookcase = bookcase
const cover = info.cover.includes('http') ? info.cover : `${config.baseUrl}${info.cover}`;
this.bookInfo = {
...info,
cover
};
console.log(res, this.bookInfo, "=======")
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
methods: {
addBookshelf() {
uni.showLoading({
title: '加载中...'
});
const data = {
sid: this.bookSid,
}
uni.$u.http.post('/addBookshelf', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
uni.showToast({
title: '加入成功',
icon: 'none'
})
this.bookcase = 1;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
toNovelReading() {
const bookInfo = this.bookInfo;
uni.navigateTo({
url: `/pages/novelReading/novelReading?sid=${bookInfo.id}`
})
}
}
}
</script>
<style lang="scss">
.booksReadingDetail_content {
width: 100%;
// padding-bottom: 130rpx;
padding-bottom: calc(constant(safe-area-inset-bottom) + 90px); /* 兼容 iOS 设备 */
padding-bottom: calc(env(safe-area-inset-bottom) + 90px); /* 兼容 iPhone X 及以上设备 */
.step_book_basic_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
.step_book_basic_info_comm {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
border-bottom: 2rpx solid #E5E5E5;
}
}
.step_book_other_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
.step_book_other_info_comm {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
border-bottom: 2rpx solid #E5E5E5;
}
}
.step_book_synopsis_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
.step_book_synopsis_info_comm {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
border-bottom: 2rpx solid #E5E5E5;
}
}
.step_book_chapter_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
.step_book_chapter_info_comm {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
}
}
.step_book_recommend_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
margin-bottom: 32rpx;
.step_book_recommend_info_comm {
width: 100%;
padding: 32rpx 0;
box-sizing: border-box;
}
}
.step_book_button_info {
width: 100%;
position: fixed;
left: 0;
bottom: 0;
background-color: #fff;
border-top: 1rpx solid #E5E5E5;
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iPhone X 及以上设备 */
.step_book_button_info_comm {
display: flex;
justify-content: space-between;
width: 100%;
padding: 14rpx 32rpx;
box-sizing: border-box;
._add_book_shelf {
display: flex;
justify-content: center;
align-items: center;
width: 328rpx;
height: 100rpx;
border-radius: 10rpx;
border: 2rpx solid #1A1A1A;
box-sizing: border-box;
color: #1A1A1A;
}
.active {
font-size: 36rpx;
color: #999999;
border-color: #999999;
}
._start_read_book {
display: flex;
justify-content: center;
align-items: center;
width: 328rpx;
height: 100rpx;
border-radius: 10rpx;
color: #fff;
background: linear-gradient(to left, #FF728F, #FF4D71);
}
}
}
}
</style>

View File

@ -0,0 +1,227 @@
<template>
<view class="booksSearchList_content">
<view v-if="!searchFlag">
<view class="step_search_box">
<view class="search_box_con">
<u-search v-model="bookKeyword" placeholder="输入您想看的小说" height="80rpx" :showAction="false"
bgColor="#F3F4F6" @clear="clearBookKeyword" confirmType="search"></u-search>
<view class="search_button" @tap="handelSearch">
<text>搜索</text>
</view>
</view>
</view>
<view v-if="!searchBooksData.length">
<view class="search_record_box">
<view class="search_popular_record">
<SearchRecord searchRecordTitle="热门搜索" :dataList="searchRecordList"
@handelSearchRecord="handelSearchRecord" />
</view>
</view>
<view class="search_history_box">
<view class="search_history_record">
<SearchRecord @handelDel="searchHistoryDel" :headerRightDelete="true" searchRecordTitle="历史搜索"
:dataList="searchHistoryList" @handelSearchRecord="handelSearchRecord" />
</view>
</view>
</view>
<view class="search_books_body" v-else>
<view class="search_books_list">
<view class="search_books_list_item" v-for="m in searchBooksData" :key="m.id">
<CommBookItemThree :bookTips="m.category_name" :bookName="m.title" :bookImage="m.cover"
:bookIntroduction="m.intro" :bookId="m.id" :bookcase="bookcase"
@addBookshelf="addBookshelf" />
</view>
</view>
</view>
</view>
<view v-else>
<u-empty :icon="search_empty" width="504rpx" text="未找到小说,正在努力产出中..." />
</view>
</view>
</template>
<script>
import SearchRecord from './searchRecord.vue'
import CommBookItemThree from '@/components/commBookItemThree/index.vue'
import search_empty from '@/static/images/search_empty.png'
import {
myGetStorage,
mySetStorage
} from '@/utils/storage/index.js'
import {
baseUrlImage
} from '@/utils/utils'
export default {
components: {
SearchRecord,
CommBookItemThree
},
data() {
return {
search_empty: search_empty,
searchRecordList: [],
searchFlag: false,
bookKeyword: '',
searchHistoryList: [],
searchBooksData: [],
bookcase: 0
}
},
onLoad() {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
uni.$u.http.post('/getSearchTags', {}, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
module
} = res.data;
this.searchRecordList = module;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
this.getAndSetSearchHistory();
},
methods: {
searchHistoryDel() {
mySetStorage('searchHistory', JSON.stringify([]));
this.searchHistoryList = [];
},
getSearchBooks(keyword) {
if (!keyword) {
uni.showToast({
title: '请先输入您想看的小说',
icon: 'none'
})
return;
}
uni.showLoading({
title: '搜索中...'
});
const data = {
keyword,
}
uni.$u.http.post('/getSearch', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
module,
bookcase
} = res.data;
// this.searchRecordList = module;
this.bookcase = bookcase;
this.searchBooksData = baseUrlImage([module]);
this.getAndSetSearchHistory(keyword);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
handelSearch() {
const bookKeyword = this.bookKeyword;
this.getSearchBooks(bookKeyword);
},
getAndSetSearchHistory(keyword) {
const searchHistoryList = myGetStorage('searchHistory') || '[]';
const list = JSON.parse(searchHistoryList);
let temp = list;
if (keyword) {
temp = [{
id: Math.random(),
title: keyword
}, ...list]
if (temp.length > 10) {
temp.splice(11, temp.length - 10)
}
mySetStorage('searchHistory', JSON.stringify(temp))
}
this.searchHistoryList = temp
},
handelSearchRecord(event) {
const title = event.currentTarget.dataset.title;
this.bookKeyword = title;
this.getSearchBooks(title);
},
addBookshelf() {
this.bookcase = 1;
},
clearBookKeyword() {
this.searchBooksData = [];
}
}
}
</script>
<style lang="scss" scoped>
.booksSearchList_content {
width: 100%;
box-sizing: border-box;
padding: 32rpx;
.step_search_box {
width: 100%;
.search_box_con {
display: flex;
align-items: center;
background-color: #F3F4F6;
border-radius: 40rpx;
.search_button {
display: flex;
justify-content: center;
align-items: center;
width: 136rpx;
height: 80rpx;
line-height: 80rpx;
background-color: #FF728F;
border-radius: 40rpx;
font-size: 36rpx;
color: #fff;
}
}
}
.search_record_box {
width: 100%;
.search_popular_record {
width: 100%;
padding: 32rpx 0;
}
}
.search_history_box {
width: 100%;
.search_history_record {
width: 100%;
padding: 32rpx 0;
}
}
.search_books_body {
width: 100%;
.search_books_list {
width: 100%;
.search_books_list_item {
margin-top: 32rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,98 @@
<template>
<view class="searchRecord_content">
<view class="searchRecord_content_header">
<view class="_header_title">
{{searchRecordTitle}}
</view>
<view class="_header_right">
<view class="_header_right_delete_icon" v-if="headerRightDelete" @tap="handelDelSearch">
<!-- delete_icon.png -->
<image class="is_image" src="/static/images/delete_icon.png"></image>
</view>
</view>
</view>
<view class="searchRecord_list">
<view class="searchRecord_list_item" v-for="m in dataList" :key="m.id" :data-title="m.title" @tap="handelSearchRecord">
<text>{{m.title}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
searchRecordTitle: {
type: String,
default: '热门搜索'
},
headerRightDelete: {
type: Boolean,
default: false
},
dataList: {
type: Array,
default: []
}
},
data() {
return {
}
},
methods: {
handelDelSearch() {
this.$emit('handelDel')
},
handelSearchRecord(e) {
this.$emit('handelSearchRecord',e)
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: flex;
width: 100%;
height: 100%;
}
.searchRecord_content {
width: 100%;
.searchRecord_content_header {
width: 100%;
display: flex;
justify-content: space-between;
._header_title {
font-size: 30rpx;
color: #666666;
}
._header_right_delete_icon {
width: 40rpx;
height: 40rpx;
}
}
.searchRecord_list {
display: flex;
flex-wrap: wrap;
width: 100%;
.searchRecord_list_item {
height: 56rpx;
line-height: 56rpx;
padding: 0 16rpx;
background-color: #F3F4F6;
color: #333333;
font-size: 28rpx;
border-radius: 12rpx;
margin-top: 30rpx;
margin-right: 30rpx;
}
}
}
</style>

View File

@ -0,0 +1,388 @@
<template>
<view class="booksTheCharts_content">
<u-navbar title="排行榜" bgColor="transparent" leftIconColor="#000" @leftClick="navbarLeftClick"
:placeholder="true" :safeAreaInsetTop="true" />
<!-- <uni-nav-bar title="排行榜" :border="false" backgroundColor="transparent" leftIcon="back" @clickLeft="navbarLeftClick">
</uni-nav-bar> -->
<view class="booksTheCharts_header_bag"></view>
<!-- :style="`height:${booksTheChartsContentHeigth}px`"-->
<view class="booksTheCharts_content_body">
<view class="booksTheCharts_body_btn_list">
<scroll-view scroll-x="true" class="btn_list_scroll_view">
<view :class="[`btn_list_scroll_view_item`,oneTitleActive == m.id ?'active':''] "
v-for="m in oneTitleList" :key="m.id" :data-id="m.id" @tap="handelOneTitle">{{m.title}}</view>
</scroll-view>
</view>
<view class="booksTheCharts_main_body">
<view class="_main_body_title_list">
<!-- :style="`height:${titleListscroll}px`" -->
<scroll-view scroll-y="true" class="_title_list_scroll_view">
<view :class="['_title_list_scroll_view_item',m.id == twoTitleActive ? 'active':'']"
v-for="(m,idx) in twoTitleList" :key="m.id" :data-id="m.id" @tap="handelTwoTitle">
{{m.name}}
</view>
</scroll-view>
</view>
<view class="_main_body_book_list">
<!-- :style="`height:${titleListscroll}px`" -->
<scroll-view scroll-y="true" class="_book_list_scroll_view">
<view :class="['_book_list_scroll_view_item']" v-for="(m,idx) in booksList" :key="m.id"
@tap="toBooksReadingDetail(m)">
<view class="scroll_view_item_book_image">
<image class="is_image" :src="m.cover"></image>
</view>
<view class="scroll_view_item_book_tips">
<view class="_book_tips_title">
{{m.title}}
</view>
<view class="_book_tips_msg">
{{m.category_name}}
</view>
</view>
</view>
<!-- <view class="_book_list_scroll_view_empty">
<CommFooter />
</view> -->
</scroll-view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
isGetSystemInfo
} from '@/utils/systemInfo.js'
import CommFooter from '@/components/commFooter/index.vue'
import {
baseUrlImage
} from '@/utils/utils'
export default {
components: {
CommFooter
},
data() {
return {
booksTheChartsContentHeigth: 0,
titleListscroll: 0,
booksList: [],
oneTitleList: [],
twoTitleList: [{
id: '0',
name: '全部'
},
{
id: '1',
name: '人气榜'
},
{
id: '2',
name: '畅销版'
},
{
id: '3',
name: '新书榜'
},
{
id: '4',
name: '完结版'
}
],
twoTitleActive: '0',
oneTitleActive: '0',
}
},
onLoad(options) {
const {
windowHeight,
screenHeight,
statusBarHeight,
devicePixelRatio
} = isGetSystemInfo();
this.booksTheChartsContentHeigth = screenHeight - statusBarHeight;
this.twoTitleActive = options.chartsType ? options.chartsType : '0';
// #ifdef APP-PLUS
this.titleListscroll = screenHeight - statusBarHeight;
// #endif
// #ifdef H5 || MP-WEIXIN
this.titleListscroll = screenHeight - statusBarHeight - devicePixelRatio * 55;
// #endif
},
onShow() {
//
uni.showLoading({
title: '加载中...'
});
const data = {}
uni.$u.http.post('/getCategory', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const list = res.data.list;
this.oneTitleList = [{
id: '0',
title: '全部'
}, ...list];
}
this.getBooks(this.twoTitleActive, 0);
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
this.getBooks(this.twoTitleActive, 0);
})
},
methods: {
navbarLeftClick() {
uni.navigateBack()
},
getBooks(type, category_id) {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
const data = {
type,
category_id,
}
uni.$u.http.post('/getChartsCategory', data, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
module
} = res.data;
this.booksList = baseUrlImage(module);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
handelTwoTitle(event) {
const id = event.currentTarget.dataset.id;
this.twoTitleActive = id;
this.getBooks(id, this.oneTitleActive);
},
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
handelOneTitle(event) {
const id = event.currentTarget.dataset.id;
this.oneTitleActive = id;
this.getBooks(this.twoTitleActive, id);
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
::v-deep.u-navbar__content__title {
font-size: 32rpx;
font-weight: 700;
}
.booksTheCharts_content {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
.uni-navbar {
position: relative;
z-index: 20;
}
.booksTheCharts_header_bag {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 330rpx;
background: linear-gradient(to left bottom, rgba(252, 194, 202, 0.5), rgba(253, 255, 227, 0.5));
}
.booksTheCharts_content_body {
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
.booksTheCharts_body_btn_list {
display: flex;
align-items: center;
width: 100%;
height: 110rpx;
box-sizing: border-box;
padding: 0 32rpx;
flex: 0 0 auto;
position: relative;
.btn_list_scroll_view {
white-space: nowrap;
.btn_list_scroll_view_item {
display: inline-block;
background-color: transparent;
height: 64rpx;
padding: 0 16rpx;
color: #222222;
line-height: 64rpx;
margin-left: 16rpx;
border-radius: 16rpx;
}
.btn_list_scroll_view_item.active {
background-color: #FF728F;
color: #fff;
}
.btn_list_scroll_view_item:first-child {
margin-left: 0;
}
}
}
.booksTheCharts_main_body {
flex: 1;
display: flex;
width: 100%;
border-top: 2rpx solid #E5E5E5;
position: relative;
z-index: 10;
box-sizing: border-box;
._main_body_title_list {
width: 160rpx;
height: 100%;
background-color: #F1EEEC;
flex: 0 0 auto;
position: relative;
._title_list_scroll_view {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
._title_list_scroll_view_item {
position: relative;
width: 100%;
height: 124rpx;
text-align: center;
line-height: 124rpx;
color: #666666;
font-size: 32rpx;
}
._title_list_scroll_view_item.active {
background-color: #fff;
color: #FF728F;
}
._title_list_scroll_view_item.active::before {
position: absolute;
top: 0;
left: 0;
content: '';
width: 6rpx;
height: 124rpx;
background-color: #FF728F;
}
}
}
._main_body_book_list {
width: 100%;
height: 100%;
background-color: #fff;
position: relative;
._book_list_scroll_view {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 32rpx 32rpx 0;
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom);
/* 兼容 iPhone X 及以上设备 */
box-sizing: border-box;
._book_list_scroll_view_item {
display: flex;
width: 100%;
padding-bottom: 32rpx;
.scroll_view_item_book_image {
width: 128rpx;
height: 170rpx;
flex: 0 0 auto;
border-radius: 8rpx;
overflow: hidden;
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
}
.scroll_view_item_book_tips {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
padding-left: 28rpx;
overflow: hidden;
._book_tips_title {
font-size: 30rpx;
line-height: 1;
color: #1A1A1A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._book_tips_msg {
font-size: 28rpx;
line-height: 1;
color: #999999;
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
._book_list_scroll_view_empty {
width: 100%;
height: 60rpx;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,488 @@
<template>
<view class="bookshelfListBody_content">
<view class="bookshelfListBody_content_header">
<view class="_header_left">
<view class="_header_name" v-if="!swipeActionBatch">
列表
</view>
<view class="_header_name" v-else-if="swipeActionBatch">
<u-checkbox-group @change="handelbookBatch" v-model="delCheckedAll">
<u-checkbox activeColor="#FF728F" labelSize="32rpx" labelColor="#1A1A1A" label="全选"
name="all" />
</u-checkbox-group>
</view>
</view>
<view class="_header_right">
<view class="_header_right_edit" @tap="handelSwipeBatch" v-if="!swipeActionBatch">
批量编辑
</view>
<view class="_header_right_confim" v-else-if="swipeActionBatch" @tap="bathComplete">
完成
</view>
</view>
</view>
<view class="bookshelfListBody_content_body">
<view class="_content_body_list">
<view class="_swipe_action_box" @longpress="swipeActionLongpress(m)" v-for="m in bookshelfList"
:key="m.id">
<view class="_swipe_action_box_book_image">
<image class="is_image" :src="m.cover" />
</view>
<view class="_swipe_action_book_info">
<view class="_book_info_title">
{{m.title}}
</view>
<view class="_book_info_chapter">
{{m.history_txt}}
</view>
<view class="_book_info_tips">
{{m.txt}}
</view>
</view>
<view class="_swipe_action_book_button" v-if="swipeActionList.indexOf(m.id) == -1">
<view class="_book_button_text" v-if="!swipeActionBatch" @tap="toNovelReading(m)">
去阅读
</view>
<view class="_book_button_checkbox_box" v-else-if="swipeActionBatch">
<u-checkbox-group @change="handelcheckbox($event,m)" v-model="m.checkedFlag">
<u-checkbox :name="m.id" activeColor="#FF728F" />
</u-checkbox-group>
</view>
</view>
<view class="_swipe_action_book_del" v-else @tap="deleteBook(m)">
删除
</view>
</view>
<!-- <view class="_swipe_action_box" @longpress="swipeActionLongpress(m)" v-for="m in bookshelfList"
:key="m.id">
<fui-swipe-action @click="onClick">
<view class="_swipe_action_box_book_image">
<image class="is_image" :src="m.cover" />
</view>
<view class="_swipe_action_book_info">
<view class="_book_info_title">
{{m.title}}
</view>
<view class="_book_info_chapter">
{{m.history_txt}}
</view>
<view class="_book_info_tips">
{{m.txt}}
</view>
</view>
<view class="_swipe_action_book_button" v-if="swipeActionList.indexOf(m.id) == -1">
<view class="_book_button_text" v-if="!swipeActionBatch" @tap="toNovelReading(m)">
去阅读
</view>
<view class="_book_button_checkbox_box" v-else-if="swipeActionBatch">
<u-checkbox-group @change="handelcheckbox($event,m)" v-model="m.checkedFlag">
<u-checkbox :name="m.id" activeColor="#FF728F" />
</u-checkbox-group>
</view>
</view>
<view class="_swipe_action_book_del" v-else @tap="deleteBook(m)">
删除
</view>
</fui-swipe-action>
</view> -->
<view class="_swipe_action_box" @tap="toBookCity">
<view class="_swipe_action_add_img_box">
<view class="_swipe_action_add_img">
<image class="is_image" src="/static/images/bookshelf/_swipe_add.png" />
</view>
</view>
<view class="_swipe_action_no_tips">
去找书
</view>
</view>
</view>
</view>
<u-popup :show="swipeActionBatch" mode="bottom" :overlay="false" bgColor="transparent" zIndex="999"
:safeAreaInsetBottom="false">
<view class="bookshelf_checked_all_del" @tap="checkedAllDel">
<view class="_all_del_button">
<image v-if="booksIds.length" class="is_image" src="/static/images/bookshelf/del_all.png" />
<image v-else class="is_image" src="/static/images/bookshelf/del_all_checked.png"></image>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import config from '@/config/index';
import {
isGetSystemInfo
} from '@/utils/systemInfo.js'
export default {
data() {
return {
swipeActionList: [],
swipeActionBatch: false,
bookshelfList: [],
delCheckedAll: [],
booksIds: [],
// options1: [{
// text: '',
// style: {
// backgroundColor: '#FF728F'
// }
// }],
}
},
mounted() {
const {
windowHeight = 0, screenHeight = 0, windowTop = 0
} = isGetSystemInfo();
const footerSafeHeight = screenHeight - windowHeight - windowTop;
if (footerSafeHeight) {
this.footerSafeHeight = footerSafeHeight;
}
},
methods: {
getBooksData() {
// uni.showLoading({
// title: '...'
// });
const data = {}
uni.$u.http.post('/getBookshelf', data).then((res) => {
// setTimeout(() => {
// uni.hideLoading();
// }, 1000);
if (res.status == 1) {
const {
module
} = res.data;
if (Array.isArray(module)) {
this.bookshelfList = module.map((m, idx) => {
return {
...m,
cover: `${config.baseUrl}${m.cover}`,
checkedFlag: [],
}
});
} else {
this.bookshelfList = [];
}
}
}).catch((err) => {
// setTimeout(() => {
// uni.hideLoading();
// }, 1000);
console.log(err, "========")
})
},
//
swipeActionLongpress(row) {
if (!this.swipeActionBatch) {
// setTimeout(() => {
// uni.hideTabBar({
// animation: true
// })
// this.swipeActionBatch = true;
// this.swipeActionList = [];
// this.$emit('bookshelfContentBodyZindexFn', 999);
// }, 1000)
// const swipeActionList = [...this.swipeActionList];
// if (swipeActionList.indexOf(row.id) != -1) {
// this.swipeActionList = swipeActionList.filter((m) => m != row.id);;
// } else {
// this.swipeActionList = [...swipeActionList, row.id];
// }
}
},
//
handelSwipeBatch() {
uni.hideTabBar({
animation: true
})
this.swipeActionBatch = true;
this.swipeActionList = [];
this.$emit('bookshelfContentBodyZindexFn', 999);
},
//
toBookCity() {
uni.reLaunch({
url: '/pages/bookCity/bookCity/index'
});
},
//
deleteBook(row) {
this.handelDeleteBookFn([row.id]);
},
//
handelbookBatch(isCheckeds) {
this.delCheckedAll = isCheckeds;
const bookshelfList = [...this.bookshelfList];
const ids = [];
this.bookshelfList = bookshelfList.map((m) => {
ids.push(m.id);
return {
...m,
checkedFlag: isCheckeds.length ? [m.id] : [],
}
})
this.booksIds = ids;
},
handelcheckbox(e, row) {
const booksIds = [...this.booksIds];
if (e.length) {
this.booksIds = [...booksIds, row.id];
this.delCheckedAll = this.booksIds.length == this.bookshelfList.length ? ['all'] : [];
} else {
this.delCheckedAll = [];
this.booksIds = booksIds.filter((m) => m != row.id);
}
},
handelDeleteBookFn(ids, allType = false) {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
const data = {
ids: JSON.stringify(ids),
}
uni.$u.http.post('/delBookshelf', data, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
this.getBooksData();
if (allType) {
this.bathComplete();
}
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
checkedAllDel() {
this.handelDeleteBookFn(this.booksIds, true);
},
//
bathComplete() {
this.swipeActionBatch = false;
uni.showTabBar({
animation: true
})
this.delCheckedAll = [];
this.booksIds = [];
this.$emit('bookshelfContentBodyZindexFn', 2);
const bookshelfList = [...this.bookshelfList];
this.bookshelfList = bookshelfList.map((m) => {
return {
...m,
checkedFlag: [],
}
})
},
toNovelReading(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.sid}&t=${row.title}`
})
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
::v-deep.u-checkbox {
margin-bottom: 0;
margin-top: 0;
}
.bookshelfListBody_content {
width: 100%;
.bookshelfListBody_content_header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
height: 40rpx;
._header_left {
._header_name {
font-size: 32rpx;
line-height: 1;
color: #1A1A1A;
}
}
._header_right {
._header_right_edit {
font-size: 28rpx;
line-height: 1;
color: #929292;
}
._header_right_confim {
font-size: 32rpx;
line-height: 1;
color: #1A1A1A;
}
}
}
.bookshelfListBody_content_body {
width: 100%;
._content_body_list {
width: 100%;
// .bookshelf_list_swipe_action {
// width: 100%;
._swipe_action_box {
display: flex;
width: 100%;
height: 192rpx;
overflow: hidden;
position: relative;
margin-top: 32rpx;
margin-bottom: 32rpx;
._swipe_action_box_book_image {
width: 144rpx;
height: 192rpx;
flex: 0 0 auto;
border-radius: 8rpx;
overflow: hidden;
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
}
._swipe_action_book_info {
flex: 1;
display: flex;
flex-direction: column;
padding-left: 28rpx;
padding-top: 16rpx;
padding-bottom: 16rpx;
flex-shrink: 0;
._book_info_title {
width: 100%;
font-size: 32rpx;
line-height: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #1A1A1A;
}
._book_info_chapter {
width: 100%;
font-size: 26rpx;
line-height: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #6F6F6F;
margin-top: 36rpx;
}
._book_info_tips {
width: 100%;
font-size: 24rpx;
line-height: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #999999;
margin-top: 20rpx;
}
}
._swipe_action_book_button {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100rpx;
height: 100%;
flex: 0 0 auto;
._book_button_text {
font-size: 28rpx;
color: #FF728F;
line-height: 1;
}
}
._swipe_action_book_del {
position: absolute;
top: 0;
right: 0;
width: 100rpx;
height: 192rpx;
text-align: center;
line-height: 192rpx;
color: #ffffff;
background-color: #FF728F;
font-size: 28rpx;
}
._swipe_action_add_img_box {
display: flex;
justify-content: center;
align-items: center;
width: 144rpx;
height: 192rpx;
flex: 0 0 auto;
background-color: #F6F6F6;
._swipe_action_add_img {
width: 42rpx;
height: 42rpx;
}
}
._swipe_action_no_tips {
flex: 1;
display: flex;
align-items: center;
padding-left: 28rpx;
font-size: 32rpx;
color: #AAAAAA;
}
}
// }
}
}
.bookshelf_checked_all_del {
// position: fixed;
// bottom: 0;
// left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 130rpx;
z-index: 1000;
background-color: #fff;
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom);
._all_del_button {
width: 150rpx;
height: 56rpx;
}
}
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<view class="bookshelf_content">
<CommNavBar :navBarList="navBarList" @navBarClick="handelCommNavBar" :navBarActive="navBarActive" />
<view class="bookshelf_content_body" :style="`z-index:${bookshelfContentBodyZindex}`">
<scroll-view scroll-y="true" class="scroll_y">
<view class="scroll_y_item">
<view class="bookshelf_content_sign_in_box" @tap="toSignInBookCurrency">
<view class="_sign_in_box_tips">
<view class="_sign_in_text">
<text>本周已连续签到</text>
<text class="_sign_in_Days">{{totalNum}}</text>
<text></text>
</view>
</view>
</view>
<view class="bookshelf_list_body">
<BookshelfListBody @bookshelfContentBodyZindexFn="bookshelfContentBodyZindexFn"
ref="BookshelfListBody" />
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import CommNavBar from '@/components/commNavBar/index.vue'
import BookshelfListBody from './bookshelfListBody.vue'
export default {
components: {
CommNavBar,
BookshelfListBody
},
data() {
return {
navBarList: [{
id: '1',
name: '书架'
}],
navBarActive: '1',
totalNum: 0,
bookshelfContentBodyZindex: 2
}
},
onShow() {
uni.$u.http.post('/getSigInfo', {}).then((res) => {
if (res.status == 1) {
const {
totalNum,
} = res.data;
this.totalNum = totalNum;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "errerr")
})
this.$nextTick(() => {
this.$refs.BookshelfListBody.getBooksData()
})
},
methods: {
handelCommNavBar() {
},
toSignInBookCurrency() {
uni.navigateTo({
url: `/pages/signInBookCurrency/index`
})
},
bookshelfContentBodyZindexFn(z) {
this.bookshelfContentBodyZindex = z;
}
}
}
</script>
<style lang="scss">
page {
height: 100%;
}
.is_image {
display: block;
width: 100%;
height: 100%;
}
.bookshelf_content {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
// padding-bottom: 40rpx;
box-sizing: border-box;
overflow: hidden;
.bookshelf_content_body {
flex: 1;
width: 100%;
height: 100%;
position: relative;
z-index: 996;
.scroll_y {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
.scroll_y_item {
// padding-bottom: 40rpx;
.bookshelf_content_sign_in_box {
width: 100%;
padding: 0 32rpx 32rpx;
box-sizing: border-box;
._sign_in_box_tips {
position: relative;
width: 100%;
height: 146rpx;
background: url('/static/images/bookshelf/_sign_in.png') no-repeat;
background-size: 100% 100%;
._sign_in_text {
position: absolute;
left: 40rpx;
bottom: 22rpx;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.6);
._sign_in_Days {
color: #fff;
margin: 0 6rpx;
font-weight: 600;
}
}
}
}
.bookshelf_list_body {
width: 100%;
padding: 10rpx 32rpx 32rpx;
box-sizing: border-box;
// background-color: #fff;
}
}
}
}
}
</style>

View File

@ -0,0 +1,227 @@
<template>
<view class="classification_content">
<CommNavBar :navBarList="navBarList" @navBarClick="handelCommNavBar" :navBarActive="navBarActive" />
<view class="classification_content_body">
<view class="classification_body_btn_list">
<!-- <u-tabs :list="oneTitleList" lineColor="#FF728F" :inactiveStyle="inactiveStyle"></u-tabs> -->
<scroll-view scroll-x="true" class="btn_list_scroll_view">
<view :class="[`btn_list_scroll_view_item`,oneTitleActive == m.id?'active':''] "
v-for="m in oneTitleList" :key="m.id" :data-id="m.id" @tap="handelOneTitle">{{m.name}}
</view>
</scroll-view>
</view>
<view class="classification_body_book_list">
<scroll-view scroll-y="true" class="scroll_y">
<view class="scroll_y_item">
<view class="_book_list_box">
<view class="_book_list_box_con_item" v-for="m in searchBooksList" :key="m.is"
@tap="toBooksReadingDetail(m)">
<CommBookLeftRigth :bookTips="m.category_name" :bookName="m.title" :bookImage="m.cover"
:bookIntroduction="m.intro" />
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import CommNavBar from '@/components/commNavBar/index.vue'
import CommBookLeftRigth from '@/components/commBookLeftRigth/index.vue'
import {
baseUrlImage
} from '@/utils/utils';
const inactiveStyle = {
color: '#222222',
fontSize:'32rpx'
}
export default {
components: {
CommNavBar,
CommBookLeftRigth
},
data() {
return {
navBarList: [{
id: '1',
name: '分类'
}],
navBarActive: '1',
searchBooksList: [],
oneTitleActive: 0,
oneTitleList: [],
inactiveStyle: inactiveStyle
}
},
onShow() {
//
// uni.showLoading({
// title: '...'
// });
const data = {}
uni.$u.http.post('/getCategory', data).then((res) => {
uni.hideLoading();
if (res.status == 1 && Array.isArray(res.data.list)) {
const list = res.data.list.map((m) => {
return {
...m,
name: m.title,
}
});
this.oneTitleList = [{
id: '0',
name: '全部',
}, ...list];
}
this.getBooks(0, 0);
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
this.getBooks(0, 0);
})
},
methods: {
handelCommNavBar() {
},
getBooks(type, category_id) {
// uni.showLoading({
// title: '...'
// });
const parameter = {
custom: {
token: true
}
}
const data = {
type,
category_id,
}
uni.$u.http.post('/getChartsCategory', data, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
module
} = res.data;
this.searchBooksList = baseUrlImage(module);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
handelOneTitle(event) {
const id = event.currentTarget.dataset.id;
this.oneTitleActive = id;
this.getBooks(0, id);
},
toBooksReadingDetail(row) {
uni.navigateTo({
url: `/pages/booksReadingDetail/booksReadingDetail?sid=${row.id}&t=${row.title}`
})
},
}
}
</script>
<style lang="scss">
.classification_content {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
// padding-bottom: 150rpx;
box-sizing: border-box;
overflow: hidden;
.classification_content_body {
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
// padding: 32rpx 0;
box-sizing: border-box;
position: relative;
z-index: 2;
.classification_body_btn_list {
width: 100%;
padding: 0 32rpx 32rpx;
box-sizing: border-box;
.btn_list_scroll_view {
white-space: nowrap;
.btn_list_scroll_view_item {
display: inline-block;
background-color: transparent;
height: 64rpx;
padding: 0 16rpx;
color: #222222;
line-height: 64rpx;
margin-left: 16rpx;
border-radius: 16rpx;
}
.btn_list_scroll_view_item.active {
background-color: #FF728F;
color: #fff;
}
.btn_list_scroll_view_item:first-child {
margin-left: 0;
}
}
}
.classification_body_book_list {
width: 100%;
box-sizing: border-box;
flex: 1;
position: relative;
// background: #fff;
.scroll_y {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0 32rpx;
box-sizing: border-box;
.scroll_y_item {
._book_list_box {
width: 100%;
// display: flex;
// margin-top: 32rpx;
padding-bottom: 40rpx;
._book_list_box_con_item {
padding: 32rpx 0;
border-bottom: 2rpx solid #E5E5E5;
}
._book_list_box_con_item:first-child {
padding-top: 0;
}
._book_list_box_con_item:last-child {
border-bottom: none;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<view class="giveCoinDetail_content">
<view class="give_list_body">
<view class="give_list_item">
<view class="give_list_item_header">
<view class="item_header_time">
2022-06
</view>
</view>
<view class="give_list_item_con">
<view class="_item_con_give_record">
<view class="give_record_item">
<view class="record_item_title">
充值赠送金币
</view>
<view class="record_item_num">
+6000
</view>
</view>
<view class="give_record_item mt16rpx">
<view class="record_item_time">
2022-06-24 21:06:54
</view>
<view class="record_item_become_due">
到期时间06-29
</view>
</view>
</view>
<view class="_item_con_give_record">
<view class="give_record_item">
<view class="record_item_title">
充值赠送金币
</view>
<view class="record_item_num">
+6000
</view>
</view>
<view class="give_record_item mt16rpx">
<view class="record_item_time">
2022-06-24 21:06:54
</view>
<view class="record_item_become_due">
到期时间06-29
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
page {
background-color: #F6F6F6;
}
.mt16rpx {
margin-top: 16rpx;
}
.giveCoinDetail_content {
width: 100%;
box-sizing: border-box;
padding: 0 32rpx 32rpx;
.give_list_body {
width: 100%;
.give_list_item {
width: 100%;
.give_list_item_header {
width: 100%;
padding: 24rpx 0;
.item_header_time {
font-size: 32rpx;
color: #1A1A1A;
}
}
.give_list_item_con {
width: 100%;
background-color: #fff;
border-radius: 8rpx;
._item_con_give_record {
width: 100%;
padding: 24rpx;
box-sizing: border-box;
.give_record_item {
display: flex;
justify-content: space-between;
line-height: 1;
.record_item_title {
font-size: 30rpx;
color: #1A1A1A;
// font-weight: 600;
}
.record_item_num {
font-size: 30rpx;
color: #FF728F;
}
.record_item_time {
font-size: 22rpx;
color: #666666;
}
.record_item_become_due {
font-size: 22rpx;
color: #1A1A1A;
}
}
}
._item_con_give_record {
border-bottom: 2rpx solid #EEEEEE;
}
._item_con_give_record:last-child {
border-bottom: none;
}
}
}
}
}
</style>

View File

@ -0,0 +1,166 @@
<template>
<view class="initialization_content">
<view class="initialization_body">
<view class="app_logo">
<image src="/static/app_logo.png" class="is_image"></image>
</view>
<view class="app_title">
古言小说
</view>
</view>
<view class="initialization_footer">
<!-- <view class="app_title">
古言小说
</view> -->
</view>
<u-modal :show="modalShowOne" title="欢迎使用" :showCancelButton="true" cancelColor="#999" confirmText="同意并继续"
cancelText="不同意" confirmColor="#FF728F" @confirm="toAgreeWith" @cancel="handelOnceMore">
<view class="slot_content">
<text>感谢您信任并使用古言小说本服务需联网申请通知权限用于为您提供书籍更新优惠活动等信息服务点击同意即表示您同意上述内容及</text>
<text class="user_agreement" @tap="toAgreement('1')">古言用户服务协议</text>
<text></text>
<text class="privacy" @tap="toAgreement('2')">古言隐私政策</text>
</view>
</u-modal>
<u-modal :show="modalShowTwo" title="您需要同意以下协议才能正常使用古言" :showCancelButton="true" cancelColor="#999"
confirmText="同意" cancelText="不同意并退出" confirmColor="#FF728F" @confirm="toAgreeWith"
@cancel="toExitApplication">
<view class="slot_content">
<view>若您不同意很遗憾我们将无法为您提供服务</view>
<view class="user_agreement" @tap="toAgreement('1')">古言用户服务协议</view>
<view class="privacy" @tap="toAgreement('2')">古言隐私政策</view>
</view>
</u-modal>
</view>
</template>
<script>
import {
myGetStorage,
mySetStorage
} from '@/utils/storage/index.js';
export default {
data() {
return {
giveService: false,
modalShowOne: false,
modalShowTwo: false
}
},
onShow() {
const giveService = myGetStorage('giveService');
this.giveService = giveService ? false : true;
this.modalShowOne = giveService ? false : true;
if (giveService) {
setTimeout(() => {
uni.switchTab({
url: `/pages/bookCity/bookCity/index`
})
}, 1000)
}
},
methods: {
toAgreeWith() {
setTimeout(() => {
uni.switchTab({
url: `/pages/bookCity/bookCity/index`
})
}, 300)
mySetStorage('giveService', 1);
this.modalShowOne = false;
this.modalShowTwo = false;
},
toExitApplication() {
if (uni.getSystemInfoSync().platform == 'ios') {
plus.ios.import("UIApplication").sharedApplication().performSelector("exit")
} else if (uni.getSystemInfoSync().platform == 'android') {
plus.runtime.quit();
}
},
toAgreement(type) {
uni.navigateTo({
url: `/pages/agreement/agreement?type=${type}`
})
},
handelOnceMore() {
this.modalShowOne = false;
this.modalShowTwo = true;
}
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
border-radius: 16rpx;
box-shadow: 0 0 16rpx rgba(0, 0, 0, 0.2);
}
.initialization_content {
width: 100%;
height: 100%;
position: relative;
background: linear-gradient(to bottom, #FFC7D3 0%, #FFEBEE 50%, #fff 100%);
.initialization_body {
padding-top: 260rpx;
display: flex;
flex-direction: column;
align-items: center;
// .app_title_image {
// width: 200rpx;
// height: 400rpx;
// }
.app_logo {
width: 160rpx;
height: 160rpx;
}
.app_title {
font-size: 60rpx;
font-weight: 600;
margin-left: 16rpx;
margin-top: 20rpx;
}
}
.initialization_footer {
// position: absolute;
// bottom: 180rpx;
// left: 0;
// display: flex;
// justify-content: center;
// align-items: center;
// width: 100%;
// .app_logo {
// width: 100rpx;
// height: 100rpx;
// }
// .app_title {
// font-size: 46rpx;
// font-weight: 600;
// margin-left: 16rpx;
// }
}
.slot_content {
font-size: 30rpx;
color: #999;
.user_agreement {
color: #FF728F;
}
.privacy {
color: #FF728F;
}
}
}
</style>

151
pages/login/login.vue Normal file
View File

@ -0,0 +1,151 @@
<template>
<view class="login_content">
<view class="login_content_bg" />
<u-navbar :autoBack="true" bgColor="transparent" :safeAreaInsetTop="true" :placeholder="true" />
<view class="login_content_body">
<view class="login_title">手机验证码登录</view>
<view class="login_tips">未注册的手机验证后自动创建账户</view>
<view class="login_mobile">
<u-input type="number" placeholder="请输入手机号码" border="node" clearable fontSize="44rpx" v-model="mobile">
<template slot='prefix'>
<text class="login_mobile_tips">+86</text>
</template>
</u-input>
</view>
<view :class="[`login_mobile_Code`, mobile.length == 11 ? '' : 'active']" @tap="handelLoginCode">
<text>获取验证码</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
mobile: "",
bookTitle:'',
bookSid :'',
chapterorder:'',
bookId:'',
toPath:''
};
},
onLoad(options) {
// this.bookTitle = options.t;
this.bookSid = options.sid;
this.chapterorder = options.c;
this.bookId = options.i;
this.toPath = options.to;
},
methods: {
handelLoginCode() {
const mobile = this.mobile;
// const bookTitle = this.bookTitle;
const bookSid = this.bookSid;
const chapterorder = this.chapterorder;
const bookId = this.bookId;
const toPath = this.toPath
if (mobile.length >= 11) {
const data = {
phone: mobile,
}
uni.showLoading({
title: '加载中...'
});
// uni.$u.post
uni.$u.http.post('/SendCode', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
uni.navigateTo({
url: `/pages/loginMobile/loginMobile?phone=${mobile}&sid=${bookSid}&i=${bookId}&c=${chapterorder}&to=${toPath}`
})
}
}).catch((err) => {
cosnole.log(err, "========")
uni.hideLoading();
})
}
}
}
};
</script>
<style lang="scss" scoped>
// ::v-deep.u-input__content {
/deep/.u-input__content {
height: 116rpx;
background-color: #fff;
border-radius: 58rpx;
}
// ::v-deep.u-input--square {
/deep/.u-input--square {
padding: 0 !important;
}
.login_content {
width: 100%;
height: 100%;
.login_content_bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 1056rpx;
background: url("/static/images/login_bg.png") no-repeat;
background-size: 100% 100%;
}
.login_content_body {
position: relative;
z-index: 2;
width: 100%;
padding: 40rpx 32rpx;
box-sizing: border-box;
.login_title {
font-size: 56rpx;
color: #1d242c;
line-height: 1;
}
.login_tips {
font-size: 28rpx;
color: #524e5c;
line-height: 1;
margin-top: 32rpx;
}
.login_mobile {
margin-top: 90rpx;
.login_mobile_tips {
margin: 0 32rpx;
font-size: 44rpx;
color: #1d242c;
}
}
.login_mobile_Code {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 116rpx;
line-height: 1;
background: linear-gradient(to left, #f27e49, #f25a14);
color: #fff;
font-size: 40rpx;
margin-top: 64rpx;
border-radius: 58rpx;
}
.login_mobile_Code.active {
background: #999999;
}
}
}
</style>

View File

@ -0,0 +1,167 @@
<template>
<view class="login_content">
<view class="login_content_bg" />
<u-navbar :autoBack="true" bgColor="transparent" :safeAreaInsetTop="true" :placeholder="true" />
<view class="login_content_body">
<view class="login_title">手机验证码登录</view>
<view class="login_tips">未注册的手机验证后自动创建账户</view>
<view class="login_mobile">
<u-input v-model="mobileCode" type="number" placeholder="请输入手机验证码" border="node" clearable
fontSize="44rpx">
<template #prefix>
<text class="login_mobile_tips"></text>
</template>
</u-input>
</view>
<view class="login_mobile_Code" @tap="confirmLogin">
<text>确认登录</text>
</view>
</view>
</view>
</template>
<script>
import {
mySetStorage
} from '@/utils/storage/index.js'
export default {
data() {
return {
mobileCode: '',
bookTitle: '',
bookSid: '',
chapterorder: '',
bookId: ''
}
},
onLoad(options) {
this.phone = options.phone;
// this.bookTitle = options.t;
this.bookSid = options.sid;
this.chapterorder = options.c;
this.bookId = options.i;
this.toPath = options.to;
},
methods: {
confirmLogin() {
const bookSid = this.bookSid;
const chapterorder = this.chapterorder;
const bookId = this.bookId;
const toPath = this.toPath;
let toPathUrl = ''
const toPathObj = {
'1': `/pages/novelReading/novelReading?sid=${bookSid}&id=${bookId}&c=${chapterorder}`,
'2': `/pages/myInfo/myInfo/index`,
'3': `/pages/bookCity/bookCity/index`
}
if (toPathObj[toPath]) {
toPathUrl = `${toPathObj[toPath]}`
} else {
toPathUrl = `/pages/bookCity/bookCity/index`
}
const data = {
phone: this.phone,
code: this.mobileCode
}
uni.showLoading({
title: '加载中...'
});
uni.$u.http.post('/Login', data).then((res) => {
uni.hideLoading();
const {
token,
uid
} = res.data;
if (res.status == 1) {
mySetStorage('token', token);
mySetStorage('uid', uid);
uni.reLaunch({
url: toPathUrl
})
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
}
}
}
</script>
<style lang="scss" scoped>
/deep/.u-input__content {
height: 116rpx;
background-color: #fff;
border-radius: 58rpx;
}
// ::v-deep
/deep/.u-input--square {
padding: 0 !important;
}
.login_content {
width: 100%;
height: 100%;
.login_content_bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 1056rpx;
background: url('/static/images/login_bg.png') no-repeat;
background-size: 100% 100%;
}
.login_content_body {
position: relative;
z-index: 2;
width: 100%;
padding: 40rpx 32rpx;
box-sizing: border-box;
.login_title {
font-size: 56rpx;
color: #1D242C;
line-height: 1;
}
.login_tips {
font-size: 28rpx;
color: #524E5C;
line-height: 1;
margin-top: 32rpx;
}
.login_mobile {
margin-top: 90rpx;
.login_mobile_tips {
margin: 0 32rpx;
font-size: 44rpx;
color: #1D242C;
}
}
.login_mobile_Code {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 116rpx;
line-height: 1;
background: linear-gradient(to left, #F27E49, #F25A14);
color: #fff;
font-size: 40rpx;
margin-top: 64rpx;
border-radius: 58rpx;
}
.login_mobile_Code.active {
background-color: #999999;
}
}
}
</style>

View File

@ -0,0 +1,23 @@
<template>
<view class="content">
<view class="version_info">
<view>当前版本</view>
<view>1.23</view>
</view>
</view>
</template>
<script>
</script>
<style lang="scss">
.content {
padding: 32rpx;
.version_info {
display: flex;
justify-content: space-between;
font-size: 36rpx;
}
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<view class="content">
<view class="step_user_info">
<view class="_info_box">
<MyUserInfo ref="MyUserInfo"/>
</view>
</view>
<!-- <view class="step_vip_info">
<CommVipInfo />
</view> -->
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<view class="step_recharge_grid_info">
<view class="rechargeGrid_box">
<rechargeGrid />
</view>
</view>
<view style="width: 100%">
<u-gap height="14rpx" bgColor="#F6F6F6"></u-gap>
</view>
<view class="step_other_info">
<view class="otherCellInfo_box">
<otherCellInfo />
</view>
</view>
</view>
</template>
<script>
import CommVipInfo from '@/components/commVipInfo/index.vue'
import MyUserInfo from './myUserInfo.vue'
import rechargeGrid from './rechargeGrid.vue'
import otherCellInfo from './otherCellInfo.vue'
export default {
components: {
CommVipInfo,
MyUserInfo,
rechargeGrid,
otherCellInfo
},
data() {
return {
}
},
onShow() {
this.$nextTick(() => {
this.$refs.MyUserInfo.isGetUserInfo()
})
},
methods: {}
}
</script>
<style lang="scss">
.image {
display: block;
width: 100%;
height: 100%;
}
.content {
background: #f6f6f6;
padding: 32rpx 0 0;
.step_user_info {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
._info_box {
width: 100%;
height: 348rpx;
background-color: #fff;
border-radius: 24rpx;
// border-radius: 24rpx 24rpx 0 0;
box-sizing: border-box;
padding: 32rpx 32rpx 56rpx;
}
}
.step_vip_info {
width: 100%;
padding: 0 32rpx;
margin-top: -30rpx;
box-sizing: border-box;
}
.step_recharge_grid_info {
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
padding: 32rpx;
margin-top: -2rpx;
.rechargeGrid_box {
width: 100%;
}
}
.step_other_info {
// margin-top: 26rpx;
background-color: #fff;
.otherCellInfo_box {
width: 100%;
}
}
}
</style>

View File

@ -0,0 +1,229 @@
<template>
<view class="myUserInfo_content">
<view class="myUserInfo_body">
<view class="_info_user_information">
<view class="_information_left">
<view class="_information_left_sculpture">
<image class="image" src="@/static/images/myInfo/default_sculpture.png"></image>
</view>
</view>
<view class="_information_right">
<view class="_information_right_name_box">
<view class="_information_right_name">{{userInfo.nickname}}</view>
<!-- <view class="_information_right_vip">
<image class="image" :src="usersVipImage"></image>
</view> -->
</view>
<view class="_information_right_userId">ID:{{userInfo.uid}}</view>
</view>
</view>
<view class="_info_box_money">
<view class="_money_coin_info">
<view class="_book_coin">
<view class="_book_coin_box">
<view class="_coin_num">
{{userInfo.egold || '0'}}
</view>
<view class="_coin_name" @tap="toBookCoinDetail">
书币
<u-icon name="arrow-right" size="24rpx" />
</view>
</view>
</view>
<view class="_book_coin">
<view class="_book_coin_box">
<view class="_coin_num">
{{userInfo.zb || '0'}}
</view>
<view class="_coin_name" @tap="toGiveCoinDetail">
赠币
<u-icon name="arrow-right" size="24rpx" />
</view>
</view>
</view>
</view>
<view class="_money_recharge_btn" @tap="toVoucherCenter">
<u-button type="primary" text="充值" shape="circle"
color="linear-gradient(to right, #FF2E53, #FF6086)" class="_money_up_button"></u-button>
</view>
</view>
</view>
<!-- <view class="">
<u-modal :show="showModal" title="提示" content='还未登录,请登录...' :showCancelButton="true" @cancel="modalCancel"
@confirm="modalConfirm" />
</view> -->
</view>
</template>
<script>
import usersVipImage from '@/static/images/myInfo/VIP.png';
import {
myGetStorage
} from '@/utils/storage/index.js'
export default {
data() {
return {
userInfo: {},
usersVipImage: usersVipImage,
showModal: false,
// /static/images/myInfo/VIP_active.png
}
},
methods: {
toBookCoinDetail() {
uni.navigateTo({
url: `/pages/bookCoinDetail/bookCoinDetail`
})
},
toGiveCoinDetail() {
uni.navigateTo({
url: `/pages/giveCoinDetail/giveCoinDetail`
})
},
toVoucherCenter() {
const token = myGetStorage('token');
if (token) {
uni.navigateTo({
url: `/pages/voucherCenter/index`
})
} else {
uni.navigateTo({
url: `/pages/login/login?to=2`
})
}
},
modalConfirm() {
uni.navigateTo({
url: `/pages/login/login`,
success: () => {
this.showModal = false;
}
})
},
isGetUserInfo() {
// uni.showLoading({
// title: '...'
// });
const data = {}
uni.$u.http.post('/getUserInfo', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const user = res.data.user
this.userInfo = user;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
}
}
}
</script>
<style lang="scss" scoped>
.image {
display: block;
width: 100%;
height: 100%;
}
.myUserInfo_content {
width: 100%;
height: 100%;
.myUserInfo_body {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
._info_user_information {
display: flex;
align-items: center;
._information_left {
._information_left_sculpture {
width: 120rpx;
height: 120rpx;
}
}
._information_right {
margin-left: 36rpx;
._information_right_name_box {
display: flex;
align-items: center;
._information_right_name {
font-size: 40rpx;
font-weight: 700;
line-height: 1;
max-width: 400rpx;
white-space: nowrap; //
overflow: hidden; //
text-overflow: ellipsis; //
}
._information_right_vip {
width: 36rpx;
height: 36rpx;
margin-left: 8rpx;
}
}
._information_right_userId {
font-size: 26rpx;
color: #888888;
margin-top: 16rpx;
}
}
}
._info_box_money {
display: flex;
justify-content: space-between;
align-items: center;
._money_coin_info {
flex: 1;
padding-right: 26rpx;
display: flex;
._book_coin {
flex: 1;
display: flex;
._book_coin_box {
display: flex;
flex-direction: column;
._coin_num {
font-size: 36rpx;
color: #FF728F;
margin-left: 18rpx;
}
._coin_name {
display: flex;
font-size: 26rpx;
color: #666666;
}
}
}
}
._money_recharge_btn {
width: 148rpx;
.u-button {
height: 66rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<view class="otherCellInfo_content">
<u-cell-group :border="false">
<u-cell v-for="(m,idx) in otherSteUpList" :key="idx" :title="m.title" isLink :border="false"
:titleStyle="m.titleStyle" size="large" :url="m.toPath" :icon="m.icon">
<!-- <template > -->
<!-- <u-icon :size="m.size" :name="m.icon" /> -->
<!-- <view solt="value" class="my_icon_box">
<image :src="m.icon" class="is_image" />
</view> -->
<!-- </template> -->
</u-cell>
</u-cell-group>
</view>
</template>
<script>
import myInfo_chat from '@/static/images/myInfo_chat.png';
import myInfo_setting from '@/static/images/myInfo_setting.png';
import myInfo_info_circle from '@/static/images/myInfo_info_circle.png';
export default {
data() {
return {
otherSteUpList: [{
title: '联系客服',
icon: myInfo_chat,
size: 26,
titleStyle: {
fontSize: '32rpx',
marginLeft: '16rpx'
}
},
{
title: '关于我们',
icon: myInfo_info_circle,
size: 26,
titleStyle: {
fontSize: '32rpx',
marginLeft: '16rpx'
},
toPath: '/pages/myInfo/aboutMy/index'
},
{
title: '设置',
icon: myInfo_setting,
size: 26,
titleStyle: {
fontSize: '32rpx',
marginLeft: '16rpx'
},
toPath: '/pages/myInfo/mySetUp/index'
},
]
}
}
}
</script>
<style lang="scss" scoped>
.is_image {
display: block;
width: 100%;
height: 100%;
}
.otherCellInfo_content {
.otherCellInfo {
width: 100%;
.my_icon_box {
width: 48rpx;
height: 48rpx;
}
}
}
</style>

View File

@ -0,0 +1,72 @@
<template>
<view class="rechargeGrid_content">
<u-grid :border="false" col="3">
<u-grid-item v-for="(m,listIndex) in rechargeGridList" :key="listIndex" @click="gridClick(m)">
<!-- <u-icon :customStyle="{paddingTop:20+'rpx'}" :name="listItem.name" :size="22"></u-icon> -->
<view class="_recharge_grid_image">
<image class="image" :src="m.imageSrc"></image>
</view>
<text class="_recharge_grid-text">{{m.title}}</text>
</u-grid-item>
</u-grid>
</view>
</template>
<script>
import browsingHistoryImage from '@/static/images/myInfo/browsingHistoryImage.png'
import rechargeHistoryImage from '@/static/images/myInfo/rechargeHistoryImage.png'
import bookCoinHistoryImage from '@/static/images/myInfo/bookCoinHistoryImage.png'
export default {
data() {
return {
rechargeGridList: [{
imageSrc: browsingHistoryImage,
title: '浏览记录',
toPath: '/pages/readingRecords/index'
},
{
imageSrc: rechargeHistoryImage,
title: '充值记录',
toPath: '/pages/voucherCenterDetail/index'
},
{
imageSrc: bookCoinHistoryImage,
title: '书币明细',
toPath: '/pages/bookCoinDetail/bookCoinDetail'
},
],
}
},
methods: {
gridClick(row) {
if (row.toPath) {
uni.navigateTo({
url: row.toPath
});
}
}
}
}
</script>
<style lang="scss" scoped>
.image {
display: block;
width: 100%;
height: 100%;
}
.rechargeGrid_content {
width: 100%;
._recharge_grid_image {
width: 64rpx;
height: 64rpx;
}
._recharge_grid-text {
margin-top: 20rpx;
}
}
</style>

View File

@ -0,0 +1,39 @@
<template>
<view class="content">
<view class="step_other_info">
<!-- url="/pages/componentsB/tag/tag" -->
<u-cell-group :border="false">
<u-cell v-for="(m,idx) in otherSteUpList" :key="idx" :title="m.title" isLink :border="false"
:titleStyle="m.titleStyle" size="large" :url="m.toPath">
</u-cell>
</u-cell-group>
</view>
</view>
</template>
<script>
export default {
data() {
return {
otherSteUpList: [
// {
// title: '',
// toPath: ''
// },
{
title: '常见问题',
toPath: '/pages/myInfo/problemList/index'
}
]
}
},
onShow(query) {
},
}
</script>
<style lang="scss">
.content {
padding: 0;
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<view class="content">
<view class="problem_title">
{{problemTitle}}
</view>
<view class="problem_describe" v-for="(m,idx) in problemList" :key="idx">
{{m}}
</view>
</view>
</template>
<script>
export default {
data () {
return {
problemTitle:'',
problemList:[]
}
},
onLoad(query) {
console.log(query);
const problemStatus = query.problemStatus || 1;
const problemObj = {
1:{
problemTitle:'赠币有有效期吗',
problemList :['参加不定时活动充值赠送的赠币有效期通常为发放后的3天如有特殊有效期会在活动中说明;','赠币到账后可在“我的”-“我的账户”-“赠币”页面中查看使用截止日期。']
},
2:{
problemTitle:'解锁得章节可以永久免费看吗?',
problemList :['可以。']
}
}
this.problemList = problemObj[problemStatus].problemList;
this.problemTitle = problemObj[problemStatus].problemTitle
},
}
</script>
<style lang="scss">
.content {
padding: 32rpx;
.problem_title {
font-size: 34rpx;
color: #1A1A1A;
}
.problem_describe {
margin-top: 40rpx;
font-size: 28rpx;
color: #666666;
line-height: 1.6;
}
}
</style>

View File

@ -0,0 +1,36 @@
<template>
<view class="content">
<view class="step_other_info">
<!-- url="/pages/componentsB/tag/tag" -->
<u-cell-group :border="false">
<u-cell v-for="(m,idx) in otherSteUpList" :key="idx" :title="m.title" :isLink="false"
:titleStyle="m.titleStyle" size="large" :url="m.toPath">
</u-cell>
</u-cell-group>
</view>
</view>
</template>
<script>
export default {
data() {
return {
otherSteUpList: [{
title: '赠币有有效期吗?',
toPath: `/pages/myInfo/problemDetail/index?problemStatus=1`
},
{
title: '解锁得章节可以永久免费看吗?',
toPath: `/pages/myInfo/problemDetail/index?problemStatus=2`
}
]
}
}
}
</script>
<style lang="scss">
.content {
padding: 0;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
const setUpReadingColorAll = {
'F3EFE9': {
// 背景色:#F3EFE9
'mainBodyBg': '#F3EFE9',
// 一级标题文字颜色:#2F1904
h1Title: '#2F1904',
// 导航栏文字颜色 #999999
navigationBarTitleTextColor: '#999999',
// 导航栏返回文字颜色 #130F26
navigationBarTitleTextBackColor: '#130F26',
// 内容文字颜色:#30150A
novelContentColor: '#30150A',
// 上一章背景颜色:#CFCDC9
previousChapterBbuttonBg: '#CFCDC9',
// 上一章文字颜色:#2D2C2B
previousChapterBbuttonTextColor: '#2D2C2B',
// 下一章背景颜色:#2D2C2B
nextChapterBbuttonBg: '#2D2C2B',
// 下一章文字颜色:#ffffff
nextChapterBbuttonTextColor: '#ffffff',
// 背景 字号文字颜色:#524843
dialogTextColor: '#524843',
// A- A+背景颜色:#E3DFDA
dialogATextBg: '#E3DFDA',
// A- A+字体颜色:#2F1904
dialogATextColor: '#2F1904',
// 文字颜色:#2F1904
tabBarTextColor: '#2F1904',
// 进度条背景颜色:#E3DCDA
progressBg: '#E3DCDA',
// 进度条背景深色:#C9BAB1
progressActiveBg: '#C9BAB1',
// 进度条圆圈颜色:#F5F5F5
progressRoundBg: '#F5F5F5',
// 阴影颜色:#3E465B
boxShowBg: '#3E465B'
},
'CCD9E2': {
// 背景色:#CCD9E2
mainBodyBg: '#CCD9E2',
// 一级标题文字颜色:#041D2F
h1Title: '#041D2F',
// 导航栏文字颜色 #999999
navigationBarTitleTextColor: '#999999',
// 导航栏返回文字颜色 #130F26
navigationBarTitleTextBackColor: '#130F26',
// 内容文字颜色:#0A1E30
novelContentColor: '#0A1E30',
// 上一章背景颜色:#CFCDC9
previousChapterBbuttonBg: '#CFCDC9',
// 上一章文字颜色:#2D2C2B
previousChapterBbuttonTextColor: '#2D2C2B',
// 下一章背景颜色:#2D2C2B
nextChapterBbuttonBg: '#2D2C2B',
// 下一章文字颜色:#ffffff
nextChapterBbuttonTextColor: '#ffffff',
// 背景 字号文字颜色:#434852
dialogTextColor: '#434852',
// A- A+背景颜色:#DCE5E8
dialogATextBg: '#DCE5E8',
// A- A+字体颜色:#041D2F
dialogATextColor: '#041D2F',
// 文字颜色:#041D2F
tabBarTextColor: '#041D2F',
// 进度条背景颜色:#DAE0E3
progressBg: '#DAE0E3',
// 进度条背景深色:#B1C1C9
progressActiveBg: '#B1C1C9',
// 进度条圆圈颜色:#F5F5F5
progressRoundBg: '#F5F5F5',
// 阴影颜色:#3E465B
boxShowBg: '#3E465B'
},
'333333': {
// 背景色:#333333
mainBodyBg: '#333333',
// 一级标题文字颜色:#9C9C9C
h1Title: '#9C9C9C',
// 导航栏文字颜色 #999999
navigationBarTitleTextColor: '#999999',
// 导航栏返回文字颜色 #FFFFFF
navigationBarTitleTextBackColor: '#FFFFFF',
// 内容文字颜色:#9D9D9D
novelContentColor: '#9D9D9D',
// 上一章背景颜色:#555555
previousChapterBbuttonBg: '#555555',
// 上一章文字颜色:#989898
previousChapterBbuttonTextColor: '#989898',
// 下一章背景颜色:#9D9D9D
nextChapterBbuttonBg: '#9D9D9D',
// 下一章文字颜色:#333333
nextChapterBbuttonTextColor: '#333333',
// 背景 字号文字颜色:#8F8F8F
dialogTextColor: '#8F8F8F',
// A- A+背景颜色:#E7E7E7
dialogATextBg: '#E7E7E7',
// A- A+字体颜色:#333333
dialogATextColor: '#333333',
// 文字颜色:#9C9C9C
tabBarTextColor: '#9C9C9C',
// 进度条背景颜色:#5C5C5C
progressBg: '#5C5C5C',
// 进度条背景深色:#797979
progressActiveBg: '#797979',
// 进度条圆圈颜色:#CCCCCC
progressRoundBg: '#CCCCCC',
// 阴影颜色:#3E465B
boxShowBg: '#3E465B',
// 弹出背景颜色:#303030
dialogBg:'#303030'
}
}
export default setUpReadingColorAll;

View File

@ -0,0 +1,248 @@
<template>
<view class="readingRecords_content">
<view class="reading_records_list">
<view class="_records_list_item" v-for="m in historyList" :key="m.id">
<view class="_list_item_book_img">
<image class="is_image" :src="m.cover"></image>
</view>
<view class="_list_item_right">
<view class="_list_item_title">
{{m.title}}
</view>
<view class="_list_item_operate">
<view class="_item_operate_name">{{m.order}}</view>
<view class="_item_operate_all">
<view class="_operate_all_have" v-if="m.bookcase == 1">
<view class="_all_have_image">
<image class="is_image" src="/static/images/readingRecords_have.png" />
</view>
<view class="_all_have_name">已有</view>
</view>
<view class="_operate_all_add" v-else @tap="addBookshelf(m)">
<view class="_all_add_image">
<image class="is_image" src="/static/images/readingRecords_add.png" />
</view>
<view class="_all_add_name">书架</view>
</view>
<view class="_operate_all_del" @tap="deteleBookHistory(m)">
<view class="_all_del_image">
<image class="is_image" src="/static/images/readingRecords_add_sdelete.png" />
</view>
</view>
</view>
</view>
<view class="_list_item_time">{{m.update_time}}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
baseUrlImage
} from '@/utils/utils'
export default {
data() {
return {
historyList: []
}
},
onShow() {
this.siGetHistory();
},
methods: {
addBookshelf(row) {
uni.showLoading({
title: '加载中...'
});
const data = {
sid: row.sid,
}
uni.$u.http.post('/addBookshelf', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
uni.showToast({
title: '加入成功',
icon: 'none'
})
this.siGetHistory(false);
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
},
siGetHistory(showLoadingFlag = true) {
if (showLoadingFlag) {
uni.showLoading({
title: '加载中...'
});
}
const data = {};
uni.$u.http.post('/getHistory', data).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const history = res.data.history;
const historyList = baseUrlImage(history);
this.historyList = historyList;
}
}).catch((err) => {
uni.hideLoading();
console.log(err, '========');
});
},
deteleBookHistory(row) {
uni.showLoading({
title: '加载中...'
});
const data = {
id: row.id,
}
uni.$u.http.post('/delHistory', data).then((res) => {
setTimeout(() => {
uni.hideLoading();
}, 1000);
if (res.status == 1) {
uni.showToast({
title: '删除成功',
icon: 'none'
})
this.siGetHistory(false);
}
}).catch((err) => {
setTimeout(() => {
uni.hideLoading();
}, 1000);
console.log(err, "========")
})
}
}
}
</script>
<style lang="scss">
.is_image {
display: block;
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.readingRecords_content {
padding: 32rpx;
.reading_records_list {
._records_list_item {
display: flex;
margin-bottom: 32rpx;
._list_item_book_img {
width: 150rpx;
height: 200rpx;
}
._list_item_right {
flex: 1;
padding: 16rpx 0 16rpx 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
._list_item_title {
color: #1A1A1A;
font-size: 32rpx;
line-height: 1;
}
._list_item_operate {
display: flex;
justify-content: space-between;
align-items: flex-end;
._item_operate_name {
color: #999999;
font-size: 26rpx;
line-height: 1;
}
._item_operate_all {
display: flex;
._operate_all_add {
display: flex;
justify-content: center;
align-items: center;
width: 114rpx;
height: 60rpx;
line-height: 60rpx;
border-radius: 30rpx;
border: 1px solid #FF728F;
._all_add_image {
width: 24rpx;
height: 24rpx;
}
._all_add_name {
font-size: 26rpx;
color: #FF728F;
margin-left: 4rpx;
}
}
._operate_all_have {
display: flex;
justify-content: center;
align-items: center;
width: 114rpx;
height: 60rpx;
line-height: 60rpx;
border-radius: 30rpx;
border: 1px solid #999999;
._all_have_image {
width: 24rpx;
height: 24rpx;
}
._all_have_name {
font-size: 26rpx;
color: #999999;
margin-left: 4rpx;
}
}
._operate_all_del {
margin-left: 16rpx;
display: flex;
justify-content: center;
align-items: center;
width: 72rpx;
height: 60rpx;
line-height: 60rpx;
border-radius: 30rpx;
border: 1px solid #696969;
._all_del_image {
width: 40rpx;
height: 40rpx;
}
}
}
}
._list_item_time {
color: #999999;
font-size: 26rpx;
line-height: 1;
margin-top: 8rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,269 @@
<template>
<view class="signInBookCurrency_content">
<u-navbar bgColor="transparent" leftIconColor="#fff" @leftClick="navbarLeftClick" />
<view class="signInBookCurrency_header_bag"></view>
<view class="signIn_list_box">
<view class="list_box_body">
<view class="list_box_body_sign_tips">
<view class="_sign_tips_header">
<text>已连续签到</text>
<text class="_sign_tips_header_num">{{totalNum}}</text>
<text> </text>
</view>
</view>
<view class="_body_sign_tips_box">
<view :class="['_body_sign_tips_box_item',m.status == 1 ? 'active':'']" v-for="m in signInList"
:key="m">
<view v-if="m.status == 1" class="_box_item_sign_in_success">
<image class="is_image" src="/static/images/sign_in_success.png"></image>
</view>
<view v-else class="_box_item_coin">
<image class="is_image" src="/static/images/_coin.png" />
</view>
<view class="_box_item_coin_num">
{{m.egold}}
</view>
</view>
</view>
</view>
<view class="sign_tips_button" @tap="handelSignIn">
<text v-if="signInFlag">已签到点击前往看书</text>
<text v-else>点击签到领取福利</text>
</view>
</view>
<u-transition :show="transitionShow" mode="fade" duration="1000">
<view class="transition_sign_box">
<view class="transition_sign_box_calendar">
<image class="is_image" src="../../static/images/sign_in_calendar.png"></image>
</view>
<view class="transition_sign_box_text">
<!-- <text>领取</text>
<text>10</text>
<text>书币</text> -->
{{signInMsg}}
</view>
</view>
</u-transition>
</view>
</template>
<script>
// const transitionCustomStyle =
export default {
data() {
return {
signInFlag: false,
transitionShow: false,
signInList: [],
totalNum: 0,
signInMsg: ''
}
},
onShow() {
this.getSignIn()
},
methods: {
handelSignIn() {
const signInFlag = this.signInFlag;
if (signInFlag) {
uni.navigateTo({
url: `pages/bookCity/bookCity/index`,
})
} else {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
uni.$u.http.post('/startSignin', {}, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
list,
totalNum,
daycheck
} = res.data;
this.signInMsg = res.msg;
this.transitionShow = true;
setTimeout(() => {
this.transitionShow = false
}, 2000);
this.getSignIn();
}
}).catch((err) => {
uni.hideLoading();
console.log(err, "========")
})
}
},
navbarLeftClick() {
uni.navigateBack();
},
getSignIn() {
uni.showLoading({
title: '加载中...'
});
const parameter = {
custom: {
token: true
}
}
uni.$u.http.post('/getSigInfo', {}, parameter).then((res) => {
uni.hideLoading();
if (res.status == 1) {
const {
list,
totalNum,
daycheck
} = res.data;
this.signInList = list;
this.totalNum = totalNum;
this.signInFlag = daycheck == 1 ? true : false;
}
}).catch((err) => {
uni.hideLoading();
})
}
}
}
</script>
<style lang="scss" scoped>
page {
background-color: #f1f1f1;
}
.is_image {
width: 100%;
height: 100%;
}
.signInBookCurrency_content {
width: 100%;
.signInBookCurrency_header_bag {
position: fixed;
width: 100%;
height: 536rpx;
background: url("/static/images/signInBookCurrency_header_bag.png") no-repeat;
background-size: 100% 100%;
}
.signIn_list_box {
position: relative;
top: 460rpx;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 32rpx;
width: 100%;
box-sizing: border-box;
.list_box_body {
width: 100%;
background: #fff;
box-sizing: border-box;
padding: 40rpx 0 40rpx 28rpx;
border-radius: 24rpx;
._sign_tips_header {
display: flex;
font-size: 34rpx;
color: #222222;
line-height: 1;
._sign_tips_header_num {
margin: 0 8rpx;
color: #FE9800;
}
}
._body_sign_tips_box {
display: flex;
justify-content: center;
width: 100%;
flex-wrap: wrap;
._body_sign_tips_box_item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 134rpx;
height: 178rpx;
background-color: #FFB423;
border-radius: 16rpx;
margin-right: 30rpx;
margin-top: 44rpx;
._box_item_coin {
width: 72rpx;
height: 72rpx;
}
._box_item_coin_num {
font-size: 28rpx;
color: #FFFFFF;
margin-top: 16rpx;
}
._box_item_sign_in_success {
width: 62rpx;
height: 42rpx;
}
}
._body_sign_tips_box_item.active {
background-color: #FFCD6C;
}
}
}
.sign_tips_button {
display: flex;
justify-content: center;
align-items: center;
width: 604rpx;
height: 102rpx;
line-height: 1;
margin-top: 40rpx;
background: linear-gradient(to left, #FE5139, #F19138);
font-size: 38rpx;
color: #ffffff;
border-radius: 51rpx;
}
}
.transition_sign_box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
top: 50%;
left: 50%;
width: 372rpx;
height: 282rpx;
background-color: rgba(20, 20, 20, 0.6);
transform: translate(-50%, -60%);
border-radius: 18rpx;
.transition_sign_box_calendar {
width: 200rpx;
height: 200rpx;
}
.transition_sign_box_text {
font-size: 34rpx;
line-height: 1;
color: #FFFFFF;
}
}
}
</style>

View File

@ -0,0 +1,420 @@
<template>
<view class="voucherCenter_content" :style="`padding-bottom:${contentSafeHeight}rpx`">
<view class="balance_info">
<view class="balance_info_box">
<view class="balance_info_name">您的余额</view>
<view class="balance_coin_box">
<view class="balance_num">{{ userInfo.egold }}</view>
<view class="balance_title">书币</view>
</view>
</view>
</view>
<view class="voucher_center_info">
<view class="voucher_annual_pass_box">
<view class="_annual_pass_tips">
<view class="_pass_tips_name">年卡</view>
<view class="_pass_tips_msg">尊享无限时书城免费畅读</view>
</view>
<view class="_annual_pass_money">
<view class="_pass_money_unit"></view>
<view class="_pass_money_num">{{ annualPass.price }}</view>
</view>
</view>
<view class="voucher_center_list">
<view class="_center_list_col_box" v-for="m in payList" :key="m.id" @tap="selectVoucherMoney($event, m)" :data-id="m.id">
<view :class="['_center_list_col_item', selectVoucherMoneyId === m.id ? 'active' : '']">
<view class="_col_item_money">
<view class="_item_money_num">{{ m.price }}</view>
<view class="_item_money_unit"></view>
</view>
<view class="_col_item_coin">
<!-- {{m.egold}}书币+{{zb}}书币 -->
{{ m.title }}
</view>
<view class="_col_item_deliver">
{{ m.description }}
</view>
<view v-if="m.poster" class="_col_item_hot_sales">{{ m.poster }}</view>
</view>
</view>
</view>
<view class="voucher_center_illustrate">
<view class="_center_illustrate_box">
<view class="_illustrate_box_title">充值说明</view>
<view class="_illustrate_box_tips_">
<view class="_illustrate_box_tips_item">11=100书币IP和书币属于虚拟商品,一旦购买不作退换,望周知</view>
<view class="_illustrate_box_tips_item">
2充值后书币到账可能有延迟15分钟内未到账请联系微信客服微信号:
<text style="color: #ff728f">yttfyyl,</text>
<text style="color: #ff728f">yt20216688</text>
工作时间:周一到周五9:00-17:00
</view>
</view>
</view>
</view>
</view>
<view class="voucher_center_confirm" >
<view class="_center_confirm_money">
<view class="_center_confirm_money_box">
<view class="_confirm_money_unit"></view>
<view class="_confirm_money_num">{{ price }}</view>
<!-- <view class="_confirm_money_preferential">已优惠12元</view> -->
<view class="_confirm_money_preferential">{{ preferential }}</view>
</view>
</view>
<view class="_center_confirm_btn">确认充值</view>
</view>
</view>
</template>
<script>
import { isGetSystemInfo } from '@/utils/systemInfo.js';
export default {
data() {
return {
selectVoucherMoneyId: '',
footerSafeHeight: 0,
contentSafeHeight: 130,
payList: [],
annualPass: {},
userInfo: {},
price: 0,
preferential: ''
};
},
onShow() {
const { windowHeight = 0, screenHeight = 0, windowTop = 0 } = isGetSystemInfo();
const footerSafeHeight = screenHeight - windowHeight - windowTop;
if (footerSafeHeight) {
// this.footerSafeHeight = footerSafeHeight;
this.contentSafeHeight = footerSafeHeight + 130;
}
this.isGetPayList();
const data = {};
uni.$u.http
.post('/getUserInfo', data)
.then((res) => {
uni.hideLoading();
if (res.status == 1) {
const user = res.data.user;
this.userInfo = user;
}
})
.catch((err) => {
uni.hideLoading();
console.log(err, '========');
});
},
methods: {
selectVoucherMoney(event, row) {
this.selectVoucherMoneyId = event.currentTarget.dataset.id;
this.price = row.price;
this.preferential = row.title;
},
isGetPayList() {
uni.showLoading({
title: '加载中...'
});
const data = {};
uni.$u.http
.post('/getPayList', data)
.then((res) => {
uni.hideLoading();
if (res.status == 1) {
this.annualPass = res.data.AnnualPass;
this.payList = res.data.list;
}
})
.catch((err) => {
uni.hideLoading();
console.log(err, '========');
});
}
}
};
</script>
<style lang="scss" scoped>
.voucherCenter_content {
width: 100%;
// padding-bottom: 130rpx;
.balance_info {
position: relative;
z-index: 2;
width: 100%;
padding: 32rpx 32rpx 0;
box-sizing: border-box;
.balance_info_box {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 100%;
height: 168rpx;
background: url('/static/images/myInfo/balance_bg.png') no-repeat;
background-size: 100% 100%;
padding: 30rpx 40rpx;
box-sizing: border-box;
.balance_info_name {
font-size: 30rpx;
color: #ffffff;
line-height: 1;
}
.balance_coin_box {
display: flex;
align-items: flex-end;
line-height: 1;
.balance_num {
font-size: 50rpx;
color: #ffffff;
font-weight: 600;
}
.balance_title {
font-size: 30rpx;
color: #ffffff;
margin-left: 8rpx;
}
}
}
}
.voucher_center_info {
width: 100%;
padding: 32rpx;
background-color: #ffffff;
border-radius: 24rpx 24rpx 0 0;
box-shadow: 0 -10rpx 10rpx 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
.voucher_annual_pass_box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 132rpx;
padding: 24rpx 40rpx;
background: linear-gradient(to left, #fecca7, #ffe5d6);
border-radius: 16rpx;
box-sizing: border-box;
._annual_pass_tips {
display: flex;
flex-direction: column;
// justify-content: space-between;
._pass_tips_name {
font-size: 38rpx;
color: #5b0c0c;
line-height: 1;
font-weight: 700;
}
._pass_tips_msg {
font-size: 26rpx;
color: #5b0c0c;
line-height: 1;
margin-top: 20rpx;
}
}
._annual_pass_money {
display: flex;
align-items: flex-end;
._pass_money_unit {
font-size: 28rpx;
color: #5b0c0c;
font-weight: 600;
line-height: 1;
}
._pass_money_num {
font-size: 52rpx;
color: #5b0c0c;
font-weight: 700;
line-height: 1;
}
}
}
.voucher_center_list {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 100%;
._center_list_col_box {
width: 50%;
padding-top: 32rpx;
box-sizing: border-box;
._center_list_col_item {
position: relative;
width: 100%;
height: 200rpx;
border: 1px solid #dddddd;
border-radius: 16rpx;
box-sizing: border-box;
padding: 30rpx 24rpx 0;
._col_item_money {
display: flex;
align-items: flex-end;
._item_money_num {
font-size: 48rpx;
color: #1a1a1a;
line-height: 1;
font-weight: 600;
}
._item_money_unit {
font-size: 26rpx;
color: #1a1a1a;
margin-left: 8rpx;
line-height: 1;
}
}
._col_item_coin {
font-size: 26rpx;
color: #999999;
line-height: 1;
margin-top: 24rpx;
}
._col_item_deliver {
font-size: 26rpx;
color: #ff4876;
line-height: 1;
margin-top: 18rpx;
}
._col_item_hot_sales {
position: absolute;
top: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
// width: 104rpx;
padding: 0 16rpx;
height: 40rpx;
line-height: 40rpx;
transform: translateY(-50%);
background: linear-gradient(to left, #ff2d2d, #ff5c5c);
font-size: 26rpx;
color: #ffffff;
border-radius: 0 20rpx 0 20rpx;
}
}
._center_list_col_item.active {
background-color: #ffeaef;
border-color: #ff4876;
}
}
._center_list_col_box:nth-child(2n-1) {
// padding-left: 16rpx;
padding-right: 16rpx;
}
._center_list_col_box:nth-child(2n) {
padding-left: 16rpx;
}
}
.voucher_center_illustrate {
margin-top: 64rpx;
._center_illustrate_box {
._illustrate_box_title {
font-size: 32rpx;
color: #1a1a1a;
margin-bottom: 20rpx;
}
._illustrate_box_tips_ {
width: 100%;
padding: 30rpx;
box-sizing: border-box;
background-color: #fff3f6;
border-radius: 24rpx;
._illustrate_box_tips_item {
font-size: 24rpx;
color: #666666;
margin-bottom: 8rpx;
line-height: 1.6;
}
}
}
}
}
.voucher_center_confirm {
display: flex;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 130rpx;
box-shadow: 0 -6rpx 6rpx 0 rgba(207, 207, 207, 0.25);
background-color: #ffffff;
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS 设备 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iPhone X 及以上设备 */
._center_confirm_money {
flex: 1;
display: flex;
align-items: center;
padding-left: 32rpx;
._center_confirm_money_box {
display: flex;
align-items: flex-end;
._confirm_money_unit {
font-size: 26rpx;
color: #ff4876;
line-height: 1;
font-weight: 600;
}
._confirm_money_num {
font-size: 52rpx;
color: #ff4876;
line-height: 1;
font-weight: 600;
margin-left: 6rpx;
}
._confirm_money_preferential {
font-size: 26rpx;
color: #8a8a8a;
line-height: 1;
margin-left: 26rpx;
}
}
}
._center_confirm_btn {
display: flex;
justify-content: center;
align-items: center;
width: 320rpx;
height: 130rpx;
line-height: 130rpx;
font-size: 36rpx;
color: #ffffff;
background: linear-gradient(to left, #ff87b5, #ff4775);
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More