Files
NetworkAuth/controllers/admin/variable.go
2025-10-26 00:08:55 +08:00

429 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}