Без опису

gongtianxiao a41eec8709 docs: README 补 CHANGELOG(按日期分节)与对话接口对接说明 4 днів тому
build 08524fb44a chore: 初始提交——项目基线 4 днів тому
public 08524fb44a chore: 初始提交——项目基线 4 днів тому
src 08524fb44a chore: 初始提交——项目基线 4 днів тому
.editorconfig 08524fb44a chore: 初始提交——项目基线 4 днів тому
.env.development 08524fb44a chore: 初始提交——项目基线 4 днів тому
.env.production 08524fb44a chore: 初始提交——项目基线 4 днів тому
.env.qingpu 08524fb44a chore: 初始提交——项目基线 4 днів тому
.env.test 08524fb44a chore: 初始提交——项目基线 4 днів тому
.eslintignore 08524fb44a chore: 初始提交——项目基线 4 днів тому
.eslintrc.js 08524fb44a chore: 初始提交——项目基线 4 днів тому
.gitignore d8178ca69a chore: CLAUDE.md 与 agents.md 不再入库 4 днів тому
.prettierrc.cjs 08524fb44a chore: 初始提交——项目基线 4 днів тому
README.md a41eec8709 docs: README 补 CHANGELOG(按日期分节)与对话接口对接说明 4 днів тому
index.html 08524fb44a chore: 初始提交——项目基线 4 днів тому
jest.config.js 08524fb44a chore: 初始提交——项目基线 4 днів тому
package-lock.json 08524fb44a chore: 初始提交——项目基线 4 днів тому
package.json 08524fb44a chore: 初始提交——项目基线 4 днів тому
redirect.html 08524fb44a chore: 初始提交——项目基线 4 днів тому
tsconfig.json 08524fb44a chore: 初始提交——项目基线 4 днів тому
tsconfig.node.json 08524fb44a chore: 初始提交——项目基线 4 днів тому
vite.config.ts 08524fb44a chore: 初始提交——项目基线 4 днів тому

README.md

青浦区营商智能助手(zhaoshang-llm)

面向青浦区企业的政策匹配与办事指引智能助手前端。用户用自然语言提问,助手检索政策知识库, 以「开场概述 + 政策卡片 + 综合说明 + 参考资料」的形式给出有原文依据的回答;涉及具体企业时, 会先让用户确认公司主体,再结合工商信息给出针对性判断。

项目概述

业务能力

能力 说明
AI 对话 自然语言问答,流式返回;支持普通咨询、政策匹配、办事指引
政策卡片 按匹配度列出政策/服务事项,含支持对象、支持方式与标准、申报条件、原文引用
政策详情 卡片可展开详情,含条件核验、匹配依据、原文引用
参考资料 回答附引用来源,可展开查看来源机构、更新时间与介绍
公司补问 需要企业事实时,引导用户补充/确认公司主体,支持候选选择
语音输入 语音识别转文字后发送(ASR)

