Files
hfb_sys/backend/internal/modules/sms/config.go
T

149 lines
4.0 KiB
Go

package sms
import (
"context"
"encoding/json"
"strings"
)
// ConfigKey 主站节点短信配置项,与分销站点的 business_templates 同构。
const ConfigKey = "sms.business_templates"
// DefaultStaleDays 上架未成交提醒的默认天数阈值。
const DefaultStaleDays = 3
// ConfigReader 读取系统配置文本,由 systemconfig.Repository 实现。
type ConfigReader interface {
FindValue(ctx context.Context, key string) (string, error)
}
// LoadConfig 从系统配置读取并解析节点短信配置。
func LoadConfig(ctx context.Context, reader ConfigReader) (Config, error) {
if reader == nil {
return DefaultConfig(), nil
}
value, err := reader.FindValue(ctx, ConfigKey)
if err != nil {
return Config{}, err
}
return ParseConfigValue(value)
}
// NodeConfig 是单个节点的开关与模板 CODE。
type NodeConfig struct {
Enabled bool `json:"enabled"`
TemplateCode string `json:"template_code"`
// StaleDays 仅上架未成交提醒使用:上架满多少天仍未成交才提醒,0 表示取默认值。
StaleDays int `json:"stale_days,omitempty"`
}
// Config 是主站节点短信配置(系统配置 sms.business_templates 的 JSON 结构)。
type Config struct {
Enabled bool `json:"enabled"`
Nodes map[string]NodeConfig `json:"nodes"`
}
// DefaultConfig 返回默认配置:总开关关闭(避免误发产生短信费用),
// 三个节点默认各自开启,模板 CODE 留空由运营在后台填写。
func DefaultConfig() Config {
nodes := make(map[string]NodeConfig, len(nodeMetas))
for _, meta := range nodeMetas {
node := NodeConfig{Enabled: true}
if meta.SupportsStaleDays {
node.StaleDays = DefaultStaleDays
}
nodes[meta.Code] = node
}
return Config{Enabled: false, Nodes: nodes}
}
// DefaultConfigValue 返回默认配置的 JSON 文本。
func DefaultConfigValue() string {
raw, err := MarshalConfig(DefaultConfig())
if err != nil {
return `{"enabled":false,"nodes":{}}`
}
return raw
}
// ParseConfigValue 解析系统配置里的 JSON 文本,缺失字段回落到默认值。
func ParseConfigValue(value string) (Config, error) {
cfg := DefaultConfig()
value = strings.TrimSpace(value)
if value == "" {
return cfg, nil
}
var raw struct {
Enabled *bool `json:"enabled"`
Nodes map[string]NodeConfig `json:"nodes"`
}
if err := json.Unmarshal([]byte(value), &raw); err != nil {
return Config{}, err
}
if raw.Enabled != nil {
cfg.Enabled = *raw.Enabled
}
if raw.Nodes != nil {
// 以已登记节点为基准合并,避免后台配置里出现未知节点。
for code, node := range raw.Nodes {
if !IsKnownNode(code) {
continue
}
node.TemplateCode = strings.TrimSpace(node.TemplateCode)
if node.StaleDays < 0 {
node.StaleDays = 0
}
cfg.Nodes[code] = node
}
}
return cfg, nil
}
// MarshalConfig 规范化并序列化配置。
func MarshalConfig(cfg Config) (string, error) {
normalized := DefaultConfig()
normalized.Enabled = cfg.Enabled
for code, node := range cfg.Nodes {
if !IsKnownNode(code) {
continue
}
node.TemplateCode = strings.TrimSpace(node.TemplateCode)
if node.StaleDays < 0 {
node.StaleDays = 0
}
normalized.Nodes[code] = node
}
raw, err := json.Marshal(normalized)
if err != nil {
return "", err
}
return string(raw), nil
}
// Node 返回指定节点的配置。
func (c Config) Node(code string) (NodeConfig, bool) {
node, ok := c.Nodes[code]
return node, ok
}
// NodeActive 判断节点是否可发送:总开关、节点开关与模板 CODE 都必须就绪。
func (c Config) NodeActive(code string) bool {
if !c.Enabled {
return false
}
node, ok := c.Node(code)
if !ok || !node.Enabled {
return false
}
return strings.TrimSpace(node.TemplateCode) != ""
}
// StaleDaysFor 返回上架未成交提醒的天数阈值,未配置时取默认值。
func (c Config) StaleDaysFor(code string) int {
node, ok := c.Node(code)
if !ok || node.StaleDays <= 0 {
return DefaultStaleDays
}
return node.StaleDays
}