diff --git a/miniprogram/app.js b/miniprogram/app.js index d7a15421..25519f48 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -13,8 +13,8 @@ const DEFAULT_WITHDRAW_TMPL_ID = 'u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE' App({ globalData: { // API 基础地址:开发时修改下面一行切换环境 - baseUrl: "https://soulapi.quwanzhi.com", - // baseUrl: 'http://localhost:8080', // 开发 + // baseUrl: "https://soulapi.quwanzhi.com", + baseUrl: 'http://localhost:8080', // 开发 // baseUrl: 'https://souldev.quwanzhi.com', // 测试 // 小程序配置 - 真实AppID appId: DEFAULT_APP_ID, diff --git a/miniprogram/assets/icons/circle.svg b/miniprogram/assets/icons/circle.svg new file mode 100644 index 00000000..71d4fad5 --- /dev/null +++ b/miniprogram/assets/icons/circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/miniprogram/components/icon/icon.js b/miniprogram/components/icon/icon.js index 10918dac..095a9068 100644 --- a/miniprogram/components/icon/icon.js +++ b/miniprogram/components/icon/icon.js @@ -135,7 +135,7 @@ Component({ 'run-in': '\ue6a7', 'pin': '\ue6a8', 'save': '\ue6a9', - 'search': '', // 强制走 SVG + 'search': '\ue6aa', 'share': '\ue6ab', 'scanning': '\ue6ac', 'security': '\ue6ad', @@ -157,19 +157,19 @@ Component({ 'chevron-right': '\ue6c6', 'chevron-down': '\ue6c4', 'chevron-up': '\ue6c2', - 'x': '', // 强制走 SVG - 'check': '', // 强制走 SVG + 'x': '\ue6c3', + 'check': '\ue6c7', 'trash-2': '\ue66a', 'pencil': '\ue685', - 'zap': '', // 强制走 SVG,找伙伴页等统一用 Lucide 风格 + 'zap': '\ue75c', 'info': '\ue69c', 'map-pin': '\ue6a8', - 'message-circle': '', // 强制走 SVG - 'smartphone': '', // 强制走 SVG + 'message-circle': '\ue678', + 'smartphone': '\ue6a0', 'refresh-cw': '\ue6a4', 'shield': '\ue6ad', - 'star': '', // 强制走 SVG - 'heart': '', // 强制走 SVG + 'star': '\ue689', + 'heart': '\ue68e', 'bar-chart': '\ue672', 'clock': '\ue6b5', } @@ -224,9 +224,7 @@ Component({ 'corner-down-left': s + '', 'folder': s + '', 'bar-chart': s + '', - 'link': s + '', - 'zap': s + '', - 'x': s + '' + 'link': s + '' } return svgMap[name] || '' }, diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js index 53fcba0d..e66cec0b 100644 --- a/miniprogram/pages/index/index.js +++ b/miniprogram/pages/index/index.js @@ -66,8 +66,7 @@ Page({ // 展开状态(首页精选/最新) featuredExpanded: false, latestExpanded: false, - featuredSectionsFull: [], // 展开时用 book/hot 加载的完整列表 - featuredExpandedLoading: false, + featuredSectionsFull: [], // ranking 返回的 10 条,默认展示前 5 条 // 功能配置(搜索开关) searchEnabled: true, @@ -203,24 +202,29 @@ Page({ tagClass: ['tag-hot', 'tag-rec', 'tag-rec'][i] || 'tag-rec' }) - const [recRes, latestRes] = await Promise.all([ - app.request({ url: '/api/miniprogram/book/recommended', silent: true }).catch(() => null), + const [rankRes, latestRes] = await Promise.all([ + app.request({ url: '/api/miniprogram/book/ranking?limit=10', silent: true }).catch(() => null), app.request({ url: '/api/miniprogram/book/latest-chapters', silent: true }).catch(() => null) ]) - // 1. 精选推荐(recommended → hot 兜底) - let featured = [] - if (recRes && recRes.success && Array.isArray(recRes.data) && recRes.data.length > 0) { - featured = recRes.data.map((s, i) => toSection(s, i)) + // 1. 精选推荐(10 条,默认展示 5 条,展开显示 10 条) + let featuredFull = [] + if (rankRes && rankRes.success && Array.isArray(rankRes.data) && rankRes.data.length > 0) { + featuredFull = rankRes.data.map((s, i) => toSection(s, i)) } - if (featured.length === 0) { + if (featuredFull.length === 0) { try { const hotRes = await app.request({ url: '/api/miniprogram/book/hot?limit=10', silent: true }) const hotList = (hotRes && hotRes.data) ? hotRes.data : [] - if (hotList.length > 0) featured = hotList.slice(0, 3).map((s, i) => toSection(s, i)) + if (hotList.length > 0) featuredFull = hotList.slice(0, 10).map((s, i) => toSection(s, i)) } catch (e) { console.log('[Index] book/hot 兜底失败:', e) } } - if (featured.length > 0) this.setData({ featuredSections: featured }) + if (featuredFull.length > 0) { + this.setData({ + featuredSectionsFull: featuredFull, + featuredSections: featuredFull.slice(0, 5) + }) + } // 2. 最新更新 + 最新列表(共用 latest-chapters 数据) const rawList = (latestRes && latestRes.data) ? latestRes.data : [] @@ -522,41 +526,14 @@ Page({ wx.switchTab({ url: '/pages/match/match' }) }, - // 精选推荐:展开/折叠 - async toggleFeaturedExpanded() { - if (this.data.featuredExpandedLoading) return + // 精选推荐:展开/折叠(默认 5 条,展开显示 10 条) + toggleFeaturedExpanded() { trackClick('home', 'tab_click', this.data.featuredExpanded ? '精选收起' : '精选展开') + const full = this.data.featuredSectionsFull || [] if (this.data.featuredExpanded) { - const collapsed = this.data.featuredSectionsFull.length > 0 ? this.data.featuredSectionsFull.slice(0, 3) : this.data.featuredSections - this.setData({ featuredExpanded: false, featuredSections: collapsed }) - return - } - if (this.data.featuredSectionsFull.length > 0) { - this.setData({ featuredExpanded: true, featuredSections: this.data.featuredSectionsFull }) - return - } - this.setData({ featuredExpandedLoading: true }) - try { - const res = await app.request({ url: '/api/miniprogram/book/hot?limit=50', silent: true }) - const list = (res && res.data) ? res.data : [] - const tagMap = ['热门', '推荐', '精选'] - const full = list.map((s, i) => ({ - id: s.id || s.section_id, - mid: s.mid ?? s.MID ?? 0, - title: s.sectionTitle || s.section_title || s.title || s.chapterTitle || '', - part: (s.partTitle || s.part_title || '').replace(/[_||]/g, ' ').trim(), - tag: tagMap[i % 3] || '精选', - tagClass: ['tag-hot', 'tag-rec', 'tag-rec'][i % 3] || 'tag-rec' - })) - this.setData({ - featuredSectionsFull: full, - featuredSections: full, - featuredExpanded: true, - featuredExpandedLoading: false - }) - } catch (e) { - console.log('[Index] 加载精选更多失败:', e) - this.setData({ featuredExpandedLoading: false }) + this.setData({ featuredExpanded: false, featuredSections: full.slice(0, 5) }) + } else { + this.setData({ featuredExpanded: true, featuredSections: full }) } }, diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml index bf9fb1c4..ff27862d 100644 --- a/miniprogram/pages/index/index.wxml +++ b/miniprogram/pages/index/index.wxml @@ -96,8 +96,8 @@ 精选推荐 - - {{featuredExpandedLoading ? '加载中...' : (featuredExpanded ? '收起' : '展开更多')}} + + {{featuredExpanded ? '收起' : '展开更多'}} diff --git a/miniprogram/pages/match/match.js b/miniprogram/pages/match/match.js index 94976962..a4dc47d6 100644 --- a/miniprogram/pages/match/match.js +++ b/miniprogram/pages/match/match.js @@ -14,7 +14,7 @@ const { trackClick } = require('../../utils/trackClick') // 导师顾问:跳转到存客宝添加微信 // 团队招募:跳转到存客宝添加微信 let MATCH_TYPES = [ - { id: 'partner', label: '找伙伴', matchLabel: '找伙伴', icon: 'star', matchFromDB: true, showJoinAfterMatch: false }, + { id: 'partner', label: '找伙伴', matchLabel: '找伙伴', icon: 'handshake', matchFromDB: true, showJoinAfterMatch: false }, { id: 'investor', label: '资源对接', matchLabel: '资源对接', icon: 'users', matchFromDB: true, showJoinAfterMatch: true, requirePurchase: true }, { id: 'mentor', label: '导师顾问', matchLabel: '导师顾问', icon: 'heart', matchFromDB: true, showJoinAfterMatch: true }, { id: 'team', label: '团队招募', matchLabel: '团队招募', icon: 'gamepad', matchFromDB: true, showJoinAfterMatch: true } @@ -453,6 +453,13 @@ Page({ const newCount = this.data.todayMatchCount + 1 const matchesRemaining = this.data.hasFullBook ? 999999 : Math.max(0, this.data.totalMatchesAllowed - newCount) + // 规范化 commonInterests:emoji 或无效 icon 转为 SVG 图标名 + const normalized = matchedUser.commonInterests?.map(item => ({ + ...item, + icon: /^[a-z0-9-]+$/i.test(item.icon) ? item.icon : 'target' + })) || [] + if (normalized.length) matchedUser = { ...matchedUser, commonInterests: normalized } + this.setData({ isMatching: false, currentMatch: matchedUser, diff --git a/miniprogram/pages/mentor-detail/mentor-detail.js b/miniprogram/pages/mentor-detail/mentor-detail.js index 9cb992cf..b0857f44 100644 --- a/miniprogram/pages/mentor-detail/mentor-detail.js +++ b/miniprogram/pages/mentor-detail/mentor-detail.js @@ -53,6 +53,11 @@ Page({ } }, + onAvatarError() { + const mentor = { ...this.data.mentor, avatarError: true } + this.setData({ mentor }) + }, + onContactTap() { if (!this.data.mentor || this.data.consultOptions.length === 0) { wx.showToast({ title: '暂无咨询项目', icon: 'none' }) diff --git a/miniprogram/pages/mentor-detail/mentor-detail.wxml b/miniprogram/pages/mentor-detail/mentor-detail.wxml index eea50000..fc635184 100644 --- a/miniprogram/pages/mentor-detail/mentor-detail.wxml +++ b/miniprogram/pages/mentor-detail/mentor-detail.wxml @@ -11,7 +11,7 @@ - + {{mentor.name ? mentor.name[0] : '?'}} {{mentor.name}} diff --git a/miniprogram/pages/mentors/mentors.js b/miniprogram/pages/mentors/mentors.js index 317abdb2..84b3c8b0 100644 --- a/miniprogram/pages/mentors/mentors.js +++ b/miniprogram/pages/mentors/mentors.js @@ -54,6 +54,12 @@ Page({ this.loadMentors() }, + onAvatarError(e) { + const id = e.currentTarget.dataset.id + const mentors = this.data.mentors.map(m => (m.id === id ? { ...m, avatarError: true } : m)) + this.setData({ mentors }) + }, + goDetail(e) { const id = e.currentTarget.dataset.id wx.navigateTo({ url: `/pages/mentor-detail/mentor-detail?id=${id}` }) diff --git a/miniprogram/pages/mentors/mentors.wxml b/miniprogram/pages/mentors/mentors.wxml index cf895c99..c0c15964 100644 --- a/miniprogram/pages/mentors/mentors.wxml +++ b/miniprogram/pages/mentors/mentors.wxml @@ -48,7 +48,7 @@ - + {{item.name ? item.name[0] : '?'}} diff --git a/miniprogram/pages/my/my.wxml b/miniprogram/pages/my/my.wxml index 440771a7..a1ce2bb6 100644 --- a/miniprogram/pages/my/my.wxml +++ b/miniprogram/pages/my/my.wxml @@ -156,7 +156,7 @@ - + 我的代付 diff --git a/miniprogram/pages/read/read.js b/miniprogram/pages/read/read.js index c3590bfc..78b5e0c3 100644 --- a/miniprogram/pages/read/read.js +++ b/miniprogram/pages/read/read.js @@ -85,6 +85,9 @@ Page({ // 余额(用于余额支付) walletBalance: 0, + // 未解锁时显示的预览比例(来自文章详情,用于付费墙「已阅读X%」) + previewPercent: 20, + // 审核模式:隐藏购买按钮 auditMode: false, @@ -337,6 +340,9 @@ Page({ chapterTitle: res.chapterTitle || '' } if (res.mid) updates.sectionMid = res.mid + if (res.previewPercent != null && res.previewPercent >= 1 && res.previewPercent <= 100) { + updates.previewPercent = res.previewPercent + } this.setData(updates) // 写入本地缓存(存 displayContent,供离线/重试降级使用) try { wx.setStorageSync(cacheKey, { ...res, content: displayContent }) } catch (_) {} diff --git a/miniprogram/pages/read/read.wxml b/miniprogram/pages/read/read.wxml index 0afcd585..4f8c0eb3 100644 --- a/miniprogram/pages/read/read.wxml +++ b/miniprogram/pages/read/read.wxml @@ -94,17 +94,23 @@ - - - 分享到朋友圈 + + + + 分享到朋友圈 + - - - 生成海报 + + + + 生成海报 + - - - 代付分享 + + + + 代付分享 +