feat: 补齐五块缺失功能(记录丢数据/文章正文/提醒管理/我的页入口/分享/关注)

P0 修数据问题
- 记录弹层有 5 个输入框从未绑定,用户填的便便备注、饮食内容、药品名称、
  剂量、消费备注全部丢弃;用药记录因此只存下「用药记录」四个字。已全部绑定并入库
- 异常观察保存时写死「风险中」,AI 实际判定的等级被丢掉。改为使用 riskData
  的真实 risk_level,并把成因与建议存进备注

文章正文
- 早期 seed 的 4 篇文章 Content 全空,点开只是打开关联记录弹层,内容运营等于白做
- 补写 4 篇真实正文(疫苗驱虫/软便判断/换粮方案/养宠花销),遵循不诊断、
  异常必提就医的护栏;对已存在的空正文做幂等回填
- 新增文章详情页,学习页与首页卡片改为打开正文

提醒管理
- 后端 CRUD 早已具备但小程序只读,用户改不了疫苗驱虫日期。提醒弹层支持增删改
- 修复后端 UpdateReminder 漏掉 type 字段导致改类型不生效

「我的」页 7 个死入口接活
- 提醒设置、健康记录、多宠物管理、会员权益分别落到对应功能
- 数据导出:汇总档案与记录为文本,可复制发给医生
- 意见反馈:新增 feedback 表与提交接口,后台加「意见反馈」管理页
- 关于我们:应用说明与免责声明

分享
- 各页面补 onShareAppMessage/onShareTimeline
- 帖子分享按钮改用微信原生 open-type="share",删除原来点了没反应的空壳弹层

社区关注
- 新增 follows 表与关注/取关接口,「关注」tab 此前等同「推荐」,
  现只显示已关注用户的帖子;帖子头部可直接关注,标记 followed / is_self

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-25 18:11:08 +08:00
parent 11c85da65d
commit 3fde90e97b
42 changed files with 1028 additions and 117 deletions
+69
View File
@@ -0,0 +1,69 @@
import { api } from '@/lib/api'
import { usePaged } from '@/lib/usePaged'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Card, CardContent } from '@/components/ui/card'
import { Pager } from '@/components/Pager'
export default function Feedback() {
const { page, setPage, data, totalPages, reload } = usePaged<any>(api.feedback)
async function toggle(f: any) {
await api.setFeedbackHandled(f.id, !f.handled)
reload()
}
return (
<div>
<div className="mb-6">
<h1 className="text-2xl font-bold"></h1>
<p className="text-sm text-muted-foreground mt-1"> </p>
</div>
<Card>
<CardContent className="pt-6">
<Table>
<TableHeader>
<TableRow>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead className="text-right"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data?.list?.map((f) => (
<TableRow key={f.id}>
<TableCell className="whitespace-nowrap text-muted-foreground">
{String(f.created_at).slice(0, 16).replace('T', ' ')}
</TableCell>
<TableCell>{f.nickname || '—'}</TableCell>
<TableCell className="max-w-md whitespace-pre-wrap">{f.content}</TableCell>
<TableCell>{f.contact || '—'}</TableCell>
<TableCell>
{f.handled ? <Badge variant="success"></Badge> : <Badge variant="muted"></Badge>}
</TableCell>
<TableCell className="text-right">
<Button variant="outline" size="sm" onClick={() => toggle(f)}>
{f.handled ? '标为待处理' : '标为已处理'}
</Button>
</TableCell>
</TableRow>
))}
{!data?.list?.length && (
<TableRow>
<TableCell colSpan={6} className="text-center text-muted-foreground py-8">
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<Pager page={page} totalPages={totalPages} total={data?.total ?? 0} onChange={setPage} />
</CardContent>
</Card>
</div>
)
}