Browse Source

refactor: 重构公告、评论和章节列表相关代码

- 将公告相关页面从 `novel` 目录移动到 `announcement` 目录
- 重构评论组件,优化代码结构
- 优化章节列表页面的导航栏和标签切换逻辑
- 删除不再使用的登录页面和旧版公告页面
- 更新 `pages.json` 中的路由配置
master
前端-胡立永 1 week ago
parent
commit
bd3a364729
41 changed files with 3619 additions and 3350 deletions
  1. +2
    -0
      .trae/rules/project_rules.md
  2. +14
    -3
      components/base/tabbar.vue
  3. +95
    -86
      components/novel/RankListItem.vue
  4. +1
    -6
      components/novel/novelItem.vue
  5. +1
    -1
      manifest.json
  6. +3
    -6
      pages.json
  7. +13
    -8
      pages/index/bookshelf.vue
  8. +15
    -13
      pages/index/center.vue
  9. +16
    -28
      pages/index/index.vue
  10. +121
    -0
      pages_order/announcement/announcementDetail.vue
  11. +117
    -0
      pages_order/announcement/announcements.vue
  12. +194
    -0
      pages_order/comment/myComment.vue
  13. +103
    -0
      pages_order/components/comment/commentItem.vue
  14. +235
    -0
      pages_order/components/novel/chapterPopup.vue
  15. +0
    -137
      pages_order/novel/Allannouncements.vue
  16. +0
    -180
      pages_order/novel/Mycomment.vue
  17. +213
    -185
      pages_order/novel/ReaderAchievement.vue
  18. +182
    -160
      pages_order/novel/Review.vue
  19. +256
    -221
      pages_order/novel/SubscriptionInformation.vue
  20. +272
    -226
      pages_order/novel/Tipping.vue
  21. +330
    -292
      pages_order/novel/Translation.vue
  22. +384
    -246
      pages_order/novel/Walletflow.vue
  23. +0
    -132
      pages_order/novel/announcement.vue
  24. +174
    -246
      pages_order/novel/chapterList.vue
  25. +0
    -109
      pages_order/novel/login.vue
  26. +721
    -909
      pages_order/novel/novelDetail.vue
  27. +156
    -155
      pages_order/novel/vote.vue
  28. BIN
      pages_order/static/book/bd.png
  29. BIN
      pages_order/static/book/gg.png
  30. BIN
      static/image/tabbar/bookshelf-a.png
  31. BIN
      static/image/tabbar/bookshelf.png
  32. BIN
      static/image/tabbar/cart-a.png
  33. BIN
      static/image/tabbar/cart.png
  34. BIN
      static/image/tabbar/category-a.png
  35. BIN
      static/image/tabbar/category.png
  36. BIN
      static/image/tabbar/center-a.png
  37. BIN
      static/image/tabbar/center.png
  38. BIN
      static/image/tabbar/home-a.png
  39. BIN
      static/image/tabbar/order-a.png
  40. BIN
      static/image/tabbar/order.png
  41. +1
    -1
      uni.scss

+ 2
- 0
.trae/rules/project_rules.md View File

@ -1,3 +1,5 @@
每次编写代码时,请你先查看我的整个目录,提供的哪些文件、组件、功能、API接口,了解我的代码风格,写出和我风格一致的代码
## 项目规则
1、将列表以及列表中的元素封装成组件,并使用组件的方式来组织项目。使他可以复用
2、项目中使用到的功能优先去查看uni_modules里面的组件列表,若没有则自己封装。


+ 14
- 3
components/base/tabbar.vue View File

@ -2,7 +2,7 @@
<view class="tabbar-box">
<view class="tabbar">
<view :class="{ 'tabbar-active' : select == item.key}" v-for="(item, index) in list" :key="index"
v-if="!item.isNotShop || !userShop" @click="toPath(item, index)" class="tabbar-item">
@click="toPath(item, index)" class="tabbar-item">
<view class="tabbar-icon">
<image :src="select == item.key ?
item.selectedIconPath :
@ -43,8 +43,8 @@
key: 'category',
},
{
"selectedIconPath": "/static/image/tabbar/order-a.png",
"iconPath": "/static/image/tabbar/order.png",
"selectedIconPath": "/static/image/tabbar/bookshelf-a.png",
"iconPath": "/static/image/tabbar/bookshelf.png",
"pagePath": "/pages/index/bookshelf",
"title": "书架",
key: 'bookshelf',
@ -91,6 +91,7 @@
bottom: 0;
left: 0;
color: #BCBCBC;
border-top: 2rpx solid #BCBCBC;;
.tabbar-item {
flex: 1;
@ -121,6 +122,16 @@
.tabbar-active {
color: $uni-color !important;
.tabbar-icon {
width: 94rpx;
height: 94rpx;
margin-top: -40rpx;
.tabbar-icon-image {
width: 94rpx;
height: 94rpx;
}
}
}
}
}

+ 95
- 86
components/novel/RankListItem.vue View File

@ -1,93 +1,102 @@
<template>
<view class="rank-item">
<view class="rank-left">
<image v-if="rankIcon" :src="rankIcon" class="rank-icon" />
<image v-else-if="rankNumImg" :src="rankNumImg" class="rank-num-img" />
<slot name="rankNum" v-else />
<image v-if="medal" :src="medal" class="medal" />
<image class="avatar" :src="avatar" mode="aspectFill" />
<view class="name">{{ name }}</view>
</view>
<view class="rank-right">
<view class="score">{{ score }} 亲密值</view>
<view class="level">{{ level }}</view>
</view>
</view>
<view class="rank-item">
<view class="rank-left">
<image v-if="rankIcon" :src="rankIcon" class="rank-icon" />
<image v-else-if="rankNumImg" :src="rankNumImg" class="rank-num-img" />
<slot name="rankNum" v-else />
<image v-if="medal" :src="medal" class="medal" />
<image class="avatar" :src="avatar" mode="aspectFill" />
<view class="name">{{ name }}</view>
</view>
<view class="rank-right">
<view class="score">{{ score }} 亲密值</view>
<view class="level">{{ level }}</view>
</view>
</view>
</template>
<script>
export default {
name: 'RankListItem',
props: {
rankIcon: String, // 3
rankNumImg: String, // 4-10
medal: String, //
avatar: String,
name: String,
score: [String, Number],
level: {
type: String,
default: '护书使者 五级'
}
}
}
export default {
name: 'RankListItem',
props: {
rankIcon: String, // 3
rankNumImg: String, // 4-10
medal: String, //
avatar: String,
name: String,
score: [String, Number],
level: {
type: String,
default: '护书使者 五级'
}
}
}
</script>
<style lang="scss" scoped>
.rank-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fffbe6;
border-radius: 16rpx;
margin-bottom: 18rpx;
box-shadow: 0 2rpx 8rpx 0 rgba(184,110,59,0.06);
padding: 0 24rpx;
height: 100rpx;
.rank-left {
display: flex;
align-items: center;
.rank-icon, .rank-num-img {
width: 38rpx;
height: 38rpx;
margin-right: 10rpx;
}
.medal {
width: 44rpx;
height: 44rpx;
margin-right: 10rpx;
}
.avatar {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
margin-right: 14rpx;
border: 2rpx solid #ffd700;
object-fit: cover;
}
.name {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
}
.rank-right {
display: flex;
flex-direction: column;
align-items: flex-end;
.score {
font-size: 22rpx;
color: #b86e3b;
}
.level {
font-size: 20rpx;
color: #fff;
background: #e6b07c;
border-radius: 8rpx;
padding: 2rpx 10rpx;
margin-top: 6rpx;
font-weight: 500;
}
}
}
</style>
.rank-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fffbe6;
border-radius: 16rpx;
margin-bottom: 18rpx;
box-shadow: 0 2rpx 8rpx 0 rgba(184, 110, 59, 0.06);
padding: 0 24rpx;
height: 100rpx;
.rank-left {
display: flex;
align-items: center;
.rank-icon,
.rank-num-img {
width: 38rpx;
height: 38rpx;
margin-right: 10rpx;
}
.medal {
width: 44rpx;
height: 44rpx;
margin-right: 10rpx;
}
.avatar {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
margin-right: 14rpx;
border: 2rpx solid #ffd700;
object-fit: cover;
}
.name {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
}
.rank-right {
display: flex;
flex-direction: column;
align-items: flex-end;
.score {
font-size: 22rpx;
color: #b86e3b;
}
.level {
font-size: 20rpx;
color: #fff;
background: #e6b07c;
border-radius: 8rpx;
padding: 2rpx 10rpx;
margin-top: 6rpx;
font-weight: 500;
}
}
}
</style>

+ 1
- 6
components/novel/novelItem.vue View File

@ -1,5 +1,5 @@
<template>
<view class="book-item" :class="{'horizontal': horizontal}" @click="goToNovelDetail">
<view class="book-item" :class="{'horizontal': horizontal}" @click="$emit('click')">
<image class="book-cover" src="https://bookcover.yuewen.com/qdbimg/349573/1033014772/150.webp" mode="aspectFill"></image>
<view class="book-info">
<view class="book-title">{{book.title}}</view>
@ -50,11 +50,6 @@
return {}
},
methods: {
goToNovelDetail() {
uni.navigateTo({
url: `/pages_order/novel/novelDetail?id=${this.book.id}`
});
}
}
}
</script>


+ 1
- 1
manifest.json View File

@ -52,7 +52,7 @@
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxe7ae8cbe1673834c",
"appid" : "wxd21ddb1fbf3f5150",
"setting" : {
"urlCheck" : false
},


+ 3
- 6
pages.json View File

@ -59,10 +59,10 @@
"path": "novel/vote"
},
{
"path": "novel/announcement"
"path": "announcement/announcementDetail"
},
{
"path": "novel/Allannouncements"
"path": "announcement/announcements"
},
{
"path": "novel/createNovel"
@ -104,14 +104,11 @@
"path": "novel/Giftpurchases"
},
{
"path": "novel/Mycomment"
"path": "comment/myComment"
},
{
"path": "novel/Translation"
},
{
"path": "novel/login"
},
{
"path": "novel/Modifyinformation"
}


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

