|
@@ -247,7 +247,7 @@
|
|
|
</el-tag>
|
|
</el-tag>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="错误信息" min-width="200">
|
|
|
|
|
|
|
+ <el-table-column label="错误信息" min-width="260">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<div v-if="isCaptchaError(row.errorMessage)" class="captcha-error">
|
|
<div v-if="isCaptchaError(row.errorMessage)" class="captcha-error">
|
|
|
<el-text type="warning">检测到验证码,需要手动验证</el-text>
|
|
<el-text type="warning">检测到验证码,需要手动验证</el-text>
|
|
@@ -260,7 +260,38 @@
|
|
|
打开浏览器验证
|
|
打开浏览器验证
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
- <span v-else>{{ row.errorMessage || '-' }}</span>
|
|
|
|
|
|
|
+ <div v-else-if="isScreenshotPendingError(row.errorMessage)" class="screenshot-pending">
|
|
|
|
|
+ <span>{{ row.errorMessage?.replace('请查看截图', '').trim() || '发布结果待确认' }}</span>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ link
|
|
|
|
|
+ @click="openScreenshotView(row)"
|
|
|
|
|
+ >
|
|
|
|
|
+ 查看截图
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-if="canRetryWithHeadful(row)"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ link
|
|
|
|
|
+ @click="openBrowserForCaptcha(row.accountId, row.platform)"
|
|
|
|
|
+ >
|
|
|
|
|
+ 使用有头浏览器重新发布
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else class="normal-error">
|
|
|
|
|
+ <span>{{ row.errorMessage || '-' }}</span>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-if="canRetryWithHeadful(row)"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ link
|
|
|
|
|
+ @click="openBrowserForCaptcha(row.accountId, row.platform)"
|
|
|
|
|
+ >
|
|
|
|
|
+ 使用有头浏览器重新发布
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="发布时间" width="160">
|
|
<el-table-column label="发布时间" width="160">
|
|
@@ -274,6 +305,13 @@
|
|
|
|
|
|
|
|
<template #footer>
|
|
<template #footer>
|
|
|
<el-button @click="showDetailDialog = false">关闭</el-button>
|
|
<el-button @click="showDetailDialog = false">关闭</el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-if="hasPendingConfirmResults"
|
|
|
|
|
+ type="success"
|
|
|
|
|
+ @click="confirmAllPendingResults"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认
|
|
|
|
|
+ </el-button>
|
|
|
<el-button type="primary" @click="openEditDialog">
|
|
<el-button type="primary" @click="openEditDialog">
|
|
|
<el-icon><Edit /></el-icon>
|
|
<el-icon><Edit /></el-icon>
|
|
|
修改并重新发布
|
|
修改并重新发布
|
|
@@ -593,6 +631,48 @@ function isCaptchaError(errorMessage: string | null | undefined): boolean {
|
|
|
return !!errorMessage && errorMessage.includes('CAPTCHA_REQUIRED');
|
|
return !!errorMessage && errorMessage.includes('CAPTCHA_REQUIRED');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 检查是否是"发布结果待确认,请查看截图"类错误
|
|
|
|
|
+function isScreenshotPendingError(errorMessage: string | null | undefined): boolean {
|
|
|
|
|
+ return !!errorMessage && errorMessage.includes('请查看截图');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 是否可以使用有头浏览器重新发布(目前主要用于小红书发布失败场景)
|
|
|
|
|
+function canRetryWithHeadful(row: { platform: string; status: string | null | undefined }): boolean {
|
|
|
|
|
+ return row.platform === 'xiaohongshu' && row.status === 'failed';
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 打开查看截图(小红书等平台暂打开创作者中心,用户可自行查看发布状态)
|
|
|
|
|
+function openScreenshotView(row: { platform: string; accountId: number }) {
|
|
|
|
|
+ if (row.platform === 'xiaohongshu') {
|
|
|
|
|
+ window.open('https://creator.xiaohongshu.com/publish/publish', '_blank', 'noopener,noreferrer');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.info('请前往对应平台查看发布状态');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 是否存在待确认的发布结果
|
|
|
|
|
+const hasPendingConfirmResults = computed(() => {
|
|
|
|
|
+ const results = taskDetail.value?.results || [];
|
|
|
|
|
+ return results.some(r => isScreenshotPendingError(r.errorMessage));
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 确认所有待确认的发布结果
|
|
|
|
|
+async function confirmAllPendingResults() {
|
|
|
|
|
+ if (!currentTask.value || !taskDetail.value?.results?.length) return;
|
|
|
|
|
+ const pending = taskDetail.value.results.filter(r => isScreenshotPendingError(r.errorMessage));
|
|
|
|
|
+ if (!pending.length) return;
|
|
|
|
|
+ try {
|
|
|
|
|
+ for (const r of pending) {
|
|
|
|
|
+ await request.post(`/api/publish/${currentTask.value.id}/results/${r.id}/confirm`);
|
|
|
|
|
+ }
|
|
|
|
|
+ ElMessage.success('已确认发布成功');
|
|
|
|
|
+ const detail = await request.get(`/api/publish/${currentTask.value.id}`);
|
|
|
|
|
+ taskDetail.value = detail;
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ ElMessage.error('确认失败');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 使用有头浏览器重新执行发布流程(用于验证码场景)
|
|
// 使用有头浏览器重新执行发布流程(用于验证码场景)
|
|
|
async function openBrowserForCaptcha(accountId: number, platform: string) {
|
|
async function openBrowserForCaptcha(accountId: number, platform: string) {
|
|
|
if (!currentTask.value) {
|
|
if (!currentTask.value) {
|
|
@@ -962,10 +1042,21 @@ onMounted(() => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.captcha-error {
|
|
|
|
|
|
|
+.captcha-error,
|
|
|
|
|
+.screenshot-pending {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
|
|
- gap: 4px;
|
|
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.normal-error {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.account-option {
|
|
.account-option {
|