Files
fanqie-go/internal/handlers/content.go
T
chenxin af9004adaf 🐛 fix(review): 弹窗内切换排序加载失败,评论页固定顶栏
- 评论页注入绝对 API_BASE:弹窗 WebView(loadDataWithBaseURL) 中相对路径
  fetch 解析不可靠,切换排序/懒加载/回复全部改走绝对地址
- externalBaseURL 识别 X-Forwarded-Proto:正文气泡 ident 与评论页地址
  不再硬编码 http://,避免反代 301
- 布局改造:顶栏固定(含拖拽把手视觉)+评论区独立滚动容器,滚动/回顶
  逻辑迁移至容器;switchSort 显式传参替代隐式 event
2026-10-10 12:49:00 +08:00

159 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"fanqie/internal/config"
"fanqie/internal/fqapi"
"fmt"
"net/http"
)
// HandleContent 内容处理
func HandleContent(w http.ResponseWriter, r *http.Request) {
incrementStat("total", "content")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
params, err := validateParams(r, "item_id")
if err != nil {
respondError(w, err.Error(), true)
return
}
itemID := params["item_id"]
// 获取URL参数(支持动态覆盖配置;image_mode/review 兼容 README 的 img_mode/review_mode 别名)
textMode := r.URL.Query().Get("text_mode") // plain/1=纯文本, html/0=HTML
imageMode := getQueryWithAlias(r, "image_mode", "img_mode")
reviewParam := getQueryWithAlias(r, "review", "review_mode") // keep/1=启用段评, remove/0=禁用段评
result, err := fqapi.HandleGetContent(itemID, textMode, imageMode)
if err != nil {
respondError(w, "获取内容失败: "+err.Error(), false)
return
}
// 判断是否启用段评功能
// 优先使用URL参数,如果没有则使用配置文件
var enableReview bool
if reviewParam == "" {
// 没有URL参数时,使用配置文件
cfg := config.GetConfig()
if cfg != nil {
enableReview = cfg.Fanqie.Content.EnableReview
}
} else {
enableReview = fqapi.ParseBoolParam(reviewParam)
}
// 如果启用了段评功能,处理正文内容添加段评标记
if enableReview {
result = addReviewToContent(result, itemID, r)
}
fmt.Fprint(w, result)
}
// HandleMultiContent 批量内容处理
func HandleMultiContent(w http.ResponseWriter, r *http.Request) {
incrementStat("total", "content")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
params, err := validateParams(r, "book_id", "item_ids")
if err != nil {
respondError(w, err.Error(), true)
return
}
textMode := r.URL.Query().Get("text_mode")
imageMode := getQueryWithAlias(r, "image_mode", "img_mode")
ignoreFailed := r.URL.Query().Get("ignore_failed")
result, err := fqapi.HandleMultiContent(params["item_ids"], params["book_id"], textMode, imageMode, ignoreFailed)
if err != nil {
respondError(w, "批量获取内容失败: "+err.Error(), false)
return
}
fmt.Fprint(w, result)
}
// HandleItemSummary 章节摘要处理
func HandleItemSummary(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
params, err := validateParams(r, "book_id", "item_ids")
if err != nil {
respondError(w, err.Error(), true)
return
}
result, err := fqapi.HandleItemSummary(params["item_ids"], params["book_id"])
if err != nil {
respondError(w, "获取章节摘要失败: "+err.Error(), false)
return
}
fmt.Fprint(w, result)
}
// addReviewToContent 为正文内容添加段评标记
func addReviewToContent(jsonResult, itemID string, r *http.Request) string {
// 解析 JSON 结果
var resultData map[string]interface{}
if err := fqapi.ParseJSON([]byte(jsonResult), &resultData); err != nil {
return jsonResult
}
// 获取 data 字段
data, ok := resultData["data"].(map[string]interface{})
if !ok {
return jsonResult
}
// 获取 content 字段
content, ok := data["content"].(string)
if !ok || content == "" {
return jsonResult
}
// 从响应数据中提取 book_id (data.novel_data.book_id)
bookID := ""
if novelData, ok := data["novel_data"].(map[string]interface{}); ok {
if bookIDVal, ok := novelData["book_id"].(string); ok {
bookID = bookIDVal
} else if bookIDVal, ok := novelData["book_id"].(float64); ok {
bookID = fmt.Sprintf("%.0f", bookIDVal)
}
}
// 获取基础 URL(反代场景识别 X-Forwarded-Proto,避免生成 http:// 被 301)
cfg := config.GetConfig()
baseURL := ""
if r.Host != "" {
baseURL = externalBaseURL(r)
} else if cfg != nil {
host := cfg.Server.Host
if host == "0.0.0.0" {
host = "localhost"
}
baseURL = "http://" + host + ":" + cfg.Server.Port
}
// 生成带段评标记的内容
newContent, err := fqapi.GenerateParagraphsWithComments(itemID, bookID, content, baseURL)
if err != nil {
// 如果失败,返回原始内容
return jsonResult
}
// 替换 content 字段
data["content"] = newContent
resultData["data"] = data
// 重新序列化为 JSON
newJSON, err := fqapi.ToJSON(resultData)
if err != nil {
return jsonResult
}
return newJSON
}