Browse Source

feat(store): 添加logoutFn方法用于清除用户信息和token

feat(config): 添加本地环境配置并设置默认环境为local
feat(api): 在bookshelf模块添加isAddBook和deleteBookshelfByBookId接口
feat(api): 在comment模块添加getMyReplyCommentList和deleteComment接口
fix(http): 修正token过期处理逻辑并调用logoutFn方法
feat(api): 在achievement模块添加getAchievementByBookId接口
style(chapterPopup): 优化排序按钮显示文本
fix(Tipping): 修正排行榜图标显示和样式
feat(myCommentItem): 添加删除评论功能
feat(createNovel): 支持多分类选择并优化表单处理
feat(category): 添加全部选项并优化分类筛选逻辑
feat(bookList): 添加分类筛选功能
feat(readnovels): 添加加入书架功能并优化状态管理
fix(Walletflow): 修正金额字段和空状态显示
feat(myComment): 重构评论页面并添加我的评论和回复我的切换
feat(novelDetail): 添加删除书架功能并优化等级显示
master
前端-胡立永 2 months ago
parent
commit
e7a83ab7a7
16 changed files with 295 additions and 71 deletions
  1. +2
    -2
      api/http.js
  2. +7
    -1
      api/model/achievement.js
  3. +11
    -0
      api/model/bookshelf.js
  4. +10
    -0
      api/model/comment.js
  5. +4
    -1
      config.js
  6. +20
    -4
      pages/index/category.vue
  7. +11
    -3
      pages_order/author/createNovel.vue
  8. +58
    -30
      pages_order/comment/myComment.vue
  9. +30
    -2
      pages_order/components/comment/myCommentItem.vue
  10. +3
    -1
      pages_order/components/novel/chapterPopup.vue
  11. +7
    -8
      pages_order/mine/Walletflow.vue
  12. +2
    -1
      pages_order/novel/Tipping.vue
  13. +48
    -2
      pages_order/novel/bookList.vue
  14. +52
    -14
      pages_order/novel/novelDetail.vue
  15. +25
    -2
      pages_order/novel/readnovels.vue
  16. +5
    -0
      store/store.js

+ 2
- 2
api/http.js View File

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


+ 7
- 1
api/model/achievement.js View File

@ -6,12 +6,18 @@ const api = {
method: 'POST',
auth: true,
},
// 根据用户标识和书籍标识查询该用户的成就等级
// 获取作者设置的成就等级
getAchievement: {
url: '/all_achievement/getAchievement',
method: 'GET',
auth: true,
},
// 根据用户标识和书籍标识查询该用户的成就等级
getAchievementByBookId: {
url: '/all_achievement/getAchievementByBookId',
method: 'GET',
auth: true,
},
// 获取读者成就列表
getAchievementList: {
url: '/all_achievement/getAchievementList',


+ 11
- 0
api/model/bookshelf.js View File

@ -31,6 +31,17 @@ const api = {
method: 'POST',
auth: true,
},
// 查询这本书是否加入书架
isAddBook: {
url: '/all_book/isAddBook',
method: 'GET',
},
// 根据书籍id删除书架
deleteBookshelfByBookId: {
url: '/all_book/deleteBookshelfByBookId',
method: 'POST',
auth: true,
},
}
export default api

+ 10
- 0
api/model/comment.js View File

@ -41,6 +41,16 @@
url: '/my_comment/getCommentDetail',
method: 'POST',
},
// 获取回复我的评论
getMyReplyCommentList: {
url: '/my_comment/getMyReplyCommentList',
method: 'GET',
},
// 删除评论信息
deleteComment: {
url: '/my_comment/deleteComment',
method: 'GET',
},
}
export default api

+ 4
- 1
config.js View File

