feat: 添加音乐键位字段,更新相关数据结构和接口
This commit is contained in:
2
backend/.gitignore
vendored
2
backend/.gitignore
vendored
@@ -27,3 +27,5 @@ go.work.sum
|
|||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
|
|
||||||
|
quyun
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func (c *Creator) ListContents(
|
|||||||
ctx fiber.Ctx,
|
ctx fiber.Ctx,
|
||||||
user *models.User,
|
user *models.User,
|
||||||
filter *dto.CreatorContentListFilter,
|
filter *dto.CreatorContentListFilter,
|
||||||
) ([]dto.ContentItem, error) {
|
) ([]dto.CreatorContentItem, error) {
|
||||||
return services.Creator.ListContents(ctx, user.ID, filter)
|
return services.Creator.ListContents(ctx, user.ID, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ type FloatStatItem struct {
|
|||||||
type ContentCreateForm struct {
|
type ContentCreateForm struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
|
Key string `json:"key"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
MediaIDs []string `json:"media_ids"`
|
MediaIDs []string `json:"media_ids"`
|
||||||
}
|
}
|
||||||
@@ -35,6 +36,7 @@ type ContentCreateForm struct {
|
|||||||
type ContentUpdateForm struct {
|
type ContentUpdateForm struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
|
Key string `json:"key"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
MediaIDs []string `json:"media_ids"`
|
MediaIDs []string `json:"media_ids"`
|
||||||
}
|
}
|
||||||
@@ -43,6 +45,7 @@ type ContentEditDTO struct {
|
|||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
|
Key string `json:"key"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
@@ -51,6 +54,16 @@ type ContentEditDTO struct {
|
|||||||
Assets []AssetDTO `json:"assets"`
|
Assets []AssetDTO `json:"assets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreatorContentItem struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Genre string `json:"genre"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Views int `json:"views"`
|
||||||
|
Likes int `json:"likes"`
|
||||||
|
IsPurchased bool `json:"is_purchased"`
|
||||||
|
}
|
||||||
|
|
||||||
type AssetDTO struct {
|
type AssetDTO struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ func (s *content) Get(ctx context.Context, userID int64, id string) (*content_dt
|
|||||||
Description: item.Description,
|
Description: item.Description,
|
||||||
Body: item.Body,
|
Body: item.Body,
|
||||||
MediaUrls: s.toMediaURLs(accessibleAssets),
|
MediaUrls: s.toMediaURLs(accessibleAssets),
|
||||||
|
Meta: content_dto.Meta{Key: item.Key},
|
||||||
IsLiked: isLiked,
|
IsLiked: isLiked,
|
||||||
IsFavorited: isFavorited,
|
IsFavorited: isFavorited,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ func (s *creator) ListContents(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID int64,
|
userID int64,
|
||||||
filter *creator_dto.CreatorContentListFilter,
|
filter *creator_dto.CreatorContentListFilter,
|
||||||
) ([]creator_dto.ContentItem, error) {
|
) ([]creator_dto.CreatorContentItem, error) {
|
||||||
tid, err := s.getTenantID(ctx, userID)
|
tid, err := s.getTenantID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -122,12 +122,13 @@ func (s *creator) ListContents(
|
|||||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var data []creator_dto.ContentItem
|
var data []creator_dto.CreatorContentItem
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
data = append(data, creator_dto.ContentItem{
|
data = append(data, creator_dto.CreatorContentItem{
|
||||||
ID: cast.ToString(item.ID),
|
ID: cast.ToString(item.ID),
|
||||||
Title: item.Title,
|
Title: item.Title,
|
||||||
Genre: item.Genre,
|
Genre: item.Genre,
|
||||||
|
Key: item.Key,
|
||||||
Views: int(item.Views),
|
Views: int(item.Views),
|
||||||
Likes: int(item.Likes),
|
Likes: int(item.Likes),
|
||||||
IsPurchased: false,
|
IsPurchased: false,
|
||||||
@@ -150,6 +151,7 @@ func (s *creator) CreateContent(ctx context.Context, userID int64, form *creator
|
|||||||
UserID: uid,
|
UserID: uid,
|
||||||
Title: form.Title,
|
Title: form.Title,
|
||||||
Genre: form.Genre,
|
Genre: form.Genre,
|
||||||
|
Key: form.Key,
|
||||||
Status: consts.ContentStatusPublished,
|
Status: consts.ContentStatusPublished,
|
||||||
}
|
}
|
||||||
if err := tx.Content.WithContext(ctx).Create(content); err != nil {
|
if err := tx.Content.WithContext(ctx).Create(content); err != nil {
|
||||||
@@ -214,6 +216,7 @@ func (s *creator) UpdateContent(
|
|||||||
_, err = tx.Content.WithContext(ctx).Where(tx.Content.ID.Eq(cid)).Updates(&models.Content{
|
_, err = tx.Content.WithContext(ctx).Where(tx.Content.ID.Eq(cid)).Updates(&models.Content{
|
||||||
Title: form.Title,
|
Title: form.Title,
|
||||||
Genre: form.Genre,
|
Genre: form.Genre,
|
||||||
|
Key: form.Key,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -318,6 +321,7 @@ func (s *creator) GetContent(ctx context.Context, userID int64, id string) (*cre
|
|||||||
ID: cast.ToString(c.ID),
|
ID: cast.ToString(c.ID),
|
||||||
Title: c.Title,
|
Title: c.Title,
|
||||||
Genre: c.Genre,
|
Genre: c.Genre,
|
||||||
|
Key: c.Key,
|
||||||
Description: c.Description,
|
Description: c.Description,
|
||||||
Status: string(c.Status),
|
Status: string(c.Status),
|
||||||
Price: price,
|
Price: price,
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
-- +goose Up
|
||||||
|
ALTER TABLE contents ADD COLUMN key VARCHAR(32) DEFAULT '';
|
||||||
|
COMMENT ON COLUMN contents.key IS 'Musical key/tone';
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
ALTER TABLE contents DROP COLUMN key;
|
||||||
@@ -38,6 +38,7 @@ type Content struct {
|
|||||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
|
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
|
||||||
|
Key string `gorm:"column:key;type:character varying(32);comment:Musical key/tone" json:"key"` // Musical key/tone
|
||||||
Author *User `gorm:"foreignKey:UserID;references:ID" json:"author,omitempty"`
|
Author *User `gorm:"foreignKey:UserID;references:ID" json:"author,omitempty"`
|
||||||
ContentAssets []*ContentAsset `gorm:"foreignKey:ContentID;references:ID" json:"content_assets,omitempty"`
|
ContentAssets []*ContentAsset `gorm:"foreignKey:ContentID;references:ID" json:"content_assets,omitempty"`
|
||||||
Comments []*Comment `gorm:"foreignKey:ContentID;references:ID" json:"comments,omitempty"`
|
Comments []*Comment `gorm:"foreignKey:ContentID;references:ID" json:"comments,omitempty"`
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ func newContent(db *gorm.DB, opts ...gen.DOOption) contentQuery {
|
|||||||
_contentQuery.CreatedAt = field.NewTime(tableName, "created_at")
|
_contentQuery.CreatedAt = field.NewTime(tableName, "created_at")
|
||||||
_contentQuery.UpdatedAt = field.NewTime(tableName, "updated_at")
|
_contentQuery.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||||
_contentQuery.DeletedAt = field.NewField(tableName, "deleted_at")
|
_contentQuery.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||||
|
_contentQuery.Key = field.NewString(tableName, "key")
|
||||||
_contentQuery.Author = contentQueryBelongsToAuthor{
|
_contentQuery.Author = contentQueryBelongsToAuthor{
|
||||||
db: db.Session(&gorm.Session{}),
|
db: db.Session(&gorm.Session{}),
|
||||||
|
|
||||||
@@ -90,6 +91,7 @@ type contentQuery struct {
|
|||||||
CreatedAt field.Time
|
CreatedAt field.Time
|
||||||
UpdatedAt field.Time
|
UpdatedAt field.Time
|
||||||
DeletedAt field.Field
|
DeletedAt field.Field
|
||||||
|
Key field.String // Musical key/tone
|
||||||
Author contentQueryBelongsToAuthor
|
Author contentQueryBelongsToAuthor
|
||||||
|
|
||||||
ContentAssets contentQueryHasManyContentAssets
|
ContentAssets contentQueryHasManyContentAssets
|
||||||
@@ -130,6 +132,7 @@ func (c *contentQuery) updateTableName(table string) *contentQuery {
|
|||||||
c.CreatedAt = field.NewTime(table, "created_at")
|
c.CreatedAt = field.NewTime(table, "created_at")
|
||||||
c.UpdatedAt = field.NewTime(table, "updated_at")
|
c.UpdatedAt = field.NewTime(table, "updated_at")
|
||||||
c.DeletedAt = field.NewField(table, "deleted_at")
|
c.DeletedAt = field.NewField(table, "deleted_at")
|
||||||
|
c.Key = field.NewString(table, "key")
|
||||||
|
|
||||||
c.fillFieldMap()
|
c.fillFieldMap()
|
||||||
|
|
||||||
@@ -162,7 +165,7 @@ func (c *contentQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *contentQuery) fillFieldMap() {
|
func (c *contentQuery) fillFieldMap() {
|
||||||
c.fieldMap = make(map[string]field.Expr, 22)
|
c.fieldMap = make(map[string]field.Expr, 23)
|
||||||
c.fieldMap["id"] = c.ID
|
c.fieldMap["id"] = c.ID
|
||||||
c.fieldMap["tenant_id"] = c.TenantID
|
c.fieldMap["tenant_id"] = c.TenantID
|
||||||
c.fieldMap["user_id"] = c.UserID
|
c.fieldMap["user_id"] = c.UserID
|
||||||
@@ -182,6 +185,7 @@ func (c *contentQuery) fillFieldMap() {
|
|||||||
c.fieldMap["created_at"] = c.CreatedAt
|
c.fieldMap["created_at"] = c.CreatedAt
|
||||||
c.fieldMap["updated_at"] = c.UpdatedAt
|
c.fieldMap["updated_at"] = c.UpdatedAt
|
||||||
c.fieldMap["deleted_at"] = c.DeletedAt
|
c.fieldMap["deleted_at"] = c.DeletedAt
|
||||||
|
c.fieldMap["key"] = c.Key
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="min-h-screen flex flex-col bg-slate-50">
|
<div class="min-h-screen flex flex-col bg-slate-50">
|
||||||
<TopNavbar />
|
<TopNavbar />
|
||||||
<main class="flex-grow pt-16">
|
<main class="flex-grow pt-16">
|
||||||
<div class="mx-auto flex gap-8 h-full" :class="isFullWidth ? 'max-w-none px-0 py-0' : 'max-w-screen-xl'">
|
<div class="mx-auto flex gap-8 h-full" :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
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ const loadContent = async (id) => {
|
|||||||
|
|
||||||
form.genre = res.genre;
|
form.genre = res.genre;
|
||||||
form.title = res.title;
|
form.title = res.title;
|
||||||
|
form.key = res.key;
|
||||||
form.abstract = res.description;
|
form.abstract = res.description;
|
||||||
form.price = res.price;
|
form.price = res.price;
|
||||||
form.priceType = res.price > 0 ? 'paid' : 'free';
|
form.priceType = res.price > 0 ? 'paid' : 'free';
|
||||||
@@ -332,6 +333,7 @@ const submit = async () => {
|
|||||||
title: form.title,
|
title: form.title,
|
||||||
description: form.abstract,
|
description: form.abstract,
|
||||||
genre: form.genre,
|
genre: form.genre,
|
||||||
|
key: form.key,
|
||||||
status: 'published', // Direct publish for demo
|
status: 'published', // Direct publish for demo
|
||||||
visibility: 'public',
|
visibility: 'public',
|
||||||
preview_seconds: form.enableTrial ? form.trialTime : 0,
|
preview_seconds: form.enableTrial ? form.trialTime : 0,
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ml-auto relative">
|
<div class="ml-auto relative">
|
||||||
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"></i>
|
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"></i>
|
||||||
<input type="text" placeholder="搜索标题..." v-model="searchKeyword" @keyup.enter="handleSearch" @blur="handleSearch"
|
<input type="text" placeholder="搜索标题..." v-model="searchKeyword" @keyup.enter="handleSearch"
|
||||||
|
@blur="handleSearch"
|
||||||
class="h-9 pl-9 pr-4 rounded border border-slate-200 text-sm focus:border-primary-500 outline-none w-48 transition-all focus:w-64">
|
class="h-9 pl-9 pr-4 rounded border border-slate-200 text-sm focus:border-primary-500 outline-none w-48 transition-all focus:w-64">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +41,8 @@
|
|||||||
|
|
||||||
<!-- Cover -->
|
<!-- Cover -->
|
||||||
<div class="w-40 h-[90px] bg-slate-100 rounded-lg flex-shrink-0 overflow-hidden relative">
|
<div class="w-40 h-[90px] bg-slate-100 rounded-lg flex-shrink-0 overflow-hidden relative">
|
||||||
<img :src="item.cover || 'https://via.placeholder.com/300x168?text=No+Cover'" class="w-full h-full object-cover">
|
<img :src="item.cover || 'https://via.placeholder.com/300x168?text=No+Cover'"
|
||||||
|
class="w-full h-full object-cover">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-black/50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
|
class="absolute inset-0 bg-black/50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
<router-link :to="`/creator/contents/${item.id}`"
|
<router-link :to="`/creator/contents/${item.id}`"
|
||||||
@@ -53,9 +55,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex items-center justify-between mb-2">
|
<div class="flex items-center justify-between mb-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.genre">[{{ item.genre }}]</span>
|
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.genre">{{
|
||||||
<h3
|
item.genre }}</span>
|
||||||
class="font-bold text-slate-900 text-lg truncate hover:text-primary-600 cursor-pointer transition-colors"
|
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.key">{{ item.key
|
||||||
|
}}</span>
|
||||||
|
<h3 class="font-bold text-slate-900 text-lg truncate hover:text-primary-600 cursor-pointer transition-colors"
|
||||||
@click="$router.push(`/creator/contents/${item.id}`)">
|
@click="$router.push(`/creator/contents/${item.id}`)">
|
||||||
{{ item.title }}</h3>
|
{{ item.title }}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,16 +87,17 @@
|
|||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div class="flex items-center gap-4 pt-3 border-t border-slate-50 mt-2">
|
<div class="flex items-center gap-4 pt-3 border-t border-slate-50 mt-2">
|
||||||
<button class="text-sm text-slate-500 hover:text-primary-600 font-medium cursor-pointer" @click="$router.push(`/creator/contents/${item.id}`)"><i
|
<button class="text-sm text-slate-500 hover:text-primary-600 font-medium cursor-pointer"
|
||||||
class="pi pi-file-edit mr-1"></i> 编辑</button>
|
@click="$router.push(`/creator/contents/${item.id}`)"><i class="pi pi-file-edit mr-1"></i>
|
||||||
|
编辑</button>
|
||||||
<button v-if="item.status === 'published'"
|
<button v-if="item.status === 'published'"
|
||||||
class="text-sm text-slate-500 hover:text-orange-600 font-medium cursor-pointer"><i
|
class="text-sm text-slate-500 hover:text-orange-600 font-medium cursor-pointer"><i
|
||||||
class="pi pi-arrow-down mr-1"></i> 下架</button>
|
class="pi pi-arrow-down mr-1"></i> 下架</button>
|
||||||
<button v-if="item.status === 'unpublished'"
|
<button v-if="item.status === 'unpublished'"
|
||||||
class="text-sm text-slate-500 hover:text-green-600 font-medium cursor-pointer"><i
|
class="text-sm text-slate-500 hover:text-green-600 font-medium cursor-pointer"><i
|
||||||
class="pi pi-arrow-up mr-1"></i> 上架</button>
|
class="pi pi-arrow-up mr-1"></i> 上架</button>
|
||||||
<button class="text-sm text-slate-500 hover:text-red-600 font-medium ml-auto cursor-pointer" @click="handleDelete(item.id)"><i
|
<button class="text-sm text-slate-500 hover:text-red-600 font-medium ml-auto cursor-pointer"
|
||||||
class="pi pi-trash mr-1"></i> 删除</button>
|
@click="handleDelete(item.id)"><i class="pi pi-trash mr-1"></i> 删除</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,10 +106,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, onMounted, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { creatorApi } from '../../api/creator';
|
|
||||||
import { commonApi } from '../../api/common';
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import { commonApi } from '../../api/common';
|
||||||
|
import { creatorApi } from '../../api/creator';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const contents = ref([]);
|
const contents = ref([]);
|
||||||
@@ -115,42 +120,42 @@ const statusOptions = ref([]);
|
|||||||
const genreOptions = ref([]);
|
const genreOptions = ref([]);
|
||||||
|
|
||||||
const fetchOptions = async () => {
|
const fetchOptions = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await commonApi.getOptions();
|
const res = await commonApi.getOptions();
|
||||||
if (res) {
|
if (res) {
|
||||||
statusOptions.value = res.content_status || [];
|
statusOptions.value = res.content_status || [];
|
||||||
genreOptions.value = res.content_genre || [];
|
genreOptions.value = res.content_genre || [];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchContents = async () => {
|
const fetchContents = async () => {
|
||||||
try {
|
try {
|
||||||
const params = {};
|
const params = {};
|
||||||
if (filterStatus.value !== 'all') params.status = filterStatus.value;
|
if (filterStatus.value !== 'all') params.status = filterStatus.value;
|
||||||
if (filterGenre.value !== 'all') params.genre = filterGenre.value;
|
if (filterGenre.value !== 'all') params.genre = filterGenre.value;
|
||||||
if (searchKeyword.value) params.keyword = searchKeyword.value;
|
if (searchKeyword.value) params.keyword = searchKeyword.value;
|
||||||
|
|
||||||
const res = await creatorApi.listContents(params);
|
const res = await creatorApi.listContents(params);
|
||||||
contents.value = res || [];
|
contents.value = res || [];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchOptions();
|
fetchOptions();
|
||||||
fetchContents();
|
fetchContents();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch([filterStatus, filterGenre], () => {
|
watch([filterStatus, filterGenre], () => {
|
||||||
fetchContents();
|
fetchContents();
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
fetchContents();
|
fetchContents();
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusStyle = (status) => {
|
const statusStyle = (status) => {
|
||||||
@@ -172,12 +177,12 @@ const statusStyle = (status) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id) => {
|
const handleDelete = async (id) => {
|
||||||
if (!confirm('确定要删除吗?')) return;
|
if (!confirm('确定要删除吗?')) return;
|
||||||
try {
|
try {
|
||||||
await creatorApi.deleteContent(id);
|
await creatorApi.deleteContent(id);
|
||||||
fetchContents();
|
fetchContents();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user