mirror of
https://github.com/wgh136/nysoure.git
synced 2025-12-16 07:51:14 +00:00
696 lines
17 KiB
Go
696 lines
17 KiB
Go
package dao
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"nysoure/server/model"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3/log"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func CreateResource(r model.Resource) (model.Resource, error) {
|
|
err := db.Transaction(func(tx *gorm.DB) error {
|
|
r.ModifiedTime = time.Now()
|
|
characters := r.Characters
|
|
r.Characters = nil
|
|
err := tx.Create(&r).Error
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, c := range characters {
|
|
c.ResourceID = r.ID
|
|
// If ImageID is 0, set it to nil to avoid foreign key constraint error
|
|
if c.ImageID != nil && *c.ImageID == 0 {
|
|
c.ImageID = nil
|
|
}
|
|
if err := tx.Create(&c).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := tx.Model(&model.User{}).Where("id = ?", r.UserID).Update("resources_count", gorm.Expr("resources_count + ?", 1)).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return model.Resource{}, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func GetResourceByID(id uint) (model.Resource, error) {
|
|
// Retrieve a resource by its ID from the database
|
|
var r model.Resource
|
|
if err := db.Preload("User").
|
|
Preload("Images").
|
|
Preload("Tags", func(db *gorm.DB) *gorm.DB {
|
|
return db.Select("id", "name", "type", "alias_of")
|
|
}).
|
|
Preload("Files").
|
|
Preload("Files.User").
|
|
Preload("Files.Storage").
|
|
Preload("Characters").
|
|
First(&r, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return model.Resource{}, model.NewNotFoundError("Resource not found")
|
|
}
|
|
return model.Resource{}, err
|
|
}
|
|
for i, tag := range r.Tags {
|
|
if tag.AliasOf != nil {
|
|
t, err := GetTagByID(*tag.AliasOf)
|
|
if err != nil {
|
|
return model.Resource{}, err
|
|
} else {
|
|
r.Tags[i].Type = t.Type
|
|
}
|
|
}
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func GetResourceList(page, pageSize int, sort model.RSort) ([]model.Resource, int, error) {
|
|
// Retrieve a list of resources with pagination
|
|
var resources []model.Resource
|
|
var total int64
|
|
|
|
if err := db.Model(&model.Resource{}).Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
order := ""
|
|
switch sort {
|
|
case model.RSortTimeAsc:
|
|
order = "modified_time ASC"
|
|
case model.RSortTimeDesc:
|
|
order = "modified_time DESC"
|
|
case model.RSortViewsAsc:
|
|
order = "views ASC"
|
|
case model.RSortViewsDesc:
|
|
order = "views DESC"
|
|
case model.RSortDownloadsAsc:
|
|
order = "downloads ASC"
|
|
case model.RSortDownloadsDesc:
|
|
order = "downloads DESC"
|
|
default:
|
|
order = "modified_time DESC" // Default sort order
|
|
}
|
|
|
|
if err := db.Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Images").Preload("Tags").Order(order).Find(&resources).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
|
|
|
|
return resources, int(totalPages), nil
|
|
}
|
|
|
|
func UpdateResource(r model.Resource) error {
|
|
// Update a resource in the database
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
images := r.Images
|
|
tags := r.Tags
|
|
characters := r.Characters
|
|
r.Characters = nil
|
|
r.Images = nil
|
|
r.Tags = nil
|
|
r.Files = nil
|
|
r.ModifiedTime = time.Now()
|
|
oldCharacters := []model.Character{}
|
|
if err := db.Model(&model.Character{}).Where("resource_id = ?", r.ID).Find(&oldCharacters).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := db.Save(&r).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := db.Model(&r).Association("Images").Replace(images); err != nil {
|
|
return err
|
|
}
|
|
if err := db.Model(&r).Association("Tags").Replace(tags); err != nil {
|
|
return err
|
|
}
|
|
for _, c := range oldCharacters {
|
|
shouldDelete := true
|
|
for _, nc := range characters {
|
|
if c.Equal(&nc) {
|
|
shouldDelete = false
|
|
break
|
|
}
|
|
}
|
|
if shouldDelete {
|
|
if err := tx.Delete(&c).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
for _, c := range characters {
|
|
shouldAdd := true
|
|
for _, oc := range oldCharacters {
|
|
if c.Equal(&oc) {
|
|
shouldAdd = false
|
|
break
|
|
}
|
|
}
|
|
if shouldAdd {
|
|
c.ID = 0
|
|
c.ResourceID = r.ID
|
|
// If ImageID is 0, set it to nil to avoid foreign key constraint error
|
|
if c.ImageID != nil && *c.ImageID == 0 {
|
|
c.ImageID = nil
|
|
}
|
|
if err := tx.Create(&c).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func DeleteResource(id uint) error {
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
var r model.Resource
|
|
if err := tx.Where("id = ?", id).First(&r).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return model.NewNotFoundError("Resource not found")
|
|
}
|
|
return err
|
|
}
|
|
if err := tx.Model(&model.File{}).Where("resource_id = ?", id).Delete(&model.File{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Model(&model.User{}).Where("id = ?", r.UserID).Update("resources_count", gorm.Expr("resources_count - ?", 1)).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Delete(&r).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Model(&model.Activity{}).Where("type = ? AND ref_id = ?", model.ActivityTypeNewResource, id).Delete(&model.Activity{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Model(&model.Activity{}).Where("type = ? AND ref_id = ?", model.ActivityTypeUpdateResource, id).Delete(&model.Activity{}).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func GetResourceByTag(tagID uint, page int, pageSize int) ([]model.Resource, int, error) {
|
|
tag, err := GetTagByID(tagID)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if tag.AliasOf != nil {
|
|
tag, err = GetTagByID(*tag.AliasOf)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
}
|
|
|
|
var tagIds []uint
|
|
tagIds = append(tagIds, tag.ID)
|
|
for _, alias := range tag.Aliases {
|
|
tagIds = append(tagIds, alias.ID)
|
|
}
|
|
|
|
var resources []model.Resource
|
|
var total int64
|
|
|
|
subQuery := db.Table("resource_tags").
|
|
Select("resource_id").
|
|
Where("tag_id IN ?", tagIds).
|
|
Group("resource_id")
|
|
|
|
if err := db.Model(&model.Resource{}).
|
|
Where("id IN (?)", subQuery).
|
|
Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if err := db.Where("id IN (?)", subQuery).
|
|
Offset((page - 1) * pageSize).
|
|
Limit(pageSize).
|
|
Preload("User").
|
|
Preload("Images").
|
|
Preload("Tags").
|
|
Preload("Files").
|
|
Order("created_at DESC").
|
|
Find(&resources).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
|
|
|
|
return resources, int(totalPages), nil
|
|
}
|
|
|
|
// CountResourcesByTag counts the number of resources associated with a specific tag.
|
|
func CountResourcesByTag(tagID uint) (int64, error) {
|
|
tag, err := GetTagByID(tagID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if tag.AliasOf != nil {
|
|
tag, err = GetTagByID(*tag.AliasOf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
var tagIds []uint
|
|
tagIds = append(tagIds, tag.ID)
|
|
for _, alias := range tag.Aliases {
|
|
tagIds = append(tagIds, alias.ID)
|
|
}
|
|
var count int64
|
|
subQuery := db.Table("resource_tags").
|
|
Select("resource_id").
|
|
Where("tag_id IN ?", tagIds).
|
|
Group("resource_id")
|
|
if err := db.Model(&model.Resource{}).
|
|
Where("id IN (?)", subQuery).
|
|
Count(&count).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func ExistsResource(id uint) (bool, error) {
|
|
var r model.Resource
|
|
if err := db.Model(&model.Resource{}).Where("id = ?", id).First(&r).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func GetResourcesByUsername(username string, page, pageSize int) ([]model.Resource, int, error) {
|
|
var user model.User
|
|
if err := db.Where("username = ?", username).First(&user).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, 0, model.NewNotFoundError("User not found")
|
|
}
|
|
return nil, 0, err
|
|
}
|
|
var resources []model.Resource
|
|
var total int64
|
|
|
|
if err := db.Model(&model.Resource{}).Where("user_id = ?", user.ID).Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if err := db.Model(&model.Resource{}).Where("user_id = ?", user.ID).Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Images").Preload("Tags").Order("created_at DESC").Find(&resources).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
|
|
|
|
return resources, int(totalPages), nil
|
|
}
|
|
|
|
// GetAllResources retrieves all resources from the database without all related data.
|
|
// It is used to generate a sitemap and rss feed.
|
|
func GetAllResources() ([]model.Resource, error) {
|
|
var resources []model.Resource
|
|
if err := db.Find(&resources).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return resources, nil
|
|
}
|
|
|
|
type CachedResourceStats struct {
|
|
id uint
|
|
views atomic.Int64
|
|
downloads atomic.Int64
|
|
}
|
|
|
|
var (
|
|
cachedResourcesStats = make(map[uint]*CachedResourceStats)
|
|
cacheMutex = sync.RWMutex{}
|
|
)
|
|
|
|
func init() {
|
|
go func() {
|
|
ticker := time.NewTicker(10 * time.Minute)
|
|
defer ticker.Stop()
|
|
|
|
for range ticker.C {
|
|
cacheMutex.Lock()
|
|
if len(cachedResourcesStats) == 0 {
|
|
cacheMutex.Unlock()
|
|
continue
|
|
}
|
|
|
|
err := db.Transaction(func(tx *gorm.DB) error {
|
|
for id, stats := range cachedResourcesStats {
|
|
var count int64
|
|
if err := tx.Model(&model.Resource{}).Where("id = ?", id).Count(&count).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
log.Warnf("Resource with ID %d not found, skipping stats update", id)
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
if count == 0 {
|
|
continue
|
|
}
|
|
|
|
if views := stats.views.Swap(0); views > 0 {
|
|
if err := tx.Model(&model.Resource{}).Where("id = ?", id).Update("views", gorm.Expr("views + ?", views)).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if downloads := stats.downloads.Swap(0); downloads > 0 {
|
|
if err := tx.Model(&model.Resource{}).Where("id = ?", id).Update("downloads", gorm.Expr("downloads + ?", downloads)).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
log.Error("Failed to update resource stats cache: ", err)
|
|
}
|
|
clear(cachedResourcesStats)
|
|
cacheMutex.Unlock()
|
|
}
|
|
}()
|
|
}
|
|
|
|
func AddResourceViewCount(id uint) error {
|
|
cacheMutex.RLock()
|
|
stats, exists := cachedResourcesStats[id]
|
|
cacheMutex.RUnlock()
|
|
|
|
if !exists {
|
|
cacheMutex.Lock()
|
|
stats, exists = cachedResourcesStats[id]
|
|
if !exists {
|
|
stats = &CachedResourceStats{id: id}
|
|
cachedResourcesStats[id] = stats
|
|
}
|
|
cacheMutex.Unlock()
|
|
}
|
|
|
|
stats.views.Add(1)
|
|
return nil
|
|
}
|
|
|
|
func AddResourceDownloadCount(id uint) error {
|
|
cacheMutex.RLock()
|
|
stats, exists := cachedResourcesStats[id]
|
|
cacheMutex.RUnlock()
|
|
|
|
if !exists {
|
|
cacheMutex.Lock()
|
|
stats, exists = cachedResourcesStats[id]
|
|
if !exists {
|
|
stats = &CachedResourceStats{id: id}
|
|
cachedResourcesStats[id] = stats
|
|
}
|
|
cacheMutex.Unlock()
|
|
}
|
|
|
|
stats.downloads.Add(1)
|
|
return nil
|
|
}
|
|
|
|
func RandomResource() (model.Resource, error) {
|
|
var maxID int64
|
|
if err := db.Model(&model.Resource{}).Select("MAX(id)").Scan(&maxID).Error; err != nil {
|
|
return model.Resource{}, err
|
|
}
|
|
for {
|
|
randomID := uint(1)
|
|
if maxID > 1 {
|
|
randomID = uint(1 + rand.Int63n(maxID-1))
|
|
}
|
|
var resource model.Resource
|
|
if err := db.
|
|
Preload("User").
|
|
Preload("Images").
|
|
Preload("Tags").
|
|
Preload("Files").
|
|
Where("id = ?", randomID).
|
|
First(&resource).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
continue // Try again if the resource does not exist
|
|
}
|
|
return model.Resource{}, err // Return error if any other issue occurs
|
|
}
|
|
return resource, nil // Return the found resource
|
|
}
|
|
}
|
|
|
|
func GetResourcesIdWithTag(tagID uint) ([]uint, error) {
|
|
tag, err := GetTagByID(tagID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if tag.AliasOf != nil {
|
|
tag, err = GetTagByID(*tag.AliasOf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
var tagIds []uint
|
|
tagIds = append(tagIds, tag.ID)
|
|
for _, alias := range tag.Aliases {
|
|
tagIds = append(tagIds, alias.ID)
|
|
}
|
|
var result []model.Resource
|
|
subQuery := db.Table("resource_tags").
|
|
Select("resource_id").
|
|
Where("tag_id IN ?", tagIds).
|
|
Group("resource_id")
|
|
if err := db.Model(&model.Resource{}).
|
|
Where("id IN (?)", subQuery).
|
|
Order("created_at DESC").
|
|
Limit(10000).
|
|
Select("id", "created_at").
|
|
Find(&result).
|
|
Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ids := make([]uint, len(result))
|
|
for i, r := range result {
|
|
ids[i] = r.ID
|
|
}
|
|
return ids, nil
|
|
}
|
|
|
|
func BatchGetResources(ids []uint) ([]model.Resource, error) {
|
|
var resources []model.Resource
|
|
|
|
for _, id := range ids {
|
|
var r model.Resource
|
|
if err := db.
|
|
Preload("User").
|
|
Preload("Images").
|
|
Preload("Tags").
|
|
First(&r, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
for i, tag := range r.Tags {
|
|
if tag.AliasOf != nil {
|
|
t, err := GetTagByID(*tag.AliasOf)
|
|
if err != nil {
|
|
return nil, err
|
|
} else {
|
|
r.Tags[i].Type = t.Type
|
|
}
|
|
}
|
|
}
|
|
resources = append(resources, r)
|
|
}
|
|
|
|
return resources, nil
|
|
}
|
|
|
|
func CountResources() (int64, error) {
|
|
var count int64
|
|
if err := db.Model(&model.Resource{}).Count(&count).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// UpdateCharacterImage 更新角色的图片ID
|
|
func UpdateCharacterImage(characterID, imageID uint) error {
|
|
var updateValue interface{}
|
|
if imageID == 0 {
|
|
updateValue = nil
|
|
} else {
|
|
updateValue = imageID
|
|
}
|
|
|
|
result := db.Model(&model.Character{}).Where("id = ?", characterID).Update("image_id", updateValue)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return model.NewNotFoundError("Character not found")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetLowResolutionCharacters 获取低清晰度的角色图片
|
|
// maxWidth和maxHeight定义了低清晰度的阈值
|
|
func GetLowResolutionCharacters(maxWidth, maxHeight int, limit int, offset int) ([]model.LowResCharacterView, error) {
|
|
var results []model.LowResCharacterView
|
|
|
|
query := `
|
|
SELECT
|
|
c.id as character_id,
|
|
c.resource_id as resource_id,
|
|
c.name as name,
|
|
i.id as image_id,
|
|
i.width as image_width,
|
|
i.height as image_height
|
|
FROM characters c
|
|
INNER JOIN images i ON c.image_id = i.id
|
|
WHERE (i.width <= ? OR i.height <= ?)
|
|
AND c.image_id IS NOT NULL
|
|
ORDER BY c.id
|
|
LIMIT ? OFFSET ?
|
|
`
|
|
|
|
err := db.Raw(query, maxWidth, maxHeight, limit, offset).Scan(&results).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// GetLowResolutionCharactersCount 获取低清晰度角色的总数
|
|
func GetLowResolutionCharactersCount(maxWidth, maxHeight int) (int64, error) {
|
|
var count int64
|
|
|
|
query := `
|
|
SELECT COUNT(*)
|
|
FROM characters c
|
|
INNER JOIN images i ON c.image_id = i.id
|
|
WHERE (i.width <= ? OR i.height <= ?)
|
|
AND c.image_id IS NOT NULL
|
|
`
|
|
|
|
err := db.Raw(query, maxWidth, maxHeight).Scan(&count).Error
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// GetLowResolutionResourceImages 获取低清晰度的资源图片
|
|
// maxWidth和maxHeight定义了低清晰度的阈值
|
|
func GetLowResolutionResourceImages(maxWidth, maxHeight int, limit int, offset int) ([]model.LowResResourceImageView, error) {
|
|
var results []model.LowResResourceImageView
|
|
|
|
query := `
|
|
SELECT DISTINCT
|
|
r.id as resource_id,
|
|
r.title as title,
|
|
i.id as image_id,
|
|
i.width as image_width,
|
|
i.height as image_height
|
|
FROM resources r
|
|
INNER JOIN resource_images ri ON r.id = ri.resource_id
|
|
INNER JOIN images i ON ri.image_id = i.id
|
|
WHERE (i.width <= ? OR i.height <= ?)
|
|
ORDER BY r.id, i.id
|
|
LIMIT ? OFFSET ?
|
|
`
|
|
|
|
err := db.Raw(query, maxWidth, maxHeight, limit, offset).Scan(&results).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// GetLowResolutionResourceImagesCount 获取低清晰度资源图片的总数
|
|
func GetLowResolutionResourceImagesCount(maxWidth, maxHeight int) (int64, error) {
|
|
var count int64
|
|
|
|
query := `
|
|
SELECT COUNT(DISTINCT ri.resource_id, ri.image_id)
|
|
FROM resources r
|
|
INNER JOIN resource_images ri ON r.id = ri.resource_id
|
|
INNER JOIN images i ON ri.image_id = i.id
|
|
WHERE (i.width <= ? OR i.height <= ?)
|
|
`
|
|
|
|
err := db.Raw(query, maxWidth, maxHeight).Scan(&count).Error
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// UpdateResourceImage 更新资源中特定的图片ID
|
|
func UpdateResourceImage(resourceID, oldImageID, newImageID uint) error {
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
// 首先检查关联是否存在
|
|
var exists bool
|
|
err := tx.Raw("SELECT EXISTS(SELECT 1 FROM resource_images WHERE resource_id = ? AND image_id = ?)",
|
|
resourceID, oldImageID).Scan(&exists).Error
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !exists {
|
|
return fmt.Errorf("resource %d does not have image %d", resourceID, oldImageID)
|
|
}
|
|
|
|
// 更新resource_images表中的image_id
|
|
result := tx.Exec("UPDATE resource_images SET image_id = ? WHERE resource_id = ? AND image_id = ?",
|
|
newImageID, resourceID, oldImageID)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return fmt.Errorf("no resource image association updated")
|
|
}
|
|
|
|
// 更新资源描述中的图片引用
|
|
var resource model.Resource
|
|
if err := tx.Select("article").Where("id = ?", resourceID).First(&resource).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// 替换描述中的图片引用
|
|
oldImageRef := fmt.Sprintf("/api/image/%d)", oldImageID)
|
|
newImageRef := fmt.Sprintf("/api/image/%d)", newImageID)
|
|
|
|
// 使用字符串替换更新文章内容
|
|
updatedArticle := strings.ReplaceAll(resource.Article, oldImageRef, newImageRef)
|
|
|
|
// 如果文章内容有变化,更新数据库
|
|
if updatedArticle != resource.Article {
|
|
if err := tx.Model(&model.Resource{}).Where("id = ?", resourceID).Update("article", updatedArticle).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|