chore: karuo-party 分平台 SKILL + 多平台分发更新;db handler 调整
Made-with: Cursor
This commit is contained in:
@@ -47,6 +47,92 @@ func parseConfigBool(v interface{}) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// isLikelyWxMiniProgramAppID 判断是否为微信小程序 AppID 常见形态:wx + 16 位十六进制(共 18 字符)。
|
||||
// 后台「链接标签」若 type=miniprogram 且在此列直接填真实 AppID,C 端会把该值当作 mpKey 去 linkedMiniprograms 里匹配 key;
|
||||
// 若未单独配置 linked_miniprograms,会提示「未找到关联小程序配置」。mergeDirectMiniProgramLinksFromLinkTags 会据此自动补全映射。
|
||||
func isLikelyWxMiniProgramAppID(s string) bool {
|
||||
s = strings.TrimSpace(s)
|
||||
if len(s) != 18 || !strings.HasPrefix(s, "wx") {
|
||||
return false
|
||||
}
|
||||
for i := 2; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func linkedMiniprogramItemKey(item gin.H) string {
|
||||
if v, ok := item["key"]; ok && v != nil {
|
||||
if s, ok := v.(string); ok {
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func linkedMiniprogramItemAppIDEmpty(item gin.H) bool {
|
||||
v, ok := item["appId"]
|
||||
if !ok || v == nil {
|
||||
return true
|
||||
}
|
||||
s, ok := v.(string)
|
||||
return !ok || strings.TrimSpace(s) == ""
|
||||
}
|
||||
|
||||
func linkedMiniprogramItemPathEmpty(item gin.H) bool {
|
||||
v, ok := item["path"]
|
||||
if !ok || v == nil {
|
||||
return true
|
||||
}
|
||||
s, ok := v.(string)
|
||||
return !ok || strings.TrimSpace(s) == ""
|
||||
}
|
||||
|
||||
// mergeDirectMiniProgramLinksFromLinkTags 将「直接填写微信 AppID」的链接标签并入 linkedMiniprograms,兼容现有小程序 navigateToMiniProgram 查表逻辑(不改 C 端)。
|
||||
func mergeDirectMiniProgramLinksFromLinkTags(linked *[]gin.H, tags []model.LinkTag) {
|
||||
if linked == nil {
|
||||
return
|
||||
}
|
||||
byKey := make(map[string]int)
|
||||
for i := range *linked {
|
||||
k := linkedMiniprogramItemKey((*linked)[i])
|
||||
if k != "" {
|
||||
byKey[k] = i
|
||||
}
|
||||
}
|
||||
for _, t := range tags {
|
||||
if strings.TrimSpace(strings.ToLower(t.Type)) != "miniprogram" {
|
||||
continue
|
||||
}
|
||||
app := strings.TrimSpace(t.AppID)
|
||||
if app == "" || !isLikelyWxMiniProgramAppID(app) {
|
||||
continue
|
||||
}
|
||||
path := strings.TrimSpace(t.PagePath)
|
||||
if idx, ok := byKey[app]; ok {
|
||||
item := (*linked)[idx]
|
||||
if linkedMiniprogramItemAppIDEmpty(item) {
|
||||
item["appId"] = app
|
||||
}
|
||||
if path != "" && linkedMiniprogramItemPathEmpty(item) {
|
||||
item["path"] = path
|
||||
}
|
||||
(*linked)[idx] = item
|
||||
continue
|
||||
}
|
||||
entry := gin.H{"key": app, "appId": app}
|
||||
if path != "" {
|
||||
entry["path"] = path
|
||||
}
|
||||
*linked = append(*linked, entry)
|
||||
byKey[app] = len(*linked) - 1
|
||||
}
|
||||
}
|
||||
|
||||
// defaultMpUi 小程序文案与导航默认值,存于 mp_config.mpUi;管理端系统设置可部分覆盖(深合并)
|
||||
func defaultMpUi() gin.H {
|
||||
return gin.H{
|
||||
@@ -226,35 +312,34 @@ func buildMiniprogramConfig() gin.H {
|
||||
if _, has := out["userDiscount"]; !has {
|
||||
out["userDiscount"] = float64(5)
|
||||
}
|
||||
// 链接标签列表(小程序 onLinkTagTap 需要 type;miniprogram 类型存 mpKey,用 key 查 linkedMiniprograms 得 appId)
|
||||
// 链接标签列表(小程序 onLinkTagTap:miniprogram 类型下发 mpKey=C 端用其匹配 linkedMiniprograms[].key;历史设计为「密钥→appId」,现支持 app_id 列直接填微信 AppID 并由下方 merge 自动补 linkedMiniprograms)
|
||||
var linkTagRows []model.LinkTag
|
||||
if err := db.Order("label ASC").Find(&linkTagRows).Error; err == nil {
|
||||
tags := make([]gin.H, 0, len(linkTagRows))
|
||||
for _, t := range linkTagRows {
|
||||
h := gin.H{"tagId": t.TagID, "label": t.Label, "url": t.URL, "type": t.Type, "pagePath": t.PagePath}
|
||||
if t.Type == "miniprogram" {
|
||||
h["mpKey"] = t.AppID // miniprogram 类型时 AppID 列存的是密钥
|
||||
} else {
|
||||
h["appId"] = t.AppID
|
||||
}
|
||||
tags = append(tags, h)
|
||||
_ = db.Order("label ASC").Find(&linkTagRows).Error
|
||||
tags := make([]gin.H, 0, len(linkTagRows))
|
||||
for _, t := range linkTagRows {
|
||||
h := gin.H{"tagId": t.TagID, "label": t.Label, "url": t.URL, "type": t.Type, "pagePath": t.PagePath}
|
||||
if t.Type == "miniprogram" {
|
||||
h["mpKey"] = t.AppID // 可为「关联表 key」或「直接 wx AppID」;后者由 mergeDirectMiniProgramLinksFromLinkTags 补全 linkedMiniprograms
|
||||
} else {
|
||||
h["appId"] = t.AppID
|
||||
}
|
||||
out["linkTags"] = tags
|
||||
tags = append(tags, h)
|
||||
}
|
||||
// 关联小程序列表(key 为 32 位密钥,小程序用 key 查 appId 后 wx.navigateToMiniProgram)
|
||||
out["linkTags"] = tags
|
||||
|
||||
// 关联小程序列表(小程序:find(m => m.key === mpKey) → navigateToMiniProgram)
|
||||
var linkedList []gin.H
|
||||
var linkedMpRow model.SystemConfig
|
||||
if err := db.Where("config_key = ?", "linked_miniprograms").First(&linkedMpRow).Error; err == nil && len(linkedMpRow.ConfigValue) > 0 {
|
||||
var linkedList []gin.H
|
||||
if err := json.Unmarshal(linkedMpRow.ConfigValue, &linkedList); err == nil && len(linkedList) > 0 {
|
||||
out["linkedMiniprograms"] = linkedList
|
||||
} else {
|
||||
// JSON解析失败,使用空数组
|
||||
out["linkedMiniprograms"] = []gin.H{}
|
||||
if err := json.Unmarshal(linkedMpRow.ConfigValue, &linkedList); err != nil {
|
||||
linkedList = nil
|
||||
}
|
||||
} else {
|
||||
// 未找到配置或查询失败,使用空数组作为默认值
|
||||
out["linkedMiniprograms"] = []gin.H{}
|
||||
}
|
||||
if linkedList == nil {
|
||||
linkedList = []gin.H{}
|
||||
}
|
||||
mergeDirectMiniProgramLinksFromLinkTags(&linkedList, linkTagRows)
|
||||
out["linkedMiniprograms"] = linkedList
|
||||
// 归一化 auditMode(兼容历史 bool / 字符串 / 数字)
|
||||
if mp, ok := out["mpConfig"].(gin.H); ok {
|
||||
mp["auditMode"] = parseConfigBool(mp["auditMode"])
|
||||
|
||||
Reference in New Issue
Block a user