feat: 添加用户错误日志功能, 禁用Redis缓存, userId自动生成5位随机字符

This commit is contained in:
AIGC Developer
2025-12-11 13:32:24 +08:00
parent 3c37006ebd
commit 0933031b59
58 changed files with 4932 additions and 1144 deletions

View File

@@ -41,7 +41,6 @@
<div class="nav-item" @click="goToStoryboardVideo">
<el-icon><Film /></el-icon>
<span>{{ t('works.storyboardVideo') }}</span>
<el-tag size="small" type="primary" class="sora-tag">Sora2.0</el-tag>
</div>
</nav>
</aside>
@@ -133,7 +132,7 @@
</div>
<div class="select-row">
<el-checkbox v-model="multiSelect" size="small">{{ t('works.selectItems', { count: selectedIds.size || 6 }) }}</el-checkbox>
<el-checkbox :model-value="isAllSelected" @change="toggleSelectAll" size="small">{{ t('works.selectAll') }}</el-checkbox>
<template v-if="multiSelect && selectedIds.size">
<el-tag type="success" size="small">{{ t('works.selectedCount', { count: selectedIds.size }) }}</el-tag>
<el-button size="small" type="primary" @click="bulkDownload" plain>{{ t('video.download') }}</el-button>
@@ -227,6 +226,7 @@
<template #footer>
<el-space size="small">
<el-button text size="small" @click.stop="download(item)">{{ t('video.download') }}</el-button>
<el-button text size="small" type="danger" @click.stop="handleDeleteWork(item)">{{ t('common.delete') || '删除' }}</el-button>
</el-space>
</template>
</el-card>
@@ -489,7 +489,7 @@ const isVerticalVideo = computed(() => {
})
const page = ref(1)
const pageSize = ref(20)
const pageSize = ref(100)
const loading = ref(false)
const hasMore = ref(true)
const items = ref([])
@@ -663,12 +663,10 @@ const loadList = async () => {
const filteredItems = computed(() => {
let filtered = [...items.value]
// 过滤掉加载失败的作品URL失效的作品自动隐藏
// 过滤掉加载失败的作品
filtered = filtered.filter(item => {
// 检查 resultUrl 和 cover 是否在失败集合中
const resultUrlFailed = item.resultUrl && failedUrls.value.has(item.resultUrl)
const coverFailed = item.cover && failedUrls.value.has(item.cover)
// 如果任一URL失败则不显示该作品
return !resultUrlFailed && !coverFailed
})
@@ -1054,7 +1052,7 @@ const download = async (item) => {
// 备用方案:使用后端代理
const downloadUrl = getWorkFileUrl(item.id, true)
const token = sessionStorage.getItem('token')
const token = localStorage.getItem('token')
console.log('开始下载:', downloadUrl)
@@ -1151,6 +1149,36 @@ const moreCommand = async (cmd, item) => {
}
}
// 删除单个作品
const handleDeleteWork = async (item) => {
try {
await ElMessageBox.confirm(
t('works.deleteWorkConfirm') || `确定要删除作品"${item.title}"吗?`,
t('works.deleteConfirmTitle') || '删除确认',
{
type: 'warning',
confirmButtonText: t('common.delete') || '删除',
cancelButtonText: t('common.cancel') || '取消'
}
)
// 执行删除
const response = await deleteWork(item.id)
if (response.data.success) {
ElMessage.success(t('works.deleteSuccess') || '删除成功')
// 从列表中移除
items.value = items.value.filter(i => i.id !== item.id)
} else {
throw new Error(response.data.message || t('works.deleteFailed') || '删除失败')
}
} catch (error) {
if (error !== 'cancel') {
console.error('删除作品失败:', error)
ElMessage.error(error.message || t('works.deleteFailed') || '删除失败')
}
}
}
const toggleSelect = (id) => {
const next = new Set(selectedIds.value)
if (next.has(id)) next.delete(id)
@@ -1158,6 +1186,24 @@ const toggleSelect = (id) => {
selectedIds.value = next
}
// 全选/取消全选
const isAllSelected = computed(() => {
if (filteredItems.value.length === 0) return false
return filteredItems.value.every(item => selectedIds.value.has(item.id))
})
const toggleSelectAll = () => {
if (isAllSelected.value) {
// 取消全选
selectedIds.value = new Set()
multiSelect.value = false
} else {
// 全选
multiSelect.value = true
selectedIds.value = new Set(filteredItems.value.map(item => item.id))
}
}
const bulkDownload = async () => {
if (selectedIds.value.size === 0) {
ElMessage.warning(t('works.noItemsSelected'))