i18n翻译
This commit is contained in:
@@ -30,7 +30,6 @@ func NewThirdPartyDataSync() *ThirdPartyDataSync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncHeroData 同步英雄数据
|
|
||||||
func (t *ThirdPartyDataSync) SyncHeroData(ctx context.Context) error {
|
func (t *ThirdPartyDataSync) SyncHeroData(ctx context.Context) error {
|
||||||
g.Log().Info(ctx, "开始同步英雄数据...")
|
g.Log().Info(ctx, "开始同步英雄数据...")
|
||||||
|
|
||||||
@@ -130,7 +129,6 @@ func (t *ThirdPartyDataSync) fetchArtifactDataFromAPI(ctx context.Context) (stri
|
|||||||
return string(content), nil
|
return string(content), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processAndSaveHeroData 处理并保存英雄数据
|
|
||||||
func (t *ThirdPartyDataSync) processAndSaveHeroData(ctx context.Context, data []byte) error {
|
func (t *ThirdPartyDataSync) processAndSaveHeroData(ctx context.Context, data []byte) error {
|
||||||
// 使用 gjson 解析
|
// 使用 gjson 解析
|
||||||
j := gjson.New(data)
|
j := gjson.New(data)
|
||||||
@@ -147,13 +145,82 @@ func (t *ThirdPartyDataSync) processAndSaveHeroData(ctx context.Context, data []
|
|||||||
|
|
||||||
g.Log().Info(ctx, "解析到", len(heroes), "个英雄数据")
|
g.Log().Info(ctx, "解析到", len(heroes), "个英雄数据")
|
||||||
|
|
||||||
|
// 一次性查出所有数据库英雄,构建map
|
||||||
|
var dbHeroes []*entity.EpicHeroInfo
|
||||||
|
err := dao.EpicHeroInfo.Ctx(ctx).Scan(&dbHeroes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("查询数据库英雄失败: %v", err)
|
||||||
|
}
|
||||||
|
heroMap := make(map[string]*entity.EpicHeroInfo, len(dbHeroes))
|
||||||
|
for _, h := range dbHeroes {
|
||||||
|
heroMap[h.HeroCode] = h
|
||||||
|
}
|
||||||
|
|
||||||
// 遍历 map,设置 Name 字段,并保存
|
// 遍历 map,设置 Name 字段,并保存
|
||||||
for name, hero := range heroes {
|
for name, hero := range heroes {
|
||||||
hero.Name = name // 将 map 的 key 作为 Name 字段
|
hero.Name = name // 将 map 的 key 作为 Name 字段
|
||||||
if err := t.saveHeroData(ctx, hero); err != nil {
|
dbHero, exists := heroMap[hero.Code]
|
||||||
g.Log().Error(ctx, "保存英雄数据失败:", err)
|
if exists && dbHero.RawJson != "" {
|
||||||
|
// 已有且rawJson有值,跳过
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if exists && dbHero.RawJson == "" {
|
||||||
|
// 只更新 rawJson 字段
|
||||||
|
rawJsonBytes, err := json.Marshal(hero)
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(ctx, "序列化英雄数据失败:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rawJson := string(rawJsonBytes)
|
||||||
|
_, err = dao.EpicHeroInfo.Ctx(ctx).
|
||||||
|
Where(dao.EpicHeroInfo.Columns().HeroCode, hero.Code).
|
||||||
|
Data(g.Map{
|
||||||
|
dao.EpicHeroInfo.Columns().RawJson: rawJson,
|
||||||
|
dao.EpicHeroInfo.Columns().UpdateTime: gtime.Now(),
|
||||||
|
}).
|
||||||
|
Update()
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(ctx, "更新英雄rawJson失败:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.Log().Debug(ctx, "更新英雄rawJson:", hero.Code)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 新增逻辑保持原样
|
||||||
|
status60 := hero.CalculatedStatus.Lv60SixStarFullyAwakened
|
||||||
|
status60json, _ := gjson.EncodeString(status60)
|
||||||
|
heroJson, _ := gjson.EncodeString(hero)
|
||||||
|
zhHeroName := i18n.GetZh(ctx, hero.Name)
|
||||||
|
//zhRole := i18n.GetZh(ctx, hero.Role)
|
||||||
|
//zhAttribute := i18n.GetZh(ctx, hero.Attribute)
|
||||||
|
fmt.Println(hero.Assets.Image)
|
||||||
|
|
||||||
|
newHero := &entity.EpicHeroInfo{
|
||||||
|
Id: 0,
|
||||||
|
HeroName: zhHeroName,
|
||||||
|
HeroCode: hero.Code,
|
||||||
|
HeroAttrLv60: status60json,
|
||||||
|
Creator: "",
|
||||||
|
CreateTime: gtime.Now(),
|
||||||
|
Updater: "",
|
||||||
|
UpdateTime: gtime.Now(),
|
||||||
|
Deleted: false,
|
||||||
|
//NickName: "",
|
||||||
|
Rarity: strconv.Itoa(hero.Rarity),
|
||||||
|
Role: hero.Role,
|
||||||
|
//Zodiac: "",
|
||||||
|
HeadImgUrl: "",
|
||||||
|
Attribute: hero.Attribute,
|
||||||
|
Remark: "",
|
||||||
|
RawJson: heroJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = dao.EpicHeroInfo.Ctx(ctx).Data(newHero).Insert()
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(ctx, "插入新英雄失败:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.Log().Debug(ctx, "插入新英雄:", hero.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -210,8 +277,7 @@ func (t *ThirdPartyDataSync) saveHeroData(ctx context.Context, hero *dto.ThirdPa
|
|||||||
_, err = dao.EpicHeroInfo.Ctx(ctx).
|
_, err = dao.EpicHeroInfo.Ctx(ctx).
|
||||||
Where(dao.EpicHeroInfo.Columns().HeroCode, hero.Code).
|
Where(dao.EpicHeroInfo.Columns().HeroCode, hero.Code).
|
||||||
Data(g.Map{
|
Data(g.Map{
|
||||||
dao.EpicHeroInfo.Columns().RawJson: rawJson,
|
dao.EpicHeroInfo.Columns().RawJson: rawJson,
|
||||||
// 可选:更新时间
|
|
||||||
dao.EpicHeroInfo.Columns().UpdateTime: gtime.Now(),
|
dao.EpicHeroInfo.Columns().UpdateTime: gtime.Now(),
|
||||||
}).
|
}).
|
||||||
Update()
|
Update()
|
||||||
@@ -222,13 +288,13 @@ func (t *ThirdPartyDataSync) saveHeroData(ctx context.Context, hero *dto.ThirdPa
|
|||||||
}
|
}
|
||||||
// 已有 rawJson,不做处理
|
// 已有 rawJson,不做处理
|
||||||
} else {
|
} else {
|
||||||
status60 := hero.CalculatedStatus["Lv60SixStarFullyAwakened"]
|
status60 := hero.CalculatedStatus.Lv60SixStarFullyAwakened
|
||||||
status60json, _ := gjson.EncodeString(status60)
|
status60json, _ := gjson.EncodeString(status60)
|
||||||
heroJson, _ := gjson.EncodeString(hero)
|
heroJson, _ := gjson.EncodeString(hero)
|
||||||
// 使用i18n服务转换字段
|
// 使用i18n服务转换字段
|
||||||
zhHeroName := i18n.GetZh(ctx, hero.Name)
|
zhHeroName := i18n.GetZh(ctx, hero.Name)
|
||||||
zhRole := i18n.GetZh(ctx, hero.Role)
|
//zhRole := i18n.GetZh(ctx, hero.Role)
|
||||||
zhAttribute := i18n.GetZh(ctx, hero.Attribute)
|
//zhAttribute := i18n.GetZh(ctx, hero.Attribute)
|
||||||
|
|
||||||
newHero := &entity.EpicHeroInfo{
|
newHero := &entity.EpicHeroInfo{
|
||||||
Id: 0,
|
Id: 0,
|
||||||
@@ -236,18 +302,18 @@ func (t *ThirdPartyDataSync) saveHeroData(ctx context.Context, hero *dto.ThirdPa
|
|||||||
HeroCode: hero.Code,
|
HeroCode: hero.Code,
|
||||||
HeroAttrLv60: status60json,
|
HeroAttrLv60: status60json,
|
||||||
Creator: "",
|
Creator: "",
|
||||||
CreateTime: nil,
|
CreateTime: gtime.Now(),
|
||||||
Updater: "",
|
Updater: "",
|
||||||
UpdateTime: nil,
|
UpdateTime: gtime.Now(),
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
NickName: "",
|
//NickName: nil,
|
||||||
Rarity: strconv.Itoa(hero.Rarity),
|
Rarity: strconv.Itoa(hero.Rarity),
|
||||||
Role: zhRole,
|
Role: hero.Role,
|
||||||
Zodiac: "",
|
Zodiac: "",
|
||||||
HeadImgUrl: "",
|
HeadImgUrl: "",
|
||||||
Attribute: zhAttribute,
|
Attribute: hero.Attribute,
|
||||||
Remark: "",
|
Remark: "",
|
||||||
RawJson: heroJson,
|
RawJson: heroJson,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没查到,插入新记录,字段按 DO 结构体补全
|
// 没查到,插入新记录,字段按 DO 结构体补全
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package cron
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"epic/internal/logic/i18n"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gctx"
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
@@ -21,35 +23,6 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockSync struct {
|
|
||||||
fetchHeroDataErr error
|
|
||||||
fetchArtifactDataErr error
|
|
||||||
processHeroDataErr error
|
|
||||||
processArtifactErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSync) fetchHeroDataFromAPI(ctx context.Context) ([]byte, error) {
|
|
||||||
if m.fetchHeroDataErr != nil {
|
|
||||||
return nil, m.fetchHeroDataErr
|
|
||||||
}
|
|
||||||
return []byte(`[{"code":"hero1"},{"code":"hero2"}]`), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSync) fetchArtifactDataFromAPI(ctx context.Context) ([]byte, error) {
|
|
||||||
if m.fetchArtifactDataErr != nil {
|
|
||||||
return nil, m.fetchArtifactDataErr
|
|
||||||
}
|
|
||||||
return []byte(`[{"code":"artifact1"}]`), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSync) processAndSaveHeroData(ctx context.Context, data []byte) error {
|
|
||||||
return m.processHeroDataErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSync) processAndSaveArtifactData(ctx context.Context, data []byte) error {
|
|
||||||
return m.processArtifactErr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试同步英雄数据
|
* 测试同步英雄数据
|
||||||
*/
|
*/
|
||||||
@@ -62,81 +35,9 @@ func TestSyncHeroData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/**
|
||||||
//func TestSyncHeroData_FetchError(t *testing.T) {
|
* 测试同步神器数据
|
||||||
// sync := &ThirdPartyDataSync{}
|
*/
|
||||||
// sync.fetchHeroDataFromAPI = (&mockSync{fetchHeroDataErr: errors.New("fetch error")}).fetchHeroDataFromAPI
|
|
||||||
// sync.processAndSaveHeroData = (&mockSync{}).processAndSaveHeroData
|
|
||||||
//
|
|
||||||
// err := sync.SyncHeroData(context.Background())
|
|
||||||
// if err == nil || err.Error() != "fetch error" {
|
|
||||||
// t.Errorf("expected fetch error, got: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func TestSyncHeroData_ProcessError(t *testing.T) {
|
|
||||||
// sync := &ThirdPartyDataSync{}
|
|
||||||
// sync.fetchHeroDataFromAPI = (&mockSync{}).fetchHeroDataFromAPI
|
|
||||||
// sync.processAndSaveHeroData = (&mockSync{processHeroDataErr: errors.New("process error")}).processAndSaveHeroData
|
|
||||||
//
|
|
||||||
// err := sync.SyncHeroData(context.Background())
|
|
||||||
// if err == nil || err.Error() != "process error" {
|
|
||||||
// t.Errorf("expected process error, got: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func TestSyncArtifactData_Success(t *testing.T) {
|
|
||||||
// sync := &ThirdPartyDataSync{}
|
|
||||||
// sync.fetchArtifactDataFromAPI = (&mockSync{}).fetchArtifactDataFromAPI
|
|
||||||
// sync.processAndSaveArtifactData = (&mockSync{}).processAndSaveArtifactData
|
|
||||||
//
|
|
||||||
// err := sync.SyncArtifactData(context.Background())
|
|
||||||
// if err != nil {
|
|
||||||
// t.Errorf("expected success, got error: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func TestSyncArtifactData_FetchError(t *testing.T) {
|
|
||||||
|
|
||||||
// sync := &ThirdPartyDataSync{}
|
|
||||||
// sync.fetchArtifactDataFromAPI = (&mockSync{fetchArtifactDataErr: errors.New("fetch error")}).fetchArtifactDataFromAPI
|
|
||||||
// sync.processAndSaveArtifactData = (&mockSync{}).processAndSaveArtifactData
|
|
||||||
//
|
|
||||||
// err := sync.SyncArtifactData(context.Background())
|
|
||||||
// if err == nil || err.Error() != "fetch error" {
|
|
||||||
// t.Errorf("expected fetch error, got: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func TestSyncArtifactData_ProcessError(t *testing.T) {
|
|
||||||
// sync := &ThirdPartyDataSync{}
|
|
||||||
// sync.fetchArtifactDataFromAPI = (&mockSync{}).fetchArtifactDataFromAPI
|
|
||||||
// sync.processAndSaveArtifactData = (&mockSync{processArtifactErr: errors.New("process error")}).processAndSaveArtifactData
|
|
||||||
//
|
|
||||||
// err := sync.SyncArtifactData(context.Background())
|
|
||||||
// if err == nil || err.Error() != "process error" {
|
|
||||||
// t.Errorf("expected process error, got: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
func TestProcessAndSaveArtifactData(t *testing.T) {
|
|
||||||
sync := &ThirdPartyDataSync{}
|
|
||||||
// 构造一个合法的 JSON 数据
|
|
||||||
data := "[{\"code\":\"artifact1\"},{\"code\":\"artifact2\"}]"
|
|
||||||
if err := sync.processAndSaveArtifactData(context.Background(), data); err != nil {
|
|
||||||
t.Errorf("expected no error, got: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProcessAndSaveHeroData(t *testing.T) {
|
|
||||||
sync := &ThirdPartyDataSync{}
|
|
||||||
// 构造一个合法的 JSON 数据
|
|
||||||
data := []byte(`[{"code":"hero1"},{"code":"hero2"}]`)
|
|
||||||
if err := sync.processAndSaveHeroData(context.Background(), data); err != nil {
|
|
||||||
t.Errorf("expected no error, got: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncArtifactData_Success(t *testing.T) {
|
func TestSyncArtifactData_Success(t *testing.T) {
|
||||||
sync := NewThirdPartyDataSync()
|
sync := NewThirdPartyDataSync()
|
||||||
|
|
||||||
@@ -145,3 +46,14 @@ func TestSyncArtifactData_Success(t *testing.T) {
|
|||||||
t.Errorf("expected success, but got error: %v", err)
|
t.Errorf("expected success, but got error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInitI18nStaticToDB(t *testing.T) {
|
||||||
|
//t.Skip("仅初始化时手动执行一次,谨慎运行!")
|
||||||
|
ctx := context.Background()
|
||||||
|
// 直接批量导入,不做重复检查
|
||||||
|
err := i18n.ImportI18nFromMap(ctx, "zh", i18n.I18nEnToZh, "init")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("导入静态i18n数据失败: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("静态i18n数据导入成功,共%d条", len(i18n.I18nEnToZh))
|
||||||
|
}
|
||||||
|
|||||||
@@ -709,7 +709,7 @@ func (l *Logic) Add(ctx context.Context, key, lang, value, category string) erro
|
|||||||
dao.EpicI18NMappings.Columns().Status: 1,
|
dao.EpicI18NMappings.Columns().Status: 1,
|
||||||
dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(),
|
dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(),
|
||||||
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
|
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
|
||||||
}).OnDuplicate("value", value).Insert()
|
}).Insert()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("添加翻译失败: %v", err)
|
return fmt.Errorf("添加翻译失败: %v", err)
|
||||||
@@ -826,11 +826,7 @@ func (l *Logic) ImportFromMap(ctx context.Context, lang string, mappings map[str
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := dao.EpicI18NMappings.Ctx(ctx).Data(data).OnDuplicate("value", g.Map{
|
_, err := dao.EpicI18NMappings.Ctx(ctx).Data(data).Insert()
|
||||||
dao.EpicI18NMappings.Columns().Value: g.Map{"value": "VALUES(value)"},
|
|
||||||
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
|
|
||||||
}).Insert()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("批量导入翻译失败: %v", err)
|
return fmt.Errorf("批量导入翻译失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,19 +19,38 @@ type ThirdPartyArtifactDTO struct {
|
|||||||
// Note: This is a placeholder structure. Adjust it according to the actual API response.
|
// Note: This is a placeholder structure. Adjust it according to the actual API response.
|
||||||
// ThirdPartyHeroDTO 第三方英雄数据传输对象
|
// ThirdPartyHeroDTO 第三方英雄数据传输对象
|
||||||
type ThirdPartyHeroDTO struct {
|
type ThirdPartyHeroDTO struct {
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
ID string `json:"_id"`
|
ID string `json:"_id"`
|
||||||
Name string `json:"-"`
|
Name string `json:"-"`
|
||||||
Rarity int `json:"rarity"`
|
Rarity int `json:"rarity"`
|
||||||
Attribute string `json:"attribute"`
|
Attribute string `json:"attribute"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
Zodiac string `json:"zodiac"`
|
Zodiac string `json:"zodiac"`
|
||||||
SelfDevotion SelfDevotion `json:"self_devotion"`
|
SelfDevotion SelfDevotion `json:"self_devotion"`
|
||||||
Assets Assets `json:"assets"`
|
Assets Assets `json:"assets"`
|
||||||
ExEquip []ExEquip `json:"ex_equip"`
|
ExEquip []ExEquip `json:"ex_equip"`
|
||||||
Skills map[string]Skill `json:"skills"`
|
Skills Skills `json:"skills"`
|
||||||
CalculatedStatus map[string]Status `json:"calculatedStatus"`
|
CalculatedStatus CalculatedStatus `json:"calculatedStatus"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skills结构体,支持点语法访问S1、S2、S3
|
||||||
|
type Skills struct {
|
||||||
|
S1 Skill `json:"S1"`
|
||||||
|
S2 Skill `json:"S2"`
|
||||||
|
S3 Skill `json:"S3"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增结构体,支持点语法访问
|
||||||
|
// CalculatedStatus 兼容第三方API的calculatedStatus字段
|
||||||
|
// 只声明常用的两个等级
|
||||||
|
// 其他等级如有需要可自行添加
|
||||||
|
// 字段名需与json tag严格对应
|
||||||
|
|
||||||
|
type CalculatedStatus struct {
|
||||||
|
Lv50FiveStarFullyAwakened Stats `json:"lv50FiveStarFullyAwakened"`
|
||||||
|
Lv60SixStarFullyAwakened Stats `json:"lv60SixStarFullyAwakened"`
|
||||||
|
}
|
||||||
|
|
||||||
type SelfDevotion struct {
|
type SelfDevotion struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Grades map[string]float64 `json:"grades"`
|
Grades map[string]float64 `json:"grades"`
|
||||||
@@ -60,11 +79,6 @@ type Skill struct {
|
|||||||
Options []any `json:"options"`
|
Options []any `json:"options"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Status struct {
|
|
||||||
Lv50FiveStarFullyAwakened Stats `json:"lv50FiveStarFullyAwakened"`
|
|
||||||
Lv60SixStarFullyAwakened Stats `json:"lv60SixStarFullyAwakened"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
CP int `json:"cp"`
|
CP int `json:"cp"`
|
||||||
ATK int `json:"atk"`
|
ATK int `json:"atk"`
|
||||||
|
|||||||
17
internal/util/oss.go
Normal file
17
internal/util/oss.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DownloadAndUploadToOSS 下载网络图片并上传到OSS,返回OSS路径
|
||||||
|
// imageUrl: 网络图片完整URL
|
||||||
|
// 返回: OSS上的图片URL,或错误
|
||||||
|
func DownloadAndUploadToOSS(ctx context.Context, imageUrl string) (string, error) {
|
||||||
|
// 1. 下载 imageUrl 到本地临时文件
|
||||||
|
// 2. 上传临时文件到OSS,获取OSS路径
|
||||||
|
// 3. 删除临时文件
|
||||||
|
// 4. 返回OSS路径
|
||||||
|
// TODO: 实现具体逻辑
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user