v1.0.0
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
package cmn
|
||||
|
||||
import (
|
||||
// "calendar-note-gin/assets"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sun-panel/assets"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// 时间格式
|
||||
|
||||
TimeFormatMode1 = "2006-01-02 15:04:05" // 标准格式
|
||||
TimeFormatMode4 = "2006-01-02 15:04" // 标准格式 无秒
|
||||
TimeFormatMode2 = "Mon Jan 2 15:04:05 -0700 MST 2006"
|
||||
TimeFormatMode3 = "Mon, 2 Jan 2006 15:04:05 -0700 MST" // webdav格式
|
||||
TimeYYYY_mm_dd = "2006-01-02"
|
||||
TIME_MODE_REMINDER_TIME = "200601021504" // 提醒定时器的执行时间格式
|
||||
|
||||
// 随机码字典
|
||||
|
||||
RAND_CODE_MODE1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // 大写,小写,数字
|
||||
RAND_CODE_MODE2 = "abcdefghijklmnopqrstuvwxyz0123456789" // 小写,数字
|
||||
RAND_CODE_MODE3 = "0123456789" // 数字
|
||||
)
|
||||
|
||||
type Version_Info struct {
|
||||
Version string
|
||||
Version_code int
|
||||
}
|
||||
|
||||
func GetTime() string {
|
||||
return time.Unix(time.Now().Unix(), 0).Format(TimeFormatMode1)
|
||||
}
|
||||
|
||||
// 字符串转时间
|
||||
func StrToTime(timeMode, formatTimeStr string) (t time.Time, err error) {
|
||||
loc, err := time.LoadLocation("Local")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
t, err = time.ParseInLocation(timeMode, formatTimeStr, loc) //使用模板在对应时区转化为time.time类型
|
||||
return
|
||||
}
|
||||
|
||||
// md5获取
|
||||
func Md5(str string) string {
|
||||
md5Byte := md5.Sum([]byte(str))
|
||||
return hex.EncodeToString(md5Byte[:])
|
||||
}
|
||||
|
||||
func RandNum(n int) int {
|
||||
rand.Seed(time.Now().Unix())
|
||||
return rand.Intn(n)
|
||||
}
|
||||
|
||||
// 随机生成编码
|
||||
// 随机码字典内容 参考常量 RAND_CODE_MODE*
|
||||
func BuildRandCode(count int, secret_content string) (code string) {
|
||||
return BuildRandCodeBySeed(count, secret_content, time.Now().UnixNano()+int64(rand.Intn(100)))
|
||||
}
|
||||
|
||||
// 随机生成编码 参考常量 RAND_CODE_MODE*
|
||||
func BuildRandCodeBySeed(count int, secret_content string, seed int64) (code string) {
|
||||
// 获取纳秒作为随机数种子
|
||||
rand.Seed(seed)
|
||||
if secret_content == "" {
|
||||
secret_content = RAND_CODE_MODE1
|
||||
}
|
||||
for i := 0; i < count; i++ {
|
||||
code += string(secret_content[rand.Intn(len(secret_content))])
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func InSlice(items []string, item string) bool {
|
||||
for _, eachItem := range items {
|
||||
if eachItem == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 字符串转int
|
||||
func StrToInt(str string) int {
|
||||
intStr, _ := strconv.Atoi(str)
|
||||
return intStr
|
||||
}
|
||||
|
||||
// uint 转string
|
||||
func UintToStr(c uint) string {
|
||||
return strconv.FormatUint(uint64(c), 10)
|
||||
}
|
||||
|
||||
// uint 转string
|
||||
func StrToUint(s string) uint {
|
||||
// i, _ := strconv.Atoi(s)
|
||||
u, _ := strconv.ParseUint(s, 10, 64)
|
||||
return uint(u)
|
||||
}
|
||||
|
||||
// 获取系统信息
|
||||
func GetSysVersionInfo() Version_Info {
|
||||
cBytes, _ := assets.Asset("assets/version")
|
||||
c := string(cBytes)
|
||||
info := strings.Split(c, "|")
|
||||
|
||||
return Version_Info{
|
||||
Version_code: StrToInt(info[0]),
|
||||
Version: info[1],
|
||||
}
|
||||
}
|
||||
|
||||
// 文件是否存在
|
||||
func PathExists(path string) (bool, error) {
|
||||
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 截取字符串,支持多字节字符
|
||||
// start:起始下标,负数从从尾部开始,最后一个为-1
|
||||
// length:截取长度,负数表示截取到末尾
|
||||
func SubRuneStr(str string, start int, length int) (result string) {
|
||||
s := []rune(str)
|
||||
total := len(s)
|
||||
if total == 0 {
|
||||
return
|
||||
}
|
||||
// 允许从尾部开始计算
|
||||
if start < 0 {
|
||||
start = total + start
|
||||
if start < 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
if start > total {
|
||||
return
|
||||
}
|
||||
// 到末尾
|
||||
if length < 0 {
|
||||
length = total
|
||||
}
|
||||
|
||||
end := start + length
|
||||
if end > total {
|
||||
result = string(s[start:])
|
||||
} else {
|
||||
result = string(s[start:end])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 字符串长度
|
||||
func RuneStrLen(str string) int {
|
||||
return len([]rune(str))
|
||||
}
|
||||
|
||||
// 是否在数组中
|
||||
func InStringArray(arr []string, item string) bool {
|
||||
for _, v := range arr {
|
||||
if v == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 从Assets文件夹中抽取文件保存到路劲
|
||||
// AssetsTakeFileToPath("config.ini", targetPath string)
|
||||
func AssetsTakeFileToPath(assetsPath, targetPath string) error {
|
||||
bytes, _ := assets.Asset("assets/" + assetsPath)
|
||||
targetPathPath := path.Dir(targetPath)
|
||||
exists, err := PathExists(targetPathPath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
if err := os.MkdirAll(targetPathPath, 0777); err != nil {
|
||||
fmt.Println(456)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return ioutil.WriteFile(targetPath, bytes, 0666)
|
||||
}
|
||||
|
||||
// 密码加密
|
||||
func PasswordEncryption(password string) string {
|
||||
return Md5(Md5(Md5(password)))
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package cmn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type LogStruct struct {
|
||||
Writer io.Writer
|
||||
File *os.File
|
||||
Print_cfg bool // 此条打印到控制台
|
||||
Separator string
|
||||
}
|
||||
|
||||
type LogFileld map[string]string
|
||||
|
||||
var (
|
||||
LOG_DEBUG = "Debug"
|
||||
LOG_ERROR = "Error"
|
||||
LOG_Info = "Info"
|
||||
LOG_WARNING = "Warning"
|
||||
)
|
||||
|
||||
// 日志颜色
|
||||
var colors = map[string]func(a ...interface{}) string{
|
||||
"Warning": color.New(color.FgYellow).Add(color.Bold).SprintFunc(),
|
||||
"Panic": color.New(color.BgRed).Add(color.Bold).SprintFunc(),
|
||||
"Error": color.New(color.FgRed).Add(color.Bold).SprintFunc(),
|
||||
"Info": color.New(color.FgCyan).Add(color.Bold).SprintFunc(),
|
||||
"Debug": color.New(color.FgWhite).Add(color.Bold).SprintFunc(),
|
||||
}
|
||||
|
||||
// 不同级别前缀与时间的间隔,保持宽度一致
|
||||
var spaces = map[string]string{
|
||||
"Warning": "",
|
||||
"Panic": " ",
|
||||
"Error": " ",
|
||||
"Info": " ",
|
||||
"Debug": " ",
|
||||
}
|
||||
|
||||
// 运行日志静态类
|
||||
var runLogStatic = LogStruct{}
|
||||
|
||||
// 控制台打印
|
||||
// Warning Panic Error Info Debug
|
||||
func Pln(prefix string, msg string) {
|
||||
fmt.Printf(
|
||||
"%s%s %s %s\n",
|
||||
colors[prefix]("["+prefix+"]"),
|
||||
spaces[prefix],
|
||||
time.Now().Format(TimeFormatMode1),
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
// 控制台打印,支持颜色
|
||||
func Print(color, key, msg string) {
|
||||
fmt.Printf(
|
||||
"%s%s %s\n",
|
||||
colors[color](key),
|
||||
time.Now().Format(TimeFormatMode1),
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
// func Debug(a ...interface{}) {
|
||||
// fmt.Print("[Debug] ")
|
||||
// fmt.Println(a...)
|
||||
// }
|
||||
|
||||
// // 错误并退出
|
||||
// func ErrorExit(err_title, err_msg string) {
|
||||
// newLog := NewLog("err.log")
|
||||
|
||||
// Pln("Error", err_title+err_msg)
|
||||
// newLog.Error(err_title, err_msg)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
// 写入日志的文件
|
||||
func NewLog(log_file_name string) *LogStruct {
|
||||
logStruct := &LogStruct{}
|
||||
logStruct.Separator = ""
|
||||
logDir := path.Dir(log_file_name)
|
||||
ok, _ := PathExists(logDir)
|
||||
if !ok {
|
||||
if err := os.MkdirAll(logDir, 0666); err != nil {
|
||||
fmt.Println("创建日志文件错误", err.Error())
|
||||
}
|
||||
}
|
||||
_, err := os.Stat(log_file_name)
|
||||
if err != nil {
|
||||
f, _ := os.Create(log_file_name)
|
||||
logStruct.File = f
|
||||
logStruct.Writer = io.MultiWriter(f)
|
||||
} else {
|
||||
f, _ := os.OpenFile(log_file_name, os.O_APPEND|os.O_WRONLY, 0666)
|
||||
logStruct.File = f
|
||||
logStruct.Writer = io.MultiWriter(f)
|
||||
}
|
||||
return logStruct
|
||||
}
|
||||
|
||||
// 运行日志直接静态
|
||||
func RunLog() *LogStruct {
|
||||
// 按小时/日/月/年
|
||||
// 先判断文件(夹)是否存在。否多级创建
|
||||
log_file := "res/runtime/log/"
|
||||
ok, _ := PathExists(log_file)
|
||||
if !ok {
|
||||
os.MkdirAll(log_file, 0777)
|
||||
}
|
||||
log_file_name := log_file + time.Unix(time.Now().Unix(), 1).Format("2006-01-02") + ".log"
|
||||
_, err := os.Stat(log_file_name)
|
||||
runLogStatic.Separator = "|"
|
||||
if err != nil {
|
||||
f, _ := os.Create(log_file_name)
|
||||
runLogStatic.File = f
|
||||
runLogStatic.Writer = io.MultiWriter(f)
|
||||
} else {
|
||||
if runLogStatic.File == nil {
|
||||
f, _ := os.OpenFile(log_file_name, os.O_APPEND|os.O_WRONLY, 0666)
|
||||
runLogStatic.File = f
|
||||
runLogStatic.Writer = io.MultiWriter(f)
|
||||
}
|
||||
}
|
||||
return &runLogStatic
|
||||
}
|
||||
|
||||
func (t *LogStruct) Write(content string) (n int, err error) {
|
||||
|
||||
return io.WriteString(t.Writer, content)
|
||||
}
|
||||
|
||||
func (t *LogStruct) Format(log_type string, content string) (n int, err error) {
|
||||
content = log_type + spaces[log_type] + " " + GetTime() + " " + content + "\n"
|
||||
return t.Write(content)
|
||||
}
|
||||
|
||||
func (t *LogStruct) Info(content ...string) (n int, err error) {
|
||||
str := ""
|
||||
for i := 0; i < len(content); i++ {
|
||||
if i != 0 {
|
||||
str += t.Separator + content[i]
|
||||
} else {
|
||||
str += content[i]
|
||||
}
|
||||
}
|
||||
n, err = t.Format("Info", str)
|
||||
if t.Print_cfg == true {
|
||||
Pln("Info", str)
|
||||
t.Print_cfg = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *LogStruct) Debug(content string) {
|
||||
t.Format("Debug", content)
|
||||
if t.Print_cfg == true {
|
||||
Pln("Debug", content)
|
||||
t.Print_cfg = false
|
||||
}
|
||||
}
|
||||
|
||||
func (t *LogStruct) Error(content ...string) {
|
||||
content_str := ""
|
||||
for i := 0; i < len(content); i++ {
|
||||
if i != 0 {
|
||||
content_str += t.Separator + content[i]
|
||||
} else {
|
||||
content_str += content[i]
|
||||
}
|
||||
}
|
||||
t.Format("Error", content_str)
|
||||
if t.Print_cfg == true {
|
||||
Pln("Error", content_str)
|
||||
t.Print_cfg = false
|
||||
}
|
||||
}
|
||||
|
||||
// // 打印错误
|
||||
// func (t *LogStruct) ErrorPrint(key, value string) {
|
||||
// t.Print_cfg = true
|
||||
// t.Error(key, value)
|
||||
// }
|
||||
|
||||
// // 打印Debug
|
||||
// func (t *LogStruct) DebugPrint(key, value string) {
|
||||
// t.Print_cfg = true
|
||||
// content := key + " " + value
|
||||
// t.Debug(content)
|
||||
// }
|
||||
|
||||
// func (t *LogStruct) Print() *LogStruct {
|
||||
// t.Print_cfg = true
|
||||
// return t
|
||||
// }
|
||||
|
||||
// func (t *LogStruct) FormatFileld(field LogFileld) string {
|
||||
// str := ""
|
||||
// for k, v := range field {
|
||||
// str += k + ":\"" + v + "\"" + t.Separator
|
||||
// }
|
||||
// if len(str) != 0 {
|
||||
// str = str[0 : len(str)-1]
|
||||
// }
|
||||
// return str
|
||||
// }
|
||||
|
||||
// TODO(GgoCoder) 日志轮转
|
||||
func InitLogger(fileName string, level zapcore.LevelEnabler) *zap.SugaredLogger {
|
||||
fileWriteSyncer := getLogWriter(fileName)
|
||||
encoder := getEncoder()
|
||||
core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(fileWriteSyncer, zapcore.AddSync(os.Stdout)), level)
|
||||
logger := zap.New(core, zap.AddCaller())
|
||||
return logger.Sugar()
|
||||
}
|
||||
|
||||
func getEncoder() zapcore.Encoder {
|
||||
logConf := zap.NewProductionEncoderConfig()
|
||||
logConf.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
logConf.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||
return zapcore.NewConsoleEncoder(logConf)
|
||||
}
|
||||
|
||||
func getLogWriter(fileName string) zapcore.WriteSyncer {
|
||||
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
log.Panic("failed to create log file", fileName)
|
||||
}
|
||||
return zapcore.AddSync(file)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package systemSetting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sun-panel/lib/cache"
|
||||
"sun-panel/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
SYSTEM_APPLICATION = "system_application"
|
||||
SYSTEM_EMAIL = "system_email"
|
||||
DISCLAIMER = "disclaimer" // 免责声明 储存类型:字符串
|
||||
WEB_ABOUT_DESCRIPTION = "web_about_description" // 关于的描述信息
|
||||
)
|
||||
|
||||
type SystemSettingCache struct {
|
||||
Cache cache.Cacher[interface{}]
|
||||
}
|
||||
|
||||
type Email struct {
|
||||
Host string `json:"host" binding:"required"`
|
||||
Port int `json:"port" binding:"required"`
|
||||
Mail string `json:"mail" binding:"required,email"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
type Register struct {
|
||||
EmailSuffix string `json:"emailSuffix"` // 注册邮箱后缀
|
||||
OpenRegister bool `json:"openRegister"` // 开放注册
|
||||
}
|
||||
|
||||
type Login struct {
|
||||
LoginCaptcha bool `json:"loginCaptcha"` // 登录验证码
|
||||
}
|
||||
|
||||
type ApplicationSetting struct {
|
||||
Register
|
||||
Login
|
||||
WebSiteUrl string `json:"webSiteUrl"` // 站点地址
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorNoExists = errors.New("no exists")
|
||||
)
|
||||
|
||||
// 系统配置启用缓存功能
|
||||
func (s *SystemSettingCache) GetValueString(configName string) (result string, err error) {
|
||||
if v, ok := s.Cache.Get(configName); ok {
|
||||
if v1, ok1 := v.(string); ok1 {
|
||||
// fmt.Println("读取缓存")
|
||||
return v1, nil
|
||||
}
|
||||
}
|
||||
|
||||
mSetting := models.SystemSetting{}
|
||||
result, err = mSetting.Get(configName)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
err = ErrorNoExists
|
||||
}
|
||||
// 查询出来,缓存起来
|
||||
s.Cache.SetDefault(configName, result)
|
||||
return
|
||||
}
|
||||
|
||||
// value 需为指针
|
||||
func (s *SystemSettingCache) GetValueByInterface(configName string, value interface{}) error {
|
||||
if v, ok := s.Cache.Get(configName); ok {
|
||||
// fmt.Println("缓存")
|
||||
if s, sok := v.(string); sok {
|
||||
if err := json.Unmarshal([]byte(s), value); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
mSetting := models.SystemSetting{}
|
||||
result, err := mSetting.Get(configName)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
err = ErrorNoExists
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal([]byte(result), value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Cache.SetDefault(configName, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SystemSettingCache) Set(configName string, configValue interface{}) error {
|
||||
s.Cache.Delete(configName)
|
||||
mSetting := models.SystemSetting{}
|
||||
err := mSetting.Set(configName, configValue)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cmn
|
||||
|
||||
import "regexp"
|
||||
|
||||
// 公式
|
||||
const (
|
||||
VERIFY_EXP_USERNAME = `^[a-zA-Z0-9_\.\@]{5,80}$`
|
||||
VERIFY_EXP_PASSWORD = `^[a-zA-Z0-9_\.\&\@]{6,16}$`
|
||||
)
|
||||
|
||||
// 正则验证
|
||||
func VerifyFormat(exp, str string) bool {
|
||||
reg := regexp.MustCompile(exp)
|
||||
return reg.MatchString(str)
|
||||
}
|
||||
|
||||
// 验证邮箱
|
||||
func VerifyEmail(email string) bool {
|
||||
return VerifyFormat(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`, email)
|
||||
}
|
||||
Reference in New Issue
Block a user