package model import ( "time" "gorm.io/datatypes" ) // Setting stores system configuration as key-value pairs with JSON values. type Setting struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` Key string `gorm:"uniqueIndex;size:100;not null" json:"key"` Value datatypes.JSON `gorm:"type:json;not null" json:"value"` UpdatedAt time.Time `json:"updated_at"` } // APIKeysConfig stores third-party API keys under the "api_keys" setting key. type APIKeysConfig struct { SerperAPIKey string `json:"serper_api_key"` LLMProvider string `json:"llm_provider"` LLMBaseURL string `json:"llm_base_url"` LLMAPIKey string `json:"llm_api_key"` LLMModel string `json:"llm_model"` GitHubToken string `json:"github_token"` } // GradingConfig is the structure stored under the "grading" setting key. type GradingConfig struct { Levels []LevelDef `json:"levels"` IndustryKeywords map[string][]string `json:"industry_keywords"` } // LevelDef defines a single merchant grade level. type LevelDef struct { Key string `json:"key"` // internal key: e.g. "Hot" Label string `json:"label"` // display label: e.g. "优质商户" Color string `json:"color"` // display color: e.g. "red" Description string `json:"description"` // explain what this level means Rules []GradeRule `json:"rules"` // any rule match → this level (OR logic) } // GradeRule defines one condition that qualifies a merchant for a level. // All non-empty fields within a rule must ALL match (AND logic). type GradeRule struct { HasIndustry *bool `json:"has_industry,omitempty"` // must have industry tag HasWebsite *bool `json:"has_website,omitempty"` // must have website HasEmail *bool `json:"has_email,omitempty"` // must have email HasPhone *bool `json:"has_phone,omitempty"` // must have phone MinSourceCount *int `json:"min_source_count,omitempty"` // minimum source count } // DefaultGradingConfig returns the built-in default grading configuration. func DefaultGradingConfig() GradingConfig { boolTrue := true minSrc2 := 2 return GradingConfig{ Levels: []LevelDef{ { Key: "Hot", Label: "优质商户", Color: "red", Description: "有行业标签 + 有网站或邮箱,或有行业标签 + 多来源/有电话", Rules: []GradeRule{ {HasIndustry: &boolTrue, HasWebsite: &boolTrue}, {HasIndustry: &boolTrue, HasEmail: &boolTrue}, {HasIndustry: &boolTrue, HasPhone: &boolTrue}, {HasIndustry: &boolTrue, MinSourceCount: &minSrc2}, }, }, { Key: "Warm", Label: "普通商户", Color: "orange", Description: "有行业标签,或有网站/邮箱/电话等联系方式", Rules: []GradeRule{ {HasIndustry: &boolTrue}, {HasWebsite: &boolTrue, MinSourceCount: &minSrc2}, {HasWebsite: &boolTrue}, {HasEmail: &boolTrue}, {HasPhone: &boolTrue}, }, }, { Key: "Cold", Label: "待跟进", Color: "blue", Description: "仅有TG用户名,缺少其他联系方式和行业信息", Rules: []GradeRule{}, // default fallback }, }, IndustryKeywords: map[string][]string{ "机场": {"机场", "节点", "订阅", "clash", "v2ray", "trojan", "shadowsocks", "ss/ssr", "翻墙", "梯子", "科学上网", "加速器", "proxy", "代理", "xray", "hysteria", "surge", "quantumult", "shadowrocket", "小火箭"}, "VPN": {"vpn", "wireguard", "openvpn", "expressvpn", "nordvpn"}, "交易所": {"交易所", "exchange", "otc", "usdt", "btc", "eth", "加密货币", "数字货币", "币", "crypto", "binance", "okx"}, "支付": {"支付", "payment", "收款", "代收", "代付", "换汇", "承兑", "跑分", "三方支付", "四方支付"}, "博彩": {"博彩", "棋牌", "彩票", "赌", "百家乐", "龙虎", "六合彩", "时时彩", "体育投注"}, "引流": {"引流", "推广", "广告", "拉人", "涨粉", "群发", "营销", "seo", "流量"}, "开发": {"开发", "定制", "搭建", "源码", "app开发", "网站建设", "小程序", "h5", "二开"}, }, } }