diff --git a/apps/FrontendDesigner/src/components/disassembly/ImageWrapper.vue b/apps/FrontendDesigner/src/components/disassembly/ImageWrapper.vue new file mode 100644 index 0000000..5a946f0 --- /dev/null +++ b/apps/FrontendDesigner/src/components/disassembly/ImageWrapper.vue @@ -0,0 +1,377 @@ + + + + + \ No newline at end of file diff --git a/apps/FrontendDesigner/src/components/disassembly/README.md b/apps/FrontendDesigner/src/components/disassembly/README.md new file mode 100644 index 0000000..2781ed4 --- /dev/null +++ b/apps/FrontendDesigner/src/components/disassembly/README.md @@ -0,0 +1,126 @@ +# ImageWrapper 组件 + +## 组件概述 + +`ImageWrapper` 是一个用于展示拆件图片的可复用Vue组件,具有悬停交互、删除和生成模型功能。 + +## 文件位置 + +``` +src/components/disassembly/ImageWrapper.vue +``` + +## 功能特性 + +- ✅ 图片展示与预览 +- ✅ 鼠标悬停显示操作按钮 +- ✅ 删除图片功能 +- ✅ 生成模型功能 +- ✅ 响应式设计,适配移动端和桌面端 +- ✅ 平滑动画效果 +- ✅ Vue 3 Composition API 支持 + +## 组件参数 + +| 参数名 | 类型 | 必需 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `imageUrl` | String | ✅ | - | 图片地址 | +| `index` | Number | ✅ | - | 图片索引 | +| `hoveredIndex` | Number | ❌ | -1 | 当前悬停的图片索引 | +| `altText` | String | ❌ | '拆件图片' | 图片替代文本 | + +## 事件 + +| 事件名 | 参数 | 说明 | +|--------|------|------| +| `preview` | `imageUrl` | 点击图片预览时触发 | +| `delete` | `index` | 点击删除按钮时触发 | +| `generate-model` | `imageUrl` | 点击生成模型按钮时触发 | +| `show-actions` | `index` | 鼠标进入时触发 | +| `hide-actions` | - | 鼠标离开时触发 | + +## 使用示例 + +```vue + + + +``` + +## 样式特性 + +- **响应式设计**:适配移动端(<768px)、平板(768px-1024px)和桌面端(>1024px) +- **主题色彩**:使用项目主色调(深紫色 #6B46C1) +- **动画效果**:平滑的过渡动画(200ms缓入缓出) +- **悬停效果**:鼠标悬停时图片缩放和阴影效果 +- **按钮样式**:圆角设计(8px半径),微妙阴影 + +## 导入方式 + +```javascript +// 方式1:直接导入 +import ImageWrapper from '@/components/disassembly/ImageWrapper.vue' + +// 方式2:通过索引文件导入 +import { ImageWrapper } from '@/components/disassembly' +``` + +## 更新日志 + +### v1.0.0 (2025-12-10) +- 初始版本发布 +- 实现图片展示、悬停交互、删除和生成模型功能 +- 支持响应式设计 +- 完整的Vue 3 Composition API支持 \ No newline at end of file diff --git a/apps/FrontendDesigner/src/components/disassembly/index.js b/apps/FrontendDesigner/src/components/disassembly/index.js new file mode 100644 index 0000000..d864fd2 --- /dev/null +++ b/apps/FrontendDesigner/src/components/disassembly/index.js @@ -0,0 +1,2 @@ +// 导出 ImageWrapper 组件 +export { default as ImageWrapper } from './ImageWrapper.vue' \ No newline at end of file diff --git a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js index 294beb0..e7dced8 100644 --- a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js +++ b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js @@ -7,8 +7,10 @@ export class AdminDisassemblyDetail { async disassemble(imgurl,callback,errorCallback,config) { try{ const result = await gimiServer.handleGenerateImage(imgurl, prompt.Hairseparation,config) - console.log('resultresult',result); - callback(result) + // 检查任务状态 + gimiServer.getTaskGinimi(result.taskId,result.taskQueue,(imgurls)=>{ + callback(imgurls[0].uri); + },errorCallback); }catch(error){ errorCallback(error); } diff --git a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue index d888f1d..8cea282 100644 --- a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue +++ b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue @@ -66,7 +66,6 @@ type="primary" size="small" @click.stop="changePreviewImage" - :disabled="currentStep > 1" > {{ $t('admin.disassemblyOrders.detail.changePreview') }} @@ -102,39 +101,22 @@ >

{{ $t('admin.disassemblyOrders.detail.step2') }}

