sync: Gitea 同步配置、miniprogram 页面逻辑、miniprogram 页面样式、脚本与配置、soul-admin 前端、soul-admin 页面、soul-api 接口逻辑、soul-api 路由等 | 原因: 多模块开发更新
This commit is contained in:
@@ -18,178 +18,9 @@ Page({
|
||||
hasFullBook: false,
|
||||
purchasedSections: [],
|
||||
|
||||
// 书籍数据 - 完整真实标题
|
||||
totalSections: 62,
|
||||
bookData: [
|
||||
{
|
||||
id: 'part-1',
|
||||
number: '一',
|
||||
title: '真实的人',
|
||||
subtitle: '人与人之间的底层逻辑',
|
||||
chapters: [
|
||||
{
|
||||
id: 'chapter-1',
|
||||
title: '第1章|人与人之间的底层逻辑',
|
||||
sections: [
|
||||
{ id: '1.1', title: '荷包:电动车出租的被动收入模式', isFree: true, price: 1 },
|
||||
{ id: '1.2', title: '老墨:资源整合高手的社交方法', isFree: false, price: 1 },
|
||||
{ id: '1.3', title: '笑声背后的MBTI:为什么ENTJ适合做资源,INTP适合做系统', isFree: false, price: 1 },
|
||||
{ id: '1.4', title: '人性的三角结构:利益、情感、价值观', isFree: false, price: 1 },
|
||||
{ id: '1.5', title: '沟通差的问题:为什么你说的别人听不懂', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-2',
|
||||
title: '第2章|人性困境案例',
|
||||
sections: [
|
||||
{ id: '2.1', title: '相亲故事:你以为找的是人,实际是在找模式', isFree: false, price: 1 },
|
||||
{ id: '2.2', title: '找工作迷茫者:为什么简历解决不了人生', isFree: false, price: 1 },
|
||||
{ id: '2.3', title: '撸运费险:小钱困住大脑的真实心理', isFree: false, price: 1 },
|
||||
{ id: '2.4', title: '游戏上瘾的年轻人:不是游戏吸引他,是生活没吸引力', isFree: false, price: 1 },
|
||||
{ id: '2.5', title: '健康焦虑(我的糖尿病经历):疾病是人生的第一次清醒', isFree: false, price: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'part-2',
|
||||
number: '二',
|
||||
title: '真实的行业',
|
||||
subtitle: '电商、内容、传统行业解析',
|
||||
chapters: [
|
||||
{
|
||||
id: 'chapter-3',
|
||||
title: '第3章|电商篇',
|
||||
sections: [
|
||||
{ id: '3.1', title: '3000万流水如何跑出来(退税模式解析)', isFree: false, price: 1 },
|
||||
{ id: '3.2', title: '供应链之王 vs 打工人:利润不在前端', isFree: false, price: 1 },
|
||||
{ id: '3.3', title: '社区团购的底层逻辑', isFree: false, price: 1 },
|
||||
{ id: '3.4', title: '跨境电商与退税套利', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-4',
|
||||
title: '第4章|内容商业篇',
|
||||
sections: [
|
||||
{ id: '4.1', title: '旅游号:30天10万粉的真实逻辑', isFree: false, price: 1 },
|
||||
{ id: '4.2', title: '做号工厂:如何让一个号变成一个机器', isFree: false, price: 1 },
|
||||
{ id: '4.3', title: '情绪内容为什么比专业内容更赚钱', isFree: false, price: 1 },
|
||||
{ id: '4.4', title: '猫与宠物号:为什么宠物赛道永不过时', isFree: false, price: 1 },
|
||||
{ id: '4.5', title: '直播间里的三种人:演员、技术工、系统流', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-5',
|
||||
title: '第5章|传统行业篇',
|
||||
sections: [
|
||||
{ id: '5.1', title: '拍卖行抱朴:一天240万的摇号生意', isFree: false, price: 1 },
|
||||
{ id: '5.2', title: '土地拍卖:招拍挂背后的游戏规则', isFree: false, price: 1 },
|
||||
{ id: '5.3', title: '地摊经济数字化:一个月900块的餐车生意', isFree: false, price: 1 },
|
||||
{ id: '5.4', title: '不良资产拍卖:我错过的一个亿佣金', isFree: false, price: 1 },
|
||||
{ id: '5.5', title: '桶装水李总:跟物业合作的轻资产模式', isFree: false, price: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'part-3',
|
||||
number: '三',
|
||||
title: '真实的错误',
|
||||
subtitle: '我和别人犯过的错',
|
||||
chapters: [
|
||||
{
|
||||
id: 'chapter-6',
|
||||
title: '第6章|我人生错过的4件大钱',
|
||||
sections: [
|
||||
{ id: '6.1', title: '电商财税窗口:2016年的千万级机会', isFree: false, price: 1 },
|
||||
{ id: '6.2', title: '供应链金融:我不懂的杠杆游戏', isFree: false, price: 1 },
|
||||
{ id: '6.3', title: '内容红利:2019年我为什么没做抖音', isFree: false, price: 1 },
|
||||
{ id: '6.4', title: '数据资产化:我还在观望的未来机会', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-7',
|
||||
title: '第7章|别人犯的错误',
|
||||
sections: [
|
||||
{ id: '7.1', title: '投资房年轻人的迷茫:资金 vs 能力', isFree: false, price: 1 },
|
||||
{ id: '7.2', title: '信息差骗局:永远有人靠卖学习赚钱', isFree: false, price: 1 },
|
||||
{ id: '7.3', title: '在Soul找恋爱但想赚钱的人', isFree: false, price: 1 },
|
||||
{ id: '7.4', title: '创业者的三种死法:冲动、轻信、没结构', isFree: false, price: 1 },
|
||||
{ id: '7.5', title: '人情生意的终点:关系越多亏得越多', isFree: false, price: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'part-4',
|
||||
number: '四',
|
||||
title: '真实的赚钱',
|
||||
subtitle: '底层结构与真实案例',
|
||||
chapters: [
|
||||
{
|
||||
id: 'chapter-8',
|
||||
title: '第8章|底层结构',
|
||||
sections: [
|
||||
{ id: '8.1', title: '流量杠杆:抖音、Soul、飞书', isFree: false, price: 1 },
|
||||
{ id: '8.2', title: '价格杠杆:供应链与信息差', isFree: false, price: 1 },
|
||||
{ id: '8.3', title: '时间杠杆:自动化 + AI', isFree: false, price: 1 },
|
||||
{ id: '8.4', title: '情绪杠杆:咨询、婚恋、生意场', isFree: false, price: 1 },
|
||||
{ id: '8.5', title: '社交杠杆:认识谁比你会什么更重要', isFree: false, price: 1 },
|
||||
{ id: '8.6', title: '云阿米巴:分不属于自己的钱', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-9',
|
||||
title: '第9章|我在Soul上亲访的赚钱案例',
|
||||
sections: [
|
||||
{ id: '9.1', title: '游戏账号私域:账号即资产', isFree: false, price: 1 },
|
||||
{ id: '9.2', title: '健康包模式:高复购、高毛利', isFree: false, price: 1 },
|
||||
{ id: '9.3', title: '药物私域:长期关系赛道', isFree: false, price: 1 },
|
||||
{ id: '9.4', title: '残疾机构合作:退税 × AI × 人力成本', isFree: false, price: 1 },
|
||||
{ id: '9.5', title: '私域银行:粉丝即小股东', isFree: false, price: 1 },
|
||||
{ id: '9.6', title: 'Soul派对房:陌生人成交的最快场景', isFree: false, price: 1 },
|
||||
{ id: '9.7', title: '飞书中台:从聊天到成交的流程化体系', isFree: false, price: 1 },
|
||||
{ id: '9.8', title: '餐饮女孩:6万营收、1万利润的死撑生意', isFree: false, price: 1 },
|
||||
{ id: '9.9', title: '电竞生态:从陪玩到签约到酒店的完整链条', isFree: false, price: 1 },
|
||||
{ id: '9.10', title: '淘客大佬:损耗30%的白色通道', isFree: false, price: 1 },
|
||||
{ id: '9.11', title: '蔬菜供应链:农户才是最赚钱的人', isFree: false, price: 1 },
|
||||
{ id: '9.12', title: '美业整合:一个人的公司如何月入十万', isFree: false, price: 1 },
|
||||
{ id: '9.13', title: 'AI工具推广:一个隐藏的高利润赛道', isFree: false, price: 1 },
|
||||
{ id: '9.14', title: '大健康私域:一个月150万的70后', isFree: false, price: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'part-5',
|
||||
number: '五',
|
||||
title: '真实的社会',
|
||||
subtitle: '未来职业与商业生态',
|
||||
chapters: [
|
||||
{
|
||||
id: 'chapter-10',
|
||||
title: '第10章|未来职业的变化趋势',
|
||||
sections: [
|
||||
{ id: '10.1', title: 'AI时代:哪些工作会消失,哪些会崛起', isFree: false, price: 1 },
|
||||
{ id: '10.2', title: '一人公司:为什么越来越多人选择单干', isFree: false, price: 1 },
|
||||
{ id: '10.3', title: '为什么链接能力会成为第一价值', isFree: false, price: 1 },
|
||||
{ id: '10.4', title: '新型公司:Soul-飞书-线下的三位一体', isFree: false, price: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chapter-11',
|
||||
title: '第11章|中国社会商业生态的未来',
|
||||
sections: [
|
||||
{ id: '11.1', title: '私域经济:为什么流量越来越贵', isFree: false, price: 1 },
|
||||
{ id: '11.2', title: '银发经济与孤独经济:两个被忽视的万亿市场', isFree: false, price: 1 },
|
||||
{ id: '11.3', title: '流量红利的终局', isFree: false, price: 1 },
|
||||
{ id: '11.4', title: '大模型 + 供应链的组合拳', isFree: false, price: 1 },
|
||||
{ id: '11.5', title: '社会分层的最终逻辑', isFree: false, price: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
// 书籍数据:以后台内容管理为准,仅用接口 /api/miniprogram/book/all-chapters 返回的数据
|
||||
totalSections: 0,
|
||||
bookData: [],
|
||||
|
||||
// 展开状态:默认不展开任何篇章,直接显示目录
|
||||
expandedPart: null,
|
||||
@@ -222,23 +53,37 @@ Page({
|
||||
return p.includes('序言') || p.includes('尾声') || p.includes('附录')
|
||||
},
|
||||
|
||||
// 一次请求拉取全量目录,同时更新 totalSections / bookData / dailyChapters
|
||||
// 一次请求拉取全量目录,以后台内容管理为准;同时更新 totalSections / bookData / dailyChapters
|
||||
async loadChaptersOnce() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
const rows = (res && res.data) || (res && res.chapters) || []
|
||||
if (rows.length === 0) return
|
||||
|
||||
// 1. totalSections
|
||||
// 无数据时清空目录,避免展示旧数据
|
||||
if (rows.length === 0) {
|
||||
app.globalData.bookData = []
|
||||
wx.setStorageSync('bookData', [])
|
||||
this.setData({
|
||||
bookData: [],
|
||||
totalSections: 0,
|
||||
dailyChapters: [],
|
||||
expandedPart: null
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const totalSections = res.total ?? rows.length
|
||||
app.globalData.bookData = rows
|
||||
wx.setStorageSync('bookData', rows)
|
||||
|
||||
// 2. bookData(过滤序言/尾声/附录,中间篇章按 part 聚合)
|
||||
// bookData:过滤序言/尾声/附录,按 part 聚合,篇章顺序按 sort_order 与后台一致(含「2026每日派对干货」等)
|
||||
const filtered = rows.filter(r => !this._isFixedPart(r.partTitle || r.part_title))
|
||||
const partMap = new Map()
|
||||
const numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']
|
||||
filtered.forEach((r) => {
|
||||
const pid = r.partId || r.part_id || 'part-1'
|
||||
const cid = r.chapterId || r.chapter_id || 'chapter-1'
|
||||
const sortOrder = r.sectionOrder ?? r.sort_order ?? 999999
|
||||
if (!partMap.has(pid)) {
|
||||
const partIdx = partMap.size
|
||||
partMap.set(pid, {
|
||||
@@ -246,10 +91,12 @@ Page({
|
||||
number: numbers[partIdx] || String(partIdx + 1),
|
||||
title: r.partTitle || r.part_title || '未分类',
|
||||
subtitle: r.chapterTitle || r.chapter_title || '',
|
||||
chapters: new Map()
|
||||
chapters: new Map(),
|
||||
minSortOrder: sortOrder
|
||||
})
|
||||
}
|
||||
const part = partMap.get(pid)
|
||||
if (sortOrder < part.minSortOrder) part.minSortOrder = sortOrder
|
||||
if (!part.chapters.has(cid)) {
|
||||
part.chapters.set(cid, {
|
||||
id: cid,
|
||||
@@ -267,13 +114,16 @@ Page({
|
||||
isNew: r.isNew === true || r.is_new === true
|
||||
})
|
||||
})
|
||||
const bookData = Array.from(partMap.values()).map(p => ({
|
||||
...p,
|
||||
const partList = Array.from(partMap.values())
|
||||
partList.sort((a, b) => (a.minSortOrder ?? 999999) - (b.minSortOrder ?? 999999))
|
||||
const bookData = partList.map((p, idx) => ({
|
||||
id: p.id,
|
||||
number: numbers[idx] || String(idx + 1),
|
||||
title: p.title,
|
||||
subtitle: p.subtitle,
|
||||
chapters: Array.from(p.chapters.values())
|
||||
}))
|
||||
const firstPart = bookData[0] && bookData[0].id
|
||||
|
||||
// 3. dailyChapters(sort_order > 62 的新增章节,按更新时间取前20)
|
||||
const baseSort = 62
|
||||
const daily = rows
|
||||
.filter(r => (r.sectionOrder ?? r.sort_order ?? 0) > baseSort)
|
||||
@@ -296,7 +146,14 @@ Page({
|
||||
dailyChapters: daily,
|
||||
expandedPart: this.data.expandedPart
|
||||
})
|
||||
} catch (e) { console.log('[Chapters] 加载目录失败:', e) }
|
||||
} catch (e) {
|
||||
console.log('[Chapters] 加载目录失败:', e)
|
||||
this.setData({ bookData: [], totalSections: 0 })
|
||||
}
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadChaptersOnce().then(() => wx.stopPullDownRefresh()).catch(() => wx.stopPullDownRefresh())
|
||||
},
|
||||
|
||||
onShow() {
|
||||
|
||||
Reference in New Issue
Block a user