From 604ce985bd04183d72eb85c18233ba3ec159986e Mon Sep 17 00:00:00 2001 From: GeekMaster Date: Fri, 8 Aug 2025 18:01:42 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8D=B3=E6=A2=A6AI=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/commands/frontend-developer.md | 37 +++ JIMENG_CONFIG_README.md | 195 --------------- api/handler/jimeng_handler.go | 6 - web/src/assets/css/mobile/jimeng.scss | 101 ++++++++ web/src/store/mobile/jimeng.js | 319 ++++++++++++++++--------- web/src/store/mobile/suno.js | 33 ++- web/src/views/mobile/JimengCreate.vue | 109 +++++---- web/src/views/mobile/SunoCreate.vue | 25 +- 8 files changed, 424 insertions(+), 401 deletions(-) create mode 100644 .claude/commands/frontend-developer.md delete mode 100644 JIMENG_CONFIG_README.md diff --git a/.claude/commands/frontend-developer.md b/.claude/commands/frontend-developer.md new file mode 100644 index 00000000..0285b526 --- /dev/null +++ b/.claude/commands/frontend-developer.md @@ -0,0 +1,37 @@ +--- +name: frontend-developer +description: Use this agent when you need assistance with frontend development tasks including Vue.js components, UI implementation, styling, responsive design, state management, or frontend architecture decisions. Examples: Context: User is working on a Vue.js component and needs help with implementing a responsive layout. user: 'I need to create a mobile-friendly chat interface component' assistant: 'I'll use the frontend-developer agent to help design and implement this responsive chat component' Since this involves frontend development work with Vue.js and responsive design, use the frontend-developer agent. Context: User encounters styling issues with Element Plus components. user: 'The Element Plus dialog is not displaying correctly on mobile devices' assistant: 'Let me use the frontend-developer agent to troubleshoot this mobile styling issue' This is a frontend styling problem that requires expertise in Element Plus and responsive design. +color: purple +--- + +You are a Senior Frontend Development Engineer with deep expertise in modern web development technologies, particularly Vue.js 3, Element Plus, Vant, and responsive design patterns. You specialize in creating high-quality, maintainable frontend applications with excellent user experience. + +Your core responsibilities include: +- Developing Vue.js 3 components using Composition API and best practices +- Implementing responsive designs that work seamlessly across desktop and mobile devices +- Working with Element Plus for desktop UI and Vant for mobile components +- Managing application state using Pinia store patterns +- Styling with Stylus preprocessor and Tailwind CSS utilities +- Optimizing build processes with Vite and ensuring proper code organization +- Implementing theme switching (dark/light mode) and accessibility features +- Follow decoupled development, with HTML, CSS, and JS codes placed in separate files for easier maintenance + +When working on frontend tasks, you will: +1. Analyze requirements and suggest the most appropriate Vue.js patterns and component structures +2. Ensure responsive design principles are followed, considering both desktop and mobile viewports +3. Choose appropriate UI components from Element Plus (desktop) or Vant (mobile) libraries +4. Write clean, maintainable code following Vue.js 3 Composition API best practices +5. Consider performance implications and suggest optimizations when relevant +6. Ensure proper state management using Pinia when component state needs to be shared +7. Follow the project's established patterns for routing, API integration, and component organization +8. Provide specific code examples and explain the reasoning behind architectural decisions + +You have deep knowledge of: +- Vue.js 3 ecosystem (Vue Router, Pinia, Composition API) +- Modern CSS techniques and preprocessors (Stylus, Tailwind) +- Component library integration (Element Plus, Vant) +- Build tools and development workflow (Vite, npm scripts) +- Cross-browser compatibility and mobile-first design principles +- Performance optimization and code splitting strategies + +Always consider the user experience, code maintainability, and alignment with modern frontend development standards. When suggesting solutions, provide clear explanations and consider both immediate needs and long-term scalability. diff --git a/JIMENG_CONFIG_README.md b/JIMENG_CONFIG_README.md deleted file mode 100644 index 9ac0975c..00000000 --- a/JIMENG_CONFIG_README.md +++ /dev/null @@ -1,195 +0,0 @@ -# 即梦 AI 配置功能说明 - -## 功能概述 - -即梦 AI 配置功能允许管理员通过 Web 界面配置即梦 AI 的 API 密钥和算力消耗设置,支持动态配置更新,无需重启服务。 - -## 功能特性 - -### 1. 秘钥配置 - -- AccessKey 和 SecretKey 配置 -- 支持密码显示/隐藏 -- 连接测试功能 - -### 2. 算力配置 - -- 文生图算力消耗 -- 图生图算力消耗 -- 图片编辑算力消耗 -- 图片特效算力消耗 -- 文生视频算力消耗 -- 图生视频算力消耗 - -### 3. 动态配置 - -- 配置实时生效 -- 无需重启服务 -- 支持配置验证 - -## API 接口 - -### 获取配置 - -``` -GET /api/admin/jimeng/config -``` - -### 更新配置 - -``` -POST /api/admin/jimeng/config -Content-Type: application/json - -{ - "config": { - "access_key": "your_access_key", - "secret_key": "your_secret_key", - "power": { - "text_to_image": 10, - "image_to_image": 15, - "image_edit": 20, - "image_effects": 25, - "text_to_video": 30, - "image_to_video": 35 - } - } -} -``` - -### 测试连接 - -``` -POST /api/admin/jimeng/config/test -Content-Type: application/json - -{ - "config": { - "access_key": "your_access_key", - "secret_key": "your_secret_key" - } -} -``` - -## 前端页面 - -### 访问路径 - -管理后台 -> 即梦 AI -> 配置设置 - -### 页面功能 - -1. **秘钥配置标签页** - - - AccessKey 输入框(密码模式) - - SecretKey 输入框(密码模式) - - 测试连接按钮 - -2. **算力配置标签页** - - - 各种任务类型的算力消耗配置 - - 数字输入框,支持 1-100 范围 - - 提示信息说明 - -3. **操作按钮** - - 保存配置 - - 重置配置 - -## 配置存储 - -配置存储在数据库的`config`表中: - -- 配置键:`jimeng` -- 配置值:JSON 格式的即梦 AI 配置 - -## 默认配置 - -如果配置不存在,系统会使用以下默认值: - -```json -{ - "access_key": "", - "secret_key": "", - "power": { - "text_to_image": 10, - "image_to_image": 15, - "image_edit": 20, - "image_effects": 25, - "text_to_video": 30, - "image_to_video": 35 - } -} -``` - -## 使用流程 - -1. **初始配置** - - - 访问管理后台即梦 AI 配置页面 - - 填写 AccessKey 和 SecretKey - - 点击"测试连接"验证配置 - - 调整各功能算力消耗 - - 保存配置 - -2. **配置更新** - - - 修改需要更新的配置项 - - 保存配置 - - 配置立即生效 - -3. **故障排查** - - 使用"测试连接"功能验证 API 密钥 - - 检查配置是否正确保存 - - 查看服务日志 - -## 注意事项 - -1. **权限要求** - - - 只有管理员可以访问配置页面 - - 需要有效的管理员登录会话 - -2. **配置验证** - - - AccessKey 和 SecretKey 不能为空 - - 算力消耗必须大于 0 - - 建议先测试连接再保存配置 - -3. **服务影响** - - 配置更新不会影响正在进行的任务 - - 新任务会使用更新后的配置 - - 客户端配置会在下次请求时更新 - -## 错误处理 - -1. **配置加载失败** - - - 使用默认配置 - - 记录错误日志 - -2. **连接测试失败** - - - 显示具体错误信息 - - 建议检查 API 密钥 - -3. **配置保存失败** - - 显示错误信息 - - 保留原有配置 - -## 开发说明 - -### 后端文件 - -- `api/handler/admin/jimeng_handler.go` - 配置管理 API -- `api/service/jimeng/service.go` - 配置服务逻辑 -- `api/core/types/jimeng.go` - 配置类型定义 - -### 前端文件 - -- `web/src/views/admin/jimeng/JimengSetting.vue` - 配置页面 - -### 数据库 - -- `config`表存储配置信息 -- 配置键:`jimeng` -- 配置值:JSON 格式 diff --git a/api/handler/jimeng_handler.go b/api/handler/jimeng_handler.go index f095d3c9..9cc0dc68 100644 --- a/api/handler/jimeng_handler.go +++ b/api/handler/jimeng_handler.go @@ -181,9 +181,6 @@ func (h *JimengHandler) CreateTask(c *gin.Context) { taskType = model.JMTaskTypeTextToVideo reqKey = jimeng.ReqKeyTextToVideo modelName = "即梦文生视频" - if req.Seed == 0 { - req.Seed = -1 - } if req.AspectRatio == "" { req.AspectRatio = jimeng.AspectRatio16_9 } @@ -196,9 +193,6 @@ func (h *JimengHandler) CreateTask(c *gin.Context) { taskType = model.JMTaskTypeImageToVideo reqKey = jimeng.ReqKeyImageToVideo modelName = "即梦图生视频" - if req.Seed == 0 { - req.Seed = -1 - } params = map[string]any{ "seed": req.Seed, "aspect_ratio": req.AspectRatio, diff --git a/web/src/assets/css/mobile/jimeng.scss b/web/src/assets/css/mobile/jimeng.scss index 7134f2c8..382cdff4 100644 --- a/web/src/assets/css/mobile/jimeng.scss +++ b/web/src/assets/css/mobile/jimeng.scss @@ -775,6 +775,107 @@ } } } + + /* 快捷操作按钮样式 */ + &__works-item-quick-actions { + display: flex; + gap: 8px; + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid #f3f4f6; + } + + &__works-item-quick-action-btn { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: none; + border-radius: 8px; + background: #f9fafb; + color: #6b7280; + cursor: pointer; + transition: all 0.2s ease; + font-size: 14px; + + &:hover { + background: #e5e7eb; + color: #374151; + transform: translateY(-1px); + } + + &:active { + transform: translateY(0); + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + } + + &--danger { + color: #ef4444; + + &:hover { + background: #fef2f2; + color: #dc2626; + } + } + + i { + font-size: 16px; + } + } + + /* 错误信息样式 */ + &__works-item-error { + margin-top: 8px; + padding: 8px 12px; + background: #fef2f2; + border: 1px solid #fecaca; + border-radius: 8px; + } + + &__works-item-error-content { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + } + + &__works-item-error-text { + flex: 1; + font-size: 12px; + color: #dc2626; + line-height: 1.4; + word-break: break-all; + } + + &__works-item-error-copy-btn { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border: none; + border-radius: 4px; + background: #fee2e2; + color: #dc2626; + cursor: pointer; + transition: all 0.2s ease; + font-size: 12px; + + &:hover { + background: #fecaca; + color: #b91c1c; + } + + i { + font-size: 12px; + } + } } /* 旋转动画 */ diff --git a/web/src/store/mobile/jimeng.js b/web/src/store/mobile/jimeng.js index e247533b..fcef03fb 100644 --- a/web/src/store/mobile/jimeng.js +++ b/web/src/store/mobile/jimeng.js @@ -1,8 +1,8 @@ -import { closeLoading, showLoading, showMessageError, showMessageOK } from '@/utils/dialog' +import { showMessageError, showMessageOK } from '@/utils/dialog' import { httpGet, httpPost } from '@/utils/http' import { defineStore } from 'pinia' import { showConfirmDialog } from 'vant' -import { computed, ref } from 'vue' +import { computed, reactive, ref, watch } from 'vue' export const useJimengStore = defineStore('mobile-jimeng', () => { // 响应式数据 @@ -22,6 +22,16 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { const taskPulling = ref(true) const tastPullHandler = ref(null) + // 新增:算力配置 + const powerConfig = ref({ + text_to_image: 20, + image_to_image: 30, + image_edit: 25, + image_effects: 15, + text_to_video: 100, + image_to_video: 120, + }) + // 功能分类 const categories = ref([ { key: 'image_generation', name: '图像生成' }, @@ -115,35 +125,45 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { ] // 功能参数 - const textToImageParams = ref({ - size: '1024x1024', - scale: 7.5, - use_pre_llm: false, + // 各功能的参数 + const textToImageParams = reactive({ + size: '1328x1328', + scale: 2.5, + seed: -1, + use_pre_llm: true, }) - const imageToImageParams = ref({ - image_input: [], - size: '1024x1024', + const imageToImageParams = reactive({ + image_input: '', + size: '1328x1328', + gpen: 0.4, + skin: 0.3, + skin_unifi: 0, + gen_mode: 'creative', + seed: -1, }) - const imageEditParams = ref({ - image_urls: [], + const imageEditParams = reactive({ + image_urls: '', scale: 0.5, + seed: -1, }) - const imageEffectsParams = ref({ - image_input1: [], + const imageEffectsParams = reactive({ + image_input1: '', template_id: '', - size: '1024x1024', + size: '1328x1328', }) - const textToVideoParams = ref({ + const textToVideoParams = reactive({ aspect_ratio: '16:9', + seed: -1, }) - const imageToVideoParams = ref({ + const imageToVideoParams = reactive({ image_urls: [], aspect_ratio: '16:9', + seed: -1, }) // 计算属性 @@ -152,12 +172,29 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { return useImageInput.value ? 'image_to_image' : 'text_to_image' } else if (activeCategory.value === 'image_editing') { return 'image_edit' + } else if (activeCategory.value === 'image_effects') { + return 'image_effects' } else if (activeCategory.value === 'video_generation') { return useImageInput.value ? 'image_to_video' : 'text_to_video' } return 'text_to_image' }) + // 新增:动态计算当前算力消耗 + const updateCurrentPowerCost = () => { + const functionKey = activeFunction.value + currentPowerCost.value = powerConfig.value[functionKey] || 10 + } + + // 监听任务类型变化,自动更新算力 + watch( + [activeCategory, useImageInput], + () => { + updateCurrentPowerCost() + }, + { immediate: true } + ) + // Actions const getCategoryIcon = (category) => { const iconMap = { @@ -174,52 +211,17 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { useImageInput.value = false } - const switchInputMode = () => { - currentPrompt.value = '' - } - - const handleMultipleImageUpload = (event) => { - const files = Array.from(event.target.files) - files.forEach((file) => { - if (imageToVideoParams.value.image_urls.length < 2) { - onImageUpload({ file, name: file.name }) + // 新增:获取算力配置 + const fetchPowerConfig = async () => { + try { + const res = await httpGet('/api/jimeng/power-config') + if (res.data) { + powerConfig.value = res.data + updateCurrentPowerCost() // 更新当前算力消耗 } - }) - } - - const removeImage = (index) => { - imageToVideoParams.value.image_urls.splice(index, 1) - } - - const onImageUpload = (file) => { - const formData = new FormData() - formData.append('file', file.file, file.name) - showLoading('正在上传图片...') - - return httpPost('/api/upload', formData) - .then((res) => { - showMessageOK('图片上传成功') - const imageData = { url: res.data.url, content: res.data.url } - - // 根据当前活动功能添加到相应的参数中 - if (activeFunction.value === 'image_to_image') { - imageToImageParams.value.image_input = [imageData] - } else if (activeFunction.value === 'image_edit') { - imageEditParams.value.image_urls = [imageData] - } else if (activeFunction.value === 'image_effects') { - imageEffectsParams.value.image_input1 = [imageData] - } else if (activeFunction.value === 'image_to_video') { - imageToVideoParams.value.image_urls.push(imageData) - } - - return res.data.url - }) - .catch((e) => { - showMessageError('图片上传失败:' + e.message) - }) - .finally(() => { - closeLoading() - }) + } catch (error) { + console.error('获取算力配置失败:', error) + } } const submitTask = () => { @@ -229,27 +231,62 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { } submitting.value = true - const params = { - type: activeFunction.value, - prompt: currentPrompt.value, - } - + let requestData = { task_type: activeFunction.value, prompt: currentPrompt.value } // 根据功能类型添加相应参数 - if (activeFunction.value === 'text_to_image') { - Object.assign(params, textToImageParams.value) - } else if (activeFunction.value === 'image_to_image') { - Object.assign(params, imageToImageParams.value) - } else if (activeFunction.value === 'image_edit') { - Object.assign(params, imageEditParams.value) - } else if (activeFunction.value === 'image_effects') { - Object.assign(params, imageEffectsParams.value) - } else if (activeFunction.value === 'text_to_video') { - Object.assign(params, textToVideoParams.value) - } else if (activeFunction.value === 'image_to_video') { - Object.assign(params, imageToVideoParams.value) + switch (activeFunction.value) { + case 'text_to_image': + Object.assign(requestData, { + width: parseInt(textToImageParams.size.split('x')[0]), + height: parseInt(textToImageParams.size.split('x')[1]), + scale: textToImageParams.scale, + seed: textToImageParams.seed, + use_pre_llm: textToImageParams.use_pre_llm, + }) + break + case 'image_to_image': + Object.assign(requestData, { + image_input: imageToImageParams.image_input, + width: parseInt(imageToImageParams.size.split('x')[0]), + height: parseInt(imageToImageParams.size.split('x')[1]), + gpen: imageToImageParams.gpen, + skin: imageToImageParams.skin, + skin_unifi: imageToImageParams.skin_unifi, + gen_mode: imageToImageParams.gen_mode, + seed: imageToImageParams.seed, + }) + break + case 'image_edit': + Object.assign(requestData, { + image_urls: [imageEditParams.image_urls], + scale: imageEditParams.scale, + seed: imageEditParams.seed, + }) + break + case 'image_effects': + Object.assign(requestData, { + image_input: imageEffectsParams.image_input1, + template_id: imageEffectsParams.template_id, + width: parseInt(imageEffectsParams.size.split('x')[0]), + height: parseInt(imageEffectsParams.size.split('x')[1]), + prompt: imageEffectsParams.prompt, + }) + break + case 'text_to_video': + Object.assign(requestData, { + aspect_ratio: textToVideoParams.aspect_ratio, + seed: textToVideoParams.seed, + }) + break + case 'image_to_video': + Object.assign(requestData, { + image_urls: imageToVideoParams.image_urls, + aspect_ratio: imageToVideoParams.aspect_ratio, + seed: imageToVideoParams.seed, + }) + break } - return httpPost('/api/jimeng/create', params) + return httpPost('/api/jimeng/task', requestData) .then(() => { fetchData(1) taskPulling.value = true @@ -333,7 +370,7 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { }) } - const removeJob = (item) => { + const removeJob = async (item) => { return showConfirmDialog({ title: '确认删除', message: '此操作将会删除任务相关文件,继续操作吗?', @@ -383,39 +420,94 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { } } - const resetParams = () => { - textToImageParams.value = { - size: '1024x1024', - scale: 7.5, - use_pre_llm: false, - } - imageToImageParams.value = { - image_input: [], - size: '1024x1024', - } - imageEditParams.value = { - image_urls: [], - scale: 0.5, - } - imageEffectsParams.value = { - image_input1: [], - template_id: '', - size: '1024x1024', - } - textToVideoParams.value = { - aspect_ratio: '16:9', - } - imageToVideoParams.value = { - image_urls: [], - aspect_ratio: '16:9', - } - } - const closeMediaDialog = () => { showMediaDialog.value = false currentMediaUrl.value = '' } + // 新增:画同款功能 + const drawSame = (item) => { + // 设置当前提示词 + currentPrompt.value = item.prompt + + // 根据任务类型设置相应的参数 + switch (item.type) { + case 'text_to_image': + activeCategory.value = 'image_generation' + useImageInput.value = false + // 设置图片尺寸(如果有的话) + if (item.width && item.height) { + textToImageParams.size = `${item.width}x${item.height}` + } + break + case 'image_to_image': + activeCategory.value = 'image_generation' + useImageInput.value = true + // 设置图片尺寸(如果有的话) + if (item.width && item.height) { + imageToImageParams.size = `${item.width}x${item.height}` + } + break + case 'image_edit': + activeCategory.value = 'image_editing' + break + case 'image_effects': + activeCategory.value = 'image_effects' + // 设置特效模板(如果有的话) + if (item.template_id) { + imageEffectsParams.template_id = item.template_id + } + break + case 'text_to_video': + activeCategory.value = 'video_generation' + useImageInput.value = false + // 设置视频比例(如果有的话) + if (item.aspect_ratio) { + textToVideoParams.aspect_ratio = item.aspect_ratio + } + break + case 'image_to_video': + activeCategory.value = 'video_generation' + useImageInput.value = true + // 设置视频比例(如果有的话) + if (item.aspect_ratio) { + imageToVideoParams.aspect_ratio = item.aspect_ratio + } + break + } + + showMessageOK('已设置画同款参数') + } + + // 新增:复制提示词功能 + const copyPrompt = (prompt) => { + navigator.clipboard + .writeText(prompt) + .then(() => { + showMessageOK('提示词已复制') + }) + .catch(() => { + showMessageError('复制失败') + }) + } + + // 新增:复制错误信息功能 + const copyErrorMsg = (msg) => { + navigator.clipboard + .writeText(msg) + .then(() => { + showMessageOK('错误信息已复制') + }) + .catch(() => { + showMessageError('复制失败') + }) + } + + // 新增:初始化方法 + const init = async () => { + await fetchPowerConfig() + } + return { // State activeCategory, @@ -443,6 +535,7 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { imageEffectsParams, textToVideoParams, imageToVideoParams, + powerConfig, // Computed activeFunction, @@ -450,10 +543,6 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { // Actions getCategoryIcon, switchCategory, - switchInputMode, - handleMultipleImageUpload, - removeImage, - onImageUpload, submitTask, fetchData, loadMore, @@ -465,7 +554,11 @@ export const useJimengStore = defineStore('mobile-jimeng', () => { getTaskType, startTaskPolling, stopTaskPolling, - resetParams, closeMediaDialog, + fetchPowerConfig, + drawSame, + copyPrompt, + copyErrorMsg, + init, } }) diff --git a/web/src/store/mobile/suno.js b/web/src/store/mobile/suno.js index c701f06a..6d10ef9c 100644 --- a/web/src/store/mobile/suno.js +++ b/web/src/store/mobile/suno.js @@ -1,10 +1,10 @@ -import { defineStore } from 'pinia' -import { ref, reactive } from 'vue' -import { checkSession } from '@/store/cache' +import { getSystemInfo } from '@/store/cache' import { closeLoading, showLoading, showToastMessage } from '@/utils/dialog' import { httpDownload, httpGet, httpPost } from '@/utils/http' import { replaceImg } from '@/utils/libs' -import { getSystemInfo } from '@/store/cache' +import { defineStore } from 'pinia' +import { showConfirmDialog } from 'vant' +import { reactive, ref } from 'vue' export const useSunoStore = defineStore('suno', () => { // 状态 @@ -35,7 +35,6 @@ export const useSunoStore = defineStore('suno', () => { const uploadRef = ref(null) const isGenerating = ref(false) const deleting = ref(false) - const deleteItem = ref(null) const models = ref([ { label: 'v3.0', value: 'chirp-v3-0' }, { label: 'v3.5', value: 'chirp-v3-5' }, @@ -287,10 +286,25 @@ export const useSunoStore = defineStore('suno', () => { item.downloading = false }) } - const showDeleteDialog = (item) => { - deleteItem.value = item - // 这里建议在页面层处理弹窗,store 只负责数据和业务 + + const removeJob = (item) => { + showConfirmDialog({ + title: '确认删除', + message: '此操作将会删除任务相关文件,继续操作吗?', + confirmButtonText: '确认删除', + cancelButtonText: '取消', + }).then(() => { + httpGet('/api/suno/remove', { id: item.id }) + .then(() => { + showToastMessage('任务删除成功', 'success') + fetchData(1) + }) + .catch(() => { + showToastMessage('任务删除失败', 'error') + }) + }) } + const extend = (item) => { refSong.value = item refSong.value.extend_secs = item.duration @@ -324,7 +338,6 @@ export const useSunoStore = defineStore('suno', () => { uploadRef, isGenerating, deleting, - deleteItem, models, tags, page, @@ -346,7 +359,7 @@ export const useSunoStore = defineStore('suno', () => { refreshFirstPage, play, download, - showDeleteDialog, + removeJob, extend, removeRefSong, } diff --git a/web/src/views/mobile/JimengCreate.vue b/web/src/views/mobile/JimengCreate.vue index 4523719f..2154dcbd 100644 --- a/web/src/views/mobile/JimengCreate.vue +++ b/web/src/views/mobile/JimengCreate.vue @@ -49,11 +49,7 @@
图生图人像写真 - +
@@ -284,9 +280,9 @@ - - -
- -
- -
+
- -
-
+ +
+ + + + + + + + + + + + + +
+ + +
+
+ {{ item.err_msg }}
-
@@ -515,6 +517,7 @@ const handleTemplateChange = (value) => { onMounted(() => { checkSession() .then(() => { + jimengStore.init() // 初始化算力配置 jimengStore.fetchData(1) jimengStore.startTaskPolling() }) diff --git a/web/src/views/mobile/SunoCreate.vue b/web/src/views/mobile/SunoCreate.vue index 00b5a845..b8cc3540 100644 --- a/web/src/views/mobile/SunoCreate.vue +++ b/web/src/views/mobile/SunoCreate.vue @@ -388,7 +388,7 @@