docs(website): 添加简记memo产品原型和UI设计规范文档
- 新增「简记memo」一体化小程序产品原型设计文档 - 新增简记memo完整版UI视觉设计规范和界面细节 - 添加IDEA项目配置文件.gitignore - 创建404页面HTML文件,包含响应式布局和错误提示 - 添加关于页面HTML文件,展示品牌介绍和团队信息 - 实现AES加解密工具函数,支持请求体加密 - 添加用户协议页面基础框架
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// 配置加载:区分dev/prod环境
|
||||
package core
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"simple-memo/global"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// InitConfig 读取命令行参数 -env dev/prod
|
||||
func InitConfig() {
|
||||
// 读取启动参数
|
||||
env := flag.String("env", "dev", "运行环境:dev 或 prod")
|
||||
flag.Parse()
|
||||
|
||||
// 1. 获取项目根目录的绝对路径(基于当前执行文件的位置)
|
||||
//exePath, err := os.Executable()
|
||||
//if err != nil {
|
||||
// panic(fmt.Sprintf("获取执行文件路径失败: %v", err))
|
||||
//}
|
||||
//projectRoot := filepath.Dir(exePath) // 执行文件在根目录,所以Dir就是根目录
|
||||
|
||||
// 2. 用绝对路径加载配置文件
|
||||
v := viper.New()
|
||||
v.SetConfigName("config-" + *env) // config-dev.yaml
|
||||
v.SetConfigType("yaml")
|
||||
v.AddConfigPath("../config") // 配置文件目录
|
||||
//viper.AddConfigPath(filepath.Join(projectRoot, "config")) // 绝对路径:根目录/config
|
||||
|
||||
// 读取配置
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
panic("配置文件读取失败:" + err.Error())
|
||||
}
|
||||
|
||||
global.VP = v // 赋值给全局
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"simple-memo/global"
|
||||
"simple-memo/models"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func InitCron() {
|
||||
go func() {
|
||||
for {
|
||||
now := time.Now()
|
||||
next := getNextRunTime(10, 0)
|
||||
duration := next.Sub(now)
|
||||
|
||||
time.Sleep(duration)
|
||||
|
||||
checkPerfectDay()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func getNextRunTime(hour, minute int) time.Time {
|
||||
now := time.Now()
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, now.Location())
|
||||
|
||||
if now.Before(today) {
|
||||
return today
|
||||
}
|
||||
return today.AddDate(0, 0, 1)
|
||||
}
|
||||
|
||||
func checkPerfectDay() {
|
||||
yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
|
||||
|
||||
var progressList []models.DailyProgress
|
||||
err := global.DB.Where("record_date = ?", yesterday).Find(&progressList).Error
|
||||
if err != nil {
|
||||
global.Logger.Error("查询每日进度失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, progress := range progressList {
|
||||
if progress.TotalTasks > 0 && progress.TaskCount >= progress.TotalTasks && !progress.PerfectDay {
|
||||
err := global.DB.Model(&models.DailyProgress{}).
|
||||
Where("id = ?", progress.ID).
|
||||
Update("perfect_day", true).Error
|
||||
if err != nil {
|
||||
global.Logger.Error("更新PerfectDay失败", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global.Logger.Info("PerfectDay check completed", zap.String("date", yesterday))
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// 日志模块:zap 高性能日志
|
||||
package core
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"os"
|
||||
"simple-memo/global"
|
||||
)
|
||||
|
||||
func InitLogger() {
|
||||
logPath := global.VP.GetString("log.path")
|
||||
file, _ := os.Create(logPath)
|
||||
|
||||
// 同时输出到文件 + 控制台
|
||||
writeSyncer := zapcore.NewMultiWriteSyncer(zapcore.AddSync(file), zapcore.AddSync(os.Stdout))
|
||||
|
||||
encoderConfig := zap.NewProductionEncoderConfig()
|
||||
encoderConfig.TimeKey = "time"
|
||||
encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
|
||||
|
||||
// 日志级别
|
||||
core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), writeSyncer, zap.InfoLevel)
|
||||
global.Logger = zap.New(core, zap.AddCaller())
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// MySQL初始化 + 表前缀sm_(已修复GORM兼容报错)
|
||||
package core
|
||||
|
||||
import (
|
||||
"simple-memo/global"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
// InitMysql 初始化MySQL数据库连接
|
||||
func InitMysql() {
|
||||
// 从配置文件读取数据库信息
|
||||
host := global.VP.GetString("mysql.host")
|
||||
port := global.VP.GetString("mysql.port")
|
||||
dbname := global.VP.GetString("mysql.dbname")
|
||||
username := global.VP.GetString("mysql.username")
|
||||
password := global.VP.GetString("mysql.password")
|
||||
|
||||
// MySQL 连接字符串
|
||||
dsn := username + ":" + password + "@tcp(" + host + ":" + port + ")/" + dbname + "?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
// 打开数据库连接,启用表前缀sm_
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
// ========== 修复:正确设置表前缀,无报错 ==========
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
TablePrefix: "sm_", // 所有表统一前缀:sm_
|
||||
SingularTable: true, // 禁用表名复数(User → sm_user)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
panic("MySQL连接失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 设置数据库连接池,支撑高并发
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
panic("获取数据库连接失败:" + err.Error())
|
||||
}
|
||||
sqlDB.SetMaxOpenConns(100) // 最大打开连接数
|
||||
sqlDB.SetMaxIdleConns(20) // 最大空闲连接数
|
||||
sqlDB.SetConnMaxLifetime(30 * time.Minute) // 连接最长存活时间
|
||||
|
||||
// 赋值给全局DB变量
|
||||
global.DB = db
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Redis初始化
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"simple-memo/global"
|
||||
)
|
||||
|
||||
func InitRedis() {
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: global.VP.GetString("redis.host") + ":" + global.VP.GetString("redis.port"),
|
||||
Password: global.VP.GetString("redis.password"),
|
||||
DB: global.VP.GetInt("redis.db"),
|
||||
})
|
||||
|
||||
// 测试连接
|
||||
_, err := client.Ping(context.Background()).Result()
|
||||
if err != nil {
|
||||
panic("Redis连接失败:" + err.Error())
|
||||
}
|
||||
|
||||
global.Redis = client
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// core/router.go
|
||||
// Gin引擎初始化 - 只保留核心配置
|
||||
package core
|
||||
|
||||
import (
|
||||
"simple-memo/middleware"
|
||||
"simple-memo/routes"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitRouter 初始化Gin引擎并注册所有路由
|
||||
func InitRouter() *gin.Engine {
|
||||
// 使用 gin.New() 手动控制中间件,避免 gin.Default() 自带的 Logger
|
||||
r := gin.New()
|
||||
|
||||
// 全局中间件
|
||||
r.Use(gin.Recovery()) // 恢复中间件(捕获 panic)
|
||||
r.Use(middleware.RequestLog()) // 请求日志中间件(记录 request-id / route / client-ip 等)
|
||||
|
||||
// 设置信任的代理(开发环境设置为 nil,生产环境应设置具体的代理地址)
|
||||
_ = r.SetTrustedProxies(nil)
|
||||
|
||||
// 注册所有路由(静态资源、页面、API)
|
||||
routes.RegisterRoutes(r)
|
||||
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user