fix: 修复问题

This commit is contained in:
2026-01-18 02:15:08 +08:00
parent aa81a1aebc
commit 961e4bcc77
15 changed files with 1652 additions and 1103 deletions

View File

@@ -9,6 +9,7 @@ import GmIcon from '@/components/icons/Icon.vue'
import { UserPromptApi } from '@/api/userPrompt'
import { useUserStore } from '@/stores/user'
import GradientButton from '@/components/GradientButton.vue'
import PromptSelector from '@/components/PromptSelector.vue'
import { setJSON, getJSON } from '@/utils/storage'
import BasicLayout from '@/layouts/components/BasicLayout.vue'
@@ -38,28 +39,10 @@ const { getVoiceText } = useVoiceText()
// 提示词相关状态
const allPrompts = ref([])
const loadingPrompts = ref(false)
const showAllPromptsModal = ref(false)
const selectedPromptId = ref(null)
const promptSearchKeyword = ref('')
const DISPLAY_COUNT = 6 // 展示的提示词数量
// 计算属性:展示的部分提示词
const displayPrompts = computed(() => {
return allPrompts.value.slice(0, DISPLAY_COUNT)
})
// 计算属性:过滤后的全部提示词(用于"更多"弹窗)
const filteredPrompts = computed(() => {
if (!promptSearchKeyword.value.trim()) {
return allPrompts.value
}
const keyword = promptSearchKeyword.value.trim().toLowerCase()
return allPrompts.value.filter(p =>
p.name.toLowerCase().includes(keyword) ||
(p.content && p.content.toLowerCase().includes(keyword))
)
})
/**
* 加载用户提示词列表
* 从服务器获取当前用户的提示词,并按创建时间倒序排列
@@ -88,9 +71,6 @@ async function loadUserPrompts() {
const timeB = b.createTime ? new Date(b.createTime).getTime() : 0
return timeB - timeA
})
// 如果用户没有选择提示词,尝试恢复本地存储的选中项或默认选中第一个
await restoreOrSelectPrompt()
} else {
throw new Error(response?.msg || response?.message || '加载失败')
}
@@ -102,97 +82,17 @@ async function loadUserPrompts() {
}
}
/**
* 保存选中的提示词ID到本地存储
*/
async function saveSelectedPromptId(promptId) {
if (promptId) {
await setJSON('copywriting_selected_prompt_id', promptId)
}
}
/**
* 从本地存储恢复选中的提示词ID
*/
async function loadSelectedPromptId() {
try {
const savedId = await getJSON('copywriting_selected_prompt_id', null)
return savedId
} catch (error) {
console.error('加载保存的提示词ID失败:', error)
return null
}
}
/**
* 根据ID选中提示词
*/
async function selectPromptById(promptId) {
if (!promptId) return false
const prompt = allPrompts.value.find(p => p.id === promptId)
if (prompt && prompt.content) {
selectedPromptId.value = prompt.id
form.value.prompt = prompt.content
promptStore.setPrompt(prompt.content, prompt)
await saveSelectedPromptId(promptId)
return true
}
return false
}
/**
* 恢复或选中提示词
* 优先级:本地存储的选中项 > 第一个提示词
*/
async function restoreOrSelectPrompt() {
if (allPrompts.value.length === 0) {
return false
}
// 如果已经有选中项且内容存在,不需要重新选择
if (selectedPromptId.value && form.value.prompt) {
// 验证选中的提示词是否还在列表中
const currentPrompt = allPrompts.value.find(p => p.id === selectedPromptId.value)
if (currentPrompt && currentPrompt.content === form.value.prompt) {
return true // 已经正确选中,无需操作
}
}
// 尝试恢复本地存储的选中项
const savedPromptId = await loadSelectedPromptId()
if (savedPromptId) {
const restored = await selectPromptById(savedPromptId)
if (restored) {
return true // 成功恢复保存的选中项
}
}
// 如果没有保存的选中项或恢复失败,则选中第一个
const firstPrompt = allPrompts.value[0]
if (firstPrompt?.content) {
selectedPromptId.value = firstPrompt.id
form.value.prompt = firstPrompt.content
promptStore.setPrompt(firstPrompt.content, firstPrompt)
await saveSelectedPromptId(firstPrompt.id)
return true
}
return false
}
// 选择提示词
async function selectPrompt(prompt) {
// 处理提示词选择
function handlePromptChange(prompt) {
if (!prompt || !prompt.content) {
message.warning('提示词内容为空')
return
}
selectedPromptId.value = prompt.id
form.value.prompt = prompt.content
promptStore.setPrompt(prompt.content, prompt)
await saveSelectedPromptId(prompt.id)
showAllPromptsModal.value = false
}
@@ -217,7 +117,7 @@ async function waitForUserInfo() {
async function ensureUserInfoLoaded() {
const isLoggedIn = userStore.isLoggedIn
const hasNoUserId = !userStore.userId
if (isLoggedIn && hasNoUserId) {
try {
await userStore.fetchUserInfo()
@@ -239,13 +139,13 @@ async function initializePage() {
if (promptStore.currentPrompt) {
form.value.prompt = promptStore.currentPrompt
}
// 2. 等待用户信息初始化完成
await waitForUserInfo()
// 3. 确保用户信息已加载
await ensureUserInfoLoaded()
// 4. 加载提示词列表
await loadUserPrompts()
}
@@ -255,34 +155,11 @@ onMounted(() => {
initializePage()
})
/**
* keep-alive 激活时的处理
* 1. 如果有提示词列表,尝试恢复或选中提示词
* 2. 如果没有提示词列表但用户已登录,加载提示词列表
*/
onActivated(async () => {
// 如果已经有提示词列表,尝试恢复或选中提示词
if (allPrompts.value.length > 0) {
await restoreOrSelectPrompt()
}
// 如果提示词列表为空,但用户已登录,则尝试加载
else if (userStore.userId) {
await loadUserPrompts()
}
// 如果用户未登录,等待用户信息加载
else if (!userStore.userId && userStore.isLoggedIn) {
await ensureUserInfoLoaded()
if (userStore.userId) {
await loadUserPrompts()
}
}
})
// 监听 userId 变化:如果之前没有 userId现在有了则自动加载提示词
watch(() => userStore.userId, async (newUserId, oldUserId) => {
const userIdChanged = newUserId && !oldUserId
const hasNoPrompts = allPrompts.value.length === 0
if (userIdChanged && hasNoPrompts) {
await loadUserPrompts()
}
@@ -510,47 +387,25 @@ defineOptions({ name: 'ContentStyleCopywriting' })
<a-form :model="form" layout="vertical" class="form-container">
<a-form-item class="form-item">
<template #label>
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>
选择提示词风格
<span class="form-tip-inline">从已保存的提示词中选择</span>
</span>
<a-space>
<a-button
size="small"
type="link"
@click="showAllPromptsModal = true"
:disabled="allPrompts.length === 0">
更多 ({{ allPrompts.length }})
</a-button>
</a-space>
</div>
<span>
选择提示词风格
<span class="form-tip-inline">从已保存的提示词中选择</span>
</span>
</template>
<!-- 提示词标签展示区域 -->
<div v-if="displayPrompts.length > 0" class="prompt-tags-container">
<div class="prompt-tags-grid">
<div
v-for="prompt in displayPrompts"
:key="prompt.id"
class="prompt-tag"
:class="{ 'prompt-tag-selected': selectedPromptId === prompt.id }"
@click="selectPrompt(prompt)">
<span class="prompt-tag-name">{{ prompt.name }}</span>
</div>
</div>
</div>
<!-- 使用 PromptSelector 组件 -->
<PromptSelector
v-model="selectedPromptId"
:prompts="allPrompts"
:loading="loadingPrompts"
:search-keyword="promptSearchKeyword"
@change="handlePromptChange"
@update:searchKeyword="promptSearchKeyword = $event"
/>
<!-- 空状态 -->
<div v-else-if="!loadingPrompts" class="prompt-empty">
<div style="color: var(--color-text-secondary); font-size: 14px; text-align: center; padding: 20px;">
您可以在视频分析页面保存风格
</div>
</div>
<!-- 加载状态 -->
<div v-else class="prompt-loading">
<a-spin size="small" />
<!-- 空状态提示 -->
<div v-if="!loadingPrompts && allPrompts.length === 0" class="prompt-empty" style="color: var(--color-text-secondary); font-size: 14px; text-align: center; padding: 20px;">
您可以在视频分析页面保存风格
</div>
</a-form-item>
@@ -664,58 +519,6 @@ defineOptions({ name: 'ContentStyleCopywriting' })
</a-row>
</div>
<!-- 更多提示词弹窗 -->
<a-modal
v-model:open="showAllPromptsModal"
title="选择提示词"
:width="800"
:maskClosable="false"
>
<div class="all-prompts-modal">
<!-- 搜索框 -->
<a-input
v-model:value="promptSearchKeyword"
placeholder="搜索提示词名称或内容..."
allow-clear
style="margin-bottom: 16px;"
>
<template #prefix>
<GmIcon name="icon-search" :size="16" />
</template>
</a-input>
<!-- 提示词列表(标签形式) -->
<div v-if="filteredPrompts.length > 0" class="all-prompts-tags">
<div
v-for="prompt in filteredPrompts"
:key="prompt.id"
class="all-prompt-tag"
:class="{ 'all-prompt-tag-selected': selectedPromptId === prompt.id }"
@click="selectPrompt(prompt)"
>
<span class="all-prompt-tag-name">{{ prompt.name }}</span>
</div>
</div>
<!-- 空状态 -->
<div v-else style="text-align: center; padding: 40px; color: var(--color-text-secondary);">
没有找到匹配的提示词
</div>
</div>
<template #footer>
<a-space>
<a-button @click="showAllPromptsModal = false">取消</a-button>
<a-button
type="primary"
@click="loadUserPrompts"
:loading="loadingPrompts"
>
刷新列表
</a-button>
</a-space>
</template>
</a-modal>
</BasicLayout>
</template>