@ -253,7 +253,17 @@
}
],
//
worksList: [] //
worksList: [
{
id: '9',
title: '纳瓦尔宝典',
cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
author: 'Naval',
desc: '硅谷天使投资人纳瓦尔·拉维坎特的人生智慧...',
tags: ['哲学', '投资'],
status: '已完结'
}
] //
}
},
onLoad() {
@ -261,9 +271,6 @@
const systemInfo = uni.getSystemInfoSync();
this.statusBarHeight = systemInfo.statusBarHeight;
//
this.loadWorksList()
//
const activeTab = uni.getStorageSync('activeBookshelfTab')
if (activeTab === 'work') {
@ -283,8 +290,6 @@
// #endif
},
onShow() {
//
this.loadWorksList()
//
const pages = getCurrentPages();
@ -314,10 +319,10 @@
this.exitEditMode();
},
//
//
toNovelDetail(id) {
uni.navigateTo({
url: '/pages_order/book/bookDetail?id=' + id
url: '/pages_order/novel/readnovels?id=' + id
})
},


+ 15
- 13
pages/index/center.vue View File

@ -2,8 +2,13 @@
<view>
<view class="page" v-if="isLogin && !showLogoutModal">
<view class="user">
<view class=""
style="height: 120rpx;padding-top: calc(var(--status-bar-height) + 20rpx);">
</view>
<!-- 用户信息区域 -->
<view class="user-info">
<image class="avatar" src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg" mode=""></image>
@ -21,14 +26,14 @@
<view class="section">
<view class="section-title">账户</view>
<view class="section-list">
<view class="section-item" @click="navigateToPage('/pages_order/novel/Walletflow')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/novel/Walletflow')">
<view class="section-item-left">
<uv-icon name="photo" size="40rpx" color="#333"></uv-icon>
<text>钱包流水</text>
</view>
<uv-icon name="arrow-right" size="36rpx" color="#999"></uv-icon>
</view>
<view class="section-item" @click="navigateToPage('/pages_order/novel/Giftbox')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/novel/Giftbox')">
<view class="section-item-left">
<uv-icon name="gift" size="40rpx" color="#333"></uv-icon>
<text>礼物盒</text>
@ -42,7 +47,7 @@
<view class="section">
<view class="section-title">日常</view>
<view class="section-list">
<view class="section-item" @click="navigateToPage('/pages_order/novel/Mycomment')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/comment/myComment')">
<view class="section-item-left">
<uv-icon name="chat" size="40rpx" color="#333"></uv-icon>
<text>我的评论</text>
@ -50,7 +55,7 @@
<view class="badge">294</view>
<uv-icon name="arrow-right" size="36rpx" color="#999"></uv-icon>
</view>
<view class="section-item" @click="navigateToPage('/pages_order/novel/Translation')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/novel/Translation')">
<view class="section-item-left">
<uv-icon name="list" size="40rpx" color="#333"></uv-icon>
<text>任务中心</text>
@ -65,14 +70,14 @@
<view class="section">
<view class="section-title">设置</view>
<view class="section-list">
<view class="section-item" @click="navigateToPage('/pages_order/novel/creator')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/novel/creator')">
<view class="section-item-left">
<uv-icon name="star" size="40rpx" color="#333"></uv-icon>
<text>申请成为作者</text>
</view>
<uv-icon name="arrow-right" size="36rpx" color="#999"></uv-icon>
</view>
<view class="section-item" @click="navigateToPage('/pages/customer-service')">
<view class="section-item" @click="$utils.navigateTo('/pages/customer-service')">
<view class="section-item-left">
<uv-icon name="star" size="40rpx" color="#333"></uv-icon>
<text>联系客服</text>
@ -80,7 +85,7 @@
</view>
<uv-icon name="arrow-right" size="36rpx" color="#999"></uv-icon>
</view>
<view class="section-item" @click="navigateToPage('/pages_order/novel/Modifyinformation')">
<view class="section-item" @click="$utils.navigateTo('/pages_order/novel/Modifyinformation')">
<view class="section-item-left">
<uv-icon name="edit-pen" size="40rpx" color="#333"></uv-icon>
<text>修改信息</text>
@ -100,6 +105,8 @@
<tabber select="center" />
</view>
<view v-else-if="!isLogin && !showLogoutModal" class="nologin-page">
<view class="nologin-top-bg">
<view class="nologin-header">
@ -144,11 +151,6 @@
}
},
methods: {
navigateToPage(url) {
uni.navigateTo({
url
})
},
logout() {
this.showLogoutModal = true;
},


+ 16
- 28
pages/index/index.vue View File

@ -77,11 +77,11 @@
</view>
<scroll-view scroll-x style="width: 100%;">
<view class="recommend-list">
<view class="recommend-item"
@click="navigateToDetail(item.id)"
v-for="(item, index) in novelList" :key="index">
<novel-item horizontal :key="index" :book="item" />
</view>
<view class="recommend-item"
@click="navigateToDetail(item.id)"
v-for="(item, index) in novelList" :key="index">
<novel-item horizontal :key="index" :book="item" />
</view>
</view>
</scroll-view>
</view>
@ -124,18 +124,6 @@
return {
//
bannerList: [
{
id: '1',
image: 'https://img95.699pic.com/photo/50136/1544.jpg_wh300.jpg',
title: '慢着,请别叫我昭昭烈帝',
desc: '醒掌天下权,醉卧美人膝,五千年风华烟雨,是非成败转头空!'
},
{
id: '2',
image: 'https://img95.699pic.com/photo/40094/9516.jpg_wh300.jpg',
title: '少年闻天语',
desc: '修仙之路,逆天改命,少年携天命而来'
},
{
id: '3',
image: 'https://img95.699pic.com/photo/50055/5909.jpg_wh300.jpg',
@ -201,21 +189,21 @@
},
//
clickBanner(index) {
const banner = this.bannerList[index];
console.log('点击了轮播图:', banner.title);
//
uni.showToast({
title: '正在前往: ' + banner.title,
icon: 'none'
})
setTimeout(() => {
this.$utils.navigateTo(`/pages_order/book/bookDetail?id=${banner.id}`)
}, 500)
// const banner = this.bannerList[index];
// console.log(':', banner.title);
// //
// uni.showToast({
// title: ': ' + banner.title,
// icon: 'none'
// })
// setTimeout(() => {
// this.$utils.navigateTo(`/pages_order/book/bookDetail?id=${banner.id}`)
// }, 500)
},
//
viewNotice() {
uni.navigateTo({
url: '/pages_order/novel/Allannouncements'
url: '/pages_order/announcement/announcements'
})
},
navigateToDetail(id) {


+ 121
- 0
pages_order/announcement/announcementDetail.vue View File

@ -0,0 +1,121 @@
<template>
<!-- 公告详情页面 -->
<view class="announcement-container">
<navbar title="公告详情" leftClick @leftClick="$utils.navigateBack" />
<view class="award-section">
<view class="award-item">
<text class="award-title">长篇网文</text>
<view class="award-content">
<view class="sub-award">
<text class="sub-title"> 优质加更奖</text>
<text class="detail">拟获奖作品156本共发放奖金41.5万元查看拟获奖名单请点击</text>
<text class="link">优质加更奖拟获奖名单</text>
</view>
<view class="sub-award">
<text class="sub-title"> 新书扶更奖</text>
<text class="detail">拟获奖作品5574本共发放奖金20万元查看拟获奖名单请点击</text>
<text class="link">新书扶更奖拟获奖名单</text>
</view>
<view class="sub-award">
<text class="sub-title"> 拉新激励奖</text>
<text class="detail">拟获奖作品50部总计奖金65万查看拟获奖名单请点击</text>
<text class="link">2月拉新激励奖</text>
</view>
<view class="sub-award">
<text class="sub-title"> 星火计划奖励</text>
<text class="detail">拟获奖作品4178部总计奖金55万查看拟获奖名单请点击</text>
<text class="link">2月星火计划奖励名单</text>
</view>
</view>
</view>
<view class="award-item">
<text class="award-title">完结专场</text>
<view class="award-content">
<view class="sub-award">
<text class="sub-title"> 脱洞盛宴征文活动</text>
<text class="detail">月度脱洞专题拟获奖作品1260部总计奖金45万查看拟获奖名单请点击</text>
<text class="link">2月完结专题奖励名单</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
'uv-navbar': () => import('@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue')
},
data() {
return {}
},
methods: {
//
}
}
</script>
<style lang="scss">
.announcement-container {
padding: 30rpx;
background: #fff;
.header {
margin-bottom: 40rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: block;
}
.date {
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
}
.award-section {
.award-item {
margin-bottom: 40rpx;
.award-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: block;
}
.award-content {
.sub-award {
margin-bottom: 20rpx;
.sub-title {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.detail {
font-size: 28rpx;
color: #666;
}
.link {
color: #007AFF;
text-decoration: underline;
font-size: 28rpx;
}
}
}
}
}
}
</style>

+ 117
- 0
pages_order/announcement/announcements.vue View File

@ -0,0 +1,117 @@
<template>
<view class="announcements-container">
<navbar title="全部公告" leftClick @leftClick="$utils.navigateBack" />
<view class="announcements-list">
<view class="announcement-item" v-for="(item, index) in announcements" :key="index"
@click="$utils.navigateTo(`/pages_order/announcement/announcementDetail?id=${item.id}`)">
<view class="item-left">
<text class="tag">通讯</text>
<text class="title">{{ item.title }}</text>
</view>
<view class="item-right">
<uv-icon name="arrow-right" color="#C8C8C8" size="28rpx"></uv-icon>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
announcements: [{
id: 1,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 2,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 3,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 4,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 5,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 6,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 7,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
}
]
}
},
methods: {
}
}
</script>
<style lang="scss">
.announcements-container {
min-height: 100vh;
background-color: #F8F8F8;
.announcements-list {
padding: 20rpx;
.announcement-item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #FFFFFF;
padding: 30rpx;
margin-bottom: 20rpx;
border-radius: 12rpx;
.item-left {
flex: 1;
margin-right: 20rpx;
.tag {
display: inline-block;
font-size: 24rpx;
color: #666666;
background-color: #F5F5F5;
padding: 4rpx 12rpx;
border-radius: 6rpx;
margin-bottom: 16rpx;
}
.title {
display: block;
font-size: 28rpx;
color: #333333;
line-height: 1.4;
}
}
.item-right {
display: flex;
align-items: center;
}
&:active {
background-color: #F9F9F9;
}
}
}
}
</style>

+ 194
- 0
pages_order/comment/myComment.vue View File

@ -0,0 +1,194 @@
<template>
<view class="my-comment-page">
<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>
</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 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>
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
unreadComments: [{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '方香橙',
bookTitle: '重生之财富滚滚',
content: '我是本书的作者方香橙,这是一本甜文爽文哒!请放心入坑,五星好评!女主又美有个性可爱,绝对不圣母,不傻白!男主身心干净深情独宠媳妇儿一个人...',
time: '2024.07.09'
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '战斗世界',
bookTitle: '重生之财富滚滚',
content: '这本书打破了我看甜文套路之前的观念女主真的太可爱太有趣和以往看过的一个NPC介绍有很大不同',
time: '2024.06.09'
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '战斗世界',
bookTitle: '重生之财富滚滚',
content: '这本书打破了我看甜文套路之前的观念女主真的太可爱太有趣和以往看过的一个NPC介绍有很大不同',
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>
<style scoped lang="scss">
.my-comment-page {
min-height: 100vh;
background: #f8f8f8;
display: flex;
flex-direction: column;
}
.comment-section {
background: #fff;
margin: 24rpx 24rpx 0 24rpx;
border-radius: 16rpx;
padding: 24rpx 24rpx 0 24rpx;
margin-bottom: 24rpx;
}
.section-title {
color: #222;
font-size: 28rpx;
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>

+ 103
- 0
pages_order/components/comment/commentItem.vue View File

@ -0,0 +1,103 @@
<template>
<view class="comment-item">
<view class="comment-header">
<image class="avatar"
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFill"></image>
<text class="username">方香橙</text>
</view>
<view class="comment-body">
<text class="content-text">我是本书的作者方香橙这是一本甜文爽文哒请放心入坑五星好评女主又美有个性可爱绝对不圣母不傻白男主身心干净深情独宠媳妇儿一个人...</text>
<view class="comment-footer">
<text class="comment-time">2024.07.09</text>
<view class="comment-likes" @click="goToCommentReply">
<text class="like-icon">💬</text>
<text class="like-count">17</text>
</view>
</view>
</view>
</view>
<!--
<view class="comment-item">
<view class="comment-header">
<image class="avatar"
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFill"></image>
<text class="username">战斗世界</text>
</view>
<view class="comment-body">
<text class="content-text">这本小说了创意了雄天霸业奇新颖深刻以白色能量为主...</text>
</view>
</view>
-->
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style scoped lang="scss">
.comment-item {
display: flex;
flex-direction: column;
gap: 16rpx;
.comment-header {
display: flex;
align-items: center;
gap: 12rpx;
}
.avatar {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
}
.username {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.comment-body {
padding-left: 76rpx;
}
.content-text {
font-size: 28rpx;
color: #333;
line-height: 1.6;
}
.comment-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
}
.comment-time {
font-size: 24rpx;
color: #999;
}
.comment-likes {
display: flex;
align-items: center;
gap: 4rpx;
}
}
</style>

+ 235
- 0
pages_order/components/novel/chapterPopup.vue View File

@ -0,0 +1,235 @@
<template>
<uv-popup ref="popup" :round="30" :customStyle="{height: '70vh'}">
<view class="catalog-popup-fullscreen">
<view class="catalog-header">
<view class="header-left" @click.stop="close">
<uv-icon name="arrow-down" size="46" color="#333"/>
</view>
<view class="header-title">目录</view>
<view class="header-right" @click.stop="orderAsc = !orderAsc">倒序</view>
</view>
<scroll-view scroll-y class="catalog-list">
<view v-for="(item, idx) in (orderAsc ? chapterList : [...chapterList].reverse())" :key="item.id"
@click="selectChapter(orderAsc ? idx : chapterList.length - 1 - idx)"
:class="['catalog-item', {active: (orderAsc ? idx : chapterList.length - 1 - idx) === currentIndex}]">
<view class="item-main">
<text class="item-title">{{ item.title }}</text>
<text v-if="item.vip" class="vip-tag">付费</text>
</view>
</view>
</scroll-view>
</view>
</uv-popup>
</template>
<script>
export default {
data() {
return {
chapterCount: 2814,
orderAsc : true,
currentIndex : 0,
chapterList: [{
id: 1,
title: '第一章 重回2004',
vip: false
},
{
id: 2,
title: '第二章 陈年旧恨',
vip: false
},
{
id: 3,
title: '第三章 再相见',
vip: false
},
{
id: 4,
title: '第四章 李东的邀请',
vip: false
},
{
id: 5,
title: '第五章 小气的男',
vip: false
},
{
id: 6,
title: '第六章 先送谁?',
vip: false
},
{
id: 7,
title: '第七章 打听行情',
vip: false
},
{
id: 8,
title: '第八章 省城探路',
vip: false
},
{
id: 9,
title: '第九章 订货',
vip: false
},
{
id: 10,
title: '第十章 第一桶金',
vip: true
},
{
id: 11,
title: '第十一章 高富帅来袭',
vip: true
},
{
id: 12,
title: '第十二章 故学后,挥场见!',
vip: true
},
{
id: 13,
title: '第十三章 你来我往',
vip: true
},
{
id: 14,
title: '第十四章 你来我往',
vip: true
},
{
id: 15,
title: '第十五章 你来我往',
vip: true
},
{
id: 16,
title: '第十六章 你来我往',
vip: true
},
{
id: 17,
title: '第十七章 你来我往',
vip: true
},
{
id: 18,
title: '第十八章 你来我往',
vip: true
}
]
}
},
methods: {
open() {
this.$refs.popup.open('bottom')
},
close() {
this.$refs.popup.close()
},
selectChapter(){
},
selectChapter(idx) {
this.currentIndex = idx
this.showCatalog = false
// TODO:
},
}
}
</script>
<style scoped lang="scss">
.catalog-popup-fullscreen {
position: relative;
height: 100%;
width: 100vw;
background: #fff;
display: flex;
flex-direction: column;
overflow: hidden;
.catalog-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
height: 96rpx;
border-bottom: 1px solid #eee;
position: sticky;
top: 0;
background: #fff;
z-index: 2;
}
.header-left {
width: 60rpx;
display: flex;
align-items: center;
justify-content: flex-start;
}
.header-title {
flex: 1;
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #222;
}
.header-right {
color: #223a7a;
font-size: 28rpx;
font-weight: 500;
min-width: 80rpx;
text-align: right;
}
.catalog-list {
height: calc(100% - 180rpx);
overflow: auto;
padding-bottom: 40rpx;
}
.catalog-item {
padding: 0 32rpx;
min-height: 80rpx;
display: flex;
flex-direction: column;
justify-content: center;
border-bottom: 1px solid #f5f5f5;
background: #fff;
color: #222;
font-size: 30rpx;
position: relative;
}
.catalog-item.active {
color: #ff5a5f;
background: #fff7f7;
}
.item-main {
display: flex;
align-items: center;
gap: 16rpx;
}
.item-title {
font-size: 30rpx;
}
.vip-tag {
background: #ffe1b2;
color: #ff9900;
border-radius: 20rpx;
font-size: 24rpx;
padding: 2rpx 18rpx;
margin-left: 16rpx;
}
}
</style>

+ 0
- 137
pages_order/novel/Allannouncements.vue View File

@ -1,137 +0,0 @@
<template>
<view class="announcements-container">
<uv-navbar
title="全部公告"
:autoBack="true"
fixed
placeholder
titleStyle="color: #333; font-weight: 500;"
:border="false"
></uv-navbar>
<view class="announcements-list">
<view
class="announcement-item"
v-for="(item, index) in announcements"
:key="index"
@click="viewAnnouncement(item)"
>
<view class="item-left">
<text class="tag">通讯</text>
<text class="title">{{ item.title }}</text>
</view>
<view class="item-right">
<uv-icon name="arrow-right" color="#C8C8C8" size="28rpx"></uv-icon>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
'uv-navbar': () => import('@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue')
},
data() {
return {
announcements: [
{
id: 1,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 2,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 3,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 4,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 5,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 6,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
},
{
id: 7,
title: '2025年2月平台福利活动拟获奖作品公示',
type: '通讯'
}
]
}
},
methods: {
viewAnnouncement(item) {
uni.navigateTo({
url: `/pages_order/novel/announcement?id=${item.id}`
})
}
}
}
</script>
<style lang="scss">
.announcements-container {
min-height: 100vh;
background-color: #F8F8F8;
.announcements-list {
padding: 20rpx;
.announcement-item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #FFFFFF;
padding: 30rpx;
margin-bottom: 20rpx;
border-radius: 12rpx;
.item-left {
flex: 1;
margin-right: 20rpx;
.tag {
display: inline-block;
font-size: 24rpx;
color: #666666;
background-color: #F5F5F5;
padding: 4rpx 12rpx;
border-radius: 6rpx;
margin-bottom: 16rpx;
}
.title {
display: block;
font-size: 28rpx;
color: #333333;
line-height: 1.4;
}
}
.item-right {
display: flex;
align-items: center;
}
&:active {
background-color: #F9F9F9;
}
}
}
}
</style>