-
+
-
- - - - -
- - 生成模型 - -
-
+
{{ $t('admin.disassemblyOrders.detail.preview') }} {{ index + 1 }}
@@ -297,8 +279,9 @@ import { } from '@element-plus/icons-vue' import ModelViewer from '@/components/common/ModelViewer.vue' import ModelCom from '@/components/modelCom/index.vue' +import ImageWrapper from '@/components/disassembly/ImageWrapper.vue' import { AdminDisassemblyDetail } from './AdminDisassemblyDetail.js'; -import { MeshyServer } from '@deotaland/utils'; +import { MeshyServer,GiminiServer } from '@deotaland/utils'; const { t } = useI18n() const router = useRouter() const route = useRoute() @@ -317,6 +300,11 @@ const saveModel = (index,result,resultTask)=>{ generatedModels.value[index].taskId = result; generatedModels.value[index].resultTask = resultTask; } +const saveImage = (index,result)=>{ + disassembledImages.value[index].taskId = result.taskId; + disassembledImages.value[index].taskQueue = result.taskQueue; + disassembledImages.value[index].imageUrl = result.imageUrl; +} // 当前步骤 const currentStep = ref(1) @@ -338,14 +326,6 @@ const hoveredImageIndex = ref(-1) // 更换预览图相关 const showImageUpload = ref(false) const uploadLoading = ref(false) - - -// 模型加载状态管理 -const modelLoadingStates = ref([]) -const modelLoadingProgress = ref([]) -const modelInitializationStates = ref([]) -const modelInitializationProgress = ref([]) - // 资源路径 const thumbnailUrl = ref(''); const modelUrl = ref('') @@ -467,21 +447,21 @@ const startDisassembly = () => { } // 执行拆件 const handleDisassembly = () => { - disassemblyLoading.value = true - Plug.disassemble(thumbnailUrl.value,(result) => { - // 更新拆件图片 - disassembledImages.value.push(result) - if(currentStep.value==1){ - currentStep.value = 2 - } - disassemblyLoading.value = false - },(error) => { - disassemblyLoading.value = false - ElMessage.error('拆件失败,请稍后重试') - },{ - project_id:orderDetail.value.projectId, - role:'admin', - }) + const newItem = { + id: new Date().getTime(), + thumbnailUrl: thumbnailUrl.value, + imageUrl: '', + taskID: '', + taskQueue: '', + project_id: orderDetail.value.projectId, + }; + // disassembledImages.value = [] + // return + // 使用展开运算符创建新数组以确保响应式更新 + disassembledImages.value = [...disassembledImages.value, newItem]; + if(currentStep.value<=2){ + currentStep.value = 2; + } } @@ -526,6 +506,7 @@ const orderData = ref({}); // 组件挂载时获取订单信息 onMounted(async () => { MeshyServer.pollingEnabled = true; + GiminiServer.pollingEnabled = true; orderId.value = route.params.id const result = await adminOrders.getOrderDetail({ id:orderId.value @@ -562,6 +543,7 @@ onMounted(async () => { // 组件卸载时清理资源 onUnmounted(() => { MeshyServer.pollingEnabled = false; + GiminiServer.pollingEnabled = false; // 清理预览状态 imagePreviewVisible.value = false modelPreviewVisible.value = false @@ -569,25 +551,9 @@ onUnmounted(() => { // 删除图片 const deleteImage = (index) => { - ElMessageBox.confirm(t('admin.disassemblyOrders.detail.messages.confirmDelete'), t('admin.disassemblyOrders.detail.messages.confirmTitle'), { - confirmButtonText: t('admin.disassemblyOrders.detail.messages.confirm'), - cancelButtonText: t('admin.disassemblyOrders.detail.messages.cancel'), - type: 'warning' - }).then(() => { - disassembledImages.value.splice(index, 1) - ElMessage.success(t('admin.disassemblyOrders.detail.messages.deleteSuccess')) - }).catch(() => { - // 用户取消删除 - }) + // disassembledImages.value.splice(index, 1) } -// 生成第二步内容(添加新图片) -const handleGenerateStep2 = () => { - generateStep2Loading.value = true - // 模拟API调用 - disassembledImages.value.push(newImage) - generateStep2Loading.value = false -} // 显示图片操作按钮 const showImageActions = (index) => { @@ -600,15 +566,19 @@ const hideImageActions = () => { } // 从单张图片生成模型并进入第三步 const generateModelFromImage = async (image) => { -generatedModels.value.push({ - id:new Date().getTime(), - image:image, - taskId:'' -}); - // 如果是第一次生成模型,进入第三步 - if (currentStep.value < 3) { - currentStep.value = 3 - } + const newModel = { + id: new Date().getTime(), + image: image, + taskId: '' + }; + + // 使用展开运算符创建新数组以确保响应式更新 + generatedModels.value = [...generatedModels.value, newModel]; + + // 如果是第一次生成模型,进入第三步 + if (currentStep.value < 3) { + currentStep.value = 3 + } } @@ -1082,46 +1052,6 @@ generatedModels.value.push({ align-items: center; } -/* 图片包装器和删除按钮样式 */ -.image-wrapper { - position: relative; - display: block; - width: 100%; -} - -.delete-button { - position: absolute; - top: 8px; - right: 8px; - z-index: 10; - opacity: 0.9; - transition: all 0.2s ease; -} - -.delete-button:hover { - opacity: 1; - transform: scale(1.1); -} - -.generate-model-button-container { - position: absolute; - bottom: 8px; - left: 0; - right: 0; - display: flex; - justify-content: center; - z-index: 10; -} - -.generate-model-button { - opacity: 0.9; - transition: all 0.2s ease; -} - -.generate-model-button:hover { - opacity: 1; -} - /* 上传容器样式 */ .upload-container { display: flex; diff --git a/apps/FrontendDesigner/vite.config.js b/apps/FrontendDesigner/vite.config.js index 8314b9d..04fecfa 100644 --- a/apps/FrontendDesigner/vite.config.js +++ b/apps/FrontendDesigner/vite.config.js @@ -34,7 +34,8 @@ export default defineConfig({ // 配置代理解决CORS问题 proxy: { '/api': { - target: 'https://api.deotaland.ai', + // target: 'https://api.deotaland.ai', + target: 'http://192.168.0.174:9000', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } diff --git a/apps/frontend/src/assets/home/center.png b/apps/frontend/src/assets/home/center.png index c86ed5b..af42c6c 100644 Binary files a/apps/frontend/src/assets/home/center.png and b/apps/frontend/src/assets/home/center.png differ diff --git a/apps/frontend/src/assets/home/center3.png b/apps/frontend/src/assets/home/center3.png index b6a7de7..1783f1c 100644 Binary files a/apps/frontend/src/assets/home/center3.png and b/apps/frontend/src/assets/home/center3.png differ diff --git a/apps/frontend/src/assets/home/center4.png b/apps/frontend/src/assets/home/center4.png index 90c502d..66f7e64 100644 Binary files a/apps/frontend/src/assets/home/center4.png and b/apps/frontend/src/assets/home/center4.png differ diff --git a/apps/frontend/src/assets/home/center5.png b/apps/frontend/src/assets/home/center5.png index 2cf847d..643c363 100644 Binary files a/apps/frontend/src/assets/home/center5.png and b/apps/frontend/src/assets/home/center5.png differ diff --git a/apps/frontend/src/assets/home/center6.png b/apps/frontend/src/assets/home/center6.png index 5351c7f..b2b2a62 100644 Binary files a/apps/frontend/src/assets/home/center6.png and b/apps/frontend/src/assets/home/center6.png differ diff --git a/apps/frontend/src/assets/home/center9.png b/apps/frontend/src/assets/home/center9.png index 8d483e9..f2f6c72 100644 Binary files a/apps/frontend/src/assets/home/center9.png and b/apps/frontend/src/assets/home/center9.png differ diff --git a/apps/frontend/src/assets/material/cz2.png b/apps/frontend/src/assets/material/cz2.png new file mode 100644 index 0000000..6510c7c Binary files /dev/null and b/apps/frontend/src/assets/material/cz2.png differ diff --git a/apps/frontend/src/assets/sketches/cjt.png b/apps/frontend/src/assets/sketches/cjt.png new file mode 100644 index 0000000..5be71fd Binary files /dev/null and b/apps/frontend/src/assets/sketches/cjt.png differ diff --git a/apps/frontend/src/assets/sketches/dwww.png b/apps/frontend/src/assets/sketches/dwww.png index 8ed69ff..b3d394a 100644 Binary files a/apps/frontend/src/assets/sketches/dwww.png and b/apps/frontend/src/assets/sketches/dwww.png differ diff --git a/apps/frontend/src/assets/sketches/dwww2.png b/apps/frontend/src/assets/sketches/dwww2.png new file mode 100644 index 0000000..86817d2 Binary files /dev/null and b/apps/frontend/src/assets/sketches/dwww2.png differ diff --git a/apps/frontend/src/assets/sketches/tcww2.png b/apps/frontend/src/assets/sketches/tcww2.png new file mode 100644 index 0000000..f43f88f Binary files /dev/null and b/apps/frontend/src/assets/sketches/tcww2.png differ diff --git a/apps/frontend/src/components/HeaderComponent/HeaderComponent.vue b/apps/frontend/src/components/HeaderComponent/HeaderComponent.vue index 9d4b1d8..596633a 100644 --- a/apps/frontend/src/components/HeaderComponent/HeaderComponent.vue +++ b/apps/frontend/src/components/HeaderComponent/HeaderComponent.vue @@ -74,17 +74,22 @@ import { Picture, MagicStick, ArrowLeft, Edit, Check, Guide } from '@element-plu import { ElButton, ElIcon, ElInput } from 'element-plus' import ThemeToggle from '../ui/ThemeToggle.vue' import LanguageToggle from '../ui/LanguageToggle.vue' + const emit = defineEmits(['openGuideModal']) const props = defineProps({ + freeImageCount: { + type: Number, + default: 0 + }, + freeModelCount: { + type: Number, + default: 0 + }, projectName: { type: String, default: 'project' } }) -// 生图免费次数(模拟数据) -const freeImageCount = ref(5) -// 模型免费次数(模拟数据) -const freeModelCount = ref(3) // 编辑相关状态 const isEditing = ref(false) const editedProjectName = ref('') diff --git a/apps/frontend/src/components/IPCard/index.vue b/apps/frontend/src/components/IPCard/index.vue index cee51a7..914b638 100644 --- a/apps/frontend/src/components/IPCard/index.vue +++ b/apps/frontend/src/components/IPCard/index.vue @@ -49,11 +49,11 @@
-
+
- @@ -66,9 +66,13 @@ --> - + +
-
{{ t('modelCard.loadingModelText') }}
+
{{ 'loadingModel' }}
{{ Math.round(loadingProgress) }}%
@@ -310,7 +310,7 @@ const loadModel = (url) => { (xhr) => { const progress = (xhr.loaded / xhr.total) * 100; loadingProgress.value = progress; - console.log(progress + '% loaded'); + // console.log(progress + '% loaded'); }, // 加载错误回调 (error) => { diff --git a/apps/frontend/src/components/iPandCardLeft/index.vue b/apps/frontend/src/components/iPandCardLeft/index.vue index 89db64f..a8376fc 100644 --- a/apps/frontend/src/components/iPandCardLeft/index.vue +++ b/apps/frontend/src/components/iPandCardLeft/index.vue @@ -296,7 +296,7 @@ const formData = ref({ const textareaRef = ref(null); const fileInput = ref(null); // 文件输入引用 -const generateCount = ref(4); // 生成数量,默认为1 +const generateCount = ref(1); // 生成数量,默认为1 const isOptimizing = ref(false); // 优化状态 const isDragOver = ref(false); // 拖拽状态 const isUploading = ref(false); // 图片上传状态 diff --git a/apps/frontend/src/router/index.js b/apps/frontend/src/router/index.js index 5615a52..d51936f 100644 --- a/apps/frontend/src/router/index.js +++ b/apps/frontend/src/router/index.js @@ -1,7 +1,7 @@ import { createRouter, createWebHistory,createWebHashHistory} from 'vue-router' import { useAuthStore } from '@/stores/auth' import NProgress from 'nprogress' -const ModernHome = () => import('../views/ModernHome.vue') +const ModernHome = () => import('../views/ModernHome/ModernHome.vue') const List = () => import('../views/List.vue') const Login = () => import('../views/Login/Login.vue') const Register = () => import('../views/Register.vue') @@ -131,8 +131,10 @@ const router = createRouter({ // 路由守卫 router.beforeEach(async (to, from, next) => { NProgress.start() - // window.localStorage.setItem('token','123') - // return next() + if(window.location.hostname=='localhost'){ + window.localStorage.setItem('token','123') + return next() + } if (to.meta.requiresAuth) { const token = localStorage.getItem('token') // 如果没有 token,跳转到登录页 diff --git a/apps/frontend/src/views/ModernHome.vue b/apps/frontend/src/views/ModernHome/ModernHome.vue similarity index 86% rename from apps/frontend/src/views/ModernHome.vue rename to apps/frontend/src/views/ModernHome/ModernHome.vue index 68f909f..1aad35a 100644 --- a/apps/frontend/src/views/ModernHome.vue +++ b/apps/frontend/src/views/ModernHome/ModernHome.vue @@ -77,7 +77,6 @@
-
@@ -88,7 +87,7 @@ :style="{ '--delay': index * 0.1 + 's' }" >
- +
@@ -98,7 +97,7 @@
{{ stat.label }}
- + {{ stat.trendValue }}
@@ -107,14 +106,15 @@
-