完成相应数据库表基础设计

dev
truthhun 2 years ago
parent 0ed88bfb67
commit 456fd750a7

3
.gitignore vendored

@ -1,5 +1,6 @@
go.sum
app.toml
*.toml
!app.example.toml
*.exe
*.exe~
# 忽略生成的proto go文件

@ -16,7 +16,7 @@ limitations under the License.
package cmd
import (
"fmt"
"moredoc/service"
"github.com/spf13/cobra"
)
@ -27,7 +27,7 @@ var syncdbCmd = &cobra.Command{
Short: "sync database scheme",
Long: `sync database scheme.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("syncdb called")
service.SyncDB(cfg, logger)
},
}

@ -34,6 +34,7 @@ var versionCmd = &cobra.Command{
Long: `show current version information.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
fmt.Println("AppName: ", "moredoc")
fmt.Println("Version: ", Version)
fmt.Println("BuildAt: ", BuildAt)
fmt.Println("GitHash: ", GitHash)

@ -25,6 +25,7 @@ require (
require google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7 // indirect
require (
github.com/alexandrevicenzi/unchained v1.3.0
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-contrib/static v0.0.1

@ -0,0 +1,172 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Attachment struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20) unsigned;default:0;primarykey;autoIncrement;comment:附件 id;"`
Hash string `form:"hash" json:"hash,omitempty" gorm:"column:hash;type:char(32);size:32;default:;index:hash;comment:文件MD5;"`
UserId int64 `form:"user_id" json:"user_id,omitempty" gorm:"column:user_id;type:bigint(20) unsigned;default:0;index:user_id;comment:用户 id;"`
TypeId int64 `form:"type_id" json:"type_id,omitempty" gorm:"column:type_id;type:bigint(20) unsigned;default:0;comment:类型数据ID对应与用户头像时则为用户id对应为文档时则为文档ID;"`
Type int `form:"type" json:"type,omitempty" gorm:"column:type;type:smallint(5) unsigned;default:0;comment:附件类型(0 头像1 文档2 文章附件 ...);"`
IsApproved int8 `form:"is_approved" json:"is_approved,omitempty" gorm:"column:is_approved;type:tinyint(3) unsigned;default:1;comment:是否合法;"`
Path string `form:"path" json:"path,omitempty" gorm:"column:path;type:varchar(255);size:255;default:;comment:文件存储路径;"`
Name string `form:"name" json:"name,omitempty" gorm:"column:name;type:varchar(255);size:255;default:;comment:文件原名称;"`
Size int64 `form:"size" json:"size,omitempty" gorm:"column:size;type:bigint(20) unsigned;default:0;comment:文件大小;"`
Width int64 `form:"width" json:"width,omitempty" gorm:"column:width;type:bigint(20) unsigned;default:0;comment:宽度;"`
Height int64 `form:"height" json:"height,omitempty" gorm:"column:height;type:bigint(20) unsigned;default:0;comment:高度;"`
Ext string `form:"ext" json:"ext,omitempty" gorm:"column:ext;type:varchar(32);size:32;default:;comment:文件类型,如 .pdf 。统一处理成小写;"`
Ip string `form:"ip" json:"ip,omitempty" gorm:"column:ip;type:varchar(16);size:16;default:;comment:上传文档的用户IP地址;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;default:;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;default:;comment:更新时间;"`
}
func (Attachment) TableName() string {
return tablePrefix + "attachment"
}
// CreateAttachment 创建Attachment
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateAttachment(attachment *Attachment) (err error) {
err = m.db.Create(attachment).Error
if err != nil {
m.logger.Error("CreateAttachment", zap.Error(err))
return
}
return
}
// UpdateAttachment 更新Attachment如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateAttachment(attachment *Attachment, updateFields ...string) (err error) {
db := m.db.Model(attachment)
updateFields = m.FilterValidFields(Attachment{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", attachment.Id).Updates(attachment).Error
if err != nil {
m.logger.Error("UpdateAttachment", zap.Error(err))
}
return
}
// GetAttachment 根据id获取Attachment
func (m *DBModel) GetAttachment(id interface{}, fields ...string) (attachment Attachment, err error) {
db := m.db
fields = m.FilterValidFields(Attachment{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&attachment).Error
return
}
type OptionGetAttachmentList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetAttachmentList 获取Attachment列表
func (m *DBModel) GetAttachmentList(opt OptionGetAttachmentList) (attachmentList []Attachment, total int64, err error) {
db := m.db.Model(&Attachment{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Attachment{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Attachment{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Attachment{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetAttachmentList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Attachment{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Attachment{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&attachmentList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetAttachmentList", zap.Error(err))
}
return
}
// DeleteAttachment 删除数据
// TODO: 删除数据之后,存在 attachment_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteAttachment(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Attachment{}).Error
if err != nil {
m.logger.Error("DeleteAttachment", zap.Error(err))
}
return
}

@ -0,0 +1,166 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Banner struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20);size:20;default:0;primarykey;autoIncrement;comment:;"`
Title string `form:"title" json:"title,omitempty" gorm:"column:title;type:varchar(255);size:255;default:;comment:横幅名称;"`
Path string `form:"path" json:"path,omitempty" gorm:"column:path;type:varchar(255);size:255;default:;comment:横幅地址;"`
Sort int `form:"sort" json:"sort,omitempty" gorm:"column:sort;type:int(11);size:11;default:0;comment:排序,值越大越靠前;"`
Status int8 `form:"status" json:"status,omitempty" gorm:"column:status;type:tinyint(4);size:4;default:0;comment:0 正常1禁用;"`
Category int8 `form:"category" json:"category,omitempty" gorm:"column:category;type:tinyint(4);size:4;default:0;comment:0 PC横幅1 H5横幅2 小程序横幅3 APP横幅;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;default:;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;default:;comment:更新时间;"`
Url string `form:"url" json:"url,omitempty" gorm:"column:url;type:varchar(255);size:255;default:;comment:横幅跳转地址;"`
}
func (Banner) TableName() string {
return tablePrefix + "banner"
}
// CreateBanner 创建Banner
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateBanner(banner *Banner) (err error) {
err = m.db.Create(banner).Error
if err != nil {
m.logger.Error("CreateBanner", zap.Error(err))
return
}
return
}
// UpdateBanner 更新Banner如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateBanner(banner *Banner, updateFields ...string) (err error) {
db := m.db.Model(banner)
updateFields = m.FilterValidFields(Banner{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", banner.Id).Updates(banner).Error
if err != nil {
m.logger.Error("UpdateBanner", zap.Error(err))
}
return
}
// GetBanner 根据id获取Banner
func (m *DBModel) GetBanner(id interface{}, fields ...string) (banner Banner, err error) {
db := m.db
fields = m.FilterValidFields(Banner{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&banner).Error
return
}
type OptionGetBannerList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetBannerList 获取Banner列表
func (m *DBModel) GetBannerList(opt OptionGetBannerList) (bannerList []Banner, total int64, err error) {
db := m.db.Model(&Banner{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Banner{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Banner{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Banner{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetBannerList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Banner{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Banner{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&bannerList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetBannerList", zap.Error(err))
}
return
}
// DeleteBanner 删除数据
// TODO: 删除数据之后,存在 banner_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteBanner(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Banner{}).Error
if err != nil {
m.logger.Error("DeleteBanner", zap.Error(err))
}
return
}

@ -0,0 +1,188 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Category struct {
Id int `form:"id" json:"id,omitempty" gorm:"column:id;type:int(11);size:11;default:0;primarykey;comment:;"`
ParentId int `form:"parent_id" json:"parent_id,omitempty" gorm:"column:parent_id;type:int(11);size:11;default:0;index:parent_id_title,unique;index:parent_id;comment:上级ID;"`
Title string `form:"title" json:"title,omitempty" gorm:"column:title;type:varchar(64);size:64;default:;index:parent_id_title,unique;comment:分类名称;"`
Cover string `form:"cover" json:"cover,omitempty" gorm:"column:cover;type:varchar(255);size:255;default:;comment:分类封面;"`
DocCount int `form:"doc_count" json:"doc_count,omitempty" gorm:"column:doc_count;type:int(11);size:11;default:0;comment:文档统计;"`
Sort int `form:"sort" json:"sort,omitempty" gorm:"column:sort;type:int(11);size:11;default:0;comment:排序,值越大越靠前;"`
Alias string `form:"alias" json:"alias,omitempty" gorm:"column:alias;type:varchar(64);size:64;default:;comment:别名,限英文和数字等组成;"`
Status int8 `form:"status" json:"status,omitempty" gorm:"column:status;type:tinyint(1);size:1;default:0;comment:状态0 正常1 禁用;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;default:;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;default:;comment:更新时间;"`
}
func (Category) TableName() string {
return tablePrefix + "category"
}
// CreateCategory 创建Category
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateCategory(category *Category) (err error) {
err = m.db.Create(category).Error
if err != nil {
m.logger.Error("CreateCategory", zap.Error(err))
return
}
return
}
// UpdateCategory 更新Category如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateCategory(category *Category, updateFields ...string) (err error) {
db := m.db.Model(category)
updateFields = m.FilterValidFields(Category{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", category.Id).Updates(category).Error
if err != nil {
m.logger.Error("UpdateCategory", zap.Error(err))
}
return
}
// GetCategory 根据id获取Category
func (m *DBModel) GetCategory(id interface{}, fields ...string) (category Category, err error) {
db := m.db
fields = m.FilterValidFields(Category{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&category).Error
return
}
// GetCategoryByParentIdTitle(parentId int, title string, fields ...string) 根据唯一索引获取Category
func (m *DBModel) GetCategoryByParentIdTitle(parentId int, title string, fields ...string) (category Category, err error) {
db := m.db
fields = m.FilterValidFields(Category{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
db = db.Where("parent_id = ?", parentId)
db = db.Where("title = ?", title)
err = db.First(&category).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetCategoryByParentIdTitle", zap.Error(err))
return
}
return
}
type OptionGetCategoryList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetCategoryList 获取Category列表
func (m *DBModel) GetCategoryList(opt OptionGetCategoryList) (categoryList []Category, total int64, err error) {
db := m.db.Model(&Category{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Category{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Category{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Category{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetCategoryList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Category{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Category{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&categoryList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetCategoryList", zap.Error(err))
}
return
}
// DeleteCategory 删除数据
// TODO: 删除数据之后,存在 category_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteCategory(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Category{}).Error
if err != nil {
m.logger.Error("DeleteCategory", zap.Error(err))
}
return
}

@ -0,0 +1,189 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Config struct {
Id int `form:"id" json:"id,omitempty" gorm:"column:id;type:int(11);size:11;default:0;primarykey;comment:;"`
Label string `form:"label" json:"label,omitempty" gorm:"column:label;type:varchar(64);size:64;default:;comment:标签名称;"`
Name string `form:"name" json:"name,omitempty" gorm:"column:name;type:varchar(64);size:64;default:;index:name_category,unique;comment:表单字段名称;"`
Value string `form:"value" json:"value,omitempty" gorm:"column:value;type:text;default:;comment:值;"`
Placeholder int `form:"placeholder" json:"placeholder,omitempty" gorm:"column:placeholder;type:int(11);size:11;default:0;comment:提示信息;"`
InputType int `form:"input_type" json:"input_type,omitempty" gorm:"column:input_type;type:int(11);size:11;default:0;comment:输入类型;"`
Category string `form:"category" json:"category,omitempty" gorm:"column:category;type:varchar(32);size:32;default:;index:name_category,unique;index:category;comment:所属类别;"`
Sort int `form:"sort" json:"sort,omitempty" gorm:"column:sort;type:int(11);size:11;default:0;comment:同一category下的排序;"`
Options string `form:"options" json:"options,omitempty" gorm:"column:options;type:text;default:;comment:针对checkbox等的枚举值;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;default:;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;default:;comment:更新时间;"`
}
func (Config) TableName() string {
return tablePrefix + "config"
}
// CreateConfig 创建Config
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateConfig(config *Config) (err error) {
err = m.db.Create(config).Error
if err != nil {
m.logger.Error("CreateConfig", zap.Error(err))
return
}
return
}
// UpdateConfig 更新Config如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateConfig(config *Config, updateFields ...string) (err error) {
db := m.db.Model(config)
updateFields = m.FilterValidFields(Config{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", config.Id).Updates(config).Error
if err != nil {
m.logger.Error("UpdateConfig", zap.Error(err))
}
return
}
// GetConfig 根据id获取Config
func (m *DBModel) GetConfig(id interface{}, fields ...string) (config Config, err error) {
db := m.db
fields = m.FilterValidFields(Config{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&config).Error
return
}
// GetConfigByNameCategory(name string, category string, fields ...string) 根据唯一索引获取Config
func (m *DBModel) GetConfigByNameCategory(name string, category string, fields ...string) (config Config, err error) {
db := m.db
fields = m.FilterValidFields(Config{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
db = db.Where("name = ?", name)
db = db.Where("category = ?", category)
err = db.First(&config).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetConfigByNameCategory", zap.Error(err))
return
}
return
}
type OptionGetConfigList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetConfigList 获取Config列表
func (m *DBModel) GetConfigList(opt OptionGetConfigList) (configList []Config, total int64, err error) {
db := m.db.Model(&Config{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Config{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Config{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Config{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetConfigList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Config{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Config{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&configList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetConfigList", zap.Error(err))
}
return
}
// DeleteConfig 删除数据
// TODO: 删除数据之后,存在 config_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteConfig(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Config{}).Error
if err != nil {
m.logger.Error("DeleteConfig", zap.Error(err))
}
return
}

@ -0,0 +1,179 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Document struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20);size:20;default:0;primarykey;autoIncrement;comment:;"`
Title string `form:"title" json:"title,omitempty" gorm:"column:title;type:varchar(255);size:255;default:;comment:文档名称;"`
Keywords string `form:"keywords" json:"keywords,omitempty" gorm:"column:keywords;type:varchar(255);size:255;default:;comment:文档关键字;"`
Description string `form:"description" json:"description,omitempty" gorm:"column:description;type:varchar(512);size:512;default:;comment:文档描述;"`
UserId int64 `form:"user_id" json:"user_id,omitempty" gorm:"column:user_id;type:bigint(20);size:20;default:0;index:user_id;comment:文档所属用户ID;"`
Cover string `form:"cover" json:"cover,omitempty" gorm:"column:cover;type:varchar(255);size:255;default:;comment:文档封面;"`
Width int `form:"width" json:"width,omitempty" gorm:"column:width;type:int(11);size:11;default:0;comment:宽;"`
Height int `form:"height" json:"height,omitempty" gorm:"column:height;type:int(11);size:11;default:0;comment:高;"`
Preview int `form:"preview" json:"preview,omitempty" gorm:"column:preview;type:int(11);size:11;default:0;comment:允许预览页数;"`
Pages int `form:"pages" json:"pages,omitempty" gorm:"column:pages;type:int(11);size:11;default:0;comment:文档页数;"`
Uuid string `form:"uuid" json:"uuid,omitempty" gorm:"column:uuid;type:varchar(36);size:36;default:;comment:文档UUID用于隐藏文档真实路径;"`
DownloadCount int `form:"download_count" json:"download_count,omitempty" gorm:"column:download_count;type:int(11);size:11;default:0;comment:下载人次;"`
ViewCount int `form:"view_count" json:"view_count,omitempty" gorm:"column:view_count;type:int(11);size:11;default:0;comment:浏览人次;"`
FavoriteCount int `form:"favorite_count" json:"favorite_count,omitempty" gorm:"column:favorite_count;type:int(11);size:11;default:0;comment:收藏人次;"`
CommentCount int `form:"comment_count" json:"comment_count,omitempty" gorm:"column:comment_count;type:int(11);size:11;default:0;comment:评论人次;"`
Score int `form:"score" json:"score,omitempty" gorm:"column:score;type:int(11);size:11;default:0;comment:评分3位整数表示500表示5分;"`
ScoreCount int `form:"score_count" json:"score_count,omitempty" gorm:"column:score_count;type:int(11);size:11;default:0;comment:评分数量;"`
Price int `form:"price" json:"price,omitempty" gorm:"column:price;type:int(11);size:11;default:0;comment:价格0表示免费;"`
Size int64 `form:"size" json:"size,omitempty" gorm:"column:size;type:bigint(20);size:20;default:0;comment:文件大小;"`
Status int `form:"status" json:"status,omitempty" gorm:"column:status;type:smallint(6);size:6;default:0;index:status;comment:文档状态0 待转换1 转换中2 转换完成3 转换失败4 禁用;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (Document) TableName() string {
return tablePrefix + "document"
}
// CreateDocument 创建Document
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateDocument(document *Document) (err error) {
err = m.db.Create(document).Error
if err != nil {
m.logger.Error("CreateDocument", zap.Error(err))
return
}
return
}
// UpdateDocument 更新Document如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateDocument(document *Document, updateFields ...string) (err error) {
db := m.db.Model(document)
updateFields = m.FilterValidFields(Document{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", document.Id).Updates(document).Error
if err != nil {
m.logger.Error("UpdateDocument", zap.Error(err))
}
return
}
// GetDocument 根据id获取Document
func (m *DBModel) GetDocument(id interface{}, fields ...string) (document Document, err error) {
db := m.db
fields = m.FilterValidFields(Document{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&document).Error
return
}
type OptionGetDocumentList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetDocumentList 获取Document列表
func (m *DBModel) GetDocumentList(opt OptionGetDocumentList) (documentList []Document, total int64, err error) {
db := m.db.Model(&Document{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Document{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Document{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Document{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetDocumentList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Document{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Document{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&documentList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetDocumentList", zap.Error(err))
}
return
}
// DeleteDocument 删除数据
// TODO: 删除数据之后,存在 document_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteDocument(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Document{}).Error
if err != nil {
m.logger.Error("DeleteDocument", zap.Error(err))
}
return
}

@ -0,0 +1,162 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type DocumentCategory struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20);size:20;default:0;primarykey;autoIncrement;comment:;"`
DocumentId int64 `form:"document_id" json:"document_id,omitempty" gorm:"column:document_id;type:bigint(20);size:20;default:0;comment:文档ID;"`
CategoryId int64 `form:"category_id" json:"category_id,omitempty" gorm:"column:category_id;type:bigint(20);size:20;default:0;index:category_id;comment:分类ID;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (DocumentCategory) TableName() string {
return tablePrefix + "document_category"
}
// CreateDocumentCategory 创建DocumentCategory
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateDocumentCategory(documentCategory *DocumentCategory) (err error) {
err = m.db.Create(documentCategory).Error
if err != nil {
m.logger.Error("CreateDocumentCategory", zap.Error(err))
return
}
return
}
// UpdateDocumentCategory 更新DocumentCategory如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateDocumentCategory(documentCategory *DocumentCategory, updateFields ...string) (err error) {
db := m.db.Model(documentCategory)
updateFields = m.FilterValidFields(DocumentCategory{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", documentCategory.Id).Updates(documentCategory).Error
if err != nil {
m.logger.Error("UpdateDocumentCategory", zap.Error(err))
}
return
}
// GetDocumentCategory 根据id获取DocumentCategory
func (m *DBModel) GetDocumentCategory(id interface{}, fields ...string) (documentCategory DocumentCategory, err error) {
db := m.db
fields = m.FilterValidFields(DocumentCategory{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&documentCategory).Error
return
}
type OptionGetDocumentCategoryList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetDocumentCategoryList 获取DocumentCategory列表
func (m *DBModel) GetDocumentCategoryList(opt OptionGetDocumentCategoryList) (documentCategoryList []DocumentCategory, total int64, err error) {
db := m.db.Model(&DocumentCategory{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(DocumentCategory{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(DocumentCategory{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(DocumentCategory{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetDocumentCategoryList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(DocumentCategory{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(DocumentCategory{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&documentCategoryList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetDocumentCategoryList", zap.Error(err))
}
return
}
// DeleteDocumentCategory 删除数据
// TODO: 删除数据之后,存在 document_category_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteDocumentCategory(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&DocumentCategory{}).Error
if err != nil {
m.logger.Error("DeleteDocumentCategory", zap.Error(err))
}
return
}

@ -0,0 +1,163 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type DocumentScore struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20);size:20;default:0;primarykey;autoIncrement;comment:;"`
DocumentId int64 `form:"document_id" json:"document_id,omitempty" gorm:"column:document_id;type:bigint(20);size:20;default:0;comment:文档ID;"`
UserId int64 `form:"user_id" json:"user_id,omitempty" gorm:"column:user_id;type:bigint(20);size:20;default:0;comment:用户ID;"`
Score int `form:"score" json:"score,omitempty" gorm:"column:score;type:int(11);size:11;default:0;comment:文档评分值3位数如500表示5分;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (DocumentScore) TableName() string {
return tablePrefix + "document_score"
}
// CreateDocumentScore 创建DocumentScore
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateDocumentScore(documentScore *DocumentScore) (err error) {
err = m.db.Create(documentScore).Error
if err != nil {
m.logger.Error("CreateDocumentScore", zap.Error(err))
return
}
return
}
// UpdateDocumentScore 更新DocumentScore如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateDocumentScore(documentScore *DocumentScore, updateFields ...string) (err error) {
db := m.db.Model(documentScore)
updateFields = m.FilterValidFields(DocumentScore{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", documentScore.Id).Updates(documentScore).Error
if err != nil {
m.logger.Error("UpdateDocumentScore", zap.Error(err))
}
return
}
// GetDocumentScore 根据id获取DocumentScore
func (m *DBModel) GetDocumentScore(id interface{}, fields ...string) (documentScore DocumentScore, err error) {
db := m.db
fields = m.FilterValidFields(DocumentScore{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&documentScore).Error
return
}
type OptionGetDocumentScoreList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetDocumentScoreList 获取DocumentScore列表
func (m *DBModel) GetDocumentScoreList(opt OptionGetDocumentScoreList) (documentScoreList []DocumentScore, total int64, err error) {
db := m.db.Model(&DocumentScore{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(DocumentScore{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(DocumentScore{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(DocumentScore{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetDocumentScoreList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(DocumentScore{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(DocumentScore{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&documentScoreList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetDocumentScoreList", zap.Error(err))
}
return
}
// DeleteDocumentScore 删除数据
// TODO: 删除数据之后,存在 document_score_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteDocumentScore(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&DocumentScore{}).Error
if err != nil {
m.logger.Error("DeleteDocumentScore", zap.Error(err))
}
return
}

@ -0,0 +1,163 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Download struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20);size:20;default:0;primarykey;autoIncrement;comment:;"`
UserId int64 `form:"user_id" json:"user_id,omitempty" gorm:"column:user_id;type:bigint(20);size:20;default:0;index:user_id;comment:下载文档的用户ID;"`
DocumentId int64 `form:"document_id" json:"document_id,omitempty" gorm:"column:document_id;type:bigint(20);size:20;default:0;comment:被下载的文档ID;"`
Ip string `form:"ip" json:"ip,omitempty" gorm:"column:ip;type:varchar(16);size:16;default:;comment:下载文档的用户IP;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (Download) TableName() string {
return tablePrefix + "download"
}
// CreateDownload 创建Download
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateDownload(download *Download) (err error) {
err = m.db.Create(download).Error
if err != nil {
m.logger.Error("CreateDownload", zap.Error(err))
return
}
return
}
// UpdateDownload 更新Download如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateDownload(download *Download, updateFields ...string) (err error) {
db := m.db.Model(download)
updateFields = m.FilterValidFields(Download{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", download.Id).Updates(download).Error
if err != nil {
m.logger.Error("UpdateDownload", zap.Error(err))
}
return
}
// GetDownload 根据id获取Download
func (m *DBModel) GetDownload(id interface{}, fields ...string) (download Download, err error) {
db := m.db
fields = m.FilterValidFields(Download{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&download).Error
return
}
type OptionGetDownloadList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetDownloadList 获取Download列表
func (m *DBModel) GetDownloadList(opt OptionGetDownloadList) (downloadList []Download, total int64, err error) {
db := m.db.Model(&Download{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Download{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Download{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Download{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetDownloadList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Download{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Download{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&downloadList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetDownloadList", zap.Error(err))
}
return
}
// DeleteDownload 删除数据
// TODO: 删除数据之后,存在 download_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteDownload(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Download{}).Error
if err != nil {
m.logger.Error("DeleteDownload", zap.Error(err))
}
return
}

@ -0,0 +1,165 @@
package model
import (
"fmt"
"strings"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Friendlink struct {
Id int `form:"id" json:"id,omitempty" gorm:"column:id;type:int(11);size:11;default:0;comment:;"`
Title string `form:"title" json:"title,omitempty" gorm:"column:title;type:varchar(64);size:64;default:;comment:链接名称;"`
Link string `form:"link" json:"link,omitempty" gorm:"column:link;type:varchar(255);size:255;default:;comment:链接地址;"`
Note string `form:"note" json:"note,omitempty" gorm:"column:note;type:text;default:;comment:备注;"`
Sort int `form:"sort" json:"sort,omitempty" gorm:"column:sort;type:int(11);size:11;default:0;comment:排序,值越大越靠前;"`
Status int8 `form:"status" json:"status,omitempty" gorm:"column:status;type:tinyint(4);size:4;default:0;comment:状态0 正常1 禁用;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (Friendlink) TableName() string {
return tablePrefix + "friendlink"
}
// CreateFriendlink 创建Friendlink
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateFriendlink(friendlink *Friendlink) (err error) {
err = m.db.Create(friendlink).Error
if err != nil {
m.logger.Error("CreateFriendlink", zap.Error(err))
return
}
return
}
// UpdateFriendlink 更新Friendlink如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateFriendlink(friendlink *Friendlink, updateFields ...string) (err error) {
db := m.db.Model(friendlink)
updateFields = m.FilterValidFields(Friendlink{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", friendlink.Id).Updates(friendlink).Error
if err != nil {
m.logger.Error("UpdateFriendlink", zap.Error(err))
}
return
}
// GetFriendlink 根据id获取Friendlink
func (m *DBModel) GetFriendlink(id interface{}, fields ...string) (friendlink Friendlink, err error) {
db := m.db
fields = m.FilterValidFields(Friendlink{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&friendlink).Error
return
}
type OptionGetFriendlinkList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetFriendlinkList 获取Friendlink列表
func (m *DBModel) GetFriendlinkList(opt OptionGetFriendlinkList) (friendlinkList []Friendlink, total int64, err error) {
db := m.db.Model(&Friendlink{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(Friendlink{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(Friendlink{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(Friendlink{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetFriendlinkList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(Friendlink{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(Friendlink{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&friendlinkList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetFriendlinkList", zap.Error(err))
}
return
}
// DeleteFriendlink 删除数据
// TODO: 删除数据之后,存在 friendlink_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteFriendlink(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&Friendlink{}).Error
if err != nil {
m.logger.Error("DeleteFriendlink", zap.Error(err))
}
return
}

@ -126,7 +126,16 @@ func NewDBModel(cfg *conf.Database, lg *zap.Logger) (m *DBModel, err error) {
func (m *DBModel) SyncDB() (err error) {
tableModels := []interface{}{
// &User{},
&Attachment{},
&Banner{},
&Category{},
&Config{},
&Document{},
&DocumentCategory{},
&DocumentScore{},
&Download{},
&Friendlink{},
&User{},
}
if err = m.db.AutoMigrate(tableModels...); err != nil {
m.logger.Error("SyncDB", zap.Error(err))

@ -0,0 +1,211 @@
package model
import (
"fmt"
"strings"
"time"
"github.com/alexandrevicenzi/unchained"
"go.uber.org/zap"
"gorm.io/gorm"
)
type User struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"column:id;type:bigint(20) unsigned;default:0;primarykey;comment:用户 id;"`
Username string `form:"username" json:"username,omitempty" gorm:"column:username;type:varchar(64);size:64;default:;index:username,unique;comment:用户名;"`
Password string `form:"password" json:"password,omitempty" gorm:"column:password;type:varchar(128);size:128;default:;comment:密码;"`
Nickname string `form:"nickname" json:"nickname,omitempty" gorm:"column:nickname;type:varchar(64);size:64;default:;comment:用户昵称;"`
Mobile string `form:"mobile" json:"mobile,omitempty" gorm:"column:mobile;type:varchar(20);size:20;default:;index:mobile;comment:手机号;"`
Email string `form:"email" json:"email,omitempty" gorm:"column:email;type:varchar(64);size:64;default:;index:email;comment:联系邮箱;"`
Address string `form:"address" json:"address,omitempty" gorm:"column:address;type:varchar(255);size:255;default:;comment:联系地址;"`
Signature string `form:"signature" json:"signature,omitempty" gorm:"column:signature;type:varchar(255);size:255;default:;comment:签名;"`
LastLoginIp string `form:"last_login_ip" json:"last_login_ip,omitempty" gorm:"column:last_login_ip;type:varchar(16);size:16;default:;comment:最后登录 ip 地址;"`
RegisterIp string `form:"register_ip" json:"register_ip,omitempty" gorm:"column:register_ip;type:varchar(16);size:16;default:;comment:注册ip;"`
DocCount int `form:"doc_count" json:"doc_count,omitempty" gorm:"column:doc_count;type:int(10) unsigned;default:0;comment:上传的文档数;"`
FollowCount int `form:"follow_count" json:"follow_count,omitempty" gorm:"column:follow_count;type:int(10) unsigned;default:0;comment:关注数;"`
FansCount int `form:"fans_count" json:"fans_count,omitempty" gorm:"column:fans_count;type:int(10) unsigned;default:0;comment:粉丝数;"`
FavoriteCount int `form:"favorite_count" json:"favorite_count,omitempty" gorm:"column:favorite_count;type:int(10) unsigned;default:0;comment:收藏数;"`
CommentCount int `form:"comment_count" json:"comment_count,omitempty" gorm:"column:comment_count;type:int(11);size:11;default:0;comment:评论数;"`
Status int8 `form:"status" json:"status,omitempty" gorm:"column:status;type:tinyint(4);size:4;default:0;index:status;comment:用户状态0正常 1禁用 2审核中 3审核拒绝 4审核忽略;"`
Avatar string `form:"avatar" json:"avatar,omitempty" gorm:"column:avatar;type:varchar(255);size:255;default:;comment:头像;"`
Identity string `form:"identity" json:"identity,omitempty" gorm:"column:identity;type:char(18);size:18;default:;comment:身份证号码;"`
Realname string `form:"realname" json:"realname,omitempty" gorm:"column:realname;type:varchar(20);size:20;default:;comment:身份证姓名;"`
LoginAt time.Time `form:"login_at" json:"login_at,omitempty" gorm:"column:login_at;type:datetime;default:;comment:最后登录时间;"`
CreatedAt time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;default:;comment:创建时间;"`
UpdatedAt time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;default:;comment:更新时间;"`
}
func (User) TableName() string {
return tablePrefix + "user"
}
// CreateUser 创建User
// TODO: 创建成功之后,注意相关表统计字段数值的增减
func (m *DBModel) CreateUser(user *User) (err error) {
user.Password, _ = unchained.MakePassword(user.Password, unchained.GetRandomString(4), "md5")
err = m.db.Create(user).Error
if err != nil {
m.logger.Error("CreateUser", zap.Error(err))
return
}
return
}
// UpdateUserPassword 更新User密码
func (m *DBModel) UpdateUserPassword(id interface{}, newPassword string) (err error) {
newPassword, _ = unchained.MakePassword(newPassword, unchained.GetRandomString(4), "md5")
err = m.db.Model(&User{}).Where("id = ?", id).Update("password", newPassword).Error
if err != nil {
m.logger.Error("UpdateUserPassword", zap.Error(err))
}
return
}
// UpdateUser 更新User如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateUser(user *User, updateFields ...string) (err error) {
db := m.db.Model(user)
updateFields = m.FilterValidFields(User{}.TableName(), updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
}
err = db.Where("id = ?", user.Id).Updates(user).Error
if err != nil {
m.logger.Error("UpdateUser", zap.Error(err))
}
return
}
// GetUser 根据id获取User
func (m *DBModel) GetUser(id interface{}, fields ...string) (user User, err error) {
db := m.db
fields = m.FilterValidFields(User{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&user).Error
return
}
// GetUserByUsername(username string, fields ...string) 根据唯一索引获取User
func (m *DBModel) GetUserByUsername(username string, fields ...string) (user User, err error) {
db := m.db
fields = m.FilterValidFields(User{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
db = db.Where("username = ?", username)
err = db.First(&user).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetUserByUsername", zap.Error(err))
return
}
return
}
type OptionGetUserList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetUserList 获取User列表
func (m *DBModel) GetUserList(opt OptionGetUserList) (userList []User, total int64, err error) {
db := m.db.Model(&User{})
for field, rangeValue := range opt.QueryRange {
fields := m.FilterValidFields(User{}.TableName(), field)
if len(fields) == 0 {
continue
}
if rangeValue[0] != nil {
db = db.Where(fmt.Sprintf("%s >= ?", field), rangeValue[0])
}
if rangeValue[1] != nil {
db = db.Where(fmt.Sprintf("%s <= ?", field), rangeValue[1])
}
}
for field, values := range opt.QueryIn {
fields := m.FilterValidFields(User{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(fmt.Sprintf("%s in (?)", field), values)
}
for field, values := range opt.QueryLike {
fields := m.FilterValidFields(User{}.TableName(), field)
if len(fields) == 0 {
continue
}
db = db.Where(strings.TrimSuffix(fmt.Sprintf(strings.Join(make([]string, len(values)+1), "%s like ? or"), field), "or"), values...)
}
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetUserList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(User{}.TableName(), opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
if len(opt.Sort) > 0 {
var sorts []string
for _, sort := range opt.Sort {
slice := strings.Split(sort, " ")
if len(m.FilterValidFields(User{}.TableName(), slice[0])) == 0 {
continue
}
if len(slice) == 2 {
sorts = append(sorts, fmt.Sprintf("%s %s", slice[0], slice[1]))
} else {
sorts = append(sorts, fmt.Sprintf("%s desc", slice[0]))
}
}
if len(sorts) > 0 {
db = db.Order(strings.Join(sorts, ","))
}
}
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&userList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetUserList", zap.Error(err))
}
return
}
// DeleteUser 删除数据
// TODO: 删除数据之后,存在 user_id 的关联表,需要删除对应数据,同时相关表的统计数值,也要随着减少
func (m *DBModel) DeleteUser(ids []interface{}) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&User{}).Error
if err != nil {
m.logger.Error("DeleteUser", zap.Error(err))
}
return
}

@ -0,0 +1,24 @@
package service
import (
"moredoc/conf"
"moredoc/model"
"go.uber.org/zap"
)
func SyncDB(cfg *conf.Config, logger *zap.Logger) {
lg := logger.Named("syncdb")
lg.Info("start syncdb")
dbModel, err := model.NewDBModel(&cfg.Database, logger)
if err != nil {
lg.Fatal("NewDBModel", zap.Error(err))
return
}
err = dbModel.SyncDB()
if err != nil {
lg.Fatal("SyncDB", zap.Error(err))
return
}
lg.Info("syncdb success")
}
Loading…
Cancel
Save