优化后的管理后台
This commit is contained in:
parent
18efb25133
commit
ad54ff0398
@ -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),
|
||||||
|
|||||||
@ -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]
|
|
||||||
}
|
|
||||||
|
|
||||||
// API基础URL
|
// API基础URL
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user