feat: 更新内容视图和编辑视图,支持动态曲种选项和标签显示
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">曲种 <span
|
||||
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 class="md:col-span-2">
|
||||
<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 isEditMode = ref(false);
|
||||
const contentId = ref('');
|
||||
const genreOptions = ref([]);
|
||||
|
||||
const autoSaveStatus = ref('已自动保存');
|
||||
|
||||
const form = reactive({
|
||||
genre: null,
|
||||
@@ -255,7 +258,19 @@ const form = reactive({
|
||||
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 () => {
|
||||
fetchOptions();
|
||||
if (route.params.id) {
|
||||
isEditMode.value = true;
|
||||
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 triggerUpload = (type) => {
|
||||
|
||||
@@ -53,14 +53,13 @@
|
||||
<!-- Info -->
|
||||
<div class="flex-1 min-w-0 flex flex-col justify-between">
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-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.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}`)">
|
||||
<div class="flex items-center justify-between mb-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">[{{ getGenreLabel(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>
|
||||
<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}`)">
|
||||
{{ item.title }}</h3>
|
||||
</div>
|
||||
<!-- Status Badge -->
|
||||
@@ -173,6 +172,11 @@ const handleSearch = () => {
|
||||
fetchContents();
|
||||
};
|
||||
|
||||
const getGenreLabel = (key) => {
|
||||
const opt = genreOptions.value.find(o => o.key === key);
|
||||
return opt ? opt.value : key;
|
||||
};
|
||||
|
||||
const statusStyle = (status) => {
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user