"ServedModel NVARCHAR(128) NOT NULL DEFAULT '', "+
"Mode VARCHAR(16) NOT NULL DEFAULT '', "+
"AnswerKind NVARCHAR(32) NOT NULL DEFAULT '', "+
"Outcome VARCHAR(16) NOT NULL DEFAULT '', "+
"ErrorType VARCHAR(32) NOT NULL DEFAULT '', "+
"QuestionHash CHAR(12) NOT NULL DEFAULT '', "+
"QuestionChars INT NOT NULL DEFAULT 0, "+
"QuestionText NVARCHAR(MAX) NULL, "+
"AnswerChars INT NOT NULL DEFAULT 0, "+
"AnswerText NVARCHAR(MAX) NULL, "+
"ToolRounds INT NOT NULL DEFAULT 0, "+
"ToolCalls INT NOT NULL DEFAULT 0, "+
"LlmCalls INT NOT NULL DEFAULT 0, "+
"PromptTokens INT NOT NULL DEFAULT 0, "+
"CompletionTokens INT NOT NULL DEFAULT 0, "+
"Cost DECIMAL(18,4) NOT NULL DEFAULT 0, "+
"TtfbMs BIGINT NOT NULL DEFAULT 0, "+
"FailoverCount INT NOT NULL DEFAULT 0, "+
"ReportedAt DATETIME2(3) NOT NULL DEFAULT SYSDATETIME(), "+
"HostName NVARCHAR(64) NOT NULL DEFAULT '');",conn))
{
cmd.ExecuteNonQuery();
}
// 三个查询索引 + RunId 唯一(防重复上报);已存在则跳过
ExecOrNull(conn,"IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'UX_"+table+"_RunId' AND object_id = OBJECT_ID(N'dbo."+table+"')) CREATE UNIQUE INDEX UX_"+table+"_RunId ON dbo."+table+"(RunId)");
ExecOrNull(conn,"IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_"+table+"_StartedAt' AND object_id = OBJECT_ID(N'dbo."+table+"')) CREATE NONCLUSTERED INDEX IX_"+table+"_StartedAt ON dbo."+table+"(StartedAt)");
ExecOrNull(conn,"IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_"+table+"_QuestionHash' AND object_id = OBJECT_ID(N'dbo."+table+"')) CREATE NONCLUSTERED INDEX IX_"+table+"_QuestionHash ON dbo."+table+"(QuestionHash)");
ExecOrNull(conn,"IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_"+table+"_UserName' AND object_id = OBJECT_ID(N'dbo."+table+"')) CREATE NONCLUSTERED INDEX IX_"+table+"_UserName ON dbo."+table+"(UserName)");
}
/// <summary>
/// 测试连接(设置页「对话上报 → 测试连接」用):对指定连接串执行 Open + SELECT 1 + 幂等建表预演。
/// <para>**返回错误消息,成功返回 null**(不抛异常 —— 遵守本类 public 不上抛红线;不写任何数据行)。</para>