Browse Source

feat: 添加成就模块并优化多个页面功能

- 在api.js中添加成就模块
- 优化wxUserInfo.vue和Modifyinformation.vue中的绑定手机号逻辑
- 在novelDetail.vue中调整成就获取逻辑
- 新增achievement.js并移除index.js中相关成就接口
- 优化fetch.js的代码格式
- 在category.vue和bookshelf.vue中调整列表展示逻辑
- 优化Giftbox.vue和Giftpurchases.vue的礼物展示和购买逻辑
- 新增myCommentItem.vue组件并优化myComment.vue的评论展示
- 优化center.vue的样式
master
前端-胡立永 2 weeks ago
parent
commit
5d8ab9776f
15 changed files with 530 additions and 503 deletions
  1. +1
    -1
      api/api.js
  2. +14
    -14
      api/fetch.js
  3. +1
    -1
      api/http.js
  4. +22
    -0
      api/model/achievement.js
  5. +0
    -17
      api/model/index.js
  6. +8
    -15
      pages/index/bookshelf.vue
  7. +4
    -4
      pages/index/category.vue
  8. +1
    -55
      pages/index/center.vue
  9. +1
    -1
      pages_order/auth/Modifyinformation.vue
  10. +1
    -1
      pages_order/auth/wxUserInfo.vue
  11. +17
    -116
      pages_order/comment/myComment.vue
  12. +113
    -0
      pages_order/components/comment/myCommentItem.vue
  13. +13
    -6
      pages_order/novel/Giftbox.vue
  14. +329
    -271
      pages_order/novel/Giftpurchases.vue
  15. +5
    -1
      pages_order/novel/novelDetail.vue

+ 1
- 1
api/api.js View File

