diff --git a/hy_qa_asset_backend/docs/README.md b/hy_qa_asset_backend/docs/README.md new file mode 100644 index 0000000..019be34 --- /dev/null +++ b/hy_qa_asset_backend/docs/README.md @@ -0,0 +1,13 @@ +# 项目文档索引 + +这个目录用于记录项目开发计划、产品决策、阶段范围和中间想法,方便后续开发、交接和复盘。 + +## 当前文档 + +- `h5-user-app-plan.md`:H5 用户端一期范围、已隐藏功能、后续智能体与登录规划。 + +## 记录原则 + +- 先记录“为什么这样做”,再记录“做了什么”。 +- 产品范围、技术边界、风险取舍要写清楚,避免后续只看代码猜意图。 +- 已暂缓的功能不要删除背景,标明暂缓原因和恢复条件。 diff --git a/hy_qa_asset_backend/docs/h5-user-app-plan.md b/hy_qa_asset_backend/docs/h5-user-app-plan.md new file mode 100644 index 0000000..85b01c7 --- /dev/null +++ b/hy_qa_asset_backend/docs/h5-user-app-plan.md @@ -0,0 +1,110 @@ +# H5 用户端开发计划与决策记录 + +更新时间:2026-07-05 + +## 当前目标 + +H5 用户端先作为“千问千答”用户入口,优先验证用户提问和系统回答这条主链路。第一期降低使用门槛,用户不登录也能进入页面并发起提问。 + +当前 H5 不是后台管理页,也不是知识库生产工具;它是未来小程序/用户端的交互雏形。 + +## 一期范围 + +一期只保留: + +- 免登录进入 H5。 +- 展示问答聊天界面。 +- 用户输入问题。 +- 前端调用后端已审核可调用库。 +- 展示答案、来源和边界提示。 +- 保留“新问答”按钮,方便用户重新开始。 +- 保留复制和答案反馈的前端交互骨架。 + +一期明确不展示: + +- 登录入口。 +- 微信授权入口。 +- 会话记录页。 +- “我的”个人中心。 +- 用户资料、手机号、微信昵称等身份信息。 + +## 当前隐藏决策 + +登录功能、微信授权、会话记录和个人中心此前已经做了部分前端预留,但一期先隐藏。 + +原因: + +- 一期先验证问答能力,不让登录流程阻断用户体验。 +- 后端还没有正式用户体系、会话历史接口和微信 code 换登录态接口。 +- 如果展示半成品登录/记录/我的,会让测试用户误以为这些能力已经可用。 +- 用户端要先把“能问、能答、答案可靠”打磨清楚。 + +恢复条件: + +- 后端有正式用户登录接口。 +- 后端支持微信授权登录或小程序登录。 +- 后端支持用户会话保存和历史查询。 +- 后端支持反馈入库。 + +## 当前接口绑定 + +H5 当前只适合直接绑定: + +```http +GET /api/standard-qa/callable +``` + +这个接口只返回: + +- 已审核标准问答。 +- 已标记可调用。 +- 低/中风险。 +- 已脱敏或无需脱敏。 + +H5 不应该直接使用后台审核、编辑、任务、飞书、日志类接口。 + +## 后续后端方向 + +中长期不建议 H5 直接拉取全部可调用库并在前端匹配。更合理的结构是后端新增智能体接口: + +```http +POST /api/h5/chat +``` + +后端智能体负责: + +- 接收用户问题。 +- 做风险初筛。 +- 从标准问答可调用库中检索相关知识。 +- 组装提示词。 +- 调用大模型 API。 +- 返回自然语言答案、来源、边界和命中状态。 +- 保存会话和反馈。 + +H5 只负责: + +- 输入问题。 +- 展示答案。 +- 展示来源和风险边界。 +- 收集反馈。 +- 管理用户交互状态。 + +## 后续建议开发顺序 + +1. 后端新增 `POST /api/h5/chat`。 +2. 后端新增智能体 prompt 和知识库检索模块。 +3. H5 从直接调用 `/standard-qa/callable` 改成调用 `/h5/chat`。 +4. 后端新增用户会话和消息表。 +5. H5 恢复会话历史页。 +6. 后端新增反馈入库接口。 +7. H5 恢复点赞、点踩、没解决等反馈入库。 +8. 后端新增微信登录或小程序登录。 +9. H5 恢复登录入口和“我的”页。 + +## 风险提醒 + +- 不要让 H5 使用未审核、不可调用、高风险或未脱敏内容。 +- 不要让前端长期承担检索和风控职责。 +- 大模型回答必须有明确边界,不能伪装成院长或老师原话。 +- 医疗、法律、心理诊断、极端风险问题必须有兜底策略。 +- 登录和历史记录上线前,要先确认隐私说明和数据保存规则。 diff --git a/hy_qa_asset_backend/frontend/components/h5/H5QAExperience.tsx b/hy_qa_asset_backend/frontend/components/h5/H5QAExperience.tsx index 37302d6..d9074bf 100644 --- a/hy_qa_asset_backend/frontend/components/h5/H5QAExperience.tsx +++ b/hy_qa_asset_backend/frontend/components/h5/H5QAExperience.tsx @@ -1,18 +1,12 @@ "use client"; -import { FormEvent, useEffect, useMemo, useRef, useState } from "react"; +import { FormEvent, useEffect, useRef, useState } from "react"; import { BookOpenCheck, - Clock3, - Home, MessageCircle, Plus, - RotateCcw, SendHorizonal, - Settings, ShieldCheck, - Trash2, - UserRound } from "lucide-react"; import { api } from "@/lib/api"; import type { CallableQAItem } from "@/lib/types"; @@ -26,10 +20,10 @@ import { type ChatMessage } from "@/lib/h5MockQa"; import ChatBubble from "./ChatBubble"; -import MockAuthPanel, { type MockUser } from "./MockAuthPanel"; -type MobileTab = "qa" | "history" | "me"; const STORAGE_KEY = "hy-qa-h5-sessions"; +const SHOW_AUTH_ENTRY = false; +const SHOW_HISTORY_AND_PROFILE = false; function nowText() { return new Intl.DateTimeFormat("zh-CN", { @@ -66,19 +60,7 @@ function buildUnavailableMessage(reason: "loading" | "empty" | "error"): ChatMes }; } -function formatSessionTime(value: string) { - return new Intl.DateTimeFormat("zh-CN", { - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - hour12: false - }).format(new Date(value)); -} - export default function H5QAExperience() { - const [activeTab, setActiveTab] = useState("qa"); - const [authOpen, setAuthOpen] = useState(false); const [input, setInput] = useState(""); const [messages, setMessages] = useState(initialMessages); const [sessions, setSessions] = useState([]); @@ -86,7 +68,6 @@ export default function H5QAExperience() { const [callableQa, setCallableQa] = useState([]); const [loadingQa, setLoadingQa] = useState(true); const [qaLoadError, setQaLoadError] = useState(null); - const [user, setUser] = useState(null); const [copiedMessageId, setCopiedMessageId] = useState(null); const bottomRef = useRef(null); @@ -128,41 +109,9 @@ export default function H5QAExperience() { .finally(() => setLoadingQa(false)); }, []); - useEffect(() => { - const params = new URLSearchParams(window.location.search); - const code = params.get("code"); - const state = params.get("state"); - if (code && state === "hyqa_h5") { - setUser({ - mode: "wechat", - name: "微信已授权", - phone: "等待后端换取登录态" - }); - window.history.replaceState(null, "", window.location.pathname); - } - }, []); - useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: "smooth", block: "end" }); - }, [messages, activeTab]); - - function mockLogin(mode: MockUser["mode"]) { - setUser({ - mode, - name: mode === "login" ? "大本营学员" : "新学员", - phone: "138****2026" - }); - setAuthOpen(false); - } - - function mockWechatLogin() { - setUser({ - mode: "wechat", - name: "微信用户", - phone: "微信授权演示" - }); - setAuthOpen(false); - } + }, [messages]); function persistMessages(nextMessages: ChatMessage[]) { setMessages(nextMessages); @@ -179,21 +128,6 @@ export default function H5QAExperience() { setCurrentSessionId(nextSession.id); setMessages(nextSession.messages); setSessions((current) => [nextSession, ...current].slice(0, 20)); - setActiveTab("qa"); - } - - function openSession(session: ChatSession) { - setCurrentSessionId(session.id); - setMessages(session.messages); - setActiveTab("qa"); - } - - function clearHistory() { - const nextSession = createEmptySession(); - setCurrentSessionId(nextSession.id); - setMessages(nextSession.messages); - setSessions([nextSession]); - setActiveTab("qa"); } async function copyMessage(message: ChatMessage) { @@ -239,7 +173,6 @@ export default function H5QAExperience() { ]; persistMessages(nextMessages); setInput(""); - setActiveTab("qa"); } function submit(event: FormEvent) { @@ -259,8 +192,8 @@ export default function H5QAExperience() {
-

当前页面只做前端加法:登录注册为 mock 状态,问答只读取后端已审核可调用库。

-

后续封装微信小程序时,主交互可以保留:顶部身份区、聊天流、快捷问题、底部导航和账号面板。

+

一期用户端先免登录使用,H5 只保留问答主链路,降低首次体验门槛。

+

登录、历史记录和个人中心已预留实现,等后端用户体系和会话接口确定后再打开。

@@ -280,12 +213,7 @@ export default function H5QAExperience() { - + {SHOW_AUTH_ENTRY ? null : null}
- ))} -
-
-