diff --git a/apps/FrontendDesigner/.env.development b/apps/FrontendDesigner/.env.development index 5cd5fd5..c5413b7 100644 --- a/apps/FrontendDesigner/.env.development +++ b/apps/FrontendDesigner/.env.development @@ -1,4 +1,24 @@ -# 开发环境配置 +# 生产环境配置 VITE_BASE_URL=/api -VITE_DEV_MODE=true -VITE_LOG_LEVEL=info \ No newline at end of file +VITE_PROJECTTYPE=admin +# Vercel 部署环境变量配置示例 +# 复制此文件为 .env.local 并填入实际值 + +# Google AI API Key(用于 AI 功能) +VITE_GOOGLE_API_KEY=your_google_api_key_here + + +# Stripe 支付配置 +VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key + +# 应用配置 +VITE_APP_TITLE=DeotalandAI +VITE_APP_DESCRIPTION=AI-Powered Creation Platform + +# 开发环境配置 +VITE_DEV_MODE=false +VITE_LOG_LEVEL=error + +# 生产环境配置(在 Vercel 中设置) +# NODE_ENV=production +# VERCEL=true \ No newline at end of file diff --git a/apps/FrontendDesigner/.env.example b/apps/FrontendDesigner/.env.production similarity index 58% rename from apps/FrontendDesigner/.env.example rename to apps/FrontendDesigner/.env.production index 7d859f1..1789adf 100644 --- a/apps/FrontendDesigner/.env.example +++ b/apps/FrontendDesigner/.env.production @@ -1,11 +1,12 @@ -# 生产环境配置 -VITE_BASE_URL=https://api.deotaland.ai -# Vercel 部署环境变量配置示例 -# 复制此文件为 .env.local 并填入实际值 - +# 开发环境变量配置 # Google AI API Key(用于 AI 功能) VITE_GOOGLE_API_KEY=your_google_api_key_here +VITE_PROJECTTYPE=admin +# 基础API地址(生产环境) +VITE_BASE_URL=https://api.deotaland.ai +# 基础API地址(备用) +VITE_APP_BASE_API=https://api.deotaland.ai # Stripe 支付配置 VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key @@ -15,9 +16,5 @@ VITE_APP_TITLE=DeotalandAI VITE_APP_DESCRIPTION=AI-Powered Creation Platform # 开发环境配置 -VITE_DEV_MODE=false -VITE_LOG_LEVEL=error - -# 生产环境配置(在 Vercel 中设置) -# NODE_ENV=production -# VERCEL=true \ No newline at end of file +VITE_DEV_MODE=true +VITE_LOG_LEVEL=debug \ No newline at end of file diff --git a/apps/FrontendDesigner/src/App.vue b/apps/FrontendDesigner/src/App.vue index db947b3..84ffbc2 100644 --- a/apps/FrontendDesigner/src/App.vue +++ b/apps/FrontendDesigner/src/App.vue @@ -151,6 +151,11 @@ onUnmounted(() => { \ 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 f374616..294beb0 100644 --- a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js +++ b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.js @@ -4,9 +4,9 @@ export class AdminDisassemblyDetail { constructor() { } //拆件 - async disassemble(imgurl,callback,errorCallback) { + async disassemble(imgurl,callback,errorCallback,config) { try{ - const result = await gimiServer.handleGenerateImage(imgurl, prompt.Hairseparation) + const result = await gimiServer.handleGenerateImage(imgurl, prompt.Hairseparation,config) console.log('resultresult',result); callback(result) }catch(error){ diff --git a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue index dc68526..83ae8a9 100644 --- a/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue +++ b/apps/FrontendDesigner/src/views/admin/AdminDisassemblyDetail/AdminDisassemblyDetail.vue @@ -39,9 +39,9 @@
进度
-
+
- {{ currentStep }}/4 + {{ currentStep }}/3
@@ -58,7 +58,7 @@
-
+
缩略图
{{ $t('admin.disassemblyOrders.detail.preview') }}
@@ -84,8 +84,8 @@ {{ $t('admin.disassemblyOrders.detail.disassembly') }} @@ -152,22 +152,25 @@
模型 {{ index + 1 }}
-
+
- @@ -230,7 +233,7 @@
- + -->
@@ -276,9 +279,10 @@ @@ -497,6 +439,7 @@ onMounted(() => { padding: 8px 12px; white-space: nowrap; vertical-align: middle; + text-align: center !important; } .disassembly-table :deep(.el-table__row) { @@ -513,7 +456,7 @@ onMounted(() => { font-weight: 600; border-bottom: 2px solid #e5e7eb; white-space: nowrap !important; - text-align: center; + text-align: center !important; text-overflow: ellipsis; overflow: hidden; } @@ -523,6 +466,15 @@ onMounted(() => { word-break: keep-all; overflow: hidden; text-overflow: ellipsis; + text-align: center !important; +} + +/* 表格内容居中 */ +.disassembly-table :deep(.el-table__body td .cell) { + text-align: center !important; + display: flex; + align-items: center; + justify-content: center; } /* 操作按钮容器 */ @@ -531,13 +483,26 @@ onMounted(() => { gap: 6px; flex-wrap: nowrap; align-items: center; - justify-content: flex-start; + justify-content: center; overflow: hidden; } .actions-container .el-button { flex-shrink: 0; white-space: nowrap; + min-width: 80px; +} + +/* 完成拆件按钮样式 */ +.actions-container .el-button--success { + background: linear-gradient(135deg, #10b981 0%, #059669 100%); + border: none; + transition: all 0.3s ease; +} + +.actions-container .el-button--success:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4); } /* 分页样式 */ @@ -595,6 +560,19 @@ onMounted(() => { .disassembly-table :deep(.el-table) { min-width: 800px; } + + /* 移动端操作按钮适配 */ + .actions-container { + flex-direction: column; + gap: 8px; + align-items: stretch; + } + + .actions-container .el-button { + width: 100%; + min-width: auto; + margin: 0; + } } @media (min-width: 769px) and (max-width: 1024px) { diff --git a/apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.js b/apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.js new file mode 100644 index 0000000..a3512f6 --- /dev/null +++ b/apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.js @@ -0,0 +1,73 @@ +import { adminApi,requestUtils} from '@deotaland/utils'; + +export class AdminOrders { + constructor() { + // 初始化防抖函数 + this.debouncedSaveProgress = this.createDebouncedSaveProgress(); + } + + /** + * 创建防抖的保存进度函数 + * 防止频繁调用API,延迟1秒执行 + */ + createDebouncedSaveProgress() { + let timeout; + return (params) => { + return new Promise((resolve, reject) => { + clearTimeout(timeout); + timeout = setTimeout(async () => { + try { + const result = await requestUtils.common(adminApi.default.updateOrderStatus, params); + resolve(result); + } catch (error) { + reject(error); + } + }, 1000); // 1秒防抖延迟 + }); + }; + } + //获取订单详情 + getOrderDetail(params){ + return requestUtils.common(adminApi.default.getOrderDetailt,params); + } + //获取订单列表 + getOrderList(params){ + return requestUtils.common(adminApi.default.getOrderList,params); + } + //同意退款 + refundApprove(params){ + return requestUtils.common(adminApi.default.refundApprove,params); + } + //拒绝退款 + refundReject(params){ + return requestUtils.common(adminApi.default.refundReject,params); + } + //同意/拒绝订单 + updateOrderStatus(type=0,audit_reject_reason='',data){//0未通过,1已通过 + let params = { + id:data.id, + order_status:type==0?1:2 + } + if(audit_reject_reason&&type==0){ + params.audit_reject_reason = audit_reject_reason; + } + return requestUtils.common(adminApi.default.updateOrderStatus,params); + } + //完成拆件 + completeDisassembly(data){ + let params = { + order_status:3, + id:data.id + } + return requestUtils.common(adminApi.default.updateOrderStatus,params); + } + //订单统计 + getOrderStatistics(){ + return requestUtils.common(adminApi.default.getOrderStatistics); + } + //保存拆件进度(带防抖功能) + saveDisassemblyProgress(params){ + // 使用防抖函数来避免频繁调用API + return this.debouncedSaveProgress(params); + } +} \ No newline at end of file diff --git a/apps/FrontendDesigner/src/views/admin/AdminOrders.vue b/apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.vue similarity index 57% rename from apps/FrontendDesigner/src/views/admin/AdminOrders.vue rename to apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.vue index 37fb73d..a4d8eec 100644 --- a/apps/FrontendDesigner/src/views/admin/AdminOrders.vue +++ b/apps/FrontendDesigner/src/views/admin/AdminOrders/AdminOrders.vue @@ -37,7 +37,7 @@
-
¥{{ orderStats.revenue.toLocaleString() }}
+
¥{{ orderStats.revenue }}
{{ t('admin.orders.stats.revenue') }}
@@ -52,31 +52,11 @@ clearable > - - - - - - -
-
+
- + - - - + + + + + - - + + - + @@ -189,26 +170,37 @@

{{ t('admin.orders.basicInfo') }}

- {{ selectedOrder.orderNumber }} + {{ selectedOrder.order_no }} - {{ selectedOrder.customerName }} + {{ selectedOrder?.order_info?.shipping?.firstName || '-'+selectedOrder?.order_info?.shipping?.lastName || '-' }} - ¥{{ selectedOrder.totalAmount.toFixed(2) }} + ¥{{ selectedOrder?.actual_amount?.toFixed(2) || '-' }} - - {{ t(`admin.orders.statusOptions.${selectedOrder.status}`) }} + + {{ t(`${getStatusTagType(selectedOrder).label}`) }}
-

{{ t('admin.orders.items') }}

- + + + + + + +
+ Preview Image +
+
- {{ selectedOrderForAction.orderNumber }} + {{ selectedOrderForAction.order_no }} - {{ selectedOrderForAction.customerName }} + {{ selectedOrderForAction?.order_info?.shipping?.firstName || '-' }} {{ selectedOrderForAction?.order_info?.shipping?.lastName || '-' }} - - {{ t(`admin.orders.statusOptions.${selectedOrderForAction.status}`) }} - + + {{ t(`${getStatusTagType(selectedOrderForAction).label}`) }} + - + - {{ t('admin.orders.availableActions') }} -
{{ t('admin.orders.view') }} - + + + {{ t('admin.disassemblyOrders.list.disassembly') }} + {{ t('admin.orders.process') }} - {{ t('admin.orders.ship') }} - - \ No newline at end of file diff --git a/apps/frontend/.env.development b/apps/frontend/.env.development index 2a780af..34ad534 100644 --- a/apps/frontend/.env.development +++ b/apps/frontend/.env.development @@ -1,12 +1,13 @@ # 开发环境变量配置 # Google AI API Key(用于 AI 功能) VITE_GOOGLE_API_KEY=your_google_api_key_here - +VITE_PROJECTTYPE=client # 基础API地址(生产环境) -VITE_BASE_URL=https://api.deotaland.ai +VITE_BASE_URL=/api +# VITE_BASE_URL=http://192.168.0.174:9000 # 基础API地址(备用) -VITE_APP_BASE_API=https://api.deotaland.ai +VITE_APP_BASE_API=/api # Stripe 支付配置 VITE_STRIPE_PUBLISHABLE_KEY=pk_test_51SUf06BzlmfuPpixQn3nBDvLcO2qTyeqseM1wcwPcTfGo2Rivggc0axNbFyPrVCfoKIfWuuzIeBzUQl3Fn4Hz0Ea008vLhvv5g diff --git a/apps/frontend/.env.production b/apps/frontend/.env.production index e266716..bdd1bb5 100644 --- a/apps/frontend/.env.production +++ b/apps/frontend/.env.production @@ -1,5 +1,6 @@ # 生产环境配置 VITE_BASE_URL=https://api.deotaland.ai +VITE_PROJECTTYPE=client # Vercel 部署环境变量配置示例 # 复制此文件为 .env.local 并填入实际值 diff --git a/apps/frontend/index.html b/apps/frontend/index.html index cfdb16f..671666a 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -4,7 +4,6 @@ - @@ -12,7 +11,6 @@
- diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 6344829..fbb22da 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -14,6 +14,9 @@ "@element-plus/icons-vue": "^2.3.2", "@google/genai": "^1.27.0", "@stripe/stripe-js": "^4.8.0", + "@twind/core": "^1.1.3", + "@twind/preset-autoprefix": "^1.0.7", + "@twind/preset-tailwind": "^1.1.4", "@types/three": "^0.180.0", "@vuelidate/core": "^2.0.3", "@vuelidate/validators": "^2.0.4", @@ -24,7 +27,9 @@ "jose": "^6.1.1", "normalize.css": "^8.0.1", "pinia": "^3.0.4", + "pinia-plugin-persistedstate": "^4.7.1", "three": "^0.180.0", + "twind": "^0.16.19", "vue": "^3.5.24", "vue-countup-v3": "^1.4.2", "vue-i18n": "^11.1.12", @@ -34,7 +39,11 @@ }, "devDependencies": { "@iconify-json/feather": "^1.2.1", + "@tailwindcss/postcss": "^4.1.17", "@vitejs/plugin-vue": "^6.0.1", + "autoprefixer": "^10.4.22", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.17", "terser": "^5.44.1", "unplugin-auto-import": "^20.2.0", "unplugin-icons": "^22.5.0", diff --git a/apps/frontend/postcss.config.js b/apps/frontend/postcss.config.js new file mode 100644 index 0000000..af9d8dc --- /dev/null +++ b/apps/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/apps/frontend/src/App.vue b/apps/frontend/src/App.vue index bd3ffed..e86549a 100644 --- a/apps/frontend/src/App.vue +++ b/apps/frontend/src/App.vue @@ -9,10 +9,10 @@ const route = useRoute() const isLoginPage = computed(() => route.path === '/login') // 判断当前是否为全屏页面 const isFullScreenPage = computed(() => route.meta.fullScreen) - +// 判断当前是否为首页 +const isHomePage = computed(() => route.path === '/') // Reactive theme state const themeState = ref(false) - // Initialize theme state from localStorage and DOM function initializeTheme() { if (typeof window !== 'undefined') { @@ -39,15 +39,18 @@ onMounted(() => {
+
+ +
\ No newline at end of file diff --git a/apps/frontend/src/components/auth/ForgotPasswordForm.vue b/apps/frontend/src/components/auth/ForgotPasswordForm.vue index 458f495..3a36fa7 100644 --- a/apps/frontend/src/components/auth/ForgotPasswordForm.vue +++ b/apps/frontend/src/components/auth/ForgotPasswordForm.vue @@ -319,7 +319,6 @@ export default { emit('reset-success', state.email) }) } catch (error) { - ElMessage.error(t('forgotPassword.reset_processing_error')) } finally { state.isSubmitting = false } diff --git a/apps/frontend/src/components/auth/GoogleOAuthButton.vue b/apps/frontend/src/components/auth/GoogleOAuthButton.vue index 7037320..a868c4d 100644 --- a/apps/frontend/src/components/auth/GoogleOAuthButton.vue +++ b/apps/frontend/src/components/auth/GoogleOAuthButton.vue @@ -94,7 +94,6 @@ const loginWithidToken = async (idToken) => { const res = await requestUtils.common(clientApi.default.OAUTH_GOOGLE,{ googleIdToken:idToken }) - if(res.code === 200){ // 登录成功,保存token和用户信息 let data = res.data; authStore.loginSuccess(data,()=>{ @@ -103,7 +102,6 @@ const loginWithidToken = async (idToken) => { return emit('success', res.data.user) return res - } return res } catch (error) { console.error('登录失败:', error) @@ -189,15 +187,13 @@ onMounted(() => { height: 18px; flex-shrink: 0; } - /* 按钮文字 */ .button-text { - flex: 1; + /* flex: 1; */ text-align: center; font-weight: 500; letter-spacing: 0.025em; } - /* 加载状态指示器 */ .loading-spinner { position: absolute; diff --git a/apps/frontend/src/components/auth/RegisterForm.vue b/apps/frontend/src/components/auth/RegisterForm.vue index 6ebe6e4..0d59da0 100644 --- a/apps/frontend/src/components/auth/RegisterForm.vue +++ b/apps/frontend/src/components/auth/RegisterForm.vue @@ -48,7 +48,7 @@ type="button" class="send-code-button" @click="handleSendVerificationCode" - :disabled="isCodeSending" + :disabled="isCodeSending || countdown > 0" :class="{ 'countdown-active': countdown > 0 }" > {{ countdown }}s @@ -213,10 +213,8 @@ const validateEmail = () => { const validatePassword = () => { if (!form.value.password) { passwordError.value = t('register.password_empty_error') - } else if (form.value.password.length < 8) { + } else if (form.value.password.length < 6) { passwordError.value = t('register.password_min_error') - } else if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(form.value.password)) { - passwordError.value = t('register.password_complexity_error') } else { passwordError.value = '' } @@ -247,7 +245,7 @@ const handleRegister = () => { emailCode: form.value.verificationCode, password: form.value.password },()=>{ - // emit('success') + emit('success') }) } diff --git a/apps/frontend/src/components/iPandCardLeft/index.vue b/apps/frontend/src/components/iPandCardLeft/index.vue index 1a6ed1b..c344a3e 100644 --- a/apps/frontend/src/components/iPandCardLeft/index.vue +++ b/apps/frontend/src/components/iPandCardLeft/index.vue @@ -261,6 +261,8 @@ import { ElMessage } from 'element-plus'; import cz1 from '../../assets/material/cz1.jpg' import humanTypeImg from '../../assets/sketches/tcww.png' import animalTypeImg from '../../assets/sketches/dwww.png' +import { FileServer } from '@deotaland/utils'; +const filePlug = new FileServer(); // 定义事件 const emit = defineEmits(['image-generated', 'model-generated', 'generate-requested', 'import-character', 'navigate-back', 'updateProjectInfo']); const props = defineProps({ @@ -692,13 +694,15 @@ const triggerFileUpload = () => { const handleFileChange = async (event) => { const file = event.target.files?.[0]; if (file) { - console.log('待上传文件:', file); + const imgUrl = await filePlug.uploadFile(file) + // console.log('待上传文件:', file); // 创建本地图片预览URL - const reader = new FileReader(); - reader.onload = (e) => { - formData.value.previewImage = e.target.result; - }; - reader.readAsDataURL(file); + // const reader = new FileReader(); + // reader.onload = (e) => { + formData.value.previewImage = imgUrl; + // }; + // reader.readAsDataURL(file); + } }; diff --git a/apps/frontend/src/components/layout/AppHeader.vue b/apps/frontend/src/components/layout/AppHeader.vue index 24f8683..a43196c 100644 --- a/apps/frontend/src/components/layout/AppHeader.vue +++ b/apps/frontend/src/components/layout/AppHeader.vue @@ -47,21 +47,21 @@
- + - {{ currentUser.name || currentUser.email }} + {{ currentUser.nickname || currentUser.email }}