f
This commit is contained in:
32
app/main/api/desc/front/toolbox.api
Normal file
32
app/main/api/desc/front/toolbox.api
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "工具箱服务"
|
||||||
|
desc: "免费小工具:手机号归属地、VIN解析、车牌归属地等"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ==================== 通用请求/响应 ====================
|
||||||
|
|
||||||
|
type (
|
||||||
|
ToolboxQueryReq {
|
||||||
|
ToolKey string `json:"tool_key" validate:"required"`
|
||||||
|
Params map[string]interface{} `json:"params"`
|
||||||
|
}
|
||||||
|
ToolboxQueryResp {
|
||||||
|
ToolKey string `json:"tool_key"`
|
||||||
|
Result map[string]interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ==================== 免费接口(无需登录) ====================
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: toolbox
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "通用工具查询"
|
||||||
|
@handler toolboxQuery
|
||||||
|
post /toolbox/query (ToolboxQueryReq) returns (ToolboxQueryResp)
|
||||||
|
}
|
||||||
@@ -97,3 +97,9 @@ Upload:
|
|||||||
TempFileMaxAgeH: 24 # 临时文件保留时长(小时),超时自动删除,0 表示默认 24
|
TempFileMaxAgeH: 24 # 临时文件保留时长(小时),超时自动删除,0 表示默认 24
|
||||||
PublicBaseURL: "https://www.tianyuancha.cn"
|
PublicBaseURL: "https://www.tianyuancha.cn"
|
||||||
ExtensionTime: 24 # 佣金解冻延迟时间,单位:24小时
|
ExtensionTime: 24 # 佣金解冻延迟时间,单位:24小时
|
||||||
|
|
||||||
|
|
||||||
|
tianxingjuhe:
|
||||||
|
url: "https://apis.tianapi.com"
|
||||||
|
key: "4ceffb1ffb95b83230b9a9c9df2467e1"
|
||||||
|
timeout: 30
|
||||||
@@ -103,6 +103,10 @@ Tianyuanapi:
|
|||||||
Key: "74902aff197d72d1caa5593560cb281e"
|
Key: "74902aff197d72d1caa5593560cb281e"
|
||||||
BaseURL: "https://api.tianyuanapi.com"
|
BaseURL: "https://api.tianyuanapi.com"
|
||||||
Timeout: 60
|
Timeout: 60
|
||||||
|
tianxingjuhe:
|
||||||
|
url: "https://apis.tianapi.com"
|
||||||
|
key: "4ceffb1ffb95b83230b9a9c9df2467e1"
|
||||||
|
timeout: 30
|
||||||
Authorization:
|
Authorization:
|
||||||
FileBaseURL: "https://www.tianyuancha.cn/api/v1/auth-docs" # 授权书文件访问基础URL
|
FileBaseURL: "https://www.tianyuancha.cn/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||||
Upload:
|
Upload:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type Config struct {
|
|||||||
Applepay ApplepayConfig
|
Applepay ApplepayConfig
|
||||||
Ali AliConfig
|
Ali AliConfig
|
||||||
Tianyuanapi TianyuanapiConfig
|
Tianyuanapi TianyuanapiConfig
|
||||||
|
Tianxingjuhe TianxingjuheConfig
|
||||||
SystemConfig SystemConfig
|
SystemConfig SystemConfig
|
||||||
WechatH5 WechatH5Config
|
WechatH5 WechatH5Config
|
||||||
Authorization AuthorizationConfig // 授权书配置
|
Authorization AuthorizationConfig // 授权书配置
|
||||||
@@ -150,6 +151,13 @@ type AuthorizationConfig struct {
|
|||||||
|
|
||||||
// UploadConfig 图片上传(行驶证等)配置,临时存储,按 hash 去重
|
// UploadConfig 图片上传(行驶证等)配置,临时存储,按 hash 去重
|
||||||
type UploadConfig struct {
|
type UploadConfig struct {
|
||||||
FileBaseURL string `json:",optional"` // 上传文件访问基础 URL,如 https://xxx/api/v1/upload/file
|
FileBaseURL string `json:"fileBaseURL,omitempty"` // 上传文件访问基础 URL,如 https://xxx/api/v1/upload/file
|
||||||
TempFileMaxAgeH int `json:",optional"` // 临时文件保留时长(小时),超时删除,0 表示默认 24 小时
|
TempFileMaxAgeH int `json:"tempFileMaxAgeH,omitempty"` // 临时文件保留时长(小时),超时删除,0 表示默认 24 小时
|
||||||
|
}
|
||||||
|
|
||||||
|
// TianxingjuheConfig 天行聚合API配置
|
||||||
|
type TianxingjuheConfig struct {
|
||||||
|
URL string // API基础URL
|
||||||
|
Key string // API密钥
|
||||||
|
Timeout int // 超时时间(秒),默认30秒
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
product "tyc-server/app/main/api/internal/handler/product"
|
product "tyc-server/app/main/api/internal/handler/product"
|
||||||
query "tyc-server/app/main/api/internal/handler/query"
|
query "tyc-server/app/main/api/internal/handler/query"
|
||||||
tianyuan "tyc-server/app/main/api/internal/handler/tianyuan"
|
tianyuan "tyc-server/app/main/api/internal/handler/tianyuan"
|
||||||
|
toolbox "tyc-server/app/main/api/internal/handler/toolbox"
|
||||||
upload "tyc-server/app/main/api/internal/handler/upload"
|
upload "tyc-server/app/main/api/internal/handler/upload"
|
||||||
user "tyc-server/app/main/api/internal/handler/user"
|
user "tyc-server/app/main/api/internal/handler/user"
|
||||||
"tyc-server/app/main/api/internal/svc"
|
"tyc-server/app/main/api/internal/svc"
|
||||||
@@ -1175,6 +1176,24 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
rest.WithPrefix("/api/v1"),
|
rest.WithPrefix("/api/v1"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// 获取工具列表
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/toolbox/list",
|
||||||
|
Handler: toolbox.ToolboxListHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 通用工具查询
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/toolbox/query",
|
||||||
|
Handler: toolbox.ToolboxQueryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
|
|||||||
17
app/main/api/internal/handler/toolbox/toolboxlisthandler.go
Normal file
17
app/main/api/internal/handler/toolbox/toolboxlisthandler.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package toolbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tyc-server/app/main/api/internal/logic/toolbox"
|
||||||
|
"tyc-server/app/main/api/internal/svc"
|
||||||
|
"tyc-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToolboxListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := toolbox.NewToolboxListLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ToolboxList()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
29
app/main/api/internal/handler/toolbox/toolboxqueryhandler.go
Normal file
29
app/main/api/internal/handler/toolbox/toolboxqueryhandler.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package toolbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"tyc-server/app/main/api/internal/logic/toolbox"
|
||||||
|
"tyc-server/app/main/api/internal/svc"
|
||||||
|
"tyc-server/app/main/api/internal/types"
|
||||||
|
"tyc-server/common/result"
|
||||||
|
"tyc-server/pkg/lzkit/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToolboxQueryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ToolboxQueryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := toolbox.NewToolboxQueryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ToolboxQuery(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/main/api/internal/logic/toolbox/toolboxlistlogic.go
Normal file
43
app/main/api/internal/logic/toolbox/toolboxlistlogic.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package toolbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tyc-server/app/main/api/internal/svc"
|
||||||
|
"tyc-server/app/main/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ToolboxListLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToolboxListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ToolboxListLogic {
|
||||||
|
return &ToolboxListLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ToolboxListLogic) ToolboxList() (resp *types.ToolboxListResp, err error) {
|
||||||
|
// 调用toolboxService获取工具列表
|
||||||
|
tools := l.svcCtx.ToolboxService.ListTools()
|
||||||
|
|
||||||
|
// 转换为响应格式
|
||||||
|
var toolInfos []types.ToolInfo
|
||||||
|
for _, tool := range tools {
|
||||||
|
toolInfos = append(toolInfos, types.ToolInfo{
|
||||||
|
Key: tool.Key,
|
||||||
|
Name: tool.Name,
|
||||||
|
Desc: tool.Desc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ToolboxListResp{
|
||||||
|
Tools: toolInfos,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
37
app/main/api/internal/logic/toolbox/toolboxquerylogic.go
Normal file
37
app/main/api/internal/logic/toolbox/toolboxquerylogic.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package toolbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tyc-server/app/main/api/internal/svc"
|
||||||
|
"tyc-server/app/main/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ToolboxQueryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToolboxQueryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ToolboxQueryLogic {
|
||||||
|
return &ToolboxQueryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ToolboxQueryLogic) ToolboxQuery(req *types.ToolboxQueryReq) (resp *types.ToolboxQueryResp, err error) {
|
||||||
|
// 调用toolboxService执行工具查询
|
||||||
|
result, err := l.svcCtx.ToolboxService.Query(l.ctx, req.ToolKey, req.Params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ToolboxQueryResp{
|
||||||
|
ToolKey: req.ToolKey,
|
||||||
|
Result: result,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
150
app/main/api/internal/service/tianxingjuhe_sdk/client.go
Normal file
150
app/main/api/internal/service/tianxingjuhe_sdk/client.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
package tianxingjuhe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client 天行聚合API客户端
|
||||||
|
type Client struct {
|
||||||
|
baseURL string
|
||||||
|
key string
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config 客户端配置
|
||||||
|
type Config struct {
|
||||||
|
BaseURL string // API基础URL
|
||||||
|
Key string // API密钥
|
||||||
|
Timeout int // 超时时间(秒)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response 通用API响应结构
|
||||||
|
type Response struct {
|
||||||
|
Code int `json:"code"` // 状态码,200表示成功
|
||||||
|
Msg string `json:"msg"` // 返回说明
|
||||||
|
Result interface{} `json:"result"` // 返回结果集,具体内容根据接口而定
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient 创建新的客户端实例
|
||||||
|
func NewClient(config Config) (*Client, error) {
|
||||||
|
if config.BaseURL == "" {
|
||||||
|
return nil, fmt.Errorf("baseURL不能为空")
|
||||||
|
}
|
||||||
|
if config.Key == "" {
|
||||||
|
return nil, fmt.Errorf("key不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
baseURL: config.BaseURL,
|
||||||
|
key: config.Key,
|
||||||
|
client: &http.Client{
|
||||||
|
Timeout: time.Duration(config.Timeout) * time.Second,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 发送GET请求
|
||||||
|
func (c *Client) Get(endpoint string, params map[string]interface{}) (*Response, error) {
|
||||||
|
// 构建完整URL
|
||||||
|
fullURL := fmt.Sprintf("%s/%s", c.baseURL, endpoint)
|
||||||
|
|
||||||
|
// 添加请求参数
|
||||||
|
queryParams := url.Values{}
|
||||||
|
for key, value := range params {
|
||||||
|
queryParams.Set(key, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加key参数
|
||||||
|
queryParams.Set("key", c.key)
|
||||||
|
|
||||||
|
// 拼接查询参数
|
||||||
|
if len(queryParams) > 0 {
|
||||||
|
fullURL = fmt.Sprintf("%s?%s", fullURL, queryParams.Encode())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTP请求
|
||||||
|
req, err := http.NewRequest("GET", fullURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("创建HTTP请求失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("User-Agent", "Tianxingjuhe-Go-SDK/1.0.0")
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
resp, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("发送HTTP请求失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var apiResp Response
|
||||||
|
if err := json.Unmarshal(body, &apiResp); err != nil {
|
||||||
|
return nil, fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post 发送POST请求
|
||||||
|
func (c *Client) Post(endpoint string, params map[string]interface{}) (*Response, error) {
|
||||||
|
// 构建完整URL
|
||||||
|
fullURL := fmt.Sprintf("%s/%s", c.baseURL, endpoint)
|
||||||
|
|
||||||
|
// 添加key参数
|
||||||
|
if params == nil {
|
||||||
|
params = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
params["key"] = c.key
|
||||||
|
|
||||||
|
// 序列化请求体
|
||||||
|
requestBody, err := json.Marshal(params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("序列化请求体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTP请求
|
||||||
|
req, err := http.NewRequest("POST", fullURL, bytes.NewBuffer(requestBody))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("创建HTTP请求失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("User-Agent", "Tianxingjuhe-Go-SDK/1.0.0")
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
resp, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("发送HTTP请求失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var apiResp Response
|
||||||
|
if err := json.Unmarshal(body, &apiResp); err != nil {
|
||||||
|
return nil, fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, nil
|
||||||
|
}
|
||||||
8071
app/main/api/internal/service/toolboxService.go
Normal file
8071
app/main/api/internal/service/toolboxService.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import (
|
|||||||
"tyc-server/app/main/api/internal/config"
|
"tyc-server/app/main/api/internal/config"
|
||||||
"tyc-server/app/main/api/internal/middleware"
|
"tyc-server/app/main/api/internal/middleware"
|
||||||
"tyc-server/app/main/api/internal/service"
|
"tyc-server/app/main/api/internal/service"
|
||||||
|
tianxingjuhe "tyc-server/app/main/api/internal/service/tianxingjuhe_sdk"
|
||||||
tianyuanapi "tyc-server/app/main/api/internal/service/tianyuanapi_sdk"
|
tianyuanapi "tyc-server/app/main/api/internal/service/tianyuanapi_sdk"
|
||||||
"tyc-server/app/main/model"
|
"tyc-server/app/main/model"
|
||||||
|
|
||||||
@@ -101,6 +102,8 @@ type ServiceContext struct {
|
|||||||
AdminPromotionLinkStatsService *service.AdminPromotionLinkStatsService
|
AdminPromotionLinkStatsService *service.AdminPromotionLinkStatsService
|
||||||
ImageService *service.ImageService
|
ImageService *service.ImageService
|
||||||
AuthorizationService *service.AuthorizationService
|
AuthorizationService *service.AuthorizationService
|
||||||
|
ToolboxService *service.ToolboxService
|
||||||
|
TianxingjuheService *tianxingjuhe.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceContext 创建服务上下文
|
// NewServiceContext 创建服务上下文
|
||||||
@@ -188,6 +191,16 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
logx.Errorf("初始化天远API失败: %+v", err)
|
logx.Errorf("初始化天远API失败: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化天行聚合API客户端
|
||||||
|
tianxingjuhe, err := tianxingjuhe.NewClient(tianxingjuhe.Config{
|
||||||
|
BaseURL: c.Tianxingjuhe.URL,
|
||||||
|
Key: c.Tianxingjuhe.Key,
|
||||||
|
Timeout: c.Tianxingjuhe.Timeout,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("初始化天行聚合API失败: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// ============================== 业务服务初始化 ==============================
|
// ============================== 业务服务初始化 ==============================
|
||||||
alipayService := service.NewAliPayService(c)
|
alipayService := service.NewAliPayService(c)
|
||||||
wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypeWxPayPubKey)
|
wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypeWxPayPubKey)
|
||||||
@@ -206,6 +219,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
adminPromotionLinkStatsTotalModel, adminPromotionLinkStatsHistoryModel)
|
adminPromotionLinkStatsTotalModel, adminPromotionLinkStatsHistoryModel)
|
||||||
imageService := service.NewImageService()
|
imageService := service.NewImageService()
|
||||||
authorizationService := service.NewAuthorizationService(c, authorizationDocumentModel)
|
authorizationService := service.NewAuthorizationService(c, authorizationDocumentModel)
|
||||||
|
toolboxService := service.NewToolboxService(tianxingjuhe)
|
||||||
|
tianxingjuheService := tianxingjuhe
|
||||||
|
|
||||||
// ============================== 异步任务服务 ==============================
|
// ============================== 异步任务服务 ==============================
|
||||||
asynqServer := asynq.NewServer(
|
asynqServer := asynq.NewServer(
|
||||||
@@ -304,6 +319,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
AdminPromotionLinkStatsService: adminPromotionLinkStatsService,
|
AdminPromotionLinkStatsService: adminPromotionLinkStatsService,
|
||||||
ImageService: imageService,
|
ImageService: imageService,
|
||||||
AuthorizationService: authorizationService,
|
AuthorizationService: authorizationService,
|
||||||
|
ToolboxService: toolboxService,
|
||||||
|
TianxingjuheService: tianxingjuheService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2134,6 +2134,26 @@ type TimeRangeReport struct {
|
|||||||
Report int `json:"report"` // 报告量
|
Report int `json:"report"` // 报告量
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ToolboxQueryReq struct {
|
||||||
|
ToolKey string `json:"tool_key" validate:"required"`
|
||||||
|
Params map[string]interface{} `json:"params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToolboxQueryResp struct {
|
||||||
|
ToolKey string `json:"tool_key"`
|
||||||
|
Result map[string]interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToolInfo struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToolboxListResp struct {
|
||||||
|
Tools []ToolInfo `json:"tools"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpdateMenuReq struct {
|
type UpdateMenuReq struct {
|
||||||
Id int64 `path:"id"` // 菜单ID
|
Id int64 `path:"id"` // 菜单ID
|
||||||
Pid int64 `json:"pid,optional"` // 父菜单ID
|
Pid int64 `json:"pid,optional"` // 父菜单ID
|
||||||
|
|||||||
228
docs/toolbox_implementation.md
Normal file
228
docs/toolbox_implementation.md
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
# 全能查询功能实现说明
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
实现了一个完整的工具查询系统,包含11个实用工具,用户可以通过首页点击工具进行查询。
|
||||||
|
|
||||||
|
## 后端实现
|
||||||
|
|
||||||
|
### 1. 配置和类型定义
|
||||||
|
|
||||||
|
#### 配置文件更新
|
||||||
|
- `config/config.go`: 添加了 `TianxingjuheConfig` 结构体和 `Tianxingjuhe` 字段
|
||||||
|
- `etc/main.yaml` 和 `etc/main.dev.yaml`: 添加了天行聚合API配置
|
||||||
|
|
||||||
|
#### 类型定义
|
||||||
|
- `types/types.go`: 添加了工具相关类型
|
||||||
|
- `ToolInfo`: 工具信息结构
|
||||||
|
- `ToolboxListResp`: 工具列表响应
|
||||||
|
- `ToolboxQueryReq`: 工具查询请求
|
||||||
|
- `ToolboxQueryResp`: 工具查询响应
|
||||||
|
|
||||||
|
### 2. 天行聚合API客户端
|
||||||
|
|
||||||
|
#### 文件结构
|
||||||
|
- `service/tianxingjuhe_sdk/client.go`: 天行聚合API客户端实现
|
||||||
|
|
||||||
|
#### 功能特性
|
||||||
|
- 支持GET和POST请求
|
||||||
|
- 自动添加API密钥
|
||||||
|
- 统一的响应处理
|
||||||
|
- 错误处理机制
|
||||||
|
|
||||||
|
### 3. 工具箱服务
|
||||||
|
|
||||||
|
#### 文件结构
|
||||||
|
- `service/toolboxService.go`: 工具箱服务核心实现
|
||||||
|
|
||||||
|
#### 工具列表(11个工具)
|
||||||
|
1. **IP地址查询** (ip-location)
|
||||||
|
- 查询IP地址归属地、运营商等信息
|
||||||
|
- 支持ipv4和ipv6
|
||||||
|
- 内网IP自动识别
|
||||||
|
|
||||||
|
2. **身份证归属地** (idcard-info)
|
||||||
|
- 查询身份证归属地、性别、出生日期等信息
|
||||||
|
- 校验身份证有效性
|
||||||
|
- 计算年龄
|
||||||
|
|
||||||
|
3. **手机号归属地** (phone-location)
|
||||||
|
- 查询手机号码归属地、运营商等信息
|
||||||
|
|
||||||
|
4. **北京时间查询** (beijing-time)
|
||||||
|
- 获取当前北京时间
|
||||||
|
- 不需要输入参数
|
||||||
|
|
||||||
|
5. **银行卡识别** (bank-card)
|
||||||
|
- 识别银行卡发卡行与卡种
|
||||||
|
|
||||||
|
6. **车牌号解析** (plate-parse)
|
||||||
|
- 解析车牌类型与归属地
|
||||||
|
|
||||||
|
7. **金额大写转换** (money-to-chinese)
|
||||||
|
- 阿拉伯数字转中文大写金额
|
||||||
|
|
||||||
|
8. **密码强度检测** (password-strength)
|
||||||
|
- 检测密码安全性并给出建议
|
||||||
|
|
||||||
|
9. **日期间隔计算** (days-between-dates)
|
||||||
|
- 计算两个日期相差的天数
|
||||||
|
|
||||||
|
10. **文件大小格式化** (file-size-format)
|
||||||
|
- 字节数转为 KB / MB / GB
|
||||||
|
|
||||||
|
11. **文本字数统计** (text-stats)
|
||||||
|
- 统计字符数、单词数、行数
|
||||||
|
|
||||||
|
### 4. API接口
|
||||||
|
|
||||||
|
#### 路由配置
|
||||||
|
- `handler/routes.go`: 添加了工具箱相关路由
|
||||||
|
- `GET /api/v1/toolbox/list`: 获取工具列表
|
||||||
|
- `POST /api/v1/toolbox/query`: 执行工具查询
|
||||||
|
|
||||||
|
#### Handler实现
|
||||||
|
- `handler/toolbox/toolboxlisthandler.go`: 工具列表接口
|
||||||
|
- `handler/toolbox/toolboxqueryhandler.go`: 工具查询接口
|
||||||
|
|
||||||
|
#### Logic实现
|
||||||
|
- `logic/toolbox/toolboxlistlogic.go`: 工具列表业务逻辑
|
||||||
|
- `logic/toolbox/toolboxquerylogic.go`: 工具查询业务逻辑
|
||||||
|
|
||||||
|
### 5. 服务上下文注册
|
||||||
|
|
||||||
|
#### 文件更新
|
||||||
|
- `svc/servicecontext.go`:
|
||||||
|
- 导入天行聚合SDK包
|
||||||
|
- 添加 `TianxingjuheService` 字段
|
||||||
|
- 初始化天行聚合客户端实例
|
||||||
|
- 注册到服务上下文
|
||||||
|
|
||||||
|
## 前端实现
|
||||||
|
|
||||||
|
### 1. 工具配置
|
||||||
|
|
||||||
|
#### 文件结构
|
||||||
|
- `config/toolboxRegistry.js`: 工具配置注册表
|
||||||
|
|
||||||
|
#### 配置内容
|
||||||
|
每个工具配置包含:
|
||||||
|
- `key`: 工具唯一标识
|
||||||
|
- `name`: 工具名称
|
||||||
|
- `desc`: 工具描述
|
||||||
|
- `icon`: 图标类名(使用carbon图标库)
|
||||||
|
- `fields`: 输入字段配置
|
||||||
|
- `validate`: 表单验证函数
|
||||||
|
- `validateMsg`: 验证失败提示信息
|
||||||
|
- `resultLabels`: 结果展示字段映射
|
||||||
|
|
||||||
|
### 2. 首页集成
|
||||||
|
|
||||||
|
#### 文件更新
|
||||||
|
- `pages/index.vue`:
|
||||||
|
- 添加了"全能查询"卡片
|
||||||
|
- 显示所有11个工具
|
||||||
|
- 点击工具跳转到查询页面
|
||||||
|
- 添加了自定义图标样式
|
||||||
|
|
||||||
|
### 3. 工具查询页面
|
||||||
|
|
||||||
|
#### 文件结构
|
||||||
|
- `pages/toolbox/query.vue`: 工具查询页面
|
||||||
|
|
||||||
|
#### 功能特性
|
||||||
|
- 动态表单生成(支持text、digit、date、textarea等类型)
|
||||||
|
- 表单验证
|
||||||
|
- 自动查询(无需输入参数的工具)
|
||||||
|
- 结果展示
|
||||||
|
- 错误处理
|
||||||
|
- 加载状态
|
||||||
|
|
||||||
|
#### 支持的字段类型
|
||||||
|
- `text`: 普通文本输入
|
||||||
|
- `digit`: 数字输入
|
||||||
|
- `idcard`: 身份证号输入
|
||||||
|
- `date`: 日期选择器
|
||||||
|
- `textarea`: 多行文本输入
|
||||||
|
|
||||||
|
### 4. API调用
|
||||||
|
|
||||||
|
#### 文件结构
|
||||||
|
- `api/toolbox.js`: 工具箱API封装
|
||||||
|
|
||||||
|
#### 接口函数
|
||||||
|
- `postToolboxQuery(toolKey, params)`: 执行工具查询
|
||||||
|
|
||||||
|
## 使用流程
|
||||||
|
|
||||||
|
### 用户使用流程
|
||||||
|
1. 打开首页
|
||||||
|
2. 看到"全能查询"卡片
|
||||||
|
3. 点击任意工具图标
|
||||||
|
4. 跳转到工具查询页面
|
||||||
|
5. 填写表单(如需)
|
||||||
|
6. 点击"立即查询"按钮
|
||||||
|
7. 查看查询结果
|
||||||
|
|
||||||
|
### 数据流程
|
||||||
|
1. 前端调用 `/api/v1/toolbox/list` 获取工具列表
|
||||||
|
2. 用户选择工具后调用 `/api/v1/toolbox/query` 执行查询
|
||||||
|
3. 后端根据 toolKey 分发到对应的处理函数
|
||||||
|
4. 处理函数执行查询逻辑(可能调用第三方API)
|
||||||
|
5. 返回查询结果
|
||||||
|
6. 前端展示结果
|
||||||
|
|
||||||
|
## 技术特点
|
||||||
|
|
||||||
|
### 后端特点
|
||||||
|
- 统一的工具接口设计
|
||||||
|
- 工具处理器注册表模式
|
||||||
|
- 灵活的参数传递(map[string]interface{})
|
||||||
|
- 完善的错误处理
|
||||||
|
- 支持第三方API集成(天行聚合)
|
||||||
|
|
||||||
|
### 前端特点
|
||||||
|
- 动态表单生成
|
||||||
|
- 类型安全的TypeScript
|
||||||
|
- 响应式UI设计
|
||||||
|
- 统一的错误处理
|
||||||
|
- 良好的用户体验
|
||||||
|
|
||||||
|
## 扩展指南
|
||||||
|
|
||||||
|
### 添加新工具
|
||||||
|
|
||||||
|
#### 后端步骤
|
||||||
|
1. 在 `toolboxService.go` 中添加处理函数
|
||||||
|
2. 在 `toolProcessors` 映射中注册新工具
|
||||||
|
3. 在 `ListTools()` 方法中添加工具信息
|
||||||
|
|
||||||
|
#### 前端步骤
|
||||||
|
1. 在 `toolboxRegistry.js` 中添加工具配置
|
||||||
|
2. 定义字段配置和验证规则
|
||||||
|
3. 定义结果展示字段映射
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **API密钥管理**: 天行聚合API的密钥已配置,请在生产环境中使用真实的API密钥
|
||||||
|
2. **错误处理**: 所有工具都有完善的错误处理机制
|
||||||
|
3. **表单验证**: 前端和后端都有验证,确保数据安全
|
||||||
|
4. **性能优化**: 工具查询响应时间已优化,建议在3秒内完成
|
||||||
|
5. **用户体验**: 无需输入参数的工具会自动查询,提升用户体验
|
||||||
|
|
||||||
|
## 测试建议
|
||||||
|
|
||||||
|
1. 测试每个工具的输入验证
|
||||||
|
2. 测试错误处理(如格式错误的输入)
|
||||||
|
3. 测试网络异常情况
|
||||||
|
4. 测试边界情况(如最大长度、特殊字符等)
|
||||||
|
5. 测试响应速度
|
||||||
|
|
||||||
|
## 部署检查清单
|
||||||
|
|
||||||
|
- [ ] 配置文件中的API密钥已更新为生产环境密钥
|
||||||
|
- [ ] 天行聚合API客户端已正确初始化
|
||||||
|
- [ ] 所有工具路由已正确注册
|
||||||
|
- [ ] 前端工具配置已同步更新
|
||||||
|
- [ ] 表单验证规则已测试通过
|
||||||
|
- [ ] 错误处理已测试
|
||||||
|
- [ ] 性能测试已通过
|
||||||
Reference in New Issue
Block a user