更新测试文档并增强设备管理逻辑
- 新增了一项功能,用于自动生成文章中的提及内容,从而优化了系统中创建计划流程的测试用例文档。 - 更新了测试关联文档,以纳入基于不同场景的测试用例的归档和复用规则。 - 实现了在未指定设备时选择默认设备的逻辑,确保设备管理流程更加顺畅。 - 在计划创建的上下文中明确了设备组的需求,从而提高了系统的整体可靠性。
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -193,6 +194,113 @@ func ckbOpenGetPlanDetail(token string, planID int64) (string, error) {
|
||||
return result.Data.APIKey, nil
|
||||
}
|
||||
|
||||
// ckbOpenGetDefaultDeviceID 获取默认设备 ID:拉设备列表,取第一个 memo 或 nickname 包含 "soul" 的设备;用于 deviceGroups 必填时的默认值
|
||||
func ckbOpenGetDefaultDeviceID(token string) (int64, error) {
|
||||
u := ckbOpenBaseURL + "/v1/devices?keyword=soul&page=1&limit=50"
|
||||
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("构造设备列表请求失败: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("请求存客宝设备列表失败: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
b, _ := io.ReadAll(resp.Body)
|
||||
var parsed map[string]interface{}
|
||||
if err := json.Unmarshal(b, &parsed); err != nil {
|
||||
return 0, fmt.Errorf("解析设备列表失败: %w", err)
|
||||
}
|
||||
var listAny interface{}
|
||||
if dataVal, ok := parsed["data"].(map[string]interface{}); ok {
|
||||
listAny = dataVal["list"]
|
||||
} else if la, ok := parsed["list"]; ok {
|
||||
listAny = la
|
||||
}
|
||||
arr, ok := listAny.([]interface{})
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("设备列表格式异常")
|
||||
}
|
||||
// 优先匹配 memo/nickname 包含 soul 的设备;若无则取第一个(keyword 可能已过滤)
|
||||
for _, item := range arr {
|
||||
m, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
memo := toString(m["memo"])
|
||||
if memo == "" {
|
||||
memo = toString(m["imei"])
|
||||
}
|
||||
nickname := toString(m["nickname"])
|
||||
lowerMemo := strings.ToLower(memo)
|
||||
lowerNick := strings.ToLower(nickname)
|
||||
if strings.Contains(lowerMemo, "soul") || strings.Contains(lowerNick, "soul") {
|
||||
id := parseDeviceID(m["id"])
|
||||
if id > 0 {
|
||||
return id, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// 未找到含 soul 的,取第一个
|
||||
if len(arr) > 0 {
|
||||
if m, ok := arr[0].(map[string]interface{}); ok {
|
||||
id := parseDeviceID(m["id"])
|
||||
if id > 0 {
|
||||
return id, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("未找到名为 soul 的设备,请先在存客宝添加设备并设置 memo 或 nickname 包含 soul")
|
||||
}
|
||||
|
||||
func toString(v interface{}) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
return val
|
||||
case float64:
|
||||
return strconv.FormatFloat(val, 'f', -1, 64)
|
||||
case int:
|
||||
return strconv.Itoa(val)
|
||||
case int64:
|
||||
return strconv.FormatInt(val, 10)
|
||||
default:
|
||||
return fmt.Sprint(v)
|
||||
}
|
||||
}
|
||||
|
||||
func parseDeviceID(v interface{}) int64 {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
switch val := v.(type) {
|
||||
case float64:
|
||||
if val > 0 {
|
||||
return int64(val)
|
||||
}
|
||||
case int:
|
||||
if val > 0 {
|
||||
return int64(val)
|
||||
}
|
||||
case int64:
|
||||
if val > 0 {
|
||||
return val
|
||||
}
|
||||
case string:
|
||||
if val == "" {
|
||||
return 0
|
||||
}
|
||||
n, err := strconv.ParseInt(val, 10, 64)
|
||||
if err == nil && n > 0 {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ckbOpenDeletePlan 调用 DELETE /v1/plan/delete 删除存客宝获客计划
|
||||
func ckbOpenDeletePlan(token string, planID int64) error {
|
||||
payload := map[string]interface{}{"planId": planID}
|
||||
|
||||
Reference in New Issue
Block a user