mirror of
https://github.com/2930134478/AI-CS.git
synced 2026-06-15 00:44:30 +08:00
新增IP地址显示
This commit is contained in:
+3
-3
@@ -69,11 +69,11 @@ REDIS_WS_CHANNEL=ai_cs:ws_events
|
||||
# =========================
|
||||
# 访客 IP 地理位置(ip2region 离线库,可选)
|
||||
# =========================
|
||||
# true 时关闭解析;Docker 镜像内已内置 data/ip2region_v4.xdb
|
||||
# true 时关闭解析;Docker 镜像内已内置 v4+v6 数据文件
|
||||
IP2REGION_DISABLED=false
|
||||
# 自定义 xdb 路径(本地开发可下载到 backend/data/,见 backend/data/README.md)
|
||||
# 自定义 xdb 路径(本地开发:sh scripts/download-ip2region-xdb.sh)
|
||||
# IP2REGION_V4_XDB=backend/data/ip2region_v4.xdb
|
||||
# IP2REGION_V6_XDB=
|
||||
# IP2REGION_V6_XDB=backend/data/ip2region_v6.xdb
|
||||
|
||||
# =========================
|
||||
# 端口映射(非必须)
|
||||
|
||||
+6
-2
@@ -18,8 +18,11 @@ RUN go mod download
|
||||
COPY . .
|
||||
|
||||
# 离线 IP 库(访客地理位置,见 backend/data/README.md)
|
||||
RUN mkdir -p data && curl -fsSL -o data/ip2region_v4.xdb \
|
||||
https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v4.xdb
|
||||
RUN mkdir -p data && \
|
||||
curl -fsSL -o data/ip2region_v4.xdb \
|
||||
https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v4.xdb && \
|
||||
curl -fsSL -o data/ip2region_v6.xdb \
|
||||
https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v6.xdb
|
||||
|
||||
# 构建应用
|
||||
# CGO_ENABLED=0: 禁用 CGO,生成纯 Go 二进制文件
|
||||
@@ -42,6 +45,7 @@ COPY --from=builder /app/backend .
|
||||
|
||||
# ip2region 数据文件
|
||||
COPY --from=builder /app/data/ip2region_v4.xdb /app/data/ip2region_v4.xdb
|
||||
COPY --from=builder /app/data/ip2region_v6.xdb /app/data/ip2region_v6.xdb
|
||||
|
||||
# 从构建阶段复制时区数据(可选)
|
||||
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
@@ -4,16 +4,14 @@
|
||||
|
||||
## 获取数据文件
|
||||
|
||||
将 **`ip2region_v4.xdb`** 放到本目录(与本文档同级):
|
||||
将 **`ip2region_v4.xdb`** 与 **`ip2region_v6.xdb`** 放到本目录(与本文档同级)。
|
||||
访客 IP 若为 **IPv6**(如 `2403:...`),必须提供 v6 库才能显示位置。
|
||||
|
||||
```bash
|
||||
# 在项目根目录执行(需 curl)
|
||||
curl -L -o backend/data/ip2region_v4.xdb \
|
||||
https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v4.xdb
|
||||
# 在项目根目录执行(推荐脚本,一次下齐 v4+v6)
|
||||
sh scripts/download-ip2region-xdb.sh
|
||||
```
|
||||
|
||||
可选 IPv6:下载 `ip2region_v6.xdb` 并设置环境变量 `IP2REGION_V6_XDB`。
|
||||
|
||||
## 环境变量
|
||||
|
||||
| 变量 | 说明 |
|
||||
|
||||
@@ -86,10 +86,13 @@ func InitFromEnv() {
|
||||
v4Path := strings.TrimSpace(os.Getenv("IP2REGION_V4_XDB"))
|
||||
v6Path := strings.TrimSpace(os.Getenv("IP2REGION_V6_XDB"))
|
||||
if v4Path == "" {
|
||||
v4Path = findDefaultV4XDB()
|
||||
v4Path = findDefaultXDB("ip2region_v4.xdb")
|
||||
}
|
||||
if v4Path == "" {
|
||||
log.Println("⚠️ 未找到 ip2region xdb 文件,访客「位置」将保持为空;可将 data/ip2region_v4.xdb 放到 backend/data/ 或设置 IP2REGION_V4_XDB")
|
||||
if v6Path == "" {
|
||||
v6Path = findDefaultXDB("ip2region_v6.xdb")
|
||||
}
|
||||
if v4Path == "" && v6Path == "" {
|
||||
log.Println("⚠️ 未找到 ip2region xdb,访客「位置」将保持为空;请放置 backend/data/ip2region_v4.xdb(及可选 v6)或设置 IP2REGION_V4_XDB / IP2REGION_V6_XDB")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -99,22 +102,34 @@ func InitFromEnv() {
|
||||
return
|
||||
}
|
||||
globalResolver = &ip2regionResolver{svc: svc}
|
||||
if v4Path != "" {
|
||||
log.Printf("✅ ip2region 已加载 (v4: %s)", v4Path)
|
||||
}
|
||||
if v6Path != "" {
|
||||
log.Printf(" IPv6 库: %s", v6Path)
|
||||
log.Printf("✅ ip2region 已加载 (v6: %s)", v6Path)
|
||||
} else {
|
||||
log.Println("ℹ️ 未加载 ip2region IPv6 库;访客若为 IPv6 地址将无法解析位置,可下载 ip2region_v6.xdb")
|
||||
}
|
||||
}
|
||||
|
||||
func findDefaultV4XDB() string {
|
||||
// LookupLocation 解析 IP;已有 location 非空时原样返回。
|
||||
func LookupLocation(ip, currentLocation string) string {
|
||||
if strings.TrimSpace(currentLocation) != "" {
|
||||
return currentLocation
|
||||
}
|
||||
return Get().Lookup(ip)
|
||||
}
|
||||
|
||||
func findDefaultXDB(filename string) string {
|
||||
candidates := []string{
|
||||
"data/ip2region_v4.xdb",
|
||||
"backend/data/ip2region_v4.xdb",
|
||||
"/app/data/ip2region_v4.xdb",
|
||||
"data/" + filename,
|
||||
"backend/data/" + filename,
|
||||
"/app/data/" + filename,
|
||||
}
|
||||
if wd, err := os.Getwd(); err == nil {
|
||||
candidates = append(candidates,
|
||||
filepath.Join(wd, "data", "ip2region_v4.xdb"),
|
||||
filepath.Join(wd, "..", "backend", "data", "ip2region_v4.xdb"),
|
||||
filepath.Join(wd, "data", filename),
|
||||
filepath.Join(wd, "..", "backend", "data", filename),
|
||||
)
|
||||
}
|
||||
for _, p := range candidates {
|
||||
|
||||
@@ -109,7 +109,7 @@ func (s *ConversationService) InitConversation(input InitConversationInput) (*In
|
||||
OS: input.OS,
|
||||
Language: input.Language,
|
||||
IPAddress: input.IPAddress,
|
||||
Location: geoip.Get().Lookup(input.IPAddress),
|
||||
Location: geoip.LookupLocation(input.IPAddress, ""),
|
||||
LastSeenAt: &now,
|
||||
ChatMode: chatMode,
|
||||
AIConfigID: aiConfigID,
|
||||
@@ -161,10 +161,15 @@ func (s *ConversationService) InitConversation(input InitConversationInput) (*In
|
||||
}
|
||||
if input.IPAddress != "" && conv.IPAddress == "" {
|
||||
updates["ip_address"] = input.IPAddress
|
||||
if conv.Location == "" {
|
||||
if loc := geoip.Get().Lookup(input.IPAddress); loc != "" {
|
||||
updates["location"] = loc
|
||||
}
|
||||
// 补全地理位置:新 IP、或历史会话仅有 IP 无 location(如升级前创建、或当时缺 v6 库)
|
||||
ipForGeo := conv.IPAddress
|
||||
if input.IPAddress != "" {
|
||||
ipForGeo = input.IPAddress
|
||||
}
|
||||
if conv.Location == "" && ipForGeo != "" {
|
||||
if loc := geoip.LookupLocation(ipForGeo, ""); loc != "" {
|
||||
updates["location"] = loc
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +437,13 @@ func (s *ConversationService) GetConversationDetail(id uint, userID uint) (*Conv
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
if conv.Location == "" && conv.IPAddress != "" {
|
||||
if loc := geoip.LookupLocation(conv.IPAddress, ""); loc != "" {
|
||||
_ = s.conversations.UpdateFields(conv.ID, map[string]interface{}{"location": loc})
|
||||
conv.Location = loc
|
||||
}
|
||||
}
|
||||
|
||||
summary, err := s.buildSummary(*conv, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
# 下载 ip2region v4 xdb 到 backend/data/(本地开发用)
|
||||
# 下载 ip2region v4/v6 xdb 到 backend/data/(本地开发用)
|
||||
set -e
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
DEST="$ROOT/backend/data/ip2region_v4.xdb"
|
||||
mkdir -p "$(dirname "$DEST")"
|
||||
curl -fsSL -o "$DEST" \
|
||||
https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v4.xdb
|
||||
echo "OK: $DEST ($(wc -c < "$DEST" | tr -d ' ') bytes)"
|
||||
DIR="$ROOT/backend/data"
|
||||
mkdir -p "$DIR"
|
||||
BASE="https://github.com/lionsoul2014/ip2region/raw/master/data"
|
||||
for f in ip2region_v4.xdb ip2region_v6.xdb; do
|
||||
DEST="$DIR/$f"
|
||||
curl -fsSL -o "$DEST" "$BASE/$f"
|
||||
echo "OK: $DEST ($(wc -c < "$DEST" | tr -d ' ') bytes)"
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user