feat: 完善后台管理+搜索功能+分销系统
主要更新: - 后台菜单精简(9项→6项) - 新增搜索功能(敏感信息过滤) - 分销绑定和提现系统完善 - 数据库初始化API(自动修复表结构) - 用户管理:显示绑定关系详情 - 小程序:上下章导航优化、匹配页面重构 - 修复hydration和数据类型问题
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 小程序入口
|
||||
* Soul创业派对 - 小程序入口
|
||||
* 开发: 卡若
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,9 @@ App({
|
||||
purchasedSections: [],
|
||||
hasFullBook: false,
|
||||
|
||||
// 推荐绑定
|
||||
pendingReferralCode: null, // 待绑定的推荐码
|
||||
|
||||
// 主题配置
|
||||
theme: {
|
||||
brandColor: '#00CED1',
|
||||
@@ -45,7 +48,7 @@ App({
|
||||
currentTab: 0
|
||||
},
|
||||
|
||||
onLaunch() {
|
||||
onLaunch(options) {
|
||||
// 获取系统信息
|
||||
this.getSystemInfo()
|
||||
|
||||
@@ -57,6 +60,75 @@ App({
|
||||
|
||||
// 检查更新
|
||||
this.checkUpdate()
|
||||
|
||||
// 处理分享参数(推荐码绑定)
|
||||
this.handleReferralCode(options)
|
||||
},
|
||||
|
||||
// 小程序显示时也检查分享参数
|
||||
onShow(options) {
|
||||
this.handleReferralCode(options)
|
||||
},
|
||||
|
||||
// 处理推荐码绑定
|
||||
handleReferralCode(options) {
|
||||
const query = options?.query || {}
|
||||
const refCode = query.ref || query.referralCode
|
||||
|
||||
if (refCode) {
|
||||
console.log('[App] 检测到推荐码:', refCode)
|
||||
|
||||
// 检查是否已经绑定过
|
||||
const boundRef = wx.getStorageSync('boundReferralCode')
|
||||
if (boundRef && boundRef !== refCode) {
|
||||
console.log('[App] 已绑定过其他推荐码,跳过')
|
||||
return
|
||||
}
|
||||
|
||||
// 保存待绑定的推荐码
|
||||
this.globalData.pendingReferralCode = refCode
|
||||
wx.setStorageSync('pendingReferralCode', refCode)
|
||||
|
||||
// 如果已登录,立即绑定
|
||||
if (this.globalData.isLoggedIn && this.globalData.userInfo) {
|
||||
this.bindReferralCode(refCode)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 绑定推荐码到用户
|
||||
async bindReferralCode(refCode) {
|
||||
try {
|
||||
const userId = this.globalData.userInfo?.id
|
||||
if (!userId || !refCode) return
|
||||
|
||||
// 检查是否已绑定
|
||||
const boundRef = wx.getStorageSync('boundReferralCode')
|
||||
if (boundRef) {
|
||||
console.log('[App] 已绑定推荐码,跳过')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[App] 绑定推荐码:', refCode, '到用户:', userId)
|
||||
|
||||
// 调用API绑定推荐关系
|
||||
const res = await this.request('/api/referral/bind', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
userId,
|
||||
referralCode: refCode
|
||||
}
|
||||
})
|
||||
|
||||
if (res.success) {
|
||||
console.log('[App] 推荐码绑定成功')
|
||||
wx.setStorageSync('boundReferralCode', refCode)
|
||||
this.globalData.pendingReferralCode = null
|
||||
wx.removeStorageSync('pendingReferralCode')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[App] 绑定推荐码失败:', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 获取系统信息
|
||||
@@ -267,8 +339,8 @@ App({
|
||||
mockLogin() {
|
||||
const mockUser = {
|
||||
id: 'user_' + Date.now(),
|
||||
nickname: '卡若',
|
||||
phone: '15880802661',
|
||||
nickname: '访客用户',
|
||||
phone: '',
|
||||
avatar: '',
|
||||
referralCode: 'SOUL' + Date.now().toString(36).toUpperCase().slice(-6),
|
||||
purchasedSections: [],
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
"pages/about/about",
|
||||
"pages/referral/referral",
|
||||
"pages/purchases/purchases",
|
||||
"pages/settings/settings"
|
||||
"pages/settings/settings",
|
||||
"pages/search/search"
|
||||
],
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#000000",
|
||||
"navigationBarTitleText": "Soul创业实验",
|
||||
"navigationBarTitleText": "Soul创业派对",
|
||||
"navigationBarTextStyle": "white",
|
||||
"backgroundColor": "#000000",
|
||||
"navigationStyle": "custom"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 关于作者页
|
||||
* Soul创业派对 - 关于作者页
|
||||
* 开发: 卡若
|
||||
*/
|
||||
const app = getApp()
|
||||
@@ -17,10 +17,8 @@ Page({
|
||||
{ label: '连续直播', value: '365天' },
|
||||
{ label: '派对分享', value: '1000+' }
|
||||
],
|
||||
contact: {
|
||||
wechat: '28533368',
|
||||
phone: '15880802661'
|
||||
},
|
||||
// 联系方式已移至后台配置
|
||||
contact: null,
|
||||
highlights: [
|
||||
'5年私域运营经验',
|
||||
'帮助100+品牌从0到1增长',
|
||||
@@ -67,19 +65,13 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 复制微信号
|
||||
// 联系方式功能已禁用
|
||||
copyWechat() {
|
||||
wx.setClipboardData({
|
||||
data: this.data.author.contact.wechat,
|
||||
success: () => wx.showToast({ title: '微信号已复制', icon: 'success' })
|
||||
})
|
||||
wx.showToast({ title: '请在派对房联系作者', icon: 'none' })
|
||||
},
|
||||
|
||||
// 拨打电话
|
||||
callPhone() {
|
||||
wx.makePhoneCall({
|
||||
phoneNumber: this.data.author.contact.phone
|
||||
})
|
||||
wx.showToast({ title: '请在派对房联系作者', icon: 'none' })
|
||||
},
|
||||
|
||||
// 返回
|
||||
|
||||
@@ -57,24 +57,18 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<!-- 联系方式 - 引导到Soul派对房 -->
|
||||
<view class="contact-card">
|
||||
<text class="card-title">联系作者</text>
|
||||
<view class="contact-item" bindtap="copyWechat">
|
||||
<text class="contact-icon">💬</text>
|
||||
<view class="contact-item">
|
||||
<text class="contact-icon">🎉</text>
|
||||
<view class="contact-info">
|
||||
<text class="contact-label">微信</text>
|
||||
<text class="contact-value">{{author.contact.wechat}}</text>
|
||||
<text class="contact-label">Soul派对房</text>
|
||||
<text class="contact-value">每天早上6-9点开播</text>
|
||||
</view>
|
||||
<text class="contact-btn">复制</text>
|
||||
</view>
|
||||
<view class="contact-item" bindtap="callPhone">
|
||||
<text class="contact-icon">📱</text>
|
||||
<view class="contact-info">
|
||||
<text class="contact-label">电话</text>
|
||||
<text class="contact-value">{{author.contact.phone}}</text>
|
||||
</view>
|
||||
<text class="contact-btn">拨打</text>
|
||||
<view class="contact-tip">
|
||||
<text>在Soul App搜索"创业实验"或"卡若",加入派对房直接交流</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 目录页
|
||||
* Soul创业派对 - 目录页
|
||||
* 开发: 卡若
|
||||
* 技术支持: 存客宝
|
||||
* 数据: 完整真实文章标题
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 首页
|
||||
* Soul创业派对 - 首页
|
||||
* 开发: 卡若
|
||||
* 技术支持: 存客宝
|
||||
*/
|
||||
@@ -28,12 +28,9 @@ Page({
|
||||
{ id: '8.1', title: '流量杠杆:抖音、Soul、飞书', tag: '推荐', tagClass: 'tag-purple', part: '真实的赚钱' }
|
||||
],
|
||||
|
||||
// 最新章节
|
||||
latestSection: {
|
||||
id: '9.14',
|
||||
title: '大健康私域:一个月150万的70后',
|
||||
part: '真实的赚钱'
|
||||
},
|
||||
// 最新章节(动态计算)
|
||||
latestSection: null,
|
||||
latestLabel: '最新更新',
|
||||
|
||||
// 内容概览
|
||||
partsList: [
|
||||
@@ -48,13 +45,19 @@ Page({
|
||||
loading: true
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
onLoad(options) {
|
||||
// 获取系统信息
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight,
|
||||
navBarHeight: app.globalData.navBarHeight
|
||||
})
|
||||
|
||||
// 处理分享参数(推荐码绑定)
|
||||
if (options && options.ref) {
|
||||
console.log('[Index] 检测到推荐码:', options.ref)
|
||||
app.handleReferralCode({ query: options })
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
this.initData()
|
||||
},
|
||||
@@ -76,6 +79,8 @@ Page({
|
||||
try {
|
||||
// 获取书籍数据
|
||||
await this.loadBookData()
|
||||
// 计算推荐章节
|
||||
this.computeLatestSection()
|
||||
} catch (e) {
|
||||
console.error('初始化失败:', e)
|
||||
} finally {
|
||||
@@ -83,6 +88,50 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 计算推荐章节(根据用户ID随机、优先未付款)
|
||||
computeLatestSection() {
|
||||
const { hasFullBook, purchasedSections } = app.globalData
|
||||
const userId = app.globalData.userInfo?.id || wx.getStorageSync('userId') || 'guest'
|
||||
|
||||
// 所有章节列表
|
||||
const allSections = [
|
||||
{ id: '9.14', title: '大健康私域:一个月150万的70后', part: '真实的赚钱' },
|
||||
{ id: '9.13', title: 'AI工具推广:一个隐藏的高利润赛道', part: '真实的赚钱' },
|
||||
{ id: '9.12', title: '美业整合:一个人的公司如何月入十万', part: '真实的赚钱' },
|
||||
{ id: '8.6', title: '云阿米巴:分不属于自己的钱', part: '真实的赚钱' },
|
||||
{ id: '8.1', title: '流量杠杆:抖音、Soul、飞书', part: '真实的赚钱' },
|
||||
{ id: '3.1', title: '3000万流水如何跑出来', part: '真实的行业' },
|
||||
{ id: '5.1', title: '拍卖行抱朴:一天240万的摇号生意', part: '真实的行业' },
|
||||
{ id: '4.1', title: '旅游号:30天10万粉的真实逻辑', part: '真实的行业' }
|
||||
]
|
||||
|
||||
// 用户ID生成的随机种子(同一用户每天看到的不同)
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const seed = (userId + today).split('').reduce((a, b) => a + b.charCodeAt(0), 0)
|
||||
|
||||
// 筛选未付款章节
|
||||
let candidates = allSections
|
||||
if (!hasFullBook) {
|
||||
const purchased = purchasedSections || []
|
||||
const unpurchased = allSections.filter(s => !purchased.includes(s.id))
|
||||
if (unpurchased.length > 0) {
|
||||
candidates = unpurchased
|
||||
}
|
||||
}
|
||||
|
||||
// 根据种子选择章节
|
||||
const index = seed % candidates.length
|
||||
const selected = candidates[index]
|
||||
|
||||
// 设置标签(如果有新增章节显示"最新更新",否则显示"推荐阅读")
|
||||
const label = candidates === allSections ? '推荐阅读' : '为你推荐'
|
||||
|
||||
this.setData({
|
||||
latestSection: selected,
|
||||
latestLabel: label
|
||||
})
|
||||
},
|
||||
|
||||
// 加载书籍数据
|
||||
async loadBookData() {
|
||||
try {
|
||||
@@ -114,6 +163,11 @@ Page({
|
||||
wx.switchTab({ url: '/pages/chapters/chapters' })
|
||||
},
|
||||
|
||||
// 跳转到搜索页
|
||||
goToSearch() {
|
||||
wx.navigateTo({ url: '/pages/search/search' })
|
||||
},
|
||||
|
||||
// 跳转到阅读页
|
||||
goToRead(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--pages/index/index.wxml-->
|
||||
<!--Soul创业实验 - 首页 1:1还原Web版本-->
|
||||
<!--Soul创业派对 - 首页 1:1还原Web版本-->
|
||||
<view class="page page-transition">
|
||||
<!-- 自定义导航栏占位 -->
|
||||
<view class="nav-placeholder" style="height: {{statusBarHeight + 44}}px;"></view>
|
||||
@@ -14,7 +14,7 @@
|
||||
<view class="logo-info">
|
||||
<view class="logo-title">
|
||||
<text class="text-white">Soul</text>
|
||||
<text class="brand-color">创业实验</text>
|
||||
<text class="brand-color">创业派对</text>
|
||||
</view>
|
||||
<text class="logo-subtitle">来自派对房的真实故事</text>
|
||||
</view>
|
||||
@@ -25,12 +25,12 @@
|
||||
</view>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-bar" bindtap="goToChapters">
|
||||
<view class="search-bar" bindtap="goToSearch">
|
||||
<view class="search-icon">
|
||||
<view class="search-circle"></view>
|
||||
<view class="search-handle"></view>
|
||||
</view>
|
||||
<text class="search-placeholder">搜索章节...</text>
|
||||
<text class="search-placeholder">搜索章节标题或内容...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 找伙伴页
|
||||
* Soul创业派对 - 找伙伴页
|
||||
* 按H5网页端完全重构
|
||||
* 开发: 卡若
|
||||
*/
|
||||
@@ -55,7 +55,11 @@ Page({
|
||||
needBindFirst: false,
|
||||
|
||||
// 解锁弹窗
|
||||
showUnlockModal: false
|
||||
showUnlockModal: false,
|
||||
|
||||
// 匹配价格(可配置)
|
||||
matchPrice: 1,
|
||||
extraMatches: 0
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
@@ -86,15 +90,18 @@ Page({
|
||||
// 更新全局配置
|
||||
MATCH_TYPES = res.data.matchTypes || MATCH_TYPES
|
||||
FREE_MATCH_LIMIT = res.data.freeMatchLimit || FREE_MATCH_LIMIT
|
||||
const matchPrice = res.data.matchPrice || 1
|
||||
|
||||
this.setData({
|
||||
matchTypes: MATCH_TYPES,
|
||||
totalMatchesAllowed: FREE_MATCH_LIMIT
|
||||
totalMatchesAllowed: FREE_MATCH_LIMIT,
|
||||
matchPrice: matchPrice
|
||||
})
|
||||
|
||||
console.log('[Match] 加载匹配配置成功:', {
|
||||
types: MATCH_TYPES.length,
|
||||
freeLimit: FREE_MATCH_LIMIT
|
||||
freeLimit: FREE_MATCH_LIMIT,
|
||||
price: matchPrice
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -240,7 +247,7 @@ Page({
|
||||
showPurchaseTip() {
|
||||
wx.showModal({
|
||||
title: '需要购买书籍',
|
||||
content: '购买《一场Soul的创业实验》后即可使用匹配功能,仅需9.9元',
|
||||
content: '购买《Soul创业派对》后即可使用匹配功能,仅需9.9元',
|
||||
confirmText: '去购买',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
@@ -334,7 +341,7 @@ Page({
|
||||
concept: concepts[index % concepts.length],
|
||||
wechat: wechats[index % wechats.length],
|
||||
commonInterests: [
|
||||
{ icon: '📚', text: '都在读《创业实验》' },
|
||||
{ icon: '📚', text: '都在读《创业派对》' },
|
||||
{ icon: '💼', text: '对私域运营感兴趣' },
|
||||
{ icon: '🎯', text: '相似的创业方向' }
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--pages/match/match.wxml-->
|
||||
<!--Soul创业实验 - 找伙伴页 按H5网页端完全重构-->
|
||||
<!--Soul创业派对 - 找伙伴页 按H5网页端完全重构-->
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
@@ -11,6 +11,9 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-placeholder" style="height: {{statusBarHeight + 44}}px;"></view>
|
||||
|
||||
<!-- 顶部留白,让内容往下 -->
|
||||
<view style="height: 30rpx;"></view>
|
||||
|
||||
<!-- 匹配提示条 - 简化显示 -->
|
||||
<view class="match-tip-bar" wx:if="{{matchesRemaining <= 0 && !hasFullBook}}">
|
||||
@@ -73,21 +76,38 @@
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 匹配中状态 -->
|
||||
<!-- 匹配中状态 - 美化特效 -->
|
||||
<block wx:if="{{isMatching}}">
|
||||
<view class="matching-state">
|
||||
<view class="matching-animation">
|
||||
<view class="matching-ring"></view>
|
||||
<view class="matching-center">
|
||||
<text class="matching-icon">👥</text>
|
||||
<view class="matching-animation-v2">
|
||||
<!-- 外层旋转光环 -->
|
||||
<view class="matching-outer-ring"></view>
|
||||
<!-- 中层脉冲环 -->
|
||||
<view class="matching-pulse-ring"></view>
|
||||
<!-- 内层球体 -->
|
||||
<view class="matching-core">
|
||||
<view class="matching-core-inner">
|
||||
<text class="matching-icon-v2">🔍</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="ripple ripple-1"></view>
|
||||
<view class="ripple ripple-2"></view>
|
||||
<view class="ripple ripple-3"></view>
|
||||
<!-- 粒子效果 -->
|
||||
<view class="particle particle-1">✨</view>
|
||||
<view class="particle particle-2">💫</view>
|
||||
<view class="particle particle-3">⭐</view>
|
||||
<view class="particle particle-4">🌟</view>
|
||||
<!-- 扩散波纹 -->
|
||||
<view class="ripple-v2 ripple-v2-1"></view>
|
||||
<view class="ripple-v2 ripple-v2-2"></view>
|
||||
<view class="ripple-v2 ripple-v2-3"></view>
|
||||
</view>
|
||||
<text class="matching-title">正在匹配{{currentTypeLabel}}...</text>
|
||||
<text class="matching-count">已匹配 {{matchAttempts}} 次</text>
|
||||
<view class="cancel-btn" bindtap="cancelMatch">取消匹配</view>
|
||||
<text class="matching-title-v2">正在匹配{{currentTypeLabel}}...</text>
|
||||
<text class="matching-subtitle-v2">正在从 {{matchAttempts * 127 + 89}} 位创业者中为你寻找</text>
|
||||
<view class="matching-tips">
|
||||
<text class="tip-item" wx:if="{{matchAttempts >= 1}}">✓ 分析兴趣标签</text>
|
||||
<text class="tip-item" wx:if="{{matchAttempts >= 2}}">✓ 匹配创业方向</text>
|
||||
<text class="tip-item" wx:if="{{matchAttempts >= 3}}">✓ 筛选优质伙伴</text>
|
||||
</view>
|
||||
<view class="cancel-btn-v2" bindtap="cancelMatch">取消</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
@@ -241,7 +261,7 @@
|
||||
<view class="unlock-info">
|
||||
<view class="info-row">
|
||||
<text class="info-label">单价</text>
|
||||
<text class="info-value text-brand">¥1 / 次</text>
|
||||
<text class="info-value text-brand">¥{{matchPrice || 1}} / 次</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">已购买</text>
|
||||
@@ -250,7 +270,7 @@
|
||||
</view>
|
||||
|
||||
<view class="unlock-buttons">
|
||||
<view class="btn-gold" bindtap="buyMatchCount">立即购买 ¥1</view>
|
||||
<view class="btn-gold" bindtap="buyMatchCount">立即购买 ¥{{matchPrice || 1}}</view>
|
||||
<view class="btn-ghost" bindtap="closeUnlockModal">明天再来</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -983,3 +983,195 @@
|
||||
.bottom-space {
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* ===== 新版匹配动画 V2 ===== */
|
||||
.matching-animation-v2 {
|
||||
position: relative;
|
||||
width: 440rpx;
|
||||
height: 440rpx;
|
||||
margin: 0 auto 48rpx;
|
||||
}
|
||||
|
||||
/* 外层旋转光环 */
|
||||
.matching-outer-ring {
|
||||
position: absolute;
|
||||
inset: -20rpx;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
from 0deg,
|
||||
transparent 0deg,
|
||||
#00CED1 60deg,
|
||||
#7B61FF 120deg,
|
||||
#E91E63 180deg,
|
||||
#FFD700 240deg,
|
||||
#00CED1 300deg,
|
||||
transparent 360deg
|
||||
);
|
||||
animation: rotateRingV2 2s linear infinite;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.matching-outer-ring::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
@keyframes rotateRingV2 {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 中层脉冲环 */
|
||||
.matching-pulse-ring {
|
||||
position: absolute;
|
||||
inset: 20rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid rgba(0, 206, 209, 0.5);
|
||||
animation: pulseRingV2 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulseRingV2 {
|
||||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||||
50% { transform: scale(1.1); opacity: 1; }
|
||||
}
|
||||
|
||||
/* 内层核心球体 */
|
||||
.matching-core {
|
||||
position: absolute;
|
||||
inset: 60rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #1a2a4a 0%, #0a1628 50%, #16213e 100%);
|
||||
box-shadow:
|
||||
0 0 60rpx rgba(0, 206, 209, 0.4),
|
||||
0 0 120rpx rgba(123, 97, 255, 0.2),
|
||||
inset 0 0 80rpx rgba(0, 206, 209, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: floatCoreV2 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.matching-core-inner {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(0, 206, 209, 0.3) 0%, transparent 70%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@keyframes floatCoreV2 {
|
||||
0%, 100% { transform: translateY(0) scale(1); }
|
||||
50% { transform: translateY(-10rpx) scale(1.02); }
|
||||
}
|
||||
|
||||
.matching-icon-v2 {
|
||||
font-size: 80rpx;
|
||||
animation: searchIconV2 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes searchIconV2 {
|
||||
0%, 100% { transform: rotate(-15deg); }
|
||||
50% { transform: rotate(15deg); }
|
||||
}
|
||||
|
||||
/* 粒子效果 */
|
||||
.particle {
|
||||
position: absolute;
|
||||
font-size: 32rpx;
|
||||
animation: floatParticle 3s ease-in-out infinite;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.particle-1 { top: 10%; left: 15%; animation-delay: 0s; }
|
||||
.particle-2 { top: 20%; right: 10%; animation-delay: 0.5s; }
|
||||
.particle-3 { bottom: 20%; left: 10%; animation-delay: 1s; }
|
||||
.particle-4 { bottom: 15%; right: 15%; animation-delay: 1.5s; }
|
||||
|
||||
@keyframes floatParticle {
|
||||
0%, 100% { transform: translateY(0) rotate(0deg); opacity: 0.4; }
|
||||
50% { transform: translateY(-20rpx) rotate(180deg); opacity: 1; }
|
||||
}
|
||||
|
||||
/* 扩散波纹 V2 */
|
||||
.ripple-v2 {
|
||||
position: absolute;
|
||||
inset: 40rpx;
|
||||
border-radius: 50%;
|
||||
border: 3rpx solid;
|
||||
border-color: rgba(0, 206, 209, 0.6);
|
||||
animation: rippleExpandV2 2.5s ease-out infinite;
|
||||
}
|
||||
|
||||
.ripple-v2-1 { animation-delay: 0s; }
|
||||
.ripple-v2-2 { animation-delay: 0.8s; }
|
||||
.ripple-v2-3 { animation-delay: 1.6s; }
|
||||
|
||||
@keyframes rippleExpandV2 {
|
||||
0% { transform: scale(1); opacity: 0.8; }
|
||||
100% { transform: scale(1.8); opacity: 0; }
|
||||
}
|
||||
|
||||
/* 新版匹配文字 */
|
||||
.matching-title-v2 {
|
||||
display: block;
|
||||
font-size: 38rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
margin-bottom: 12rpx;
|
||||
background: linear-gradient(90deg, #00CED1, #7B61FF, #00CED1);
|
||||
background-size: 200% auto;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: shineText 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes shineText {
|
||||
to { background-position: 200% center; }
|
||||
}
|
||||
|
||||
.matching-subtitle-v2 {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
text-align: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.matching-tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
font-size: 26rpx;
|
||||
color: #00CED1;
|
||||
animation: fadeInUp 0.5s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tip-item:nth-child(1) { animation-delay: 0.5s; }
|
||||
.tip-item:nth-child(2) { animation-delay: 1.5s; }
|
||||
.tip-item:nth-child(3) { animation-delay: 2.5s; }
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from { opacity: 0; transform: translateY(20rpx); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.cancel-btn-v2 {
|
||||
display: inline-block;
|
||||
padding: 20rpx 60rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 28rpx;
|
||||
border-radius: 40rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 我的页面
|
||||
* Soul创业派对 - 我的页面
|
||||
* 开发: 卡若
|
||||
* 技术支持: 存客宝
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 阅读页
|
||||
* Soul创业派对 - 阅读页
|
||||
* 开发: 卡若
|
||||
* 技术支持: 存客宝
|
||||
*/
|
||||
@@ -62,9 +62,11 @@ Page({
|
||||
sectionId: id
|
||||
})
|
||||
|
||||
// 保存推荐码
|
||||
// 处理推荐码绑定
|
||||
if (ref) {
|
||||
console.log('[Read] 检测到推荐码:', ref)
|
||||
wx.setStorageSync('referral_code', ref)
|
||||
app.handleReferralCode({ query: { ref } })
|
||||
}
|
||||
|
||||
this.initSection(id)
|
||||
@@ -281,15 +283,33 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享到微信
|
||||
// 分享到微信 - 自动带分享人ID
|
||||
onShareAppMessage() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || wx.getStorageSync('referralCode') || ''
|
||||
|
||||
// 分享标题优化
|
||||
const shareTitle = section?.title
|
||||
? `📚 ${section.title.length > 20 ? section.title.slice(0, 20) + '...' : section.title}`
|
||||
: '📚 Soul创业派对 - 真实商业故事'
|
||||
|
||||
return {
|
||||
title: shareTitle,
|
||||
path: `/pages/read/read?id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`,
|
||||
imageUrl: '/assets/share-cover.png' // 可配置分享封面图
|
||||
}
|
||||
},
|
||||
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || ''
|
||||
|
||||
return {
|
||||
title: `📚 ${section?.title || '推荐阅读'}`,
|
||||
path: `/pages/read/read?id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`
|
||||
title: `${section?.title || 'Soul创业派对'} - 来自派对房的真实故事`,
|
||||
query: `id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--pages/read/read.wxml-->
|
||||
<!--Soul创业实验 - 阅读页 1:1还原Web版本-->
|
||||
<!--Soul创业派对 - 阅读页-->
|
||||
<view class="page">
|
||||
<!-- 阅读进度条 -->
|
||||
<view class="progress-bar-fixed" style="top: {{statusBarHeight}}px;">
|
||||
@@ -138,6 +138,36 @@
|
||||
|
||||
<text class="paywall-tip">邀请好友加入,享90%推广收益</text>
|
||||
</view>
|
||||
|
||||
<!-- 章节导航 - 付费内容也显示 -->
|
||||
<view class="chapter-nav chapter-nav-locked">
|
||||
<view class="nav-buttons">
|
||||
<view
|
||||
class="nav-btn nav-prev {{!prevSection ? 'nav-disabled' : ''}}"
|
||||
bindtap="goToPrev"
|
||||
wx:if="{{prevSection}}"
|
||||
>
|
||||
<text class="btn-label">上一篇</text>
|
||||
<text class="btn-title">章节 {{prevSection.id}}</text>
|
||||
</view>
|
||||
<view class="nav-btn-placeholder" wx:else></view>
|
||||
|
||||
<view
|
||||
class="nav-btn nav-next"
|
||||
bindtap="goToNext"
|
||||
wx:if="{{nextSection}}"
|
||||
>
|
||||
<text class="btn-label">下一篇</text>
|
||||
<view class="btn-row">
|
||||
<text class="btn-title">{{nextSection.title}}</text>
|
||||
<text class="btn-arrow">→</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-btn nav-end" wx:else>
|
||||
<text class="btn-end-text">已是最后一篇 🎉</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -177,7 +207,7 @@
|
||||
<view class="modal-content login-modal" catchtap="stopPropagation">
|
||||
<view class="modal-close" bindtap="closeLoginModal">✕</view>
|
||||
<view class="login-icon">🔐</view>
|
||||
<text class="login-title">登录 Soul创业实验</text>
|
||||
<text class="login-title">登录 Soul创业派对</text>
|
||||
<text class="login-desc">登录后可购买章节、参与匹配、赚取佣金</text>
|
||||
|
||||
<button class="btn-wechat" bindtap="handleWechatLogin">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 分销中心页
|
||||
* Soul创业派对 - 分销中心页
|
||||
* 1:1还原Web版本
|
||||
*/
|
||||
const app = getApp()
|
||||
@@ -140,7 +140,7 @@ Page({
|
||||
|
||||
// 分享到朋友圈
|
||||
shareToMoments() {
|
||||
const shareText = `🔥 发现一本超棒的创业实战书《一场Soul的创业实验》!\n\n💡 62个真实商业案例,从私域运营到资源整合,干货满满!\n\n🎁 通过我的链接购买立享5%优惠,我是 ${this.data.userInfo?.nickname || '卡若'} 推荐!\n\n👉 ${this.data.referralCode} 是我的专属邀请码\n\n#创业实验 #私域运营 #商业案例`
|
||||
const shareText = `🔥 发现一本超棒的创业实战书《Soul创业派对》!\n\n💡 62个真实商业案例,从私域运营到资源整合,干货满满!\n\n🎁 通过我的链接购买立享5%优惠,我是 ${this.data.userInfo?.nickname || '卡若'} 推荐!\n\n👉 ${this.data.referralCode} 是我的专属邀请码\n\n#创业派对 #私域运营 #商业案例`
|
||||
|
||||
wx.setClipboardData({
|
||||
data: shareText,
|
||||
@@ -155,14 +155,78 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 提现
|
||||
handleWithdraw() {
|
||||
const earnings = parseFloat(this.data.earnings)
|
||||
if (earnings < 10) {
|
||||
// 提现 - 直接到微信零钱
|
||||
async handleWithdraw() {
|
||||
const pendingEarnings = parseFloat(this.data.pendingEarnings) || 0
|
||||
|
||||
if (pendingEarnings < 10) {
|
||||
wx.showToast({ title: '满10元可提现', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.showToast({ title: '提现功能开发中', icon: 'none' })
|
||||
|
||||
// 确认提现
|
||||
wx.showModal({
|
||||
title: '确认提现',
|
||||
content: `将提现 ¥${pendingEarnings.toFixed(2)} 到您的微信零钱`,
|
||||
confirmText: '立即提现',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
await this.doWithdraw(pendingEarnings)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 执行提现
|
||||
async doWithdraw(amount) {
|
||||
wx.showLoading({ title: '提现中...' })
|
||||
|
||||
try {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) {
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const res = await app.request('/api/withdraw', {
|
||||
method: 'POST',
|
||||
data: { userId, amount }
|
||||
})
|
||||
|
||||
wx.hideLoading()
|
||||
|
||||
if (res.success) {
|
||||
wx.showModal({
|
||||
title: '提现成功 🎉',
|
||||
content: `¥${amount.toFixed(2)} 已到账您的微信零钱`,
|
||||
showCancel: false,
|
||||
confirmText: '好的'
|
||||
})
|
||||
|
||||
// 刷新数据
|
||||
this.initData()
|
||||
} else {
|
||||
if (res.needBind) {
|
||||
wx.showModal({
|
||||
title: '需要绑定微信',
|
||||
content: '请先在设置中绑定微信账号后再提现',
|
||||
confirmText: '去绑定',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.navigateTo({ url: '/pages/settings/settings' })
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
wx.showToast({ title: res.error || '提现失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
wx.hideLoading()
|
||||
console.error('[Referral] 提现失败:', e)
|
||||
wx.showToast({ title: '提现失败,请重试', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 显示通知
|
||||
@@ -184,11 +248,20 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享
|
||||
// 分享 - 带推荐码
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '📚 一场SOUL的创业实验场 - 来自派对房的真实商业故事',
|
||||
path: `/pages/index/index?ref=${this.data.referralCode}`
|
||||
title: '📚 Soul创业派对 - 来自派对房的真实商业故事',
|
||||
path: `/pages/index/index?ref=${this.data.referralCode}`,
|
||||
imageUrl: '/assets/share-cover.png'
|
||||
}
|
||||
},
|
||||
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: `Soul创业派对 - 62个真实商业案例`,
|
||||
query: `ref=${this.data.referralCode}`
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
87
miniprogram/pages/search/search.js
Normal file
87
miniprogram/pages/search/search.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Soul创业派对 - 章节搜索页
|
||||
* 搜索章节标题和内容
|
||||
*/
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 44,
|
||||
keyword: '',
|
||||
results: [],
|
||||
loading: false,
|
||||
searched: false,
|
||||
total: 0,
|
||||
// 热门搜索
|
||||
hotKeywords: ['私域', '电商', '流量', '赚钱', '创业', 'Soul', '抖音']
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44
|
||||
})
|
||||
},
|
||||
|
||||
// 输入关键词
|
||||
onInput(e) {
|
||||
this.setData({ keyword: e.detail.value })
|
||||
},
|
||||
|
||||
// 清空搜索
|
||||
clearSearch() {
|
||||
this.setData({
|
||||
keyword: '',
|
||||
results: [],
|
||||
searched: false,
|
||||
total: 0
|
||||
})
|
||||
},
|
||||
|
||||
// 点击热门关键词
|
||||
onHotKeyword(e) {
|
||||
const keyword = e.currentTarget.dataset.keyword
|
||||
this.setData({ keyword })
|
||||
this.doSearch()
|
||||
},
|
||||
|
||||
// 执行搜索
|
||||
async doSearch() {
|
||||
const { keyword } = this.data
|
||||
if (!keyword || keyword.trim().length < 1) {
|
||||
wx.showToast({ title: '请输入搜索关键词', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({ loading: true, searched: true })
|
||||
|
||||
try {
|
||||
const res = await app.request(`/api/book/search?q=${encodeURIComponent(keyword.trim())}`)
|
||||
|
||||
if (res && res.success) {
|
||||
this.setData({
|
||||
results: res.results || [],
|
||||
total: res.total || 0
|
||||
})
|
||||
} else {
|
||||
this.setData({ results: [], total: 0 })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('搜索失败:', e)
|
||||
wx.showToast({ title: '搜索失败', icon: 'none' })
|
||||
this.setData({ results: [], total: 0 })
|
||||
} finally {
|
||||
this.setData({ loading: false })
|
||||
}
|
||||
},
|
||||
|
||||
// 跳转阅读
|
||||
goToRead(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
|
||||
},
|
||||
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
}
|
||||
})
|
||||
5
miniprogram/pages/search/search.json
Normal file
5
miniprogram/pages/search/search.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "搜索"
|
||||
}
|
||||
92
miniprogram/pages/search/search.wxml
Normal file
92
miniprogram/pages/search/search.wxml
Normal file
@@ -0,0 +1,92 @@
|
||||
<!--pages/search/search.wxml-->
|
||||
<!--章节搜索页-->
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-content">
|
||||
<view class="back-btn" bindtap="goBack">
|
||||
<text class="back-icon">←</text>
|
||||
</view>
|
||||
<view class="search-input-wrap">
|
||||
<view class="search-icon-small">🔍</view>
|
||||
<input
|
||||
class="search-input"
|
||||
placeholder="搜索章节标题或内容..."
|
||||
value="{{keyword}}"
|
||||
bindinput="onInput"
|
||||
bindconfirm="doSearch"
|
||||
confirm-type="search"
|
||||
focus="{{true}}"
|
||||
/>
|
||||
<view class="clear-btn" wx:if="{{keyword}}" bindtap="clearSearch">×</view>
|
||||
</view>
|
||||
<view class="search-btn" bindtap="doSearch">搜索</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<view class="main-content" style="padding-top: {{statusBarHeight + 56}}px;">
|
||||
|
||||
<!-- 热门搜索(未搜索时显示) -->
|
||||
<view class="hot-section" wx:if="{{!searched}}">
|
||||
<text class="section-title">热门搜索</text>
|
||||
<view class="hot-tags">
|
||||
<view
|
||||
class="hot-tag"
|
||||
wx:for="{{hotKeywords}}"
|
||||
wx:key="*this"
|
||||
bindtap="onHotKeyword"
|
||||
data-keyword="{{item}}"
|
||||
>{{item}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索结果 -->
|
||||
<view class="results-section" wx:if="{{searched}}">
|
||||
<!-- 加载中 -->
|
||||
<view class="loading-wrap" wx:if="{{loading}}">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="loading-text">搜索中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 结果列表 -->
|
||||
<block wx:elif="{{results.length > 0}}">
|
||||
<view class="results-header">
|
||||
<text class="results-count">找到 {{total}} 个结果</text>
|
||||
</view>
|
||||
|
||||
<view class="results-list">
|
||||
<view
|
||||
class="result-item"
|
||||
wx:for="{{results}}"
|
||||
wx:key="id"
|
||||
bindtap="goToRead"
|
||||
data-id="{{item.id}}"
|
||||
>
|
||||
<view class="result-header">
|
||||
<text class="result-chapter">{{item.chapterLabel}}</text>
|
||||
<view class="result-tags">
|
||||
<text class="tag tag-match" wx:if="{{item.matchType === 'title'}}">标题匹配</text>
|
||||
<text class="tag tag-match" wx:elif="{{item.matchType === 'content'}}">内容匹配</text>
|
||||
<text class="tag tag-free" wx:if="{{item.isFree}}">免费</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="result-title">{{item.title}}</text>
|
||||
<text class="result-part">{{item.part}}</text>
|
||||
<view class="result-content" wx:if="{{item.matchedContent}}">
|
||||
<text class="content-preview">{{item.matchedContent}}</text>
|
||||
</view>
|
||||
<view class="result-arrow">→</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 无结果 -->
|
||||
<view class="empty-wrap" wx:elif="{{!loading}}">
|
||||
<text class="empty-icon">🔍</text>
|
||||
<text class="empty-text">未找到相关章节</text>
|
||||
<text class="empty-hint">换个关键词试试</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
264
miniprogram/pages/search/search.wxss
Normal file
264
miniprogram/pages/search/search.wxss
Normal file
@@ -0,0 +1,264 @@
|
||||
/* 章节搜索页样式 */
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #0a0a0a 0%, #111111 100%);
|
||||
}
|
||||
|
||||
/* 导航栏 */
|
||||
.nav-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8rpx 24rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #00CED1;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(255,255,255,0.08);
|
||||
border-radius: 40rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 64rpx;
|
||||
margin: 0 16rpx;
|
||||
}
|
||||
|
||||
.search-icon-small {
|
||||
font-size: 28rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
font-size: 28rpx;
|
||||
color: #00CED1;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
|
||||
/* 主内容 */
|
||||
.main-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
/* 热门搜索 */
|
||||
.hot-section {
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255,255,255,0.6);
|
||||
margin-bottom: 24rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hot-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.hot-tag {
|
||||
background: rgba(0, 206, 209, 0.15);
|
||||
color: #00CED1;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 32rpx;
|
||||
font-size: 28rpx;
|
||||
border: 1rpx solid rgba(0, 206, 209, 0.3);
|
||||
}
|
||||
|
||||
/* 搜索结果 */
|
||||
.results-section {
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
|
||||
.results-header {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.results-count {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.results-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 24rpx;
|
||||
padding: 28rpx;
|
||||
position: relative;
|
||||
border: 1rpx solid rgba(255,255,255,0.08);
|
||||
}
|
||||
|
||||
.result-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.result-chapter {
|
||||
font-size: 24rpx;
|
||||
color: #00CED1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.result-tags {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tag {
|
||||
font-size: 20rpx;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tag-match {
|
||||
background: rgba(147, 112, 219, 0.2);
|
||||
color: #9370DB;
|
||||
}
|
||||
|
||||
.tag-free {
|
||||
background: rgba(76, 175, 80, 0.2);
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.result-part {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255,255,255,0.5);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.result-content {
|
||||
margin-top: 16rpx;
|
||||
padding-top: 16rpx;
|
||||
border-top: 1rpx solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.content-preview {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255,255,255,0.6);
|
||||
line-height: 1.6;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.result-arrow {
|
||||
position: absolute;
|
||||
right: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 32rpx;
|
||||
color: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.loading-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border: 4rpx solid rgba(0, 206, 209, 0.3);
|
||||
border-top-color: #00CED1;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: rgba(255,255,255,0.6);
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255,255,255,0.4);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Soul创业实验 - 设置页
|
||||
* Soul创业派对 - 设置页
|
||||
* 账号绑定功能
|
||||
*/
|
||||
const app = getApp()
|
||||
@@ -115,7 +115,7 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
// 保存绑定信息
|
||||
// 保存绑定信息到本地
|
||||
if (bindType === 'phone') {
|
||||
wx.setStorageSync('user_phone', bindValue)
|
||||
this.setData({ phoneNumber: bindValue })
|
||||
@@ -127,9 +127,122 @@ Page({
|
||||
this.setData({ alipayAccount: bindValue })
|
||||
}
|
||||
|
||||
// 同步到服务器
|
||||
this.syncProfileToServer()
|
||||
|
||||
this.setData({ showBindModal: false })
|
||||
wx.showToast({ title: '绑定成功', icon: 'success' })
|
||||
},
|
||||
|
||||
// 同步资料到服务器
|
||||
async syncProfileToServer() {
|
||||
try {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) return
|
||||
|
||||
const res = await app.request('/api/user/profile', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
userId,
|
||||
phone: this.data.phoneNumber || undefined,
|
||||
wechatId: this.data.wechatId || undefined
|
||||
}
|
||||
})
|
||||
|
||||
if (res.success) {
|
||||
console.log('[Settings] 资料同步成功')
|
||||
// 更新本地用户信息
|
||||
if (app.globalData.userInfo) {
|
||||
app.globalData.userInfo.phone = this.data.phoneNumber
|
||||
app.globalData.userInfo.wechatId = this.data.wechatId
|
||||
wx.setStorageSync('userInfo', app.globalData.userInfo)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Settings] 资料同步失败:', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 获取微信头像(新版授权)
|
||||
async getWechatAvatar() {
|
||||
try {
|
||||
const res = await wx.getUserProfile({
|
||||
desc: '用于完善会员资料'
|
||||
})
|
||||
|
||||
if (res.userInfo) {
|
||||
const { nickName, avatarUrl } = res.userInfo
|
||||
|
||||
// 更新本地
|
||||
this.setData({
|
||||
userInfo: {
|
||||
...this.data.userInfo,
|
||||
nickname: nickName,
|
||||
avatar: avatarUrl
|
||||
}
|
||||
})
|
||||
|
||||
// 同步到服务器
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (userId) {
|
||||
await app.request('/api/user/profile', {
|
||||
method: 'POST',
|
||||
data: { userId, nickname: nickName, avatar: avatarUrl }
|
||||
})
|
||||
}
|
||||
|
||||
// 更新全局
|
||||
if (app.globalData.userInfo) {
|
||||
app.globalData.userInfo.nickname = nickName
|
||||
app.globalData.userInfo.avatar = avatarUrl
|
||||
wx.setStorageSync('userInfo', app.globalData.userInfo)
|
||||
}
|
||||
|
||||
wx.showToast({ title: '头像更新成功', icon: 'success' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Settings] 获取头像失败:', e)
|
||||
wx.showToast({ title: '获取头像失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 获取微信手机号(需要button组件配合)
|
||||
async getPhoneNumber(e) {
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
wx.showToast({ title: '授权失败', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 需要将code发送到服务器解密获取手机号
|
||||
const code = e.detail.code
|
||||
if (!code) {
|
||||
wx.showToast({ title: '获取失败,请手动输入', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务器解密手机号
|
||||
const res = await app.request('/api/wechat/phone', {
|
||||
method: 'POST',
|
||||
data: { code }
|
||||
})
|
||||
|
||||
if (res.success && res.phoneNumber) {
|
||||
wx.setStorageSync('user_phone', res.phoneNumber)
|
||||
this.setData({ phoneNumber: res.phoneNumber })
|
||||
|
||||
// 同步到服务器
|
||||
this.syncProfileToServer()
|
||||
|
||||
wx.showToast({ title: '手机号绑定成功', icon: 'success' })
|
||||
} else {
|
||||
wx.showToast({ title: '获取失败,请手动输入', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Settings] 获取手机号失败:', e)
|
||||
wx.showToast({ title: '获取失败,请手动输入', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭绑定弹窗
|
||||
closeBindModal() {
|
||||
@@ -177,12 +290,9 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 联系客服
|
||||
// 联系客服 - 跳转到Soul派对房
|
||||
contactService() {
|
||||
wx.setClipboardData({
|
||||
data: '28533368',
|
||||
success: () => wx.showToast({ title: '客服微信已复制', icon: 'success' })
|
||||
})
|
||||
wx.showToast({ title: '请在Soul派对房联系客服', icon: 'none' })
|
||||
},
|
||||
|
||||
// 阻止冒泡
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compileType": "miniprogram",
|
||||
"miniprogramRoot": "",
|
||||
"projectname": "soul-startup",
|
||||
"description": "一场SOUL的创业实验场 - 来自Soul派对房的真实商业故事",
|
||||
"description": "Soul创业派对 - 来自派对房的真实商业故事",
|
||||
"appid": "wxb8bbb2b10dec74aa",
|
||||
"setting": {
|
||||
"urlCheck": false,
|
||||
|
||||
Reference in New Issue
Block a user