@ -6,7 +6,7 @@ let limit = {}
let debounce = {}
const models = ['login', 'index', 'bookshelf', 'my_book', 'comment', 'task'
, 'order', 'writer']
, 'order', 'writer', 'achievement']
const config = {
// 示例


+ 14
- 14
api/fetch.js View File

@ -1,20 +1,20 @@
import api from './api.js'
const fetch = (key, data = {}, transform = true, loadingTitle) => {
return new Promise(resolve => {
const callback = (res) => {
if (!transform) {
resolve(res)
return
}
if (res.code == 200) {
resolve(res.result)
}
}
return new Promise(resolve => {
api(key, data, callback, loadingTitle)
})
const callback = (res) => {
if (!transform) {
resolve(res)
return
}
if (res.code == 200) {
resolve(res.result)
}
}
api(key, data, callback, loadingTitle)
})
}
export default fetch
export default fetch

+ 1
- 1
api/http.js View File

@ -37,7 +37,7 @@ function http(uri, data, callback, method = 'GET', showLoading, title) {
res.data.message == '操作失败,用户不存在!'){
store.commit('logout', '登录过期了,你可以停留在此页面或去重新登录')
console.error('登录过期');
utils.toLogin()
// utils.toLogin()
}
if(res.statusCode == 200 && res.data.code != 200


+ 22
- 0
api/model/achievement.js View File

@ -0,0 +1,22 @@
const api = {
// 设置读者成就等级名称
setAchievementName: {
url: '/all_achievement/setAchievementName',
method: 'GET',
auth: true,
},
// 根据用户标识和书籍标识查询该用户的成就等级
getAchievement: {
url: '/all_achievement/getAchievement',
method: 'GET',
auth: true,
},
// 获取读者成就列表
getAchievementList: {
url: '/all_achievement/getAchievementList',
method: 'GET',
},
}
export default api

+ 0
- 17
api/model/index.js View File

@ -7,17 +7,6 @@ const api = {
method: 'GET',
auth: true,
},
// 根据用户标识和书籍标识查询该用户的成就等级
getAchievement: {
url: '/all_index/getAchievement',
method: 'GET',
auth: true,
},
// 获取读者成就列表
getAchievementList: {
url: '/all_index/getAchievementList',
method: 'GET',
},
// 获取首页banner
getBanner: {
url: '/all_index/getBanner',
@ -84,12 +73,6 @@ const api = {
method: 'GET',
auth: true,
},
// 设置读者成就等级名称
setAchievementName: {
url: '/all_index/setAchievementName',
method: 'GET',
auth: true,
},
// 订阅章节
subscribeBook: {
url: '/all_index/subscribeBook',


+ 8
- 15
pages/index/bookshelf.vue View File

@ -171,7 +171,7 @@
activeTab: 'read',
isEditMode: false,
selectedItems: [], //
mixinsListApi : 'getReadBookPage',
mixinsListApi : '',
apiMap : {
read : 'getReadBookPage',
work : 'getMyBookPage',
@ -196,20 +196,11 @@
},
onShow() {
//
const pages = getCurrentPages();
const current = pages[pages.length - 1];
if (current.options && current.options.fromPublish === '1') {
this.activeTab = 'work';
uni.showToast({
title: '发布成功',
icon: 'success'
});
//
delete current.options.fromPublish;
// this.isEditMode = false;
// this.selectedItems = [];
if(this.isLogin){
this.mixinsListApi = this.apiMap[tab]
}
this.isEditMode = false;
this.selectedItems = [];
},
onUnload() {
//
@ -220,7 +211,9 @@
switchTab(tab) {
this.activeTab = tab;
this.mixinsListApi = this.apiMap[tab]
if(this.isLogin){
this.mixinsListApi = this.apiMap[tab]
}
this.list = []


+ 4
- 4
pages/index/category.vue View File

@ -33,14 +33,14 @@
@change="change">
<uv-vtabs-item>
<view class="category-item">
<view class="novel-list" v-if="categoryList.shopList.length > 0">
<view class="novel-list" v-if="list.length > 0">
<novelItem
v-for="(book, index) in categoryList.shopList"
v-for="(book, index) in list"
:key="index"
:book="book">
</novelItem>
</view>
<uv-empty v-if="categoryList.shopList.length == 0" text="还没有呢"/>
<uv-empty v-if="list.length == 0" text="还没有呢"/>
</view>
</uv-vtabs-item>
</uv-vtabs>
@ -66,7 +66,7 @@
},
data() {
return {
mixinsListApi: '',
mixinsListApi: 'getRecommendList',
current : 0,
currentChildren : 0,
categoryList: [],


+ 1
- 55
pages/index/center.vue View File

@ -152,13 +152,11 @@
<style scoped lang="scss">
.page {
padding-bottom: 200rpx;
background-color: #f5f5f5;
}
.user {
padding: 20rpx 30rpx;
.user-info {
height: 270rpx;
display: flex;
@ -257,7 +255,6 @@
}
.nologin-page {
min-height: 100vh;
background: #fff;
display: flex;
flex-direction: column;
@ -299,7 +296,7 @@
top: 48rpx;
}
.nologin-content-center {
position: absolute;
position: fixed;
top: 50%;
left: 0;
width: 100vw;
@ -322,55 +319,4 @@
align-items: center;
justify-content: center;
}
.nologin-tip {
color: #bcbcbc;
font-size: 24rpx;
margin-top: 10rpx;
}
.modal-mask {
position: fixed;
left: 0; top: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.modal-box {
background: #fff;
border-radius: 20rpx;
width: 80vw;
padding: 40rpx 0 0 0;
text-align: center;
}
.modal-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 20rpx;
}
.modal-content {
font-size: 28rpx;
color: #333;
margin-bottom: 30rpx;
}
.modal-actions {
display: flex;
border-top: 1px solid #eee;
height: 90rpx;
}
.modal-btn {
flex: 1;
line-height: 90rpx;
font-size: 30rpx;
color: #333;
border-right: 1px solid #eee;
}
.modal-btn:last-child {
border-right: none;
color: #2a5ed6;
}
.modal-btn.confirm {
color: #2a5ed6;
}
</style>

+ 1
- 1
pages_order/auth/Modifyinformation.vue View File

@ -82,7 +82,7 @@
},
getPhone(e) {
this.$api('bindPhone', {
phoneCode: e.detail.code
code: e.detail.code
}, res => {
if (res.code == 200) {
let phoneObj = JSON.parse(res.result)


+ 1
- 1
pages_order/auth/wxUserInfo.vue View File

@ -90,7 +90,7 @@
},
getPhone(e){
this.$api('bindPhone', {
phoneCode : e.detail.code
code : e.detail.code
}, res => {
if(res.code == 200){
let phoneObj = JSON.parse(res.result)


+ 17
- 116
pages_order/comment/myComment.vue View File

@ -3,55 +3,45 @@
<navbar title="我的评论" :leftClick="true" @leftClick="goBack" />
<view class="comment-section">
<view class="section-title">未读评论·{{ unreadComments.length }}</view>
<view v-for="(item, idx) in unreadComments" :key="idx" class="comment-card">
<uv-avatar :src="item.avatar" size="44" shape="circle" class="avatar" />
<view class="comment-main">
<view class="comment-header">
<text class="username">{{ item.username }}</text>
<text class="from">来自{{ item.bookTitle }}</text>
</view>
<view class="comment-content">{{ item.content }}</view>
<view class="comment-footer">
<text class="comment-time">{{ item.time }}</text>
<view class="reply-btn-wrap" @click="goToReply(item)">
<text class="reply-btn">回复</text>
</view>
</view>
</view>
</view>
<myCommentItem :item="item" v-for="(item, idx) in list" :key="idx"/>
</view>
<view class="comment-section history-section">
<view class="section-title">历史评论</view>
<view v-for="(item, idx) in historyComments" :key="idx" class="comment-card">
<uv-avatar :src="item.avatar" size="44" shape="circle" class="avatar" />
<!-- <view v-for="(item, idx) in list" :key="idx" class="comment-card">
<uv-avatar :src="item.hanHaiMember.headImage" size="44" shape="circle" class="avatar" />
<view class="comment-main">
<view class="comment-header">
<text class="username">{{ item.username }}</text>
<text class="from">来自{{ item.bookTitle }}</text>
<text class="username">{{ item.hanHaiMember.nickName }}</text>
<text class="from">来自{{ item.commonShop.name }}</text>
</view>
<view class="comment-content">{{ item.content }}</view>
<view class="comment-content">{{ item.comment }}</view>
<view class="comment-footer">
<text class="comment-time">{{ item.time }}</text>
<text class="comment-time">{{ item.createTime }}</text>
<view class="reply-btn-wrap" @click="goToReply(item)">
<text class="reply-btn">回复</text>
</view>
</view>
</view>
</view>
</view> -->
<myCommentItem :item="item" v-for="(item, idx) in list" :key="idx"/>
</view>
</view>
</template>
<script>
import mixinsList from '@/mixins/list.js'
import myCommentItem from '../components/comment/myCommentItem.vue'
export default {
mixins: [mixinsList],
components: {
myCommentItem,
},
data() {
return {
unreadComments: [{
mixinsListApi : 'getMyCommentList',
unreadComments: [
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '方香橙',
bookTitle: '重生之财富滚滚',
@ -73,24 +63,9 @@
time: '2024.06.09'
}
],
historyComments: [{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '方香橙',
bookTitle: '重生之财富滚滚',
content: '我是本书的作者方香橙,这是一本甜文爽文哒!请放心入坑,五星好评!女主又美有个性可爱,绝对不圣母,不傻白!男主身心干净深情独宠媳妇儿一个人...',
time: '2024.07.09'
}]
}
},
methods: {
goBack() {
uni.navigateBack()
},
goToReply(item) {
uni.navigateTo({
url: '/pages_order/novel/Respondcomments'
})
}
}
}
</script>
@ -117,78 +92,4 @@
font-weight: 500;
margin-bottom: 16rpx;
}
.comment-card {
display: flex;
align-items: flex-start;
margin-bottom: 32rpx;
}
.avatar {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
margin-right: 16rpx;
flex-shrink: 0;
}
.comment-main {
flex: 1;
display: flex;
flex-direction: column;
}
.comment-header {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 4rpx;
}
.username {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
.from {
font-size: 22rpx;
color: #bdbdbd;
}
.comment-content {
font-size: 26rpx;
color: #333;
margin-bottom: 12rpx;
}
.comment-footer {
display: flex;
align-items: center;
font-size: 22rpx;
color: #bdbdbd;
justify-content: space-between;
padding-right: 8rpx;
}
.comment-time {
color: #bdbdbd;
}
.reply-btn-wrap {
display: flex;
align-items: center;
cursor: pointer;
}
.reply-btn {
color: #223a6b;
font-weight: 500;
margin-left: 0;
font-size: 24rpx;
}
.history-section {
margin-top: 24rpx;
}
</style>

+ 113
- 0
pages_order/components/comment/myCommentItem.vue View File

@ -0,0 +1,113 @@
<template>
<view class="comment-card">
<uv-avatar :src="item.hanHaiMember.headImage" size="44" shape="circle" class="avatar" />
<view class="comment-main">
<view class="comment-header">
<text class="username">{{ item.hanHaiMember.nickName }}</text>
<text class="from">来自{{ item.commonShop.name }}</text>
</view>
<view class="comment-content">{{ item.comment }}</view>
<view class="comment-footer">
<text class="comment-time">{{ item.createTime }}</text>
<view class="reply-btn-wrap" @click="goToReply(item)">
<text class="reply-btn">回复</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: ['item'],
data() {
return {
}
},
methods: {
goToReply(item) {
uni.navigateTo({
url: '/pages_order/comment/respondComments?id=' + item.id
})
},
}
}
</script>
<style scoped lang="scss">
.comment-card {
display: flex;
align-items: flex-start;
margin-bottom: 32rpx;
.avatar {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
margin-right: 16rpx;
flex-shrink: 0;
}
.comment-main {
flex: 1;
display: flex;
flex-direction: column;
margin-left: 10rpx;
}
.comment-header {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 4rpx;
}
.username {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
.from {
font-size: 22rpx;
color: #bdbdbd;
}
.comment-content {
font-size: 26rpx;
color: #333;
margin-bottom: 12rpx;
}
.comment-footer {
display: flex;
align-items: center;
font-size: 22rpx;
color: #bdbdbd;
justify-content: space-between;
padding-right: 8rpx;
}
.comment-time {
color: #bdbdbd;
}
.reply-btn-wrap {
display: flex;
align-items: center;
cursor: pointer;
}
.reply-btn {
color: #223a6b;
font-weight: 500;
margin-left: 0;
font-size: 24rpx;
}
.history-section {
margin-top: 24rpx;
}
}
</style>

+ 13
- 6
pages_order/novel/Giftbox.vue View File

@ -20,12 +20,15 @@
<view v-for="(gift, idx) in list" :key="gift.id"
:class="['gift-item', { selected: idx === selectedIndex }]" @click="selectGift(idx)">
<view class="gift-img">
<text class="gift-emoji">{{ gift.emoji }}</text>
<view class="gift-emoji">
<image :src="gift.image"
mode="aspectFill"></image>
</view>
</view>
<view class="gift-name">{{ gift.name }}</view>
<view class="gift-name">{{ gift.title }}</view>
<view class="gift-info">
<text class="gift-count">x{{ gift.count }}</text>
<text class="gift-bean">{{ gift.price }}豆豆</text>
<!-- <text class="gift-count">x{{ gift.count }}</text> -->
<text class="gift-bean">{{ gift.integerPrice }}豆豆</text>
</view>
</view>
</view>
@ -146,9 +149,9 @@
},
buyGift() {
//
const gift = this.gifts[this.selectedIndex]
const gift = this.list[this.selectedIndex]
uni.navigateTo({
url: `/pages_order/novel/Giftpurchases?name=${encodeURIComponent(gift.name)}&price=${gift.price}&count=${this.buyCount}`
url: `/pages_order/novel/Giftpurchases?&id=${gift.id}&count=${this.buyCount}`
})
},
},
@ -199,6 +202,10 @@
.gift-emoji {
font-size: 56rpx;
image{
width: 80rpx;
height: 80rpx;
}
}
.gift-name {


+ 329
- 271
pages_order/novel/Giftpurchases.vue View File

@ -1,278 +1,336 @@
<template>
<!-- 礼物购买页面 -->
<view class="gift-purchase-page">
<!-- 顶部导航栏 -->
<navbar title="礼物购买" leftClick @leftClick="$utils.navigateBack" />
<!-- 礼物购买卡片 -->
<view class="card gift-card">
<view class="card-title">礼物购买</view>
<view class="form-row">
<view class="form-label">礼物名称</view>
<view class="form-value">{{ giftName }}</view>
</view>
<view class="divider"></view>
<view class="form-row">
<view class="form-label required"><text class="star">*</text> 购买数量</view>
<input class="form-input" placeholder="请输入数量" v-model="buyCount" type="number" :placeholder-style="'color:#bbb;'" :style="buyCount ? 'color:#222;' : ''" />
</view>
<view class="divider"></view>
<view class="form-row">
<view class="form-label">支付方式</view>
</view>
<view class="form-row">
<view class="balance">账户余额<text class="bean">{{ balance }} 豆豆</text></view>
</view>
</view>
<!-- 订单信息卡片 -->
<view class="card order-card">
<view class="order-title">订单信息</view>
<view class="row">
<view class="order-content">内容</view>
</view>
<view class="row total-row">
<view class="order-total-label">合计</view>
<view class="order-total"><text class="order-total-highlight">{{ totalPrice.toFixed(2) }}</text> </view>
</view>
<view class="order-divider"></view>
</view>
<!-- 提示信息 -->
<view class="tip-text">
请仔细核查并确认相关信息因用户个人疏忽导致的充值错误需由用户自行承担一旦完成充值概不退换
</view>
<!-- 底部购买按钮 -->
<view class="footer-bar">
<button class="buy-btn" @click="handleBuy">购买</button>
</view>
</view>
<!-- 礼物购买页面 -->
<view class="gift-purchase-page">
<!-- 顶部导航栏 -->
<navbar title="礼物购买" leftClick @leftClick="$utils.navigateBack" />
<!-- 礼物购买卡片 -->
<view class="card gift-card">
<view class="card-title">礼物购买</view>
<view class="form-row">
<view class="form-label">礼物名称</view>
<view class="form-value">{{ detail.title }}</view>
</view>
<view class="divider"></view>
<view class="form-row">
<view class="form-label required"><text class="star">*</text> 购买数量</view>
<input class="form-input" placeholder="请输入数量" v-model="buyCount" type="number"
:placeholder-style="'color:#bbb;'" :style="buyCount ? 'color:#222;' : ''" />
</view>
<view class="divider"></view>
<view class="form-row">
<view class="form-label">支付方式</view>
</view>
<view class="form-row">
<view class="balance">账户余额<text class="bean">{{ userInfo.integerPrice }} 豆豆</text></view>
</view>
</view>
<!-- 订单信息卡片 -->
<view class="card order-card"
v-if="totalIntegerPrice > userInfo.integerPrice">
<view class="order-title">订单信息</view>
<view class="row">
<view class="order-content">内容</view>
</view>
<view class="row total-row">
<view class="order-total-label">合计</view>
<view class="order-total"><text class="order-total-highlight">{{ totalPrice.toFixed(2) }}</text>
</view>
</view>
<view class="order-divider"></view>
</view>
<!-- 提示信息 -->
<view class="tip-text">
请仔细核查并确认相关信息因用户个人疏忽导致的充值错误需由用户自行承担一旦完成充值概不退换
</view>
<!-- 底部购买按钮 -->
<view class="footer-bar">
<button class="buy-btn" @click="handleBuy">购买</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
giftName: '小星星',
price: 0.1, //
buyCount: '',
balance: 0, //
}
},
computed: {
totalPrice() {
const count = parseInt(this.buyCount, 10)
return isNaN(count) ? 0 : count * this.price
}
},
onLoad(query) {
//
if (query.name) this.giftName = decodeURIComponent(query.name)
if (query.price) this.price = Number(query.price)
if (query.count) this.buyCount = query.count
},
methods: {
handleBuy() {
if (!this.buyCount || parseInt(this.buyCount, 10) <= 0) {
uni.showToast({ title: '请输入购买数量', icon: 'none' })
return
}
//
uni.showToast({ title: `成功购买${this.buyCount}${this.giftName}`, icon: 'success' })
}
}
}
export default {
data() {
return {
buyCount: 1,
detail :{},
giftId : 0,
}
},
computed: {
totalPrice() {
const count = parseInt(this.buyCount, 10)
return isNaN(count) ? 0 : count * this.detail.price
},
totalIntegerPrice(){
const count = parseInt(this.buyCount, 10)
return isNaN(count) ? 0 : count * this.detail.integerPrice
},
},
onLoad(query) {
//
if (query.id) this.giftId = query.id
if (query.count) this.buyCount = query.count
},
onShow() {
this.$store.commit(('getUserInfo'))
this.getGiftDetail()
},
methods: {
async getGiftDetail(){
this.detail = await this.$fetch('getGiftDetail', {
giftId : this.giftId,
})
},
async handleBuy() {
if (!this.buyCount || parseInt(this.buyCount, 10) <= 0) {
uni.showToast({
title: '请输入购买数量',
icon: 'none'
})
return
}
await this.$fetch('createOrder', {
giftId : this.giftId,
num : this.buyCount,
token : uni.getStorageSync('token'),
})
//
uni.showToast({
title: `成功购买${this.buyCount}${this.detail.title}`,
icon: 'success'
})
setTimeout(uni.navigateBack, 1000, -1)
}
}
}
</script>
<style scoped lang="scss">
.gift-purchase-page {
min-height: 100vh;
background: #f8f8f8;
padding-bottom: 120rpx;
}
.card {
background: #fff;
border-radius: 18rpx;
margin: 24rpx 16rpx 0 16rpx;
padding: 24rpx 24rpx 10rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
}
.card-title {
font-size: 24rpx;
font-weight: bold;
color: #222;
margin-bottom: 18rpx;
}
.row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.label {
color: #888;
font-size: 26rpx;
width: 160rpx;
}
.label.required {
color: #222;
font-weight: 500;
}
.value {
color: #222;
font-size: 26rpx;
}
.input {
flex: 1;
border: none;
border-bottom: 1rpx solid #eee;
font-size: 26rpx;
padding: 8rpx 0;
background: transparent;
outline: none;
}
.order-card {
border-radius: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
padding: 24px 20px 16px 20px;
margin: 16px;
position: relative;
}
.order-title {
font-size: 18px;
font-weight: bold;
color: #222;
margin-bottom: 12px;
}
.order-content {
color: #bbb;
font-size: 15px;
margin-bottom: 8px;
}
.row.total-row {
display: flex;
align-items: center;
margin-bottom: 0;
}
.order-total-label {
color: #222;
font-size: 18px;
font-weight: 500;
}
.order-total {
color: #222;
font-size: 18px;
font-weight: 500;
margin-left: 8px;
}
.order-total-highlight {
color: #ff7e00;
font-size: 18px;
font-weight: bold;
margin: 0 2px;
}
.order-divider {
width: 100%;
height: 1px;
background: #f2f2f2;
margin-top: 16px;
}
.tip-text {
color: #bbb;
font-size: 22rpx;
margin: 32rpx 32rpx 0 32rpx;
line-height: 1.6;
}
.footer-bar {
position: fixed;
left: 0;
right: 0;
bottom: 90rpx;
background: #fff;
padding: 24rpx 32rpx 32rpx 32rpx;
box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05);
z-index: 10;
}
.buy-btn {
width: 100%;
background: #223a7a;
color: #fff;
font-size: 32rpx;
border-radius: 32rpx;
height: 88rpx;
line-height: 88rpx;
border: none;
font-weight: 500;
}
.card.gift-card {
border-radius: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
padding: 24px 20px 16px 20px;
margin: 16px;
position: relative;
}
.card-title {
font-size: 18px;
font-weight: bold;
color: #222;
margin-bottom: 12px;
}
.form-row {
display: flex;
flex-direction: column;
align-items: flex-start;
min-height: 36px;
padding: 0;
margin-top: 5rpx;
}
.form-label {
color: #888;
font-size: 14px;
margin-bottom: 9px;
font-weight: 400;
margin-top: 5px;
}
.form-label.required {
color: #222;
font-weight: 500;
display: flex;
align-items: center;
}
.star {
color: #e94f7a;
margin-right: 2px;
font-size: 16px;
}
.form-value {
color: #0e0e0e;
font-size: 14px;
font-weight: 600;
margin-bottom: 2px;
}
.form-input {
flex: 1;
border: none;
background: transparent;
font-size: 14px;
outline: none;
padding: 0;
color: #222;
}
.divider {
height: 1px;
background: #f2f2f2;
margin: 0 0 0 0;
border: none;
}
.balance {
color: #0e0e0e;
font-size: 14px;
margin: 0 0 8px 0;
}
.bean {
color: #222;
font-weight: 600;
}
</style>
.gift-purchase-page {
min-height: 100vh;
background: #f8f8f8;
padding-bottom: 120rpx;
}
.card {
background: #fff;
border-radius: 18rpx;
margin: 24rpx 16rpx 0 16rpx;
padding: 24rpx 24rpx 10rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
}
.card-title {
font-size: 24rpx;
font-weight: bold;
color: #222;
margin-bottom: 18rpx;
}
.row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.label {
color: #888;
font-size: 26rpx;
width: 160rpx;
}
.label.required {
color: #222;
font-weight: 500;
}
.value {
color: #222;
font-size: 26rpx;
}
.input {
flex: 1;
border: none;
border-bottom: 1rpx solid #eee;
font-size: 26rpx;
padding: 8rpx 0;
background: transparent;
outline: none;
}
.order-card {
border-radius: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
padding: 24px 20px 16px 20px;
margin: 16px;
position: relative;
}
.order-title {
font-size: 18px;
font-weight: bold;
color: #222;
margin-bottom: 12px;
}
.order-content {
color: #bbb;
font-size: 15px;
margin-bottom: 8px;
}
.row.total-row {
display: flex;
align-items: center;
margin-bottom: 0;
}
.order-total-label {
color: #222;
font-size: 18px;
font-weight: 500;
}
.order-total {
color: #222;
font-size: 18px;
font-weight: 500;
margin-left: 8px;
}
.order-total-highlight {
color: #ff7e00;
font-size: 18px;
font-weight: bold;
margin: 0 2px;
}
.order-divider {
width: 100%;
height: 1px;
background: #f2f2f2;
margin-top: 16px;
}
.tip-text {
color: #bbb;
font-size: 22rpx;
margin: 32rpx 32rpx 0 32rpx;
line-height: 1.6;
}
.footer-bar {
position: fixed;
left: 0;
right: 0;
bottom: 90rpx;
background: #fff;
padding: 24rpx 32rpx 32rpx 32rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
z-index: 10;
}
.buy-btn {
width: 100%;
background: #223a7a;
color: #fff;
font-size: 32rpx;
border-radius: 32rpx;
height: 88rpx;
line-height: 88rpx;
border: none;
font-weight: 500;
}
.card.gift-card {
border-radius: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
padding: 24px 20px 16px 20px;
margin: 16px;
position: relative;
}
.card-title {
font-size: 18px;
font-weight: bold;
color: #222;
margin-bottom: 12px;
}
.form-row {
display: flex;
flex-direction: column;
align-items: flex-start;
min-height: 36px;
padding: 0;
margin-top: 5rpx;
}
.form-label {
color: #888;
font-size: 14px;
margin-bottom: 9px;
font-weight: 400;
margin-top: 5px;
}
.form-label.required {
color: #222;
font-weight: 500;
display: flex;
align-items: center;
}
.star {
color: #e94f7a;
margin-right: 2px;
font-size: 16px;
}
.form-value {
color: #0e0e0e;
font-size: 14px;
font-weight: 600;
margin-bottom: 2px;
}
.form-input {
flex: 1;
border: none;
background: transparent;
font-size: 14px;
outline: none;
padding: 0;
color: #222;
}
.divider {
height: 1px;
background: #f2f2f2;
margin: 0 0 0 0;
border: none;
}
.balance {
color: #0e0e0e;
font-size: 14px;
margin: 0 0 8px 0;
}
.bean {
color: #222;
font-weight: 600;
}
</style>

+ 5
- 1
pages_order/novel/novelDetail.vue View File

@ -204,9 +204,13 @@
}) {
this.id = id
this.queryParams.bookId = id
},
onShow() {
this.getDateil()
this.getAchievement()
this.getBookCatalogList()
if(this.isLogin){
this.getAchievement()
}
},
methods: {
updateVote() {


Loading…
Cancel
Save