Files
yunhai-agent-front/src/types/agent.ts
T
lijing abd97adf9a
build / build (push) Successful in 1m52s
feat(leave): 裸意图直达表单 + 按身份分离请假表单 + 前端代取下拉
- 说「我要请假」这类只有意图的短句时,直接弹出表单不再过模型:
  后端 IntentShortcut 在编排器入口做「去空白标点 + 剥前后缀后正好等于标准说法
  且原句 ≤12 字」的窄匹配,命中即跳过 LLM 直接下发表单。
- 按身份分离:学生 → leave.submit(提交申请),教师/管理员 → leave.register
  (帮学生登记,必填 classId+stuId);RolePolicy 把两者分别归入 STUDENT_ONLY
  与 STAFF_ONLY,模型视野里天然只有一个,不可能选错。
- 表单字段由各自必填参数推导;下拉选项改为后端下发 optionCall(含 {{占位符}}),
  由前端带用户登录态代取后按 valueKey/labelKey 映射(模块 /api/* 服务端必然 302)。
  stuId 依赖 classId,选完班级才解锁学生名单。
- 抽出 utils/module-session.ts(会话预热 / 带登录态调模块 / 字典项解析),
  Chat.vue 与 FormCard.vue 复用。
- 例句与提示改为「我要请假」「帮学生登记请假」。
2026-10-12 17:49:34 +08:00

233 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 智能助手相关类型契约(与后端 com.yunhai.agent.model 对齐) */
/** 平台用户信息(BoaUser 的子集) */
export interface UserInfoVo {
id?: number;
name?: string;
account?: string;
profilePicture?: string;
deptName?: string;
/** 当前身份(平台下发,与 GetUserInfo 一致):roleName 即门户里当前激活的身份名 */
currentRole?: {
roleId?: number;
/** 平台当前身份名称,如「老师」「校领导」「学生」 */
roleName?: string;
schId?: number;
schName?: string;
[key: string]: any;
};
[key: string]: any;
}
/** 平台已授权模块节点 */
export interface ModuleNode {
id: number;
name: string;
modId: number;
page?: string;
children?: ModuleNode[];
[key: string]: any;
}
/** 补全表单里的一个字段(由后端工具定义推导) */
export interface FormField {
/** 提交时的参数名 */
name: string;
/** 中文标签,如「开始时间」 */
label: string;
/** 控件类型 */
widget: "text" | "textarea" | "number" | "date" | "datetime" | "select";
type?: string;
required: boolean;
/** 字段说明(含义与格式) */
description?: string;
/** 格式示例,用作 placeholder */
example?: string;
defaultValue?: string;
/** 下拉选项 */
options?: { value: string; label: string }[];
/**
* 下拉选项的动态来源(后端字典工具名,如 leave.types)。
* 有值但 options 为空 ⇒ 字典接口没取到,前端提示「可先手填编号」。
*/
optionsFrom?: string;
/**
* 当前 options 是否为内置兜底(而非学校实时字典)。
* 为 true 时说明「选项能用,但可能不含学校自定义的项」,前端给一句轻提示即可,不阻塞填写。
*/
optionsFallback?: boolean;
/**
* 「浏览器代取选项」的调用描述:业务模块的字典接口(班级、学生名单…)只认浏览器 CAS 会话,
* 服务端代取必然 302,所以由前端带**用户自己的登录态**去取原始字典,再渲染成下拉。
*
* <p>{@link pathAndQuery} 里可能含 {@code {{字段名}}} 占位符(见 {@link dependsOn}),
* 依赖字段有值后才能替换并发起请求。
*/
optionCall?: BrowserToolCall;
/** 本字段选项依赖的先序字段名(如「学生」依赖「班级」);依赖未填时清空并提示先选 */
dependsOn?: string[];
/** 从字典返回对象里取哪个字段作为选项「值」(如 classId / stuId) */
valueKey?: string;
/** 从字典返回对象里取哪个字段作为选项「显示名」(如 className / stuName) */
labelKey?: string;
}
/**
* 信息不全时后端下发的「补全表单」。
* 用户填完直接提交,服务端会直接执行对应工具(不再让模型二次猜测)。
*/
export interface FormRequest {
tool: string;
title: string;
description?: string;
module?: string;
write: boolean;
landingPath?: string;
fields: FormField[];
/** 已从对话中确定的参数(只读回显) */
preset?: Record<string, any>;
/** 已识别参数的可读回显(text 已按字典翻译成中文,如「病假」而非 1) */
recognized?: { name: string; label: string; text: string }[];
/** 缺失字段的中文名 */
missing?: string[];
hint?: string;
}
/** 表单提交体 */
export interface FormSubmit {
tool: string;
args: Record<string, any>;
}
/**
* 「浏览器代执行」挂起载荷(方案 A):模块接口只认浏览器 CAS 会话,
* 服务端把接口描述下发前端,由前端用用户自己的登录态调用后回传结果续跑。
*/
export interface BrowserToolRequest {
calls: BrowserToolCall[];
/** 给用户看的一句话说明 */
notice?: string;
}
/** 一次代执行调用描述(pathAndQuery 相对当前站点根,同站部署 ⇒ 同源) */
export interface BrowserToolCall {
name: string;
title: string;
arguments?: Record<string, any>;
write: boolean;
method: "GET" | "POST_JSON" | "POST_FORM";
pathAndQuery: string;
body?: string;
contentType?: string;
}
/** 代执行结果回传项(与 BrowserToolCall 按 name 对应) */
export interface ToolResultItem {
name: string;
arguments?: Record<string, any>;
/** HTTP 状态码;网络层失败时为空 */
status?: number;
/** 响应体原文 */
body?: string;
/** 网络层错误(失败/超时/跨域) */
error?: string;
}
/** 对话请求 */
export interface AgentChatRequest {
sessionId?: string;
message?: string;
enableTools?: boolean;
/** 非空时:直接执行指定工具(表单提交) */
formSubmit?: FormSubmit;
/** 非空时:浏览器代执行结果回传(续跑) */
toolResult?: ToolResultItem[];
}
/** 一次工具调用轨迹 */
export interface ToolCallTrace {
name: string;
title: string;
/** 业务模块标识(前端据此拼模块页面地址做「去系统里查看」跳转) */
module?: string;
arguments?: Record<string, any>;
success: boolean;
error?: string;
write?: boolean;
/**
* 模块内的落地路由(如 `/my`)。
* 写操作 = 执行成功后去确认;**查询失败**(下游 code=302 需要浏览器登录态)= 深链兜底入口。
*/
landingPath?: string;
costMs?: number;
}
/** 对话响应 */
export interface AgentChatResponse {
sessionId: string;
reply: string;
toolCalls: ToolCallTrace[];
wroteSomething: boolean;
landingPath?: string;
rounds?: number;
promptTokens?: number;
completionTokens?: number;
warning?: string;
/** 需要用户补全信息时返回的表单 */
form?: FormRequest;
/** 非空:本轮工具需要浏览器代执行,前端调完接口把 toolResult 回传续跑 */
browserTool?: BrowserToolRequest;
}
/** 能力目录里的单项能力 */
export interface ToolCatalogItem {
name: string;
title: string;
description: string;
write: boolean;
landingPath?: string;
/** 可执行该能力的身份(中文标签,如「学生、教师」);不限身份时为空 */
roles?: string;
}
/** 能力目录:后端已按「当前角色 + 已授权模块」过滤后返回 */
export interface AgentToolCatalog {
/** 模块标识 → 能力列表;不同身份拿到的模块集合与能力数不同 */
modules: Record<string, ToolCatalogItem[]>;
/** 当前身份可见的能力总数 */
total: number;
/** 当前登录身份的中文描述(由后端按 BoaUser 解析,如「学生」「教师」「访客」) */
roles?: string;
/** 当前身份明细:一个账号可能有多重身份,后端只按「当前身份」生效 */
identity?: {
userId?: string;
userName?: string;
schoolId?: string;
/** 当前身份的角色号(平台 currentRole.roleId) */
roleId?: string;
/** 当前身份名称(平台 currentRole.roleName) */
roleName?: string;
roles?: string;
};
}
/** 聊天界面里的一条消息 */
export interface ChatItem {
id: string;
role: "user" | "assistant";
/** 正文(assistant 回复可能先为空,由 toolCalls 展示过程) */
text: string;
/** 阶段提示("正在调用:提交请假申请") */
stage?: string;
traces?: ToolCallTrace[];
wroteSomething?: boolean;
landingPath?: string;
error?: string;
/** 需要用户补全信息时的表单 */
form?: FormRequest;
/** 表单是否已提交(提交后置为只读回显) */
formSubmitted?: boolean;
/** 消息创建时间(毫秒) */
at: number;
}