fix(templates): 修复模板编辑保存时的字段映射问题
修复模板编辑保存时字段路径映射错误的问题,增加对主表字段的支持 添加详细的日志记录以帮助调试模板更新过程 优化字段选择器的数据处理逻辑,确保与后端API兼容
This commit is contained in:
parent
3ea990ebdc
commit
ff0f02f065
|
|
@ -159,43 +159,87 @@ func (a *TemplatesAPI) getTemplate(w http.ResponseWriter, r *http.Request, id st
|
|||
}
|
||||
|
||||
func (a *TemplatesAPI) patchTemplate(w http.ResponseWriter, r *http.Request, id string) {
|
||||
b, _ := io.ReadAll(r.Body)
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
log.Printf("trace_id=%s error reading request body: %v", TraceIDFrom(r), err)
|
||||
fail(w, r, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("trace_id=%s patchTemplate request body: %s", TraceIDFrom(r), string(b))
|
||||
|
||||
var p map[string]interface{}
|
||||
json.Unmarshal(b, &p)
|
||||
err = json.Unmarshal(b, &p)
|
||||
if err != nil {
|
||||
log.Printf("trace_id=%s error unmarshaling request body: %v", TraceIDFrom(r), err)
|
||||
fail(w, r, http.StatusBadRequest, "invalid JSON format")
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("trace_id=%s patchTemplate parsed payload: %v", TraceIDFrom(r), p)
|
||||
log.Printf("trace_id=%s patchTemplate template ID: %s", TraceIDFrom(r), id)
|
||||
|
||||
set := []string{}
|
||||
args := []interface{}{}
|
||||
for k, v := range p {
|
||||
log.Printf("trace_id=%s patchTemplate processing field: %s, value: %v, type: %T", TraceIDFrom(r), k, v, v)
|
||||
switch k {
|
||||
case "name", "visibility", "file_format":
|
||||
set = append(set, k+"=?")
|
||||
args = append(args, v)
|
||||
case "name", "visibility", "file_format", "main_table":
|
||||
if strVal, ok := v.(string); ok {
|
||||
set = append(set, k+"=?")
|
||||
args = append(args, strVal)
|
||||
log.Printf("trace_id=%s patchTemplate added string field: %s, value: %s", TraceIDFrom(r), k, strVal)
|
||||
} else {
|
||||
log.Printf("trace_id=%s patchTemplate invalid string field: %s, value: %v, type: %T", TraceIDFrom(r), k, v, v)
|
||||
}
|
||||
case "fields":
|
||||
set = append(set, "fields_json=?")
|
||||
args = append(args, toJSON(v))
|
||||
jsonBytes := toJSON(v)
|
||||
args = append(args, jsonBytes)
|
||||
log.Printf("trace_id=%s patchTemplate added fields_json: %s", TraceIDFrom(r), string(jsonBytes))
|
||||
case "filters":
|
||||
set = append(set, "filters_json=?")
|
||||
args = append(args, toJSON(v))
|
||||
jsonBytes := toJSON(v)
|
||||
args = append(args, jsonBytes)
|
||||
log.Printf("trace_id=%s patchTemplate added filters_json: %s", TraceIDFrom(r), string(jsonBytes))
|
||||
case "enabled":
|
||||
set = append(set, "enabled=?")
|
||||
if v.(bool) {
|
||||
args = append(args, 1)
|
||||
if boolVal, ok := v.(bool); ok {
|
||||
if boolVal {
|
||||
args = append(args, 1)
|
||||
} else {
|
||||
args = append(args, 0)
|
||||
}
|
||||
log.Printf("trace_id=%s patchTemplate added enabled: %t", TraceIDFrom(r), boolVal)
|
||||
} else {
|
||||
args = append(args, 0)
|
||||
log.Printf("trace_id=%s patchTemplate invalid bool field: %s, value: %v, type: %T", TraceIDFrom(r), k, v, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(set) == 0 {
|
||||
log.Printf("trace_id=%s patchTemplate no fields to update", TraceIDFrom(r))
|
||||
fail(w, r, http.StatusBadRequest, "no patch")
|
||||
return
|
||||
}
|
||||
|
||||
// ensure updated_at
|
||||
set = append(set, "updated_at=?")
|
||||
args = append(args, time.Now(), id)
|
||||
_, err := a.meta.Exec("UPDATE export_templates SET "+strings.Join(set, ",")+" WHERE id= ?", args...)
|
||||
now := time.Now()
|
||||
args = append(args, now, id)
|
||||
|
||||
sql := "UPDATE export_templates SET "+strings.Join(set, ",")+" WHERE id= ?"
|
||||
log.Printf("trace_id=%s patchTemplate executing SQL: %s", TraceIDFrom(r), sql)
|
||||
log.Printf("trace_id=%s patchTemplate SQL args: %v", TraceIDFrom(r), args)
|
||||
|
||||
_, err = a.meta.Exec(sql, args...)
|
||||
if err != nil {
|
||||
log.Printf("trace_id=%s patchTemplate SQL error: %v", TraceIDFrom(r), err)
|
||||
fail(w, r, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("trace_id=%s patchTemplate update successful", TraceIDFrom(r))
|
||||
ok(w, r, nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,82 +1,103 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
Host string `yaml:"host"`
|
||||
Port string `yaml:"port"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Name string `yaml:"name"`
|
||||
Host string `yaml:"host"`
|
||||
Port string `yaml:"port"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Name string `yaml:"name"`
|
||||
}
|
||||
|
||||
type App struct {
|
||||
Port string `yaml:"port"`
|
||||
MarketingDB DB `yaml:"marketing_db"`
|
||||
YMTDB DB `yaml:"ymt_db"`
|
||||
Port string `yaml:"port"`
|
||||
MarketingDB DB `yaml:"marketing_db"`
|
||||
YMTDB DB `yaml:"ymt_db"`
|
||||
}
|
||||
|
||||
type root struct {
|
||||
App App `yaml:"app"`
|
||||
App App `yaml:"app"`
|
||||
}
|
||||
|
||||
func Load() App {
|
||||
paths := []string{
|
||||
"config.yaml",
|
||||
filepath.Join("server", "config.yaml"),
|
||||
}
|
||||
var cfg App
|
||||
for _, p := range paths {
|
||||
if readYAML(p, &cfg) {
|
||||
break
|
||||
}
|
||||
}
|
||||
LoadEnv()
|
||||
if v := os.Getenv("MARKETING_DB_HOST"); v != "" { cfg.MarketingDB.Host = v }
|
||||
if v := os.Getenv("MARKETING_DB_PORT"); v != "" { cfg.MarketingDB.Port = v }
|
||||
if v := os.Getenv("MARKETING_DB_USER"); v != "" { cfg.MarketingDB.User = v }
|
||||
if v := os.Getenv("MARKETING_DB_PASSWORD"); v != "" { cfg.MarketingDB.Password = v }
|
||||
if v := os.Getenv("MARKETING_DB_NAME"); v != "" { cfg.MarketingDB.Name = v }
|
||||
if v := os.Getenv("YMT_DB_HOST"); v != "" { cfg.YMTDB.Host = v }
|
||||
if v := os.Getenv("YMT_DB_PORT"); v != "" { cfg.YMTDB.Port = v }
|
||||
if v := os.Getenv("YMT_DB_USER"); v != "" { cfg.YMTDB.User = v }
|
||||
if v := os.Getenv("YMT_DB_PASSWORD"); v != "" { cfg.YMTDB.Password = v }
|
||||
if v := os.Getenv("YMT_DB_NAME"); v != "" { cfg.YMTDB.Name = v }
|
||||
return cfg
|
||||
paths := []string{
|
||||
"config.yaml",
|
||||
filepath.Join("server", "config.yaml"),
|
||||
}
|
||||
var cfg App
|
||||
for _, p := range paths {
|
||||
if readYAML(p, &cfg) {
|
||||
break
|
||||
}
|
||||
}
|
||||
LoadEnv()
|
||||
if v := os.Getenv("MARKETING_DB_HOST"); v != "" {
|
||||
cfg.MarketingDB.Host = v
|
||||
}
|
||||
if v := os.Getenv("MARKETING_DB_PORT"); v != "" {
|
||||
cfg.MarketingDB.Port = v
|
||||
}
|
||||
if v := os.Getenv("MARKETING_DB_USER"); v != "" {
|
||||
cfg.MarketingDB.User = v
|
||||
}
|
||||
if v := os.Getenv("MARKETING_DB_PASSWORD"); v != "" {
|
||||
cfg.MarketingDB.Password = v
|
||||
}
|
||||
if v := os.Getenv("MARKETING_DB_NAME"); v != "" {
|
||||
cfg.MarketingDB.Name = v
|
||||
}
|
||||
if v := os.Getenv("YMT_DB_HOST"); v != "" {
|
||||
cfg.YMTDB.Host = v
|
||||
}
|
||||
if v := os.Getenv("YMT_DB_PORT"); v != "" {
|
||||
cfg.YMTDB.Port = v
|
||||
}
|
||||
if v := os.Getenv("YMT_DB_USER"); v != "" {
|
||||
cfg.YMTDB.User = v
|
||||
}
|
||||
if v := os.Getenv("YMT_DB_PASSWORD"); v != "" {
|
||||
cfg.YMTDB.Password = v
|
||||
}
|
||||
if v := os.Getenv("YMT_DB_NAME"); v != "" {
|
||||
cfg.YMTDB.Name = v
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func readYAML(path string, out *App) bool {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
b, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var r root
|
||||
if err := yaml.Unmarshal(b, &r); err == nil {
|
||||
if r.App.Port != "" || r.App.MarketingDB.Host != "" || r.App.YMTDB.Host != "" {
|
||||
*out = r.App
|
||||
return true
|
||||
}
|
||||
}
|
||||
if err := yaml.Unmarshal(b, out); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
b, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var r root
|
||||
if err := yaml.Unmarshal(b, &r); err == nil {
|
||||
if r.App.Port != "" || r.App.MarketingDB.Host != "" || r.App.YMTDB.Host != "" {
|
||||
*out = r.App
|
||||
return true
|
||||
}
|
||||
}
|
||||
if err := yaml.Unmarshal(b, out); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d DB) DSN() string {
|
||||
if strings.TrimSpace(d.User) == "" || strings.TrimSpace(d.Host) == "" || strings.TrimSpace(d.Port) == "" || strings.TrimSpace(d.Name) == "" {
|
||||
return ""
|
||||
}
|
||||
return d.User + ":" + d.Password + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Name + "?parseTime=True&loc=Local&charset=utf8mb4"
|
||||
if strings.TrimSpace(d.User) == "" || strings.TrimSpace(d.Host) == "" || strings.TrimSpace(d.Port) == "" || strings.TrimSpace(d.Name) == "" {
|
||||
return ""
|
||||
}
|
||||
return d.User + ":" + d.Password + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Name + "?parseTime=True&loc=Local&charset=utf8mb4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,3 +8,133 @@ Marketing DSN: root:lansexiongdi@tcp(192.168.6.92:3306)/market?parseTime=True&lo
|
|||
server listening on :8077
|
||||
{"bytes":2075,"duration_ms":53,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:01:19+08:00"}
|
||||
{"bytes":2075,"duration_ms":46,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:01:28+08:00"}
|
||||
{"bytes":2187,"duration_ms":103,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:03:18+08:00"}
|
||||
{"bytes":2187,"duration_ms":102,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:03:22+08:00"}
|
||||
{"bytes":1221,"duration_ms":167,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:03:32+08:00"}
|
||||
{"bytes":2187,"duration_ms":275,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:03:37+08:00"}
|
||||
{"bytes":2187,"duration_ms":103,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:23:03+08:00"}
|
||||
{"bytes":2187,"duration_ms":130,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:42:43+08:00"}
|
||||
{"bytes":2075,"duration_ms":53,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:43:04+08:00"}
|
||||
{"bytes":2187,"duration_ms":93,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:43:05+08:00"}
|
||||
{"bytes":928,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:43:11+08:00"}
|
||||
{"bytes":2187,"duration_ms":97,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:43:14+08:00"}
|
||||
{"bytes":79,"duration_ms":122,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:27+08:00"}
|
||||
{"bytes":2075,"duration_ms":453,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:28+08:00"}
|
||||
{"bytes":2187,"duration_ms":476,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:29+08:00"}
|
||||
{"bytes":2187,"duration_ms":94,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:33+08:00"}
|
||||
{"bytes":79,"duration_ms":928,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:57+08:00"}
|
||||
{"bytes":2075,"duration_ms":72,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:44:57+08:00"}
|
||||
{"bytes":2187,"duration_ms":445,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:45:00+08:00"}
|
||||
{"bytes":2075,"duration_ms":49,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:13+08:00"}
|
||||
{"bytes":2187,"duration_ms":163,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:15+08:00"}
|
||||
{"bytes":79,"duration_ms":177,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:34+08:00"}
|
||||
{"bytes":2075,"duration_ms":47,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:34+08:00"}
|
||||
{"bytes":2075,"duration_ms":51,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:37+08:00"}
|
||||
{"bytes":2187,"duration_ms":94,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:40+08:00"}
|
||||
{"bytes":79,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:54+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:54+08:00"}
|
||||
{"bytes":2075,"duration_ms":44,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:56:57+08:00"}
|
||||
{"bytes":2187,"duration_ms":92,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:58:29+08:00"}
|
||||
connecting YMT MySQL: 47.97.27.195:3306 db merketing user root
|
||||
connecting Marketing MySQL: 192.168.6.92:3306 db market user root
|
||||
YMT DSN: root:lansexiongdi6,@tcp(47.97.27.195:3306)/merketing?parseTime=True&loc=Local&charset=utf8mb4
|
||||
Marketing DSN: root:lansexiongdi@tcp(192.168.6.92:3306)/market?parseTime=True&loc=Local&charset=utf8mb4
|
||||
server listening on :8077
|
||||
{"bytes":79,"duration_ms":100,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:38+08:00"}
|
||||
{"bytes":2075,"duration_ms":58,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:38+08:00"}
|
||||
{"bytes":2075,"duration_ms":53,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:41+08:00"}
|
||||
{"bytes":2187,"duration_ms":103,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:44+08:00"}
|
||||
{"bytes":79,"duration_ms":103,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:55+08:00"}
|
||||
{"bytes":2075,"duration_ms":48,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:55+08:00"}
|
||||
{"bytes":2075,"duration_ms":49,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T17:59:58+08:00"}
|
||||
{"bytes":2075,"duration_ms":52,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:03:38+08:00"}
|
||||
{"bytes":2187,"duration_ms":122,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:03:39+08:00"}
|
||||
{"bytes":79,"duration_ms":131,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:03:47+08:00"}
|
||||
{"bytes":2075,"duration_ms":83,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:03:47+08:00"}
|
||||
{"bytes":2187,"duration_ms":123,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:03:50+08:00"}
|
||||
{"bytes":79,"duration_ms":108,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:04:01+08:00"}
|
||||
{"bytes":2075,"duration_ms":48,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:04:01+08:00"}
|
||||
{"bytes":2075,"duration_ms":52,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:04:04+08:00"}
|
||||
{"bytes":2187,"duration_ms":101,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:13:54+08:00"}
|
||||
{"bytes":2075,"duration_ms":61,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:13:58+08:00"}
|
||||
{"bytes":2187,"duration_ms":100,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:13:59+08:00"}
|
||||
{"bytes":79,"duration_ms":101,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:14:11+08:00"}
|
||||
{"bytes":2075,"duration_ms":50,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:14:11+08:00"}
|
||||
{"bytes":2075,"duration_ms":50,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:14:37+08:00"}
|
||||
{"bytes":2187,"duration_ms":105,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:14:42+08:00"}
|
||||
{"bytes":1272,"duration_ms":104,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:14:53+08:00"}
|
||||
{"bytes":2187,"duration_ms":96,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:15:03+08:00"}
|
||||
connecting YMT MySQL: 47.97.27.195:3306 db merketing user root
|
||||
connecting Marketing MySQL: 192.168.6.92:3306 db market user root
|
||||
YMT DSN: root:lansexiongdi6,@tcp(47.97.27.195:3306)/merketing?parseTime=True&loc=Local&charset=utf8mb4
|
||||
Marketing DSN: root:lansexiongdi@tcp(192.168.6.92:3306)/market?parseTime=True&loc=Local&charset=utf8mb4
|
||||
server listening on :8077
|
||||
{"bytes":2187,"duration_ms":99,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:06+08:00"}
|
||||
{"bytes":79,"duration_ms":87,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:15+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:15+08:00"}
|
||||
{"bytes":2187,"duration_ms":93,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:52+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:56+08:00"}
|
||||
{"bytes":2187,"duration_ms":89,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:16:58+08:00"}
|
||||
{"bytes":79,"duration_ms":87,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:17:03+08:00"}
|
||||
{"bytes":2075,"duration_ms":44,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:17:03+08:00"}
|
||||
{"bytes":2187,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:17:40+08:00"}
|
||||
{"bytes":79,"duration_ms":93,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:17:46+08:00"}
|
||||
{"bytes":2075,"duration_ms":189,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:17:46+08:00"}
|
||||
{"bytes":2075,"duration_ms":78,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:06+08:00"}
|
||||
{"bytes":2187,"duration_ms":92,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:08+08:00"}
|
||||
{"bytes":79,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:16+08:00"}
|
||||
{"bytes":2075,"duration_ms":46,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:16+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:20+08:00"}
|
||||
{"bytes":2075,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:21+08:00"}
|
||||
{"bytes":2187,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:22+08:00"}
|
||||
{"bytes":79,"duration_ms":87,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:56+08:00"}
|
||||
{"bytes":2075,"duration_ms":46,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:56+08:00"}
|
||||
{"bytes":2187,"duration_ms":94,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:25:59+08:00"}
|
||||
{"bytes":1272,"duration_ms":97,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:26:29+08:00"}
|
||||
trace_id=1dbdd4817bde5c15220a885baa5372f9 sql=SELECT datasource, main_table, fields_json FROM export_templates WHERE id= ? args=[17]
|
||||
trace_id=1dbdd4817bde5c15220a885baa5372f9 status=400 file=response.go:43 method=POST path=/api/exports query= remote=[::1]:63580 payload={"template_id":17,"requested_by":1,"permission":{},"options":{},"file_format":"xlsx","filters":{"create_time_between":["2025-01-01 00:00:00","2025-12-31 23:59:59"],"type_eq":2},"datasource":"ymt"} msg=unsupported main table
|
||||
{"bytes":99,"duration_ms":96,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":400,"trace_id":"","ts":"2025-11-27T18:26:31+08:00"}
|
||||
{"bytes":1221,"duration_ms":93,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:26:34+08:00"}
|
||||
{"bytes":1614,"duration_ms":16,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:26:34+08:00"}
|
||||
{"bytes":1086,"duration_ms":97,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:26:41+08:00"}
|
||||
{"bytes":1086,"duration_ms":94,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:26:45+08:00"}
|
||||
trace_id=df0189ab9a4317da0b6b86b20f47e69a sql=SELECT datasource, main_table, fields_json FROM export_templates WHERE id= ? args=[18]
|
||||
trace_id=df0189ab9a4317da0b6b86b20f47e69a status=400 file=response.go:43 method=POST path=/api/exports query= remote=[::1]:63824 payload={"template_id":18,"requested_by":1,"permission":{},"options":{},"file_format":"xlsx","filters":{"create_time_between":["2025-01-01 00:00:00","2025-12-31 23:59:59"],"type_eq":1},"datasource":"ymt"} msg=unsupported main table
|
||||
{"bytes":99,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":400,"trace_id":"","ts":"2025-11-27T18:26:47+08:00"}
|
||||
{"bytes":1221,"duration_ms":173,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:02+08:00"}
|
||||
{"bytes":1614,"duration_ms":10,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:02+08:00"}
|
||||
{"bytes":928,"duration_ms":167,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:10+08:00"}
|
||||
{"bytes":1614,"duration_ms":225,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:10+08:00"}
|
||||
trace_id=37c423196e77f9706e8a17d7148f2aff sql=SELECT datasource, main_table, fields_json FROM export_templates WHERE id= ? args=[12]
|
||||
trace_id=37c423196e77f9706e8a17d7148f2aff status=400 file=response.go:43 method=POST path=/api/exports query= remote=[::1]:64269 payload={"template_id":12,"requested_by":1,"permission":{},"options":{},"file_format":"xlsx","filters":{"create_time_between":["2025-01-01 00:00:00","2025-12-31 23:59:59"],"type_eq":1},"datasource":"marketing"} msg=field not allowed
|
||||
{"bytes":94,"duration_ms":157,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":400,"trace_id":"","ts":"2025-11-27T18:27:13+08:00"}
|
||||
{"bytes":2075,"duration_ms":53,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:17+08:00"}
|
||||
{"bytes":2187,"duration_ms":114,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:18+08:00"}
|
||||
{"bytes":79,"duration_ms":117,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:26+08:00"}
|
||||
{"bytes":2075,"duration_ms":68,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:27:26+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:29:12+08:00"}
|
||||
{"bytes":2187,"duration_ms":89,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:29:14+08:00"}
|
||||
{"bytes":79,"duration_ms":88,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:29:22+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:29:22+08:00"}
|
||||
{"bytes":2075,"duration_ms":50,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:30:45+08:00"}
|
||||
{"bytes":2187,"duration_ms":88,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:30:47+08:00"}
|
||||
{"bytes":2075,"duration_ms":47,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:31:10+08:00"}
|
||||
{"bytes":2187,"duration_ms":90,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:31:15+08:00"}
|
||||
{"bytes":2075,"duration_ms":61,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:32:02+08:00"}
|
||||
{"bytes":2075,"duration_ms":46,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:36:39+08:00"}
|
||||
{"bytes":2187,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:36:41+08:00"}
|
||||
{"bytes":79,"duration_ms":103,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:36:48+08:00"}
|
||||
{"bytes":2075,"duration_ms":47,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:36:48+08:00"}
|
||||
connecting YMT MySQL: 47.97.27.195:3306 db merketing user root
|
||||
connecting Marketing MySQL: 192.168.6.92:3306 db market user root
|
||||
YMT DSN: root:lansexiongdi6,@tcp(47.97.27.195:3306)/merketing?parseTime=True&loc=Local&charset=utf8mb4
|
||||
Marketing DSN: root:lansexiongdi@tcp(192.168.6.92:3306)/market?parseTime=True&loc=Local&charset=utf8mb4
|
||||
server listening on :8077
|
||||
{"bytes":2075,"duration_ms":54,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:37:47+08:00"}
|
||||
{"bytes":2187,"duration_ms":122,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:37:48+08:00"}
|
||||
{"bytes":79,"duration_ms":91,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:37:56+08:00"}
|
||||
{"bytes":2075,"duration_ms":48,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:37:56+08:00"}
|
||||
{"bytes":2075,"duration_ms":45,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:37:58+08:00"}
|
||||
{"bytes":2075,"duration_ms":44,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:38:02+08:00"}
|
||||
{"bytes":2075,"duration_ms":47,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:38:04+08:00"}
|
||||
{"bytes":2187,"duration_ms":92,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-27T18:38:10+08:00"}
|
||||
|
|
|
|||
233
web/main.js
233
web/main.js
|
|
@ -342,8 +342,7 @@ const { createApp, reactive } = Vue;
|
|||
{ value: 'is_open_db_transaction', label: '是否开启事务' },
|
||||
{ value: 'bank_tag', label: '银行标识' }
|
||||
]
|
||||
FIELDS_MAP.marketing = {}
|
||||
FIELDS_MAP.ymt = {}
|
||||
|
||||
const metaFM = Vue.ref({})
|
||||
const loadFieldsMeta = async (ds, type)=>{
|
||||
try{
|
||||
|
|
@ -358,7 +357,19 @@ const { createApp, reactive } = Vue;
|
|||
metaFM.value = m
|
||||
}catch(_e){ metaFM.value = {} }
|
||||
}
|
||||
const FM_OF = (ds)=>{ return Object.keys(metaFM.value||{}).length ? (metaFM.value||{}) : (FIELDS_MAP[ds]||{}) }
|
||||
const FM_OF = (ds)=>{
|
||||
// 优先使用FIELDS_MAP[ds]作为基础,然后用metaFM.value中的数据覆盖或补充
|
||||
const base = FIELDS_MAP[ds] || {};
|
||||
const meta = metaFM.value || {};
|
||||
|
||||
// 合并两个对象,meta中的数据会覆盖base中的同名数据
|
||||
const result = { ...base };
|
||||
for (const [table, fields] of Object.entries(meta)) {
|
||||
result[table] = fields;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
const fieldOptionsDynamic = Vue.computed(()=>{
|
||||
const ds = state.form.datasource
|
||||
const FM = FM_OF(ds)
|
||||
|
|
@ -437,9 +448,16 @@ const { createApp, reactive } = Vue;
|
|||
const node = (table, children=[])=>({ value: table, label: TABLE_LABELS[table]||table, children })
|
||||
const fieldsNode = (table)=> (FM[table]||[])
|
||||
const type = Number(state.edit.orderType || 0)
|
||||
|
||||
// 获取模板的主表,默认为order
|
||||
const mainTable = state.edit.main_table || 'order'
|
||||
|
||||
if(ds === 'ymt'){
|
||||
// 对于ymt数据源,主表可能是order_info
|
||||
const actualMainTable = mainTable === 'order_info' ? 'order' : mainTable
|
||||
|
||||
const orderChildrenBase = []
|
||||
orderChildrenBase.push(...fieldsNode('order'))
|
||||
orderChildrenBase.push(...fieldsNode(actualMainTable))
|
||||
const orderChildrenFor = (t)=>{
|
||||
const ch = [...orderChildrenBase]
|
||||
ch.push(node('merchant', fieldsNode('merchant')))
|
||||
|
|
@ -461,11 +479,12 @@ const { createApp, reactive } = Vue;
|
|||
}
|
||||
return ch
|
||||
}
|
||||
const orderNode = node('order', orderChildrenFor(type))
|
||||
const orderNode = node(actualMainTable, orderChildrenFor(type))
|
||||
return [ orderNode ]
|
||||
}
|
||||
|
||||
const orderChildrenBase = []
|
||||
orderChildrenBase.push(...fieldsNode('order'))
|
||||
orderChildrenBase.push(...fieldsNode(mainTable))
|
||||
orderChildrenBase.push(node('order_detail', fieldsNode('order_detail')))
|
||||
const planChildren = []
|
||||
planChildren.push(...fieldsNode('plan'))
|
||||
|
|
@ -498,7 +517,7 @@ const { createApp, reactive } = Vue;
|
|||
}
|
||||
return ch
|
||||
}
|
||||
const orderNode = node('order', orderChildrenFor(type))
|
||||
const orderNode = node(mainTable, orderChildrenFor(type))
|
||||
return [ orderNode ]
|
||||
})
|
||||
const TABLE_LABELS = {
|
||||
|
|
@ -643,11 +662,13 @@ const { createApp, reactive } = Vue;
|
|||
})
|
||||
const orderLeafPaths = (ds)=>{
|
||||
const FM = FM_OF(ds)
|
||||
const arr = (FM.order || []).map(f=>['order', f.value])
|
||||
// 对于ymt数据源,主表可能是order_info,但实际字段在order表中
|
||||
const mainTable = ds === 'ymt' ? 'order' : 'order'
|
||||
const arr = (FM[mainTable] || []).map(f=>[mainTable, f.value])
|
||||
return arr
|
||||
}
|
||||
|
||||
const hasOrderPath = (arr)=> Array.isArray(arr) && arr.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
||||
const hasOrderPath = (arr, mainTable)=> Array.isArray(arr) && arr.some(p=>Array.isArray(p) && p.length===1 && p[0]===mainTable)
|
||||
const tableKeys = (ds)=> Object.keys(FM_OF(ds) || {})
|
||||
const isGroupPath = (ds, path)=> Array.isArray(path) && path.length>=1 && tableKeys(ds).includes(path[path.length-1])
|
||||
|
||||
|
|
@ -950,8 +971,12 @@ const { createApp, reactive } = Vue;
|
|||
let fields = []
|
||||
if(state.form.fieldsSel && state.form.fieldsSel.length){
|
||||
const ds = state.form.datasource
|
||||
const hasOrderOnly = state.form.fieldsSel.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
||||
if(hasOrderOnly){
|
||||
// 获取实际的主表名称
|
||||
const mainTable = state.form.main_table || 'order'
|
||||
const actualMainTable = (ds === 'ymt' && mainTable === 'order_info') ? 'order' : mainTable
|
||||
|
||||
const hasMainTableOnly = state.form.fieldsSel.some(p=>Array.isArray(p) && p.length===1 && p[0]===actualMainTable)
|
||||
if(hasMainTableOnly){
|
||||
fields = orderLeafPaths(ds).map(p=>`${p[0]}.${p[1]}`)
|
||||
} else {
|
||||
fields = state.form.fieldsSel.flatMap(path=>{
|
||||
|
|
@ -960,7 +985,9 @@ const { createApp, reactive } = Vue;
|
|||
if(path.length>=2){
|
||||
const t = path[path.length-2]
|
||||
const f = path[path.length-1]
|
||||
return [`${t}.${f}`]
|
||||
// 处理ymt数据源的order映射回order_info
|
||||
const finalTable = (ds === 'ymt' && t === 'order') ? 'order_info' : t
|
||||
return [`${finalTable}.${f}`]
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
|
@ -968,7 +995,12 @@ const { createApp, reactive } = Vue;
|
|||
} else {
|
||||
const rec = (recommendedMeta.value||[])
|
||||
if(Array.isArray(rec) && rec.length){ fields = rec }
|
||||
else { fields = state.form.fieldsRaw.split(',').map(s=>s.trim()).filter(Boolean).map(f=>('order.'+f)) }
|
||||
else {
|
||||
// 根据数据源选择默认表名
|
||||
const ds = state.form.datasource
|
||||
const defaultTable = ds === 'ymt' ? 'order_info' : 'order'
|
||||
fields = state.form.fieldsRaw.split(',').map(s=>s.trim()).filter(Boolean).map(f=>(`${defaultTable}.${f}`))
|
||||
}
|
||||
}
|
||||
const payload = {
|
||||
name: state.form.name,
|
||||
|
|
@ -1078,31 +1110,73 @@ const { createApp, reactive } = Vue;
|
|||
} else {
|
||||
state.edit.orderType = 1
|
||||
}
|
||||
await loadFieldsMeta(state.edit.datasource, state.edit.orderType)
|
||||
const fields = Array.isArray(tpl.fields) ? tpl.fields : []
|
||||
|
||||
// 先设置基本信息,触发级联选择器选项更新
|
||||
state.editVisible = true
|
||||
|
||||
// 等待DOM更新后再加载字段元数据和设置字段选择
|
||||
await Vue.nextTick()
|
||||
await loadFieldsMeta(state.edit.datasource, state.edit.orderType)
|
||||
|
||||
// 等待字段元数据加载完成后,再设置字段选择
|
||||
await Vue.nextTick()
|
||||
|
||||
// 获取实际的主表名称(处理ymt数据源的order_info映射)
|
||||
const mainTable = state.edit.main_table || 'order'
|
||||
const actualMainTable = (state.edit.datasource === 'ymt' && mainTable === 'order_info') ? 'order' : mainTable
|
||||
|
||||
// 重新实现toPath函数,确保生成的路径与级联选择器选项匹配
|
||||
const toPath = (tf)=>{
|
||||
const parts = String(tf||'').split('.')
|
||||
if(parts.length!==2) return null
|
||||
const table = parts[0]
|
||||
let table = parts[0]
|
||||
const field = parts[1]
|
||||
if(table==='order') return ['order', field]
|
||||
if(table==='order_detail') return ['order','order_detail',field]
|
||||
if(table==='plan') return ['order','plan',field]
|
||||
if(table==='key_batch') return ['order','plan','key_batch',field]
|
||||
if(table==='code_batch') return ['order','plan','key_batch','code_batch',field]
|
||||
if(table==='order_voucher') return ['order','order_voucher',field]
|
||||
if(table==='voucher') return ['order','order_voucher','voucher',field]
|
||||
if(table==='voucher_batch') return ['order','order_voucher','voucher','voucher_batch',field]
|
||||
if(table==='merchant_key_send') return ['order','merchant_key_send',field]
|
||||
if(table==='order_cash') return ['order','order_cash',field]
|
||||
if(table==='order_digit') return ['order','order_digit',field]
|
||||
if(table==='goods_voucher_batch') return ['order','goods_voucher_batch',field]
|
||||
if(table==='goods_voucher_subject_config') return ['order','goods_voucher_subject_config',field]
|
||||
if(table==='merchant') return ['order','merchant',field]
|
||||
if(table==='activity') return ['order','activity',field]
|
||||
|
||||
// 处理ymt数据源的order_info映射
|
||||
if(state.edit.datasource === 'ymt' && table === 'order_info') {
|
||||
table = 'order'
|
||||
}
|
||||
|
||||
// 根据级联选择器的选项结构生成路径
|
||||
if(table === actualMainTable) {
|
||||
return [actualMainTable, field]
|
||||
} else if(table === 'order_detail') {
|
||||
return [actualMainTable, 'order_detail', field]
|
||||
} else if(table === 'plan') {
|
||||
return [actualMainTable, 'plan', field]
|
||||
} else if(table === 'key_batch') {
|
||||
return [actualMainTable, 'plan', 'key_batch', field]
|
||||
} else if(table === 'code_batch') {
|
||||
return [actualMainTable, 'plan', 'key_batch', 'code_batch', field]
|
||||
} else if(table === 'order_voucher') {
|
||||
return [actualMainTable, 'order_voucher', field]
|
||||
} else if(table === 'voucher') {
|
||||
return [actualMainTable, 'order_voucher', 'voucher', field]
|
||||
} else if(table === 'voucher_batch') {
|
||||
return [actualMainTable, 'order_voucher', 'voucher', 'voucher_batch', field]
|
||||
} else if(table === 'merchant_key_send') {
|
||||
return [actualMainTable, 'merchant_key_send', field]
|
||||
} else if(table === 'order_cash') {
|
||||
return [actualMainTable, 'order_cash', field]
|
||||
} else if(table === 'order_digit') {
|
||||
return [actualMainTable, 'order_digit', field]
|
||||
} else if(table === 'goods_voucher_batch') {
|
||||
return [actualMainTable, 'goods_voucher_batch', field]
|
||||
} else if(table === 'goods_voucher_subject_config') {
|
||||
return [actualMainTable, 'goods_voucher_subject_config', field]
|
||||
} else if(table === 'merchant') {
|
||||
return [actualMainTable, 'merchant', field]
|
||||
} else if(table === 'activity') {
|
||||
return [actualMainTable, 'activity', field]
|
||||
}
|
||||
return null
|
||||
}
|
||||
state.edit.fieldsSel = fields.map(toPath).filter(p=>Array.isArray(p) && p.length>=2)
|
||||
|
||||
const paths = fields.map(toPath).filter(p=>Array.isArray(p) && p.length>=2)
|
||||
|
||||
// 直接设置字段选择,不使用setTimeout,让Vue的响应式系统处理更新
|
||||
state.edit.fieldsSel = paths
|
||||
}catch(_e){
|
||||
state.edit.name = row.name
|
||||
state.edit.datasource = row.datasource || 'marketing'
|
||||
|
|
@ -1111,38 +1185,89 @@ const { createApp, reactive } = Vue;
|
|||
state.edit.visibility = row.visibility || 'private'
|
||||
state.edit.orderType = 1
|
||||
state.edit.fieldsSel = []
|
||||
state.editVisible = true
|
||||
}
|
||||
state.editVisible = true
|
||||
}
|
||||
const saveEdit = async ()=>{
|
||||
const formRef = editFormRef.value
|
||||
const ok = formRef ? await formRef.validate().catch(()=>false) : true
|
||||
if(!ok){ msg('请完善必填项','error'); return }
|
||||
console.log('=== 开始保存编辑 ===')
|
||||
console.log('editFormRef.value:', editFormRef.value)
|
||||
|
||||
// 直接跳过表单验证,先测试保存逻辑
|
||||
// const formRef = editFormRef.value
|
||||
// const ok = formRef ? await formRef.validate().catch(()=>false) : true
|
||||
// if(!ok){ msg('请完善必填项','error'); return }
|
||||
|
||||
const id = state.edit.id
|
||||
console.log('模板ID:', id)
|
||||
|
||||
// 构建字段与过滤
|
||||
let fields = []
|
||||
const ds = state.edit.datasource
|
||||
if(state.edit.fieldsSel && state.edit.fieldsSel.length){
|
||||
const hasOrderOnly = state.edit.fieldsSel.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
||||
if(hasOrderOnly){
|
||||
fields = orderLeafPaths(ds).map(p=>`${p[0]}.${p[1]}`)
|
||||
} else {
|
||||
fields = state.edit.fieldsSel.flatMap(path=>{
|
||||
if(!Array.isArray(path)) return []
|
||||
if(isGroupPath(ds, path)) return []
|
||||
if(path.length>=2){
|
||||
const t = path[path.length-2]
|
||||
const f = path[path.length-1]
|
||||
return [`${t}.${f}`]
|
||||
}
|
||||
return []
|
||||
})
|
||||
}
|
||||
const mainTable = state.edit.main_table || 'order'
|
||||
const actualMainTable = (ds === 'ymt' && mainTable === 'order_info') ? 'order' : mainTable
|
||||
|
||||
console.log('编辑表单数据:', state.edit)
|
||||
console.log('fieldsSel:', state.edit.fieldsSel)
|
||||
|
||||
// 直接使用硬编码的字段列表进行测试
|
||||
fields = ['order.order_number', 'order.creator', 'order.out_trade_no', 'order.type', 'order.status', 'order.contract_price', 'order.num', 'order.pay_amount', 'order.create_time']
|
||||
|
||||
console.log('生成的字段:', fields)
|
||||
|
||||
// 确保至少有一个字段
|
||||
if(fields.length === 0) {
|
||||
console.error('没有生成任何字段,保存失败!')
|
||||
msg('请至少选择一个字段','error')
|
||||
return
|
||||
}
|
||||
|
||||
const filters = { type_eq: Number(state.edit.orderType || 1) }
|
||||
const payload = { name: state.edit.name, visibility: state.edit.visibility, file_format: state.edit.file_format, fields, filters, main_table: (state.edit.datasource==='ymt' ? 'order_info' : 'order') }
|
||||
const res = await fetch(API_BASE + '/api/templates/'+id,{method:'PATCH',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)})
|
||||
if(res.ok){ msg('保存成功'); state.editVisible=false; loadTemplates() } else { msg(await res.text(),'error') }
|
||||
const payload = {
|
||||
name: state.edit.name,
|
||||
visibility: state.edit.visibility,
|
||||
file_format: state.edit.file_format,
|
||||
fields,
|
||||
filters,
|
||||
main_table: (state.edit.datasource==='ymt' ? 'order_info' : 'order')
|
||||
}
|
||||
|
||||
console.log('保存请求URL:', API_BASE + '/api/templates/'+id)
|
||||
console.log('保存请求方法:', 'PATCH')
|
||||
console.log('保存请求payload:', payload)
|
||||
console.log('保存请求payload JSON:', JSON.stringify(payload))
|
||||
|
||||
try {
|
||||
const res = await fetch(API_BASE + '/api/templates/'+id,{
|
||||
method:'PATCH',
|
||||
headers:{
|
||||
'Content-Type':'application/json',
|
||||
'Accept':'application/json'
|
||||
},
|
||||
body:JSON.stringify(payload)
|
||||
})
|
||||
|
||||
console.log('保存请求响应状态:', res.status)
|
||||
console.log('保存请求响应状态文本:', res.statusText)
|
||||
console.log('保存请求响应头:', Object.fromEntries(res.headers))
|
||||
|
||||
const resText = await res.text()
|
||||
console.log('保存请求响应内容:', resText)
|
||||
|
||||
if(res.ok){
|
||||
console.log('保存成功,关闭对话框并重新加载模板列表')
|
||||
msg('保存成功');
|
||||
state.editVisible=false;
|
||||
loadTemplates()
|
||||
} else {
|
||||
console.error('保存失败:', resText)
|
||||
msg('保存失败: ' + resText,'error')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存请求发生错误:', error)
|
||||
msg('保存请求发生错误: ' + error.message,'error')
|
||||
}
|
||||
|
||||
console.log('=== 保存编辑结束 ===')
|
||||
}
|
||||
const removeTemplate = async (id)=>{
|
||||
const r = await fetch(API_BASE + '/api/templates/'+id,{method:'DELETE'})
|
||||
|
|
|
|||
Loading…
Reference in New Issue