init
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
main.exe
|
||||
go_build_energy_management_system.exe
|
||||
.idea
|
||||
176
api/v1/enter.go
Normal file
176
api/v1/enter.go
Normal file
@@ -0,0 +1,176 @@
|
||||
package v1
|
||||
|
||||
type Controller struct {
|
||||
TestApi
|
||||
PeakValley // 谷峰规则
|
||||
//UserApi // 用户管理
|
||||
//DictApi // 字典管理
|
||||
//ProductApi // 产品管理
|
||||
//OTAApi // ota管理
|
||||
//UpLoadApi // 上传
|
||||
//ProtocolPluginApi // 协议插件
|
||||
//DeviceApi // 设备
|
||||
//DeviceModelApi // 设备物模型
|
||||
//UiElementsApi // UI元素控制
|
||||
//BoardApi // 首页
|
||||
//TelemetryDataApi // 遥测数据
|
||||
//AttributeDataApi // 属性数据
|
||||
//EventDataApi // 事件数据
|
||||
//CommandSetLogApi // 命令下发记录
|
||||
//OperationLogsApi // 系统日志
|
||||
//LogoApi // 站标
|
||||
//DataPolicyApi // 数据清理
|
||||
//DeviceConfigApi // 设备配置
|
||||
//DataScriptApi // 数据处理脚本
|
||||
//RoleApi // 用户管理
|
||||
//CasbinApi // 权限管理
|
||||
//NotificationGroupApi // 通知组
|
||||
//NotificationHistoryApi // 通知历史
|
||||
//NotificationServicesConfigApi // 通知服务配置
|
||||
//AlarmApi // 告警
|
||||
//SceneAutomationsApi //场景联动
|
||||
//SceneApi //场景
|
||||
//SystemApi //系统相关
|
||||
//SysFunctionApi //功能设置
|
||||
//VisPluginApi //可视化插件
|
||||
//ServicePluginApi //插件管理
|
||||
//ServiceAccessApi //服务接入管理
|
||||
}
|
||||
|
||||
var Controllers = new(Controller)
|
||||
|
||||
//var Validate *validator.Validate
|
||||
|
||||
func init() {
|
||||
//Validate = validator.New()
|
||||
}
|
||||
|
||||
// ValidateStruct validates the request structure
|
||||
//func ValidateStruct(i interface{}) error {
|
||||
// err := Validate.Struct(i)
|
||||
// if err != nil {
|
||||
// if _, ok := err.(*validator.InvalidValidationError); ok {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// var errors []string
|
||||
// for _, err := range err.(validator.ValidationErrors) {
|
||||
// var error string
|
||||
// switch err.Tag() {
|
||||
// case "required":
|
||||
// error = fmt.Sprintf("Field '%s' is required", err.Field())
|
||||
// case "email":
|
||||
// error = fmt.Sprintf("Field '%s' must be a valid email address", err.Field())
|
||||
// case "gte":
|
||||
// error = fmt.Sprintf("The value of field '%s' must be at least %s", err.Field(), err.Param())
|
||||
// case "lte":
|
||||
// error = fmt.Sprintf("The value of field '%s' must be at most %s", err.Field(), err.Param())
|
||||
// default:
|
||||
// error = fmt.Sprintf("Field '%s' failed validation (%s)", err.Field(), validationErrorToText(err))
|
||||
// }
|
||||
// errors = append(errors, error)
|
||||
// }
|
||||
//
|
||||
// return fmt.Errorf("%s", errors[0])
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
// validationErrorToText converts validation errors to more descriptive text
|
||||
//func validationErrorToText(e validator.FieldError) string {
|
||||
// switch e.Tag() {
|
||||
// case "min":
|
||||
// return fmt.Sprintf("At least %s characters", e.Param())
|
||||
// case "max":
|
||||
// return fmt.Sprintf("At most %s characters", e.Param())
|
||||
// case "len":
|
||||
// return fmt.Sprintf("Must be %s characters", e.Param())
|
||||
// // Add more cases as needed
|
||||
// default:
|
||||
// return "Does not meet validation rules"
|
||||
// }
|
||||
//}
|
||||
|
||||
// 定义统一的HTTP响应结构
|
||||
//type ApiResponse struct {
|
||||
// Code int `json:"code"`
|
||||
// Message string `json:"message"`
|
||||
// Data interface{} `json:"data,omitempty"`
|
||||
//}
|
||||
|
||||
// ErrorHandler 统一错误处理
|
||||
//func ErrorHandler(c *gin.Context, code int, err error) {
|
||||
// if strings.Contains(err.Error(), "SQLSTATE 23503") {
|
||||
// // 处理外键约束违反
|
||||
// err = fmt.Errorf("操作无法完成:请先删除与此项相关联的数据后再进行尝试")
|
||||
// }
|
||||
// if strings.Contains(err.Error(), "SQLSTATE 23505") {
|
||||
// // 处理唯一键约束违反
|
||||
// err = fmt.Errorf("操作无法完成:已存在相同的数据")
|
||||
// }
|
||||
// // fmt.Printf("%T\n", err)
|
||||
// // // 检查这个错误是否是 *pgconn.PgError
|
||||
// // var pgErr *pgconn.PgError
|
||||
// // if errors.As(err, &pgErr) {
|
||||
// // logrus.Error("-----------------")
|
||||
// // // 现在 pgErr 是 err 中的 *pgconn.PgError 部分(如果存在)
|
||||
// // if pgErr.SQLState() == "23503" {
|
||||
// // // 这就是一个外键约束违反错误
|
||||
// // err = fmt.Errorf("外键约束违反: %w", err)
|
||||
// // }
|
||||
// // }
|
||||
// logrus.Error(err)
|
||||
// c.JSON(http.StatusOK, ApiResponse{
|
||||
// Code: code,
|
||||
// Message: err.Error(),
|
||||
// })
|
||||
//}
|
||||
//
|
||||
//// SuccessHandler 统一成功响应
|
||||
//func SuccessHandler(c *gin.Context, message string, data interface{}) {
|
||||
// c.JSON(http.StatusOK, ApiResponse{
|
||||
// Code: http.StatusOK,
|
||||
// Message: message,
|
||||
// Data: data,
|
||||
// })
|
||||
//}
|
||||
//
|
||||
//// SuccessOK 统一成功响应
|
||||
//func SuccessOK(c *gin.Context) {
|
||||
// c.JSON(http.StatusOK, ApiResponse{
|
||||
// Code: http.StatusOK,
|
||||
// Message: "Success",
|
||||
// })
|
||||
//}
|
||||
//
|
||||
//func BindAndValidate(c *gin.Context, obj interface{}) bool {
|
||||
// // 判断请求方法
|
||||
// if c.Request.Method == http.MethodGet {
|
||||
// if err := c.ShouldBindQuery(obj); err != nil {
|
||||
// ErrorHandler(c, http.StatusBadRequest, err)
|
||||
// return false
|
||||
// }
|
||||
// } else if c.Request.Method == http.MethodPost || c.Request.Method == http.MethodPut || c.Request.Method == http.MethodDelete {
|
||||
// if err := c.ShouldBindJSON(obj); err != nil {
|
||||
// ErrorHandler(c, http.StatusBadRequest, err)
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if err := ValidateStruct(obj); err != nil {
|
||||
// // 如果是验证错误,返回422 Unprocessable Entity
|
||||
// ErrorHandler(c, http.StatusUnprocessableEntity, err)
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// return true
|
||||
//}
|
||||
//
|
||||
//var Wsupgrader = websocket.Upgrader{
|
||||
// ReadBufferSize: 1024,
|
||||
// WriteBufferSize: 1024,
|
||||
// CheckOrigin: func(r *http.Request) bool {
|
||||
// // 不做跨域检查
|
||||
// return true
|
||||
// },
|
||||
//}
|
||||
62
api/v1/peak_valley.go
Normal file
62
api/v1/peak_valley.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"energy-management-system/form"
|
||||
"energy-management-system/request"
|
||||
"energy-management-system/response"
|
||||
"energy-management-system/service"
|
||||
"energy-management-system/utils/exception"
|
||||
"github.com/gin-gonic/gin"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type PeakValley struct{}
|
||||
|
||||
// GetPeakValleyTypes 获取峰谷类型
|
||||
func (r *PeakValley) GetPeakValleyTypes(c *gin.Context) {
|
||||
types := service.GroupServices.PeakValley.GetPeakValleyType()
|
||||
response.SuccessData(gin.H{"types": types}, c)
|
||||
}
|
||||
|
||||
// PeakValleyRuleList 谷峰规则列表
|
||||
func (r *PeakValley) PeakValleyRuleList(c *gin.Context) {
|
||||
var req form.PeakValleyRuleListReq
|
||||
request.BindParam(c, &req)
|
||||
respData := service.GroupServices.PeakValley.PeakValleyRuleList(&req)
|
||||
response.SuccessData(respData, c)
|
||||
}
|
||||
|
||||
// CreatePeakValleyRule 创建谷峰规则
|
||||
func (r *PeakValley) CreatePeakValleyRule(c *gin.Context) {
|
||||
var req form.CreatePeakValleyRuleReq
|
||||
request.BindJson(c, &req)
|
||||
service.GroupServices.PeakValley.CreatePeakValleyRule(&req)
|
||||
response.Success(c)
|
||||
}
|
||||
|
||||
// UpdatePeakValleyRule 修改谷峰规则
|
||||
func (r *PeakValley) UpdatePeakValleyRule(c *gin.Context) {
|
||||
var req form.UpdatePeakValleyRuleReq
|
||||
request.BindJson(c, &req)
|
||||
service.GroupServices.PeakValley.UpdatePeakValleyRule(&req)
|
||||
//response.Success(c)
|
||||
}
|
||||
|
||||
// PeakValleyRuleDetail 谷峰规则详情
|
||||
func (r *PeakValley) PeakValleyRuleDetail(c *gin.Context) {
|
||||
var req form.PeakValleyRuleDetailReq
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
exception.PanicMsgBool(err != nil, "参数有误")
|
||||
req.RuleId = id
|
||||
respData := service.GroupServices.PeakValley.PeakValleyRuleDetail(&req)
|
||||
response.SuccessData(respData, c)
|
||||
}
|
||||
|
||||
func (r *PeakValley) PeakValleyRuleEditDetail(c *gin.Context) {
|
||||
var req form.PeakValleyRuleEditDetailReq
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
exception.PanicMsgBool(err != nil, "参数有误")
|
||||
req.RuleId = id
|
||||
respData := service.GroupServices.PeakValley.PeakValleyRuleEditDetail(&req)
|
||||
response.SuccessData(respData, c)
|
||||
}
|
||||
33
api/v1/test.go
Normal file
33
api/v1/test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"energy-management-system/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type TestApi struct {
|
||||
}
|
||||
|
||||
func (r *TestApi) Test(c *gin.Context) {
|
||||
response.Success(c)
|
||||
}
|
||||
|
||||
func (r *TestApi) TestData(c *gin.Context) {
|
||||
response.SuccessData(gin.H{"userName": "iuu"}, c)
|
||||
}
|
||||
|
||||
//func (a *AlarmApi) CreateAlarmConfig(c *gin.Context) {
|
||||
// var req model.CreateAlarmConfigReq
|
||||
// if !BindAndValidate(c, &req) {
|
||||
// return
|
||||
// }
|
||||
// var userClaims = c.MustGet("claims").(*utils.UserClaims)
|
||||
// req.TenantID = userClaims.TenantID
|
||||
// data, err := service.GroupApp.Alarm.CreateAlarmConfig(&req)
|
||||
// if err != nil {
|
||||
// ErrorHandler(c, http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// SuccessHandler(c, "Create successfully", data)
|
||||
//}
|
||||
17
config.yaml
Normal file
17
config.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
service:
|
||||
http:
|
||||
host: 0.0.0.0 # 默认localhost
|
||||
port: 9999 # 默认9999
|
||||
|
||||
db:
|
||||
db_host: "192.168.0.9"
|
||||
db_port: "15432"
|
||||
db_name: "nengyuan"
|
||||
db_user: "iuu_postgres"
|
||||
db_pass: "iuu_postgres"
|
||||
table_prefix: "energy_"
|
||||
time_zone: "Asia/Shanghai"
|
||||
log_level: 4
|
||||
slow_threshold: 200
|
||||
idle_conns: 10
|
||||
open_conns: 50
|
||||
19
config/config.go
Normal file
19
config/config.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package config
|
||||
|
||||
//环境 全称 简写
|
||||
//开发环境 development dev
|
||||
//测试环境 testing test
|
||||
//灰度/预发布环境 staging/pre-production stag
|
||||
//生产环境 production prod
|
||||
|
||||
const (
|
||||
// AppEnv 应用环境 dev,test,stag,prod
|
||||
AppEnv = "dev"
|
||||
// EnvConfig 环境配置
|
||||
EnvConfig = "config.yaml"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Db DbConf `mapstructure:"db" json:"db" yaml:"db"`
|
||||
Service ServiceConf `mapstructure:"service" json:"service" yaml:"service"`
|
||||
}
|
||||
15
config/db.go
Normal file
15
config/db.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package config
|
||||
|
||||
type DbConf struct {
|
||||
DbHost string `mapstructure:"db_host" json:"db_host" yaml:"db_host"`
|
||||
DbPort int `mapstructure:"db_port" json:"db_port" yaml:"db_port"`
|
||||
DbName string `mapstructure:"db_name" json:"db_name" yaml:"db_name"`
|
||||
DbUser string `mapstructure:"db_user" json:"db_user" yaml:"db_user"`
|
||||
DbPass string `mapstructure:"db_pass" json:"db_pass" yaml:"db_pass"`
|
||||
TablePrefix string `mapstructure:"table_prefix" json:"table_prefix" yaml:"table_prefix"`
|
||||
TimeZone string `mapstructure:"time_zone" json:"time_zone" yaml:"time_zone"`
|
||||
LogLevel int `mapstructure:"log_level" json:"log_level" yaml:"log_level"` // LogLevel SQL日志级别 (1-静音 2-错误 3-警告 4-信息)
|
||||
SlowThreshold int `mapstructure:"slow_threshold" json:"slow_threshold" yaml:"slow_threshold"` // SlowThreshold 慢SQL阈值(毫秒)。慢SQL会在log_level大于等于3时输出。
|
||||
IdleConns int `mapstructure:"idle_conns" json:"idle_conns" yaml:"idle_conns"` // 空闲连接池中的最大连接数,建议为open_conns的百分之5-20之间
|
||||
OpenConns int `mapstructure:"open_conns" json:"open_conns" yaml:"open_conns"` // 最大打开连接数,建议这里设置为50
|
||||
}
|
||||
10
config/service.go
Normal file
10
config/service.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
type ServiceConf struct {
|
||||
Http HttpConf `mapstructure:"http" json:"http" yaml:"http"`
|
||||
}
|
||||
|
||||
type HttpConf struct {
|
||||
Host string `mapstructure:"host" json:"host" yaml:"host"`
|
||||
Port string `mapstructure:"port" json:"port" yaml:"port"`
|
||||
}
|
||||
78
core/gorm.go
Normal file
78
core/gorm.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
peak_valley "energy-management-system/model/peak-valley"
|
||||
"fmt"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitGorm() {
|
||||
dsn := fmt.Sprintf("host=%s port=%d dbname=%s user=%s password=%s sslmode=disable TimeZone=%s",
|
||||
global.AppConf.Db.DbHost, global.AppConf.Db.DbPort, global.AppConf.Db.DbName, global.AppConf.Db.DbUser, global.AppConf.Db.DbPass, global.AppConf.Db.TimeZone)
|
||||
postgresConfig := postgres.Config{
|
||||
DSN: dsn, // DSN data source name
|
||||
PreferSimpleProtocol: true, // 禁用隐式 prepared statement
|
||||
}
|
||||
|
||||
// 使用标准日志库的New方法创建日志输出
|
||||
newLogger := logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
||||
logger.Config{
|
||||
SlowThreshold: time.Duration(global.AppConf.Db.SlowThreshold) * time.Millisecond, // 慢SQL阈值
|
||||
LogLevel: logger.LogLevel(global.AppConf.Db.LogLevel), // 日志级别
|
||||
IgnoreRecordNotFoundError: true,
|
||||
Colorful: true,
|
||||
})
|
||||
|
||||
PGDB, err := gorm.Open(postgres.New(postgresConfig), &gorm.Config{
|
||||
//Logger: newLogger,
|
||||
//Logger: logger.Default.LogMode(logger.Info),
|
||||
Logger: newLogger,
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true, // 使用单数表名,在启用此选项的情况下,“user”的表将是“user”
|
||||
TablePrefix: global.AppConf.Db.TablePrefix, // 表前缀
|
||||
},
|
||||
})
|
||||
|
||||
DB := PGDB
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("数据库链接失败")
|
||||
os.Exit(0)
|
||||
}
|
||||
//AutoMigrate(DB)
|
||||
sqlDB, _ := DB.DB()
|
||||
sqlDB.SetMaxIdleConns(global.AppConf.Db.IdleConns)
|
||||
sqlDB.SetMaxOpenConns(global.AppConf.Db.OpenConns)
|
||||
// 设置数据库连接池中连接的最大生命周期
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
fmt.Println("[+]PG连接成功!")
|
||||
global.Db = DB
|
||||
}
|
||||
|
||||
// AutoMigrate 自动迁移
|
||||
func AutoMigrate(db *gorm.DB) {
|
||||
err := db.AutoMigrate(
|
||||
new(peak_valley.PeakValleyTimeBlock),
|
||||
new(peak_valley.PeakValleyTimeBlockPrice),
|
||||
new(peak_valley.PeakValleyQuarterRule),
|
||||
new(peak_valley.PeakValleyRule),
|
||||
//new(model.Role),
|
||||
//new(model.UserRole),
|
||||
//new(model.Api),
|
||||
//new(model.Menu),
|
||||
//new(model.RoleApi),
|
||||
//new(model.RoleMenu),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println("[-] 迁移数据表失败:", err.Error())
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
2
core/validator.go
Normal file
2
core/validator.go
Normal file
@@ -0,0 +1,2 @@
|
||||
package core
|
||||
|
||||
59
core/viper.go
Normal file
59
core/viper.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"energy-management-system/config"
|
||||
"energy-management-system/global"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
"os"
|
||||
)
|
||||
|
||||
// InitViper 解析yaml格式文件
|
||||
func InitViper(path ...string) {
|
||||
var confPath string
|
||||
if len(path) == 0 {
|
||||
flag.StringVar(&confPath, "c", "", "choose config file.")
|
||||
flag.Parse()
|
||||
if confPath == "" {
|
||||
if AppEnv := os.Getenv(config.AppEnv); AppEnv == "" {
|
||||
confPath = config.EnvConfig
|
||||
} else {
|
||||
confPath = AppEnv
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
confPath = path[0]
|
||||
}
|
||||
|
||||
v := viper.New()
|
||||
// 指定配置文件路径
|
||||
v.SetConfigFile(confPath)
|
||||
// 如果配置文件的名称中没有扩展名,则需要配置此项
|
||||
v.SetConfigType("yaml")
|
||||
// 查找并读取配置文件
|
||||
err := v.ReadInConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("[-]读取配置文件错误: %s \n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
// 监控并重新读取配置文件
|
||||
v.WatchConfig()
|
||||
v.OnConfigChange(func(e fsnotify.Event) {
|
||||
if err = v.Unmarshal(&global.AppConf); err != nil {
|
||||
fmt.Printf("[-]重新解析配置文件失败: %s \n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
fmt.Println("[+]重新加载配置文件完成")
|
||||
})
|
||||
if err = v.Unmarshal(&global.AppConf); err != nil {
|
||||
fmt.Printf("[-]解析配置文件失败: %s \n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
fmt.Println("[+]加载配置文件完成")
|
||||
|
||||
//dump.P(global.AppConf)
|
||||
|
||||
}
|
||||
20
form/page.go
Normal file
20
form/page.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package form
|
||||
|
||||
type Page struct {
|
||||
PageIndex int `form:"page_index" json:"page_index"`
|
||||
PageSize int `form:"page_size" json:"page_size"`
|
||||
}
|
||||
|
||||
func (m *Page) GetPageIndex() int {
|
||||
if m.PageIndex <= 0 {
|
||||
m.PageIndex = 1
|
||||
}
|
||||
return m.PageIndex
|
||||
}
|
||||
|
||||
func (m *Page) GetPageSize() int {
|
||||
if m.PageSize <= 0 {
|
||||
m.PageSize = 10
|
||||
}
|
||||
return m.PageSize
|
||||
}
|
||||
42
form/peak_valley_rule.go
Normal file
42
form/peak_valley_rule.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package form
|
||||
|
||||
// 一天的完整谷峰规则
|
||||
// 发电 (光伏)
|
||||
// 用电 (电机、生产)
|
||||
|
||||
//新建规则
|
||||
//
|
||||
//选择时间段 设置电价
|
||||
//(将时间段 转化为十分钟区块 查找到对应十分钟区块 创建该规则的电价)
|
||||
|
||||
type PeakValleyRuleListReq struct {
|
||||
Page `json:"page"`
|
||||
}
|
||||
|
||||
type PeakValleyRuleDetailReq struct {
|
||||
RuleId int `form:"rule_id" json:"rule_id"`
|
||||
}
|
||||
|
||||
type PeakValleyRuleEditDetailReq struct {
|
||||
RuleId int `form:"rule_id" json:"rule_id"`
|
||||
}
|
||||
|
||||
type CreatePeakValleyRuleReq struct {
|
||||
RuleName string `json:"rule_name" binding:"required"`
|
||||
Description string `json:"description" binding:"required"`
|
||||
RuleItem []TimeBlockPriceReq `json:"rule_item"`
|
||||
}
|
||||
type UpdatePeakValleyRuleReq struct {
|
||||
RuleId int `json:"rule_id" binding:"required"`
|
||||
RuleName string `json:"rule_name" binding:"required"`
|
||||
Description string `json:"description" binding:"required"`
|
||||
RuleItem []TimeBlockPriceReq `json:"rule_item"`
|
||||
}
|
||||
|
||||
type TimeBlockPriceReq struct {
|
||||
CustomName string `json:"custom_name"`
|
||||
PeakValleyType uint `json:"peak_valley_type"`
|
||||
StartTime string `json:"start_time"`
|
||||
EndTime string `json:"end_time"`
|
||||
Price int `json:"price"`
|
||||
}
|
||||
17
global/var.go
Normal file
17
global/var.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"energy-management-system/config"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
// AppConf 配置信息
|
||||
AppConf *config.Config
|
||||
// Db 数据库
|
||||
Db *gorm.DB
|
||||
|
||||
// Trans 定义一个全局翻译器T
|
||||
//Trans ut.Translator
|
||||
//Validate *validator.Validate
|
||||
)
|
||||
64
go.mod
Normal file
64
go.mod
Normal file
@@ -0,0 +1,64 @@
|
||||
module energy-management-system
|
||||
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/gookit/goutil v0.6.16
|
||||
github.com/spf13/viper v1.19.0
|
||||
gorm.io/driver/postgres v1.5.9
|
||||
gorm.io/gorm v1.25.11
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
154
go.sum
Normal file
154
go.sum
Normal file
@@ -0,0 +1,154 @@
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gookit/goutil v0.6.16 h1:9fRMCF4X9abdRD5+2HhBS/GwafjBlTUBjRtA5dgkvuw=
|
||||
github.com/gookit/goutil v0.6.16/go.mod h1:op2q8AoPDFSiY2+qkHxcBWQMYxOLQ1GbLXqe7vrwscI=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
|
||||
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
138
main.go
Normal file
138
main.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"energy-management-system/core"
|
||||
"energy-management-system/global"
|
||||
"energy-management-system/request"
|
||||
"energy-management-system/router"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
core.InitViper()
|
||||
core.InitGorm()
|
||||
//init_model_data.InitDbData()
|
||||
//core.InitCasbin()
|
||||
request.InitTrans()
|
||||
//core.AutoMigrate(global.Db)
|
||||
|
||||
}
|
||||
func main() {
|
||||
|
||||
r := router.InitRouter()
|
||||
host := global.AppConf.Service.Http.Host
|
||||
port := global.AppConf.Service.Http.Port
|
||||
srv := initServer(host, port, r)
|
||||
|
||||
// 启动服务
|
||||
go startServer(srv, host, port)
|
||||
|
||||
// 优雅关闭
|
||||
gracefulShutdown(srv)
|
||||
|
||||
//// 定义一个切片来接收查询结果
|
||||
//var users []peaks_valleys.PeakValleyTimeBlock
|
||||
//
|
||||
//// 查询所有用户
|
||||
//result := global.Db.Find(&users)
|
||||
//if result.Error != nil {
|
||||
// fmt.Println("Error:", result.Error)
|
||||
//}
|
||||
//
|
||||
//// 打印查询结果
|
||||
//for _, user := range users {
|
||||
//
|
||||
// if user.BlockIndex < 20 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 35,
|
||||
// PeakValleyType: 5,
|
||||
// })
|
||||
// } else if user.BlockIndex < 40 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 45,
|
||||
// PeakValleyType: 4,
|
||||
// })
|
||||
// } else if user.BlockIndex < 60 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 55,
|
||||
// PeakValleyType: 3,
|
||||
// })
|
||||
// } else if user.BlockIndex < 80 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 65,
|
||||
// PeakValleyType: 2,
|
||||
// })
|
||||
// } else if user.BlockIndex < 100 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 85,
|
||||
// PeakValleyType: 1,
|
||||
// })
|
||||
// } else if user.BlockIndex <= 144 {
|
||||
// global.Db.Create(&peaks_valleys.PeakValleyTimeBlockPrice{
|
||||
// BlockId: user.BlockIndex,
|
||||
// Price: 35,
|
||||
// PeakValleyType: 5,
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// //fmt.Printf("ID: %d, Name: %s, Email: %s\n", user.BlockIndex)
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
//func loadConfig() (host, port string) {
|
||||
// host = viper.GetString("service.http.host")
|
||||
// if host == "" {
|
||||
// host = "localhost"
|
||||
// fmt.Println("Using default host:", host)
|
||||
// }
|
||||
//
|
||||
// port = viper.GetString("service.http.port")
|
||||
// if port == "" {
|
||||
// port = "9999"
|
||||
// fmt.Println("Using default port:", port)
|
||||
// }
|
||||
//
|
||||
// return host, port
|
||||
//}
|
||||
|
||||
func initServer(host, port string, handler http.Handler) *http.Server {
|
||||
return &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%s", host, port),
|
||||
Handler: handler,
|
||||
ReadTimeout: 60 * time.Second,
|
||||
WriteTimeout: 60 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func startServer(srv *http.Server, host, port string) {
|
||||
fmt.Println("Listening and serving HTTP on", host, ":", port)
|
||||
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
fmt.Printf("listen: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func gracefulShutdown(srv *http.Server) {
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, os.Interrupt)
|
||||
<-quit
|
||||
fmt.Println("Shutdown Server ...")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
fmt.Println("Server Shutdown:", err)
|
||||
}
|
||||
fmt.Println("Server exiting")
|
||||
}
|
||||
25
middleware/cors.go
Normal file
25
middleware/cors.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Cors 处理跨域请求,支持options访问
|
||||
func Cors() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
method := c.Request.Method
|
||||
origin := c.Request.Header.Get("Origin")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
|
||||
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
// 放行所有OPTIONS方法
|
||||
if method == "OPTIONS" {
|
||||
c.AbortWithStatus(http.StatusNoContent)
|
||||
}
|
||||
// 处理请求
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
48
middleware/recovery.go
Normal file
48
middleware/recovery.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"energy-management-system/utils"
|
||||
"energy-management-system/utils/exception"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Recovery() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
var brokenPipe bool
|
||||
if ne, ok := err.(*net.OpError); ok {
|
||||
if se, ok := ne.Err.(*os.SyscallError); ok {
|
||||
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
|
||||
brokenPipe = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if brokenPipe {
|
||||
c.Error(err.(error))
|
||||
} else {
|
||||
if h, ok := err.(*exception.Exception); ok {
|
||||
exception.Panic(c, h)
|
||||
c.Errors = append(c.Errors, &gin.Error{Meta: h})
|
||||
} else if _, ok = err.(error); ok {
|
||||
if gin.IsDebugging() {
|
||||
fmt.Printf("[Recovery] %s : %s", utils.TimeFormat(time.Now()), err)
|
||||
utils.Stack(3)
|
||||
}
|
||||
exception.Unknow(c)
|
||||
} else {
|
||||
fmt.Print(err)
|
||||
exception.Server(c)
|
||||
}
|
||||
}
|
||||
c.Abort()
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
26
model/peak-valley/peak_valley_quarter_rule.go
Normal file
26
model/peak-valley/peak_valley_quarter_rule.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 季度谷峰规则
|
||||
|
||||
// 开始时间
|
||||
// 结束时间
|
||||
// 谷峰规则ID
|
||||
|
||||
type PeakValleyQuarterRule struct {
|
||||
RuleId uint `gorm:"column:rule_id;primaryKey" json:"rule_id"`
|
||||
StartTime uint `gorm:"column:start_time;comment:开始时间" json:"start_time"`
|
||||
EndTime uint `gorm:"column:end_time;comment:结束时间" json:"end_time"`
|
||||
Created time.Time `gorm:"column:created;autoCreateTime;comment:创建时间" json:"created"`
|
||||
Updated time.Time `gorm:"column:updated;autoUpdateTime;comment:修改时间" json:"updated"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间" json:"-"`
|
||||
}
|
||||
|
||||
func (r *PeakValleyQuarterRule) TableName() string {
|
||||
return global.AppConf.Db.TablePrefix + "peak_valley_quarter_rules"
|
||||
}
|
||||
29
model/peak-valley/peak_valley_rule.go
Normal file
29
model/peak-valley/peak_valley_rule.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 一天的完整谷峰规则
|
||||
// 发电 (光伏)
|
||||
// 用电 (电机、生产)
|
||||
|
||||
//新建规则
|
||||
//
|
||||
//选择时间段 设置电价
|
||||
//(将时间段 转化为十分钟区块 查找到对应十分钟区块 创建该规则的电价)
|
||||
|
||||
type PeakValleyRule struct {
|
||||
RuleId uint `gorm:"column:rule_id;primaryKey" json:"rule_id"`
|
||||
RuleName string `gorm:"column:rule_name;comment:规则名称" json:"rule_name"`
|
||||
Description string `gorm:"column:description;comment:描述" json:"description"`
|
||||
Created time.Time `gorm:"column:created;autoCreateTime;comment:创建时间" json:"created"`
|
||||
Updated time.Time `gorm:"column:updated;autoUpdateTime;comment:修改时间" json:"updated"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间" json:"-"`
|
||||
}
|
||||
|
||||
func (r *PeakValleyRule) TableName() string {
|
||||
return global.AppConf.Db.TablePrefix + "peak_valley_rules"
|
||||
}
|
||||
58
model/peak-valley/peak_valley_time_block.go
Normal file
58
model/peak-valley/peak_valley_time_block.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
const MinutesInADay = 24 * 60
|
||||
|
||||
// PeakValleyTimeBlock 峰谷时间区块
|
||||
type PeakValleyTimeBlock struct {
|
||||
BlockIndex uint `gorm:"column:block_index;primaryKey;comment:区块编号" json:"block_index"`
|
||||
StartTime uint `gorm:"column:start_time;comment:开始时间" json:"start_time"`
|
||||
EndTime uint `gorm:"column:end_time;comment:结束时间" json:"end_time"`
|
||||
Created time.Time `gorm:"column:created;autoCreateTime;comment:创建时间" json:"created"`
|
||||
Updated time.Time `gorm:"column:updated;autoUpdateTime;comment:修改时间" json:"updated"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间" json:"-"`
|
||||
}
|
||||
|
||||
func (r *PeakValleyTimeBlock) TableName() string {
|
||||
return global.AppConf.Db.TablePrefix + "peak_valley_time_blocks"
|
||||
}
|
||||
|
||||
func Init() {
|
||||
// 一天有24小时,即1440分钟
|
||||
totalMinutes := 24 * 60
|
||||
// 时间块的持续时间:10分钟
|
||||
blockDuration := 10
|
||||
|
||||
// 遍历一天中的所有时间块
|
||||
for i := 0; i < totalMinutes; i += blockDuration {
|
||||
startTime := i
|
||||
endTime := i + blockDuration
|
||||
|
||||
fmt.Println("start", startTime)
|
||||
fmt.Println("start", endTime)
|
||||
|
||||
global.Db.Create(&PeakValleyTimeBlock{
|
||||
StartTime: uint(startTime),
|
||||
EndTime: uint(endTime),
|
||||
})
|
||||
|
||||
// 打印开始时间和结束时间,格式为 HH:MM
|
||||
//fmt.Printf("时间块 %d: 开始时间: %02d:%02d, 结束时间: %02d:%02d\n",
|
||||
// i/blockDuration+1,
|
||||
// startTime/60, startTime%60,
|
||||
// endTime/60, endTime%60)
|
||||
|
||||
// 使用整数存储时间块的开始和结束时间(以分钟为单位)
|
||||
//startTime := 0 // 00:00
|
||||
//endTime := 10 // 00:10
|
||||
//
|
||||
//fmt.Printf("开始时间: %02d:%02d\n", startTime/60, startTime%60)
|
||||
//fmt.Printf("结束时间: %02d:%02d\n", endTime/60, endTime%60)
|
||||
}
|
||||
}
|
||||
86
model/peak-valley/peak_valley_time_block_price.go
Normal file
86
model/peak-valley/peak_valley_time_block_price.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
"energy-management-system/utils"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// POINTED 尖
|
||||
POINTED = iota + 1
|
||||
// PEAK 峰
|
||||
PEAK
|
||||
// FLAT 平
|
||||
FLAT
|
||||
// VALLEY 谷
|
||||
VALLEY
|
||||
// FUKAYA 深谷
|
||||
FUKAYA
|
||||
)
|
||||
|
||||
var PeakValleyTypes = map[int]string{
|
||||
POINTED: "尖",
|
||||
PEAK: "峰",
|
||||
FLAT: "平",
|
||||
VALLEY: "谷",
|
||||
FUKAYA: "深谷",
|
||||
}
|
||||
|
||||
type PeakValleyType struct {
|
||||
Value int `json:"value"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// PeakValleyTimeBlockPrice 峰谷时间区块价格
|
||||
type PeakValleyTimeBlockPrice struct {
|
||||
Id uint `gorm:"column:id;primaryKey" json:"id"`
|
||||
BlockId uint `gorm:"column:block_id;comment:时间区块编号" json:"block_id"`
|
||||
Price int `gorm:"column:price;comment:价格" json:"price"`
|
||||
CustomName string `gorm:"column:custom_name;comment:自定义名称" json:"custom_name"`
|
||||
PeakValleyRuleId uint `gorm:"column:peak_valley_rule_id;comment:峰谷规则" json:"peak_valley_rule_id"`
|
||||
PeakValleyType uint `gorm:"column:peak_valley_type;default:1;size:10;comment:峰谷类型[1:尖,2:峰,3:平,4:谷,5:深谷]" json:"peak_valley_type"` // 峰谷类型
|
||||
Created time.Time `gorm:"column:created;autoCreateTime;comment:创建时间" json:"created"`
|
||||
Updated time.Time `gorm:"column:updated;autoUpdateTime;comment:修改时间" json:"updated"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间" json:"-"`
|
||||
}
|
||||
|
||||
func (r *PeakValleyTimeBlockPrice) TableName() string {
|
||||
return global.AppConf.Db.TablePrefix + "peak_valley_time_block_prices"
|
||||
}
|
||||
|
||||
type PeakValleyRuleCustomName struct {
|
||||
PeakValleyType uint `json:"peak_valley_type"`
|
||||
Price int `json:"price"`
|
||||
CustomName string `json:"custom_name"`
|
||||
StartTime uint `json:"start_time"`
|
||||
EndTime uint `json:"end_time"`
|
||||
StartTimeStr string `json:"start_time_str"`
|
||||
EndTimeStr string `json:"end_time_str"`
|
||||
}
|
||||
|
||||
type PeakValleyRuleType struct {
|
||||
PeakValleyType uint `json:"peak_valley_type"`
|
||||
Price int `json:"price"`
|
||||
RuleTimeBlocks []RuleTimeBlock `gorm:"-" json:"rule_time_blocks"`
|
||||
}
|
||||
|
||||
type RuleTimeBlock struct {
|
||||
StartTime uint `json:"start_time"`
|
||||
EndTime uint `json:"end_time"`
|
||||
StartTimeStr string `json:"start_time_str"`
|
||||
EndTimeStr string `json:"end_time_str"`
|
||||
CustomName string `json:"custom_name"`
|
||||
TimeBlockIds []int `json:"-"`
|
||||
}
|
||||
|
||||
type ByCustomNameNumber []*PeakValleyRuleCustomName
|
||||
|
||||
func (a ByCustomNameNumber) Len() int { return len(a) }
|
||||
func (a ByCustomNameNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a ByCustomNameNumber) Less(i, j int) bool {
|
||||
numI, _ := utils.ExtractNumber(a[i].CustomName)
|
||||
numJ, _ := utils.ExtractNumber(a[j].CustomName)
|
||||
return numI < numJ // 升序排序
|
||||
}
|
||||
9
repository/enter.go
Normal file
9
repository/enter.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package repository
|
||||
|
||||
import "energy-management-system/repository/peak-valley"
|
||||
|
||||
type groupRepository struct {
|
||||
peak_valley.PeakValley
|
||||
}
|
||||
|
||||
var GroupRepositorys = new(groupRepository)
|
||||
53
repository/peak-valley/peak_valley_rule.go
Normal file
53
repository/peak-valley/peak_valley_rule.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/form"
|
||||
"energy-management-system/global"
|
||||
peak_valley_model "energy-management-system/model/peak-valley"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PeakValley struct {
|
||||
}
|
||||
|
||||
// 一天的完整谷峰规则
|
||||
// 发电 (光伏)
|
||||
// 用电 (电机、生产)
|
||||
|
||||
//新建规则
|
||||
//
|
||||
//选择时间段 设置电价
|
||||
//(将时间段 转化为十分钟区块 查找到对应十分钟区块 创建该规则的电价)
|
||||
|
||||
func (r *PeakValley) CreatePeakValleyRule(tx *gorm.DB, d *peak_valley_model.PeakValleyRule) error {
|
||||
return tx.Create(d).Error
|
||||
}
|
||||
|
||||
func (r *PeakValley) UpdatePeakValleyRule(tx *gorm.DB, d *peak_valley_model.PeakValleyRule) error {
|
||||
return tx.Save(d).Error
|
||||
}
|
||||
|
||||
func (r *PeakValley) GetOnePeakValleyRule(qr map[string]interface{}) (d *peak_valley_model.PeakValleyRule, err error) {
|
||||
db := global.Db
|
||||
for key, value := range qr {
|
||||
db = db.Where(key, value)
|
||||
}
|
||||
err = db.First(&d).Error
|
||||
//if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// d = nil
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PeakValley) GetPeakValleyRulePage(req *form.PeakValleyRuleListReq) (count int64, list []*peak_valley_model.PeakValleyRule, err error) {
|
||||
db := global.Db.Model(&peak_valley_model.PeakValleyRule{})
|
||||
//for key, value := range qr {
|
||||
// db = db.Where(key, value)
|
||||
//}
|
||||
err = db.Count(&count).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = db.Offset((req.Page.GetPageIndex() - 1) * req.Page.GetPageSize()).Limit(req.Page.GetPageSize()).Order("rule_id desc").Find(&list).Error
|
||||
return
|
||||
}
|
||||
34
repository/peak-valley/peak_valley_time_block.go
Normal file
34
repository/peak-valley/peak_valley_time_block.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
peak_valley_model "energy-management-system/model/peak-valley"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (r *PeakValley) GetTimeBlockIdsByTimeBlock(tx *gorm.DB, startTime, endTime uint) (ids []uint, err error) {
|
||||
err = tx.Model(&peak_valley_model.PeakValleyTimeBlock{}).
|
||||
Where("start_time < ? AND end_time > ?", endTime, startTime).
|
||||
Pluck("block_index", &ids).Error
|
||||
return ids, err
|
||||
}
|
||||
|
||||
// GetBlockStartTime 获取最小开始时间
|
||||
func (r *PeakValley) GetBlockStartTime(blockId int) (startTime uint, err error) {
|
||||
var peakValleyTimeBlockModel peak_valley_model.PeakValleyTimeBlock
|
||||
err = global.Db.First(&peakValleyTimeBlockModel, blockId).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return peakValleyTimeBlockModel.StartTime, nil
|
||||
}
|
||||
|
||||
// GetBlockEndTime 获取最大结束时间
|
||||
func (r *PeakValley) GetBlockEndTime(blockId int) (endTime uint, err error) {
|
||||
var peakValleyTimeBlockModel peak_valley_model.PeakValleyTimeBlock
|
||||
err = global.Db.First(&peakValleyTimeBlockModel, blockId).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return peakValleyTimeBlockModel.EndTime, nil
|
||||
}
|
||||
87
repository/peak-valley/peak_valley_time_block_price.go
Normal file
87
repository/peak-valley/peak_valley_time_block_price.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package peak_valley
|
||||
|
||||
import (
|
||||
"energy-management-system/global"
|
||||
peak_valley_model "energy-management-system/model/peak-valley"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (r *PeakValley) CreatePeakValleyTimeBlockPrices(tx *gorm.DB, ds []*peak_valley_model.PeakValleyTimeBlockPrice) error {
|
||||
return tx.Create(ds).Error
|
||||
}
|
||||
|
||||
func (r *PeakValley) DeletePeakValleyTimeBlockPricesByRuleId(tx *gorm.DB, ruleId uint, unscoped bool) error {
|
||||
db := tx.Where("peak_valley_rule_id", ruleId)
|
||||
if unscoped {
|
||||
db = db.Unscoped()
|
||||
}
|
||||
return db.Delete(&peak_valley_model.PeakValleyTimeBlockPrice{}).Error
|
||||
}
|
||||
|
||||
func (r *PeakValley) GetPeakValleyTypes() map[int]string {
|
||||
return peak_valley_model.PeakValleyTypes
|
||||
}
|
||||
|
||||
// 获取指定规则的某个类型的时间段
|
||||
func (r *PeakValley) GetPeakValleyRulePriceByTypeAndRuleID(ruleId uint, pvType uint) (blockIds []int, err error) {
|
||||
db := global.Db.Model(&peak_valley_model.PeakValleyTimeBlockPrice{})
|
||||
//for key, value := range qr {
|
||||
db = db.Where("peak_valley_rule_id = ?", ruleId)
|
||||
db = db.Where("peak_valley_type = ?", pvType)
|
||||
err = db.Order("block_id ASC").Pluck("block_id", &blockIds).Error
|
||||
return
|
||||
}
|
||||
|
||||
// 获取指定规则的某个类型的时间段
|
||||
func (r *PeakValley) GetPeakValleyRulePriceByCustomNameAndRuleID(ruleId uint, customName string) (blockIds []int, err error) {
|
||||
db := global.Db.Model(&peak_valley_model.PeakValleyTimeBlockPrice{})
|
||||
//for key, value := range qr {
|
||||
db = db.Where("peak_valley_rule_id = ?", ruleId)
|
||||
db = db.Where("custom_name = ?", customName)
|
||||
err = db.Order("block_id ASC").Pluck("block_id", &blockIds).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PeakValley) GetPeakValleyRulePriceCustomName(blockId int, ruleId uint) (customName string, err error) {
|
||||
var peakValleyTimeBlockPriceModel peak_valley_model.PeakValleyTimeBlockPrice
|
||||
err = global.Db.Model(&peak_valley_model.PeakValleyTimeBlockPrice{}).
|
||||
Where("block_id = ?", blockId).
|
||||
Where("peak_valley_rule_id = ?", ruleId).
|
||||
First(&peakValleyTimeBlockPriceModel).Error
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return peakValleyTimeBlockPriceModel.CustomName, nil
|
||||
}
|
||||
|
||||
// GetPeakValleyRuleTypes 获取规则下 五种类型
|
||||
func (r *PeakValley) GetPeakValleyRuleTypes(ruleId int) (list []*peak_valley_model.PeakValleyRuleType, err error) {
|
||||
// 查询指定规则下的所有不同的 peak_valley_type
|
||||
err = global.Db.Model(&peak_valley_model.PeakValleyTimeBlockPrice{}).
|
||||
//Select("DISTINCT peak_valley_type,custom_name").
|
||||
Select("DISTINCT peak_valley_type,price").
|
||||
Where("peak_valley_rule_id = ?", ruleId).
|
||||
Find(&list).Error
|
||||
return
|
||||
}
|
||||
|
||||
// GetPeakValleyRuleCustomName 规则下 五种类型 + 自定义名称 + 价格
|
||||
func (r *PeakValley) GetPeakValleyRuleCustomName(ruleId int) (list []*peak_valley_model.PeakValleyRuleCustomName, err error) {
|
||||
// 查询指定规则下的所有不同的 peak_valley_type
|
||||
err = global.Db.Model(&peak_valley_model.PeakValleyTimeBlockPrice{}).
|
||||
//Select("DISTINCT peak_valley_type,custom_name").
|
||||
Select("DISTINCT custom_name,peak_valley_type,price").
|
||||
Where("peak_valley_rule_id = ?", ruleId).
|
||||
Find(&list).Error
|
||||
return
|
||||
}
|
||||
|
||||
//type ByCustomNameNumber []*peak_valley_model.PeakValleyRuleCustomName
|
||||
//
|
||||
//func (a ByCustomNameNumber) Len() int { return len(a) }
|
||||
//func (a ByCustomNameNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
//func (a ByCustomNameNumber) Less(i, j int) bool {
|
||||
// numI, _ := utils.ExtractNumber(a[i].CustomName)
|
||||
// numJ, _ := utils.ExtractNumber(a[j].CustomName)
|
||||
// return numI < numJ // 升序排序
|
||||
//}
|
||||
107
request/request.go
Normal file
107
request/request.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"energy-management-system/utils/exception"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/locales/en"
|
||||
"github.com/go-playground/locales/zh"
|
||||
ut "github.com/go-playground/universal-translator"
|
||||
"github.com/go-playground/validator/v10"
|
||||
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Trans 定义一个全局翻译器T
|
||||
var trans ut.Translator
|
||||
var validate *validator.Validate
|
||||
var ok bool
|
||||
|
||||
// InitTrans 初始化翻译器
|
||||
func InitTrans(locale ...string) {
|
||||
if len(locale) == 0 {
|
||||
locale = []string{"zh"}
|
||||
}
|
||||
// 修改gin框架中的Validator引擎属性,实现自定制
|
||||
if validate, ok = binding.Validator.Engine().(*validator.Validate); ok {
|
||||
|
||||
// zi
|
||||
//validate.SetTagName("ss")
|
||||
|
||||
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
|
||||
if name == "-" || name == "_" {
|
||||
return ""
|
||||
}
|
||||
return name
|
||||
})
|
||||
|
||||
// 第一个参数是备用(fallback)的语言环境
|
||||
uni := ut.New(en.New(), zh.New())
|
||||
trans, _ = uni.FindTranslator(locale[0])
|
||||
// 注册翻译器
|
||||
err := zhTranslations.RegisterDefaultTranslations(validate, trans)
|
||||
|
||||
// 注册自定义验证
|
||||
validate.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
|
||||
regRuler := "^1[3456789]{1}\\d{9}$"
|
||||
reg := regexp.MustCompile(regRuler)
|
||||
return reg.MatchString(fl.Field().String())
|
||||
})
|
||||
|
||||
// 注册自定义验证的翻译
|
||||
validate.RegisterTranslation("mobile", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("mobile", "手机号错误!", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("mobile", fe.Field())
|
||||
return t
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("[-]自定义gin验证器失败: %s \n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BindJson(c *gin.Context, f interface{}) {
|
||||
dealWithError(c.ShouldBindJSON(f), "JSON")
|
||||
}
|
||||
func BindJsonWith(c *gin.Context, f interface{}) {
|
||||
dealWithError(c.ShouldBindBodyWith(f, binding.JSON), "JSON")
|
||||
}
|
||||
func BindParam(c *gin.Context, f interface{}) {
|
||||
dealWithError(c.ShouldBindQuery(f), "FORM")
|
||||
}
|
||||
|
||||
func dealWithError(err error, t string) {
|
||||
if err != nil {
|
||||
var validationErrors validator.ValidationErrors
|
||||
var unmarshalTypeError *json.UnmarshalTypeError
|
||||
var numError *strconv.NumError
|
||||
switch {
|
||||
case errors.As(err, &validationErrors):
|
||||
exception.PanicMsg(removeTopStruct(err.(validator.ValidationErrors).Translate(trans)))
|
||||
case errors.As(err, &unmarshalTypeError):
|
||||
exception.PanicCodeMsg(exception.PARAMETER_ERROR, err.(*json.UnmarshalTypeError).Field+": 类型错误")
|
||||
case errors.As(err, &numError):
|
||||
exception.PanicCodeMsg(exception.PARAMETER_ERROR, err.(*strconv.NumError).Num+": 类型错误")
|
||||
default:
|
||||
exception.PanicCodeMsg(exception.PARAMETER_ERROR, fmt.Sprintf("请将参数放于%s中传递: ", t)+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeTopStruct(fields map[string]string) (re []string) {
|
||||
for _, err := range fields {
|
||||
re = append(re, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
30
response/response.go
Normal file
30
response/response.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"energy-management-system/utils/exception"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Data interface{} `json:"data"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// Result ... 正常业务获得结果
|
||||
func Result(code int, data interface{}, msg string, c *gin.Context) {
|
||||
c.JSON(http.StatusOK, Response{code, data, msg})
|
||||
}
|
||||
|
||||
func Success(c *gin.Context) {
|
||||
SuccessMsg("操作成功", c)
|
||||
}
|
||||
|
||||
func SuccessMsg(message string, c *gin.Context) {
|
||||
Result(exception.SUCCESS, map[string]interface{}{}, message, c)
|
||||
}
|
||||
|
||||
func SuccessData(data interface{}, c *gin.Context) {
|
||||
Result(exception.SUCCESS, data, "操作成功", c)
|
||||
}
|
||||
43
router/base.go-
Normal file
43
router/base.go-
Normal file
@@ -0,0 +1,43 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"energy-management-system/utils/exception"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ExceptionResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg interface{} `json:"msg"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
type Exception struct {
|
||||
HttpCode int `json:"-"`
|
||||
Code int `json:"code"`
|
||||
Msg interface{} `json:"msg"`
|
||||
Err error `json:"err"`
|
||||
}
|
||||
|
||||
func Panic(c *gin.Context, e *Exception) {
|
||||
c.JSON(e.HttpCode, ExceptionResponse{e.Code, e.Msg, GetReqPath(c)})
|
||||
}
|
||||
func Unknow(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{exception.UNKNOW_ERROR, "未知错误", GetReqPath(c)})
|
||||
}
|
||||
func Server(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, ExceptionResponse{exception.SERVER_ERROR, "服务器错误", GetReqPath(c)})
|
||||
}
|
||||
|
||||
func NotFoundR(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{exception.NOT_FOUND_ROUTE, "Not Found Route", GetReqPath(c)})
|
||||
}
|
||||
|
||||
func NotFoundM(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{exception.NOT_FOUND_METH, "Not Found Method", GetReqPath(c)})
|
||||
}
|
||||
|
||||
// GetReqPath 获取请求路径
|
||||
func GetReqPath(c *gin.Context) string {
|
||||
return c.Request.Method + " " + c.Request.URL.String()
|
||||
}
|
||||
2
router/recovery.go-
Normal file
2
router/recovery.go-
Normal file
@@ -0,0 +1,2 @@
|
||||
package router
|
||||
|
||||
40
router/router.go
Normal file
40
router/router.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
v1 "energy-management-system/api/v1"
|
||||
"energy-management-system/middleware"
|
||||
"energy-management-system/router/routes"
|
||||
"energy-management-system/utils/exception"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitRouter() *gin.Engine {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
r := gin.Default()
|
||||
r.NoRoute(exception.NotFoundR)
|
||||
r.NoMethod(exception.NotFoundM)
|
||||
r.Use(middleware.Cors(), middleware.Recovery())
|
||||
api := r.Group("api")
|
||||
{
|
||||
controllersV1 := new(v1.Controller)
|
||||
apiV1 := api.Group("v1")
|
||||
{
|
||||
apiV1.GET("test/test", controllersV1.TestApi.Test)
|
||||
apiV1.GET("test/testData", controllersV1.TestApi.TestData)
|
||||
}
|
||||
//// 需要权限校验
|
||||
//apiV1.Use(middleware.JWTAuth())
|
||||
//{
|
||||
// apiV1.GET("user/test_d", controllersV1.TestD)
|
||||
//}
|
||||
|
||||
// 需要权限校验
|
||||
//apiV1.Use(middleware.CasbinRBAC())
|
||||
|
||||
{
|
||||
routes.GroupRoutes.PeakValley.InitPeakValley(apiV1)
|
||||
}
|
||||
|
||||
}
|
||||
return r
|
||||
}
|
||||
7
router/routes/enter.go
Normal file
7
router/routes/enter.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package routes
|
||||
|
||||
type groupRoutes struct {
|
||||
PeakValley
|
||||
}
|
||||
|
||||
var GroupRoutes = new(groupRoutes)
|
||||
38
router/routes/peak_valley.go
Normal file
38
router/routes/peak_valley.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
v1 "energy-management-system/api/v1"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type PeakValley struct{}
|
||||
|
||||
func (r *PeakValley) InitPeakValley(Router *gin.RouterGroup) {
|
||||
peakValleyApi := Router.Group("peakValley")
|
||||
{
|
||||
|
||||
peakValleyApi.GET("types", v1.Controllers.PeakValley.GetPeakValleyTypes)
|
||||
peakValleyApi.GET("ruleList", v1.Controllers.PeakValley.PeakValleyRuleList)
|
||||
peakValleyApi.POST("createRule", v1.Controllers.PeakValley.CreatePeakValleyRule)
|
||||
peakValleyApi.PUT("updateRule", v1.Controllers.PeakValley.UpdatePeakValleyRule)
|
||||
peakValleyApi.GET("ruleDetail/:id", v1.Controllers.PeakValley.PeakValleyRuleDetail)
|
||||
peakValleyApi.GET("ruleEditDetail/:id", v1.Controllers.PeakValley.PeakValleyRuleEditDetail)
|
||||
|
||||
//userapi.DELETE(":id", api.Controllers.UserApi.DeleteUser)
|
||||
|
||||
//// 个人信息管理
|
||||
//userapi.GET("detail", api.Controllers.UserApi.GetUserDetail)
|
||||
//userapi.PUT("update", api.Controllers.UserApi.UpdateUsers)
|
||||
//userapi.GET("logout", api.Controllers.UserApi.Logout)
|
||||
//userapi.GET("refresh", api.Controllers.UserApi.RefreshToken)
|
||||
//
|
||||
//// 用户管理
|
||||
//userapi.GET("", api.Controllers.UserApi.GetUserListByPage)
|
||||
//userapi.POST("", api.Controllers.UserApi.CreateUser)
|
||||
//userapi.PUT("", api.Controllers.UserApi.UpdateUser)
|
||||
//userapi.DELETE(":id", api.Controllers.UserApi.DeleteUser)
|
||||
//userapi.GET(":id", api.Controllers.UserApi.GetUser)
|
||||
//userapi.POST("transform", api.Controllers.UserApi.TransformUser)
|
||||
|
||||
}
|
||||
}
|
||||
7
service/enter.go
Normal file
7
service/enter.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package service
|
||||
|
||||
type groupService struct {
|
||||
PeakValley
|
||||
}
|
||||
|
||||
var GroupServices = new(groupService)
|
||||
276
service/peak_valley.go
Normal file
276
service/peak_valley.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"energy-management-system/form"
|
||||
"energy-management-system/global"
|
||||
peak_valley_model "energy-management-system/model/peak-valley"
|
||||
"energy-management-system/repository"
|
||||
"energy-management-system/utils"
|
||||
"energy-management-system/utils/exception"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type PeakValley struct{}
|
||||
|
||||
// GetPeakValleyType 获取峰谷类型
|
||||
func (r *PeakValley) GetPeakValleyType() (typeList []*peak_valley_model.PeakValleyType) {
|
||||
types := repository.GroupRepositorys.PeakValley.GetPeakValleyTypes()
|
||||
for key, val := range types {
|
||||
typeList = append(typeList, &peak_valley_model.PeakValleyType{
|
||||
Value: key,
|
||||
Title: val,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CreatePeakValleyRule 创建峰谷规则
|
||||
func (r *PeakValley) CreatePeakValleyRule(req *form.CreatePeakValleyRuleReq) {
|
||||
var err error
|
||||
tx := global.Db.Begin()
|
||||
// 确保在结束时提交或回滚事务
|
||||
defer func() {
|
||||
if rec := recover(); rec != nil {
|
||||
tx.Rollback() // 如果发生错误,回滚事务
|
||||
fmt.Println("事务回滚")
|
||||
exception.PanicMsg(rec)
|
||||
} else if err != nil {
|
||||
tx.Rollback() // 错误时回滚事务
|
||||
fmt.Println("事务回滚")
|
||||
exception.PanicMsgErr(err, err.Error())
|
||||
} else {
|
||||
err = tx.Commit().Error // 提交事务
|
||||
if err != nil {
|
||||
exception.PanicMsgErr(err, "事务提交失败")
|
||||
}
|
||||
}
|
||||
}()
|
||||
pvr := &peak_valley_model.PeakValleyRule{}
|
||||
pvr.RuleName = req.RuleName
|
||||
pvr.Description = req.Description
|
||||
err = repository.GroupRepositorys.PeakValley.CreatePeakValleyRule(tx, pvr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var total, start, end, blockTotal = 0, 0, 0, 0
|
||||
|
||||
// 每个时间段的时间区块ID
|
||||
var timeBlockIds []uint
|
||||
var timeBlockIdsMap = make(map[string][]uint)
|
||||
|
||||
for _, item := range req.RuleItem {
|
||||
start, end, blockTotal, err = utils.GetMinutesFromTimeRange(item.StartTime, item.EndTime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total += blockTotal
|
||||
if total > peak_valley_model.MinutesInADay {
|
||||
err = errors.New("选择的时间段超过一天")
|
||||
return
|
||||
}
|
||||
timeBlockIds, err = repository.GroupRepositorys.PeakValley.GetTimeBlockIdsByTimeBlock(tx, uint(start), uint(end))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timeBlockIdsMap[item.StartTime+item.EndTime] = timeBlockIds
|
||||
}
|
||||
if total < peak_valley_model.MinutesInADay {
|
||||
err = errors.New("各个时间段累加不足一天")
|
||||
return
|
||||
}
|
||||
var timeBlockPrices []*peak_valley_model.PeakValleyTimeBlockPrice
|
||||
for index, item := range req.RuleItem {
|
||||
// 获取某个区块的具体时间区块编号
|
||||
timeBlockIds = timeBlockIdsMap[item.StartTime+item.EndTime]
|
||||
for _, timeBlockId := range timeBlockIds {
|
||||
timeBlockPrices = append(timeBlockPrices, &peak_valley_model.PeakValleyTimeBlockPrice{
|
||||
CustomName: strconv.Itoa(index+1) + "_TIME_" + item.CustomName,
|
||||
BlockId: timeBlockId,
|
||||
Price: item.Price,
|
||||
PeakValleyRuleId: pvr.RuleId,
|
||||
PeakValleyType: item.PeakValleyType,
|
||||
})
|
||||
}
|
||||
}
|
||||
err = repository.GroupRepositorys.PeakValley.CreatePeakValleyTimeBlockPrices(tx, timeBlockPrices)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdatePeakValleyRule 修改峰谷规则
|
||||
func (r *PeakValley) UpdatePeakValleyRule(req *form.UpdatePeakValleyRuleReq) {
|
||||
var err error
|
||||
tx := global.Db.Begin()
|
||||
// 确保在结束时提交或回滚事务
|
||||
defer func() {
|
||||
if rec := recover(); rec != nil {
|
||||
tx.Rollback() // 如果发生错误,回滚事务
|
||||
fmt.Println("事务回滚1", rec)
|
||||
exception.PanicMsg(rec)
|
||||
} else if err != nil {
|
||||
tx.Rollback() // 错误时回滚事务
|
||||
fmt.Println("事务回滚2", err)
|
||||
exception.PanicMsgErr(err, err.Error())
|
||||
} else {
|
||||
err = tx.Commit().Error // 提交事务
|
||||
if err != nil {
|
||||
exception.PanicMsgErr(err, "事务提交失败")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
pvr, err := repository.GroupRepositorys.PeakValley.GetOnePeakValleyRule(map[string]interface{}{"rule_id": req.RuleId})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pvr.RuleName = req.RuleName
|
||||
pvr.Description = req.Description
|
||||
err = repository.GroupRepositorys.PeakValley.UpdatePeakValleyRule(tx, pvr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var total, start, end, blockTotal = 0, 0, 0, 0
|
||||
|
||||
// 每个时间段的时间区块ID
|
||||
var timeBlockIds []uint
|
||||
var timeBlockIdsMap = make(map[string][]uint)
|
||||
|
||||
for _, item := range req.RuleItem {
|
||||
start, end, blockTotal, err = utils.GetMinutesFromTimeRange(item.StartTime, item.EndTime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total += blockTotal
|
||||
if total > peak_valley_model.MinutesInADay {
|
||||
err = errors.New("选择的时间段超过一天")
|
||||
return
|
||||
}
|
||||
timeBlockIds, err = repository.GroupRepositorys.PeakValley.GetTimeBlockIdsByTimeBlock(tx, uint(start), uint(end))
|
||||
exception.PanicMsgBool(err != nil, "获取时间区块ID列表失败")
|
||||
timeBlockIdsMap[item.StartTime+item.EndTime] = timeBlockIds
|
||||
}
|
||||
if total < peak_valley_model.MinutesInADay {
|
||||
err = errors.New("各个时间段累加不足一天")
|
||||
return
|
||||
}
|
||||
// 删除旧的
|
||||
err = repository.GroupRepositorys.PeakValley.DeletePeakValleyTimeBlockPricesByRuleId(tx, uint(req.RuleId), true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//
|
||||
var timeBlockPrices []*peak_valley_model.PeakValleyTimeBlockPrice
|
||||
for index, item := range req.RuleItem {
|
||||
// 获取某个区块的具体时间区块编号
|
||||
timeBlockIds = timeBlockIdsMap[item.StartTime+item.EndTime]
|
||||
for _, timeBlockId := range timeBlockIds {
|
||||
timeBlockPrices = append(timeBlockPrices, &peak_valley_model.PeakValleyTimeBlockPrice{
|
||||
CustomName: strconv.Itoa(index+1) + "_TIME_" + item.CustomName,
|
||||
BlockId: timeBlockId,
|
||||
Price: item.Price,
|
||||
PeakValleyRuleId: pvr.RuleId,
|
||||
PeakValleyType: item.PeakValleyType,
|
||||
})
|
||||
}
|
||||
}
|
||||
err = repository.GroupRepositorys.PeakValley.CreatePeakValleyTimeBlockPrices(tx, timeBlockPrices)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PeakValleyRuleList 峰谷规则列表
|
||||
func (r *PeakValley) PeakValleyRuleList(req *form.PeakValleyRuleListReq) map[string]interface{} {
|
||||
count, list, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePage(req)
|
||||
if err != nil {
|
||||
exception.PanicMsgErr(err, "获取列表失败")
|
||||
//return
|
||||
}
|
||||
ListRsp := make(map[string]interface{})
|
||||
ListRsp["total"] = count
|
||||
ListRsp["list"] = list
|
||||
return ListRsp
|
||||
}
|
||||
|
||||
// PeakValleyRuleDetail 获取规则详情吧
|
||||
func (r *PeakValley) PeakValleyRuleDetail(req *form.PeakValleyRuleDetailReq) map[string]interface{} {
|
||||
// 获取分了多少个时间段 以及每个时间段的自定义名称 峰谷类型
|
||||
ruleTypes, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRuleTypes(req.RuleId)
|
||||
fmt.Println(ruleTypes)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败1")
|
||||
// 查询指定规则 指定峰谷类型的区块
|
||||
for idx, ruleType := range ruleTypes {
|
||||
// 查询当前类型的时间区块
|
||||
typeBlockList, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceByTypeAndRuleID(uint(req.RuleId), ruleType.PeakValleyType)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败2")
|
||||
// 根据连贯性 小区块 组合成大区块 (一个区块 或者多个区块)
|
||||
blocks := utils.SplitIntoGroups(typeBlockList)
|
||||
for _, block := range blocks {
|
||||
maxBlockId, minBlockId, err := utils.GetSplitIntMaxMin(block)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败3")
|
||||
customName, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceCustomName(minBlockId, uint(req.RuleId))
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败4")
|
||||
startTime, err := repository.GroupRepositorys.PeakValley.GetBlockStartTime(minBlockId)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败5")
|
||||
endTime, err := repository.GroupRepositorys.PeakValley.GetBlockEndTime(maxBlockId)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败6")
|
||||
startTimeStr := fmt.Sprintf("%02d:%02d", startTime/60, startTime%60)
|
||||
endTimeStr := fmt.Sprintf("%02d:%02d", endTime/60, endTime%60)
|
||||
ruleTimeBlock := peak_valley_model.RuleTimeBlock{
|
||||
TimeBlockIds: block,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
StartTimeStr: startTimeStr,
|
||||
EndTimeStr: endTimeStr,
|
||||
CustomName: customName,
|
||||
}
|
||||
ruleTypes[idx].RuleTimeBlocks = append(ruleTypes[idx].RuleTimeBlocks, ruleTimeBlock)
|
||||
}
|
||||
}
|
||||
DetailRsp := make(map[string]interface{})
|
||||
DetailRsp["rule_id"] = req.RuleId
|
||||
DetailRsp["detail"] = ruleTypes
|
||||
return DetailRsp
|
||||
}
|
||||
|
||||
// PeakValleyRuleEditDetail 获取规则详情-编辑使用
|
||||
func (r *PeakValley) PeakValleyRuleEditDetail(req *form.PeakValleyRuleEditDetailReq) map[string]interface{} {
|
||||
// 获取分了多少个时间段 以及每个时间段的自定义名称 峰谷类型
|
||||
customNames, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRuleCustomName(req.RuleId)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败1")
|
||||
// 查询指定规则 指定峰谷类型的区块
|
||||
for idx, customName := range customNames {
|
||||
// 查询当前类型的时间区块
|
||||
customNameBlockList, err := repository.GroupRepositorys.PeakValley.GetPeakValleyRulePriceByCustomNameAndRuleID(uint(req.RuleId), customName.CustomName)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败2")
|
||||
maxBlockId, minBlockId, err := utils.GetSplitIntMaxMin(customNameBlockList)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败3")
|
||||
startTime, err := repository.GroupRepositorys.PeakValley.GetBlockStartTime(minBlockId)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败4")
|
||||
endTime, err := repository.GroupRepositorys.PeakValley.GetBlockEndTime(maxBlockId)
|
||||
exception.PanicMsgBool(err != nil, "获取规则区块类型失败5")
|
||||
startTimeStr := fmt.Sprintf("%02d:%02d", startTime/60, startTime%60)
|
||||
endTimeStr := fmt.Sprintf("%02d:%02d", endTime/60, endTime%60)
|
||||
//dump.P(customNameBlockList)
|
||||
customNames[idx].StartTimeStr = startTimeStr
|
||||
customNames[idx].StartTime = startTime
|
||||
customNames[idx].EndTimeStr = endTimeStr
|
||||
customNames[idx].EndTime = endTime
|
||||
customNames[idx].EndTimeStr = endTimeStr
|
||||
}
|
||||
|
||||
// 根据 自定义名称 中的数字部分进行升序排序
|
||||
sort.Sort(peak_valley_model.ByCustomNameNumber(customNames))
|
||||
|
||||
DetailRsp := make(map[string]interface{})
|
||||
DetailRsp["rule_id"] = req.RuleId
|
||||
DetailRsp["detail"] = customNames
|
||||
return DetailRsp
|
||||
}
|
||||
47
utils/exception/code.go
Normal file
47
utils/exception/code.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package exception
|
||||
|
||||
const (
|
||||
SUCCESS = 0 // 操作成功
|
||||
ERROR = 10000 // 默认错误返回
|
||||
|
||||
SERVER_ERROR = 10001 // 服务器错误
|
||||
UNKNOW_ERROR = 10002 // 未知错误
|
||||
REMOTE_ERROR = 10003 // 远程服务错误
|
||||
IP_LINMIT = 10004 // 地址限制
|
||||
IP_LINMIT_CODE = 10014 // 地址限制需要验证码
|
||||
NO_PERMISSION = 10005 // 未拥有授权
|
||||
PARAMETER_ERROR = 10008 // 参数错误
|
||||
RPC_ERROR = 10013 // RPC通讯错误
|
||||
NOT_FOUND_ROUTE = 10020 // 未查询到路由
|
||||
NOT_FOUND_METH = 10021 // 未查询到方式
|
||||
|
||||
NOT_FOUND = 10022 // 未查询到
|
||||
AUTH_ERROR = 10023 // 认证错误
|
||||
NO_VALID_TOKEN = 10024 // token无效
|
||||
REPEAD = 10025 // 重复数据或操作
|
||||
OUT_SLINCE = 10026 // 超出限制
|
||||
DB_ERRROR = 10027 // 数据库错误
|
||||
SENSITIVE = 10028 // 敏感词语
|
||||
)
|
||||
const (
|
||||
//用户
|
||||
NOT_FOUND_USER = 20001 // 未查询到用户
|
||||
EXIST_USER = 20002 // 用户已存在
|
||||
NO_BELONG_ACTION = 20003 // 越权操作
|
||||
NO_PHONE = 20004 // 未验证手机号
|
||||
|
||||
//订单
|
||||
ORDER_ERROR = 20100 // 订单统用错误
|
||||
NO_ORDER = 20101 // 订单不存在
|
||||
NO_PAID_ORDER = 20102 // 订单未支付
|
||||
PAID_ORDER = 20103 // 订单已支付
|
||||
EXPIRE_ORDER = 20104 // 订单超时
|
||||
DONE_ORDER = 20105 // 订单已完结
|
||||
NO_BELONG_ORDER = 20106 // 不属于自己的订单
|
||||
|
||||
//积分
|
||||
SIGNED = 20200 // 已签到
|
||||
NO_ENOUGH_POINT = 20201 // 积分不足
|
||||
NO_ILLEGAL_CHANNEL = 20202 // 渠道非法
|
||||
NO_ILLEGAL_SIGN = 20203 // 渠道非签到
|
||||
)
|
||||
81
utils/exception/exception.go
Normal file
81
utils/exception/exception.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package exception
|
||||
|
||||
import (
|
||||
"energy-management-system/utils"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Exception struct {
|
||||
HttpCode int `json:"-"`
|
||||
Code int `json:"code"`
|
||||
Msg interface{} `json:"msg"`
|
||||
Err error `json:"err"`
|
||||
}
|
||||
|
||||
type ExceptionResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg interface{} `json:"msg"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func (r *Exception) Error() interface{} {
|
||||
return r.Msg
|
||||
}
|
||||
|
||||
func NotFoundR(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_ROUTE, "Not Found Route", utils.GetReqPath(c)})
|
||||
}
|
||||
|
||||
func NotFoundM(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{NOT_FOUND_METH, "Not Found Method", utils.GetReqPath(c)})
|
||||
}
|
||||
|
||||
func Panic(c *gin.Context, e *Exception) {
|
||||
c.JSON(e.HttpCode, ExceptionResponse{e.Code, e.Msg, utils.GetReqPath(c)})
|
||||
}
|
||||
func Unknow(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, ExceptionResponse{UNKNOW_ERROR, "未知错误", utils.GetReqPath(c)})
|
||||
}
|
||||
func Server(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, ExceptionResponse{SERVER_ERROR, "服务器错误", utils.GetReqPath(c)})
|
||||
}
|
||||
|
||||
// FailMsg 主动抛出错误Exception类型
|
||||
func FailMsg(msg interface{}) *Exception {
|
||||
return &Exception{http.StatusOK, ERROR, msg, nil}
|
||||
}
|
||||
|
||||
func FailCodeMsg(code int, msg string) *Exception {
|
||||
return &Exception{http.StatusOK, code, msg, nil}
|
||||
}
|
||||
|
||||
func PanicMsg(msg interface{}) {
|
||||
PanicMsgBool(true, msg)
|
||||
}
|
||||
func PanicCodeMsg(code int, msg string) {
|
||||
PanicCodeMsgBool(true, code, msg)
|
||||
}
|
||||
|
||||
func PanicMsgBool(flag bool, msg interface{}) {
|
||||
if flag {
|
||||
panic(&Exception{http.StatusOK, ERROR, msg, nil})
|
||||
}
|
||||
}
|
||||
func PanicCodeMsgBool(flag bool, code int, msg string) {
|
||||
if flag {
|
||||
panic(&Exception{http.StatusOK, code, msg, nil})
|
||||
}
|
||||
}
|
||||
|
||||
func PanicMsgErr(err error, msg interface{}) {
|
||||
if err != nil {
|
||||
panic(&Exception{http.StatusOK, ERROR, msg, err})
|
||||
}
|
||||
}
|
||||
func PanicCodeMsgErr(err error, code int, msg string) {
|
||||
if err != nil {
|
||||
panic(&Exception{http.StatusOK, code, msg, err})
|
||||
}
|
||||
}
|
||||
189
utils/utils.go
Normal file
189
utils/utils.go
Normal file
@@ -0,0 +1,189 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetReqPath(c *gin.Context) string {
|
||||
return c.Request.Method + " " + c.Request.URL.String()
|
||||
}
|
||||
|
||||
func TimeFormat(t time.Time) string {
|
||||
timeString := t.Format("2006/01/02 - 15:04:05")
|
||||
return timeString
|
||||
}
|
||||
|
||||
// GetMinutesFromTimeRange 接受时间范围字符串,返回开始分钟、结束分钟和总分钟数
|
||||
func GetMinutesFromTimeRange(startTimeStr, endTimeStr string) (int, int, int, error) {
|
||||
startTimeParts := strings.Split(startTimeStr, ":")
|
||||
endTimeParts := strings.Split(endTimeStr, ":")
|
||||
if len(startTimeParts) != 2 || len(endTimeParts) != 2 {
|
||||
return 0, 0, 0, fmt.Errorf("时间格式不正确,应该是 HH:MM")
|
||||
}
|
||||
startHour, err := strconv.Atoi(startTimeParts[0])
|
||||
if err != nil {
|
||||
return 0, 0, 0, fmt.Errorf("无效的开始小时: %s", startTimeParts[0])
|
||||
}
|
||||
startMinute, err := strconv.Atoi(startTimeParts[1])
|
||||
if err != nil {
|
||||
return 0, 0, 0, fmt.Errorf("无效的开始分钟: %s", startTimeParts[1])
|
||||
}
|
||||
endHour, err := strconv.Atoi(endTimeParts[0])
|
||||
if err != nil {
|
||||
return 0, 0, 0, fmt.Errorf("无效的结束小时: %s", endTimeParts[0])
|
||||
}
|
||||
endMinute, err := strconv.Atoi(endTimeParts[1])
|
||||
if err != nil {
|
||||
return 0, 0, 0, fmt.Errorf("无效的结束分钟: %s", endTimeParts[1])
|
||||
}
|
||||
// 计算开始和结束的总分钟
|
||||
startMinutes := startHour*60 + startMinute
|
||||
endMinutes := endHour*60 + endMinute
|
||||
// 判断开始时间和结束时间的大小关系
|
||||
if startMinutes >= endMinutes {
|
||||
return 0, 0, 0, fmt.Errorf("开始时间必须小于结束时间")
|
||||
}
|
||||
// 计算总分钟数
|
||||
totalMinutes := endMinutes - startMinutes
|
||||
return startMinutes, endMinutes, totalMinutes, nil
|
||||
}
|
||||
|
||||
var (
|
||||
dunno = []byte("???")
|
||||
centerDot = []byte("·")
|
||||
dot = []byte(".")
|
||||
slash = []byte("/")
|
||||
)
|
||||
|
||||
func Stack(skip int) {
|
||||
var lines [][]byte
|
||||
var lastFile string
|
||||
for i := skip; ; i++ { // Skip the expected number of frames
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%s:%d (0x%x)\n", file, line, pc)
|
||||
if file != lastFile {
|
||||
data, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines = bytes.Split(data, []byte{'\n'})
|
||||
lastFile = file
|
||||
}
|
||||
fmt.Printf("\t%s: %s\n", function(pc), source(lines, line))
|
||||
}
|
||||
}
|
||||
|
||||
func source(lines [][]byte, n int) []byte {
|
||||
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
|
||||
if n < 0 || n >= len(lines) {
|
||||
return dunno
|
||||
}
|
||||
return bytes.TrimSpace(lines[n])
|
||||
}
|
||||
|
||||
// function returns, if possible, the name of the function containing the PC.
|
||||
func function(pc uintptr) []byte {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
return dunno
|
||||
}
|
||||
name := []byte(fn.Name())
|
||||
// The name includes the path name to the package, which is unnecessary
|
||||
// since the file name is already included. Plus, it has center dots.
|
||||
// That is, we see
|
||||
// runtime/debug.*T·ptrmethod
|
||||
// and want
|
||||
// *T.ptrmethod
|
||||
// Also the package path might contains dot (e.g. code.google.com/...),
|
||||
// so first eliminate the path prefix
|
||||
if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 {
|
||||
name = name[lastSlash+1:]
|
||||
}
|
||||
if period := bytes.Index(name, dot); period >= 0 {
|
||||
name = name[period+1:]
|
||||
}
|
||||
name = bytes.Replace(name, centerDot, dot, -1)
|
||||
return name
|
||||
}
|
||||
|
||||
// ExtractNumber 提取数字并返回整数
|
||||
func ExtractNumber(id string) (int, error) {
|
||||
parts := strings.Split(id, "_")
|
||||
if len(parts) == 0 {
|
||||
return 0, fmt.Errorf("无效的 Id: %s", id)
|
||||
}
|
||||
numStr := parts[0]
|
||||
num, err := strconv.Atoi(numStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("转换错误: %v", err)
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
// GetSplitIntMaxMin 函数返回切片中的最大值和最小值
|
||||
func GetSplitIntMaxMin(nums []int) (max int, min int, err error) {
|
||||
if len(nums) == 0 {
|
||||
return 0, 0, fmt.Errorf("切片为空")
|
||||
}
|
||||
|
||||
// 初始化最大值和最小值
|
||||
max = math.MinInt64 // 设置为最小整数
|
||||
min = math.MaxInt64 // 设置为最大整数
|
||||
|
||||
// 遍历切片,找到最大值和最小值
|
||||
for _, num := range nums {
|
||||
if num > max {
|
||||
max = num
|
||||
}
|
||||
if num < min {
|
||||
min = num
|
||||
}
|
||||
}
|
||||
|
||||
return max, min, nil
|
||||
}
|
||||
|
||||
// SplitIntoGroups 切片根据是否连续来进行分组
|
||||
func SplitIntoGroups(nums []int) [][]int {
|
||||
if len(nums) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将切片排序
|
||||
sort.Ints(nums)
|
||||
|
||||
var groups [][]int
|
||||
var currentGroup []int
|
||||
|
||||
// 初始化第一组
|
||||
currentGroup = append(currentGroup, nums[0])
|
||||
|
||||
for i := 1; i < len(nums); i++ {
|
||||
// 检查当前数字与前一个数字的差值
|
||||
if nums[i] == nums[i-1]+1 {
|
||||
// 如果是连续的,添加到当前组
|
||||
currentGroup = append(currentGroup, nums[i])
|
||||
} else {
|
||||
// 如果不连续,保存当前组并开始新的一组
|
||||
groups = append(groups, currentGroup)
|
||||
currentGroup = []int{nums[i]} // 开始新的一组
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一组
|
||||
groups = append(groups, currentGroup)
|
||||
|
||||
return groups
|
||||
}
|
||||
Reference in New Issue
Block a user