```
feat(diary): 优化日记AI协助交互体验
- 添加promptBanner作为未开始协作时的醒目邀请横幅,包含圆形图标、标题和说明文字
- 重构assistSection使用switch语句处理careState不同状态,区分隐藏、prompt和其他状态
- 增加动画过渡效果消除聚焦/失焦切换时的布局跳动
- 优化thinking状态下的UI展示,添加AIFlowBar彩色呼吸条显示推理进度
- 修改requestSuggestions逻辑,进入推理时收起键盘以完整显示协作卡片
refactor(inference): 优化性能自检界面样式
- 将性能自检入口改为描边动作按钮(TjGhostButton),与引擎选择在视觉上区分开
- 调整未就绪状态下的禁用样式和提示文案
feat(localization): 添加新的本地化字符串
- 新增"追踪"和"记一笔"的多语言翻译,包括英语、日语和韩语
fix(diary): 增强AI问答解析稳定性
- 将最大token数从400提升至512,避免中文问题JSON被截断导致解析失败
- 实现salvageQuestionObjects方法作为终极兜底机制,逐个解析平衡的{...}对象
- 当外层wrapper解析失败时,仍可救回内部已闭合的问题对象,确保用户不被AI错误卡住
test(diary): 补充AI问答解析测试用例
- 添加截断对象恢复测试,验证maxTokens截断时前序完整问题的救回能力
- 添加wrapper key错误情况的恢复测试,确保模型输出格式异常时的容错性
```
This commit is contained in:
@@ -43,63 +43,44 @@ struct InferenceSettingsView: View {
|
||||
.onAppear { modelService.refreshStates() }
|
||||
}
|
||||
|
||||
/// 性能自检入口:用当前选中的引擎跑固定 prompt,实测并按后端归档对比。
|
||||
/// 模型未就绪时显示「前往下载」提示而非死链。
|
||||
/// 性能自检入口:它是「动作/工具」而非引擎选择,所以做成描边动作按钮(TjGhostButton),
|
||||
/// 从视觉类别上和上方引擎/状态卡区分开。模型未就绪时禁用并给出下载提示而非死链。
|
||||
@ViewBuilder
|
||||
private var selfTestSection: some View {
|
||||
if modelReady {
|
||||
NavigationLink {
|
||||
ModelSelfTestView()
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
ZStack {
|
||||
Circle().fill(Tj.Palette.sand2)
|
||||
Image(systemName: "gauge.with.needle")
|
||||
.font(.tjScaled(18))
|
||||
.foregroundStyle(Tj.Palette.ink)
|
||||
}
|
||||
.frame(width: 44, height: 44)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("性能自检")
|
||||
.font(.tjScaled(15, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
Text("用上方选中的引擎跑固定 prompt,实测 prefill / 生成 tok/s")
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.lineLimit(2)
|
||||
}
|
||||
Spacer()
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.tjScaled(13, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
.padding(14)
|
||||
.tjCard()
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
} else {
|
||||
HStack(spacing: 12) {
|
||||
ZStack {
|
||||
Circle().fill(Tj.Palette.sand2)
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "gauge.with.needle")
|
||||
.font(.tjScaled(18))
|
||||
.foregroundStyle(Tj.Palette.text2)
|
||||
}
|
||||
.frame(width: 44, height: 44)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("性能自检")
|
||||
.font(.tjScaled(15, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
Text("模型未就绪,前往「模型管理」下载后可用")
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.lineLimit(2)
|
||||
Text("性能自检")
|
||||
Image(systemName: "arrow.right")
|
||||
.font(.tjScaled(13, weight: .semibold))
|
||||
}
|
||||
Spacer()
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.padding(14)
|
||||
.tjCard()
|
||||
.opacity(0.55)
|
||||
.buttonStyle(TjGhostButton())
|
||||
.padding(.top, 4)
|
||||
} else {
|
||||
VStack(spacing: 8) {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "gauge.with.needle")
|
||||
.font(.tjScaled(15, weight: .semibold))
|
||||
Text("性能自检")
|
||||
}
|
||||
.font(.tjScaled(15, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 48)
|
||||
.background(Capsule().strokeBorder(Tj.Palette.line, lineWidth: 1))
|
||||
.opacity(0.6)
|
||||
|
||||
Text("模型未就绪,前往「模型管理」下载后可用")
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
.padding(.top, 4)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user