fix: split workbench core mysql access
This commit is contained in:
+41
-3
@@ -198,6 +198,7 @@ func (s *Service) GenerateDocument(ctx context.Context, sourceText, titleHint, d
|
||||
if err != nil {
|
||||
return DocumentResult{}, err
|
||||
}
|
||||
usage := usageFromResponse(resp)
|
||||
var out struct {
|
||||
Title string `json:"title"`
|
||||
Summary string `json:"summary"`
|
||||
@@ -206,7 +207,7 @@ func (s *Service) GenerateDocument(ctx context.Context, sourceText, titleHint, d
|
||||
Sections []DocumentSection `json:"sections"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(ExtractJSONObject(resp.Content)), &out); err != nil {
|
||||
return DocumentResult{}, fmt.Errorf("%w: %v", ErrBadOutput, err)
|
||||
return fallbackDocument(sourceText, titleHint, documentType, usage, "AI 输出格式异常,已使用兜底文档。"), nil
|
||||
}
|
||||
out.Title = strings.TrimSpace(firstNonEmpty(out.Title, titleHint, "智能文档"))
|
||||
out.ContentMarkdown = strings.TrimSpace(out.ContentMarkdown)
|
||||
@@ -217,7 +218,7 @@ func (s *Service) GenerateDocument(ctx context.Context, sourceText, titleHint, d
|
||||
out.ContentPlain = plainFromSections(out.Sections)
|
||||
}
|
||||
if out.ContentMarkdown == "" {
|
||||
return DocumentResult{}, ErrBadOutput
|
||||
return fallbackDocument(sourceText, titleHint, documentType, usage, "AI 输出缺少文档正文,已使用兜底文档。"), nil
|
||||
}
|
||||
return DocumentResult{
|
||||
Title: out.Title,
|
||||
@@ -225,10 +226,47 @@ func (s *Service) GenerateDocument(ctx context.Context, sourceText, titleHint, d
|
||||
ContentPlain: strings.TrimSpace(out.ContentPlain),
|
||||
Sections: out.Sections,
|
||||
Summary: strings.TrimSpace(out.Summary),
|
||||
Usage: usageFromResponse(resp),
|
||||
Usage: usage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fallbackDocument(sourceText, titleHint, documentType string, usage Usage, reason string) DocumentResult {
|
||||
title := firstNonEmpty(titleHint, documentTypeTitle(documentType), excerptPlain(sourceText, 30), "智能文档")
|
||||
source := strings.TrimSpace(sourceText)
|
||||
if source == "" {
|
||||
source = "用户未提供有效原文。"
|
||||
}
|
||||
sections := []DocumentSection{
|
||||
{Heading: "处理说明", Content: reason},
|
||||
{Heading: "用户输入", Content: source},
|
||||
{Heading: "后续建议", Content: "建议检查原始输入是否完整,或重新发起生成以获取更完整的智能文档。"},
|
||||
}
|
||||
contentMarkdown := markdownFromSections(sections)
|
||||
return DocumentResult{
|
||||
Title: title,
|
||||
ContentMarkdown: contentMarkdown,
|
||||
ContentPlain: plainFromSections(sections),
|
||||
Sections: sections,
|
||||
Summary: excerptPlain(source, 120),
|
||||
Usage: usage,
|
||||
}
|
||||
}
|
||||
|
||||
func documentTypeTitle(documentType string) string {
|
||||
switch strings.TrimSpace(documentType) {
|
||||
case "meeting_minutes":
|
||||
return "会议纪要"
|
||||
case "speech":
|
||||
return "演讲稿"
|
||||
case "proposal":
|
||||
return "方案文档"
|
||||
case "summary":
|
||||
return "内容总结"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) AnalyzeTable(ctx context.Context, input TableAnalysisInput) (TableAnalysisResult, error) {
|
||||
if s == nil || s.client == nil {
|
||||
return TableAnalysisResult{}, ErrNotConfigured
|
||||
|
||||
@@ -27,3 +27,28 @@ func TestFallbackTableAnalysisUnparsedProfile(t *testing.T) {
|
||||
t.Fatalf("last metric value=%q, want 未解析", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFallbackDocumentBuildsDisplayableContent(t *testing.T) {
|
||||
result := fallbackDocument(
|
||||
"生成一个竞争销售部门副科长职位的演讲稿",
|
||||
"竞争销售部门副科长职位演讲稿",
|
||||
"meeting_minutes",
|
||||
Usage{Model: "deepseek-flash"},
|
||||
"AI 输出格式异常,已使用兜底文档。",
|
||||
)
|
||||
if result.Title != "竞争销售部门副科长职位演讲稿" {
|
||||
t.Fatalf("Title=%q, want title hint", result.Title)
|
||||
}
|
||||
if strings.TrimSpace(result.ContentMarkdown) == "" {
|
||||
t.Fatal("ContentMarkdown is empty")
|
||||
}
|
||||
if !strings.Contains(result.ContentMarkdown, "AI 输出格式异常") {
|
||||
t.Fatalf("ContentMarkdown=%q, want fallback reason", result.ContentMarkdown)
|
||||
}
|
||||
if !strings.Contains(result.ContentPlain, "生成一个竞争销售部门副科长职位的演讲稿") {
|
||||
t.Fatalf("ContentPlain=%q, want source text", result.ContentPlain)
|
||||
}
|
||||
if len(result.Sections) != 3 {
|
||||
t.Fatalf("Sections len=%d, want 3", len(result.Sections))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +157,8 @@ func applyEnv(cfg *Config) {
|
||||
setInt(&cfg.MySQL.MaxOpenConns, "IM_WORKBENCH_MYSQL_MAX_OPEN_CONNS")
|
||||
setInt(&cfg.MySQL.MaxIdleConns, "IM_WORKBENCH_MYSQL_MAX_IDLE_CONNS")
|
||||
setString(&cfg.CoreMySQL.DSN, "IM_WORKBENCH_CORE_MYSQL_DSN")
|
||||
setInt(&cfg.CoreMySQL.MaxOpenConns, "IM_WORKBENCH_CORE_MYSQL_MAX_OPEN_CONNS")
|
||||
setInt(&cfg.CoreMySQL.MaxIdleConns, "IM_WORKBENCH_CORE_MYSQL_MAX_IDLE_CONNS")
|
||||
if strings.TrimSpace(cfg.CoreMySQL.DSN) == "" {
|
||||
cfg.CoreMySQL.DSN = cfg.MySQL.DSN
|
||||
}
|
||||
|
||||
@@ -396,7 +396,11 @@ func (s *Store) SaveCompletedFileUpload(ctx context.Context, file CompletedFileU
|
||||
if now.IsZero() {
|
||||
now = time.Now().UTC().Round(time.Millisecond)
|
||||
}
|
||||
_, err := s.db.ExecContext(ctx, `INSERT INTO im_fileuploads
|
||||
db := s.db
|
||||
if s.core != nil && s.core.db != nil {
|
||||
db = s.core.db
|
||||
}
|
||||
_, err := db.ExecContext(ctx, `INSERT INTO im_fileuploads
|
||||
(tenant_id,id,createdat,updatedat,userid,status,mimetype,size,etag,location)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?)`,
|
||||
s.tenant(), file.ID, now, now, formatInt64(file.UserID), 1, file.MIMEType, file.Size, file.ETag, file.Location)
|
||||
|
||||
@@ -172,10 +172,13 @@ func (s *Store) WorkbenchModules(ctx context.Context, userID int64) ([]Workbench
|
||||
}
|
||||
|
||||
func (s *Store) MeetingUnreadCount(ctx context.Context, userID int64) (int, error) {
|
||||
if s.core == nil || s.core.db == nil {
|
||||
return 0, nil
|
||||
}
|
||||
var count int
|
||||
query := fmt.Sprintf(`SELECT COUNT(*) FROM %s
|
||||
WHERE tenant_id=? AND user_id=? AND read_at IS NULL AND event_type LIKE 'meeting.%%'`, tenantSystemNotificationsTable(s.tenant()))
|
||||
err := s.db.GetContext(ctx, &count, query, s.tenant(), userID)
|
||||
err := s.core.db.GetContext(ctx, &count, query, s.tenant(), userID)
|
||||
if isMissingTable(err) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user