package model import ( "context" "database/sql" "fmt" "strings" "time" "github.com/zeromicro/go-zero/core/stores/sqlx" ) // TConfig is one dynamic configuration row. Hot-reloadable audit settings // (MinIO endpoint/keys, log level, archive threshold, HMAC secret) are // stored here and read back on every request by the audit middleware. type TConfig struct { Id int64 `db:"id"` // 主键 ConfigItem string `db:"config_item"` // 配置项 ConfigValue string `db:"config_value"` // 配置值 EditFlag int64 `db:"edit_flag"` // 是否允许编辑,1是不可编辑configItem,2是所有均可编辑 Description sql.NullString `db:"description"` // 描述 UpdatedBy string `db:"updated_by"` // 最后更新人 UpdatedAt time.Time `db:"updated_at"` // 配置更新时间 } type TConfigModel interface { // FindAll returns every configuration row ordered by id. FindAll(ctx context.Context) ([]TConfig, error) // Config management APIs (ported from sdf-serve applicationConfig). Insert(ctx context.Context, data *TConfig) (sql.Result, error) FindOne(ctx context.Context, id int64) (*TConfig, error) FindOneByConfigItem(ctx context.Context, configItem string) (*TConfig, error) Update(ctx context.Context, data *TConfig) error Delete(ctx context.Context, id int64) error FindPage(ctx context.Context, page, pageSize int64, configItem, description string) ([]TConfig, int64, error) } type customTConfigModel struct { conn sqlx.SqlConn table string } var _ TConfigModel = (*customTConfigModel)(nil) // NewTConfigModel returns the model for the t_config table. func NewTConfigModel(conn sqlx.SqlConn) TConfigModel { return &customTConfigModel{ conn: conn, table: "`t_config`", } } // tConfigRows is the full column list of t_config. var tConfigRows = strings.Join([]string{ "`id`", "`config_item`", "`config_value`", "`edit_flag`", "`description`", "`updated_by`", "`updated_at`", }, ", ") func (m *customTConfigModel) FindAll(ctx context.Context) ([]TConfig, error) { var resp []TConfig query := fmt.Sprintf("select %s from %s order by `id` asc", tConfigRows, m.table) if err := m.conn.QueryRowsCtx(ctx, &resp, query); err != nil { return nil, err } return resp, nil } // Insert stores one configuration row; updated_at is filled by // DEFAULT CURRENT_TIMESTAMP and refreshes via ON UPDATE. func (m *customTConfigModel) Insert(ctx context.Context, data *TConfig) (sql.Result, error) { query := fmt.Sprintf("insert into %s (`config_item`, `config_value`, `edit_flag`, `description`, `updated_by`) values (?, ?, ?, ?, ?)", m.table) return m.conn.ExecCtx(ctx, query, data.ConfigItem, data.ConfigValue, data.EditFlag, data.Description, data.UpdatedBy) } // FindOne looks a config row up by its auto-increment id. func (m *customTConfigModel) FindOne(ctx context.Context, id int64) (*TConfig, error) { query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", tConfigRows, m.table) var resp TConfig switch err := m.conn.QueryRowCtx(ctx, &resp, query, id); err { case nil: return &resp, nil case sqlx.ErrNotFound: return nil, ErrNotFound default: return nil, err } } // FindOneByConfigItem looks a config row up by its unique config_item. func (m *customTConfigModel) FindOneByConfigItem(ctx context.Context, configItem string) (*TConfig, error) { query := fmt.Sprintf("select %s from %s where `config_item` = ? limit 1", tConfigRows, m.table) var resp TConfig switch err := m.conn.QueryRowCtx(ctx, &resp, query, configItem); err { case nil: return &resp, nil case sqlx.ErrNotFound: return nil, ErrNotFound default: return nil, err } } // Update writes the mutable fields; updated_at refreshes via the table's // ON UPDATE CURRENT_TIMESTAMP. func (m *customTConfigModel) Update(ctx context.Context, data *TConfig) error { query := fmt.Sprintf("update %s set `config_item` = ?, `config_value` = ?, `edit_flag` = ?, `description` = ?, `updated_by` = ? where `id` = ?", m.table) _, err := m.conn.ExecCtx(ctx, query, data.ConfigItem, data.ConfigValue, data.EditFlag, data.Description, data.UpdatedBy, data.Id) return err } // Delete removes the configuration row by its id. func (m *customTConfigModel) Delete(ctx context.Context, id int64) error { query := fmt.Sprintf("delete from %s where `id` = ?", m.table) _, err := m.conn.ExecCtx(ctx, query, id) return err } // FindPage returns one page of rows ordered by id with the total count. // Empty configItem means no item filter; description matches by LIKE. func (m *customTConfigModel) FindPage(ctx context.Context, page, pageSize int64, configItem, description string) ([]TConfig, int64, error) { var conds []string var args []any if configItem != "" { conds = append(conds, "`config_item` = ?") args = append(args, configItem) } if keyword, ok := trimKeyword(description); ok { conds = append(conds, "`description` like ? escape '\\\\'") args = append(args, "%"+escapeLike(keyword)+"%") } where := "" if len(conds) > 0 { where = " where " + strings.Join(conds, " and ") } var total int64 if err := m.conn.QueryRowCtx(ctx, &total, fmt.Sprintf("select count(*) from %s%s", m.table, where), args...); err != nil { return nil, 0, err } if total == 0 { return nil, 0, nil } offset := (page - 1) * pageSize args = append(args, pageSize, offset) query := fmt.Sprintf("select %s from %s%s order by `id` limit ? offset ?", tConfigRows, m.table, where) var resp []TConfig if err := m.conn.QueryRowsCtx(ctx, &resp, query, args...); err != nil { return nil, 0, err } return resp, total, nil } // trimKeyword reports whether a keyword carries any non-space character. func trimKeyword(s string) (string, bool) { trimmed := strings.TrimSpace(s) return trimmed, trimmed != "" }