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

@@ -7,8 +7,9 @@ import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { Switch } from "@/components/ui/switch"
import { Slider } from "@/components/ui/slider"
import { Textarea } from "@/components/ui/textarea"
import { useStore } from "@/lib/store"
import { Save, Settings, Users, DollarSign } from "lucide-react"
import { Save, Settings, Users, DollarSign, UserCircle, Calendar, MapPin, BookOpen } from "lucide-react"
export default function SettingsPage() {
const { settings, updateSettings } = useStore()
@@ -16,21 +17,46 @@ export default function SettingsPage() {
sectionPrice: settings.sectionPrice,
baseBookPrice: settings.baseBookPrice,
distributorShare: settings.distributorShare,
authorInfo: settings.authorInfo,
authorInfo: {
...settings.authorInfo,
startDate: settings.authorInfo?.startDate || "2025年10月15日",
bio: settings.authorInfo?.bio || "连续创业者,私域运营专家,每天早上6-9点在Soul派对房分享真实商业故事",
},
})
const [isSaving, setIsSaving] = useState(false)
useEffect(() => {
setLocalSettings({
sectionPrice: settings.sectionPrice,
baseBookPrice: settings.baseBookPrice,
distributorShare: settings.distributorShare,
authorInfo: settings.authorInfo,
authorInfo: {
...settings.authorInfo,
startDate: settings.authorInfo?.startDate || "2025年10月15日",
bio: settings.authorInfo?.bio || "连续创业者,私域运营专家,每天早上6-9点在Soul派对房分享真实商业故事",
},
})
}, [settings])
const handleSave = () => {
updateSettings(localSettings)
alert("设置已保存!")
const handleSave = async () => {
setIsSaving(true)
try {
updateSettings(localSettings)
// 同时保存到数据库
await fetch('/api/db/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(localSettings)
})
alert("设置已保存!")
} catch (error) {
console.error('Save settings error:', error)
alert("保存失败")
} finally {
setIsSaving(false)
}
}
return (
@@ -40,26 +66,31 @@ export default function SettingsPage() {
<h2 className="text-2xl font-bold text-white"></h2>
<p className="text-gray-400 mt-1"></p>
</div>
<Button onClick={handleSave} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
<Button
onClick={handleSave}
disabled={isSaving}
className="bg-[#38bdac] hover:bg-[#2da396] text-white"
>
<Save className="w-4 h-4 mr-2" />
{isSaving ? "保存中..." : "保存设置"}
</Button>
</div>
<div className="space-y-6">
{/* 基础信息 */}
{/* 作者信息 - 重点增强 */}
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Settings className="w-5 h-5 text-[#38bdac]" />
<UserCircle className="w-5 h-5 text-[#38bdac]" />
</CardTitle>
<CardDescription className="text-gray-400"></CardDescription>
<CardDescription className="text-gray-400">"关于作者"</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="author-name" className="text-gray-300">
<Label htmlFor="author-name" className="text-gray-300 flex items-center gap-1">
<UserCircle className="w-3 h-3" />
</Label>
<Input
@@ -75,12 +106,34 @@ export default function SettingsPage() {
/>
</div>
<div className="space-y-2">
<Label htmlFor="live-time" className="text-gray-300">
<Label htmlFor="start-date" className="text-gray-300 flex items-center gap-1">
<Calendar className="w-3 h-3" />
</Label>
<Input
id="start-date"
className="bg-[#0a1628] border-gray-700 text-white"
placeholder="例如: 2025年10月15日"
value={localSettings.authorInfo.startDate || ""}
onChange={(e) =>
setLocalSettings((prev) => ({
...prev,
authorInfo: { ...prev.authorInfo, startDate: e.target.value },
}))
}
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="live-time" className="text-gray-300 flex items-center gap-1">
<Calendar className="w-3 h-3" />
</Label>
<Input
id="live-time"
className="bg-[#0a1628] border-gray-700 text-white"
placeholder="例如: 06:00-09:00"
value={localSettings.authorInfo.liveTime}
onChange={(e) =>
setLocalSettings((prev) => ({
@@ -90,9 +143,28 @@ export default function SettingsPage() {
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="platform" className="text-gray-300 flex items-center gap-1">
<MapPin className="w-3 h-3" />
</Label>
<Input
id="platform"
className="bg-[#0a1628] border-gray-700 text-white"
placeholder="例如: Soul派对房"
value={localSettings.authorInfo.platform}
onChange={(e) =>
setLocalSettings((prev) => ({
...prev,
authorInfo: { ...prev.authorInfo, platform: e.target.value },
}))
}
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="description" className="text-gray-300">
<Label htmlFor="description" className="text-gray-300 flex items-center gap-1">
<BookOpen className="w-3 h-3" />
</Label>
<Input
@@ -107,6 +179,38 @@ export default function SettingsPage() {
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="bio" className="text-gray-300"></Label>
<Textarea
id="bio"
className="bg-[#0a1628] border-gray-700 text-white min-h-[100px]"
placeholder="输入作者详细介绍..."
value={localSettings.authorInfo.bio || ""}
onChange={(e) =>
setLocalSettings((prev) => ({
...prev,
authorInfo: { ...prev.authorInfo, bio: e.target.value },
}))
}
/>
</div>
{/* 预览卡片 */}
<div className="mt-4 p-4 rounded-xl bg-[#0a1628] border border-[#38bdac]/30">
<p className="text-xs text-gray-500 mb-2"></p>
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-full bg-gradient-to-br from-[#00CED1] to-[#20B2AA] flex items-center justify-center text-xl font-bold text-white">
{localSettings.authorInfo.name?.charAt(0) || "K"}
</div>
<div>
<p className="text-white font-semibold">{localSettings.authorInfo.name}</p>
<p className="text-gray-400 text-xs">{localSettings.authorInfo.description}</p>
<p className="text-[#38bdac] text-xs mt-1">
{localSettings.authorInfo.liveTime} · {localSettings.authorInfo.platform}
</p>
</div>
</div>
</div>
</CardContent>
</Card>
@@ -216,6 +320,13 @@ export default function SettingsPage() {
</Label>
<Switch id="referral-enabled" defaultChecked />
</div>
<div className="flex items-center justify-between">
<Label htmlFor="match-enabled" className="flex flex-col space-y-1">
<span className="text-white"></span>
<span className="font-normal text-xs text-gray-500"></span>
</Label>
<Switch id="match-enabled" defaultChecked />
</div>
</CardContent>
</Card>
</div>