package api import ( "database/sql" "net/http" "sort" "strings" "server/internal/schema" ) func MetadataHandler(meta, marketing, ymt *sql.DB) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ds := r.URL.Query().Get("datasource") ot := r.URL.Query().Get("order_type") db := marketing if ds == "ymt" { db = ymt } // 从代码中获取隐藏字段列表 hiddenFields := getHiddenFieldsFromCode(ds) tables := []string{} if ds == "ymt" { tables = []string{"order_info", "order_cash", "order_voucher", "order_digit", "goods_voucher_batch", "goods_voucher_subject_config", "merchant", "activity"} } else { tables = []string{"order", "order_detail", "order_cash", "order_voucher", "plan", "key_batch", "code_batch", "voucher", "voucher_batch", "merchant_key_send"} } out := []map[string]interface{}{} for _, tbl := range tables { cols := getColumns(db, tbl) fields := []map[string]string{} for _, c := range cols { tCanonical, fCanonical := canonicalField(ds, tbl, c.Name) if tCanonical == "" || fCanonical == "" { continue } // 检查字段是否在隐藏列表中 if isFieldHidden(hiddenFields, tCanonical, fCanonical) { continue } lab := c.Comment if lab == "" { lab = fCanonical } fields = append(fields, map[string]string{"key": tCanonical + "." + fCanonical, "field": fCanonical, "label": lab}) } tDisplay := displayTable(ds, tbl) out = append(out, map[string]interface{}{"table": tDisplay, "label": tableLabel(tDisplay), "fields": fields}) } sort.Slice(out, func(i, j int) bool { return out[i]["table"].(string) < out[j]["table"].(string) }) rec := recommendedDefaults(ds, ot) ok(w, r, map[string]interface{}{"datasource": ds, "tables": out, "recommended": rec}) }) } // getHiddenFieldsFromCode 从代码中获取指定数据源的隐藏字段映射 func getHiddenFieldsFromCode(ds string) map[string]map[string]bool { // 从字段白名单构建隐藏字段映射,所有字段默认 true(隐藏) return buildHiddenFieldsFromWhitelist() } // buildHiddenFieldsFromWhitelist 读取 schema.AllWhitelist 中的所有字段,按表分组,全部标记为 true func buildHiddenFieldsFromWhitelist() map[string]map[string]bool { out := make(map[string]map[string]bool) for k := range schema.AllWhitelist() { parts := strings.SplitN(k, ".", 2) if len(parts) != 2 { continue } tbl, field := parts[0], parts[1] if _, ok := out[tbl]; !ok { out[tbl] = make(map[string]bool) } out[tbl][field] = true } return out } // isFieldHidden 检查字段是否在隐藏列表中 func isFieldHidden(hiddenFields map[string]map[string]bool, table, field string) bool { tableFields, ok := hiddenFields[table] if !ok { return false } return tableFields[field] } func tableLabel(t string) string { switch t { case "order": return "订单主表" case "order_detail": return "订单详情" case "order_cash": return "红包订单" case "order_voucher": return "立减金订单" case "order_digit": return "直充卡密订单" case "plan": return "活动" case "key_batch": return "key批次" case "code_batch": return "兑换码批次" case "voucher": return "立减金" case "voucher_batch": return "立减金批次" case "merchant_key_send": return "key码API发放记录" case "goods_voucher_batch": return "立减金批次表" case "goods_voucher_subject_config": return "立减金主体" case "merchant": return "客户" case "activity": return "活动" default: return t } } func displayTable(ds, tbl string) string { if ds == "ymt" && tbl == "order_info" { return "order" } return tbl } func canonicalField(ds, tbl, col string) (string, string) { if ds == "ymt" && tbl == "order_info" { switch col { case "order_no": return "order", "order_number" case "key_code": return "order", "key" case "user_id": return "order", "creator" case "out_order_no": return "order", "out_trade_no" case "activity_id": return "order", "plan_id" case "merchant_id": return "order", "reseller_id" case "goods_id": return "order", "product_id" case "pay_price": return "order", "pay_amount" case "key_batch_name": return "order", "key_batch_id" default: return "order", col } } // other tables: canonical equals actual return tbl, col } type columnMeta struct { Name string Comment string } func getColumns(db *sql.DB, tbl string) []columnMeta { rows, err := db.Query("SELECT COLUMN_NAME, COLUMN_COMMENT FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? ORDER BY ORDINAL_POSITION", tbl) if err != nil { return []columnMeta{} } defer rows.Close() cols := []columnMeta{} for rows.Next() { var name, comment string if err := rows.Scan(&name, &comment); err == nil { cols = append(cols, columnMeta{Name: name, Comment: comment}) } } return cols } func recommendedDefaults(ds, orderType string) []string { base := []string{"order.order_number", "order.creator", "order.out_trade_no", "order.type", "order.status", "order.contract_price", "order.num", "order.pay_amount", "order.create_time"} if ds != "ymt" { base = []string{"order.order_number", "order.creator", "order.out_trade_no", "order.type", "order.status", "order.contract_price", "order.num", "order.total", "order.pay_amount", "order.create_time"} } t := orderType if t == "2" { // 直充卡密 if ds == "ymt" { base = append(base, "order_digit.order_no", "order_digit.account", "order_digit.success_time") } else { base = append(base, "plan.title") } } else if t == "3" { // 立减金 if ds == "ymt" { base = append(base, "order_voucher.channel", "order_voucher.status", "goods_voucher_batch.channel_batch_no") } else { base = append(base, "order_voucher.channel", "voucher.denomination") } } else if t == "1" { // 红包 if ds == "ymt" { base = append(base, "order_cash.channel", "order_cash.receive_status", "order_cash.denomination") } else { base = append(base, "order_cash.channel", "order_cash.receive_status", "order_cash.amount") } } return base }