feat: 完整重构小程序匹配功能 + 修复UI对齐 + 文章数据API

主要更新:
1. 按H5网页端完全重构匹配功能(match页面)
   - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募
   - 资源对接等类型弹出手机号/微信号输入框
   - 去掉重新匹配按钮,改为返回按钮

2. 修复所有卡片对齐和宽度问题
   - 目录页附录卡片居中
   - 首页阅读进度卡片满宽度
   - 我的页面菜单卡片对齐
   - 推广中心分享卡片统一宽度

3. 修复目录页图标和文字对齐
   - section-icon固定40rpx宽高
   - section-title与图标垂直居中

4. 更新真实完整文章标题(62篇)
   - 从book目录读取真实markdown文件名
   - 替换之前的简化标题

5. 新增文章数据API
   - /api/db/chapters - 获取完整书籍结构
   - 支持按ID获取单篇文章内容
This commit is contained in:
卡若
2026-01-21 15:49:12 +08:00
parent 1ee25e3dab
commit b60edb3d47
197 changed files with 34430 additions and 7345 deletions

View File

@@ -2,13 +2,38 @@ import { type NextRequest, NextResponse } from "next/server"
import crypto from "crypto"
// 存客宝API配置
const CKB_API_KEY = "fyngh-ecy9h-qkdae-epwd5-rz6kd"
const CKB_API_KEY = process.env.CKB_API_KEY || "fyngh-ecy9h-qkdae-epwd5-rz6kd"
const CKB_API_URL = "https://ckbapi.quwanzhi.com/v1/api/scenarios"
// 生成签名
function generateSign(apiKey: string, timestamp: number): string {
const signStr = `${apiKey}${timestamp}`
return crypto.createHash("md5").update(signStr).digest("hex")
// 生成签名 - 根据文档实现
function generateSign(params: Record<string, any>, apiKey: string): string {
// 1. 移除 sign、apiKey、portrait 字段
const filteredParams = { ...params }
delete filteredParams.sign
delete filteredParams.apiKey
delete filteredParams.portrait
// 2. 移除空值字段
const nonEmptyParams: Record<string, any> = {}
for (const [key, value] of Object.entries(filteredParams)) {
if (value !== null && value !== "") {
nonEmptyParams[key] = value
}
}
// 3. 按参数名升序排序
const sortedKeys = Object.keys(nonEmptyParams).sort()
// 4. 拼接参数值
const stringToSign = sortedKeys.map(key => nonEmptyParams[key]).join("")
// 5. 第一次 MD5
const firstMd5 = crypto.createHash("md5").update(stringToSign).digest("hex")
// 6. 拼接 apiKey 再次 MD5
const sign = crypto.createHash("md5").update(firstMd5 + apiKey).digest("hex")
return sign
}
// 不同类型对应的source标签
@@ -16,44 +41,69 @@ const sourceMap: Record<string, string> = {
team: "团队招募",
investor: "资源对接",
mentor: "导师顾问",
partner: "创业合伙",
}
const tagsMap: Record<string, string> = {
team: "切片团队,团队招募",
investor: "资源对接,资源群",
mentor: "导师顾问,咨询服务",
partner: "创业合伙,创业伙伴",
}
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { type, phone, name, wechatId, remark } = body
const { type, phone, wechat, name, userId, remark } = body
// 验证必填参数
if (!type || !phone) {
return NextResponse.json({ success: false, message: "缺少必填参数" }, { status: 400 })
// 验证必填参数 - 手机号或微信号至少一个
if (!phone && !wechat) {
return NextResponse.json({ success: false, message: "请提供手机号或微信号" }, { status: 400 })
}
// 验证类型
if (!["team", "investor", "mentor"].includes(type)) {
if (!["team", "investor", "mentor", "partner"].includes(type)) {
return NextResponse.json({ success: false, message: "无效的加入类型" }, { status: 400 })
}
// 生成时间戳和签名
// 生成时间戳(秒级)
const timestamp = Math.floor(Date.now() / 1000)
const sign = generateSign(CKB_API_KEY, timestamp)
// 构建请求参数
// 构建请求参数不包含sign
const requestParams: Record<string, any> = {
timestamp,
source: `创业实验-${sourceMap[type]}`,
tags: tagsMap[type],
siteTags: "创业实验APP",
remark: remark || `用户通过创业实验APP申请${sourceMap[type]}`,
}
// 添加可选字段
if (phone) requestParams.phone = phone
if (wechat) requestParams.wechatId = wechat
if (name) requestParams.name = name
// 生成签名
const sign = generateSign(requestParams, CKB_API_KEY)
// 构建最终请求体
const requestBody = {
...requestParams,
apiKey: CKB_API_KEY,
sign,
timestamp,
phone,
name: name || "",
wechatId: wechatId || "",
source: sourceMap[type],
remark: remark || `来自创业实验APP-${sourceMap[type]}`,
tags: tagsMap[type],
portrait: {
type: 4, // 互动行为
source: 0, // 本站
sourceData: {
joinType: type,
joinLabel: sourceMap[type],
userId: userId || "",
device: "webapp",
timestamp: new Date().toISOString(),
},
remark: `${sourceMap[type]}申请`,
uniqueId: `soul_${phone || wechat}_${timestamp}`,
},
}
// 调用存客宝API
@@ -67,13 +117,14 @@ export async function POST(request: NextRequest) {
const result = await response.json()
if (response.ok && result.code === 0) {
if (result.code === 200) {
return NextResponse.json({
success: true,
message: `成功加入${sourceMap[type]}`,
message: result.message === "已存在" ? "您已加入,我们会尽快联系您" : `成功加入${sourceMap[type]}`,
data: result.data,
})
} else {
console.error("CKB API Error:", result)
return NextResponse.json({
success: false,
message: result.message || "加入失败,请稍后重试",