feat: 完善 bug_optimization_submit 实现

This commit is contained in:
fuzhongyun 2025-12-27 10:13:57 +08:00
parent f50e87524e
commit 43edfc54c7
7 changed files with 92 additions and 14 deletions

View File

@ -65,6 +65,13 @@ tools:
enabled: true enabled: true
base_url: "https://revcl.1688sup.com/api/admin/afterSales/reseller_pre_ai" base_url: "https://revcl.1688sup.com/api/admin/afterSales/reseller_pre_ai"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
base_id: "2Amq4vjg89RnYx9DTp66m2orW3kdP0wQ"
sheet_id_or_name: "数据表"
default_prompt: default_prompt:
img_recognize: img_recognize:

View File

@ -105,6 +105,13 @@ eino_tools:
hytGoodsBrandSearch: hytGoodsBrandSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list" base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
sheet_id_or_name: "数据表"
default_prompt: default_prompt:

View File

@ -119,6 +119,13 @@ eino_tools:
hytGoodsBrandSearch: hytGoodsBrandSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list" base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
sheet_id_or_name: "数据表"
default_prompt: default_prompt:
img_recognize: img_recognize:

View File

@ -4,6 +4,7 @@ import (
"ai_scheduler/internal/biz/llm_service" "ai_scheduler/internal/biz/llm_service"
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/data/constants" "ai_scheduler/internal/data/constants"
errorcode "ai_scheduler/internal/data/error"
errors "ai_scheduler/internal/data/error" errors "ai_scheduler/internal/data/error"
"ai_scheduler/internal/data/impl" "ai_scheduler/internal/data/impl"
"ai_scheduler/internal/data/model" "ai_scheduler/internal/data/model"
@ -16,7 +17,6 @@ import (
"ai_scheduler/internal/pkg/mapstructure" "ai_scheduler/internal/pkg/mapstructure"
"ai_scheduler/internal/pkg/rec_extra" "ai_scheduler/internal/pkg/rec_extra"
"ai_scheduler/internal/pkg/util" "ai_scheduler/internal/pkg/util"
"ai_scheduler/internal/tool_callback"
"ai_scheduler/internal/tools" "ai_scheduler/internal/tools"
"ai_scheduler/internal/tools/public" "ai_scheduler/internal/tools/public"
errorsSpecial "errors" errorsSpecial "errors"
@ -255,25 +255,38 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo
accessToken, _ := r.dingtalkOldClient.GetAccessToken() accessToken, _ := r.dingtalkOldClient.GetAccessToken()
// 获取创建者 dingtalk unionId // 获取创建者 dingtalk unionId
unionId := r.getUserDingtalkUnionId(ctx, accessToken, sessionID) unionId := r.getUserDingtalkUnionId(ctx, accessToken, sessionID)
baseId := "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz" // 附件url
// 获取第一个数据表 var attachmentUrl string
// sheetIdOrName := r.getFirstSheetIdOrName(ctx, baseId) for _, file := range rec.UserContent.File {
attachmentUrl = file.FileUrl
break
}
recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, &dingtalk.InsertRecordReq{ recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, &dingtalk.InsertRecordReq{
BaseId: baseId, BaseId: r.conf.Dingtalk.TableDemand.BaseId,
SheetIdOrName: "数据表", SheetIdOrName: r.conf.Dingtalk.TableDemand.SheetIdOrName,
OperatorId: tool_callback.BotBugOptimizationSubmitAdminUnionId, // OperatorId: tool_callback.BotBugOptimizationSubmitAdminUnionId,
OperatorId: unionId,
CreatorUnionId: unionId, CreatorUnionId: unionId,
Content: rec.Match.Parameters, Content: rec.UserContent.Text,
AttachmentUrl: attachmentUrl,
}) })
if err != nil { if err != nil {
errCode := r.dingtalkNotableClient.GetHTTPStatus(err)
// 权限不足
if errCode == 403 {
return errorcode.ForbiddenErr("您当前没有AI需求表编辑权限请联系管理员添加权限")
}
return err return err
} }
if recordId == "" { if recordId == "" {
return errors.NewBusinessErr(422, "创建记录失败") return errors.NewBusinessErr(422, "创建记录失败,请联系管理员")
} }
entitys.ResText(rec.Ch, "", fmt.Sprintf("创建记录成功记录ID: %s", recordId)) // 构建跳转链接
detailPage := util.BuildJumpLink(r.conf.Dingtalk.TableDemand.Url, "去查看")
entitys.ResText(rec.Ch, "", fmt.Sprintf("问题已记录,正在分配相关人员处理,请您耐心等待处理结果。点击查看工单进度:%s", detailPage))
return nil return nil
} }

View File

