- 导航页所有文案(标题/副标题/标签/咨询区/页脚/工作室名称)均可在后台「导航页设置」页配置 - 新增公开API GET /api/v1/nav-settings,导航页加载时自动拉取配置覆盖默认值 - CustomerHandler改为从数据库读取webhook URL,不再依赖config.yaml - 新增默认企业微信webhook地址,开箱即用 - 后台新增webhook测试专用接口 POST /api/v1/admin/webhook/test - 后台新增批量配置保存接口 PUT /api/v1/admin/config-batch - 后台新增「导航页设置」管理页面,支持分组编辑保存 - 页脚添加工作室名称展示位
158 lines
4.1 KiB
Go
158 lines
4.1 KiB
Go
package handler
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
"time"
|
||
|
||
"gotest/internal/model"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// CustomerHandler 客户信息收集处理器
|
||
type CustomerHandler struct {
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewCustomerHandler 创建客户信息收集处理器
|
||
func NewCustomerHandler(db *gorm.DB) *CustomerHandler {
|
||
return &CustomerHandler{db: db}
|
||
}
|
||
|
||
// CustomerRequest 客户信息请求
|
||
type CustomerRequest struct {
|
||
Name string `json:"name" binding:"required"`
|
||
Phone string `json:"phone" binding:"required"`
|
||
Company string `json:"company"`
|
||
Email string `json:"email"`
|
||
Needs string `json:"needs" binding:"required"`
|
||
}
|
||
|
||
// Submit 提交客户信息 POST /api/v1/customer/submit
|
||
func (h *CustomerHandler) Submit(c *gin.Context) {
|
||
var req CustomerRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
FailBadRequest(c, "请填写完整的联系信息")
|
||
return
|
||
}
|
||
|
||
// 构建企业微信消息内容
|
||
content := fmt.Sprintf("【新客户咨询】\n"+
|
||
"━━━━━━━━━━━━━━━━━━━━\n"+
|
||
"👤 姓名:%s\n"+
|
||
"📱 电话:%s\n"+
|
||
"📧 邮箱:%s\n"+
|
||
"🏢 公司:%s\n"+
|
||
"💼 需求:%s\n"+
|
||
"⏰ 时间:%s\n"+
|
||
"━━━━━━━━━━━━━━━━━━━━",
|
||
req.Name, req.Phone, req.Email, req.Company, req.Needs, time.Now().Format("2006-01-02 15:04:05"))
|
||
|
||
// 发送到企业微信webhook
|
||
if err := h.sendToWechatWebhook(content); err != nil {
|
||
fmt.Printf("发送企业微信webhook失败: %v\n", err)
|
||
}
|
||
|
||
Success(c, gin.H{
|
||
"message": "提交成功,我们会尽快联系您!",
|
||
})
|
||
}
|
||
|
||
// getWebhookURL 从数据库获取webhook URL
|
||
func (h *CustomerHandler) getWebhookURL() string {
|
||
var cfg model.Config
|
||
if err := h.db.Where("`key` = ?", "wechat_webhook_url").First(&cfg).Error; err == nil && cfg.Value != "" {
|
||
return cfg.Value
|
||
}
|
||
return "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=71110fd5-9f51-4695-88dc-85ca34385d66"
|
||
}
|
||
|
||
// sendToWechatWebhook 发送消息到企业微信群机器人
|
||
func (h *CustomerHandler) sendToWechatWebhook(content string) error {
|
||
webhookURL := h.getWebhookURL()
|
||
|
||
message := map[string]interface{}{
|
||
"msgtype": "text",
|
||
"text": map[string]string{
|
||
"content": content,
|
||
},
|
||
}
|
||
|
||
jsonData, err := json.Marshal(message)
|
||
if err != nil {
|
||
return fmt.Errorf("序列化消息失败: %w", err)
|
||
}
|
||
|
||
resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(jsonData))
|
||
if err != nil {
|
||
return fmt.Errorf("发送请求失败: %w", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
body, err := io.ReadAll(resp.Body)
|
||
if err != nil {
|
||
return fmt.Errorf("读取响应失败: %w", err)
|
||
}
|
||
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("请求失败,状态码: %d,响应: %s", resp.StatusCode, string(body))
|
||
}
|
||
|
||
var result map[string]interface{}
|
||
if err := json.Unmarshal(body, &result); err != nil {
|
||
return fmt.Errorf("解析响应失败: %w", err)
|
||
}
|
||
|
||
if errcode, ok := result["errcode"].(float64); ok && errcode != 0 {
|
||
errmsg, _ := result["errmsg"].(string)
|
||
return fmt.Errorf("企业微信返回错误: %v - %s", errcode, errmsg)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// TestWebhook 测试webhook POST /api/v1/admin/webhook/test
|
||
func (h *CustomerHandler) TestWebhook(c *gin.Context) {
|
||
webhookURL := h.getWebhookURL()
|
||
|
||
content := fmt.Sprintf("✅ Webhook 测试成功\n⏰ 时间:%s", time.Now().Format("2006-01-02 15:04:05"))
|
||
|
||
message := map[string]interface{}{
|
||
"msgtype": "text",
|
||
"text": map[string]string{
|
||
"content": content,
|
||
},
|
||
}
|
||
|
||
jsonData, err := json.Marshal(message)
|
||
if err != nil {
|
||
FailInternal(c, "序列化失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(jsonData))
|
||
if err != nil {
|
||
FailInternal(c, "发送失败: "+err.Error())
|
||
return
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
body, _ := io.ReadAll(resp.Body)
|
||
|
||
var result map[string]interface{}
|
||
json.Unmarshal(body, &result)
|
||
|
||
if errcode, ok := result["errcode"].(float64); ok && errcode != 0 {
|
||
errmsg, _ := result["errmsg"].(string)
|
||
FailInternal(c, fmt.Sprintf("企业微信返回错误: %v - %s", errcode, errmsg))
|
||
return
|
||
}
|
||
|
||
SuccessMsg(c, "测试消息发送成功!请检查企业微信群")
|
||
}
|