2026-06-26 14:58:15 +08:00
package handlers
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"prompt-generator/internal/db"
"prompt-generator/internal/models"
)
func GetBuilderSessions ( w http . ResponseWriter , r * http . Request ) {
rows , err := db . DB . Query ( "SELECT id, title, project_name, final_prompt, claude_session_id, created_at, updated_at FROM builder_sessions ORDER BY updated_at DESC" )
if err != nil {
fail ( w , 500 , "查询会话列表失败" )
return
}
defer rows . Close ()
var sessions [] models . BuilderSession
for rows . Next () {
var s models . BuilderSession
if err := rows . Scan ( & s . ID , & s . Title , & s . ProjectName , & s . FinalPrompt , & s . ClaudeSessionID , & s . CreatedAt , & s . UpdatedAt ); err != nil {
continue
}
sessions = append ( sessions , s )
}
if sessions == nil {
sessions = [] models . BuilderSession {}
}
success ( w , sessions )
}
func CreateBuilderSession ( w http . ResponseWriter , r * http . Request ) {
var req struct {
Title string `json:"title"`
ProjectName string `json:"project_name"`
FinalPrompt string `json:"final_prompt"`
ClaudeSessionID string `json:"claude_session_id"`
TagOptionIDs [] struct {
TagID int64 `json:"tag_id"`
TagOptionID int64 `json:"tag_option_id"`
} `json:"tag_option_ids"`
SnippetIDs [] struct {
SnippetID int64 `json:"snippet_id"`
SortOrder int `json:"sort_order"`
} `json:"snippet_ids"`
}
if err := json . NewDecoder ( r . Body ). Decode ( & req ); err != nil {
fail ( w , 400 , "请求格式错误" )
return
}
var claudeID * string
if req . ClaudeSessionID != "" {
claudeID = & req . ClaudeSessionID
}
res , err := db . DB . Exec ( "INSERT INTO builder_sessions (title, project_name, final_prompt, claude_session_id) VALUES (?, ?, ?, ?)" ,
req . Title , req . ProjectName , req . FinalPrompt , claudeID )
if err != nil {
fail ( w , 500 , "创建会话失败" )
return
}
sessionID , _ := res . LastInsertId ()
// Insert tag associations
for _ , t := range req . TagOptionIDs {
db . DB . Exec ( "INSERT INTO builder_session_tags (builder_session_id, tag_id, tag_option_id) VALUES (?, ?, ?)" ,
sessionID , t . TagID , t . TagOptionID )
}
// Insert snippet associations
for _ , s := range req . SnippetIDs {
db . DB . Exec ( "INSERT INTO builder_session_snippets (builder_session_id, snippet_id, sort_order) VALUES (?, ?, ?)" ,
sessionID , s . SnippetID , s . SortOrder )
}
success ( w , map [ string ] int64 { "id" : sessionID })
}
func GetBuilderSession ( w http . ResponseWriter , r * http . Request ) {
id , err := strconv . ParseInt ( r . PathValue ( "id" ), 10 , 64 )
if err != nil {
fail ( w , 400 , "无效的 ID" )
return
}
var s models . BuilderSession
err = db . DB . QueryRow ( "SELECT id, title, project_name, final_prompt, claude_session_id, created_at, updated_at FROM builder_sessions WHERE id=?" , id ).
Scan ( & s . ID , & s . Title , & s . ProjectName , & s . FinalPrompt , & s . ClaudeSessionID , & s . CreatedAt , & s . UpdatedAt )
if err != nil {
fail ( w , 404 , "会话不存在" )
return
}
// Load tags
tagRows , err := db . DB . Query ( "SELECT id, builder_session_id, tag_id, tag_option_id FROM builder_session_tags WHERE builder_session_id=?" , id )
if err == nil {
for tagRows . Next () {
var t models . SessionTag
if err := tagRows . Scan ( & t . ID , & t . BuilderSessionID , & t . TagID , & t . TagOptionID ); err == nil {
s . Tags = append ( s . Tags , t )
}
}
tagRows . Close ()
}
// Load snippets
snippetRows , err := db . DB . Query ( "SELECT id, builder_session_id, snippet_id, sort_order FROM builder_session_snippets WHERE builder_session_id=? ORDER BY sort_order" , id )
if err == nil {
for snippetRows . Next () {
var sn models . SessionSnippet
if err := snippetRows . Scan ( & sn . ID , & sn . BuilderSessionID , & sn . SnippetID , & sn . SortOrder ); err == nil {
s . Snippets = append ( s . Snippets , sn )
}
}
snippetRows . Close ()
}
if s . Tags == nil {
s . Tags = [] models . SessionTag {}
}
if s . Snippets == nil {
s . Snippets = [] models . SessionSnippet {}
}
success ( w , s )
}
func UpdateBuilderSession ( w http . ResponseWriter , r * http . Request ) {
id , err := strconv . ParseInt ( r . PathValue ( "id" ), 10 , 64 )
if err != nil {
fail ( w , 400 , "无效的 ID" )
return
}
var req struct {
Title string `json:"title"`
ProjectName string `json:"project_name"`
FinalPrompt string `json:"final_prompt"`
ClaudeSessionID string `json:"claude_session_id"`
TagOptionIDs [] struct {
TagID int64 `json:"tag_id"`
TagOptionID int64 `json:"tag_option_id"`
} `json:"tag_option_ids"`
SnippetIDs [] struct {
SnippetID int64 `json:"snippet_id"`
SortOrder int `json:"sort_order"`
} `json:"snippet_ids"`
}
if err := json . NewDecoder ( r . Body ). Decode ( & req ); err != nil {
fail ( w , 400 , "请求格式错误" )
return
}
var claudeID * string
if req . ClaudeSessionID != "" {
claudeID = & req . ClaudeSessionID
}
_ , err = db . DB . Exec ( "UPDATE builder_sessions SET title=?, project_name=?, final_prompt=?, claude_session_id=? WHERE id=?" ,
req . Title , req . ProjectName , req . FinalPrompt , claudeID , id )
if err != nil {
fail ( w , 500 , "更新会话失败" )
return
}
// Replace tags
db . DB . Exec ( "DELETE FROM builder_session_tags WHERE builder_session_id=?" , id )
for _ , t := range req . TagOptionIDs {
db . DB . Exec ( "INSERT INTO builder_session_tags (builder_session_id, tag_id, tag_option_id) VALUES (?, ?, ?)" ,
id , t . TagID , t . TagOptionID )
}
// Replace snippets
db . DB . Exec ( "DELETE FROM builder_session_snippets WHERE builder_session_id=?" , id )
for _ , s := range req . SnippetIDs {
db . DB . Exec ( "INSERT INTO builder_session_snippets (builder_session_id, snippet_id, sort_order) VALUES (?, ?, ?)" ,
id , s . SnippetID , s . SortOrder )
}
success ( w , nil )
}
func DeleteBuilderSession ( w http . ResponseWriter , r * http . Request ) {
id , err := strconv . ParseInt ( r . PathValue ( "id" ), 10 , 64 )
if err != nil {
fail ( w , 400 , "无效的 ID" )
return
}
db . DB . Exec ( "DELETE FROM builder_session_tags WHERE builder_session_id=?" , id )
db . DB . Exec ( "DELETE FROM builder_session_snippets WHERE builder_session_id=?" , id )
db . DB . Exec ( "DELETE FROM builder_sessions WHERE id=?" , id )
success ( w , nil )
}
// AssemblePrompt 组装最终 Prompt
func AssemblePrompt ( projectName string , customContent string , tagOptions [] models . TagOption , snippets [] models . Snippet , suggestions [] string ) string {
var parts [] string
// Project context
if projectName != "" {
parts = append ( parts , fmt . Sprintf ( "## 项目上下文\n\n项目名称: %s" , projectName ))
}
// Custom content
if customContent != "" {
2026-06-26 16:05:59 +08:00
parts = append ( parts , fmt . Sprintf ( "## 自定义内容\n\n%s" , customContent ))
2026-06-26 14:58:15 +08:00
}
// Tag constraints
if len ( tagOptions ) > 0 {
var constraints [] string
for _ , opt := range tagOptions {
constraints = append ( constraints , fmt . Sprintf ( "- %s" , opt . ConstraintText ))
}
2026-06-26 16:05:59 +08:00
parts = append ( parts , fmt . Sprintf ( "## 约束\n\n%s" , strings . Join ( constraints , "\n" )))
2026-06-26 14:58:15 +08:00
}
// Snippets
if len ( snippets ) > 0 {
var snippetParts [] string
for _ , s := range snippets {
2026-06-26 16:05:59 +08:00
snippetParts = append ( snippetParts , fmt . Sprintf ( "--- %s ---\n%s" , s . Name , s . Content ))
2026-06-26 14:58:15 +08:00
}
2026-06-26 16:05:59 +08:00
parts = append ( parts , fmt . Sprintf ( "## 参考片段\n\n%s" , strings . Join ( snippetParts , "\n\n" )))
2026-06-26 14:58:15 +08:00
}
// Suggestions
if len ( suggestions ) > 0 {
2026-06-26 16:05:59 +08:00
parts = append ( parts , fmt . Sprintf ( "## 补充建议\n\n%s" , strings . Join ( suggestions , "\n" )))
2026-06-26 14:58:15 +08:00
}
return strings . Join ( parts , "\n\n" )
}