+ 0
- 180
pages_order/novel/Mycomment.vue View File

@ -1,180 +0,0 @@
<template>
<view class="my-comment-page">
<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="'unread-' + 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>
</view>
<view class="comment-section history-section">
<view class="section-title">历史评论</view>
<view v-for="(item, idx) in historyComments" :key="'history-' + 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>
</view>
</view>
</template>
<script>
import navbar from '@/components/base/navbar.vue'
export default {
components: { navbar },
data() {
return {
unreadComments: [
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '方香橙',
bookTitle: '重生之财富滚滚',
content: '我是本书的作者方香橙,这是一本甜文爽文哒!请放心入坑,五星好评!女主又美有个性可爱,绝对不圣母,不傻白!男主身心干净深情独宠媳妇儿一个人...',
time: '2024.07.09'
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '战斗世界',
bookTitle: '重生之财富滚滚',
content: '这本书打破了我看甜文套路之前的观念女主真的太可爱太有趣和以往看过的一个NPC介绍有很大不同',
time: '2024.06.09'
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
username: '战斗世界',
bookTitle: '重生之财富滚滚',
content: '这本书打破了我看甜文套路之前的观念女主真的太可爱太有趣和以往看过的一个NPC介绍有很大不同',
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>
<style scoped lang="scss">
.my-comment-page {
min-height: 100vh;
background: #f8f8f8;
display: flex;
flex-direction: column;
}
.comment-section {
background: #fff;
margin: 24rpx 24rpx 0 24rpx;
border-radius: 16rpx;
padding: 24rpx 24rpx 0 24rpx;
margin-bottom: 24rpx;
}
.section-title {
color: #222;
font-size: 28rpx;
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>

+ 213
- 185
pages_order/novel/ReaderAchievement.vue View File

@ -1,192 +1,220 @@
<template>
<view class="achievement-page">
<uv-navbar title="读者成就设置" fixed placeholder></uv-navbar>
<view class="achievement-card">
<view class="card-title-row">
<view class="card-title">阅读成就设置</view>
<view v-if="isPending" class="pending-tag">设置审核中</view>
</view>
<view class="achievement-list">
<view class="achievement-item">
<image class="badge-img" src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7" mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">一级成就名称</text>
</view>
<input class="input" v-model="level1" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
<view class="divider"></view>
<view class="achievement-item">
<image class="badge-img" src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7" mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">二级成就名称</text>
</view>
<input class="input" v-model="level2" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
<view class="divider"></view>
<view class="achievement-item">
<image class="badge-img" src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7" mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">三级成就名称</text>
</view>
<input class="input" v-model="level3" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
</view>
</view>
<view class="bottom-btn-area">
<button class="submit-btn" :disabled="isPending" :class="{disabled: isPending, pending: isPending}" @click="submit">
{{ isPending ? '设置' : '提交申请' }}
</button>
</view>
</view>
<view class="achievement-page">
<uv-navbar title="读者成就设置" fixed placeholder></uv-navbar>
<view class="achievement-card">
<view class="card-title-row">
<view class="card-title">阅读成就设置</view>
<view v-if="isPending" class="pending-tag">设置审核中</view>
</view>
<view class="achievement-list">
<view class="achievement-item">
<image class="badge-img"
src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7"
mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">一级成就名称</text>
</view>
<input class="input" v-model="level1" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
<view class="divider"></view>
<view class="achievement-item">
<image class="badge-img"
src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7"
mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">二级成就名称</text>
</view>
<input class="input" v-model="level2" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
<view class="divider"></view>
<view class="achievement-item">
<image class="badge-img"
src="https://tse3-mm.cn.bing.net/th/id/OIP-C.wUsFZgl70iE4tI7b_HKaKgHaHa?w=166&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7"
mode="aspectFill" />
<view class="input-area">
<view class="label-row">
<text class="required">*</text>
<text class="label">三级成就名称</text>
</view>
<input class="input" v-model="level3" placeholder="请输入" placeholder-class="input-placeholder" />
</view>
</view>
</view>
</view>
<view class="bottom-btn-area">
<button class="submit-btn" :disabled="isPending" :class="{disabled: isPending, pending: isPending}"
@click="submit">
{{ isPending ? '设置' : '提交申请' }}
</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
level1: '',
level2: '',
level3: '',
isPending: false
}
},
methods: {
submit() {
if (!this.level1 || !this.level2 || !this.level3) {
uni.showToast({ title: '请填写所有成就名称', icon: 'none' })
return
}
this.isPending = true
//
}
}
}
export default {
data() {
return {
level1: '',
level2: '',
level3: '',
isPending: false
}
},
methods: {
submit() {
if (!this.level1 || !this.level2 || !this.level3) {
uni.showToast({
title: '请填写所有成就名称',
icon: 'none'
})
return
}
this.isPending = true
//
}
}
}
</script>
<style scoped lang="scss">
.achievement-page {
min-height: 100vh;
background: #f7f8fa;
display: flex;
flex-direction: column;
}
.achievement-card {
background: #fff;
border-radius: 20rpx;
margin: 40rpx 32rpx 0 32rpx;
padding: 32rpx 24rpx;
box-shadow: 0 4rpx 24rpx 0 rgba(0,0,0,0.04);
}
.card-title-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.card-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 32rpx;
}
.achievement-list {
display: flex;
flex-direction: column;
gap: 0;
}
.achievement-item {
display: flex;
align-items: flex-start;
padding: 18rpx 0 10rpx 0;
}
.badge-img {
width: 72rpx;
height: 72rpx;
margin-right: 20rpx;
border-radius: 50%;
background: #f5f5f5;
object-fit: cover;
border: 2rpx solid #fff;
box-shadow: 0 2rpx 8rpx 0 rgba(0,0,0,0.04);
}
.input-area {
margin-top: 15rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.label-row {
display: flex;
align-items: center;
margin-bottom: 6rpx;
}
.required {
color: #e23d3d;
font-size: 28rpx;
margin-right: 4rpx;
}
.label {
font-size: 28rpx;
color: #222;
font-weight: bold;
}
.input {
width: 100%;
border: none;
border-bottom: 1.5rpx solid #ececec;
font-size: 28rpx;
background: transparent;
padding: 8rpx 0 6rpx 0;
margin-bottom: 2rpx;
}
.input-placeholder {
color: #d2d2d2;
font-size: 26rpx;
}
.divider {
height: 1rpx;
background: #f3f3f3;
margin: 0 0 0 92rpx;
}
.bottom-btn-area {
margin-top: auto;
padding: 48rpx 32rpx 32rpx 32rpx;
background: transparent;
}
.submit-btn {
width: 100%;
height: 88rpx;
background: #0a2e6d;
color: #fff;
font-size: 32rpx;
border-radius: 44rpx;
font-weight: bold;
letter-spacing: 2rpx;
transition: background 0.2s;
}
.submit-btn.disabled {
background: #807a7a;
color: #fff;
}
.submit-btn.pending {
background: #0a226d;
color: #fff;
}
.pending-tag {
background: #807a7a;
color: #fff;
font-size: 24rpx;
border-radius: 10rpx;
padding: 6rpx 24rpx;
margin-left: 20rpx;
margin-bottom: 32rpx;
}
</style>
.achievement-page {
min-height: 100vh;
background: #f7f8fa;
display: flex;
flex-direction: column;
}
.achievement-card {
background: #fff;
border-radius: 20rpx;
margin: 40rpx 32rpx 0 32rpx;
padding: 32rpx 24rpx;
box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.04);
}
.card-title-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.card-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 32rpx;
}
.achievement-list {
display: flex;
flex-direction: column;
gap: 0;
}
.achievement-item {
display: flex;
align-items: flex-start;
padding: 18rpx 0 10rpx 0;
}
.badge-img {
width: 72rpx;
height: 72rpx;
margin-right: 20rpx;
border-radius: 50%;
background: #f5f5f5;
object-fit: cover;
border: 2rpx solid #fff;
box-shadow: 0 2rpx 8rpx 0 rgba(0, 0, 0, 0.04);
}
.input-area {
margin-top: 15rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.label-row {
display: flex;
align-items: center;
margin-bottom: 6rpx;
}
.required {
color: #e23d3d;
font-size: 28rpx;
margin-right: 4rpx;
}
.label {
font-size: 28rpx;
color: #222;
font-weight: bold;
}
.input {
width: 100%;
border: none;
border-bottom: 1.5rpx solid #ececec;
font-size: 28rpx;
background: transparent;
padding: 8rpx 0 6rpx 0;
margin-bottom: 2rpx;
}
.input-placeholder {
color: #d2d2d2;
font-size: 26rpx;
}
.divider {
height: 1rpx;
background: #f3f3f3;
margin: 0 0 0 92rpx;
}
.bottom-btn-area {
margin-top: auto;
padding: 48rpx 32rpx 32rpx 32rpx;
background: transparent;
}
.submit-btn {
width: 100%;
height: 88rpx;
background: #0a2e6d;
color: #fff;
font-size: 32rpx;
border-radius: 44rpx;
font-weight: bold;
letter-spacing: 2rpx;
transition: background 0.2s;
}
.submit-btn.disabled {
background: #807a7a;
color: #fff;
}
.submit-btn.pending {
background: #0a226d;
color: #fff;
}
.pending-tag {
background: #807a7a;
color: #fff;
font-size: 24rpx;
border-radius: 10rpx;
padding: 6rpx 24rpx;
margin-left: 20rpx;
margin-bottom: 32rpx;
}
</style>

+ 182
- 160
pages_order/novel/Review.vue View File

@ -1,167 +1,189 @@
<template>
<view class="review-page">
<!-- 顶部导航栏 -->
<navbar title="写书评" :leftClick="true" @leftClick="goBack" />
<view class="review-content">
<view class="book-title-label">书本名称</view>
<view class="book-title">{{ bookTitle }}</view>
<view class="form-area flex-grow">
<view class="form-label-row">
<text class="required-star">*</text>
<text class="form-label">书评内容</text>
</view>
<textarea v-model="form.content" class="review-textarea custom-placeholder full-textarea" placeholder="请输入书评内容" />
</view>
</view>
<view class="review-footer">
<view class="footer-divider"></view>
<button class="submit-btn" @click="submitReview">发布</button>
</view>
</view>
<view class="review-page">
<!-- 顶部导航栏 -->
<navbar title="写书评" :leftClick="true" @leftClick="goBack" />
<view class="review-content">
<view class="book-title-label">书本名称</view>
<view class="book-title">{{ bookTitle }}</view>
<view class="form-area flex-grow">
<view class="form-label-row">
<text class="required-star">*</text>
<text class="form-label">书评内容</text>
</view>
<textarea v-model="form.content" class="review-textarea custom-placeholder full-textarea"
placeholder="请输入书评内容" />
</view>
</view>
<view class="review-footer">
<view class="footer-divider"></view>
<button class="submit-btn" @click="submitReview">发布</button>
</view>
</view>
</template>
<script>
import navbar from '@/components/base/navbar.vue'
export default {
components: { navbar },
data() {
return {
bookTitle: '',
form: {
content: ''
},
rules: {
content: [
{ required: true, message: '请输入书评内容', trigger: ['blur', 'change'] }
]
}
}
},
onLoad(options) {
//
this.bookTitle = options.title || '未知书名'
},
methods: {
goBack() {
uni.navigateBack()
},
submitReview() {
this.$refs.reviewForm.validate().then(() => {
// API
uni.showToast({ title: '发布成功', icon: 'success' })
setTimeout(() => {
uni.navigateBack()
}, 1000)
}).catch(() => {})
}
}
}
import navbar from '@/components/base/navbar.vue'
export default {
components: {
navbar
},
data() {
return {
bookTitle: '',
form: {
content: ''
},
rules: {
content: [{
required: true,
message: '请输入书评内容',
trigger: ['blur', 'change']
}]
}
}
},
onLoad(options) {
//
this.bookTitle = options.title || '未知书名'
},
methods: {
goBack() {
uni.navigateBack()
},
submitReview() {
this.$refs.reviewForm.validate().then(() => {
// API
uni.showToast({
title: '发布成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack()
}, 1000)
}).catch(() => {})
}
}
}
</script>
<style scoped lang="scss">
.review-page {
min-height: 100vh;
background: #f8f8f8;
display: flex;
flex-direction: column;
margin-top: -50rpx;
}
.review-content {
background: #fff;
margin: 24rpx 24rpx 0 24rpx;
border-radius: 16rpx;
padding: 32rpx 24rpx 24rpx 24rpx;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
padding-bottom: 140rpx;
margin-top: calc(var(--status-bar-height, 0px) + 100rpx);
}
.flex-grow {
flex: 1 1 0;
display: flex;
flex-direction: column;
min-height: 0;
}
.book-title-label {
color: #bdbdbd;
font-size: 24rpx;
margin-bottom: 4rpx;
}
.book-title {
font-size: 28rpx;
color: #222;
margin-bottom: 36rpx;
border-bottom: 1px solid #ededed;
padding-bottom: 8rpx;
}
.form-area {
margin-top: 18rpx;
}
.form-label-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.required-star {
color: #e23d3d;
font-size: 22rpx;
margin-right: 4rpx;
line-height: 1;
}
.form-label {
color: #222;
font-size: 26rpx;
font-weight: 400;
}
.review-textarea {
width: 100%;
min-height: 320rpx;
border: none;
background: transparent;
font-size: 28rpx;
color: #333;
resize: none;
margin-top: 0;
outline: none;
}
.review-textarea.custom-placeholder::placeholder {
color: #d2d2d2;
font-size: 26rpx;
}
.full-textarea {
flex: 1;
min-height: 0;
max-height: none;
box-sizing: border-box;
margin-bottom: 0;
}
.review-footer {
position: fixed;
left: 0;
right: 0;
bottom: 90rpx;
background: #fff;
padding: 24rpx 32rpx 32rpx 32rpx;
box-shadow: 0 -2rpx 12rpx rgba(0,0,0,0.03);
z-index: 10;
}
.footer-divider {
width: 100%;
height: 2rpx;
background: #f2f2f2;
margin-bottom: 24rpx;
}
.submit-btn {
width: 100%;
height: 80rpx;
background: #0a225f;
color: #fff;
font-size: 30rpx;
border-radius: 40rpx;
font-weight: 500;
letter-spacing: 2rpx;
}
</style>
.review-page {
min-height: 100vh;
background: #f8f8f8;
display: flex;
flex-direction: column;
margin-top: -50rpx;
}
.review-content {
background: #fff;
margin: 24rpx 24rpx 0 24rpx;
border-radius: 16rpx;
padding: 32rpx 24rpx 24rpx 24rpx;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
padding-bottom: 140rpx;
margin-top: calc(var(--status-bar-height, 0px) + 100rpx);
}
.flex-grow {
flex: 1 1 0;
display: flex;
flex-direction: column;
min-height: 0;
}
.book-title-label {
color: #bdbdbd;
font-size: 24rpx;
margin-bottom: 4rpx;
}
.book-title {
font-size: 28rpx;
color: #222;
margin-bottom: 36rpx;
border-bottom: 1px solid #ededed;
padding-bottom: 8rpx;
}
.form-area {
margin-top: 18rpx;
}
.form-label-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.required-star {
color: #e23d3d;
font-size: 22rpx;
margin-right: 4rpx;
line-height: 1;
}
.form-label {
color: #222;
font-size: 26rpx;
font-weight: 400;
}
.review-textarea {
width: 100%;
min-height: 320rpx;
border: none;
background: transparent;
font-size: 28rpx;
color: #333;
resize: none;
margin-top: 0;
outline: none;
}
.review-textarea.custom-placeholder::placeholder {
color: #d2d2d2;
font-size: 26rpx;
}
.full-textarea {
flex: 1;
min-height: 0;
max-height: none;
box-sizing: border-box;
margin-bottom: 0;
}
.review-footer {
position: fixed;
left: 0;
right: 0;
bottom: 90rpx;
background: #fff;
padding: 24rpx 32rpx 32rpx 32rpx;
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.03);
z-index: 10;
}
.footer-divider {
width: 100%;
height: 2rpx;
background: #f2f2f2;
margin-bottom: 24rpx;
}
.submit-btn {
width: 100%;
height: 80rpx;
background: #0a225f;
color: #fff;
font-size: 30rpx;
border-radius: 40rpx;
font-weight: 500;
letter-spacing: 2rpx;
}
</style>