技术栈

  • 框架:Vue 3(<script setup>)+ TypeScript + Vite 5
  • UI:Ant Design Vue 4(经 unplugin-vue-components 按需自动引入)
  • 状态无 Vuex / Pinia。对话状态在 useBusinessAssistantChat 组合式函数内, 会话与消息持久化到 localStorage
  • 流式@microsoft/fetch-event-source(旧协议,保留未用)与原生 fetch + ReadableStream(现行)
  • Markdownmarked3D/语音:Three.js、alloyfinger (Three.js 用于粒子背景与语音识别,项目内没有 3D 虚拟人渲染

对话接口的关键约束

当前使用接口 POST /api/chat(SSE)。三条最容易踩的规则:

  1. 请求体只接受 {thread_id, question} 两个字段,多一个返回 422。 旧协议的 transmission.files / file_pos 发不出去(这是"文件上传"功能待定的原因)。
  2. 前端不直接渲染接口协议。 src/components/api-chat-coordinator.ts协议适配层, 把 SSE 事件翻译成既有渲染组件能识别的内容标记: <scope> / <!-- POLICY_TABLE --> / <ref_links> / <question-cards>。 渲染层(BusinessRecord / PolicyMatch / QuestionCard / ScopeContent)不需要感知新协议。
  3. 不要用后端文案做判断。 例如补问的形态由 kind + status 字段决定, 而不是拿 input_help 的中文措辞做正则——后端改一个字判定就会失效。

开发与构建

npm install

npm run dev            # 开发服务器 → https://localhost:8083
npm run build          # 生产构建(提交前必过)
npm run build:test     # 测试环境构建
npm run build:qingpu   # 青浦环境构建 + 打包 zip
npm run test           # jest(可选)

开发环境注意:

  • dev server 为 HTTPS(自签证书),浏览器首次访问会有证书告警,属正常现象
  • 聊天接口走同源代理 /chat-apihttp://192.168.2.23:8000(见 vite.config.ts)。 代理由服务端发起,因此局域网同事访问也不会有混合内容或跨域问题
  • 生产环境 vite 代理不生效,需由 nginx 做等价转发,否则同样会被浏览器拦截

环境变量

变量 用途
VITE_API 主业务 API 网关
VITE_CHAT_API 对话接口。兼容两种写法:服务前缀(/chat-apihttp://host:8000)会自动追加 /api/chat;已是完整地址则原样使用
VITE_MODEL_SERVER 模型服务
VITE_ASR / VITE_STREAM_SERVER 语音识别 / 流媒体

目录结构

src/
├── components/
│   ├── Chat/                    消息渲染、政策卡片、补问问卷等
│   ├── Common/                  通用组件(MediaViewer、ScrollList、Toast…)
│   ├── business-assistant/      对话编排(useBusinessAssistantChat、上传、滚动等)
│   ├── api-chat-coordinator.ts  ★ 协议适配层(现行)
│   └── stream-message-coordinator.ts  旧协议实现(保留未用,勿改)
├── network/api/                 接口封装(chat-sessions、enterprise、assistant-statistics、card)
├── types/                       TypeScript 类型定义
├── utils/                       工具(runtime-config、stream-xml-filter、scope-record-rows…)
└── three-libs/asr/              语音识别

本机另有 docs/reference/(接口契约与参考资料)、harness/(开发工作流文件)、 CLAUDE.md / agents.md(agent 指令)。这些按 .gitignore 约定不入库, 缺失属正常。

后续新增改动的参考规范

后续新增改动,参考「华新镇产权单位和企业信息采集小程序」20260909 版本的工程实践。 该版本做了如下升级,可作为本仓库后续重构的对照基准:

构建工具与技术栈升级

  • 构建从 Vue CLI(vue-cli-service)+ Babel 迁移到 Vite
  • 源码从 JavaScript 全量改写为 TypeScript,接入 vue-tsc 类型检查
  • 移除 core-js / babel 相关依赖

目录结构分层重构

目录 说明
api 后端接口封装(auth、content)
composables 可复用逻辑(表单、草稿、提示、滚动定位)
constants 集中管理 API 基地址、栏目 id、模型 id 等常量
layouts 页面框架布局(TabBarLayout)
stores Pinia 状态管理
styles 抽离的全局样式(style.css、form.css)
types TypeScript 类型定义(property、enterprise 等)
utils 通用工具(request、crypto、format、validators)

状态管理改造

  • 引入 Pinia,新增 auth store 统一维护登录态(token / user)
  • 登录不再持久化明文密码,并清理历史遗留的 password

路由改造

  • 抽出 TabBarLayout 作为主框架,home / property / enterprise / myrecord 改为嵌套子路由
  • 页面组件改为按需懒加载
  • 新增全局前置守卫:受保护页面(requiresAuth)未登录时跳转登录页并携带 redirect

巨型页面拆分

视图只保留页面骨架,表单逻辑抽离为 composable + 子组件:

  • EnterprisePage2586 行精简至 333 行,逻辑抽离到 useEnterpriseForm, 拆出 LocationEditorYearlyMoneyList 组件
  • PropertyPage2144 行精简至 288 行,逻辑抽离到 usePropertyForm, 拆出 BuildingCardFloorCardOperatorList 组件

通用组件沉淀

新增 FormFieldRadioGroupCheckboxGroupSearchSelectPageHeaderSuccessToast 等通用组件。

通用逻辑沉淀(composables)

composable 作用
useDraft 进入「查看」前保存草稿快照、退出时还原
useSuccessToast 统一的成功提示
useScrollToError 校验失败时滚动定位到错误项

接口层统一封装

  • 新增 utils/request 统一 axios 实例(内容平台基地址、urlencoded、请求拦截自动携带 Token)
  • api/authapi/content 统一封装登录与内容平台的增删改查

对照本仓库时的注意:本项目是单模块 Vue 应用,且目前没有引入任何状态管理库 (对话状态在 useBusinessAssistantChat 里)。上文的分层与 Pinia 改造适用于多页面小程序形态, 本项目是否需要照搬,应按实际规模判断,不要为了对齐而引入用不上的依赖。

对话接口对接说明

接口:POST /api/chat

  • 接口说明:提交问题并流式返回回答;同一 thread_id 复用同一会话窗口
  • 请求头Content-Type: application/json
  • 请求参数
参数 类型 说明
thread_id string 会话窗口 ID,复用同一 ID 即接续上下文
question string 用户本轮输入。只能是这两个字段,多余字段返回 422
  • 返回text/event-stream,命名事件流 acceptedprogress… → answersource… → item… → summaryresultdone (补问流程为 … → interrupt → result → done(status=needs_input)
  • 每个事件的 data 统一封装{thread_id, request_id, data}
  • 注意answer.textresult.response 内容相同,只能展示一次(result 是快照)

补问(interrupt)的形态

补问用 kind + status 描述,四种情况

kind status 含义 前端形态
company_selection found 有候选待选择 候选列表 + 查看更多 / 取消公司查询
company_need not_found 未找到候选,需补充信息 上方常驻输入框 + 跳过公司查询
company_need failed 查询服务失败 上方常驻输入框 + 跳过公司查询(文案须说明是失败)
company_need status 初次询问是否需要公司信息 上方常驻输入框 + 不需要公司信息

空候选与查询失败必须分别展示,不能把失败说成"查无公司"。

环境变量:新增 VITE_CHAT_API

  • 说明:对话接口地址。服务前缀(/chat-apihttp://host:8000)会自动追加 /api/chat; 已是完整接口地址则原样使用
  • 开发环境默认:/chat-api(走 vite 同源代理,见 vite.config.ts

CHANGE LOG

20260916

  • 公司补问改为按 status 字段判定形态(found / not_found / failed / 无 status), 替掉原先靠"候选数是否为 0"和 input_help 文案正则的猜测式判断
    • failed(查询服务失败)此前会落进 not_found 分支,文案被填成"未查询到匹配的公司", 等于把失败说成查无公司,已改为独立分支并说明失败原因
    • status(初次询问是否需要公司信息)此前给"跳过公司查询",改为"不需要公司信息"
  • 补问卡片:输入框移到选项上方并常驻(原来在选项之后、需点击才展开)
  • 补问卡片:修复选项序号错乱——输入框在最上却拿 B、选项在下面却拿 A,现输入框取 A、选项顺延
  • 补问卡片:正文里已展示过的同一段文字不再在卡片内重复
  • 「跳过公司查询」由发送 /skip 改为发送选项文本「跳过公司查询」
  • 问卷提交:修复只取第一题(多题丢失)、多选只取第一项、以及数字开头选项被静默改写成纯数字
  • README 补充项目概述与对话接口对接说明;修正 CLAUDE.md 中与仓库实际不符的描述 (端口、状态管理、不存在的文件与目录等)

20260915

  • 修复回答内容顺序:正文 → 政策卡片 → 综合说明 → 参考资料(参考资料移到最下方)
  • 修复换行丢失:块级 markdown 下单个换行会被折叠,导致列表后紧跟的说明行被并进上一条列表项
  • 修复复制功能:复制结果剔除协议标记,不再把 <scope><!-- POLICY_TABLE --><ref_links> 等原始标记一起复制出来
  • 修复卡片顺序与「更多」列表不一致:卡片改为按接口 priority.rank 排序
  • 「更多」面板的列表改为复用卡片数据,不再拉取与卡片无关的公共政策库
  • 部门筛选还原为最初的 15 个固定部门与字面匹配(此前一度改为按接口数据动态生成)
  • 新增惠企政策库来源标识(来自惠企政策库的卡片在右上角打标)
  • 政策详情面板新增「条件核验 / 匹配依据 / 原文引用」三个区块
  • 建立 harness/ 开发工作流文件与 docs/reference/ 接口参考

20260914

  • AI 对话迁移到接口 POST /api/chat(SSE)
    • 新增协议适配层 src/components/api-chat-coordinator.ts,把 SSE 事件翻译成既有渲染组件 可识别的内容标记,渲染层无需感知新协议
    • 请求体严格只发 {thread_id, question}answerresult.response 只展示一次; 未收到 done/error 即断流时按连接中断处理,不自动重试
    • 旧协议实现 src/components/stream-message-coordinator.ts 保留未用
  • 新增环境变量 VITE_CHAT_API,新增 dev 代理 /chat-apihttp://192.168.2.23:8000
  • 政策卡片、政策详情、参考资料、公司补问与候选确认接入新协议
  • 错误码翻译:把 HTTP 与 SSE 错误码转成中文提示(如 thread_busy → 该问题还在处理中)

历史版本

变更记录见飞书文档:https://awbm.feishu.cn/docx/O2mVdW5q3oqhLGxzEdbcniIKnYb