fix: content quality, image format, task monitor, calendar data source, search UI & sort

This commit is contained in:
Yuzhiran Dev
2026-05-26 11:26:10 +08:00
parent b2d043b231
commit ac8644d752
36 changed files with 2294 additions and 873 deletions
+53 -6
View File
@@ -189,14 +189,15 @@
<el-table v-else :data="selectedDayEntries" stripe>
<el-table-column prop="title" label="标题" min-width="120"></el-table-column>
<el-table-column prop="platform" label="平台" width="100">
<template #default="scope">{{ platformName(scope.row.platform) }}</template>
<template #default="scope">{{ scope.row._source === 'topic' ? (scope.row.status === 'published' ? '已发布' : '选题') : platformName(scope.row.platform) }}</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template #default="scope"><el-tag :type="statusType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag></template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="scope">
<el-button size="small" @click="openEntryDialog(scope.row)">编辑</el-button>
<el-button v-if="scope.row._source === 'topic'" size="small" type="primary" @click="openEntryDialog(scope.row)">查看</el-button>
<el-button v-else size="small" @click="openEntryDialog(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
@@ -407,11 +408,51 @@ function getDayMeta(year, month, day) {
loadingCalendar.value = true;
calendarError.value = '';
errorMsg.value = '';
try { entries.value = await api(`/api/calendar?year=${currentYear.value}&month=${currentMonth.value}`); } catch (e) { console.error(e); calendarError.value = e.message; errorMsg.value = '加载失败: ' + e.message; }
try {
const [calEntries, topicList] = await Promise.all([
api(`/api/calendar?year=${currentYear.value}&month=${currentMonth.value}`),
api('/api/topics?limit=200'),
]);
topics.value = topicList;
const virtualEntries = [];
(topicList || []).forEach(t => {
const s = t.status;
if ((s === 'ready' || s === '待发布') && t.ready_at) {
const d = new Date(t.ready_at);
if (d.getFullYear() === currentYear.value && d.getMonth() + 1 === currentMonth.value) {
virtualEntries.push({ id: 'topic_ready_' + t.id, title: t.title, planned_date: t.ready_at, platform: '', status: 'planned', platform_icon: '📋', topic_status: 'ready', _source: 'topic' });
}
} else if ((s === 'published' || s === '已发布') && t.published_at) {
const d = new Date(t.published_at);
if (d.getFullYear() === currentYear.value && d.getMonth() + 1 === currentMonth.value) {
virtualEntries.push({ id: 'topic_pub_' + t.id, title: t.title, planned_date: t.published_at, platform: '', status: 'published', platform_icon: '📄', topic_status: 'published', _source: 'topic' });
}
}
});
entries.value = [...(calEntries || []), ...virtualEntries];
} catch (e) { console.error(e); calendarError.value = e.message; errorMsg.value = '加载失败: ' + e.message; }
finally { loadingCalendar.value = false; }
};
const fetchStats = async () => {
try { stats.value = await api(`/api/calendar/stats?year=${currentYear.value}&month=${currentMonth.value}`); } catch (e) { console.error(e); ElMessage.error('加载统计失败: ' + e.message); }
try {
const [calStats, topicList] = await Promise.all([
api(`/api/calendar/stats?year=${currentYear.value}&month=${currentMonth.value}`),
api('/api/topics?limit=200').catch(() => []),
]);
const s = { planned: calStats.planned || 0, published: calStats.published || 0, delayed: calStats.delayed || 0, cancelled: calStats.cancelled || 0 };
(topicList || []).forEach(t => {
const st = t.status;
if ((st === 'ready' || st === '待发布') && t.ready_at) {
const d = new Date(t.ready_at);
if (d.getFullYear() === currentYear.value && d.getMonth() + 1 === currentMonth.value) s.planned++;
} else if ((st === 'published' || st === '已发布') && t.published_at) {
const d = new Date(t.published_at);
if (d.getFullYear() === currentYear.value && d.getMonth() + 1 === currentMonth.value) s.published++;
}
});
stats.value = s;
} catch (e) { console.error(e); ElMessage.error('加载统计失败: ' + e.message); }
};
const fetchTopics = async () => {
try { const res = await api('/api/topics?limit=100'); topics.value = res; } catch (e) { console.error(e); ElMessage.error('加载选题失败: ' + e.message); }
@@ -423,7 +464,14 @@ function getDayMeta(year, month, day) {
const openDayDialog = (day) => { selectedDay.value = day; selectedDayEntries.value = entries.value.filter(e => { const pd = new Date(e.planned_date); return pd.getFullYear() === day.year && pd.getMonth() + 1 === day.month && pd.getDate() === day.day; }); dayDialogVisible.value = true; };
const openCreateDialog = () => { isEdit.value = false; entryForm.value = { id: null, title: '', planned_date: `${selectedDay.value.year}-${selectedDay.value.month}-${selectedDay.value.day}`, platform: 'zhihu', topic_id: null, status: 'planned', notes: '' }; entryDialogVisible.value = true; };
const openEntryDialog = (entry) => { isEdit.value = true; entryForm.value = { ...entry, planned_date: entry.planned_date }; entryDialogVisible.value = true; };
const openEntryDialog = (entry) => {
if (entry._source === 'topic') {
const topicId = entry.id.replace(/^topic_(ready|pub)_/, '');
window.location.href = '/topics.html?topic_id=' + topicId;
return;
}
isEdit.value = true; entryForm.value = { ...entry, planned_date: entry.planned_date }; entryDialogVisible.value = true;
};
const saveEntry = async () => {
saving.value = true;
@@ -463,7 +511,6 @@ function getDayMeta(year, month, day) {
isAdmin.value = d.user.role === 'admin';
fetchEntries();
fetchStats();
fetchTopics();
})
.catch(() => {
localStorage.removeItem('authToken');