feat: 优化编辑器 UI 和文件名显示,支持全屏编辑模式
This commit is contained in:
@@ -248,6 +248,7 @@ func (s *common) CompleteUpload(ctx context.Context, userID int64, form *common_
|
|||||||
ObjectKey: objectKey,
|
ObjectKey: objectKey,
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Meta: types.NewJSONType(fields.MediaAssetMeta{
|
Meta: types.NewJSONType(fields.MediaAssetMeta{
|
||||||
|
Filename: meta.Filename,
|
||||||
Size: totalSize,
|
Size: totalSize,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -384,6 +385,7 @@ func (s *common) Upload(
|
|||||||
ObjectKey: objectKey,
|
ObjectKey: objectKey,
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Meta: types.NewJSONType(fields.MediaAssetMeta{
|
Meta: types.NewJSONType(fields.MediaAssetMeta{
|
||||||
|
Filename: file.Filename,
|
||||||
Size: size,
|
Size: size,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -398,10 +400,14 @@ func (s *common) Upload(
|
|||||||
|
|
||||||
func (s *common) composeUploadResult(asset *models.MediaAsset) *common_dto.UploadResult {
|
func (s *common) composeUploadResult(asset *models.MediaAsset) *common_dto.UploadResult {
|
||||||
url := s.GetAssetURL(asset.ObjectKey)
|
url := s.GetAssetURL(asset.ObjectKey)
|
||||||
filename := filepath.Base(asset.ObjectKey)
|
filename := asset.Meta.Data().Filename
|
||||||
// Try to get original filename if stored? Currently objectKey has UUID prefix.
|
if filename == "" {
|
||||||
// We can store original filename in Meta if needed. For now, just return valid result.
|
filename = filepath.Base(asset.ObjectKey)
|
||||||
// Meta is JSONType wrapper.
|
// Try to strip UUID prefix (36 chars + 1 underscore = 37)
|
||||||
|
if len(filename) > 37 && filename[36] == '_' {
|
||||||
|
filename = filename[37:]
|
||||||
|
}
|
||||||
|
}
|
||||||
size := asset.Meta.Data().Size
|
size := asset.Meta.Data().Size
|
||||||
|
|
||||||
return &common_dto.UploadResult{
|
return &common_dto.UploadResult{
|
||||||
|
|||||||
@@ -370,7 +370,18 @@ func (s *creator) GetContent(ctx context.Context, userID int64, id string) (*cre
|
|||||||
|
|
||||||
for _, ca := range c.ContentAssets {
|
for _, ca := range c.ContentAssets {
|
||||||
if ca.Asset != nil {
|
if ca.Asset != nil {
|
||||||
sizeBytes := ca.Asset.Meta.Data().Size
|
meta := ca.Asset.Meta.Data()
|
||||||
|
name := meta.Filename
|
||||||
|
if name == "" {
|
||||||
|
// Fallback: strip UUID prefix (36 chars + 1 underscore = 37)
|
||||||
|
if len(ca.Asset.ObjectKey) > 37 && ca.Asset.ObjectKey[36] == '_' {
|
||||||
|
name = ca.Asset.ObjectKey[37:]
|
||||||
|
} else {
|
||||||
|
name = ca.Asset.ObjectKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeBytes := meta.Size
|
||||||
sizeMB := float64(sizeBytes) / 1024.0 / 1024.0
|
sizeMB := float64(sizeBytes) / 1024.0 / 1024.0
|
||||||
sizeStr := cast.ToString(float64(int(sizeMB*100))/100.0) + " MB"
|
sizeStr := cast.ToString(float64(int(sizeMB*100))/100.0) + " MB"
|
||||||
|
|
||||||
@@ -379,7 +390,7 @@ func (s *creator) GetContent(ctx context.Context, userID int64, id string) (*cre
|
|||||||
Role: string(ca.Role),
|
Role: string(ca.Role),
|
||||||
Type: string(ca.Asset.Type),
|
Type: string(ca.Asset.Type),
|
||||||
URL: Common.GetAssetURL(ca.Asset.ObjectKey),
|
URL: Common.GetAssetURL(ca.Asset.ObjectKey),
|
||||||
Name: ca.Asset.ObjectKey, // Simple fallback
|
Name: name,
|
||||||
Size: sizeStr,
|
Size: sizeStr,
|
||||||
Sort: int(ca.Sort),
|
Sort: int(ca.Sort),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package fields
|
|||||||
|
|
||||||
// MediaAssetMeta 媒体资源元数据
|
// MediaAssetMeta 媒体资源元数据
|
||||||
type MediaAssetMeta struct {
|
type MediaAssetMeta struct {
|
||||||
|
Filename string `json:"filename,omitempty"`
|
||||||
Hash string `json:"hash,omitempty"`
|
Hash string `json:"hash,omitempty"`
|
||||||
Duration float64 `json:"duration,omitempty"` // 秒
|
Duration float64 `json:"duration,omitempty"` // 秒
|
||||||
Width int `json:"width,omitempty"`
|
Width int `json:"width,omitempty"`
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col bg-slate-50">
|
<div class="flex flex-col bg-slate-50" :class="isFullWidth ? 'h-screen overflow-hidden' : 'min-h-screen'">
|
||||||
<TopNavbar />
|
<TopNavbar v-if="!isFullWidth" />
|
||||||
<main class="flex-grow pt-16">
|
<main class="flex-grow flex flex-col min-h-0" :class="!isFullWidth ? 'pt-16' : ''">
|
||||||
<div class="mx-auto flex gap-8 h-full" :class="isFullWidth ? 'max-w-none px-0' : 'max-w-screen-xl py-8'">
|
<div class="mx-auto flex gap-8 w-full min-h-0 flex-grow" :class="isFullWidth ? 'max-w-none px-0' : 'max-w-screen-xl py-8'">
|
||||||
<!-- Creator Sidebar (Dark Theme) -->
|
<!-- Creator Sidebar (Dark Theme) -->
|
||||||
<aside class="w-[280px] flex-shrink-0 hidden lg:block" v-if="!isFullWidth">
|
<aside class="w-[280px] flex-shrink-0 hidden lg:block" v-if="!isFullWidth">
|
||||||
<div
|
<div
|
||||||
@@ -66,12 +66,12 @@
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<div class="flex-grow min-w-0">
|
<div class="flex-grow min-w-0 h-full">
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<AppFooter />
|
<AppFooter v-if="!isFullWidth" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user