@ -8,11 +8,14 @@ import uvUI from '@/uni_modules/uv-ui-tools'
Vue.use(uvUI);
// 当前环境
const type = 'prod'
const type = 'local'
// 环境配置
const config = {
local : {
baseUrl : 'http://127.0.0.1:8002/novel-admin',
},
dev : {
baseUrl : 'http://h5.xzaiyp.top/novel-admin',
},


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

@ -37,6 +37,7 @@
<novelItem
v-for="(book, index) in list"
:key="index"
@click="navigateToDetail(book.id)"
:book="book">
</novelItem>
</view>
@ -116,17 +117,28 @@
this.getData()
},
beforeGetData(){
return {
shopCion : this.categoryList[this.currentChildren].id,
shopClass : this.category[this.current].id,
let data = {}
if(this.categoryList[this.currentChildren].id){
data.shopCion = this.categoryList[this.currentChildren].id
}
if(this.category[this.current].id){
data.shopClass = this.category[this.current].id
}
return data
},
async getCategoryList() {
// const data = await this.$fetch('getCategoryList')
// this.category = data
let [data1, data2] = await Promise.all([this.$fetch('getCategoryList'), this.$fetch('getBookAreaList')])
this.category = data1
this.category = [
{
title : '全部'
},
...data1,
]
this.categoryList = data2
this.mixinsListApi = 'getRecommendList'
@ -139,6 +151,10 @@
const data = await this.$fetch('getBookAreaList')
this.categoryList = data
},
navigateToDetail(id) {
//
this.$utils.navigateTo(`/pages_order/novel/novelDetail?id=${id}`)
},
}
}
</script>


+ 11
- 3
pages_order/author/createNovel.vue View File

@ -56,7 +56,7 @@
v-for="(item, index) in categoryList"
:key="index"
class="category-tag"
:class="{ active: formData.shopClass == item.id }"
:class="{ active: classList.includes(item.id) }"
@click="selectCategory(item)"
>
{{item.title}}
@ -124,6 +124,7 @@
details: '',
status: '0' //
},
classList : [],
id: 0,
// showCategoryPicker: false,
categoryList: [],
@ -146,6 +147,8 @@
id : this.id
}).then(res => {
this.formData = res
this.classList = res.shopClass ? res.shopClass.split(',') : []
})
},
@ -172,7 +175,12 @@
//
selectCategory(item) {
this.formData.shopClass = item.id
let index = this.classList.indexOf(item.id)
if(index != -1){
this.classList.splice(index, 1)
}else{
this.classList.push(item.id)
}
},
//
@ -203,7 +211,7 @@
const workData = {
name: this.formData.name,
image: this.formData.image,
shopClass: this.formData.shopClass,
shopClass: this.classList.join(','),
details: this.formData.details,
status: this.formData.status || 0,
}


+ 58
- 30
pages_order/comment/myComment.vue View File

