feat: 更新内容视图和编辑视图,支持动态曲种选项和标签显示
This commit is contained in:
@@ -20,6 +20,16 @@ import (
|
|||||||
// @provider
|
// @provider
|
||||||
type creator struct{}
|
type creator struct{}
|
||||||
|
|
||||||
|
var genreMap = map[string]string{
|
||||||
|
"Jingju": "京剧",
|
||||||
|
"Kunqu": "昆曲",
|
||||||
|
"Yueju": "越剧",
|
||||||
|
"Yuju": "豫剧",
|
||||||
|
"Huangmeixi": "黄梅戏",
|
||||||
|
"Pingju": "评剧",
|
||||||
|
"Qinqiang": "秦腔",
|
||||||
|
}
|
||||||
|
|
||||||
func (s *creator) Apply(ctx context.Context, userID int64, form *creator_dto.ApplyForm) error {
|
func (s *creator) Apply(ctx context.Context, userID int64, form *creator_dto.ApplyForm) error {
|
||||||
if userID == 0 {
|
if userID == 0 {
|
||||||
return errorx.ErrUnauthorized
|
return errorx.ErrUnauthorized
|
||||||
@@ -111,7 +121,12 @@ func (s *creator) ListContents(
|
|||||||
q = q.Where(tbl.Status.Eq(consts.ContentStatus(*filter.Status)))
|
q = q.Where(tbl.Status.Eq(consts.ContentStatus(*filter.Status)))
|
||||||
}
|
}
|
||||||
if filter.Genre != nil && *filter.Genre != "" {
|
if filter.Genre != nil && *filter.Genre != "" {
|
||||||
q = q.Where(tbl.Genre.Eq(*filter.Genre))
|
val := *filter.Genre
|
||||||
|
if cn, ok := genreMap[val]; ok {
|
||||||
|
q = q.Where(tbl.Genre.In(val, cn))
|
||||||
|
} else {
|
||||||
|
q = q.Where(tbl.Genre.Eq(val))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if filter.Keyword != nil && *filter.Keyword != "" {
|
if filter.Keyword != nil && *filter.Keyword != "" {
|
||||||
q = q.Where(tbl.Title.Like("%" + *filter.Keyword + "%"))
|
q = q.Where(tbl.Title.Like("%" + *filter.Keyword + "%"))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<label class="block text-sm font-bold text-slate-700 mb-2">曲种 <span
|
<label class="block text-sm font-bold text-slate-700 mb-2">曲种 <span
|
||||||
class="text-red-500">*</span></label>
|
class="text-red-500">*</span></label>
|
||||||
<Select v-model="form.genre" :options="genres" placeholder="选择曲种" class="w-full h-12" />
|
<Select v-model="form.genre" :options="genreOptions" optionLabel="value" optionValue="key" placeholder="选择曲种" class="w-full h-12" />
|
||||||
</div>
|
</div>
|
||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<label class="block text-sm font-bold text-slate-700 mb-2">主定调</label>
|
<label class="block text-sm font-bold text-slate-700 mb-2">主定调</label>
|
||||||
@@ -239,6 +239,9 @@ const currentUploadType = ref('');
|
|||||||
const isSubmitting = ref(false);
|
const isSubmitting = ref(false);
|
||||||
const isEditMode = ref(false);
|
const isEditMode = ref(false);
|
||||||
const contentId = ref('');
|
const contentId = ref('');
|
||||||
|
const genreOptions = ref([]);
|
||||||
|
|
||||||
|
const autoSaveStatus = ref('已自动保存');
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
genre: null,
|
genre: null,
|
||||||
@@ -255,7 +258,19 @@ const form = reactive({
|
|||||||
images: [] // { name, size, url, id }
|
images: [] // { name, size, url, id }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fetchOptions = async () => {
|
||||||
|
try {
|
||||||
|
const res = await commonApi.getOptions();
|
||||||
|
if (res) {
|
||||||
|
genreOptions.value = res.content_genre || [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
fetchOptions();
|
||||||
if (route.params.id) {
|
if (route.params.id) {
|
||||||
isEditMode.value = true;
|
isEditMode.value = true;
|
||||||
contentId.value = route.params.id;
|
contentId.value = route.params.id;
|
||||||
@@ -306,7 +321,6 @@ const loadContent = async (id) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const genres = ['京剧', '昆曲', '越剧', '黄梅戏', '豫剧', '评剧'];
|
|
||||||
const keys = ['C大调', 'D大调', 'E大调', 'F大调', 'G大调', 'A大调', 'B大调', '降E大调'];
|
const keys = ['C大调', 'D大调', 'E大调', 'F大调', 'G大调', 'A大调', 'B大调', '降E大调'];
|
||||||
|
|
||||||
const triggerUpload = (type) => {
|
const triggerUpload = (type) => {
|
||||||
|
|||||||
@@ -53,14 +53,13 @@
|
|||||||
<!-- Info -->
|
<!-- Info -->
|
||||||
<div class="flex-1 min-w-0 flex flex-col justify-between">
|
<div class="flex-1 min-w-0 flex flex-col justify-between">
|
||||||
<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">{{
|
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.genre">[{{ getGenreLabel(item.genre) }}]</span>
|
||||||
item.genre }}</span>
|
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.key">[{{ item.key }}]</span>
|
||||||
<span class="text-xs px-1.5 py-0.5 border rounded text-slate-500" v-if="item.key">{{ item.key
|
<h3
|
||||||
}}</span>
|
class="font-bold text-slate-900 text-lg truncate hover:text-primary-600 cursor-pointer transition-colors"
|
||||||
<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>
|
||||||
<!-- Status Badge -->
|
<!-- Status Badge -->
|
||||||
@@ -173,6 +172,11 @@ const handleSearch = () => {
|
|||||||
fetchContents();
|
fetchContents();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getGenreLabel = (key) => {
|
||||||
|
const opt = genreOptions.value.find(o => o.key === key);
|
||||||
|
return opt ? opt.value : key;
|
||||||
|
};
|
||||||
|
|
||||||
const statusStyle = (status) => {
|
const statusStyle = (status) => {
|
||||||
// Map backend status to UI style. Labels should ideally come from backend option value/label map if needed,
|
// Map backend status to UI style. Labels should ideally come from backend option value/label map if needed,
|
||||||
// but for style/color mapping we can keep it here or use a helper.
|
// but for style/color mapping we can keep it here or use a helper.
|
||||||
|
|||||||
Reference in New Issue
Block a user