2024-10-14 19:27:46 +08:00
|
|
|
|
package model
|
|
|
|
|
|
2024-10-18 10:04:01 +08:00
|
|
|
|
import (
|
|
|
|
|
"catface/app/global/variable"
|
|
|
|
|
"catface/app/utils/data_bind"
|
2024-10-21 01:24:01 +08:00
|
|
|
|
"log"
|
2024-11-02 11:06:27 +08:00
|
|
|
|
"strings"
|
2024-10-18 10:04:01 +08:00
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"go.uber.org/zap"
|
2024-10-21 01:24:01 +08:00
|
|
|
|
"gorm.io/gorm"
|
2024-10-18 10:04:01 +08:00
|
|
|
|
)
|
|
|
|
|
|
2024-10-17 22:43:20 +08:00
|
|
|
|
func CreateEncounterFactory(sqlType string) *Encounter {
|
|
|
|
|
return &Encounter{BaseModel: BaseModel{DB: UseDbConn(sqlType)}}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-17 19:48:43 +08:00
|
|
|
|
type Encounter struct { // Encounter 或者称为 post,指的就是 Human 单次的记录。
|
2024-10-14 19:27:46 +08:00
|
|
|
|
BaseModel
|
2024-10-17 19:48:43 +08:00
|
|
|
|
// TAG 外键关联
|
2024-10-21 16:31:53 +08:00
|
|
|
|
UsersModelId int64 `gorm:"column:user_id" json:"user_id"`
|
2024-11-02 11:49:49 +08:00
|
|
|
|
UsersModel *UsersModel `json:"users_model,omitempty"` // INFO 由于 Detail 返回空子段有些麻烦,先尝试采用指针。
|
|
|
|
|
// AnimalsId string `gorm:"size:20" json:"animals_id"` // 关联对象存在上限 // INFO 还是采取分表,方便查询。
|
2024-10-17 19:48:43 +08:00
|
|
|
|
|
2024-11-14 04:26:12 +08:00
|
|
|
|
Title string `gorm:"size:20;column:title" json:"title"`
|
|
|
|
|
Content string `json:"content"`
|
|
|
|
|
Level uint8 `json:"level" gorm:"column:level;default:1"`
|
|
|
|
|
Tags string `json:"tags,omitempty" gorm:"column:tags;size:50"`
|
|
|
|
|
TagsList []string `gorm:"-" json:"tags_list,omitempty"`
|
|
|
|
|
TagsHighlight []string `gorm:"-" json:"tags_highlight,omitempty"`
|
2024-10-17 19:48:43 +08:00
|
|
|
|
|
|
|
|
|
// TAG Avatar 最好是压缩后的备份图像
|
2024-10-23 01:33:34 +08:00
|
|
|
|
Avatar string `gorm:"type:varchar(50)" json:"avatar,omitempty"` // 缩略图 url,为 Go 获取 Photo 之后压缩处理后的图像,单独存储。
|
|
|
|
|
AvatarHeight uint16 `json:"avatar_height,omitempty"` // 为了方便前端在加载图像前的骨架图 & 瀑布流展示。
|
|
|
|
|
AvatarWidth uint16 `json:"avatar_width,omitempty"`
|
|
|
|
|
Photos string `gorm:"type:varchar(100)" json:"photos,omitempty"` // 图片数组
|
2024-11-13 19:43:26 +08:00
|
|
|
|
PhotosList []string `gorm:"-" json:"photos_list,omitempty"` // TIP GORM 忽略
|
2024-10-17 19:48:43 +08:00
|
|
|
|
// POI
|
|
|
|
|
Latitude float64 `json:"latitude,omitempty"` // POI 位置相关
|
|
|
|
|
Longitude float64 `json:"longitude,omitempty"`
|
|
|
|
|
// TODO Comment Num 然后去统计?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *Encounter) TableName() string {
|
|
|
|
|
return "encounters"
|
2024-10-14 19:27:46 +08:00
|
|
|
|
}
|
2024-10-18 10:04:01 +08:00
|
|
|
|
|
2024-11-12 15:53:47 +08:00
|
|
|
|
/**
|
|
|
|
|
* @description:
|
|
|
|
|
* @param {*gin.Context} c
|
|
|
|
|
* @return {*} 返回创建的绑定对象,之后 model_es 的利用。
|
|
|
|
|
*/
|
|
|
|
|
func (e *Encounter) InsertDate(c *gin.Context) (tmp Encounter, ok bool) {
|
2024-10-18 10:04:01 +08:00
|
|
|
|
if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
|
|
|
|
|
if res := e.Create(&tmp); res.Error == nil {
|
2024-11-12 15:53:47 +08:00
|
|
|
|
return tmp, true
|
2024-10-18 10:04:01 +08:00
|
|
|
|
} else {
|
|
|
|
|
variable.ZapLog.Error("Encounter 数据新增出错", zap.Error(res.Error))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
variable.ZapLog.Error("Encounter 数据绑定出错", zap.Error(err))
|
|
|
|
|
}
|
2024-11-12 15:53:47 +08:00
|
|
|
|
return tmp, false
|
2024-10-18 10:04:01 +08:00
|
|
|
|
}
|
2024-10-20 21:01:12 +08:00
|
|
|
|
|
2024-11-02 11:06:27 +08:00
|
|
|
|
func formatEncounterList(rows *gorm.DB) (temp []EncounterList, err error) {
|
2024-10-21 01:24:01 +08:00
|
|
|
|
// 获取底层的 sql.Rows 对象
|
|
|
|
|
sqlRows, err := rows.Rows()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println("获取 sql.Rows 失败:", err)
|
2024-11-02 11:06:27 +08:00
|
|
|
|
return nil, err
|
2024-10-21 01:24:01 +08:00
|
|
|
|
}
|
|
|
|
|
defer sqlRows.Close()
|
|
|
|
|
|
|
|
|
|
for sqlRows.Next() {
|
|
|
|
|
var item EncounterList
|
|
|
|
|
var ueLikeInt int
|
|
|
|
|
dest := []interface{}{
|
|
|
|
|
&item.Id, &item.UserId, &item.Title, &item.Avatar, &item.AvatarHeight, &item.AvatarWidth, &item.UpdatedAt, &item.UserName, &item.UserAvatar, &ueLikeInt,
|
|
|
|
|
}
|
|
|
|
|
if err := sqlRows.Scan(dest...); err != nil {
|
|
|
|
|
log.Println("扫描失败:", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2024-11-02 12:32:33 +08:00
|
|
|
|
// STAGE: Set link Status
|
2024-10-21 01:24:01 +08:00
|
|
|
|
item.Like = ueLikeInt == 1
|
2024-11-02 12:32:33 +08:00
|
|
|
|
// STAGE: Check Url exist
|
|
|
|
|
if item.Avatar == "" {
|
|
|
|
|
if animal_id, ok := CreateEncounterAnimalLinkFactory("").ShowByEncounterIdFirst(int64(item.Id)); ok {
|
|
|
|
|
if animal := CreateAnimalFactory("").ShowByID(animal_id); animal != nil {
|
|
|
|
|
item.Avatar = animal.Avatar
|
|
|
|
|
item.AvatarHeight = int(animal.AvatarHeight)
|
|
|
|
|
item.AvatarWidth = int(animal.AvatarWidth)
|
|
|
|
|
item.UseAnimalAvatar = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// append
|
2024-10-21 01:24:01 +08:00
|
|
|
|
temp = append(temp, item)
|
|
|
|
|
}
|
2024-10-20 21:01:12 +08:00
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-10-21 16:16:03 +08:00
|
|
|
|
|
2024-11-02 11:06:27 +08:00
|
|
|
|
func (e *Encounter) Show(num, skip, user_id int, animals_id []int) (temp []EncounterList) {
|
2024-11-07 21:28:41 +08:00
|
|
|
|
// STAGE - 1:build SQL
|
2024-11-02 11:06:27 +08:00
|
|
|
|
var sqlBuilder strings.Builder
|
|
|
|
|
|
|
|
|
|
// 构建基础查询
|
|
|
|
|
sqlBuilder.WriteString(`
|
2024-11-02 14:49:03 +08:00
|
|
|
|
SELECT e.id, e.user_id, title, avatar, avatar_height, avatar_width, e.updated_at, user_name, user_avatar,
|
|
|
|
|
EXISTS (
|
|
|
|
|
SELECT 1
|
|
|
|
|
FROM encounter_likes l
|
|
|
|
|
WHERE l.user_id = ? AND l.encounter_id = e.id AND l.is_del = 0
|
|
|
|
|
) AS ue_like
|
|
|
|
|
FROM encounters e
|
|
|
|
|
JOIN tb_users u ON e.user_id = u.id`)
|
2024-11-02 11:06:27 +08:00
|
|
|
|
|
|
|
|
|
// 动态插入 animals_id 条件
|
|
|
|
|
if len(animals_id) > 0 {
|
2024-11-02 14:49:03 +08:00
|
|
|
|
sqlBuilder.WriteString(`
|
|
|
|
|
JOIN encounter_animal_links eal ON e.id = eal.encounter_id
|
|
|
|
|
WHERE eal.animal_id IN (?)`)
|
2024-11-02 11:06:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加排序和分页
|
|
|
|
|
sqlBuilder.WriteString(`
|
2024-11-07 21:28:41 +08:00
|
|
|
|
ORDER BY e.updated_at DESC
|
|
|
|
|
LIMIT ? OFFSET ?
|
2024-11-02 11:06:27 +08:00
|
|
|
|
`)
|
|
|
|
|
|
|
|
|
|
sql := sqlBuilder.String() // 获取到 SQL;
|
|
|
|
|
|
|
|
|
|
// STAGE - 2: Exe SQL
|
|
|
|
|
var rows *gorm.DB
|
2024-11-02 14:49:03 +08:00
|
|
|
|
if len(animals_id) > 0 {
|
|
|
|
|
rows = e.Raw(sql, user_id, animals_id, num, skip)
|
|
|
|
|
} else {
|
|
|
|
|
rows = e.Raw(sql, user_id, num, skip)
|
|
|
|
|
}
|
|
|
|
|
if rows.Error != nil {
|
2024-11-02 11:06:27 +08:00
|
|
|
|
log.Println("查询失败:", rows.Error)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var err error
|
|
|
|
|
if temp, err = formatEncounterList(rows); err != nil {
|
|
|
|
|
log.Println("格式化数据失败:", err)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-21 16:16:03 +08:00
|
|
|
|
func (e *Encounter) ShowByID(id int64) (temp *Encounter, err error) {
|
|
|
|
|
// 1. search encounter
|
|
|
|
|
if err = e.Where("id = ?", id).First(&temp).Error; err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
// // 2. search user data
|
|
|
|
|
// user := UsersModel{BaseModel: BaseModel{Id: encounter.UsersModelId}}
|
|
|
|
|
// if err := user.Select("user_name", "user_avatar").First(&user).Error; err != nil {
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // 3. search animals data
|
|
|
|
|
// animals_id := query_handler.StringToint64Array(encounter.AnimalsId)
|
|
|
|
|
// var animals []Animal
|
|
|
|
|
// if err := e.Model(&animals).Select("id", "avatar", "name").Where("id in (?)", animals_id).Find(&animals).Error; err != nil {
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // TODO 4. 然后整合
|
|
|
|
|
// return
|
|
|
|
|
}
|
2024-11-07 21:28:41 +08:00
|
|
|
|
|
2024-11-12 16:39:06 +08:00
|
|
|
|
func (e *Encounter) ShowByIDs(ids []int64, attrs ...string) (temp []Encounter) {
|
|
|
|
|
db := e.DB.Table(e.TableName())
|
|
|
|
|
|
|
|
|
|
if len(attrs) > 0 {
|
|
|
|
|
db = db.Select(attrs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := db.Where("id in (?)", ids).Find(&temp).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
variable.ZapLog.Error("Encounter ShowByIDs Error", zap.Error(err))
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-08 16:57:47 +08:00
|
|
|
|
/**
|
|
|
|
|
* @description: 过去 1 个月,发送过路遇表的 ids,同时去重。
|
|
|
|
|
* @param {*} user_id
|
|
|
|
|
* @param {int} num
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
2024-11-07 21:28:41 +08:00
|
|
|
|
func (e *Encounter) EncounteredCats(user_id, num int) ([]int64, error) {
|
|
|
|
|
sql := `SELECT eal.animal_id
|
|
|
|
|
FROM encounter_animal_links eal
|
|
|
|
|
JOIN encounters e
|
|
|
|
|
ON e.id = eal.encounter_id AND e.user_id = ?
|
2024-11-08 16:57:47 +08:00
|
|
|
|
WHERE e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
|
2024-11-07 21:28:41 +08:00
|
|
|
|
ORDER BY e.updated_at DESC
|
|
|
|
|
LIMIT ?`
|
|
|
|
|
|
|
|
|
|
rows, err := e.Raw(sql, user_id, num).Rows()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println("查询失败:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
|
|
// Scan 同时去重。
|
|
|
|
|
var temp []int64
|
|
|
|
|
seen := make(map[int64]bool)
|
|
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var animal_id int64
|
|
|
|
|
if err := rows.Scan(&animal_id); err != nil {
|
|
|
|
|
log.Println("扫描失败:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if !seen[animal_id] {
|
|
|
|
|
seen[animal_id] = true
|
|
|
|
|
temp = append(temp, animal_id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
log.Println("遍历失败:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return temp, nil
|
|
|
|
|
}
|