Browse Source

积分

dev_des
1054425342@qq.com 1 month ago
parent
commit
5a8a05811b
  1. 6905
      audioBook/components/msg copy 2.json
  2. 8980
      audioBook/components/msg.json
  3. 532
      audioBook/pages/index.vue
  4. 6
      pages.json
  5. 19
      pages/index/components/FollowTab.vue
  6. 27
      pages/index/timeShopBank.vue
  7. 6
      pages/login/login.vue
  8. 4
      static/js/request.js
  9. 6
      subPackages/other/ipPoster.vue
  10. 452
      subPackages/points/index.vue

6905
audioBook/components/msg copy 2.json

File diff suppressed because one or more lines are too long

8980
audioBook/components/msg.json

File diff suppressed because one or more lines are too long

532
audioBook/pages/index.vue

@ -3,19 +3,36 @@
<!-- 歌词显示区域 -->
<view class="lyrics-container">
<view class="lyrics-content">
<!-- 当前句子显示 -->
<view class="current-sentence">
<text class="lyric-line active">
{{ currentSentence ? currentSentence.FinalSentence : "" }}
</text>
<!-- 三句歌词显示 -->
<view class="three-sentences">
<!-- 上一句 -->
<view class="sentence-item prev-sentence">
<text class="lyric-line prev-line">
{{ prevSentence ? prevSentence.FinalSentence : "" }}
</text>
</view>
<!-- 当前句子 -->
<view class="sentence-item current-sentence">
<text class="lyric-line active">
{{ currentSentence ? currentSentence.FinalSentence : "" }}
</text>
</view>
<!-- 下一句 -->
<view class="sentence-item next-sentence">
<text class="lyric-line next-line">
{{ nextSentence ? nextSentence.FinalSentence : "" }}
</text>
</view>
</view>
<!-- 句子指示器 -->
<view class="sentence-indicator">
<!-- <view class="sentence-indicator">
<text class="sentence-text">
{{ currentSentenceIndex + 1 }}/{{ totalSentences }}
</text>
</view>
</view> -->
</view>
</view>
@ -50,27 +67,73 @@
</view>
<text class="time-text">{{ formatTime(duration) }}</text>
</view>
<!-- 句子控制按钮 -->
<view class="sentence-controls">
<view
class="control-btn"
@click="prevSentence"
:disabled="currentSentenceIndex === 0"
>
<text class="control-icon-text"></text>
<!-- 点赞和评论区域 -->
<view class="interaction-section">
<view class="like-section">
<view class="like-btn" @click="toggleLike">
<text class="like-icon">{{ isLiked ? "❤️" : "🤍" }}</text>
<text class="like-count">{{ likeCount }}</text>
</view>
<view class="comment-btn" @click="toggleComments">
<text class="comment-icon">💬</text>
<text class="comment-count">{{ comments.length }}</text>
</view>
</view>
<view class="sentence-info">
<text class="sentence-info-text"
>{{ currentSentenceIndex + 1 }}/{{ totalSentences }}</text
>
</view>
<!-- 评论列表 -->
<view class="comments-container" v-if="showComments">
<view class="comments-header">
<text class="comments-title">评论 ({{ comments.length }})</text>
<view class="close-btn" @click="closeComments">
<text class="close-icon"></text>
</view>
</view>
<view
class="control-btn"
@click="nextSentence"
:disabled="currentSentenceIndex >= totalSentences - 1"
>
<text class="control-icon-text"></text>
<!-- 评论输入框 -->
<view class="comment-input-section">
<input
class="comment-input"
v-model="newComment"
placeholder="写下你的想法..."
@confirm="submitComment"
/>
<view
class="submit-btn"
@click="submitComment"
:class="{ disabled: !newComment.trim() }"
>
<text class="submit-text">发送</text>
</view>
</view>
<!-- 评论列表 -->
<scroll-view class="comments-list" scroll-y>
<view
class="comment-item"
v-for="(comment, index) in comments"
:key="index"
>
<view class="comment-avatar">
<text class="avatar-text">{{ comment.userName.charAt(0) }}</text>
</view>
<view class="comment-content">
<view class="comment-header">
<text class="comment-user">{{ comment.userName }}</text>
<text class="comment-time">{{
formatCommentTime(comment.createTime)
}}</text>
</view>
<text class="comment-text">{{ comment.content }}</text>
</view>
</view>
<!-- 空状态 -->
<view class="empty-comments" v-if="comments.length === 0">
<text class="empty-text">暂无评论快来抢沙发吧~</text>
</view>
</scroll-view>
</view>
<!-- 底部控制按钮 -->
@ -135,6 +198,13 @@ export default {
scrollViewHeight: 0,
//
currentSentenceIndex: 0,
//
isLiked: false,
likeCount: 0,
comments: [],
showComments: false,
newComment: "",
commentLoading: false,
};
},
mounted() {
@ -181,6 +251,22 @@ export default {
currentSentence() {
return this.currentChapter.sentences[this.currentSentenceIndex] || null;
},
prevSentence() {
if (this.currentSentenceIndex > 0) {
return (
this.currentChapter.sentences[this.currentSentenceIndex - 1] || null
);
}
return null;
},
nextSentence() {
if (this.currentSentenceIndex < this.totalSentences - 1) {
return (
this.currentChapter.sentences[this.currentSentenceIndex + 1] || null
);
}
return null;
},
},
methods: {
togglePlay() {
@ -357,31 +443,134 @@ export default {
//
this.scrollViewHeight = windowHeight - controlsHeight - 60; // 60px
},
//
prevSentence() {
if (this.currentSentenceIndex > 0) {
this.currentSentenceIndex--;
this.activeSentenceIndex = this.currentSentenceIndex;
//
const sentence =
this.currentChapter.sentences[this.currentSentenceIndex];
if (sentence && this.$refs.audioPlayer) {
this.$refs.audioPlayer.seek(sentence.startTimeInSeconds);
}
//
toggleLike() {
this.isLiked = !this.isLiked;
this.likeCount += this.isLiked ? 1 : -1;
// API
this.saveLikeStatus();
},
toggleComments() {
this.showComments = !this.showComments;
if (this.showComments && this.comments.length === 0) {
this.loadComments();
}
},
nextSentence() {
if (this.currentSentenceIndex < this.totalSentences - 1) {
this.currentSentenceIndex++;
this.activeSentenceIndex = this.currentSentenceIndex;
//
const sentence =
this.currentChapter.sentences[this.currentSentenceIndex];
if (sentence && this.$refs.audioPlayer) {
this.$refs.audioPlayer.seek(sentence.startTimeInSeconds);
}
closeComments() {
this.showComments = false;
},
async loadComments() {
try {
//
// API
this.comments = [
{
id: 1,
userName: "用户1",
content: "这首歌真的很好听!",
createTime: new Date().getTime() - 1000 * 60 * 30, // 30
},
{
id: 2,
userName: "音乐爱好者",
content: "歌词写得很有意境",
createTime: new Date().getTime() - 1000 * 60 * 60 * 2, // 2
},
{
id: 3,
userName: "文艺青年",
content: "每次听都有不同的感受",
createTime: new Date().getTime() - 1000 * 60 * 60 * 24, // 1
},
{
id: 1,
userName: "用户1",
content: "这首歌真的很好听!",
createTime: new Date().getTime() - 1000 * 60 * 30, // 30
},
{
id: 2,
userName: "音乐爱好者",
content: "歌词写得很有意境",
createTime: new Date().getTime() - 1000 * 60 * 60 * 2, // 2
},
{
id: 3,
userName: "文艺青年",
content: "每次听都有不同的感受",
createTime: new Date().getTime() - 1000 * 60 * 60 * 24, // 1
},
];
} catch (error) {
console.error("加载评论失败:", error);
uni.showToast({
title: "加载评论失败",
icon: "none",
});
}
},
async submitComment() {
if (!this.newComment.trim()) {
uni.showToast({
title: "请输入评论内容",
icon: "none",
});
return;
}
this.commentLoading = true;
try {
//
const newComment = {
id: Date.now(),
userName: "我",
content: this.newComment.trim(),
createTime: new Date().getTime(),
};
this.comments.unshift(newComment);
this.newComment = "";
uni.showToast({
title: "评论成功",
icon: "success",
});
// API
this.saveComment(newComment);
} catch (error) {
console.error("提交评论失败:", error);
uni.showToast({
title: "评论失败",
icon: "none",
});
} finally {
this.commentLoading = false;
}
},
formatCommentTime(timestamp) {
const now = new Date().getTime();
const diff = now - timestamp;
if (diff < 1000 * 60) {
return "刚刚";
} else if (diff < 1000 * 60 * 60) {
return Math.floor(diff / (1000 * 60)) + "分钟前";
} else if (diff < 1000 * 60 * 60 * 24) {
return Math.floor(diff / (1000 * 60 * 60)) + "小时前";
} else {
return Math.floor(diff / (1000 * 60 * 60 * 24)) + "天前";
}
},
async saveLikeStatus() {
// API
console.log("保存点赞状态:", this.isLiked);
},
async saveComment(comment) {
// API
console.log("保存评论:", comment);
},
},
};
</script>
@ -451,25 +640,49 @@ export default {
position: relative;
}
.current-sentence {
.three-sentences {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
gap: 20rpx;
position: relative;
overflow: hidden;
}
.sentence-item {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
transition: all 0.3s ease;
}
.current-sentence {
transform: scale(1.05);
z-index: 2;
}
.prev-sentence {
opacity: 0.5;
transform: scale(0.85) translateY(-10rpx);
}
.next-sentence {
opacity: 0.5;
transform: scale(0.85) translateY(10rpx);
}
.lyric-line {
display: block;
text-align: center;
font-size: 36rpx;
color: #333;
line-height: 1.8;
line-height: 1.6;
margin: 0;
transition: all 0.3s ease;
padding: 20rpx;
font-weight: 600;
padding: 16rpx 20rpx;
word-break: break-all;
}
.lyric-line.active {
@ -478,6 +691,18 @@ export default {
font-size: 36rpx;
}
.lyric-line.prev-line {
color: #999;
font-size: 28rpx;
font-weight: 400;
}
.lyric-line.next-line {
color: #999;
font-size: 28rpx;
font-weight: 400;
}
.sentence-indicator {
position: absolute;
bottom: 20rpx;
@ -590,31 +815,210 @@ export default {
color: #999;
}
/* 句子控制按钮 */
.sentence-controls {
/* 点赞和评论区域 */
.interaction-section {
padding: 20rpx 0;
border-top: 1rpx solid #f0f0f0;
}
.like-section {
display: flex;
justify-content: center;
align-items: center;
gap: 40rpx;
margin-bottom: 30rpx;
padding: 20rpx 0;
border-top: 1rpx solid #f0f0f0;
gap: 60rpx;
}
.sentence-info {
background: #f8f8f8;
padding: 12rpx 24rpx;
.like-btn,
.comment-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
padding: 16rpx 24rpx;
border-radius: 20rpx;
min-width: 120rpx;
text-align: center;
background: #f8f8f8;
transition: all 0.3s ease;
}
.sentence-info-text {
.like-btn:active,
.comment-btn:active {
transform: scale(0.95);
background: #e8e8e8;
}
.like-icon,
.comment-icon {
font-size: 32rpx;
line-height: 1;
}
.like-count,
.comment-count {
font-size: 24rpx;
color: #666;
font-weight: 500;
}
/* 评论容器 */
.comments-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60vh;
background: white;
border-radius: 32rpx 32rpx 0 0;
box-shadow: 0 -8rpx 32rpx rgba(0, 0, 0, 0.1);
z-index: 1000;
display: flex;
flex-direction: column;
}
.comments-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 40rpx 20rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.comments-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.close-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #f0f0f0;
}
.close-icon {
font-size: 28rpx;
color: #666;
}
/* 评论输入区域 */
.comment-input-section {
display: flex;
align-items: center;
padding: 20rpx 40rpx;
gap: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.comment-input {
flex: 1;
height: 80rpx;
background: #f8f8f8;
border-radius: 40rpx;
padding: 0 24rpx;
font-size: 28rpx;
border: none;
outline: none;
}
.submit-btn {
padding: 16rpx 32rpx;
background: #007aff;
border-radius: 40rpx;
transition: all 0.3s ease;
}
.submit-btn.disabled {
background: #ccc;
}
.submit-text {
color: white;
font-size: 28rpx;
font-weight: 500;
}
/* 评论列表 */
.comments-list {
flex: 1;
padding: 20rpx 40rpx;
width: 680rpx;
height: 400rpx;
}
.comment-item {
display: flex;
gap: 20rpx;
padding: 24rpx 0;
border-bottom: 1rpx solid #f8f8f8;
}
.comment-item:last-child {
border-bottom: none;
}
.comment-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #667eea, #764ba2);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.avatar-text {
color: white;
font-size: 32rpx;
font-weight: 600;
}
.comment-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 12rpx;
}
.comment-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.comment-user {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.comment-time {
font-size: 24rpx;
color: #999;
}
.comment-text {
font-size: 28rpx;
color: #333;
line-height: 1.6;
}
/* 空状态 */
.empty-comments {
display: flex;
justify-content: center;
align-items: center;
height: 200rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
/* 底部控制按钮 */
.bottom-controls {
display: flex;

6
pages.json

@ -327,6 +327,12 @@
"navigationBarTextStyle": "white",
"navigationStyle": "custom"
}
},
{
"path": "points/index",
"style": {
"navigationBarTitleText": "积分明细"
}
}
]
},

19
pages/index/components/FollowTab.vue

@ -15,15 +15,15 @@
<!-- 我的关注标题和排序 -->
<view class="follows-header">
<text class="follows-title">我的关注 ({{ followsList.length }})</text>
<view class="sort-option" @click="toggleSort">
<text class="follows-title">我的关注 ({{ followsList.length||0 }})</text>
<!-- <view class="sort-option" @click="toggleSort">
<text class="sort-text">综合排序</text>
<image class="sort-arrow" :src="showImg('/uploads/20250826/8e40deaa0bc67da3a9b104ff0e6b3e7c.png')"></image>
</view>
</view> -->
</view>
<!-- 分类导航 -->
<view class="category-tabs">
<!-- <view class="category-tabs">
<view
class="tab-item"
:class="{ active: activeCategory === 'all' }"
@ -38,7 +38,7 @@
>
商家
</view>
</view>
</view> -->
<!-- 关注用户列表 -->
<view class="follows-list">
@ -58,18 +58,18 @@
<view class="follow-status-btn">
已关注
</view>
<view class="more-options" @click="showOptions(item)">
<!-- <view class="more-options" @click="showOptions(item)">
<text class="more-dots"></text>
</view>
</view> -->
</view>
</view>
</view>
<!-- 推荐用户分隔线 -->
<view class="divider-line"></view>
<view class="divider-line" v-if="false"></view>
<!-- 推荐用户区域 -->
<view class="recommend-section">
<view class="recommend-section" v-if="false">
<view class="recommend-header">
<view class="recommend-title" style="display: flex;align-items: center;">
你可能感兴趣的人
@ -284,7 +284,6 @@ export default {
<style lang="scss" scoped>
.follow-tab-container {
background: #fff;
min-height: 100vh;
}
/* 搜索栏 */

27
pages/index/timeShopBank.vue

@ -66,15 +66,30 @@
<text class="coming-soon">笔记功能开发中...</text>
</view> -->
<!-- 关注tab内容 -->
<view v-if="currentTab == 1" class="follow-content recommend-content">
<!-- <FollowTab /> -->
<text class="coming-soon">关注功能开发中...</text>
<view v-if="currentTab == 1" class="follow-content ">
<FollowTab />
<!-- <text class="coming-soon">关注功能开发中...</text> -->
</view>
<!-- 推荐tab内容 -->
<view v-if="currentTab == 2" class="recommend-content">
<text class="coming-soon">推荐功能开发中...</text>
</view>
<view v-if="currentTab == 2" class="notes-content">
<view class="fab-container">
<image
:src="
showImg('/uploads/20250825/7ea7864b8abb89c3dd7834f025e49b3f.png')
"
style="width: 91rpx; height: 91rpx"
></image>
</view>
<WaterfallLayout
:items="waterfallItems"
:column-count="2"
:column-gap="16"
:item-gap="16"
@item-click="handleItemClick"
style="margin-top: 20rpx"
/>
</view>
</view>
<!-- 控制按钮 -->

6
pages/login/login.vue

@ -88,8 +88,14 @@ export default {
token: uni.getStorageSync('token1')
}, '/api/mini_program/bindPhoneNumber')
.then(res => {
this.Post({
}, '/framework/points/add','DES')
.then(res => {
})
this.$store.commit('changeUserInfo', res.data.userinfo);
this.navigateBasedOnPath();
})
.catch(error => {
console.error('绑定手机号失败:', error);

4
static/js/request.js

@ -8,9 +8,9 @@ const DEV_API_URL = 'http://1.13.193.49';
// const PROD_API_URL = 'https://epic.js-dyyj.com';
const PROD_API_URL = 'http://1.13.193.49';
const NEWAPIURL = process.env.NODE_ENV === 'development' ? DEV_API_URL : PROD_API_URL;
// const DEV_API_URL_DES = 'http://192.168.124.177:8083/xcx';
const DEV_API_URL_DES = 'http://192.168.124.177:8083/xcx';
// const DEV_API_URL_DES = 'https://des.js-dyyj.com/xcx';
const DEV_API_URL_DES = 'http://1.13.193.49:8083/xcx';
// const DEV_API_URL_DES = 'http://1.13.193.49:8083/xcx';
// const PROD_API_URL_DES = 'https://des.js-dyyj.com/xcx';
const PROD_API_URL_DES = 'http://1.13.193.49:8083/xcx';
const NEWAPIURL_DES = process.env.NODE_ENV === 'development' ? DEV_API_URL_DES : PROD_API_URL_DES;

6
subPackages/other/ipPoster.vue

@ -3,13 +3,13 @@
<view class="" style="font-size: 0;">
<BackButton />
<view class="" v-if="index==0">
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/7c5aaadc-0d03-479d-a6b8-a372b0bd7449.jpg"> </image>
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/16/1df5889f-9315-4533-839f-232ea65e3364.png"> </image>
</view>
<view class="" v-if="index==1">
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/ea73035d-f282-4a5b-82df-3ff4be8ba9ae.jpg"> </image>
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/16/d31fb948-a705-4e23-9544-38f1e705a146.jpg"> </image>
</view>
<view class="" v-if="index==2">
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/cade15a3-b473-49fd-80b9-0caee9f7d404.jpg"> </image>
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/16/94e342f7-7215-4f93-b4d0-64aedd2cdbe3.jpg"> </image>
</view>
<view class="" v-if="index==3">
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/4f5581b4-e354-4a2b-8f41-5d37fcd3904b.png"> </image>

452
subPackages/points/index.vue

@ -0,0 +1,452 @@
<template>
<view class="points-detail-page">
<!-- 积分总览 -->
<view class="points-overview">
<view class="total-points">
<text class="points-number">{{ totalPoints }}</text>
<text class="points-label">当前积分</text>
</view>
</view>
<!-- 筛选选项 -->
<view class="filter-tabs">
<view class="tab-item" :class="[{ active: currentTab === 'all' }]" @click="switchTab('all')">
全部
</view>
<view class="tab-item" :class="[{ active: currentTab === 'in' }]" @click="switchTab('in')">
收入
</view>
<view class="tab-item" :class="[{ active: currentTab === 'out' }]" @click="switchTab('out')">
支出
</view>
</view>
<!-- 积分记录列表 -->
<scroll-view class="points-list" scroll-y="true" @scrolltolower="loadMore">
<template v-if="pointsList.length">
<view class="record-item" v-for="(item, index) in pointsList" :key="index">
<view class="record-left">
<view class="record-icon" :class="item.fromType === 'in' ? 'income' : 'expense'">
<uni-icons type="vip" size="30" style="color: white;"></uni-icons>
</view>
<view class="record-info">
<view class="record-title">{{ item.dictName }}</view>
<view class="record-desc">{{ item.remark }}</view>
<view class="record-time">{{ item.createTime }}</view>
</view>
</view>
<view class="record-right">
<view class="record-points" :class="item.fromType === 'in' ? 'income' : 'expense'">
{{ item.points }}
</view>
</view>
</view>
<!-- 加载更多提示 -->
<view class="load-more" v-if="hasMore">
<text class="load-text">{{
loading ? "加载中..." : "上拉加载更多"
}}</text>
</view>
<!-- 没有更多数据 -->
<view class="no-more" v-if="!hasMore && pointsList.length > 0">
<text class="no-more-text">没有更多数据了</text>
</view>
</template>
<!-- 空状态 -->
<view class="empty-state" v-if="pointsList.length === 0 && !loading">
<image class="empty-icon"
src="https://epic.js-dyyj.com/uploads/20250808/c16267f9cc2b7a68bf23713b5847987e.png"
mode="aspectFit"></image>
<text class="empty-text">暂无积分记录</text>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
totalPoints: 0,
currentTab: "all",
pointsList: [],
page: 1,
pageSize: 20,
hasMore: true,
loading: false,
refreshing: false,
};
},
onLoad() {
this.loadPointsData();
this.getTotalPoints();
},
methods: {
//
goBack() {
uni.navigateBack();
},
//
switchTab(tab) {
if (this.currentTab === tab) return;
this.currentTab = tab;
this.resetData();
this.loadPointsData();
},
//
resetData() {
this.pointsList = [];
this.page = 1;
this.hasMore = true;
},
//
async getTotalPoints() {
try {
this.Post({}, '/framework/points/getLastBalance', 'DES').then(res =>{
if (res.code === 200) {
this.totalPoints = res.data || 0;
}
})
} catch (error) {
console.error("获取总积分失败:", error);
}
},
//
async loadPointsData() {
if (this.loading) return;
this.loading = true;
try {
const params = {
page: this.page,
pageSize: this.pageSize,
};
if (this.currentTab !== "all") {
params.fromType = this.currentTab;
}
this.Post(params, '/framework/points/list', 'DES')
.then(res => {
console.log(res)
if (res.code === 200) {
const newData = res.rows || [];
if (this.page === 1) {
this.pointsList = newData;
} else {
this.pointsList = [...this.pointsList, ...newData];
}
this.hasMore = newData.length === this.pageSize;
if (this.hasMore) {
this.page++;
}
} else {
uni.showToast({
title: res.msg || "加载失败",
icon: "none",
});
}
})
} catch (error) {
console.error("加载积分记录失败:", error);
uni.showToast({
title: "网络错误,请重试",
icon: "none",
});
} finally {
this.loading = false;
this.refreshing = false;
}
},
//
loadMore() {
if (this.hasMore && !this.loading) {
this.loadPointsData();
}
},
//
onRefresh() {
this.refreshing = true;
this.resetData();
this.loadPointsData();
this.getTotalPoints();
},
//
formatTime(timestamp) {
const date = new Date(timestamp);
const now = new Date();
const diff = now.getTime() - date.getTime();
//
if (diff < 24 * 60 * 60 * 1000 && now.getDate() === date.getDate()) {
return `今天 ${date.getHours().toString().padStart(2, "0")}:${date
.getMinutes()
.toString()
.padStart(2, "0")}`;
}
//
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (yesterday.getDate() === date.getDate()) {
return `昨天 ${date.getHours().toString().padStart(2, "0")}:${date
.getMinutes()
.toString()
.padStart(2, "0")}`;
}
//
return `${date.getMonth() + 1}-${date.getDate()} ${date
.getHours()
.toString()
.padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
},
},
};
</script>
<style scoped>
.points-detail-page {
min-height: 100vh;
background-color: #f5f5f5;
}
/* 导航栏 */
.nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
height: 88rpx;
padding: 0 32rpx;
background-color: #fff;
border-bottom: 1rpx solid #eee;
}
.nav-back {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nav-back .iconfont {
font-size: 36rpx;
color: #333;
}
.nav-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
.nav-placeholder {
width: 60rpx;
}
/* 积分总览 */
.points-overview {
background: linear-gradient(135deg, #77f3f9 0%, #764ba2 100%);
padding: 60rpx 32rpx;
text-align: center;
}
.total-points {
display: flex;
flex-direction: column;
align-items: center;
}
.points-number {
font-size: 72rpx;
font-weight: bold;
color: #fff;
margin-bottom: 12rpx;
}
.points-label {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 筛选标签 */
.filter-tabs {
display: flex;
background-color: #fff;
padding: 0 32rpx;
}
.tab-item {
flex: 1;
text-align: center;
padding: 32rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
}
.tab-item.active {
color: #77f3f9;
font-weight: 600;
}
.tab-item.active::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: #77f3f9;
border-radius: 2rpx;
}
/* 积分记录列表 */
.points-list {
height: calc(100vh - 368rpx);
padding: 0 30rpx;
width: 690rpx;
}
.record-item {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
padding: 32rpx 24rpx;
margin-top: 20rpx;
border-radius: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
}
.record-left {
display: flex;
align-items: center;
flex: 1;
}
.record-icon {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
}
.record-icon.income {
background-color: #e8f5e8;
}
.record-icon.expense {
background-color: #ffeaea;
}
.record-icon .iconfont {
font-size: 36rpx;
}
.record-icon.income .iconfont {
color: #52c41a;
}
.record-icon.expense .iconfont {
color: #ff4d4f;
}
.record-info {
flex: 1;
}
.record-title {
font-size: 32rpx;
color: #333;
font-weight: 500;
margin-bottom: 8rpx;
}
.record-desc {
font-size: 26rpx;
color: #999;
margin-bottom: 8rpx;
}
.record-time {
font-size: 24rpx;
color: #ccc;
}
.record-right {
text-align: right;
}
.record-points {
font-size: 32rpx;
font-weight: 600;
}
.record-points.income {
color: #52c41a;
}
.record-points.expense {
color: #ff4d4f;
}
/* 加载状态 */
.load-more,
.no-more {
text-align: center;
padding: 40rpx 0;
}
.load-text,
.no-more-text {
font-size: 28rpx;
color: #999;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-icon {
width: 200rpx;
height: 200rpx;
margin-bottom: 32rpx;
opacity: 0.6;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
</style>
Loading…
Cancel
Save