Initial commit: Gitea Project Management System

Features:
- Complete project management system with Epic/Story/Task hierarchy
- Vue.js 3 + Element Plus frontend with kanban board
- Go backend with Gin framework and GORM
- OAuth2 integration with Gitea
- Docker containerization with MySQL
- RESTful API for project, task, and user management
- JWT authentication and authorization
- Responsive web interface with dashboard
This commit is contained in:
huxunan
2025-09-22 14:53:53 +08:00
commit 885fad6c64
33 changed files with 4128 additions and 0 deletions

102
config/config.go Normal file
View File

@@ -0,0 +1,102 @@
package config
import (
"github.com/spf13/viper"
)
type Config struct {
Server ServerConfig `mapstructure:"server"`
Database DatabaseConfig `mapstructure:"database"`
Gitea GiteaConfig `mapstructure:"gitea"`
JWT JWTConfig `mapstructure:"jwt"`
CORS CORSConfig `mapstructure:"cors"`
}
type ServerConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Mode string `mapstructure:"mode"`
}
type DatabaseConfig struct {
Driver string `mapstructure:"driver"`
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Database string `mapstructure:"database"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Charset string `mapstructure:"charset"`
}
type GiteaConfig struct {
BaseURL string `mapstructure:"base_url"`
ClientID string `mapstructure:"client_id"`
ClientSecret string `mapstructure:"client_secret"`
RedirectURL string `mapstructure:"redirect_url"`
WebhookSecret string `mapstructure:"webhook_secret"`
}
type JWTConfig struct {
Secret string `mapstructure:"secret"`
ExpireHour int `mapstructure:"expire_hour"`
}
type CORSConfig struct {
AllowOrigins []string `mapstructure:"allow_origins"`
AllowMethods []string `mapstructure:"allow_methods"`
AllowHeaders []string `mapstructure:"allow_headers"`
AllowCredentials bool `mapstructure:"allow_credentials"`
}
func Load(configPath string) (*Config, error) {
viper.SetConfigFile(configPath)
viper.SetConfigType("yaml")
// 启用环境变量
viper.AutomaticEnv()
viper.SetEnvPrefix("") // 不使用前缀
viper.SetDefault("server.host", "localhost")
viper.SetDefault("server.port", 8080)
viper.SetDefault("server.mode", "debug")
viper.SetDefault("database.driver", "mysql")
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.port", 3306)
viper.SetDefault("database.charset", "utf8mb4")
viper.SetDefault("jwt.expire_hour", 24)
viper.SetDefault("cors.allow_origins", []string{"*"})
viper.SetDefault("cors.allow_methods", []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"})
viper.SetDefault("cors.allow_headers", []string{"*"})
viper.SetDefault("cors.allow_credentials", true)
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
// 覆盖数据库配置(如果环境变量存在)
if host := viper.GetString("DB_HOST"); host != "" {
config.Database.Host = host
}
if port := viper.GetInt("DB_PORT"); port != 0 {
config.Database.Port = port
}
if user := viper.GetString("DB_USER"); user != "" {
config.Database.Username = user
}
if password := viper.GetString("DB_PASSWORD"); password != "" {
config.Database.Password = password
}
if database := viper.GetString("DB_NAME"); database != "" {
config.Database.Database = database
}
return &config, nil
}

30
config/config.yaml Normal file
View File

@@ -0,0 +1,30 @@
server:
host: "0.0.0.0"
port: 8080
mode: "debug"
database:
driver: "mysql"
host: "localhost"
port: 3306
database: "giteapm"
username: "root"
password: "password"
charset: "utf8mb4"
gitea:
base_url: "http://218.84.152.14:65001"
client_id: "0671c92d-ae8b-4a5f-9fa9-0c17d971be01"
client_secret: "gto_cdmdo4xp4tysa6oyhzpfk3kymeywbkkkybeplob2oxyw7h3no7pq"
redirect_url: "http://hu.s7.tunnelfrp.com/api/v1/auth/callback"
webhook_secret: "your-webhook-secret"
jwt:
secret: "your-jwt-secret-key"
expire_hour: 168 # 7 days
cors:
allow_origins: ["http://218.84.152.14:65001", "http://localhost:8080","http://hu.s7.tunnelfrp.com"]
allow_methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
allow_headers: ["*"]
allow_credentials: true