From 8513cbce5566965c28a1ca51da0672e73bc8aa0f Mon Sep 17 00:00:00 2001 From: skyle1995 Date: Sun, 26 Oct 2025 00:08:55 +0800 Subject: [PATCH] Add application variables --- controllers/admin/api.go | 8 +- controllers/admin/variable.go | 429 +++++++++++++++++++++++++++ database/migrate.go | 2 +- models/api.go | 15 + models/variable.go | 61 ++++ server/admin.go | 16 +- utils/logger/http.go | 13 +- web/template/admin/apis.html | 37 ++- web/template/admin/layout.html | 1 + web/template/admin/variables.html | 464 ++++++++++++++++++++++++++++++ 10 files changed, 1020 insertions(+), 26 deletions(-) create mode 100644 controllers/admin/variable.go create mode 100644 models/variable.go create mode 100644 web/template/admin/variables.html diff --git a/controllers/admin/api.go b/controllers/admin/api.go index 1f41584..2b1415f 100644 --- a/controllers/admin/api.go +++ b/controllers/admin/api.go @@ -168,7 +168,7 @@ func APIUpdateHandler(w http.ResponseWriter, r *http.Request) { } var req struct { - ID uint `json:"id"` + UUID string `json:"uuid"` Status int `json:"status"` SubmitAlgorithm int `json:"submit_algorithm"` ReturnAlgorithm int `json:"return_algorithm"` @@ -184,8 +184,8 @@ func APIUpdateHandler(w http.ResponseWriter, r *http.Request) { } // 验证必填字段 - if req.ID == 0 { - http.Error(w, "接口ID不能为空", http.StatusBadRequest) + if strings.TrimSpace(req.UUID) == "" { + http.Error(w, "接口UUID不能为空", http.StatusBadRequest) return } @@ -209,7 +209,7 @@ func APIUpdateHandler(w http.ResponseWriter, r *http.Request) { // 查找并更新API记录 var api models.API - if err := db.First(&api, req.ID).Error; err != nil { + if err := db.Where("uuid = ?", strings.TrimSpace(req.UUID)).First(&api).Error; err != nil { http.Error(w, "接口不存在", http.StatusNotFound) return } diff --git a/controllers/admin/variable.go b/controllers/admin/variable.go new file mode 100644 index 0000000..e0db73e --- /dev/null +++ b/controllers/admin/variable.go @@ -0,0 +1,429 @@ +package admin + +import ( + "encoding/json" + "net/http" + "networkDev/database" + "networkDev/models" + "networkDev/utils" + "regexp" + "strconv" + "strings" + + "github.com/sirupsen/logrus" +) + +// VariableFragmentHandler 变量列表页面片段处理器 +func VariableFragmentHandler(w http.ResponseWriter, r *http.Request) { + utils.RenderTemplate(w, "variables", map[string]interface{}{ + "Title": "变量管理", + }) +} + +// VariableListHandler 变量列表API处理器 +func VariableListHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + // 获取分页参数 + page, _ := strconv.Atoi(r.URL.Query().Get("page")) + if page <= 0 { + page = 1 + } + limit, _ := strconv.Atoi(r.URL.Query().Get("limit")) + if limit <= 0 { + limit = 10 + } + + // 获取应用UUID参数(用于按应用筛选变量) + appUUID := strings.TrimSpace(r.URL.Query().Get("app_uuid")) + + // 获取别名搜索参数 + alias := strings.TrimSpace(r.URL.Query().Get("alias")) + + // 构建查询 + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // 构建基础查询 + query := db.Model(&models.Variable{}) + + // 如果指定了应用UUID,则按应用筛选 + if appUUID != "" { + query = query.Where("app_uuid = ?", appUUID) + } + + // 如果指定了别名搜索,则按别名模糊搜索 + if alias != "" { + query = query.Where("alias LIKE ?", "%"+alias+"%") + } + + // 获取总数 + var total int64 + if err := query.Count(&total).Error; err != nil { + logrus.WithError(err).Error("Failed to count variables") + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // 获取分页数据 + var variables []models.Variable + offset := (page - 1) * limit + if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&variables).Error; err != nil { + logrus.WithError(err).Error("Failed to fetch variables") + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // 获取关联的应用信息 + var appUUIDs []string + for _, variable := range variables { + appUUIDs = append(appUUIDs, variable.AppUUID) + } + + var apps []models.App + if len(appUUIDs) > 0 { + if err := db.Where("uuid IN ?", appUUIDs).Find(&apps).Error; err != nil { + logrus.WithError(err).Error("Failed to fetch related apps") + } + } + + // 创建应用UUID到应用名称的映射 + appMap := make(map[string]string) + for _, app := range apps { + appMap[app.UUID] = app.Name + } + + // 构建响应数据 + type VariableResponse struct { + ID uint `json:"id"` + UUID string `json:"uuid"` + Number string `json:"number"` + AppUUID string `json:"app_uuid"` + AppName string `json:"app_name"` + Alias string `json:"alias"` + Data string `json:"data"` + Remark string `json:"remark"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + } + + var responseData []VariableResponse + for _, variable := range variables { + appName := appMap[variable.AppUUID] + if appName == "" { + appName = "未知应用" + } + + responseData = append(responseData, VariableResponse{ + ID: variable.ID, + UUID: variable.UUID, + Number: variable.Number, + AppUUID: variable.AppUUID, + AppName: appName, + Alias: variable.Alias, + Data: variable.Data, + Remark: variable.Remark, + CreatedAt: variable.CreatedAt.Format("2006-01-02 15:04:05"), + UpdatedAt: variable.UpdatedAt.Format("2006-01-02 15:04:05"), + }) + } + + response := map[string]interface{}{ + "code": 0, + "msg": "success", + "count": total, + "data": responseData, + } + + w.Header().Set("Content-Type", "application/json") + utils.WriteJSONResponse(w, http.StatusOK, response) +} + +// VariableCreateHandler 新增变量API处理器 +func VariableCreateHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + AppUUID string `json:"app_uuid"` + Alias string `json:"alias"` + Data string `json:"data"` + Remark string `json:"remark"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + logrus.WithError(err).Error("Failed to decode JSON request") + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + // 验证必填字段 + if strings.TrimSpace(req.AppUUID) == "" { + http.Error(w, "应用UUID不能为空", http.StatusBadRequest) + return + } + if strings.TrimSpace(req.Alias) == "" { + http.Error(w, "变量别名不能为空", http.StatusBadRequest) + return + } + + // 验证别名格式:必须以英文字母开头,只能包含数字和英文字母 + aliasPattern := regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9]*$`) + if !aliasPattern.MatchString(req.Alias) { + http.Error(w, "别名必须以英文字母开头,只能包含数字和英文字母", http.StatusBadRequest) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "数据库连接失败", http.StatusInternalServerError) + return + } + + // 验证应用是否存在 + var app models.App + if err := db.Where("uuid = ?", req.AppUUID).First(&app).Error; err != nil { + http.Error(w, "应用不存在", http.StatusBadRequest) + return + } + + // 创建变量 + variable := models.Variable{ + AppUUID: strings.TrimSpace(req.AppUUID), + Alias: strings.TrimSpace(req.Alias), + Data: req.Data, + Remark: strings.TrimSpace(req.Remark), + } + + if err := db.Create(&variable).Error; err != nil { + logrus.WithError(err).Error("Failed to create variable") + http.Error(w, "创建变量失败", http.StatusInternalServerError) + return + } + + response := map[string]interface{}{ + "code": 0, + "msg": "创建成功", + "data": variable, + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + +// VariableUpdateHandler 更新变量API处理器 +func VariableUpdateHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + UUID string `json:"uuid"` + AppUUID string `json:"app_uuid"` + Alias string `json:"alias"` + Data string `json:"data"` + Remark string `json:"remark"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + // 验证必填字段 + if strings.TrimSpace(req.UUID) == "" { + http.Error(w, "变量UUID不能为空", http.StatusBadRequest) + return + } + if strings.TrimSpace(req.AppUUID) == "" { + http.Error(w, "应用UUID不能为空", http.StatusBadRequest) + return + } + if strings.TrimSpace(req.Alias) == "" { + http.Error(w, "变量别名不能为空", http.StatusBadRequest) + return + } + + // 验证别名格式:必须以英文字母开头,只能包含数字和英文字母 + aliasPattern := regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9]*$`) + if !aliasPattern.MatchString(req.Alias) { + http.Error(w, "别名必须以英文字母开头,只能包含数字和英文字母", http.StatusBadRequest) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "数据库连接失败", http.StatusInternalServerError) + return + } + + // 验证应用是否存在 + var app models.App + if err := db.Where("uuid = ?", req.AppUUID).First(&app).Error; err != nil { + http.Error(w, "应用不存在", http.StatusBadRequest) + return + } + + // 通过uuid字段查找变量 + var variable models.Variable + if err := db.Where("uuid = ?", strings.TrimSpace(req.UUID)).First(&variable).Error; err != nil { + http.Error(w, "变量不存在", http.StatusNotFound) + return + } + + // 更新字段 + variable.AppUUID = strings.TrimSpace(req.AppUUID) + variable.Alias = strings.TrimSpace(req.Alias) + variable.Data = req.Data + variable.Remark = strings.TrimSpace(req.Remark) + + if err := db.Save(&variable).Error; err != nil { + logrus.WithError(err).Error("Failed to update variable") + http.Error(w, "更新变量失败", http.StatusInternalServerError) + return + } + + response := map[string]interface{}{ + "code": 0, + "msg": "更新成功", + "data": variable, + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + +// VariableDeleteHandler 删除变量API处理器 +func VariableDeleteHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + ID uint `json:"id"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + if req.ID == 0 { + http.Error(w, "变量ID不能为空", http.StatusBadRequest) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "数据库连接失败", http.StatusInternalServerError) + return + } + + // 删除变量 + if err := db.Delete(&models.Variable{}, req.ID).Error; err != nil { + logrus.WithError(err).Error("Failed to delete variable") + http.Error(w, "删除变量失败", http.StatusInternalServerError) + return + } + + logrus.WithField("variable_id", req.ID).Info("Successfully deleted variable") + + response := map[string]interface{}{ + "code": 0, + "msg": "删除成功", + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + +// VariablesBatchDeleteHandler 批量删除变量API处理器 +func VariablesBatchDeleteHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + IDs []uint `json:"ids"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + if len(req.IDs) == 0 { + http.Error(w, "请选择要删除的变量", http.StatusBadRequest) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "数据库连接失败", http.StatusInternalServerError) + return + } + + // 批量删除变量 + if err := db.Delete(&models.Variable{}, req.IDs).Error; err != nil { + logrus.WithError(err).Error("Failed to batch delete variables") + http.Error(w, "批量删除失败", http.StatusInternalServerError) + return + } + + logrus.WithField("variable_ids", req.IDs).Info("Successfully batch deleted variables") + + response := map[string]interface{}{ + "code": 0, + "msg": "批量删除成功", + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + +// VariableGetAppsHandler 获取应用列表(用于筛选下拉框) +func VariableGetAppsHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + var apps []models.App + if err := db.Select("uuid, name").Find(&apps).Error; err != nil { + logrus.WithError(err).Error("Failed to fetch apps") + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + response := map[string]interface{}{ + "code": 0, + "msg": "success", + "data": apps, + } + + w.Header().Set("Content-Type", "application/json") + utils.WriteJSONResponse(w, http.StatusOK, response) +} \ No newline at end of file diff --git a/database/migrate.go b/database/migrate.go index b652bae..a05b2e9 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -17,7 +17,7 @@ func AutoMigrate() error { if err != nil { return err } - if err := db.AutoMigrate(&models.User{}, &models.Settings{}, &models.App{}, &models.API{}); err != nil { + if err := db.AutoMigrate(&models.User{}, &models.Settings{}, &models.App{}, &models.API{}, &models.Variable{}); err != nil { logrus.WithError(err).Error("AutoMigrate 执行失败") return err } diff --git a/models/api.go b/models/api.go index 89fae2d..9cf7698 100644 --- a/models/api.go +++ b/models/api.go @@ -1,7 +1,11 @@ package models import ( + "strings" "time" + + "github.com/google/uuid" + "gorm.io/gorm" ) // API 接口表模型 @@ -13,6 +17,9 @@ type API struct { // ID:主键,自增 ID uint `gorm:"primaryKey;comment:API接口ID,自增主键" json:"id"` + // UUID:API接口唯一标识符,自动生成 + UUID string `gorm:"uniqueIndex;size:36;not null;comment:API接口UUID,唯一标识符" json:"uuid"` + // API类型(int型) APIType int `gorm:"not null;comment:API类型" json:"api_type"` @@ -47,6 +54,14 @@ type API struct { UpdatedAt time.Time `gorm:"comment:更新时间" json:"updated_at"` } +// BeforeCreate 在创建记录前自动生成UUID +func (api *API) BeforeCreate(tx *gorm.DB) error { + if api.UUID == "" { + api.UUID = strings.ToUpper(uuid.New().String()) + } + return nil +} + // TableName 指定表名 func (API) TableName() string { return "apis" diff --git a/models/variable.go b/models/variable.go new file mode 100644 index 0000000..a9b248e --- /dev/null +++ b/models/variable.go @@ -0,0 +1,61 @@ +package models + +import ( + "strings" + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +// Variable 变量表模型 +// 用于管理应用程序的变量数据 +// UUID 为变量的唯一标识符,自动生成并转换为大写 +// Alias 为变量别名,便于识别和管理 +// Data 为变量数据内容 +// Remark 为备注信息,用于描述变量用途 +// CreatedAt/UpdatedAt 由 GORM 自动维护 + +type Variable struct { + // ID:主键,自增 + ID uint `gorm:"primaryKey;comment:变量ID,自增主键" json:"id"` + + // UUID:变量的唯一标识符,36位字符串 + UUID string `gorm:"uniqueIndex;size:36;not null;comment:变量的唯一标识符" json:"uuid"` + + // Number:变量编号,时间戳+6位随机数字格式 + Number string `gorm:"uniqueIndex;size:20;not null;comment:变量编号,时间戳+6位随机数字格式" json:"number"` + + // AppUUID:关联的应用UUID + AppUUID string `gorm:"size:36;not null;index;comment:关联的应用UUID" json:"app_uuid"` + + // Alias:变量别名,便于识别和管理 + Alias string `gorm:"size:100;not null;comment:变量别名" json:"alias"` + + // Data:变量数据内容 + Data string `gorm:"type:text;comment:变量数据" json:"data"` + + // Remark:备注信息,用于描述变量用途 + Remark string `gorm:"type:text;comment:备注信息" json:"remark"` + + // 时间字段 + CreatedAt time.Time `gorm:"comment:创建时间" json:"created_at"` + UpdatedAt time.Time `gorm:"comment:更新时间" json:"updated_at"` +} + +// BeforeCreate 在创建记录前自动生成UUID和Number +func (variable *Variable) BeforeCreate(tx *gorm.DB) error { + // 生成UUID + if variable.UUID == "" { + variable.UUID = strings.ToUpper(uuid.New().String()) + } + + // 生成Number:使用时间戳格式 + variable.Number = time.Now().Format("20060102150405") + return nil +} + +// TableName 指定表名 +func (Variable) TableName() string { + return "variables" +} \ No newline at end of file diff --git a/server/admin.go b/server/admin.go index 57c9150..3e3e9ea 100644 --- a/server/admin.go +++ b/server/admin.go @@ -44,12 +44,17 @@ func RegisterAdminRoutes(mux *http.ServeMux) { mux.HandleFunc("/admin/settings", adminctl.AdminAuthRequired(adminctl.SettingsFragmentHandler)) mux.HandleFunc("/admin/apps", adminctl.AdminAuthRequired(adminctl.AppsFragmentHandler)) mux.HandleFunc("/admin/apis", adminctl.AdminAuthRequired(adminctl.APIFragmentHandler)) + mux.HandleFunc("/admin/variables", adminctl.AdminAuthRequired(adminctl.VariableFragmentHandler)) + + // 系统信息API(用于仪表盘定时刷新) + mux.HandleFunc("/admin/api/system/info", adminctl.AdminAuthRequired(adminctl.SystemInfoHandler)) // 个人资料API mux.HandleFunc("/admin/api/user/profile", adminctl.AdminAuthRequired(adminctl.UserProfileQueryHandler)) mux.HandleFunc("/admin/api/user/profile/update", adminctl.AdminAuthRequired(adminctl.UserProfileUpdateHandler)) mux.HandleFunc("/admin/api/user/password", adminctl.AdminAuthRequired(adminctl.UserPasswordUpdateHandler)) - // 设置API(需要管理员认证) + + // 系统设置API mux.HandleFunc("/admin/api/settings", adminctl.AdminAuthRequired(adminctl.SettingsQueryHandler)) mux.HandleFunc("/admin/api/settings/update", adminctl.AdminAuthRequired(adminctl.SettingsUpdateHandler)) @@ -79,6 +84,11 @@ func RegisterAdminRoutes(mux *http.ServeMux) { mux.HandleFunc("/admin/api/apis/types", adminctl.AdminAuthRequired(adminctl.APIGetTypesHandler)) mux.HandleFunc("/admin/api/apis/generate_keys", adminctl.AdminAuthRequired(adminctl.APIGenerateKeysHandler)) - // 系统信息API(用于仪表盘定时刷新) - mux.HandleFunc("/admin/api/system/info", adminctl.AdminAuthRequired(adminctl.SystemInfoHandler)) + // 变量管理API + mux.HandleFunc("/admin/variable/list", adminctl.AdminAuthRequired(adminctl.VariableListHandler)) + mux.HandleFunc("/admin/variable/apps", adminctl.AdminAuthRequired(adminctl.VariableGetAppsHandler)) + mux.HandleFunc("/admin/variable/create", adminctl.AdminAuthRequired(adminctl.VariableCreateHandler)) + mux.HandleFunc("/admin/variable/update", adminctl.AdminAuthRequired(adminctl.VariableUpdateHandler)) + mux.HandleFunc("/admin/variable/delete", adminctl.AdminAuthRequired(adminctl.VariableDeleteHandler)) + mux.HandleFunc("/admin/variable/batch_delete", adminctl.AdminAuthRequired(adminctl.VariablesBatchDeleteHandler)) } diff --git a/utils/logger/http.go b/utils/logger/http.go index 5063bf0..7574ce7 100644 --- a/utils/logger/http.go +++ b/utils/logger/http.go @@ -54,12 +54,13 @@ func (l *Logger) LogRequestWithHeaders(method, path, clientIP string, statusCode // 避免Logrus的任何格式化和转义,保持Apache日志格式的原始性 // logLine: 格式化后的日志行 func (l *Logger) writeHTTPLog(logLine string) { - // 输出到标准输出 - fmt.Fprintln(os.Stdout, logLine) - - // 同时输出到logrus配置的输出目标(包括文件) - // 使用logrus的输出目标,但不经过格式化器 - if l.Logger.Out != nil && l.Logger.Out != os.Stdout { + // 直接使用logrus的输出目标,避免重复输出 + // 如果logrus配置了MultiWriter,会自动输出到所有目标(控制台+文件) + // 如果logrus只配置了标准输出,也会正确输出到控制台 + if l.Logger.Out != nil { fmt.Fprintln(l.Logger.Out, logLine) + } else { + // 如果没有配置输出目标,默认输出到标准输出 + fmt.Fprintln(os.Stdout, logLine) } } diff --git a/web/template/admin/apis.html b/web/template/admin/apis.html index b8c1405..20dba0d 100644 --- a/web/template/admin/apis.html +++ b/web/template/admin/apis.html @@ -17,7 +17,7 @@
- +
+
@@ -209,11 +209,13 @@ layui.use(['table', 'form', 'layer', 'dropdown'], function() { limit: 20, limits: [10, 20, 50, 100], loading: true, + done: function(res, curr, count) { + // 表格渲染完成后的回调 + }, cols: [[ { field: 'id', title: 'ID', width: 80, sort: true }, - { field: 'app_name', title: '应用名称', mixWidth: 180 }, - { field: 'api_type_name', title: '接口类型', mixWidth: 120 }, - + { field: 'app_name', title: '应用名称', minWidth: 150 }, + { field: 'api_type_name', title: '接口类型', minWidth: 120 }, { field: 'status_name', title: '状态', @@ -227,27 +229,39 @@ layui.use(['table', 'form', 'layer', 'dropdown'], function() { field: 'submit_algorithm', title: '提交算法', width: 120, - templet: (d) => d.algorithm_names ? d.algorithm_names.submit : '-' + templet: (d) => { + const algorithm = d.algorithm_names ? d.algorithm_names.submit : '-'; + if (algorithm && algorithm.length > 10) { + return '' + algorithm.substring(0, 10) + '...'; + } + return algorithm; + } }, { field: 'return_algorithm', title: '返回算法', width: 120, - templet: (d) => d.algorithm_names ? d.algorithm_names.return : '-' + templet: (d) => { + const algorithm = d.algorithm_names ? d.algorithm_names.return : '-'; + if (algorithm && algorithm.length > 10) { + return '' + algorithm.substring(0, 10) + '...'; + } + return algorithm; + } }, { field: 'created_at', title: '创建时间', - width: 180, + width: 160, templet: (d) => formatDateTime(d.created_at) }, { field: 'updated_at', title: '修改时间', - width: 180, + width: 160, templet: (d) => formatDateTime(d.updated_at) }, - { fixed: 'right', title: '操作', toolbar: '#tpl-apis-ops', width: 70 } + { fixed: 'right', title: '操作', toolbar: '#tpl-apis-ops', width: 100, align: 'center' } ]] }); @@ -533,7 +547,7 @@ layui.use(['table', 'form', 'layer', 'dropdown'], function() { if (obj.event === 'edit') { // 编辑接口 $('#apiForm')[0].reset(); - $('input[name="id"]').val(data.id); + $('input[name="uuid"]').val(data.uuid); $('select[name="submit_algorithm"]').val(data.submit_algorithm); $('select[name="return_algorithm"]').val(data.return_algorithm); $('input[name="status"]').prop('checked', data.status === 1); @@ -574,7 +588,6 @@ layui.use(['table', 'form', 'layer', 'dropdown'], function() { // 转换数值类型 formData.submit_algorithm = parseInt(formData.submit_algorithm); formData.return_algorithm = parseInt(formData.return_algorithm); - formData.id = parseInt(formData.id); $.ajax({ url: '/admin/api/apis/update', diff --git a/web/template/admin/layout.html b/web/template/admin/layout.html index eec5a68..fbfef73 100644 --- a/web/template/admin/layout.html +++ b/web/template/admin/layout.html @@ -56,6 +56,7 @@
应用列表
接口列表
+
变量列表
diff --git a/web/template/admin/variables.html b/web/template/admin/variables.html new file mode 100644 index 0000000..ada8ea6 --- /dev/null +++ b/web/template/admin/variables.html @@ -0,0 +1,464 @@ +{{ define "variables" }} +
+

变量管理

+
+ + +
+ +
+
筛选
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + +
+
+
+
+
+ +
+
变量列表
+
+
+
+
+ + + + + + + + +
+{{ end }} \ No newline at end of file