feat: 完善见素起名小程序功能
- 添加收藏锦囊功能,支持查看和删除收藏 - 实现积分系统,每日赠送5次灵感次数 - 添加静心阅读功能,阅读15秒可获得额外次数 - 实现灵感广场,展示用户分享的名字 - 添加字源溯源组件,长按汉字查看详情 - 优化空状态和结语卡片样式统一 - 添加音频控制(静音/风铃/雨落/古琴/白噪音/森林/溪流) - 优化名字生成逻辑,确保每次返回5个不重复名字 - 修复卡片翻转样式问题 - 移除首页动态提醒气泡
This commit is contained in:
@@ -4,20 +4,47 @@ Page({
|
||||
showDetail: false,
|
||||
selectedItem: {},
|
||||
selectedIndex: -1,
|
||||
openid: 'test_openid' // 实际应从登录获取
|
||||
openid: null,
|
||||
creditsInfo: {
|
||||
dailyCredits: 5,
|
||||
totalCredits: 0,
|
||||
watchedAdCount: 0
|
||||
},
|
||||
// 静心阅读
|
||||
showMeditation: false,
|
||||
meditationPoem: null,
|
||||
meditationProgress: 0
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadFavorites();
|
||||
this.setOpenid();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 每次显示页面时刷新列表
|
||||
this.loadFavorites();
|
||||
// 加载积分信息
|
||||
this.loadCreditsInfo();
|
||||
},
|
||||
|
||||
// 设置 openid
|
||||
setOpenid() {
|
||||
const openid = getApp().getOpenid();
|
||||
if (openid) {
|
||||
this.setData({ openid });
|
||||
this.loadFavorites();
|
||||
} else {
|
||||
// openid 还未获取到,延迟重试
|
||||
setTimeout(() => this.setOpenid(), 500);
|
||||
}
|
||||
},
|
||||
|
||||
// 加载收藏列表
|
||||
loadFavorites() {
|
||||
if (!this.data.openid) {
|
||||
console.log('openid 未获取到,跳过加载收藏');
|
||||
return;
|
||||
}
|
||||
const apiBaseUrl = getApp().globalData.apiBaseUrl;
|
||||
wx.request({
|
||||
url: `${apiBaseUrl}/api/favorites/list`,
|
||||
@@ -38,6 +65,140 @@ Page({
|
||||
wx.navigateBack();
|
||||
},
|
||||
|
||||
// 加载积分信息
|
||||
loadCreditsInfo() {
|
||||
const openid = getApp().getOpenid();
|
||||
if (!openid) {
|
||||
console.log('openid 未获取到,跳过加载积分');
|
||||
return;
|
||||
}
|
||||
const apiBaseUrl = getApp().globalData.apiBaseUrl;
|
||||
wx.request({
|
||||
url: `${apiBaseUrl}/api/credits/info`,
|
||||
data: { openid },
|
||||
success: (res) => {
|
||||
if (res.data && res.data.success) {
|
||||
this.setData({ creditsInfo: res.data.data });
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 点击积分区域
|
||||
onCreditsTap() {
|
||||
const { creditsInfo } = this.data;
|
||||
|
||||
// 如果还有剩余次数,显示提示
|
||||
if (creditsInfo.dailyCredits > 0) {
|
||||
wx.showToast({
|
||||
title: `今日还有 ${creditsInfo.dailyCredits} 次灵感`,
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果次数用完且还可以看广告
|
||||
if (creditsInfo.watchedAdCount < 5) {
|
||||
wx.showModal({
|
||||
title: '静心阅读',
|
||||
content: '观看 15 秒静心画报,即可获得 3 次灵感',
|
||||
confirmText: '开始阅读',
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.watchAd();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '今日次数已达上限,明日再来',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 静心阅读 - 模拟 15 秒阅读体验
|
||||
watchAd() {
|
||||
const openid = getApp().getOpenid();
|
||||
if (!openid) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 随机选择一首诗词
|
||||
const poems = [
|
||||
{ text: '「采菊东篱下,悠然见南山」', author: '陶渊明《饮酒》' },
|
||||
{ text: '「行到水穷处,坐看云起时」', author: '王维《终南别业》' },
|
||||
{ text: '「人闲桂花落,夜静春山空」', author: '王维《鸟鸣涧》' },
|
||||
{ text: '「松风吹解带,山月照弹琴」', author: '王维《酬张少府》' },
|
||||
{ text: '「曲径通幽处,禅房花木深」', author: '常建《题破山寺后禅院》' },
|
||||
{ text: '「明月松间照,清泉石上流」', author: '王维《山居秋暝》' }
|
||||
];
|
||||
const poem = poems[Math.floor(Math.random() * poems.length)];
|
||||
|
||||
// 显示静心阅读页面
|
||||
this.setData({
|
||||
showMeditation: true,
|
||||
meditationPoem: poem,
|
||||
meditationProgress: 0
|
||||
});
|
||||
|
||||
// 15 秒倒计时 - 每 150ms 增加 1%,总共 150 * 100 = 15000ms = 15秒
|
||||
let progress = 0;
|
||||
const timer = setInterval(() => {
|
||||
progress += 1;
|
||||
this.setData({ meditationProgress: progress });
|
||||
|
||||
if (progress >= 100) {
|
||||
clearInterval(timer);
|
||||
this.meditationTimer = null;
|
||||
// 延迟一下再关闭,让用户看到完成状态
|
||||
setTimeout(() => {
|
||||
this.setData({ showMeditation: false });
|
||||
// 领取奖励
|
||||
this.rewardAd(openid);
|
||||
}, 500);
|
||||
}
|
||||
}, 150);
|
||||
|
||||
// 保存 timer 以便可以提前关闭
|
||||
this.meditationTimer = timer;
|
||||
},
|
||||
|
||||
// 提前关闭静心阅读
|
||||
closeMeditation() {
|
||||
if (this.meditationTimer) {
|
||||
clearInterval(this.meditationTimer);
|
||||
this.meditationTimer = null;
|
||||
}
|
||||
this.setData({ showMeditation: false });
|
||||
},
|
||||
|
||||
// 领取广告奖励
|
||||
rewardAd(openid) {
|
||||
const apiBaseUrl = getApp().globalData.apiBaseUrl;
|
||||
wx.request({
|
||||
url: `${apiBaseUrl}/api/credits/reward`,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
data: `openid=${encodeURIComponent(openid)}`,
|
||||
success: (res) => {
|
||||
if (res.data && res.data.success) {
|
||||
wx.showToast({ title: '获得 3 次灵感', icon: 'success' });
|
||||
this.loadCreditsInfo();
|
||||
} else {
|
||||
wx.showToast({ title: res.data.message || '领取失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
wx.showToast({ title: '领取失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 点击收藏项
|
||||
onItemTap(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
@@ -79,12 +240,8 @@ Page({
|
||||
if (res.confirm) {
|
||||
const apiBaseUrl = getApp().globalData.apiBaseUrl;
|
||||
wx.request({
|
||||
url: `${apiBaseUrl}/api/favorites/remove`,
|
||||
url: `${apiBaseUrl}/api/favorites/remove?openid=${this.data.openid}&name=${encodeURIComponent(item.name)}`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
openid: this.data.openid,
|
||||
name: item.name
|
||||
},
|
||||
success: (res) => {
|
||||
if (res.data && res.data.success) {
|
||||
wx.showToast({ title: '已移除', icon: 'success' });
|
||||
|
||||
@@ -6,6 +6,18 @@
|
||||
<view class="header-spacer"></view>
|
||||
</view>
|
||||
|
||||
<!-- 积分信息 - 克制地放在角落 -->
|
||||
<view class="credits-bar" bindtap="onCreditsTap">
|
||||
<view class="credits-item">
|
||||
<text class="credits-icon">✦</text>
|
||||
<text class="credits-text">今日灵感 {{creditsInfo.dailyCredits || 0}}/5</text>
|
||||
</view>
|
||||
<view class="credits-item watch-ad" wx:if="{{(creditsInfo.dailyCredits || 0) === 0 && (creditsInfo.watchedAdCount || 0) < 5}}">
|
||||
<text class="credits-icon">📖</text>
|
||||
<text class="credits-text">静心阅读 +3</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收藏列表 -->
|
||||
<scroll-view scroll-y class="favorites-scroll" wx:if="{{favorites.length > 0}}">
|
||||
<view class="favorites-grid">
|
||||
@@ -46,4 +58,23 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 静心阅读全屏页 -->
|
||||
<view class="meditation-page {{showMeditation ? 'visible' : ''}}">
|
||||
<view class="meditation-close" bindtap="closeMeditation">×</view>
|
||||
<view class="meditation-content">
|
||||
<view class="meditation-title">静心阅读</view>
|
||||
<view class="meditation-poem" wx:if="{{meditationPoem}}">
|
||||
<text class="poem-text">{{meditationPoem.text}}</text>
|
||||
<text class="poem-author">——{{meditationPoem.author}}</text>
|
||||
</view>
|
||||
<view class="meditation-hint">静观 15 秒,心随诗远</view>
|
||||
</view>
|
||||
<view class="meditation-progress">
|
||||
<view class="progress-bar">
|
||||
<view class="progress-fill" style="width: {{meditationProgress}}%"></view>
|
||||
</view>
|
||||
<text class="progress-text">{{meditationProgress}}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -36,6 +36,47 @@ page {
|
||||
width: 76rpx;
|
||||
}
|
||||
|
||||
/* 积分信息 - 克制地放在角落 */
|
||||
.credits-bar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.credits-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 12rpx 20rpx;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 30rpx;
|
||||
opacity: 0.7;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.credits-item:active {
|
||||
opacity: 1;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.credits-item.watch-ad {
|
||||
background: #F5F5F0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.credits-icon {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.credits-text {
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
/* 收藏列表 */
|
||||
.favorites-scroll {
|
||||
height: calc(100vh - 200rpx);
|
||||
@@ -215,3 +256,113 @@ page {
|
||||
.remove-btn:active {
|
||||
background: #E8E8E8;
|
||||
}
|
||||
|
||||
/* 静心阅读全屏页 */
|
||||
.meditation-page {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.meditation-page.visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.meditation-close {
|
||||
position: absolute;
|
||||
top: 60rpx;
|
||||
right: 40rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 48rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.meditation-content {
|
||||
text-align: center;
|
||||
padding: 60rpx;
|
||||
}
|
||||
|
||||
.meditation-title {
|
||||
font-size: 32rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
letter-spacing: 8rpx;
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
|
||||
.meditation-poem {
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.poem-text {
|
||||
display: block;
|
||||
font-family: "KaiTi", "STKaiti", serif;
|
||||
font-size: 56rpx;
|
||||
color: #ffffff;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 8rpx;
|
||||
margin-bottom: 40rpx;
|
||||
text-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.poem-author {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
|
||||
.meditation-hint {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
letter-spacing: 4rpx;
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.meditation-progress {
|
||||
position: absolute;
|
||||
bottom: 100rpx;
|
||||
left: 80rpx;
|
||||
right: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
flex: 1;
|
||||
height: 4rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 2rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 2rpx;
|
||||
transition: width 0.15s linear;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
min-width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user