feat: 完成见素起名小程序核心功能
- 实现 AI 起名功能(Kimi API 接入) - 添加用户收藏功能(MySQL 数据库) - 实现海报生成与分享 - 添加音效和触觉反馈 - 配置生产环境部署(WAR 包 + Nginx) - 支持多种起名模式(经典、诗词、自然、现代) - 实现分批加载优化体验
This commit is contained in:
@@ -1,25 +1,98 @@
|
||||
Page({
|
||||
data: {
|
||||
keyword: ''
|
||||
keyword: '',
|
||||
surname: '',
|
||||
activeMode: 'baby',
|
||||
isGenerating: false,
|
||||
modes: [
|
||||
{ key: 'baby', label: '宝宝' },
|
||||
{ key: 'persona', label: '人设' },
|
||||
{ key: 'classic', label: '拾遗' }
|
||||
]
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 页面加载时检查是否需要重置状态
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 每次显示页面时重置生成状态
|
||||
this.setData({
|
||||
isGenerating: false
|
||||
});
|
||||
},
|
||||
|
||||
// 选择模式
|
||||
selectMode(e) {
|
||||
const mode = e.currentTarget.dataset.mode;
|
||||
this.setData({
|
||||
activeMode: mode
|
||||
});
|
||||
},
|
||||
|
||||
// 姓氏输入
|
||||
onSurnameInput(e) {
|
||||
this.setData({
|
||||
surname: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
// 关键词输入
|
||||
onInput(e) {
|
||||
this.setData({
|
||||
keyword: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
startNaming() {
|
||||
if (!this.data.keyword.trim()) {
|
||||
// 开始生成(带水墨动画)
|
||||
startGenerate() {
|
||||
const { keyword, surname, activeMode } = this.data;
|
||||
|
||||
// 非空校验
|
||||
if (!keyword.trim()) {
|
||||
const placeholderMap = {
|
||||
'baby': '请输入期待',
|
||||
'persona': '请输入人设',
|
||||
'classic': '请输入关键词'
|
||||
};
|
||||
wx.showToast({
|
||||
title: '请输入一抹期待',
|
||||
title: placeholderMap[activeMode] || '请输入内容',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 宝宝模式需要姓氏
|
||||
if (activeMode === 'baby' && !surname.trim()) {
|
||||
wx.showToast({
|
||||
title: '请输入姓氏',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.navigateTo({
|
||||
url: `/pages/index/index?keyword=${encodeURIComponent(this.data.keyword)}`
|
||||
// 触发水墨动画
|
||||
this.setData({
|
||||
isGenerating: true
|
||||
});
|
||||
|
||||
// 播放水滴声
|
||||
getApp().playAudio('inkDrop');
|
||||
|
||||
// 触觉反馈
|
||||
wx.vibrateShort({ type: 'light' });
|
||||
|
||||
// 延迟 1000ms 后跳转,确保仪式感完整
|
||||
setTimeout(() => {
|
||||
// 构建跳转 URL
|
||||
let url = `/pages/index/index?keyword=${encodeURIComponent(keyword)}&mode=${activeMode}`;
|
||||
if (activeMode === 'baby' && surname) {
|
||||
url += `&surname=${encodeURIComponent(surname)}`;
|
||||
}
|
||||
|
||||
wx.navigateTo({
|
||||
url: url
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,45 @@
|
||||
<view class="container">
|
||||
<view class="content">
|
||||
<!-- 水墨动画遮罩 -->
|
||||
<view class="ink-overlay {{isGenerating ? 'active' : ''}}">
|
||||
<view class="ink-circle"></view>
|
||||
</view>
|
||||
|
||||
<view class="content {{isGenerating ? 'fade-out' : ''}}">
|
||||
<view class="title">见素</view>
|
||||
<view class="subtitle">回归名字的诗意与留白</view>
|
||||
|
||||
<!-- 模式选择 -->
|
||||
<view class="mode-selector">
|
||||
<view
|
||||
wx:for="{{modes}}"
|
||||
wx:key="key"
|
||||
class="mode-item {{activeMode === item.key ? 'active' : ''}}"
|
||||
bindtap="selectMode"
|
||||
data-mode="{{item.key}}"
|
||||
>
|
||||
{{item.label}}
|
||||
<view class="mode-dot" wx:if="{{activeMode === item.key}}"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 姓氏输入(仅在宝宝模式显示) -->
|
||||
<view class="surname-section" wx:if="{{activeMode === 'baby'}}">
|
||||
<input
|
||||
class="surname-input"
|
||||
placeholder="姓氏"
|
||||
placeholder-class="placeholder"
|
||||
bindinput="onSurnameInput"
|
||||
value="{{surname}}"
|
||||
maxlength="2"
|
||||
/>
|
||||
<view class="line"></view>
|
||||
</view>
|
||||
|
||||
<!-- 关键词输入 -->
|
||||
<view class="input-section">
|
||||
<input
|
||||
class="keyword-input"
|
||||
placeholder="输入关键词,如:自由、清冷"
|
||||
placeholder="{{activeMode === 'baby' ? '期待,如:自由、清冷' : activeMode === 'persona' ? '人设,如:温柔、坚韧' : '关键词,如:自由、清冷'}}"
|
||||
placeholder-class="placeholder"
|
||||
bindinput="onInput"
|
||||
value="{{keyword}}"
|
||||
@@ -15,11 +48,11 @@
|
||||
</view>
|
||||
|
||||
<view class="action-section">
|
||||
<button class="generate-btn" bindtap="startNaming">感悟名字</button>
|
||||
<button class="generate-btn" bindtap="startGenerate">感悟名字</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="footer">
|
||||
<view class="footer {{isGenerating ? 'fade-out' : ''}}">
|
||||
<text>© 见素 · 审美溢价</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -9,14 +9,67 @@ page {
|
||||
flex-direction: column;
|
||||
padding: 0 80rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 水墨动画遮罩 */
|
||||
.ink-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ink-overlay.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.ink-circle {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: #000000;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.ink-overlay.active .ink-circle {
|
||||
animation: inkSpread 1.8s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes inkSpread {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 350vmax;
|
||||
height: 350vmax;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 35vh;
|
||||
margin-top: 30vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
animation: contentFadeIn 1.5s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.content.fade-out {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -33,12 +86,61 @@ page {
|
||||
font-size: 22rpx;
|
||||
color: #D0D0D0;
|
||||
letter-spacing: 6rpx;
|
||||
margin-bottom: 150rpx;
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
|
||||
/* 模式选择器 */
|
||||
.mode-selector {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-bottom: 60rpx;
|
||||
gap: 60rpx;
|
||||
}
|
||||
|
||||
.mode-item {
|
||||
font-size: 24rpx;
|
||||
color: #B0B0B0;
|
||||
letter-spacing: 4rpx;
|
||||
padding: 10rpx 0;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.mode-item.active {
|
||||
color: #2D2D2D;
|
||||
}
|
||||
|
||||
.mode-dot {
|
||||
position: absolute;
|
||||
bottom: -4rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 6rpx;
|
||||
height: 6rpx;
|
||||
background-color: #2D2D2D;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* 姓氏输入 */
|
||||
.surname-section {
|
||||
width: 100%;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.surname-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #4A4A4A;
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
|
||||
/* 关键词输入 */
|
||||
.input-section {
|
||||
width: 100%;
|
||||
margin-bottom: 80rpx;
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.keyword-input {
|
||||
@@ -63,6 +165,7 @@ page {
|
||||
transition: width 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
}
|
||||
|
||||
.surname-section:focus-within .line,
|
||||
.input-section:focus-within .line {
|
||||
width: 80rpx;
|
||||
background-color: #2D2D2D;
|
||||
@@ -75,16 +178,18 @@ page {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
/* 全黑背景、无圆角、加宽字间距的按钮 */
|
||||
.generate-btn {
|
||||
background: none !important;
|
||||
color: #A0A0A0 !important;
|
||||
background-color: #1a1a1a !important;
|
||||
color: #ffffff !important;
|
||||
font-size: 24rpx !important;
|
||||
font-weight: 200 !important;
|
||||
padding: 20rpx 60rpx !important;
|
||||
letter-spacing: 12rpx !important;
|
||||
text-indent: 12rpx !important;
|
||||
transition: all 0.3s;
|
||||
font-weight: 300 !important;
|
||||
padding: 24rpx 80rpx !important;
|
||||
letter-spacing: 16rpx !important;
|
||||
text-indent: 16rpx !important;
|
||||
transition: all 0.3s ease;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.generate-btn::after {
|
||||
@@ -92,7 +197,7 @@ page {
|
||||
}
|
||||
|
||||
.generate-btn:active {
|
||||
color: #2D2D2D !important;
|
||||
background-color: #333333 !important;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
@@ -103,6 +208,11 @@ page {
|
||||
right: 0;
|
||||
text-align: center;
|
||||
animation: footerFadeIn 3s ease-in;
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.footer.fade-out {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.footer text {
|
||||
@@ -120,4 +230,4 @@ page {
|
||||
0% { opacity: 0; }
|
||||
70% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user