|
@@ -23,7 +23,7 @@
|
|
|
auto-height
|
|
auto-height
|
|
|
/>
|
|
/>
|
|
|
<view class="input-actions">
|
|
<view class="input-actions">
|
|
|
- <button class="action-btn ai-btn" @click="showAIModal">
|
|
|
|
|
|
|
+ <button class="action-btn ai-btn" @click="goToAIPage">
|
|
|
<text>🤖 AI 生成</text>
|
|
<text>🤖 AI 生成</text>
|
|
|
</button>
|
|
</button>
|
|
|
<button class="action-btn" @click="clearText">清空</button>
|
|
<button class="action-btn" @click="clearText">清空</button>
|
|
@@ -104,45 +104,14 @@
|
|
|
<text class="btn-text">{{ generating ? '生成中...' : '生成音频' }}</text>
|
|
<text class="btn-text">{{ generating ? '生成中...' : '生成音频' }}</text>
|
|
|
</button>
|
|
</button>
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
- <!-- AI 生成弹窗 -->
|
|
|
|
|
- <view v-if="showAiModal" class="ai-modal-mask" @click="closeAiModal">
|
|
|
|
|
- <view class="ai-modal" @click.stop>
|
|
|
|
|
- <view class="ai-modal-header">
|
|
|
|
|
- <text class="ai-modal-title">🤖 AI 智能生成</text>
|
|
|
|
|
- <text class="ai-modal-close" @click="closeAiModal">×</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="ai-modal-content">
|
|
|
|
|
- <textarea
|
|
|
|
|
- v-model="aiPrompt"
|
|
|
|
|
- class="ai-prompt-input"
|
|
|
|
|
- placeholder="输入你想了解的内容,例如:计算机原理是什么?什么是人工智能?"
|
|
|
|
|
- :maxlength="500"
|
|
|
|
|
- />
|
|
|
|
|
- <view class="ai-prompt-hint">
|
|
|
|
|
- <text>AI 将根据你的输入生成相关文本,可直接用于生成音频</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="ai-modal-footer">
|
|
|
|
|
- <button class="ai-cancel-btn" @click="closeAiModal">取消</button>
|
|
|
|
|
- <button
|
|
|
|
|
- class="ai-confirm-btn"
|
|
|
|
|
- :disabled="!aiPrompt.trim() || aiGenerating"
|
|
|
|
|
- @click="handleAIGenerate"
|
|
|
|
|
- >
|
|
|
|
|
- <text>{{ aiGenerating ? '生成中...' : '生成文本' }}</text>
|
|
|
|
|
- </button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref, computed, onMounted } from 'vue';
|
|
import { ref, computed, onMounted } from 'vue';
|
|
|
|
|
+import { onShow } from '@dcloudio/uni-app';
|
|
|
import { useUserStore } from '../../store/user';
|
|
import { useUserStore } from '../../store/user';
|
|
|
import { useAudioStore } from '../../store/audio';
|
|
import { useAudioStore } from '../../store/audio';
|
|
|
-import { post } from '../../utils/request';
|
|
|
|
|
import type { VoiceParams } from '../../types';
|
|
import type { VoiceParams } from '../../types';
|
|
|
|
|
|
|
|
const userStore = useUserStore();
|
|
const userStore = useUserStore();
|
|
@@ -157,9 +126,6 @@ const voiceParams = ref<VoiceParams>({
|
|
|
volume: 50,
|
|
volume: 50,
|
|
|
});
|
|
});
|
|
|
const generating = ref(false);
|
|
const generating = ref(false);
|
|
|
-const aiGenerating = ref(false);
|
|
|
|
|
-const aiPrompt = ref('');
|
|
|
|
|
-const showAiModal = ref(false);
|
|
|
|
|
|
|
|
|
|
// 计算属性
|
|
// 计算属性
|
|
|
const canGenerate = computed(() => {
|
|
const canGenerate = computed(() => {
|
|
@@ -171,6 +137,16 @@ onMounted(async () => {
|
|
|
await audioStore.fetchVoices();
|
|
await audioStore.fetchVoices();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+// 页面显示时检查是否有 AI 生成的文本
|
|
|
|
|
+onShow(() => {
|
|
|
|
|
+ const aiText = uni.getStorageSync('ai_generated_text');
|
|
|
|
|
+ if (aiText) {
|
|
|
|
|
+ text.value = aiText;
|
|
|
|
|
+ uni.removeStorageSync('ai_generated_text');
|
|
|
|
|
+ uni.showToast({ title: '已填充 AI 生成的文本', icon: 'success' });
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
// 清空文本
|
|
// 清空文本
|
|
|
function clearText() {
|
|
function clearText() {
|
|
|
text.value = '';
|
|
text.value = '';
|
|
@@ -184,44 +160,9 @@ async function pasteText() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// AI 生成文本
|
|
|
|
|
-async function handleAIGenerate() {
|
|
|
|
|
- if (!aiPrompt.value.trim()) {
|
|
|
|
|
- uni.showToast({ title: '请输入想了解的内容', icon: 'none' });
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- aiGenerating.value = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const result = await post<{ text: string }>('/ai/generate', {
|
|
|
|
|
- prompt: aiPrompt.value,
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 将生成的文本填充到输入框
|
|
|
|
|
- text.value = result.text;
|
|
|
|
|
- aiPrompt.value = '';
|
|
|
|
|
-
|
|
|
|
|
- // 关闭弹窗
|
|
|
|
|
- showAiModal.value = false;
|
|
|
|
|
-
|
|
|
|
|
- uni.showToast({ title: '已生成文本', icon: 'success' });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- console.error('AI 生成失败:', error);
|
|
|
|
|
- uni.showToast({ title: error.message || 'AI 生成失败', icon: 'none' });
|
|
|
|
|
- } finally {
|
|
|
|
|
- aiGenerating.value = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 显示 AI 生成弹窗
|
|
|
|
|
-function showAIModal() {
|
|
|
|
|
- aiPrompt.value = '';
|
|
|
|
|
- showAiModal.value = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 关闭 AI 生成弹窗
|
|
|
|
|
-function closeAiModal() {
|
|
|
|
|
- showAiModal.value = false;
|
|
|
|
|
|
|
+// 跳转到 AI 生成页面
|
|
|
|
|
+function goToAIPage() {
|
|
|
|
|
+ uni.navigateTo({ url: '/pages/ai/index' });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 生成音频
|
|
// 生成音频
|
|
@@ -444,108 +385,6 @@ async function handleGenerate() {
|
|
|
color: #ffffff;
|
|
color: #ffffff;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* AI 弹窗样式 */
|
|
|
|
|
-.ai-modal-mask {
|
|
|
|
|
- position: fixed;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- bottom: 0;
|
|
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
- z-index: 1000;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- padding: 32rpx;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- background: #ffffff;
|
|
|
|
|
- border-radius: 24rpx;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal-header {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
- padding: 32rpx;
|
|
|
|
|
- border-bottom: 1rpx solid #f3f4f6;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal-title {
|
|
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
- color: #1f2937;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal-close {
|
|
|
|
|
- font-size: 48rpx;
|
|
|
|
|
- color: #9ca3af;
|
|
|
|
|
- line-height: 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal-content {
|
|
|
|
|
- padding: 32rpx;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-prompt-input {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 200rpx;
|
|
|
|
|
- padding: 24rpx;
|
|
|
|
|
- background: #f9fafb;
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
- font-size: 28rpx;
|
|
|
|
|
- color: #1f2937;
|
|
|
|
|
- line-height: 1.6;
|
|
|
|
|
- box-sizing: border-box;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-prompt-hint {
|
|
|
|
|
- margin-top: 16rpx;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-prompt-hint text {
|
|
|
|
|
- font-size: 22rpx;
|
|
|
|
|
- color: #9ca3af;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-modal-footer {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 24rpx;
|
|
|
|
|
- padding: 32rpx;
|
|
|
|
|
- border-top: 1rpx solid #f3f4f6;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-cancel-btn,
|
|
|
|
|
-.ai-confirm-btn {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- height: 80rpx;
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
- font-size: 28rpx;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-cancel-btn {
|
|
|
|
|
- background: #f3f4f6;
|
|
|
|
|
- color: #6b7280;
|
|
|
|
|
- border: none;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-confirm-btn {
|
|
|
|
|
- background: linear-gradient(135deg, #4f46e5 0%, #818cf8 100%);
|
|
|
|
|
- color: #ffffff;
|
|
|
|
|
- border: none;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ai-confirm-btn[disabled] {
|
|
|
|
|
- background: #e5e7eb;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.ai-btn {
|
|
.ai-btn {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|