feat: 添加内容可见性字段和过滤选项,优化内容列表查询功能

This commit is contained in:
2026-01-06 10:04:50 +08:00
parent 1d53d9560e
commit 31d6192816
3 changed files with 39 additions and 3 deletions

View File

@@ -18,6 +18,14 @@
<option v-for="opt in statusOptions" :key="opt.key" :value="opt.key">{{ opt.value }}</option>
</select>
</div>
<div class="flex items-center gap-2">
<span class="text-sm font-bold text-slate-500">可见性:</span>
<select v-model="filterVisibility"
class="h-9 px-3 rounded border border-slate-200 text-sm focus:border-primary-500 outline-none bg-white cursor-pointer min-w-[100px]">
<option value="all">全部</option>
<option v-for="opt in visibilityOptions" :key="opt.key" :value="opt.key">{{ opt.value }}</option>
</select>
</div>
<div class="flex items-center gap-2">
<span class="text-sm font-bold text-slate-500">曲种:</span>
<select v-model="filterGenre"
@@ -77,6 +85,9 @@
</div>
<!-- Status Badge -->
<div class="flex items-center gap-2 ml-4">
<span class="text-[10px] px-1.5 py-0.5 rounded border border-slate-200 text-slate-500 bg-slate-50" v-if="item.visibility">
{{ getVisibilityLabel(item.visibility) }}
</span>
<span v-if="item.status === 'blocked'" class="text-red-500 text-xs flex items-center gap-1 cursor-help"
title="已被封禁">
<i class="pi pi-info-circle"></i> 封禁
@@ -173,10 +184,16 @@ const toast = useToast();
const confirm = useConfirm();
const contents = ref([]);
const filterStatus = ref('all');
const filterVisibility = ref('all');
const filterGenre = ref('all');
const filterKey = ref('all');
const searchKeyword = ref('');
const statusOptions = ref([]);
const visibilityOptions = [
{ key: 'public', value: '公开' },
{ key: 'tenant_only', value: '仅会员' },
{ key: 'private', value: '私有' }
];
const genreOptions = ref([]);
const keys = ['C大调', 'D大调', 'E大调', 'F大调', 'G大调', 'A大调', 'B大调', '降E大调'];
@@ -196,6 +213,7 @@ const fetchContents = async () => {
try {
const params = {};
if (filterStatus.value !== 'all') params.status = filterStatus.value;
if (filterVisibility.value !== 'all') params.visibility = filterVisibility.value;
if (filterGenre.value !== 'all') params.genre = filterGenre.value;
if (filterKey.value !== 'all') params.key = filterKey.value;
if (searchKeyword.value) params.keyword = searchKeyword.value;
@@ -212,7 +230,7 @@ onMounted(() => {
fetchContents();
});
watch([filterStatus, filterGenre, filterKey], () => {
watch([filterStatus, filterVisibility, filterGenre, filterKey], () => {
fetchContents();
});
@@ -225,6 +243,15 @@ const getGenreLabel = (key) => {
return opt ? opt.value : key;
};
const getVisibilityLabel = (vis) => {
const map = {
'public': '公开',
'tenant_only': '仅会员',
'private': '私有'
};
return map[vis] || vis;
};
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.