feat: 内容管理第5批优化 - Bug修复 + 分享功能 + 代付功能

1. Bug修复:
   - 修复Markdown星号/下划线在小程序端原样显示问题(markdownToHtml增加__和_支持,contentParser增加Markdown格式剥离)
   - 修复@提及无反应(MentionSuggestion使用ref保持persons最新值,解决闭包捕获空数组问题)
   - 修复#链接标签点击"未找到小程序配置"(增加appId直接跳转降级路径)

2. 分享功能优化:
   - "分享到朋友圈"改为"分享给好友"(open-type从shareTimeline改为share)
   - 90%收益提示移到分享按钮下方
   - 阅读20%后向上滑动弹出分享浮层提示(4秒自动消失)

3. 代付功能:
   - 后端:新增UserBalance/BalanceTransaction/GiftUnlock三个模型
   - 后端:新增8个余额相关API(查询/充值/充值确认/代付/领取/退款/交易记录/礼物信息)
   - 小程序:阅读页新增"代付分享"按钮,支持用余额为好友解锁章节
   - 分享链接携带gift参数,好友打开自动领取解锁

Made-with: Cursor
This commit is contained in:
卡若
2026-03-15 09:20:27 +08:00
parent 8778a42429
commit 991e17698c
260 changed files with 26780 additions and 1026 deletions

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""批量去掉重复标题并重新上传到小程序。content_upload 已内置 strip 首行 # 标题。"""
import subprocess
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
BASE_2026 = Path("/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/2026每日派对干货")
BASE_9 = Path("/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章我在Soul上亲访的赚钱案例")
# (id, title, md_file_path relative to BASE_2026 or "9" for BASE_9)
CHAPTERS_2026 = [
("10.01", "第102场今年第一个红包你发给谁", BASE_2026 / "第102场今年第一个红包你发给谁.md"),
("10.02", "第103场号商、某客与炸房", BASE_2026 / "第103场号商、某客与炸房.md"),
("10.03", "第105场创业社群、直播带货与程序员", BASE_2026 / "第105场创业社群、直播带货与程序员.md"),
("10.04", "第104场婚恋、AI客服与一个微信", BASE_2026 / "第104场婚恋、AI客服与一个微信.md"),
("10.05", "第107场性格、陪伴经济与本地AI", BASE_2026 / "第107场性格、陪伴经济与本地AI.md"),
("10.06", "第108场Soul场观400等于抖音1万", BASE_2026 / "第108场Soul场观400等于抖音1万.md"),
("10.07", "第111场平台规则变了怎么办", BASE_2026 / "第111场平台规则变了怎么办.md"),
("10.08", "第110场Soul变现逻辑全程公开", BASE_2026 / "第110场Soul变现逻辑全程公开.md"),
("10.09", "第112场一个人起头维权挣了大半套房", BASE_2026 / "第112场一个人起头维权挣了大半套房.md"),
("10.10", "第113场不会选择怎么办", BASE_2026 / "第113场不会选择怎么办.md"),
("10.11", "第114场人跟人差别以前没 AI 差 100 倍,有 AI 差 1 万倍。", BASE_2026 / "第114场-人跟人差别,以前没 AI 差 100 倍,有 AI 差 1 万倍。.md"),
("10.12", "第115场一天改变可控的事先做", BASE_2026 / "第115场一天改变可控的事先做.md"),
("10.13", "第116场钱是大风刮来的怎么抓住", BASE_2026 / "第116场钱是大风刮来的怎么抓住.md"),
("10.14", "第117场流水百万挣八千你还干不干", BASE_2026 / "第117场流水百万挣八千你还干不干.md"),
("10.15", "第118场运气是选出来的不是等出来的", BASE_2026 / "第118场运气是选出来的不是等出来的.md"),
("10.16", "第119场开派对的初心是早上不影响老婆睡觉", BASE_2026 / "第119场开派对的初心是早上不影响老婆睡觉.md"),
("10.17", "第120场发视频就有钱这才是最低门槛的AI副业", BASE_2026 / "第120场发视频就有钱这才是最低门槛的AI副业.md"),
]
CHAPTERS_9 = [
("9.15", "派对副业|做切片分发和副业分发的具体步骤与收益", BASE_9 / "9.15 派对副业.md"),
("9.16", "如何开Soul派对房主避坑、流量、变现与封号", BASE_9 / "9.16 如何开Soul派对房主避坑、流量、变现与封号.md"),
]
def run_upload(section_id: str, title: str, content_file: Path, part: str, chapter: str) -> bool:
if not content_file.exists():
print(f" 跳过 {section_id}: 文件不存在 {content_file}")
return False
cmd = [
sys.executable,
str(PROJECT_ROOT / "content_upload.py"),
"--id", section_id,
"--title", title,
"--content-file", str(content_file),
"--part", part,
"--chapter", chapter,
"--price", "1.0",
]
r = subprocess.run(cmd, cwd=str(PROJECT_ROOT))
return r.returncode == 0
def main():
ok, fail = 0, 0
for sid, title, fpath in CHAPTERS_2026:
print(f"上传 {sid} {title[:30]}...")
if run_upload(sid, title, fpath, "part-2026-daily", "chapter-2026-daily"):
ok += 1
else:
fail += 1
for sid, title, fpath in CHAPTERS_9:
print(f"上传 {sid} {title[:30]}...")
if run_upload(sid, title, fpath, "part-4", "chapter-9"):
ok += 1
else:
fail += 1
print(f"\n完成: 成功 {ok}, 失败 {fail}")
if __name__ == "__main__":
main()