Compare commits
9 Commits
761c24efbf
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 569e6618a8 | |||
| fb5f8ca2a5 | |||
| 090acb0454 | |||
| 991165125f | |||
| 6945e6db93 | |||
| 8c5fa60081 | |||
| 2d467c710f | |||
| 326118eefb | |||
| 2e5aa77e25 |
2
.env
2
.env
@@ -1,3 +1,5 @@
|
|||||||
|
|
||||||
|
LOG_FILE_ENABLE=1
|
||||||
# Nacos配置
|
# Nacos配置
|
||||||
NACOS_HOST=127.0.0.1
|
NACOS_HOST=127.0.0.1
|
||||||
NACOS_PORT=8848
|
NACOS_PORT=8848
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
# online_code
|
# online_code
|
||||||
|
|
||||||
练习系统
|
一个类似于LeetCode的刷题系统
|
||||||
|
开发进度:完成基础框架
|
||||||
31
api/problem.go
Normal file
31
api/problem.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"online_code/core"
|
||||||
|
"online_code/models/param"
|
||||||
|
"online_code/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type problemApi struct{}
|
||||||
|
|
||||||
|
func ProblemApi() *problemApi {
|
||||||
|
return &problemApi{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (problemApi) GetProbleList(ctx *gin.Context) {
|
||||||
|
var p param.GetProblemList
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
core.R(ctx).FailWithMessage("参数错误: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
records, count, err := repository.ProblemService().GetList(p)
|
||||||
|
if err != nil {
|
||||||
|
core.R(ctx).FailWithMessage("获取题目列表失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
core.R(ctx).OkDataPage(count, core.PageData{Current: p.Current, Size: p.Size, Total: count, Records: records})
|
||||||
|
}
|
||||||
31
api/submit.go
Normal file
31
api/submit.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"online_code/core"
|
||||||
|
"online_code/models/param"
|
||||||
|
"online_code/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type submitApi struct{}
|
||||||
|
|
||||||
|
func SubmitApi() *submitApi {
|
||||||
|
return &submitApi{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (submitApi) GetSubmitList(c *gin.Context) {
|
||||||
|
var p param.GetSubmitList
|
||||||
|
if err := c.ShouldBind(&p); err != nil {
|
||||||
|
core.R(c).FailWithMessage("参数错误: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
records, count, err := repository.SubmitService().GetList(p)
|
||||||
|
if err != nil {
|
||||||
|
core.R(c).FailWithMessage("获取提交列表失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
core.R(c).OkDataPage(count, core.PageData{Current: p.Current, Size: p.Size, Total: count, Records: records})
|
||||||
|
}
|
||||||
32
api/user.go
Normal file
32
api/user.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"online_code/client"
|
||||||
|
"online_code/core"
|
||||||
|
"online_code/models/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type userApi struct{}
|
||||||
|
|
||||||
|
func UserApi() *userApi {
|
||||||
|
return &userApi{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo 获取用户详情
|
||||||
|
func (userApi) GetUserInfo(ctx *gin.Context) {
|
||||||
|
// 获取用户信息
|
||||||
|
identity := ctx.Param("identity")
|
||||||
|
if identity == "" {
|
||||||
|
core.R(ctx).FailWithMessage("参数不能为空: identity")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userData := entity.UserBasic{}
|
||||||
|
err := client.MySQL.Omit("password").Where("identity = ?", identity).Take(&userData).Error
|
||||||
|
if err != nil {
|
||||||
|
core.R(ctx).FailWithMessage("获取用户信息失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
core.R(ctx).OkWithData(userData)
|
||||||
|
}
|
||||||
@@ -13,11 +13,21 @@ var MySQL *gorm.DB
|
|||||||
|
|
||||||
func InitMySQLClient() {
|
func InitMySQLClient() {
|
||||||
// 创建连接对象
|
// 创建连接对象
|
||||||
conn, err := gorm.Open(mysql.Open(config.Scd.MySQL.GetDSN()), &gorm.Config{Logger: logger.DefaultGormLogger()})
|
mysqlConfig := mysql.Config{
|
||||||
|
DSN: config.Scd.MySQL.GetDSN(),
|
||||||
|
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式
|
||||||
|
DontSupportRenameColumn: true, // 用 `change` 重命名列
|
||||||
|
}
|
||||||
|
conn, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{Logger: logger.DefaultGormLogger()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic("初始化MySQL连接失败, 错误信息: %v", err)
|
log.Panic("初始化MySQL连接失败, 错误信息: %v", err)
|
||||||
} else {
|
} else {
|
||||||
log.Debug("MySQL连接成功")
|
log.Debug("MySQL连接成功")
|
||||||
}
|
}
|
||||||
MySQL = conn
|
MySQL = conn
|
||||||
|
|
||||||
|
//db, err := conn.DB()
|
||||||
|
//db.SetMaxIdleConns(10) // 用于设置连接池中空闲连接的最大数量
|
||||||
|
//db.SetMaxOpenConns(100) // 用于设置数据库连接的最大打开数量
|
||||||
|
//db.SetConnMaxLifetime(time.Hour) // 设置连接的最大存活时间
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/uuid"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseDbModel 数据库通用字段
|
// BaseDbModel 数据库通用字段
|
||||||
type BaseDbModel struct {
|
type BaseDbModel struct {
|
||||||
Id string `json:"id" gorm:"type:varchar(50);primarykey"`
|
ID uint `gorm:"type:int(11);primarykey;" json:"id"`
|
||||||
CreatedAt DateTime `json:"createdAt"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt DateTime `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index:deleted"`
|
DeletedAt gorm.DeletedAt `json:"-" gorm:"index:deleted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeCreate 创建数据库对象之前生成UUID
|
/*// BeforeCreate 创建数据库对象之前生成UUID
|
||||||
func (m *BaseDbModel) BeforeCreate(*gorm.DB) (err error) {
|
func (m *BaseDbModel) BeforeCreate(*gorm.DB) (err error) {
|
||||||
m.Id = uuid.New().String()
|
m.Id = uuid.New().String()
|
||||||
return
|
return
|
||||||
}
|
}*/
|
||||||
|
|||||||
19
config.yaml
19
config.yaml
@@ -0,0 +1,19 @@
|
|||||||
|
api:
|
||||||
|
port: 8083
|
||||||
|
name: online_code
|
||||||
|
version: v1
|
||||||
|
prefix: /api/v1
|
||||||
|
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 3306
|
||||||
|
user: root
|
||||||
|
password: root
|
||||||
|
db: online_code
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 6379
|
||||||
|
password: loser7659
|
||||||
|
db: 0
|
||||||
@@ -3,6 +3,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"online_code/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 返回数据包装
|
// 返回数据包装
|
||||||
@@ -59,6 +60,15 @@ func (r rs) OkDetailed(data interface{}, message string) {
|
|||||||
r.Result(SUCCESS, data, message)
|
r.Result(SUCCESS, data, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OkDataPage 返回分页数据
|
||||||
|
func (r rs) OkDataPage(count int64, page PageData) {
|
||||||
|
// 计算总页码
|
||||||
|
totalPage := utils.GenTotalPage(count, page.Size)
|
||||||
|
page.TotalPage = totalPage
|
||||||
|
// 返回结果
|
||||||
|
r.Result(SUCCESS, page, "操作成功")
|
||||||
|
}
|
||||||
|
|
||||||
// Fail 返回默认失败
|
// Fail 返回默认失败
|
||||||
func (r rs) Fail() {
|
func (r rs) Fail() {
|
||||||
r.Result(ERROR, nil, "操作失败")
|
r.Result(ERROR, nil, "操作失败")
|
||||||
|
|||||||
6
define/define.go
Normal file
6
define/define.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package define
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultCurrent = "1"
|
||||||
|
DefaultSize = "10"
|
||||||
|
)
|
||||||
6
go.mod
6
go.mod
@@ -5,13 +5,13 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
git.echol.cn/loser/logger v1.0.14
|
git.echol.cn/loser/logger v1.0.14
|
||||||
git.echol.cn/loser/nacos-viper-remote v0.4.1-0.20220525104600-e38430672884
|
git.echol.cn/loser/nacos-viper-remote v0.4.1-0.20220525104600-e38430672884
|
||||||
gitee.ltd/lxh/logger v1.0.14
|
|
||||||
github.com/caarlos0/env/v6 v6.9.2
|
github.com/caarlos0/env/v6 v6.9.2
|
||||||
github.com/fsnotify/fsnotify v1.5.1
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
github.com/gin-gonic/gin v1.7.7
|
github.com/gin-gonic/gin v1.7.7
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/google/uuid v1.1.2
|
|
||||||
github.com/spf13/viper v1.10.1
|
github.com/spf13/viper v1.10.1
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
gorm.io/driver/mysql v1.3.2
|
gorm.io/driver/mysql v1.3.2
|
||||||
gorm.io/gorm v1.23.5
|
gorm.io/gorm v1.23.5
|
||||||
)
|
)
|
||||||
@@ -19,6 +19,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.99.0 // indirect
|
cloud.google.com/go v0.99.0 // indirect
|
||||||
cloud.google.com/go/firestore v1.6.1 // indirect
|
cloud.google.com/go/firestore v1.6.1 // indirect
|
||||||
|
gitee.ltd/lxh/logger v1.0.14 // indirect
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
|
||||||
github.com/armon/go-metrics v0.3.10 // indirect
|
github.com/armon/go-metrics v0.3.10 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
@@ -96,7 +97,6 @@ require (
|
|||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.8.0 // indirect
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
go.uber.org/zap v1.21.0 // indirect
|
go.uber.org/zap v1.21.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 // indirect
|
|
||||||
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 // indirect
|
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect
|
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ import (
|
|||||||
// 初始化数据库表
|
// 初始化数据库表
|
||||||
func databaseTable() {
|
func databaseTable() {
|
||||||
dbs := []any{
|
dbs := []any{
|
||||||
new(entity.User), // 管理员用户
|
new(entity.UserBasic),
|
||||||
|
new(entity.TestCase),
|
||||||
|
new(entity.CategoryBasic),
|
||||||
|
new(entity.ProblemCategory),
|
||||||
|
//new(entity.ProblemBasic),
|
||||||
|
//new(entity.SubmitBasic),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.MySQL.AutoMigrate(dbs...); err != nil {
|
if err := client.MySQL.AutoMigrate(dbs...); err != nil {
|
||||||
|
|||||||
57
main.go
Normal file
57
main.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.echol.cn/loser/logger"
|
||||||
|
"git.echol.cn/loser/logger/log"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"net/http"
|
||||||
|
"online_code/config"
|
||||||
|
"online_code/core"
|
||||||
|
"online_code/initialize"
|
||||||
|
"online_code/route"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var g errgroup.Group
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logger.InitLogger(logger.LogConfig{Mode: logger.Dev, LokiEnable: false, FileEnable: true})
|
||||||
|
initialize.InitSystem() // 初始化系统配置
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动入口
|
||||||
|
func main() {
|
||||||
|
// 强制日志颜色化
|
||||||
|
gin.ForceConsoleColor()
|
||||||
|
app := &http.Server{
|
||||||
|
Addr: fmt.Sprintf(":%d", config.Scd.Api.Port),
|
||||||
|
Handler: api(),
|
||||||
|
ReadTimeout: 5 * time.Second,
|
||||||
|
WriteTimeout: 1 * time.Minute,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动项目
|
||||||
|
g.Go(func() error {
|
||||||
|
return app.ListenAndServe()
|
||||||
|
})
|
||||||
|
if err := g.Wait(); err != nil {
|
||||||
|
log.Panicf("启动失败,错误信息:%s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成接口服务
|
||||||
|
func api() http.Handler {
|
||||||
|
app := gin.New()
|
||||||
|
app.Use(gin.Recovery())
|
||||||
|
// 开启自定义请求方式不允许处理函数
|
||||||
|
app.HandleMethodNotAllowed = true
|
||||||
|
// 处理请求方式不对
|
||||||
|
app.NoMethod(core.NoMethodHandler())
|
||||||
|
// 404返回数据
|
||||||
|
app.NoRoute(core.NoRouteHandler())
|
||||||
|
// 初始化路由
|
||||||
|
route.InitRoute(app.Group(config.Scd.Api.Prefix))
|
||||||
|
return app
|
||||||
|
}
|
||||||
18
models/cache/user.go
vendored
Normal file
18
models/cache/user.go
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
// UserInfo 登录用的用户信息结构体
|
||||||
|
type UserInfo struct {
|
||||||
|
UserType string `json:"userType"` // 用户类型
|
||||||
|
UserId string `json:"userId"` // 用户Id
|
||||||
|
}
|
||||||
|
|
||||||
|
// String 实现Stringer接口
|
||||||
|
func (i UserInfo) String() (string, error) {
|
||||||
|
b, err := json.Marshal(i)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(b), nil
|
||||||
|
}
|
||||||
@@ -2,14 +2,14 @@ package entity
|
|||||||
|
|
||||||
import "online_code/common/types"
|
import "online_code/common/types"
|
||||||
|
|
||||||
// Category 分类表
|
// CategoryBasic 分类表
|
||||||
type Category struct {
|
type CategoryBasic struct {
|
||||||
types.BaseDbModel
|
types.BaseDbModel
|
||||||
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'分类的唯一标识'"`
|
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'问题表的唯一标识'"`
|
||||||
Name string `json:"name" gorm:"column:name;type:varchar(100);comment:'分类名称'" `
|
Name string `json:"name" gorm:"column:name;type:varchar(100);comment:'分类名称'" `
|
||||||
ParentId int `json:"parent_id" gorm:"column:parent_id;type:int(11);comment:'父级ID'" `
|
ParentId int `json:"parent_id" gorm:"column:parent_id;type:int(11);comment:'父级ID'" `
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *Category) TableName() string {
|
func (table *CategoryBasic) TableName() string {
|
||||||
return "category"
|
return "category_basic"
|
||||||
}
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package entity
|
|
||||||
|
|
||||||
import "online_code/common/types"
|
|
||||||
|
|
||||||
// Problem 问题表
|
|
||||||
type Problem struct {
|
|
||||||
types.BaseDbModel
|
|
||||||
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'问题表的唯一标识'" ` // 问题表的唯一标识
|
|
||||||
ProblemCategories []*ProblemCategory `json:"problem_categories" gorm:"foreignKey:problem_id;references:id;comment:'关联问题分类表'" ` // 关联问题分类表
|
|
||||||
Title string `json:"title" gorm:"column:title;type:varchar(255);comment:'文章标题'" ` // 文章标题
|
|
||||||
Content string `json:"content" gorm:"column:content;type:text;comment:'文章正文'" ` // 文章正文
|
|
||||||
MaxRuntime int `json:"max_runtime" gorm:"column:max_runtime;type:int(11);comment:'最大运行时长'" ` // 最大运行时长
|
|
||||||
MaxMem int `json:"max_mem" gorm:"column:max_mem;type:int(11);comment:'最大运行内存'" ` // 最大运行内存
|
|
||||||
TestCases []*TestCase `json:"test_cases" gorm:"foreignKey:problem_identity;references:identity;comment:'关联测试用例表'" ` // 关联测试用例表
|
|
||||||
PassNum int64 `json:"pass_num" gorm:"column:pass_num;type:int(11);comment:'通过次数'" ` // 通过次数
|
|
||||||
SubmitNum int64 `json:"submit_num" gorm:"column:submit_num;type:int(11);comment:'提交次数'" ` // 提交次数
|
|
||||||
}
|
|
||||||
|
|
||||||
func (table *Problem) TableName() string {
|
|
||||||
return "problem_basic"
|
|
||||||
}
|
|
||||||
21
models/entity/problem_basic.go
Normal file
21
models/entity/problem_basic.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "online_code/common/types"
|
||||||
|
|
||||||
|
// ProblemBasic 问题基础表
|
||||||
|
type ProblemBasic struct {
|
||||||
|
types.BaseDbModel
|
||||||
|
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'问题表的唯一标识'"` // 问题表的唯一标识
|
||||||
|
ProblemCategories []ProblemCategory `json:"problem_categories" gorm:"ForeignKey:ProblemId;comment:'关联问题分类表'"` // 关联问题分类表
|
||||||
|
Title string `json:"title" gorm:"column:title;type:varchar(255);comment:'文章标题'"` // 文章标题
|
||||||
|
Content string `json:"content" gorm:"column:content;type:text;comment:'文章正文'"` // 文章正文
|
||||||
|
MaxRuntime int `json:"max_runtime" gorm:"column:max_runtime;type:int(11);comment:'最大运行时长'"` // 最大运行时长
|
||||||
|
MaxMem int `json:"max_mem" gorm:"column:max_mem;type:int(11);comment:'最大运行内存'"` // 最大运行内存
|
||||||
|
TestCases []TestCase `json:"test_cases" gorm:"foreignKey:ProblemIdentity;comment:'关联测试用例表'"` // 关联测试用例表
|
||||||
|
PassNum int64 `json:"pass_num" gorm:"column:pass_num;type:int(11);comment:'通过次数'"` // 通过次数
|
||||||
|
SubmitNum int64 `json:"submit_num" gorm:"column:submit_num;type:int(11);comment:'提交次数'"` // 提交次数
|
||||||
|
}
|
||||||
|
|
||||||
|
func (table *ProblemBasic) TableName() string {
|
||||||
|
return "problem_basic"
|
||||||
|
}
|
||||||
@@ -4,12 +4,12 @@ import (
|
|||||||
"online_code/common/types"
|
"online_code/common/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProblemCategory 问题分类表
|
// ProblemCategory 问题分类关联表
|
||||||
type ProblemCategory struct {
|
type ProblemCategory struct {
|
||||||
types.BaseDbModel
|
types.BaseDbModel
|
||||||
ProblemId uint `json:"problem_id" gorm:"column:problem_id;type:int(11);comment:'问题的ID'" ` // 问题的ID
|
ProblemId uint `json:"problem_id" gorm:"column:problem_id;type:int(11);comment:'问题的ID'" ` // 问题的ID
|
||||||
CategoryId uint `json:"category_id" gorm:"column:category_id;type:int(11);comment:'分类的ID'" ` // 分类的ID
|
CategoryId uint `json:"category_id" gorm:"column:category_id;type:int(11);comment:'分类的ID'" ` // 分类的ID
|
||||||
CategoryBasic *Category `json:"category_basic" gorm:"foreignKey:id;references:category_id;comment:'关联分类的基础信息表'" ` // 关联分类的基础信息表
|
CategoryBasic *CategoryBasic `json:"category_basic" gorm:"foreignKey:CategoryId;comment:'关联分类的基础信息表'" ` // 关联分类的基础信息表
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *ProblemCategory) TableName() string {
|
func (table *ProblemCategory) TableName() string {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
package entity
|
|
||||||
|
|
||||||
// Submit 提交表
|
|
||||||
type Submit struct {
|
|
||||||
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'用户唯一标识'" ` // 唯一标识
|
|
||||||
ProblemIdentity string `json:"problem_identity" gorm:"column:problem_identity;type:varchar(36);comment:'问题表的唯一标识'" ` // 问题表的唯一标识
|
|
||||||
ProblemBasic *Problem `json:"problem_basic" gorm:"foreignKey:identity;references:problem_identity;comment:'关联问题基础表'" ` // 关联问题基础表
|
|
||||||
UserIdentity string `json:"user_identity" gorm:"column:user_identity;type:varchar(36);comment:'用户表的唯一标识'" ` // 用户表的唯一标识
|
|
||||||
UserBasic *User `json:"user_basic" gorm:"foreignKey:identity;references:user_identity;comment:'联用户基础表'" ` // 关联用户基础表
|
|
||||||
Path string `json:"path" gorm:"column:path;type:varchar(255);comment:'代码存放路径'" ` // 代码存放路径
|
|
||||||
Status int `json:"status" gorm:"column:status;type:tinyint(1);comment:'状态'" ` // 【-1-待判断,1-答案正确,2-答案错误,3-运行超时,4-运行超内存, 5-编译错误】
|
|
||||||
}
|
|
||||||
|
|
||||||
func (table *Submit) TableName() string {
|
|
||||||
return "submit"
|
|
||||||
}
|
|
||||||
19
models/entity/submit_basic.go
Normal file
19
models/entity/submit_basic.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "online_code/common/types"
|
||||||
|
|
||||||
|
// SubmitBasic 提交表
|
||||||
|
type SubmitBasic struct {
|
||||||
|
types.BaseDbModel
|
||||||
|
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'用户唯一标识'" ` // 唯一标识
|
||||||
|
ProblemIdentity string `json:"problem_identity" gorm:"column:problem_identity;type:varchar(36);comment:'问题表的唯一标识'" ` // 问题表的唯一标识
|
||||||
|
ProblemBasic *ProblemBasic `json:"problem_basic" gorm:"foreignKey:ProblemIdentity;comment:'关联问题基础表'" ` // 关联问题基础表
|
||||||
|
UserIdentity string `json:"user_identity" gorm:"column:user_identity;type:varchar(36);comment:'用户表的唯一标识'" ` // 用户表的唯一标识
|
||||||
|
UserBasic *UserBasic `json:"user_basic" gorm:"foreignKey:UserIdentity;comment:'联用户基础表'" ` // 关联用户基础表
|
||||||
|
Path string `json:"path" gorm:"column:path;type:varchar(255);comment:'代码存放路径'" ` // 代码存放路径
|
||||||
|
Status int `json:"status" gorm:"column:status;type:tinyint(1);comment:'状态'" ` // 【-1-待判断,1-答案正确,2-答案错误,3-运行超时,4-运行超内存, 5-编译错误】
|
||||||
|
}
|
||||||
|
|
||||||
|
func (table *SubmitBasic) TableName() string {
|
||||||
|
return "submit_basic"
|
||||||
|
}
|
||||||
@@ -5,8 +5,8 @@ import "online_code/common/types"
|
|||||||
// TestCase 测试用例
|
// TestCase 测试用例
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
types.BaseDbModel
|
types.BaseDbModel
|
||||||
Identity string `json:"identity" gorm:"column:identity;type:varchar(255);comment:'用户唯一标识''" `
|
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'测试用例唯一标识''" `
|
||||||
ProblemIdentity string `json:"problem_identity" gorm:"column:problem_identity;type:varchar(255);comment:'问题'" `
|
ProblemIdentity string `json:"problem_identity" gorm:"column:problem_identity;type:varchar(36);comment:'问题'" `
|
||||||
Input string `json:"input" gorm:"column:input;type:text;" `
|
Input string `json:"input" gorm:"column:input;type:text;" `
|
||||||
Output string `json:"output" gorm:"column:output;type:text;" `
|
Output string `json:"output" gorm:"column:output;type:text;" `
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package entity
|
|||||||
|
|
||||||
import "online_code/common/types"
|
import "online_code/common/types"
|
||||||
|
|
||||||
type User struct {
|
type UserBasic struct {
|
||||||
types.BaseDbModel
|
types.BaseDbModel
|
||||||
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'用户唯一标识'"`
|
Identity string `json:"identity" gorm:"column:identity;type:varchar(36);comment:'用户唯一标识'"`
|
||||||
Name string `json:"name" gorm:"column:name;type:varchar(100);not null;comment:'用户名'"`
|
Name string `json:"name" gorm:"column:name;type:varchar(100);not null;comment:'用户名'"`
|
||||||
@@ -14,6 +14,6 @@ type User struct {
|
|||||||
IsAdmin int `json:"is_admin" gorm:"column:is_admin;type:tinyint(1);comment:'是否是管理员【0-否,1-是】'"`
|
IsAdmin int `json:"is_admin" gorm:"column:is_admin;type:tinyint(1);comment:'是否是管理员【0-否,1-是】'"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *User) TableName() string {
|
func (table *UserBasic) TableName() string {
|
||||||
return "user"
|
return "user_basic"
|
||||||
}
|
}
|
||||||
7
models/param/base.go
Normal file
7
models/param/base.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
// 分页通用参数
|
||||||
|
type page struct {
|
||||||
|
Current int `json:"current" form:"current" binding:"required"` // 页码
|
||||||
|
Size int `json:"size" form:"size" binding:"required"` // 每页数量
|
||||||
|
}
|
||||||
7
models/param/problem.go
Normal file
7
models/param/problem.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
type GetProblemList struct {
|
||||||
|
page
|
||||||
|
Keyword string `json:"keyword" form:"keyword"` // 问题关键字
|
||||||
|
CategoryIdentity string `json:"category_identity" form:"category_identity"` // 问题分类标识
|
||||||
|
}
|
||||||
8
models/param/submit.go
Normal file
8
models/param/submit.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
type GetSubmitList struct {
|
||||||
|
page
|
||||||
|
ProblemIdentity string `json:"problemIdentity" form:"problemIdentity"`
|
||||||
|
UserIdentity string `json:"userIdentity" form:"userIdentity"`
|
||||||
|
Status int `json:"status" form:"status"`
|
||||||
|
}
|
||||||
19
repository/base.go
Normal file
19
repository/base.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
// 分页组件
|
||||||
|
func page(current, size int) func(db *gorm.DB) *gorm.DB {
|
||||||
|
return func(db *gorm.DB) *gorm.DB {
|
||||||
|
if current == 0 {
|
||||||
|
current = 1
|
||||||
|
}
|
||||||
|
if size < 1 {
|
||||||
|
size = 10
|
||||||
|
}
|
||||||
|
// 计算偏移量
|
||||||
|
offset := (current - 1) * size
|
||||||
|
// 返回组装结果
|
||||||
|
return db.Offset(offset).Limit(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
repository/problem.go
Normal file
35
repository/problem.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"online_code/client"
|
||||||
|
"online_code/models/entity"
|
||||||
|
"online_code/models/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
type problemService struct{}
|
||||||
|
|
||||||
|
func ProblemService() *problemService {
|
||||||
|
return &problemService{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetList 获取题目列表
|
||||||
|
func (problemService) GetList(p param.GetProblemList) (records []entity.ProblemBasic, count int64, err error) {
|
||||||
|
sel := client.MySQL.Scopes(page(p.Current, p.Size)).Preload("ProblemCategories").Preload("ProblemCategories.CategoryBasic")
|
||||||
|
|
||||||
|
if p.Keyword != "" {
|
||||||
|
sel.Where("title LIKE ? OR content like ?", "%"+p.Keyword+"%", "%"+p.Keyword+"%")
|
||||||
|
}
|
||||||
|
if p.CategoryIdentity != "" {
|
||||||
|
sel.Joins("RIGHT JOINN problem_category pc on pc.problem_id = problem.id").
|
||||||
|
Where("pc.category_id= (SELECT cb.id FROM category cb WHERE cb.identity = ?)", p.CategoryIdentity)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sel.Order("updated_at DESC").Find(&records).Offset(-1).Limit(-1).Count(&count).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProblemInfo 获取题目详情
|
||||||
|
func (problemService) GetProblemInfo(id int) (problem entity.ProblemBasic, err error) {
|
||||||
|
err = client.MySQL.Where("id = ?", id).Find(&problem).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
28
repository/submit.go
Normal file
28
repository/submit.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"online_code/client"
|
||||||
|
"online_code/models/entity"
|
||||||
|
"online_code/models/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
type submitService struct{}
|
||||||
|
|
||||||
|
func SubmitService() *submitService {
|
||||||
|
return &submitService{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (submitService) GetList(p param.GetSubmitList) (records []entity.SubmitBasic, count int64, err error) {
|
||||||
|
tx := client.MySQL.Scopes(page(p.Current, p.Size))
|
||||||
|
if p.ProblemIdentity != "" {
|
||||||
|
tx = tx.Where("problem_identity = ?", p.ProblemIdentity)
|
||||||
|
}
|
||||||
|
if p.UserIdentity != "" {
|
||||||
|
tx = tx.Where("user_identity = ?", p.UserIdentity)
|
||||||
|
}
|
||||||
|
if p.Status != 0 && p.Status != 1 && p.Status != 2 {
|
||||||
|
tx = tx.Where("status = ?", p.Status)
|
||||||
|
}
|
||||||
|
err = tx.Offset(-1).Limit(-1).Count(&count).Find(&records).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
7
repository/user.go
Normal file
7
repository/user.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
type userService struct{}
|
||||||
|
|
||||||
|
func UserService() *userService {
|
||||||
|
return &userService{}
|
||||||
|
}
|
||||||
10
route/problem.go
Normal file
10
route/problem.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"online_code/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func problem(g *gin.RouterGroup) {
|
||||||
|
g.GET("/list", api.ProblemApi().GetProbleList)
|
||||||
|
}
|
||||||
8
route/router.go
Normal file
8
route/router.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
func InitRoute(g *gin.RouterGroup) {
|
||||||
|
problem(g.Group("/problem"))
|
||||||
|
user(g.Group("/user"))
|
||||||
|
}
|
||||||
10
route/user.go
Normal file
10
route/user.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"online_code/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func user(g *gin.RouterGroup) {
|
||||||
|
g.GET("/:identity", api.UserApi().GetUserInfo) // 获取用户详情
|
||||||
|
}
|
||||||
14
utils/page.go
Normal file
14
utils/page.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
// GenTotalPage 计算总页数
|
||||||
|
func GenTotalPage(count int64, size int) int {
|
||||||
|
totalPage := 0
|
||||||
|
if count > 0 {
|
||||||
|
upPage := 0
|
||||||
|
if int(count)%size > 0 {
|
||||||
|
upPage = 1
|
||||||
|
}
|
||||||
|
totalPage = (int(count) / size) + upPage
|
||||||
|
}
|
||||||
|
return totalPage
|
||||||
|
}
|
||||||
20
utils/token.go
Normal file
20
utils/token.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 生成Token的密钥,写死,防止乱改
|
||||||
|
//var jwtSecret = "qSxw4fCBBBecPsws"
|
||||||
|
|
||||||
|
// HashPassword 加密密码
|
||||||
|
func HashPassword(pass *string) {
|
||||||
|
bytePass := []byte(*pass)
|
||||||
|
hPass, _ := bcrypt.GenerateFromPassword(bytePass, bcrypt.DefaultCost)
|
||||||
|
*pass = string(hPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComparePassword 校验密码
|
||||||
|
func ComparePassword(dbPass, pass string) bool {
|
||||||
|
return bcrypt.CompareHashAndPassword([]byte(dbPass), []byte(pass)) == nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user