优化后的管理后台

This commit is contained in:
Qyir 2025-11-07 17:36:53 +08:00
parent 18efb25133
commit ad54ff0398
3 changed files with 19 additions and 244 deletions

View File

@ -197,7 +197,7 @@ def format_interaction_count(count):
def format_mix_item(doc, target_date=None): def format_mix_item(doc, target_date=None):
"""格式化合集数据项 - 完全按照数据库原始字段返回""" """格式化合集数据项 - 完全按照数据库原始字段返回"""
mix_name = doc.get("mix_name", "") mix_name = doc.get("mix_name", "") or doc.get("title", "")
# 计算总点赞数 # 计算总点赞数
episode_details = doc.get("episode_details", []) episode_details = doc.get("episode_details", [])
@ -217,6 +217,7 @@ def format_mix_item(doc, target_date=None):
"_id": str(doc.get("_id", "")), "_id": str(doc.get("_id", "")),
"batch_time": format_time(doc.get("batch_time")), "batch_time": format_time(doc.get("batch_time")),
"mix_name": mix_name, "mix_name": mix_name,
"title": mix_name,
"video_url": doc.get("video_url", ""), "video_url": doc.get("video_url", ""),
"playcount": doc.get("playcount", ""), "playcount": doc.get("playcount", ""),
"play_vv": doc.get("play_vv", 0), "play_vv": doc.get("play_vv", 0),

View File