+ 256
- 221
pages_order/novel/SubscriptionInformation.vue View File

@ -1,228 +1,263 @@
<template>
<view class="subscription-info-container">
<uv-navbar title="订阅信息" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;" :border="false" leftIconSize="46" />
<view class="content-area">
<view class="card">
<view class="section-title">订阅章节</view>
<view class="row row-split">
<template v-if="!showBatch">
<text class="label">章节名称</text>
<view class="row-content">
<text class="value">第1章 2004</text>
<text class="batch-link" @click="showBatch = true">批量订阅</text>
</view>
</template>
<template v-else>
<view class="batch-row">
<view class="batch-left">
<text class="star">*</text>
<text class="batch-title">批量订阅</text>
</view>
</view>
<view class="batch-input-row">
<input class="batch-input" v-model="batchCount" placeholder="请输入订阅数" placeholder-class="batch-placeholder" />
<text class="batch-action" @click="batchSubscribeAction">订阅本章</text>
</view>
<view class="batch-divider"></view>
</template>
</view>
<view class="row row-split">
<text class="label">章节信息</text>
<view class="row-content">
<text class="value">本次订阅消耗10 豆豆</text>
</view>
</view>
<view class="row">
<text class="label">支付方式</text>
<view class="row-content">
<text class="value">账户余额0 豆豆</text>
</view>
</view>
</view>
<view class="card order-info">
<view class="section-title">订单信息</view>
<view class="row">
<text class="label">内容</text>
</view>
<view class="row">
<text class="price"><span class="total-label">合计</span><span class="total-amount">0.10 </span></text>
</view>
</view>
<view class="tips">
请仔细检查并确认相关信息因用户个人疏忽导致的充值错误章节用户自行承担一旦完成充值概不退换
</view>
</view>
<button class="pay-btn" @click="payAndSubscribe">支付并订阅</button>
</view>
<view class="subscription-info-container">
<uv-navbar title="订阅信息" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;"
:border="false" leftIconSize="46" />
<view class="content-area">
<view class="card">
<view class="section-title">订阅章节</view>
<view class="row row-split">
<template v-if="!showBatch">
<text class="label">章节名称</text>
<view class="row-content">
<text class="value">第1章 2004</text>
<text class="batch-link" @click="showBatch = true">批量订阅</text>
</view>
</template>
<template v-else>
<view class="batch-row">
<view class="batch-left">
<text class="star">*</text>
<text class="batch-title">批量订阅</text>
</view>
</view>
<view class="batch-input-row">
<input class="batch-input" v-model="batchCount" placeholder="请输入订阅数"
placeholder-class="batch-placeholder" />
<text class="batch-action" @click="batchSubscribeAction">订阅本章</text>
</view>
<view class="batch-divider"></view>
</template>
</view>
<view class="row row-split">
<text class="label">章节信息</text>
<view class="row-content">
<text class="value">本次订阅消耗10 豆豆</text>
</view>
</view>
<view class="row">
<text class="label">支付方式</text>
<view class="row-content">
<text class="value">账户余额0 豆豆</text>
</view>
</view>
</view>
<view class="card order-info">
<view class="section-title">订单信息</view>
<view class="row">
<text class="label">内容</text>
</view>
<view class="row">
<text class="price"><span class="total-label">合计</span><span class="total-amount">0.10
</span></text>
</view>
</view>
<view class="tips">
请仔细检查并确认相关信息因用户个人疏忽导致的充值错误章节用户自行承担一旦完成充值概不退换
</view>
</view>
<button class="pay-btn" @click="payAndSubscribe">支付并订阅</button>
</view>
</template>
<script>
export default {
data() {
return {
showBatch: false,
batchCount: ''
}
},
methods: {
batchSubscribe() {
uni.showToast({ title: '批量订阅功能开发中', icon: 'none' })
},
batchSubscribeAction() {
// Implementation of batchSubscribeAction method
},
payAndSubscribe() {
uni.showToast({ title: '支付成功,已订阅', icon: 'success' })
//
}
}
}
export default {
data() {
return {
showBatch: false,
batchCount: ''
}
},
methods: {
batchSubscribe() {
uni.showToast({
title: '批量订阅功能开发中',
icon: 'none'
})
},
batchSubscribeAction() {
// Implementation of batchSubscribeAction method
},
payAndSubscribe() {
uni.showToast({
title: '支付成功,已订阅',
icon: 'success'
})
//
}
}
}
</script>
<style scoped>
.subscription-info-container {
background: #f8f8f8;
height: 100vh;
overflow: hidden;
position: relative;
}
.content-area {
padding-bottom: 180rpx;
}
body {
overflow: hidden;
}
.card {
background: #fff;
border-radius: 24rpx;
margin: 32rpx 24rpx 0 24rpx;
padding: 32rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #222;
margin-bottom: 24rpx;
}
.row {
display: flex;
flex-direction: column;
padding: 10rpx 0;
margin-top: 10rpx;
}
.row-split {
border-bottom: 1px solid #f0f0f0;
}
.label {
color: #888;
font-size: 26rpx;
margin-bottom: 4rpx;
margin-top: 20rpx;
}
.row-content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.value {
color: #222;
font-size: 26rpx;
}
.batch-link {
color: #3478f6;
font-size: 24rpx;
margin-left: 24rpx;
}
.order-info {
margin-top: 32rpx;
}
.order-row {
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 10rpx 0;
}
.price {
font-size: 28rpx;
margin-left: 0;
}
.total-label {
color: #222;
}
.total-amount {
color: #ff6600;
}
.tips {
color: #bbb;
font-size: 22rpx;
margin: 32rpx 24rpx 0 24rpx;
line-height: 1.6;
}
.pay-btn {
position: fixed;
left: 24rpx;
right: 24rpx;
bottom: 90rpx;
background: #0a297e;
color: #fff;
font-size: 32rpx;
border-radius: 40rpx;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-weight: bold;
z-index: 100;
}
.batch-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0;
}
.batch-left {
display: flex;
align-items: center;
}
.star {
color: #f5222d;
margin-right: 6rpx;
font-size: 26rpx;
}
.batch-title {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
.batch-action {
color: #3478f6;
font-size: 24rpx;
margin-left: 24rpx;
}
.batch-input-row {
display: flex;
align-items: center;
margin-top: 4rpx;
}
.batch-input {
flex: 1;
border: none;
font-size: 24rpx;
color: #bbb;
background: transparent;
outline: none;
padding: 0;
height: 40rpx;
}
.batch-placeholder {
color: #bbb;
font-size: 24rpx;
}
.batch-divider {
height: 2rpx;
background: #f0f0f0;
width: 100%;
margin-top: 4rpx;
}
</style>
.subscription-info-container {
background: #f8f8f8;
height: 100vh;
overflow: hidden;
position: relative;
}
.content-area {
padding-bottom: 180rpx;
}
body {
overflow: hidden;
}
.card {
background: #fff;
border-radius: 24rpx;
margin: 32rpx 24rpx 0 24rpx;
padding: 32rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #222;
margin-bottom: 24rpx;
}
.row {
display: flex;
flex-direction: column;
padding: 10rpx 0;
margin-top: 10rpx;
}
.row-split {
border-bottom: 1px solid #f0f0f0;
}
.label {
color: #888;
font-size: 26rpx;
margin-bottom: 4rpx;
margin-top: 20rpx;
}
.row-content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.value {
color: #222;
font-size: 26rpx;
}
.batch-link {
color: #3478f6;
font-size: 24rpx;
margin-left: 24rpx;
}
.order-info {
margin-top: 32rpx;
}
.order-row {
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 10rpx 0;
}
.price {
font-size: 28rpx;
margin-left: 0;
}
.total-label {
color: #222;
}
.total-amount {
color: #ff6600;
}
.tips {
color: #bbb;
font-size: 22rpx;
margin: 32rpx 24rpx 0 24rpx;
line-height: 1.6;
}
.pay-btn {
position: fixed;
left: 24rpx;
right: 24rpx;
bottom: 90rpx;
background: #0a297e;
color: #fff;
font-size: 32rpx;
border-radius: 40rpx;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-weight: bold;
z-index: 100;
}
.batch-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0;
}
.batch-left {
display: flex;
align-items: center;
}
.star {
color: #f5222d;
margin-right: 6rpx;
font-size: 26rpx;
}
.batch-title {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
.batch-action {
color: #3478f6;
font-size: 24rpx;
margin-left: 24rpx;
}
.batch-input-row {
display: flex;
align-items: center;
margin-top: 4rpx;
}
.batch-input {
flex: 1;
border: none;
font-size: 24rpx;
color: #bbb;
background: transparent;
outline: none;
padding: 0;
height: 40rpx;
}
.batch-placeholder {
color: #bbb;
font-size: 24rpx;
}
.batch-divider {
height: 2rpx;
background: #f0f0f0;
width: 100%;
margin-top: 4rpx;
}
</style>

+ 272
- 226
pages_order/novel/Tipping.vue View File

@ -1,233 +1,279 @@
<template>
<view class="tipping-page">
<!-- 顶部导航栏 -->
<uv-navbar title="读者亲密值榜单" fixed placeholder></uv-navbar>
<!-- 榜单前三名 -->
<view class="top-three">
<view class="top-item second">
<image class="avatar" :src="topList[1].avatar" mode="aspectFill" />
<view class="name">{{ topList[1].name }}</view>
<view class="score">{{ topList[1].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
<view class="top-item first">
<image class="avatar" :src="topList[0].avatar" mode="aspectFill" />
<view class="name">{{ topList[0].name }}</view>
<view class="score">{{ topList[0].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
<view class="top-item third">
<image class="avatar" :src="topList[2].avatar" mode="aspectFill" />
<view class="name">{{ topList[2].name }}</view>
<view class="score">{{ topList[2].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
</view>
<!-- 榜单列表 -->
<view class="rank-list">
<RankListItem
v-for="(item, idx) in rankList"
:key="item.id"
:rankIcon="idx < 3 ? rankIcons[idx] : ''"
:rankNumImg="idx >= 3 ? ('/static/rank-num-' + (idx+1) + '.png') : ''"
medal="/static/medal.png"
:avatar="item.avatar"
:name="item.name"
:score="item.score"
level="护书使者 五级"
/>
</view>
<!-- 底部按钮 -->
<view class="bottom-btn-area">
<button class="tipping-btn">互动打赏</button>
</view>
</view>
<view class="tipping-page">
<!-- 顶部导航栏 -->
<uv-navbar title="读者亲密值榜单" fixed placeholder></uv-navbar>
<!-- 榜单前三名 -->
<view class="top-three">
<view class="top-item second">
<image class="avatar" :src="topList[1].avatar" mode="aspectFill" />
<view class="name">{{ topList[1].name }}</view>
<view class="score">{{ topList[1].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
<view class="top-item first">
<image class="avatar" :src="topList[0].avatar" mode="aspectFill" />
<view class="name">{{ topList[0].name }}</view>
<view class="score">{{ topList[0].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
<view class="top-item third">
<image class="avatar" :src="topList[2].avatar" mode="aspectFill" />
<view class="name">{{ topList[2].name }}</view>
<view class="score">{{ topList[2].score }} 亲密值</view>
<view class="level">护书使者 五级</view>
</view>
</view>
<!-- 榜单列表 -->
<view class="rank-list">
<RankListItem v-for="(item, idx) in rankList" :key="item.id" :rankIcon="idx < 3 ? rankIcons[idx] : ''"
:rankNumImg="idx >= 3 ? ('/static/rank-num-' + (idx+1) + '.png') : ''" medal="/static/medal.png"
:avatar="item.avatar" :name="item.name" :score="item.score" level="护书使者 五级" />
</view>
<!-- 底部按钮 -->
<view class="bottom-btn-area">
<button class="tipping-btn">互动打赏</button>
</view>
</view>
</template>
<script>
import RankListItem from '@/components/novel/RankListItem.vue'
export default {
components: { RankListItem },
data() {
return {
topList: [
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '周海',
score: 6785452
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '冯冉冉',
score: 6785452
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '南静',
score: 6785452
}
],
rankList: [
{ id: 4, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '钱胡胡', score: 5325324 },
{ id: 5, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '冯艺瑄', score: 4819704 },
{ id: 6, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '王凡宏', score: 4696874 },
{ id: 7, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '辛书萍', score: 3722953 },
{ id: 8, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '李婷', score: 2872476 },
{ id: 9, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '郑盈', score: 2464869 },
{ id: 10, avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain', name: '吴承联', score: 990238 }
],
rankIcons: [
'https://img.yzcdn.cn/vant/rank-1.png',
'https://img.yzcdn.cn/vant/rank-2.png',
'https://img.yzcdn.cn/vant/rank-3.png'
]
}
}
}
import RankListItem from '@/components/novel/RankListItem.vue'
export default {
components: {
RankListItem
},
data() {
return {
topList: [{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '周海',
score: 6785452
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '冯冉冉',
score: 6785452
},
{
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '南静',
score: 6785452
}
],
rankList: [{
id: 4,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '钱胡胡',
score: 5325324
},
{
id: 5,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '冯艺瑄',
score: 4819704
},
{
id: 6,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '王凡宏',
score: 4696874
},
{
id: 7,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '辛书萍',
score: 3722953
},
{
id: 8,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '李婷',
score: 2872476
},
{
id: 9,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '郑盈',
score: 2464869
},
{
id: 10,
avatar: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
name: '吴承联',
score: 990238
}
],
rankIcons: [
'https://img.yzcdn.cn/vant/rank-1.png',
'https://img.yzcdn.cn/vant/rank-2.png',
'https://img.yzcdn.cn/vant/rank-3.png'
]
}
}
}
</script>
<style lang="scss" scoped>
.tipping-page {
min-height: 100vh;
background: linear-gradient(180deg, #b86e3b 0%, #e6b07c 100%);
padding-bottom: 40rpx;
}
.top-three {
display: flex;
justify-content: center;
align-items: flex-end;
margin: 40rpx 0 20rpx 0;
.top-item {
display: flex;
flex-direction: column;
align-items: center;
background: #fff7e0;
border-radius: 20rpx;
margin: 0 16rpx;
padding: 24rpx 18rpx 18rpx 18rpx;
box-shadow: 0 4rpx 16rpx 0 rgba(0,0,0,0.08);
position: relative;
width: 180rpx;
.avatar {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
border: 4rpx solid #ffd700;
margin-bottom: 10rpx;
}
.name {
font-size: 28rpx;
font-weight: bold;
color: #b86e3b;
margin-bottom: 6rpx;
}
.score {
font-size: 24rpx;
color: #e6b07c;
margin-bottom: 4rpx;
}
.level {
font-size: 22rpx;
color: #b86e3b;
background: #ffe7b2;
border-radius: 10rpx;
padding: 2rpx 12rpx;
}
}
.first {
transform: scale(1.15);
z-index: 2;
background: #fffbe6;
box-shadow: 0 8rpx 24rpx 0 rgba(255,215,0,0.18);
}
.second, .third {
z-index: 1;
opacity: 0.95;
}
}
.rank-list {
background: transparent;
margin: 0 24rpx;
margin-top: 20rpx;
.rank-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fffbe6;
border-radius: 16rpx;
margin-bottom: 18rpx;
box-shadow: 0 2rpx 8rpx 0 rgba(184,110,59,0.06);
padding: 0 24rpx;
height: 100rpx;
.rank-left {
display: flex;
align-items: center;
.rank-icon, .rank-num-img {
width: 38rpx;
height: 38rpx;
margin-right: 10rpx;
}
.medal {
width: 44rpx;
height: 44rpx;
margin-right: 10rpx;
}
.avatar {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
margin-right: 14rpx;
border: 2rpx solid #ffd700;
object-fit: cover;
}
.name {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
}
.rank-right {
display: flex;
flex-direction: column;
align-items: flex-end;
.score {
font-size: 22rpx;
color: #b86e3b;
}
.level {
font-size: 20rpx;
color: #fff;
background: #e6b07c;
border-radius: 8rpx;
padding: 2rpx 10rpx;
margin-top: 6rpx;
font-weight: 500;
}
}
}
}
.bottom-btn-area {
margin: 40rpx 24rpx 90rpx 24rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
.tipping-btn {
width: 100%;
height: 80rpx;
background: #fffbe6;
color: #b86e3b;
font-size: 32rpx;
border-radius: 40rpx;
font-weight: bold;
letter-spacing: 2rpx;
box-shadow: 0 4rpx 16rpx 0 rgba(184,110,59,0.12);
border: none;
}
}
</style>
.tipping-page {
min-height: 100vh;
background: linear-gradient(180deg, #b86e3b 0%, #e6b07c 100%);
padding-bottom: 40rpx;
}
.top-three {
display: flex;
justify-content: center;
align-items: flex-end;
margin: 40rpx 0 20rpx 0;
.top-item {
display: flex;
flex-direction: column;
align-items: center;
background: #fff7e0;
border-radius: 20rpx;
margin: 0 16rpx;
padding: 24rpx 18rpx 18rpx 18rpx;
box-shadow: 0 4rpx 16rpx 0 rgba(0, 0, 0, 0.08);
position: relative;
width: 180rpx;
.avatar {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
border: 4rpx solid #ffd700;
margin-bottom: 10rpx;
}
.name {
font-size: 28rpx;
font-weight: bold;
color: #b86e3b;
margin-bottom: 6rpx;
}
.score {
font-size: 24rpx;
color: #e6b07c;
margin-bottom: 4rpx;
}
.level {
font-size: 22rpx;
color: #b86e3b;
background: #ffe7b2;
border-radius: 10rpx;
padding: 2rpx 12rpx;
}
}
.first {
transform: scale(1.15);
z-index: 2;
background: #fffbe6;
box-shadow: 0 8rpx 24rpx 0 rgba(255, 215, 0, 0.18);
}
.second,
.third {
z-index: 1;
opacity: 0.95;
}
}
.rank-list {
background: transparent;
margin: 0 24rpx;
margin-top: 20rpx;
.rank-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fffbe6;
border-radius: 16rpx;
margin-bottom: 18rpx;
box-shadow: 0 2rpx 8rpx 0 rgba(184, 110, 59, 0.06);
padding: 0 24rpx;
height: 100rpx;
.rank-left {
display: flex;
align-items: center;
.rank-icon,
.rank-num-img {
width: 38rpx;
height: 38rpx;
margin-right: 10rpx;
}
.medal {
width: 44rpx;
height: 44rpx;
margin-right: 10rpx;
}
.avatar {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
margin-right: 14rpx;
border: 2rpx solid #ffd700;
object-fit: cover;
}
.name {
font-size: 26rpx;
color: #222;
font-weight: 500;
}
}
.rank-right {
display: flex;
flex-direction: column;
align-items: flex-end;
.score {
font-size: 22rpx;
color: #b86e3b;
}
.level {
font-size: 20rpx;
color: #fff;
background: #e6b07c;
border-radius: 8rpx;
padding: 2rpx 10rpx;
margin-top: 6rpx;
font-weight: 500;
}
}
}
}
.bottom-btn-area {
margin: 40rpx 24rpx 90rpx 24rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
.tipping-btn {
width: 100%;
height: 80rpx;
background: #fffbe6;
color: #b86e3b;
font-size: 32rpx;
border-radius: 40rpx;
font-weight: bold;
letter-spacing: 2rpx;
box-shadow: 0 4rpx 16rpx 0 rgba(184, 110, 59, 0.12);
border: none;
}
}
</style>

+ 330
- 292
pages_order/novel/Translation.vue View File

@ -1,299 +1,337 @@
<template>
<view class="page-container">
<view class="task-center">
<uv-navbar
title="任务中心"
:autoBack="true"
fixed
placeholder
titleStyle="color: #222; font-weight: 500;"
:border="false"
:bgColor="'#fff9e2'"
>
<template #left>
<BackArrow :size="56" color="#222" @back="goBack" />
</template>
</uv-navbar>
<view class="navbar-placeholder"></view>
<!-- 账户剩余 -->
<view class="account-balance">
<view class="balance-label">账户剩余</view>
<view class="balance-value"><text class="num">9</text> <text class="unit"> 推荐票</text></view>
</view>
<!-- 打卡得奖励 -->
<view class="checkin-section">
<view class="section-header">
<text>打卡得奖励</text>
<view class="record-btn">打卡记录</view>
</view>
<view class="checkin-grid">
<view v-for="day in 8" :key="day" class="checkin-day" :class="{ active: day <= checkedDays }">
<view class="day-label" :class="{ bold: day <= checkedDays }">{{ day }}</view>
<image class="ticket-img" src="https://tse1-mm.cn.bing.net/th/id/OIP-C.pca_tFb6ZjyDNdQYgFvi0wHaE7?w=219&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7" mode="aspectFit" />
<view class="ticket-num">+1</view>
</view>
</view>
<button
class="checkin-btn"
:class="{ 'checked-btn': isChecked }"
:disabled="isChecked"
@click="handleCheckin"
>
{{ isChecked ? '已签到' : '签到得奖励' }}
</button>
</view>
<!-- 更多任务 -->
<view class="more-tasks">
<view class="more-header">更多任务</view>
<view class="task-list">
<view class="task-item" v-for="(task, idx) in tasks" :key="idx" :class="{ 'no-border': idx === tasks.length - 1 }">
<view class="task-info">
<view class="task-title">{{ task.title }}</view>
<view class="task-desc">推荐票 +1</view>
</view>
<button
class="get-btn"
:class="{ 'received-btn': task.received }"
:disabled="task.received"
@click="handleReceive(idx)"
>
{{ task.received ? '已领取' : '去领取' }}
</button>
</view>
</view>
</view>
</view>
</view>
<view class="page-container">
<view class="task-center">
<uv-navbar title="任务中心" :autoBack="true" fixed placeholder titleStyle="color: #222; font-weight: 500;"
:border="false" :bgColor="'#fff9e2'">
<template #left>
<BackArrow :size="56" color="#222" @back="goBack" />
</template>
</uv-navbar>
<view class="navbar-placeholder"></view>
<!-- 账户剩余 -->
<view class="account-balance">
<view class="balance-label">账户剩余</view>
<view class="balance-value"><text class="num">9</text> <text class="unit"> 推荐票</text></view>
</view>
<!-- 打卡得奖励 -->
<view class="checkin-section">
<view class="section-header">
<text>打卡得奖励</text>
<view class="record-btn">打卡记录</view>
</view>
<view class="checkin-grid">
<view v-for="day in 8" :key="day" class="checkin-day" :class="{ active: day <= checkedDays }">
<view class="day-label" :class="{ bold: day <= checkedDays }">{{ day }}</view>
<image class="ticket-img"
src="https://tse1-mm.cn.bing.net/th/id/OIP-C.pca_tFb6ZjyDNdQYgFvi0wHaE7?w=219&h=180&c=7&r=0&o=5&dpr=1.1&pid=1.7"
mode="aspectFit" />
<view class="ticket-num">+1</view>
</view>
</view>
<button class="checkin-btn" :class="{ 'checked-btn': isChecked }" :disabled="isChecked"
@click="handleCheckin">
{{ isChecked ? '已签到' : '签到得奖励' }}
</button>
</view>
<!-- 更多任务 -->
<view class="more-tasks">
<view class="more-header">更多任务</view>
<view class="task-list">
<view class="task-item" v-for="(task, idx) in tasks" :key="idx"
:class="{ 'no-border': idx === tasks.length - 1 }">
<view class="task-info">
<view class="task-title">{{ task.title }}</view>
<view class="task-desc">推荐票 +1</view>
</view>
<button class="get-btn" :class="{ 'received-btn': task.received }" :disabled="task.received"
@click="handleReceive(idx)">
{{ task.received ? '已领取' : '去领取' }}
</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import uvNavbar from '@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue'
import uvIcon from '@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue'
import BackArrow from './components/BackArrow.vue'
export default {
components: { uvNavbar, uvIcon, BackArrow },
data() {
return {
checkedDays: 3, //
tasks: [
{ title: '观看视频广告', received: false },
{ title: '每日首阅三个章节', received: false },
{ title: '每日首条评论', received: false },
],
isChecked: false, //
}
},
methods: {
goBack() {
uni.navigateBack();
},
handleCheckin() {
if (this.checkedDays < 8) {
this.checkedDays++;
this.isChecked = true;
uni.showToast({ title: '签到成功', icon: 'success' });
} else {
this.isChecked = true;
uni.showToast({ title: '已全部签到', icon: 'none' });
}
},
handleReceive(idx) {
this.tasks[idx].received = true;
uni.showToast({ title: '领取成功', icon: 'success' });
},
},
}
import uvNavbar from '@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue'
import uvIcon from '@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue'
import BackArrow from './components/BackArrow.vue'
export default {
components: {
uvNavbar,
uvIcon,
BackArrow
},
data() {
return {
checkedDays: 3, //
tasks: [{
title: '观看视频广告',
received: false
},
{
title: '每日首阅三个章节',
received: false
},
{
title: '每日首条评论',
received: false
},
],
isChecked: false, //
}
},
methods: {
goBack() {
uni.navigateBack();
},
handleCheckin() {
if (this.checkedDays < 8) {
this.checkedDays++;
this.isChecked = true;
uni.showToast({
title: '签到成功',
icon: 'success'
});
} else {
this.isChecked = true;
uni.showToast({
title: '已全部签到',
icon: 'none'
});
}
},
handleReceive(idx) {
this.tasks[idx].received = true;
uni.showToast({
title: '领取成功',
icon: 'success'
});
},
},
}
</script>
<style scoped lang="scss">
.page-container {
height: 100vh;
overflow: hidden;
}
.task-center {
background: #f8f8f8;
height: 100vh;
padding-bottom: 40rpx;
overflow: hidden;
box-sizing: border-box;
}
.navbar-placeholder {
height: 100rpx;
}
.account-balance {
background: linear-gradient(90deg, #ffe16b, #ffd700);
border-radius: 20rpx;
margin: 24rpx 24rpx 0 24rpx;
padding: 24rpx 32rpx;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 30rpx;
color: #333;
.balance-label {
font-weight: 500;
}
.balance-value {
font-weight: bold;
color: #bfa100;
.num {
font-size: 24rpx;
}
.unit {
font-size: 22rpx;
}
}
}
.checkin-section {
background: #fff;
border-radius: 20rpx;
margin: 24rpx;
padding: 32rpx 24rpx 24rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(255, 215, 0, 0.08);
border: 4rpx solid #ffe16b;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
font-weight: 600;
margin-bottom: 24rpx;
.record-btn {
background: #d6ff4b ;
color: #383938;
border-radius: 24rpx;
padding: 6rpx 28rpx;
font-size: 24rpx;
}
}
.checkin-grid {
display: flex;
flex-wrap: wrap;
gap: 18rpx;
margin-bottom: 32rpx;
.checkin-day {
width: 22%;
background: #f7f7f7;
border-radius: 12rpx;
display: flex;
flex-direction: column;
align-items: center;
padding: 18rpx 0 10rpx 0;
border: 2rpx solid #f0f0f0;
&.active {
background: #d6ff4b !important;
border-color: #b6e900 !important;
.day-label, .ticket-num {
color: #222 !important;
font-weight: bold;
}
}
.day-label {
font-size: 24rpx;
font-weight: 600;
height: 90rpx;
margin-bottom: 8rpx;
color: #333;
&.bold {
font-weight: bold;
}
}
.ticket-img {
width: 48rpx;
height: 36rpx;
margin-bottom: 6rpx;
display: flex;
}
.ticket-num {
font-size: 22rpx;
color: #bfa100;
}
}
}
.checkin-btn {
width: 600rpx;
background: linear-gradient(90deg, #ffe16b, #ffd700);
color: #333;
font-size: 30rpx;
border-radius: 46rpx;
padding: 18rpx 0;
font-weight: bold;
margin-top: 8rpx;
transition: background 0.2s;
}
}
.checked-btn {
background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
color: #444 !important;
cursor: not-allowed;
}
.more-tasks {
background: #faffea;
border-radius: 20rpx;
margin: 0 24rpx;
padding: 24rpx 24rpx 8rpx 24rpx;
margin-top: 100rpx;
.more-header {
font-size: 28rpx;
color: #bfa100;
font-weight: 600;
margin-bottom: 18rpx;
}
.task-list {
.task-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
border-radius: 0;
margin: 0;
padding: 18rpx 20rpx 10rpx 20rpx;
border-bottom: 1rpx solid #f2f2f2;
.task-info {
display: flex;
flex-direction: column;
align-items: flex-start;
flex: 1;
min-width: 0;
margin-top: 30rpx;
.task-title {
font-size: 26rpx;
color: #222;
font-weight: bold;
}
.task-desc {
font-size: 20rpx;
color: #bbb;
margin-top: 4rpx;
}
}
.get-btn {
background: #ffd700;
color: #fff;
font-size: 24rpx;
border-radius: 24rpx;
padding: 0 28rpx;
font-weight: bold;
border: none;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
white-space: nowrap;
margin-left: 18rpx;
transition: background 0.2s;
}
.received-btn {
background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
color: #444 !important;
cursor: not-allowed;
}
&.no-border {
border-bottom: none;
}
}
}
}
</style>
.page-container {
height: 100vh;
overflow: hidden;
}
.task-center {
background: #f8f8f8;
height: 100vh;
padding-bottom: 40rpx;
overflow: hidden;
box-sizing: border-box;
}
.navbar-placeholder {
height: 100rpx;
}
.account-balance {
background: linear-gradient(90deg, #ffe16b, #ffd700);
border-radius: 20rpx;
margin: 24rpx 24rpx 0 24rpx;
padding: 24rpx 32rpx;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 30rpx;
color: #333;
.balance-label {
font-weight: 500;
}
.balance-value {
font-weight: bold;
color: #bfa100;
.num {
font-size: 24rpx;
}
.unit {
font-size: 22rpx;
}
}
}
.checkin-section {
background: #fff;
border-radius: 20rpx;
margin: 24rpx;
padding: 32rpx 24rpx 24rpx 24rpx;
box-shadow: 0 2rpx 8rpx rgba(255, 215, 0, 0.08);
border: 4rpx solid #ffe16b;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
font-weight: 600;
margin-bottom: 24rpx;
.record-btn {
background: #d6ff4b;
color: #383938;
border-radius: 24rpx;
padding: 6rpx 28rpx;
font-size: 24rpx;
}
}
.checkin-grid {
display: flex;
flex-wrap: wrap;
gap: 18rpx;
margin-bottom: 32rpx;
.checkin-day {
width: 22%;
background: #f7f7f7;
border-radius: 12rpx;
display: flex;
flex-direction: column;
align-items: center;
padding: 18rpx 0 10rpx 0;
border: 2rpx solid #f0f0f0;
&.active {
background: #d6ff4b !important;
border-color: #b6e900 !important;
.day-label,
.ticket-num {
color: #222 !important;
font-weight: bold;
}
}
.day-label {
font-size: 24rpx;
font-weight: 600;
height: 90rpx;
margin-bottom: 8rpx;
color: #333;
&.bold {
font-weight: bold;
}
}
.ticket-img {
width: 48rpx;
height: 36rpx;
margin-bottom: 6rpx;
display: flex;
}
.ticket-num {
font-size: 22rpx;
color: #bfa100;
}
}
}
.checkin-btn {
width: 600rpx;
background: linear-gradient(90deg, #ffe16b, #ffd700);
color: #333;
font-size: 30rpx;
border-radius: 46rpx;
padding: 18rpx 0;
font-weight: bold;
margin-top: 8rpx;
transition: background 0.2s;
}
}
.checked-btn {
background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
color: #444 !important;
cursor: not-allowed;
}
.more-tasks {
background: #faffea;
border-radius: 20rpx;
margin: 0 24rpx;
padding: 24rpx 24rpx 8rpx 24rpx;
margin-top: 100rpx;
.more-header {
font-size: 28rpx;
color: #bfa100;
font-weight: 600;
margin-bottom: 18rpx;
}
.task-list {
.task-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
border-radius: 0;
margin: 0;
padding: 18rpx 20rpx 10rpx 20rpx;
border-bottom: 1rpx solid #f2f2f2;
.task-info {
display: flex;
flex-direction: column;
align-items: flex-start;
flex: 1;
min-width: 0;
margin-top: 30rpx;
.task-title {
font-size: 26rpx;
color: #222;
font-weight: bold;
}
.task-desc {
font-size: 20rpx;
color: #bbb;
margin-top: 4rpx;
}
}
.get-btn {
background: #ffd700;
color: #fff;
font-size: 24rpx;
border-radius: 24rpx;
padding: 0 28rpx;
font-weight: bold;
border: none;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
white-space: nowrap;
margin-left: 18rpx;
transition: background 0.2s;
}
.received-btn {
background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
color: #444 !important;
cursor: not-allowed;
}
&.no-border {
border-bottom: none;
}
}
}
}
</style>

+ 384
- 246
pages_order/novel/Walletflow.vue View File

@ -1,258 +1,396 @@
<!-- 钱包流水页面 -->
<template>
<view class="walletflow-page">
<!-- 顶部导航栏 -->
<uv-navbar title="钱包流水" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;" :border="false">
<template #left>
<BackArrow :size="56" color="#333" />
</template>
</uv-navbar>
<view class="walletflow-page">
<!-- 顶部导航栏 -->
<uv-navbar title="钱包流水" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;"
:border="false">
<template #left>
<BackArrow :size="56" color="#333" />
</template>
</uv-navbar>
<!-- 账户余额卡片 -->
<view class="balance-card">
<view class="balance-label">账户</view>
<view class="balance-row">
<text class="balance-amount">{{ balance }}</text>
<button class="recharge-btn" @click="goRecharge">充值</button>
</view>
</view>
<!-- 账户余额卡片 -->
<view class="balance-card">
<view class="balance-label">账户</view>
<view class="balance-row">
<text class="balance-amount">{{ balance }}</text>
<button class="recharge-btn" @click="goRecharge">充值</button>
</view>
</view>
<!-- tab和流水列表卡片 -->
<view class="flow-card">
<view class="tab-header">
<view :class="['tab-item', {active: activeTab === 0}]" @click="activeTab = 0">
充值
<view v-if="activeTab === 0" class="tab-underline"></view>
</view>
<view :class="['tab-item', {active: activeTab === 1}]" @click="activeTab = 1">
支付
<view v-if="activeTab === 1" class="tab-underline"></view>
</view>
</view>
<scroll-view scroll-y class="flow-list">
<view v-if="activeTab === 0">
<view class="flow-item" v-for="(item, idx) in rechargeList" :key="idx">
<view class="flow-item-row">
<view class="flow-item-left">
<view class="flow-title">{{ item.title }}</view>
<view class="flow-date">{{ item.date }}</view>
</view>
<view class="flow-amount plus">+{{ item.amount }}</view>
</view>
</view>
</view>
<view v-else>
<view class="flow-item" v-for="(item, idx) in payList" :key="idx">
<view class="flow-item-row">
<view class="flow-item-left">
<view class="flow-title">{{ item.title }}</view>
<view class="flow-date">{{ item.date }}</view>
</view>
<view class="flow-amount minus">-{{ item.amount }}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<!-- tab和流水列表卡片 -->
<view class="flow-card">
<view class="tab-header">
<view :class="['tab-item', {active: activeTab === 0}]" @click="activeTab = 0">
充值
<view v-if="activeTab === 0" class="tab-underline"></view>
</view>
<view :class="['tab-item', {active: activeTab === 1}]" @click="activeTab = 1">
支付
<view v-if="activeTab === 1" class="tab-underline"></view>
</view>
</view>
<scroll-view scroll-y class="flow-list">
<view v-if="activeTab === 0">
<view class="flow-item" v-for="(item, idx) in rechargeList" :key="idx">
<view class="flow-item-row">
<view class="flow-item-left">
<view class="flow-title">{{ item.title }}</view>
<view class="flow-date">{{ item.date }}</view>
</view>
<view class="flow-amount plus">+{{ item.amount }}</view>
</view>
</view>
</view>
<view v-else>
<view class="flow-item" v-for="(item, idx) in payList" :key="idx">
<view class="flow-item-row">
<view class="flow-item-left">
<view class="flow-title">{{ item.title }}</view>
<view class="flow-date">{{ item.date }}</view>
</view>
<view class="flow-amount minus">-{{ item.amount }}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import BackArrow from './components/BackArrow.vue';
import BackArrow from './components/BackArrow.vue';
export default {
components: {
BackArrow,
},
data() {
return {
balance: 34532,
activeTab: 0,
rechargeList: [
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '推荐票', date: '2025.03.18', amount: 5 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
{ title: '豆豆充值', date: '2025.03.18', amount: 55 },
],
payList: [
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
{ title: '章节支付', date: '2025.03.18', amount: 10 },
]
}
},
methods: {
goRecharge() {
uni.showToast({ title: '充值功能开发中', icon: 'none' })
}
}
}
export default {
components: {
BackArrow,
},
data() {
return {
balance: 34532,
activeTab: 0,
rechargeList: [{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '推荐票',
date: '2025.03.18',
amount: 5
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
{
title: '豆豆充值',
date: '2025.03.18',
amount: 55
},
],
payList: [{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
{
title: '章节支付',
date: '2025.03.18',
amount: 10
},
]
}
},
methods: {
goRecharge() {
uni.showToast({
title: '充值功能开发中',
icon: 'none'
})
}
}
}
</script>
<style lang="scss" scoped>
.walletflow-page {
min-height: 100vh;
background: linear-gradient(180deg, #f8f8fc 0%, #fff 100%);
padding-bottom: 30rpx;
}
.balance-card {
background: linear-gradient(90deg, #f7f2fa 0%, #fbeaf2 100%);
border-radius: 18rpx;
margin: 24rpx 12rpx 0 12rpx;
padding: 18rpx 24rpx 14rpx 24rpx;
box-shadow: none;
border: 1rpx solid #ede7ef;
position: relative;
display: flex;
flex-direction: column;
min-height: 130rpx;
justify-content: center;
.balance-label {
color: #bbb;
font-size: 26rpx;
margin-bottom: 8rpx;
}
.balance-row {
display: flex;
align-items: center;
margin-top: 0;
position: relative;
.balance-amount {
color: #e94f7a;
font-size: 48rpx;
font-weight: bold;
}
.recharge-btn {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
background: linear-gradient(90deg, #ffb6c1 0%, #fa5a99 100%);
color: #fff;
font-size: 28rpx;
border-radius: 32rpx;
padding: 0 40rpx;
height: 56rpx;
line-height: 56rpx;
font-weight: 500;
border: none;
box-shadow: none;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.flow-card {
background: #fff;
border-radius: 20rpx;
margin: 32rpx 16rpx 0 16rpx;
box-shadow: 0 4rpx 24rpx 0 rgba(0,0,0,0.06);
padding-bottom: 8rpx;
overflow: hidden;
}
.tab-header {
display: flex;
margin: 0;
background: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
overflow: hidden;
.tab-item {
flex: 1;
text-align: center;
font-size: 30rpx;
color: #888;
padding: 0 0 18rpx 0;
font-weight: bold;
background: transparent;
position: relative;
&.active {
color: #223a7a;
font-weight: bold;
}
.tab-underline {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 44rpx;
height: 4rpx;
background: #223a7a;
border-radius: 2rpx;
margin-top: 4rpx;
}
}
}
.flow-list {
margin: 0;
padding: 0 16rpx;
max-height: 75vh;
background: #fff;
}
.flow-item {
border-bottom: 1px solid #f5f5f5;
padding: 18rpx 0 8rpx 0;
&:last-child {
border-bottom: none;
}
.flow-item-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding-right: 45rpx;
padding-left: 15rpx;
}
.flow-item-left {
display: flex;
flex-direction: column;
align-items: flex-start;
.flow-title {
font-size: 28rpx;
color: #222;
font-weight: 500;
margin-bottom: 2rpx;
}
.flow-date {
color: #bbb;
font-size: 22rpx;
margin-top: 0;
}
}
.flow-amount {
font-size: 26rpx;
font-weight: 500;
margin-left: 24rpx;
margin-top: 2rpx;
&.plus {
color: #223a7a;
}
&.minus {
color: #e94f7a;
}
}
}
.walletflow-page {
min-height: 100vh;
background: linear-gradient(180deg, #f8f8fc 0%, #fff 100%);
padding-bottom: 30rpx;
}
.balance-card {
background: linear-gradient(90deg, #f7f2fa 0%, #fbeaf2 100%);
border-radius: 18rpx;
margin: 24rpx 12rpx 0 12rpx;
padding: 18rpx 24rpx 14rpx 24rpx;
box-shadow: none;
border: 1rpx solid #ede7ef;
position: relative;
display: flex;
flex-direction: column;
min-height: 130rpx;
justify-content: center;
.balance-label {
color: #bbb;
font-size: 26rpx;
margin-bottom: 8rpx;
}
.balance-row {
display: flex;
align-items: center;
margin-top: 0;
position: relative;
.balance-amount {
color: #e94f7a;
font-size: 48rpx;
font-weight: bold;
}
.recharge-btn {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
background: linear-gradient(90deg, #ffb6c1 0%, #fa5a99 100%);
color: #fff;
font-size: 28rpx;
border-radius: 32rpx;
padding: 0 40rpx;
height: 56rpx;
line-height: 56rpx;
font-weight: 500;
border: none;
box-shadow: none;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.flow-card {
background: #fff;
border-radius: 20rpx;
margin: 32rpx 16rpx 0 16rpx;
box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.06);
padding-bottom: 8rpx;
overflow: hidden;
}
.tab-header {
display: flex;
margin: 0;
background: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
overflow: hidden;
.tab-item {
flex: 1;
text-align: center;
font-size: 30rpx;
color: #888;
padding: 0 0 18rpx 0;
font-weight: bold;
background: transparent;
position: relative;
&.active {
color: #223a7a;
font-weight: bold;
}
.tab-underline {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 44rpx;
height: 4rpx;
background: #223a7a;
border-radius: 2rpx;
margin-top: 4rpx;
}
}
}
.flow-list {
margin: 0;
padding: 0 16rpx;
max-height: 75vh;
background: #fff;
}
.flow-item {
border-bottom: 1px solid #f5f5f5;
padding: 18rpx 0 8rpx 0;
&:last-child {
border-bottom: none;
}
.flow-item-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding-right: 45rpx;
padding-left: 15rpx;
}
.flow-item-left {
display: flex;
flex-direction: column;
align-items: flex-start;
.flow-title {
font-size: 28rpx;
color: #222;
font-weight: 500;
margin-bottom: 2rpx;
}
.flow-date {
color: #bbb;
font-size: 22rpx;
margin-top: 0;
}
}
.flow-amount {
font-size: 26rpx;
font-weight: 500;
margin-left: 24rpx;
margin-top: 2rpx;
&.plus {
color: #223a7a;
}
&.minus {
color: #e94f7a;
}
}
}
</style>

+ 0
- 132
pages_order/novel/announcement.vue View File

@ -1,132 +0,0 @@
<template>
<!-- 公告详情页面 -->
<view class="announcement-container">
<uv-navbar
title="公告详情"
:autoBack="true"
fixed
placeholder
titleStyle="color: #333; font-weight: 500;"
:border="false"
></uv-navbar>
<view class="header">
<text class="title">2025年2月平台福利活动拟获奖作品公示</text>
<text class="date">岁序更替华章日新2025平台福利内容建设的实施进展载誉前行我们秉持"精品为本,重磅发布"的理念现面向全体作者重磅发布2025年度长篇网文作家福利上线主新潮当中文网作家专属福利全年奖半年奖季度奖月度奖总计奖金超过百万元现将2025年2月平台各项福利活动拟获奖作品公示如下</text>
</view>
<view class="award-section">
<view class="award-item">
<text class="award-title">长篇网文</text>
<view class="award-content">
<view class="sub-award">
<text class="sub-title"> 优质加更奖</text>
<text class="detail">拟获奖作品156本共发放奖金41.5万元查看拟获奖名单请点击</text>
<text class="link">优质加更奖拟获奖名单</text>
</view>
<view class="sub-award">
<text class="sub-title"> 新书扶更奖</text>
<text class="detail">拟获奖作品5574本共发放奖金20万元查看拟获奖名单请点击</text>
<text class="link">新书扶更奖拟获奖名单</text>
</view>
<view class="sub-award">
<text class="sub-title"> 拉新激励奖</text>
<text class="detail">拟获奖作品50部总计奖金65万查看拟获奖名单请点击</text>
<text class="link">2月拉新激励奖</text>
</view>
<view class="sub-award">
<text class="sub-title"> 星火计划奖励</text>
<text class="detail">拟获奖作品4178部总计奖金55万查看拟获奖名单请点击</text>
<text class="link">2月星火计划奖励名单</text>
</view>
</view>
</view>
<view class="award-item">
<text class="award-title">完结专场</text>
<view class="award-content">
<view class="sub-award">
<text class="sub-title"> 脱洞盛宴征文活动</text>
<text class="detail">月度脱洞专题拟获奖作品1260部总计奖金45万查看拟获奖名单请点击</text>
<text class="link">2月完结专题奖励名单</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
'uv-navbar': () => import('@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue')
},
data() {
return {}
},
methods: {
//
}
}
</script>
<style lang="scss">
.announcement-container {
padding: 30rpx;
background: #fff;
.header {
margin-bottom: 40rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: block;
}
.date {
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
}
.award-section {
.award-item {
margin-bottom: 40rpx;
.award-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: block;
}
.award-content {
.sub-award {
margin-bottom: 20rpx;
.sub-title {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.detail {
font-size: 28rpx;
color: #666;
}
.link {
color: #007AFF;
text-decoration: underline;
font-size: 28rpx;
}
}
}
}
}
}
</style>

+ 174
- 246
pages_order/novel/chapterList.vue View File

@ -1,254 +1,182 @@
<template>
<view class="chapter-container">
<view class="header">
<view class="nav-bar" style="position: relative; height: 44px;">
<view class="back">
<BackArrow :size="56" color="black" @back="goBack" />
</view>
<view class="title">兽王进化从被小萝莉...</view>
<view class="right-icons"></view>
</view>
<view class="tabs">
<view class="tab" :class="{ active: activeTab === 'draft' }" @click="switchTab('draft')">草稿箱</view>
<view class="tab" :class="{ active: activeTab === 'published' }" @click="switchTab('published')">已发布</view>
</view>
</view>
<view class="chapter-list">
<view class="chapter-item" v-for="(chapter, index) in chapters" :key="index" @click="editChapter(chapter)">
<view class="chapter-info">
<text class="chapter-title">章节名</text>
<text class="chapter-number">{{index + 1}}</text>
</view>
<uv-icon name="arrow-right" color="#999" size="28"></uv-icon>
</view>
</view>
<view class="bottom-actions">
<button class="btn-settings" @click="handleSettings">设置作品</button>
<button class="btn-new" @click="addNewChapter">新建章节</button>
</view>
</view>
<view class="chapter-container">
<navbar title="章节列表" leftClick @leftClick="$utils.navigateBack"/>
<view class="tabs">
<uv-tabs :list="tabs"
:activeStyle="{color : '#0A2463', fontWeight : 600}"
lineColor="#0A2463"
:inactiveStyle="{color: '#0A2463'}"
lineHeight="8rpx"
lineWidth="50rpx"
:scrollable="false"
:current="activeTab"
@click="clickTabs"></uv-tabs>
</view>
<view class="chapter-list">
<view class="chapter-item" v-for="(chapter, index) in chapters" :key="index" @click="editChapter(chapter)">
<view class="chapter-info">
<text class="chapter-title">章节名</text>
<text class="chapter-number">{{index + 1}}</text>
</view>
<uv-icon name="arrow-right" color="#999" size="28"></uv-icon>
</view>
</view>
<view class="bottom-actions">
<button class="btn-settings" @click="handleSettings">设置作品</button>
<button class="btn-new" @click="addNewChapter">新建章节</button>
</view>
</view>
</template>
<script>
import BackArrow from './components/BackArrow.vue';
import BackArrow from './components/BackArrow.vue';
export default {
components: {
BackArrow,
},
data() {
return {
activeTab: 'draft',
chapters: [] //
}
},
onLoad(options) {
// tabtab
if (options && options.tab === 'published') {
this.activeTab = 'published';
} else {
this.activeTab = 'draft';
}
this.loadChapters();
//
if (options && options.fromSave === '1') {
uni.showToast({
title: '保存成功',
icon: 'success'
});
}
if (options && options.fromPublish === '1') {
uni.showToast({
title: '发布成功',
icon: 'success'
});
}
},
methods: {
loadChapters() {
if (this.activeTab === 'published') {
this.chapters = uni.getStorageSync('publishedChapters') || [];
} else {
this.chapters = uni.getStorageSync('chapters') || [];
}
},
goBack() {
uni.navigateBack()
},
switchTab(tab) {
this.activeTab = tab;
this.loadChapters();
},
addNewChapter() {
uni.navigateTo({
url: '/pages_order/author/editor'
})
},
editChapter(chapter) {
uni.navigateTo({
url: '/pages_order/author/editor?id=' + chapter.id
})
},
handleSettings() {
uni.navigateTo({
url: '/pages_order/novel/createNovel?type=edit'
})
}
}
}
export default {
components: {
BackArrow,
},
data() {
return {
tabs : [
{
name : '已发布',
},
{
name : '草稿箱',
}
],
activeTab: 0,
chapters: [] //
}
},
onLoad(options) {
// tabtab
if (options.activeTab) {
this.activeTab = options.activeTab;
}
this.loadChapters();
//
if (options && options.fromSave === '1') {
uni.showToast({
title: '保存成功',
icon: 'success'
});
}
if (options && options.fromPublish === '1') {
uni.showToast({
title: '发布成功',
icon: 'success'
});
}
},
methods: {
loadChapters() {
if (this.activeTab === 'published') {
this.chapters = uni.getStorageSync('publishedChapters') || [];
} else {
this.chapters = uni.getStorageSync('chapters') || [];
}
},
goBack() {
uni.navigateBack()
},
clickTabs(tab) {
this.activeTab = tab.index;
},
addNewChapter() {
uni.navigateTo({
url: '/pages_order/author/editor'
})
},
editChapter(chapter) {
uni.navigateTo({
url: '/pages_order/author/editor?id=' + chapter.id
})
},
handleSettings() {
uni.navigateTo({
url: '/pages_order/novel/createNovel?type=edit'
})
}
}
}
</script>
<style lang="scss" scoped>
.chapter-container {
min-height: 100vh;
background-color: #fff;
padding-bottom: 70px;
.header {
background: #fff;
.nav-bar {
position: relative;
height: 44px;
.back {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 48px;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.right-icons {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 48px;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.title {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 500;
color: #222;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
z-index: 1;
pointer-events: none;
}
}
.tabs {
display: flex;
margin-top: 4px;
margin-left: 120rpx;
justify-content: space-between;
.tab {
font-size: 15px;
color: #888;
margin-right: 120rpx;
position: relative;
&.active {
color: #223a7a;
font-weight: 600;
&::after {
content: '';
display: block;
width: 24px;
height: 3px;
background: #223a7a;
border-radius: 2px;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -6px;
}
}
}
}
}
.chapter-list {
padding: 20rpx 40rpx;
background-color: rgb(255, 254, 254);
margin: 50rpx 40rpx;
border-radius: 3%;
.chapter-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #eee;
.chapter-info {
.chapter-title {
font-size: 14px;
color: #999;
margin-bottom: 5px;
display: block;
}
.chapter-number {
font-size: 16px;
color: #333;
display: block;
}
}
.icon-arrow {
color: #999;
font-size: 16px;
}
}
}
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
padding: 10px 15px;
background: #fff;
box-shadow: 0 -2px 6px rgba(0,0,0,0.05);
button {
flex: 1;
height: 40px;
border-radius: 20px;
font-size: 16px;
margin: 0 5px;
&.btn-settings {
background: #fff;
border: 1px solid #ddd;
color: #333;
}
&.btn-new {
background: #2b4acb;
color: #fff;
border: none;
}
}
}
}
</style>
.chapter-container {
min-height: 100vh;
background-color: #fff;
padding-bottom: 70px;
.chapter-list {
padding: 20rpx 40rpx;
background-color: rgb(255, 254, 254);
margin: 50rpx 40rpx;
border-radius: 3%;
.chapter-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #eee;
.chapter-info {
.chapter-title {
font-size: 14px;
color: #999;
margin-bottom: 5px;
display: block;
}
.chapter-number {
font-size: 16px;
color: #333;
display: block;
}
}
.icon-arrow {
color: #999;
font-size: 16px;
}
}
}
.bottom-actions {
padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
padding: 10px 15px;
background: #fff;
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
button {
flex: 1;
height: 40px;
border-radius: 20px;
font-size: 16px;
margin: 0 5px;
&.btn-settings {
background: #fff;
border: 1px solid #ddd;
color: #333;
}
&.btn-new {
background: #2b4acb;
color: #fff;
border: none;
}
}
}
}
</style>

+ 0
- 109
pages_order/novel/login.vue View File

@ -1,109 +0,0 @@
<template>
<div class="login-page">
<div class="logo-box">
<img class="logo" src="/static/auth/headImage.png" alt="logo" />
</div>
<div class="title">瀚涵中文网</div>
<LoginButton type="primary" @click="onLogin">登录</LoginButton>
<div class="cancel-row">
<LoginButton type="secondary" @click="onCancel">取消登录</LoginButton>
<span class="arrow-icon"></span>
<span class="dashed-line"></span>
</div>
<AgreementCheck v-model:checked="checked">
我已阅读并同意<a href="#">服务协议</a><a href="#">隐私政策</a>
</AgreementCheck>
<div class="book-bg"></div>
</div>
</template>
<script>
import LoginButton from './components/LoginButton.vue';
import AgreementCheck from './components/AgreementCheck.vue';
export default {
name: 'NovelLogin',
components: { LoginButton, AgreementCheck },
data() {
return {
checked: false
};
},
methods: {
onLogin() {
if (!this.checked) {
this.$toast && this.$toast('请先同意协议');
return;
}
//
},
onCancel() {
//
}
}
};
</script>
<style scoped>
.login-page {
min-height: 100vh;
background: #eef2fc;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding-top: 60px;
}
.logo-box {
width: 120px;
height: 120px;
background: #fff;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16px;
box-shadow: 0 2px 8px #e0e6f6;
}
.logo {
width: 80px;
height: 80px;
object-fit: contain;
}
.title {
font-size: 22px;
font-weight: bold;
color: #222;
margin-bottom: 32px;
}
.cancel-row {
width: 80%;
display: flex;
align-items: center;
position: relative;
margin-bottom: 8px;
}
.arrow-icon {
color: #fd7e14;
font-size: 18px;
margin: 0 6px;
z-index: 2;
}
.dashed-line {
flex: 1;
border-bottom: 2px dashed #fd7e14;
height: 0;
margin-left: -8px;
}
.book-bg {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 220px;
height: 180px;
background: url('/static/auth/headImage.png') no-repeat center/contain;
opacity: 0.08;
z-index: 0;
}
</style>

+ 721
- 909
pages_order/novel/novelDetail.vue
File diff suppressed because it is too large
View File


+ 156
- 155
pages_order/novel/vote.vue View File

@ -1,162 +1,163 @@
<template>
<view class="vote-container">
<!-- Empty space at the top -->
<view class="empty-space"></view>
<!-- Bottom sheet with voting interface -->
<view class="vote-sheet">
<view class="sheet-header">
<text class="sheet-title">投推荐票</text>
</view>
<view class="vote-options">
<text class="option-label">推荐投票</text>
<view class="quick-options">
<view class="option-btn" @click="setVotes(1)">1</view>
<view class="option-btn" @click="setVotes(5)">5</view>
<view class="option-btn" @click="setVotes(10)">10</view>
</view>
<text class="option-label">手动设置</text>
<view class="manual-input">
<view class="minus-btn" @click="decreaseVotes">-</view>
<view class="vote-count">
<text>x{{voteCount}}</text>
</view>
<view class="plus-btn" @click="increaseVotes">+</view>
</view>
</view>
<button class="submit-btn" @click="submitVote">投票</button>
</view>
</view>
<view class="vote-container">
<!-- Empty space at the top -->
<view class="empty-space"></view>
<!-- Bottom sheet with voting interface -->
<view class="vote-sheet">
<view class="sheet-header">
<text class="sheet-title">投推荐票</text>
</view>
<view class="vote-options">
<text class="option-label">推荐投票</text>
<view class="quick-options">
<view class="option-btn" @click="setVotes(1)">1</view>
<view class="option-btn" @click="setVotes(5)">5</view>
<view class="option-btn" @click="setVotes(10)">10</view>
</view>
<text class="option-label">手动设置</text>
<view class="manual-input">
<view class="minus-btn" @click="decreaseVotes">-</view>
<view class="vote-count">
<text>x{{voteCount}}</text>
</view>
<view class="plus-btn" @click="increaseVotes">+</view>
</view>
</view>
<button class="submit-btn" @click="submitVote">投票</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
voteCount: 1
}
},
methods: {
setVotes(count) {
this.voteCount = count
},
increaseVotes() {
this.voteCount++
},
decreaseVotes() {
if (this.voteCount > 1) {
this.voteCount--
}
},
submitVote() {
// TODO: Implement vote submission
uni.showToast({
title: `已投${this.voteCount}`,
icon: 'success'
})
}
}
}
export default {
data() {
return {
voteCount: 1
}
},
methods: {
setVotes(count) {
this.voteCount = count
},
increaseVotes() {
this.voteCount++
},
decreaseVotes() {
if (this.voteCount > 1) {
this.voteCount--
}
},
submitVote() {
// TODO: Implement vote submission
uni.showToast({
title: `已投${this.voteCount}`,
icon: 'success'
})
}
}
}
</script>
<style lang="scss">
.vote-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4);
}
.empty-space {
flex: 1;
}
.vote-sheet {
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding: 30rpx;
}
.sheet-header {
text-align: center;
margin-bottom: 40rpx;
}
.sheet-title {
font-size: 32rpx;
font-weight: 500;
}
.vote-options {
margin-bottom: 40rpx;
}
.option-label {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.quick-options {
display: flex;
gap: 20rpx;
margin-top: 30rpx;
margin-bottom: 40rpx;
}
.option-btn {
flex: 1;
height: 80rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 28rpx;
}
.manual-input {
margin-top: 30rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.minus-btn, .plus-btn {
width: 220rpx;
height: 80rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 32rpx;
}
.vote-count {
width: 220rpx;
height: 82rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 28rpx;
}
.submit-btn {
width: 100%;
height: 88rpx;
background-color: #000033;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
</style>
.vote-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4);
}
.empty-space {
flex: 1;
}
.vote-sheet {
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding: 30rpx;
}
.sheet-header {
text-align: center;
margin-bottom: 40rpx;
}
.sheet-title {
font-size: 32rpx;
font-weight: 500;
}
.vote-options {
margin-bottom: 40rpx;
}
.option-label {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.quick-options {
display: flex;
gap: 20rpx;
margin-top: 30rpx;
margin-bottom: 40rpx;
}
.option-btn {
flex: 1;
height: 80rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 28rpx;
}
.manual-input {
margin-top: 30rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.minus-btn,
.plus-btn {
width: 220rpx;
height: 80rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 32rpx;
}
.vote-count {
width: 220rpx;
height: 82rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 28rpx;
}
.submit-btn {
width: 100%;
height: 88rpx;
background-color: #000033;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
</style>

BIN
pages_order/static/book/bd.png View File

Before After
Width: 183  |  Height: 58  |  Size: 17 KiB

BIN
pages_order/static/book/gg.png View File

Before After
Width: 29  |  Height: 28  |  Size: 1.5 KiB

BIN
static/image/tabbar/bookshelf-a.png View File

Before After
Width: 47  |  Height: 46  |  Size: 1.6 KiB

BIN
static/image/tabbar/bookshelf.png View File

Before After
Width: 29  |  Height: 28  |  Size: 644 B

BIN
static/image/tabbar/cart-a.png View File

Before After
Width: 40  |  Height: 40  |  Size: 958 B

BIN
static/image/tabbar/cart.png View File

Before After
Width: 40  |  Height: 40  |  Size: 953 B

BIN
static/image/tabbar/category-a.png View File

Before After
Width: 40  |  Height: 40  |  Size: 1.1 KiB Width: 47  |  Height: 46  |  Size: 1.6 KiB

BIN
static/image/tabbar/category.png View File

Before After
Width: 40  |  Height: 40  |  Size: 1.2 KiB Width: 29  |  Height: 28  |  Size: 475 B

BIN
static/image/tabbar/center-a.png View File

Before After
Width: 40  |  Height: 40  |  Size: 915 B Width: 47  |  Height: 46  |  Size: 2.0 KiB

BIN
static/image/tabbar/center.png View File

Before After
Width: 40  |  Height: 40  |  Size: 937 B Width: 29  |  Height: 28  |  Size: 945 B

BIN
static/image/tabbar/home-a.png View File

Before After
Width: 47  |  Height: 43  |  Size: 2.2 KiB Width: 47  |  Height: 46  |  Size: 1.6 KiB

BIN
static/image/tabbar/order-a.png View File

Before After
Width: 40  |  Height: 40  |  Size: 691 B

BIN
static/image/tabbar/order.png View File

Before After
Width: 40  |  Height: 40  |  Size: 736 B

+ 1
- 1
uni.scss View File

@ -12,7 +12,7 @@
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量同时无需 import 这个文件
*/
/* 颜色变量 */
$uni-color: #0001ff;
$uni-color: #0A2463;
/* 行为相关颜色 */
$uni-color-primary: #007aff;


Loading…
Cancel
Save