提问背景 Question:
大概明白你的意思了,我以为你要用<script src=/xxx></script>
来显示聊天内容呢
Go+前端历史对话渲染方案
是的,完全不需要额外的 <script src="/xxx"></script> 加载。我们是通过 Go 的模板引擎,把历史对话的结构体切片直接 Marshal 成 JSON 字符串,像写普通 JS 变量一样,直接印在 HTML 的 <script> 标签里。
这样,浏览器在解析 HTML 的时候,就已经把这段数据作为内存中的 JS 数组准备好了。接着我们只需要用一段极简的 JS 遍历它,调用你写好的 appendMessage 即可,所有的样式、Markdown 解析、代码块复制按钮都将 100% 完美复用!
第一步:修改你的 Go 渲染后端
为了避免 Go 的 html/template 模板安全机制把 JSON 中的引号转义成 " 或 ",你需要在 Go 代码里把序列化后的 JSON 字符串转换为 template.JS 类型:
import (
"encoding/json"
"html/template"
)
type ChatMessage struct {
Role string `json:"role"` // "user" 或 "ai"
Text string `json:"text"` // 消息内容
Provider string `json:"provider"` // AI 通道,可为空
}
func ChatHandler(w http.ResponseWriter, r *http.Request) {
// 1. 获取登录用户的历史聊天记录(从数据库读取)
var historyList []ChatMessage
// historyList = db.GetHistoryForUser(userID)
// 假设得到: [{Role: "user", Text: "你好"}, {Role: "ai", Text: "你好!我是AI。", Provider: "Gemini"}]
// 2. 序列化为 JSON 字节
jsonBytes, err := json.Marshal(historyList)
if err != nil {
jsonBytes = []byte("[]")
}
data := map[string]interface{}{
"CHAT_UNIT": "gemini",
// 🌟 重点:转换为 template.JS 防止模板引擎破坏 JSON 结构
"HistoryJSON": template.JS(jsonBytes),
}
tmpl.Execute(w, data)
}
第二步:完整的 HTML/JS 模板(直接替换原文件)
下面是为你改造好的完整代码。核心改动点在最下方的 DOMContentLoaded 初始化区域。如果 HistoryJSON 为空或没有数据,会自动降级显示你精美撰写的 【欢迎与使用帮助】 气泡:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<title>百问百答 - AI Chat</title>
<meta
name="description"
content="BBSGOOD 百问百答:您的全能智能助手。无论解答学习疑问、翻译全球语言,还是寻找日常美食菜谱,这里都能为您一站式搞定。融合 AI 与社区智慧,轻松服务您的品质生活。"
/>
<link rel=