@ -8,9 +8,7 @@ const router = useRouter()
// //
const rankingData = ref([]) const rankingData = ref([])
const loading = ref(false) const loading = ref(false)
const selectedDate = ref('')
const showEditModal = ref(false) const showEditModal = ref(false)
const showAddModal = ref(false)
// //
const editForm = reactive({ const editForm = reactive({
@ -34,32 +32,20 @@ const editForm = reactive({
isDrama: false isDrama: false
}) })
//
const addForm = reactive({
title: '',
mix_name: '',
series_author: '',
Manufacturing_Field: '',
Copyright_field: '',
play_vv: 0,
total_likes_formatted: '',
cover_image_url: '',
cover_backup_urls: [],
timeline_data: {
play_vv_change: 0,
play_vv_change_rate: 0
}
})
//
const initDate = () => {
const today = new Date()
selectedDate.value = today.toISOString().split('T')[0]
}
// APIURL // APIURL
const API_BASE_URL = 'http://localhost:5001/api' const API_BASE_URL = 'http://localhost:5001/api'
//
const formatPlayCount = (count) => {
if (!count) return '0'
if (count >= 100000000) {
return (count / 100000000).toFixed(1) + '亿'
} else if (count >= 10000) {
return (count / 10000).toFixed(1) + '万'
}
return count.toString()
}
// //
const fetchRankingData = async () => { const fetchRankingData = async () => {
loading.value = true loading.value = true
@ -68,9 +54,7 @@ const fetchRankingData = async () => {
params: { params: {
page: 1, page: 1,
limit: 100, limit: 100,
sort: 'growth', sort: 'growth'
start_date: selectedDate.value,
end_date: selectedDate.value
} }
}) })
@ -119,17 +103,6 @@ const fetchRankingData = async () => {
} }
} }
//
const formatPlayCount = (count) => {
if (!count) return '0'
if (count >= 100000000) {
return (count / 100000000).toFixed(1) + '亿'
} else if (count >= 10000) {
return (count / 10000).toFixed(1) + '万'
}
return count.toString()
}
// //
const editItem = async (item) => { const editItem = async (item) => {
editForm.id = item.id || item._id editForm.id = item.id || item._id
@ -161,7 +134,7 @@ const loadClassificationStatus = async (mixName) => {
}) })
if (response.data.success) { if (response.data.success) {
const classifications = response.data.data const classifications = response.data.data.classification_status || response.data.data
editForm.isNovel = classifications.novel || false editForm.isNovel = classifications.novel || false
editForm.isAnime = classifications.anime || false editForm.isAnime = classifications.anime || false
editForm.isDrama = classifications.drama || false editForm.isDrama = classifications.drama || false
@ -273,8 +246,7 @@ const saveEdit = async () => {
total_likes_formatted: editForm.total_likes_formatted, total_likes_formatted: editForm.total_likes_formatted,
cover_image_url: editForm.cover_image_url, cover_image_url: editForm.cover_image_url,
cover_backup_urls: editForm.cover_backup_urls, cover_backup_urls: editForm.cover_backup_urls,
timeline_data: editForm.timeline_data, timeline_data: editForm.timeline_data
target_date: selectedDate.value
} }
// API // API
@ -312,113 +284,11 @@ const saveEdit = async () => {
} }
} }
//
const addNewItem = async () => {
try {
const newItemData = {
title: addForm.title,
mix_name: addForm.mix_name,
series_author: addForm.series_author,
Manufacturing_Field: addForm.Manufacturing_Field,
Copyright_field: addForm.Copyright_field,
play_vv: addForm.play_vv,
total_likes_formatted: addForm.total_likes_formatted,
cover_image_url: addForm.cover_image_url,
cover_backup_urls: addForm.cover_backup_urls,
timeline_data: addForm.timeline_data
}
// API
try {
const response = await axios.post(`${API_BASE_URL}/rank/videos`, newItemData)
//
Object.keys(addForm).forEach(key => {
if (key === 'play_vv') {
addForm[key] = 0
} else if (key === 'cover_backup_urls') {
addForm[key] = []
} else if (key === 'timeline_data') {
addForm[key] = {
play_vv_change: 0,
play_vv_change_rate: 0
}
} else {
addForm[key] = ''
}
})
showAddModal.value = false
//
await fetchRankingData()
alert('添加成功!')
} catch (apiError) {
console.warn('API添加失败使用本地添加:', apiError)
const newItem = {
id: Date.now(),
...newItemData
}
//
rankingData.value.unshift(newItem)
//
Object.keys(addForm).forEach(key => {
if (key === 'play_vv') {
addForm[key] = 0
} else if (key === 'cover_backup_urls') {
addForm[key] = []
} else if (key === 'timeline_data') {
addForm[key] = {
play_vv_change: 0,
play_vv_change_rate: 0
}
} else {
addForm[key] = ''
}
})
showAddModal.value = false
alert('添加失败,但本地数据已更新。请检查网络连接。')
}
} catch (error) {
console.error('添加失败:', error)
alert('添加失败!')
}
}
// //
const cancelEdit = () => { const cancelEdit = () => {
showEditModal.value = false showEditModal.value = false
} }
//
const cancelAdd = () => {
showAddModal.value = false
//
Object.keys(addForm).forEach(key => {
if (key === 'play_vv') {
addForm[key] = 0
} else if (key === 'cover_backup_urls') {
addForm[key] = []
} else if (key === 'timeline_data') {
addForm[key] = {
play_vv_change: 0,
play_vv_change_rate: 0
}
} else {
addForm[key] = ''
}
})
}
//
const onDateChange = () => {
fetchRankingData()
}
// //
const goBack = () => { const goBack = () => {
router.push('/') router.push('/')
@ -426,7 +296,6 @@ const goBack = () => {
// //
onMounted(() => { onMounted(() => {
initDate()
fetchRankingData() fetchRankingData()
}) })
</script> </script>
@ -442,28 +311,12 @@ onMounted(() => {
<h1 class="main-title">AI棒榜 - 后台管理</h1> <h1 class="main-title">AI棒榜 - 后台管理</h1>
</div> </div>
<div class="header-actions"> <div class="header-actions">
<button class="btn btn-primary" @click="showAddModal = true">
添加新项目
</button>
<button class="btn btn-secondary" @click="fetchRankingData"> <button class="btn btn-secondary" @click="fetchRankingData">
刷新数据 刷新数据
</button> </button>
</div> </div>
</div> </div>
<!-- 日期选择区域 -->
<div class="date-section">
<label for="date-input">选择日期</label>
<input
id="date-input"
type="date"
v-model="selectedDate"
@change="onDateChange"
class="date-input"
/>
<span class="data-count"> {{ rankingData.length }} 条数据</span>
</div>
<!-- 管理内容区域 --> <!-- 管理内容区域 -->
<div class="admin-content"> <div class="admin-content">
<!-- 加载状态 --> <!-- 加载状态 -->
@ -624,58 +477,6 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
<!-- 添加模态框 -->
<div v-if="showAddModal" class="modal-overlay" @click="cancelAdd">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3>添加新项目</h3>
<button class="close-btn" @click="cancelAdd">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>剧名</label>
<input v-model="addForm.title" type="text" class="form-input" />
</div>
<div class="form-group">
<label>合集名</label>
<input v-model="addForm.mix_name" type="text" class="form-input" />
</div>
<div class="form-group">
<label>剧场名</label>
<input v-model="addForm.series_author" type="text" class="form-input" />
</div>
<div class="form-group">
<label>承制方</label>
<input v-model="addForm.Manufacturing_Field" type="text" class="form-input" />
</div>
<div class="form-group">
<label>版权方</label>
<input v-model="addForm.Copyright_field" type="text" class="form-input" />
</div>
<div class="form-group">
<label>播放量</label>
<input v-model.number="addForm.play_vv" type="number" class="form-input" />
</div>
<div class="form-group">
<label>点赞数格式化</label>
<input v-model="addForm.total_likes_formatted" type="text" class="form-input" />
</div>
<div class="form-group">
<label>封面图片URL</label>
<input v-model="addForm.cover_image_url" type="url" class="form-input" />
</div>
<div class="form-group">
<label>增长量</label>
<input v-model.number="addForm.timeline_data.play_vv_change" type="number" class="form-input" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" @click="cancelAdd">取消</button>
<button class="btn btn-primary" @click="addNewItem">添加</button>
</div>
</div>
</div>
</div> </div>
</template> </template>
@ -807,29 +608,6 @@ export default {
background: #c82333; background: #c82333;
} }
/* 日期选择区域 */
.date-section {
padding: 16px;
background: white;
border-bottom: 1px solid #e0e0e0;
display: flex;
align-items: center;
gap: 12px;
font-size: 14px;
}
.date-input {
padding: 6px 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.data-count {
color: #666;
margin-left: auto;
}
/* 管理内容区域 */ /* 管理内容区域 */
.admin-content { .admin-content {
padding: 16px; padding: 16px;
@ -1158,10 +936,6 @@ export default {
padding: 16px 12px; padding: 16px 12px;
} }
.date-section {
padding: 12px;
}
.admin-content { .admin-content {
padding: 12px; padding: 12px;
} }

View File

@ -370,9 +370,9 @@ onMounted(() => {
<img src="./images/版权icon.svg" alt="版权" class="detail-icon" /> <img src="./images/版权icon.svg" alt="版权" class="detail-icon" />
</div> </div>
<div class="detail-text"> <div class="detail-text">
<p>剧场名{{ item.series_author || '爱微剧场' }}</p> <p>剧场名{{ item.series_author || '' }}</p>
<p>承制{{ item.Manufacturing_Field || '妙想制片厂' }}</p> <p>承制{{ item.Manufacturing_Field || '' }}</p>
<p>版权{{ item.Copyright_field || '可梦' }}</p> <p>版权{{ item.Copyright_field || '' }}</p>
</div> </div>
</div> </div>