@ -23,6 +23,7 @@ type Config struct {
PermissionConfig PermissionConfig `mapstructure:"permissionConfig"` PermissionConfig PermissionConfig `mapstructure:"permissionConfig"`
LLM LLM `mapstructure:"llm"` LLM LLM `mapstructure:"llm"`
// DingTalkBots map[string]*DingTalkBot `mapstructure:"ding_talk_bots"` // DingTalkBots map[string]*DingTalkBot `mapstructure:"ding_talk_bots"`
Dingtalk DingtalkConfig `mapstructure:"dingtalk"`
} }
type SysPrompt struct { type SysPrompt struct {
@ -61,6 +62,20 @@ type LLMCapabilityConfig struct {
Parameters LLMParameters `mapstructure:"parameters"` Parameters LLMParameters `mapstructure:"parameters"`
} }
// DingtalkConfig 钉钉配置
type DingtalkConfig struct {
ApiKey string `mapstructure:"api_key"`
ApiSecret string `mapstructure:"api_secret"`
TableDemand AITableConfig `mapstructure:"table_demand"`
}
// TableDemandConfig 需求表配置
type AITableConfig struct {
Url string `mapstructure:"url"`
BaseId string `mapstructure:"base_id"`
SheetIdOrName string `mapstructure:"sheet_id_or_name"`
}
// SysConfig 系统配置 // SysConfig 系统配置
type SysConfig struct { type SysConfig struct {
SessionLen int `mapstructure:"session_len"` SessionLen int `mapstructure:"session_len"`

View File

@ -3,10 +3,11 @@ package errorcode
import "fmt" import "fmt"
var ( var (
Success = &BusinessErr{code: 200, message: "成功"} Success = &BusinessErr{code: 200, message: "成功"}
ParamError = &BusinessErr{code: 401, message: "参数错误"} ParamError = &BusinessErr{code: 401, message: "参数错误"}
NotFoundError = &BusinessErr{code: 404, message: "请求地址未找到"} ForbiddenError = &BusinessErr{code: 403, message: "权限不足"}
SystemError = &BusinessErr{code: 405, message: "系统错误"} NotFoundError = &BusinessErr{code: 404, message: "请求地址未找到"}
SystemError = &BusinessErr{code: 405, message: "系统错误"}
ClientNotFound = &BusinessErr{code: 406, message: "未找到client_id"} ClientNotFound = &BusinessErr{code: 406, message: "未找到client_id"}
SessionNotFound = &BusinessErr{code: 407, message: "未找到会话信息"} SessionNotFound = &BusinessErr{code: 407, message: "未找到会话信息"}
@ -67,3 +68,7 @@ func (e *BusinessErr) Wrap(err error) *BusinessErr {
func WorkflowErr(message string) *BusinessErr { func WorkflowErr(message string) *BusinessErr {
return NewBusinessErr(WorkflowError.code, message) return NewBusinessErr(WorkflowError.code, message)
} }
func ForbiddenErr(message string) *BusinessErr {
return NewBusinessErr(ForbiddenError.code, message)
}

View File

@ -3,6 +3,8 @@ package dingtalk
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
errorcode "ai_scheduler/internal/data/error" errorcode "ai_scheduler/internal/data/error"
"encoding/json"
"time"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
notable "github.com/alibabacloud-go/dingtalk/notable_1_0" notable "github.com/alibabacloud-go/dingtalk/notable_1_0"
@ -79,6 +81,7 @@ type InsertRecordReq struct {
OperatorId string OperatorId string
CreatorUnionId string CreatorUnionId string
Content string Content string
AttachmentUrl string
} }
func (c *NotableClient) InsertRecord(accessToken string, req *InsertRecordReq) (string, error) { func (c *NotableClient) InsertRecord(accessToken string, req *InsertRecordReq) (string, error) {
@ -97,12 +100,16 @@ func (c *NotableClient) InsertRecord(accessToken string, req *InsertRecordReq) (
Records: []*notable.InsertRecordsRequestRecords{ Records: []*notable.InsertRecordsRequestRecords{
{ {
Fields: map[string]any{ Fields: map[string]any{
"创建日期": time.Now().Format(time.DateTime),
"需求内容": req.Content, "需求内容": req.Content,
"提交人": []map[string]any{ "提交人": []map[string]any{
{ {
"unionId": req.CreatorUnionId, "unionId": req.CreatorUnionId,
}, },
}, },
"附件": map[string]any{
"link": req.AttachmentUrl,
},
}, },
}, },
}, },
@ -117,3 +124,20 @@ func (c *NotableClient) InsertRecord(accessToken string, req *InsertRecordReq) (
return *resp.Body.Value[0].Id, nil return *resp.Body.Value[0].Id, nil
} }
func (c *NotableClient) GetHTTPStatus(err error) int {
if sdkErr, ok := err.(*tea.SDKError); ok {
if sdkErr.StatusCode != nil {
return *sdkErr.StatusCode
}
if sdkErr.Data != nil {
var m struct {
StatusCode int `json:"statusCode"`
}
if json.Unmarshal([]byte(*sdkErr.Data), &m) == nil {
return m.StatusCode
}
}
}
return 0 // 0 = 非 HTTP 错误
}