@ -1,34 +1,39 @@
<template>
<view class="my-comment-page">
<navbar title="我的评论" :leftClick="true" @leftClick="goBack" />
<view class="comment-section">
<view class="section-title">未读评论·{{ unreadComments.length }}</view>
<myCommentItem :item="item" v-for="(item, idx) in unreadComments" :key="idx"/>
<uv-empty mode="list" v-if="unreadComments.length == 0"></uv-empty>
</view>
<view class="comment-section history-section">
<view class="section-title">历史评论</view>
<!-- <view v-for="(item, idx) in list" :key="idx" class="comment-card">
<uv-avatar :src="item.hanHaiMember.headImage" size="44" shape="circle" class="avatar" />
<view class="comment-main">
<view class="comment-header">
<text class="username">{{ item.hanHaiMember.nickName }}</text>
<text class="from">来自{{ item.commonShop.name }}</text>
</view>
<view class="comment-content">{{ item.comment }}</view>
<view class="comment-footer">
<text class="comment-time">{{ item.createTime }}</text>
<view class="reply-btn-wrap" @click="goToReply(item)">
<text class="reply-btn">回复</text>
</view>
</view>
</view>
</view> -->
<uv-empty mode="list" v-if="list.length == 0"></uv-empty>
<myCommentItem :item="item" v-for="(item, idx) in list" :key="idx"/>
</view>
<navbar title="我的评论" :leftClick="true" @leftClick="$utils.navigateBack" />
<uv-tabs :list="tabs"
:activeStyle="{ color: '#0A2463', fontWeight: 600 }"
lineColor="#0A2463" lineHeight="8rpx"
lineWidth="50rpx"
:scrollable="false"
:current="current"
@click="clickTabs"></uv-tabs>
<template v-if="current == 0">
<view class="comment-section">
<myCommentItem :item="item"
edit
@getData="getData"
v-for="(item, idx) in list" :key="idx"/>
</view>
</template>
<template v-if="current == 1">
<view class="comment-section">
<view class="section-title">未读评论·{{ unreadComments.length }}</view>
<myCommentItem :item="item" v-for="(item, idx) in unreadComments" :key="idx"/>
<uv-empty mode="list" v-if="unreadComments.length == 0"></uv-empty>
</view>
<view class="comment-section history-section">
<view class="section-title">历史评论</view>
<myCommentItem
:item="item"
v-for="(item, idx) in list" :key="idx"/>
</view>
</template>
<uv-empty mode="list" v-if="list.length == 0"></uv-empty>
</view>
</template>
@ -44,18 +49,41 @@
return {
mixinsListApi : 'getMyCommentList',
unreadComments: [],
tabs: [
{
name: '我的评论'
},
{
name: '回复我的'
},
],
current : 0,
apiList : [
'getMyCommentList',
'getMyReplyCommentList'
],
}
},
onLoad() {
this.queryParams.type = 'Y'
this.mixinsListApi = this.apiList[this.current]
},
onShow() {
this.getList()
},
methods: {
//tab
clickTabs({ index }) {
this.queryParams.pageSize = 10
this.current = index
this.mixinsListApi = this.apiList[this.current]
this.getData()
},
//
getList(){
this.$fetch('getMyCommentList', {
this.$fetch('getMyReplyCommentList', {
type : 'N',
pageNo: 1,
pageSize: 100000


+ 30
- 2
pages_order/components/comment/myCommentItem.vue View File

@ -9,9 +9,21 @@
<view class="comment-content">{{ item.comment }}</view>
<view class="comment-footer">
<text class="comment-time">{{ item.createTime }}</text>
<view class="reply-btn-wrap" @click="goToReply(item)">
<view class="reply-btn-wrap"
v-if="edit"
@click="deleteItem(item)">
<text class="reply-btn">删除</text>
</view>
<view class="reply-btn-wrap"
v-else
@click="goToReply(item)">
<text class="reply-btn">回复</text>
</view>
</view>
</view>
</view>
@ -19,7 +31,7 @@
<script>
export default {
props: ['item'],
props: ['item', 'edit'],
data() {
return {
@ -36,6 +48,22 @@
url: '/pages_order/comment/respondComments?id=' + item.id
})
},
deleteItem(item){
uni.showModal({
title : '确认删除该评论吗',
success : (r) => {
if (r.confirm) {
this.$fetch('deleteComment', {
commentId : item.id,
}).then(res => {
this.$emit('getData')
})
}
}
})
},
}
}
</script>


+ 3
- 1
pages_order/components/novel/chapterPopup.vue View File

@ -7,7 +7,9 @@
<uv-icon name="arrow-down" size="46" :color="isDarkMode ? '#ccc' : '#333'"/>
</view>
<view class="header-title theme-transition">目录</view>
<view class="header-right theme-transition" @click.stop="orderAsc = !orderAsc">倒序</view>
<view class="header-right theme-transition" @click.stop="orderAsc = !orderAsc">
{{ orderAsc ? '倒序' : '正序' }}
</view>
</view>
<scroll-view scroll-y class="catalog-list">
<view v-for="(item, idx) in (orderAsc ? chapterList : [...chapterList].reverse())" :key="item.id"


+ 7
- 8
pages_order/mine/Walletflow.vue View File

@ -39,10 +39,10 @@
<view class="flow-title">{{ item.title || item.type || '充值' }}</view>
<view class="flow-date">{{ formatDate(item.createTime) }}</view>
</view>
<view class="flow-amount plus">+{{ item.num }}</view>
<view class="flow-amount plus">+{{ item.money }}</view>
</view>
</view>
<view v-if="rechargeList.length === 0 && !loading" class="empty-tip">暂无充值记录</view>
<view v-if="rechargeList.length == 0 && !loading" class="empty-tip">暂无记录</view>
</view>
<view v-else>
<view class="flow-item" v-for="(item, idx) in payList" :key="idx">
@ -51,13 +51,12 @@
<view class="flow-title">{{ item.title || item.type || '支付' }}</view>
<view class="flow-date">{{ formatDate(item.createTime) }}</view>
</view>
<view class="flow-amount minus">-{{ item.num }}</view>
<view class="flow-amount minus">-{{ item.money }}</view>
</view>
</view>
<view v-if="payList.length === 0 && !loading" class="empty-tip">暂无支付记录</view>
<view v-if="payList.length == 0 && !loading" class="empty-tip">暂无记录</view>
</view>
<view v-if="loading" class="loading-tip">加载中...</view>
<view v-if="noMore && (rechargeList.length > 0 || payList.length > 0)" class="no-more-tip">没有更多了</view>
</scroll-view>
</view>
</view>
@ -82,11 +81,11 @@
pageSize: 20,
tabList: [
{
name: '充值',
name: '收入',
value: 0
},
{
name: '支',
name: '支',
value: 1
}
]
@ -140,7 +139,7 @@
this.$fetch('getMyMoneyLogPage', {
pageNo: this.pageNo,
pageSize: this.pageSize,
status: logType // 0-1-
type: logType // 0-1-
}).then(res => {
const records = res.records || [];


+ 2
- 1
pages_order/novel/Tipping.vue View File

@ -52,7 +52,7 @@
&& topList[2].hanHaiMember.headImage" mode="aspectFill"></image>
</view>
<view class="badge">
<image class="badge-img" src="/pages_order/static/book/dj.png" mode="aspectFit"></image>
<image class="badge-img" :src="topList[2].icon" mode="aspectFit"></image>
</view>
<view class="name">{{ topList[2].name }}</view>
<view class="score">{{ topList[2].num }} 亲密值</view>
@ -225,6 +225,7 @@ export default {
font-size: 30rpx;
color: #FFFFFF;
font-weight: bold;
text-align: center;
}
.score {


+ 48
- 2
pages_order/novel/bookList.vue View File

@ -13,6 +13,18 @@
showAction="false"></uv-search>
</view>
<view class="tabs">
<uv-tabs
:list="category"
:activeStyle="{color : '#000', fontWeight : 600}"
lineColor="#000"
:inactiveStyle="{color: '#000'}"
lineHeight="8rpx"
lineWidth="50rpx"
:current="current"
keyName="title"
@click="clickTabs"></uv-tabs>
</view>
<view class="novel-list">
<novel-item v-for="(item, index) in list"
@ -33,11 +45,45 @@
},
data() {
return {
mixinsListApi : 'getRecommendList',
mixinsListApi : '',
current : 0,
category: [],
}
},
onLoad() {
this.getCategoryList()
},
methods: {
async getCategoryList() {
const data = await this.$fetch('getCategoryList')
data.unshift({
title : '全部'
})
this.category = data
this.mixinsListApi = 'getRecommendList'
this.getData()
},
beforeGetData(){
let params = {}
if(this.category[this.current].id){
params.shopClass = this.category[this.current].id
}
return params
},
navigateToDetail(id) {
//
this.$utils.navigateTo(`/pages_order/novel/novelDetail?id=${id}`)
},
clickTabs({index}){
this.current = index
//
this.getData()
},
}
}
</script>


+ 52
- 14
pages_order/novel/novelDetail.vue View File

@ -69,24 +69,32 @@
<text>我的等级</text>
</view>
<view class="level-info">
<image class="user-avatar" src="/pages_order/static/book/dj.png" mode="aspectFill"></image>
<!-- <image class="user-avatar" src="/pages_order/static/book/dj.png" mode="aspectFill"></image> -->
<image
:src="bookLevel.icon"
class="user-avatar"
mode="aspectFill"></image>
<view class="user-details">
<text class="username">
<view class="username">
<image
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFill"></image>
:src="bookLevel.hanHaiMember
&& bookLevel.hanHaiMember.headImage"
style="width: 40rpx;height: 40rpx;border-radius: 50%;margin-right: 4rpx;"
mode="aspectFill"></image>
<view class="name">
周海
{{ (bookLevel.hanHaiMember
&& bookLevel.hanHaiMember.nickName) || '_' }}
</view>
</text>
</view>
<view class="user-score">
<text class="score-value">6785452</text>
<text class="score-value">{{ bookLevel.num || 0}}</text>
<text class="score-label">亲密值</text>
</view>
<text class="user-role">护书使者 五级</text>
<text class="user-role">{{ bookLevel.commonBookAchievement
&& (bookLevel.commonBookAchievement.oldName || bookLevel.commonBookAchievement.title)}}</text>
</view>
</view>
</view>
@ -145,9 +153,22 @@
<!-- 底部操作栏 -->
<view class="novel-bottom">
<view class="bottom-left">
<view class="action-btn" @click="addToBookshelf">
<view class="action-btn"
v-if="isBooshelf"
@click="deleteBookshelfByBookId">
<view class="btn-icon">
<uv-icon name="grid" color="#f20" size="50rpx"></uv-icon>
</view>
<text style="color: #f20;">删除书架</text>
</view>
<view class="action-btn"
v-else
@click="addToBookshelf">
<view class="btn-icon">
<uv-icon name="grid" color="#999" size="60rpx"></uv-icon>
<uv-icon name="grid" color="#999" size="50rpx"></uv-icon>
</view>
<text>加入书架</text>
</view>
@ -157,7 +178,7 @@
</view> -->
<view class="action-btn" @click="$refs.interactiveGiftPopup.open()">
<view class="btn-icon">
<uv-icon name="gift" color="#999" size="60rpx"></uv-icon>
<uv-icon name="gift" color="#999" size="50rpx"></uv-icon>
</view>
<text>互动打赏</text>
</view>
@ -205,6 +226,8 @@
catalog: {}, //
fastCatalog: {}, //
chapterList : [],//
isBooshelf : false,
}
},
computed: {},
@ -217,6 +240,7 @@
onShow() {
this.getDateil()
this.getBookCatalogList()
this.isAddBook()
if(this.isLogin){
this.getAchievement()
}
@ -238,8 +262,8 @@
})
},
getAchievement() {
this.$fetch('getAchievement', {
id: this.id
this.$fetch('getAchievementByBookId', {
bookId: this.id
}).then(res => {
this.bookLevel = res
})
@ -292,6 +316,7 @@
image: this.novelData.image,
novelId : this.fastCatalog && this.fastCatalog.id
}).then(res => {
this.isBooshelf = true
uni.showToast({
title: '已加入书架',
icon: 'success'
@ -308,6 +333,11 @@
url: `/pages_order/novel/Giftbox?id=${this.id}`
})
},
async isAddBook(){
this.isBooshelf = await this.$fetch('isAddBook', {
bookId: this.id
})
},
toRead() {
if (!this.fastCatalog) {
uni.showToast({
@ -342,6 +372,14 @@
this.getAchievement();
}
},
//
deleteBookshelfByBookId(){
this.$fetch('deleteBookshelfByBookId', {
bookId : this.id
}).then(res => {
this.isBooshelf = false
})
},
}
}
</script>


+ 25
- 2
pages_order/novel/readnovels.vue View File

@ -38,7 +38,7 @@
<view class="bottom-bar" :class="{'bottom-bar-hidden': isFullScreen}">
<view class="bottom-left">
<view class="bar-item">
<view class="bar-item" v-if="!isBooshelf" @click="addToBookshelf">
<view class="bar-icon"> <uv-icon name="plus"></uv-icon> </view>
<text class="bar-label">加入书架</text>
</view>
@ -104,6 +104,8 @@
//
isPay : false,
isBooshelf : false,
}
},
computed: {
@ -127,6 +129,7 @@
},
onShow() {
this.getBookCatalogList()
this.isAddBook()
},
mounted() {
//
@ -140,6 +143,13 @@
this.novelData = res
})
},
async isAddBook(){
this.$fetch('isAddBook', {
bookId: this.id
}).then(res => {
this.isBooshelf = res
})
},
async getBookCatalogDetail() {
this.isPay = await this.$fetch('getMyShopNovel', {
@ -228,7 +238,20 @@
this.isFullScreen = true
this.getBookCatalogDetail()
},
addToBookshelf() {
this.$fetch('addReadBook', {
shopId: this.id,
name: this.novelData.name,
image: this.novelData.image,
novelId : this.fastCatalog && this.fastCatalog.id
}).then(res => {
this.isBooshelf = true
uni.showToast({
title: '已加入书架',
icon: 'success'
})
})
},
//
updateReadProgress() {
if (!this.id || !this.cid) return;


+ 5
- 0
store/store.js View File

@ -116,6 +116,11 @@ const store = new Vuex.Store({
}
})
},
logoutFn(state){
state.userInfo = {}
state.isLogin = false
uni.removeStorageSync('token')
},
},
actions: {},
})


Loading…
Cancel
Save