diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md
index 747f7f5..b8e3ef0 100644
--- a/.trae/rules/project_rules.md
+++ b/.trae/rules/project_rules.md
@@ -29,13 +29,7 @@
移动端兼容 iOS 13+、Android 8+;桌面端兼容 Chrome 80+、Firefox 75+、Edge 80+;平板端覆盖主流设备(iPadOS、Android 平板)。
避免使用 ES6 + 以上高级语法(或通过 Babel 转译),确保低版本浏览器兼容性。
12.设计风格
-- 主色调:深紫色(#6B46C1)用于主要操作,浅紫色(#A78BFA)用于强调
-- 辅助色:深灰色(#1F2937)用于文本,浅灰色(#F3F4F6)用于背景
-- 按钮样式:圆角设计(8px半径),微妙阴影,悬停效果
-- 字体排版:Inter字体系列,16px基础大小,响应式缩放
-- 布局风格:基于卡片的设计,统一间距(8px网格系统)
-- 图标风格:Feather图标库,UI元素统一24px大小
-- 动画效果:平滑过渡(200ms缓入缓出),加载骨架屏
+- 粘土拟态风格
13.交付标准
代码结构清晰,遵循 Vue3 最佳实践(如组件拆分粒度合理、逻辑与 UI 分离)。
提供完整的多端测试报告(说明在不同设备 / 尺寸下的测试结果及适配方案)。
diff --git a/README.md b/README.md
index 11a1478..7a8b6f9 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@
deotaland-ai-monorepo/
├── apps/
│ └── frontend/ # 主前端应用
+│ └── FrontendDesigner/ # 管理端应用
├── packages/ # 共享包目录
├── .eslintrc.base.json # 基础ESLint配置
├── .prettierrc # Prettier配置
diff --git a/apps/FrontendDesigner/src/locales/lang/en-US.js b/apps/FrontendDesigner/src/locales/lang/en-US.js
index 04b95bb..5db09b9 100644
--- a/apps/FrontendDesigner/src/locales/lang/en-US.js
+++ b/apps/FrontendDesigner/src/locales/lang/en-US.js
@@ -270,6 +270,7 @@ export default {
promptManagement: 'Prompt Management',
productManagement: 'Product Management',
voucherManagement: 'Voucher Management',
+ operationLog: 'Operation Log',
logout: 'Logout',
profile: 'Profile',
settings: 'Settings'
@@ -929,6 +930,21 @@ export default {
hint: {
userIds: 'Multiple user IDs separated by commas, e.g.: 1,2,3'
}
+ },
+ operationLog: {
+ title: 'Operation Log',
+ adminUserId: 'Admin User ID',
+ adminUsername: 'Admin Username',
+ operationType: 'Operation Type',
+ all: 'All',
+ resourceType: 'Resource Type',
+ resourceId: 'Resource ID',
+ description: 'Description',
+ ipAddress: 'IP Address',
+ userAgent: 'User Agent',
+ createdAt: 'Created At',
+ detailTitle: 'Operation Log Detail',
+ getListFailed: 'Failed to get operation log list'
}
},
modelUpload: {
diff --git a/apps/FrontendDesigner/src/locales/lang/zh-CN.js b/apps/FrontendDesigner/src/locales/lang/zh-CN.js
index cbbaede..0a966d1 100644
--- a/apps/FrontendDesigner/src/locales/lang/zh-CN.js
+++ b/apps/FrontendDesigner/src/locales/lang/zh-CN.js
@@ -284,6 +284,7 @@ orderManagement: {
promptManagement: '提示词管理',
productManagement: '产品管理',
voucherManagement: '优惠券管理',
+ operationLog: '操作日志',
logout: '退出登录',
profile: '个人资料',
settings: '设置',
@@ -922,6 +923,21 @@ orderManagement: {
hint: {
userIds: '多个用户ID用逗号分隔,例如:1,2,3'
}
+ },
+ operationLog: {
+ title: '操作日志',
+ adminUserId: '管理员ID',
+ adminUsername: '管理员用户名',
+ operationType: '操作类型',
+ all: '全部',
+ resourceType: '资源类型',
+ resourceId: '资源ID',
+ description: '操作描述',
+ ipAddress: 'IP地址',
+ userAgent: '用户代理',
+ createdAt: '创建时间',
+ detailTitle: '操作日志详情',
+ getListFailed: '获取操作日志列表失败'
}
},
modelUpload: {
diff --git a/apps/FrontendDesigner/src/router/index.js b/apps/FrontendDesigner/src/router/index.js
index c3867ac..9fc42ff 100644
--- a/apps/FrontendDesigner/src/router/index.js
+++ b/apps/FrontendDesigner/src/router/index.js
@@ -24,6 +24,7 @@ const AdminCommissionManagement = () => import('@/views/admin/AdminCommissionMan
const AdminPromptManagement = () => import('@/views/admin/AdminPromptManagement/AdminPromptManagement.vue')
const AdminProductManagement = () => import('@/views/admin/ProductManagement/ProductManagement.vue')
const AdminVoucherManagement = () => import('@/views/admin/VoucherManagement/VoucherManagement.vue')
+const AdminOperationLog = () => import('@/views/admin/AdminOperationLog/AdminOperationLog.vue')
//权限路由映射表
export const permissionRoutes = [
{
@@ -149,6 +150,17 @@ export const permissionRoutes = [
requiresAuth: true
}
},
+ {
+ path: 'operation-log',
+ name: 'AdminOperationLog',
+ component: AdminOperationLog,
+ meta: {
+ title: 'admin.layout.operationLog',
+ icon: 'Document',
+ menuOrder: 7,
+ requiresAuth: true
+ }
+ },
{
path: 'permission',
@@ -156,7 +168,7 @@ export const permissionRoutes = [
meta: {
title: 'admin.layout.permission',
icon: 'Lock',
- menuOrder: 7,
+ menuOrder: 8,
isParent: true,
requiresAuth: true
},
diff --git a/apps/FrontendDesigner/src/views/admin/AdminOperationLog/AdminOperationLog.vue b/apps/FrontendDesigner/src/views/admin/AdminOperationLog/AdminOperationLog.vue
new file mode 100644
index 0000000..9c938fa
--- /dev/null
+++ b/apps/FrontendDesigner/src/views/admin/AdminOperationLog/AdminOperationLog.vue
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('admin.common.search') }}
+
+
+ {{ t('admin.common.reset') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.operationTypeDesc || row.operationType }}
+
+
+
+
+
+
+
+
+
+ {{ formatDateTime(row.createdAt) }}
+
+
+
+
+
+ {{ t('admin.common.detail') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ selectedLog?.id }}
+
+
+ {{ selectedLog?.adminUserId }}
+
+
+ {{ selectedLog?.adminUsername }}
+
+
+
+ {{ selectedLog?.operationTypeDesc || selectedLog?.operationType }}
+
+
+
+ {{ selectedLog?.resourceType }}
+
+
+ {{ selectedLog?.resourceId }}
+
+
+ {{ selectedLog?.description }}
+
+
+ {{ selectedLog?.ipAddress }}
+
+
+ {{ selectedLog?.userAgent }}
+
+
+ {{ formatDateTime(selectedLog?.createdAt) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/FrontendDesigner/src/views/admin/AdminOperationLog/index.js b/apps/FrontendDesigner/src/views/admin/AdminOperationLog/index.js
new file mode 100644
index 0000000..ee55459
--- /dev/null
+++ b/apps/FrontendDesigner/src/views/admin/AdminOperationLog/index.js
@@ -0,0 +1,48 @@
+import { adminApi,requestUtils } from "@deotaland/utils";
+export class AdminOperationLog {
+ constructor() {
+ }
+ // 分页查询操作日志列表
+ async getOperationLogList(data) {
+ let params = {
+ adminUserId: data.adminUserId ?? '',
+ adminUsername: data.adminUsername ?? '',
+ operationType: data.operationType ?? '',
+ startTime: data.startTime ?? '',
+ endTime: data.endTime ?? '',
+ pageSize: data.pageSize ?? 10,
+ pageNum: data.pageNum ?? 1,
+ orderByColumn: data.orderByColumn ?? '',
+ isAsc: data.isAsc ?? ''//排序的方向desc或者asc
+ }
+ return requestUtils.common(adminApi.default.getOperationLogList, params);
+ /*
+ 返回示例:
+ {
+ "code": 0,
+ "success": true,
+ "data": {
+ "total": 9007199254740991,
+ "rows": [
+ {
+ "id": 1073741824,
+ "adminUserId": 1073741824,
+ "adminUsername": "string",
+ "operationType": "string",
+ "operationTypeDesc": "string",
+ "resourceType": "string",
+ "resourceId": "string",
+ "description": "string",
+ "ipAddress": "string",
+ "userAgent": "string",
+ "createdAt": "2026-01-09T09:10:39.219Z"
+ }
+ ],
+ "code": 1073741824,
+ "msg": "string"
+ },
+ "message": "操作成功"
+}
+ */
+ }
+}
\ No newline at end of file
diff --git a/apps/frontend/index.html b/apps/frontend/index.html
index e9c8da4..1de6fda 100644
--- a/apps/frontend/index.html
+++ b/apps/frontend/index.html
@@ -2,7 +2,7 @@
-
+
diff --git a/apps/frontend/src/components/AddModal/index.vue b/apps/frontend/src/components/AddModal/index.vue
index 4b39086..1f7429a 100644
--- a/apps/frontend/src/components/AddModal/index.vue
+++ b/apps/frontend/src/components/AddModal/index.vue
@@ -166,7 +166,7 @@ const fileInput = ref(null);
const needHook = ref(true);
const isGenerateDisabled = computed(() => {
- return !formData.value.prompt.trim();
+ return !formData.value.prompt.trim() && !formData.value.previewImage;
});
const handleIpTypeSelect = (type) => {
@@ -272,10 +272,9 @@ const handleOptimizePrompt = async () => {
};
const handleGenerate = () => {
- if (!formData.value.prompt.trim()) {
+ if(!formData.value.prompt.trim() && !formData.value.previewImage){
return;
}
-
emit('generate', {
ipType: ipType.value,
prompt: formData.value.prompt,
diff --git a/apps/frontend/src/components/IPCard/index.vue b/apps/frontend/src/components/IPCard/index.vue
index 98022e1..53b3311 100644
--- a/apps/frontend/src/components/IPCard/index.vue
+++ b/apps/frontend/src/components/IPCard/index.vue
@@ -118,6 +118,7 @@ const formData = ref({
const isTouching = ref(false);
const isControlsVisible = ref(false);
const cjimg = 'https://draft-user.s3.us-east-2.amazonaws.com/images/14f98f33-06a7-4629-a42e-d7cfbced786f';
+const e1cjimg='https://draft-user.s3.us-east-2.amazonaws.com/images/23130608-283e-41c3-bb28-8f2492f5e233.png'
const anTypeImg = 'https://draft-user.s3.us-east-2.amazonaws.com/images/1e82b2b6-0e5d-4a62-b65f-098952eb2f67';
// const humanTypeImg = 'https://draft-user.s3.us-east-2.amazonaws.com/images/e3e60cc7-9777-41ba-9d1e-f5ffc92e4fac.webp';
// const humanTypeImg = 'https://draft-user.s3.us-east-2.amazonaws.com/images/61770f50-4b87-40a0-9297-cabda0ec6317.webp'
@@ -234,6 +235,10 @@ const props = defineProps({
type: Boolean,
default: false
},
+ series:{//产品类型
+ type: String,
+ default: 'D1'
+ },
});
// 定义事件
@@ -261,7 +266,10 @@ const handleGenerateImage = async () => {
if(iscjt){
props.cardData.imgyt&&referenceImages.push(props.cardData.imgyt);
referenceImages.push(props.cardData.diyPromptImg);
- referenceImages.push(cjimg);
+ referenceImages.push({
+ D1:cjimg,
+ E1:e1cjimg,
+ }[props.series]);
}
if(props.cardData.diyPromptText||props.cardData.addDiyPromptImg){
referenceImages.push(props.cardData.diyPromptImg);
diff --git a/apps/frontend/src/components/OrderProcessModal/index.vue b/apps/frontend/src/components/OrderProcessModal/index.vue
index 6860074..96b9918 100644
--- a/apps/frontend/src/components/OrderProcessModal/index.vue
+++ b/apps/frontend/src/components/OrderProcessModal/index.vue
@@ -23,10 +23,17 @@

+
{{ t('orderProcess.steps.inspection.thumbnailCaption') }}
@@ -59,10 +66,12 @@ import {
Picture,
Van
} from '@element-plus/icons-vue'
+import service from '@deotaland/utils/src/utils/request'
const { t } = useI18n()
const props = defineProps({
show: { type: Boolean, default: false },
- modelData: { type: Object, default: null }
+ modelData: { type: Object, default: null },
+ series: { type: String, default: '' }
})
const emit = defineEmits(['close', 'acknowledge'])
const handleOverlayClick = () => onClose()
@@ -91,12 +100,15 @@ const processSteps = computed(() => [
description: t('orderProcess.steps.scheduling.description'),
time: t('orderProcess.steps.scheduling.time')
},
- // {
- // icon: Setting,
- // title: t('orderProcess.steps.production.title'),
- // description: t('orderProcess.steps.production.description'),
- // time: t('orderProcess.steps.production.time')
- // },
+ {
+ icon: Setting,
+ title: t('orderProcess.steps.production.title'),
+ description: t('orderProcess.steps.production.description'),
+ time: {
+ D1: t('orderProcess.steps.production.time'),
+ E1: t('orderProcess.steps.production.time2'),
+ }[props.series]
+ },
{
icon: Picture,
title: t('orderProcess.steps.inspection.title'),
diff --git a/apps/frontend/src/components/layout/AppHeader.vue b/apps/frontend/src/components/layout/AppHeader.vue
index 73ca678..098d567 100644
--- a/apps/frontend/src/components/layout/AppHeader.vue
+++ b/apps/frontend/src/components/layout/AppHeader.vue
@@ -14,7 +14,7 @@
-

+
{{ t('app.title') }}
diff --git a/apps/frontend/src/locales/index.js b/apps/frontend/src/locales/index.js
index b4e026b..6a743d2 100644
--- a/apps/frontend/src/locales/index.js
+++ b/apps/frontend/src/locales/index.js
@@ -204,7 +204,8 @@ export default {
production: {
title: '模型制作',
description: '专业团队使用高精度3D打印机制作您的定制模型,确保每个细节都完美呈现。',
- time: '7-10个工作日'
+ time: '7-10个工作日',
+ time2: '1个工作日',
},
inspection: {
title: '产品检测包装',
@@ -1755,7 +1756,8 @@ export default {
production: {
title: 'Model Production',
description: 'Professional team uses high-precision 3D printers to create your custom model, ensuring every detail is perfectly presented.',
- time: '7-10 working days'
+ time: '7-10 working days',
+ time2: '1-2 working days',
},
inspection: {
title: 'Product Inspection & Packaging',
diff --git a/apps/frontend/src/main.js b/apps/frontend/src/main.js
index d112935..7c67bf1 100644
--- a/apps/frontend/src/main.js
+++ b/apps/frontend/src/main.js
@@ -23,11 +23,14 @@ import 'nprogress/nprogress.css'
import {ElMessage,ElLoading } from 'element-plus'
import dtUI from '@deotaland/ui'
import '@deotaland/ui/style.css'
-import { environmentUtils } from '@deotaland/utils';
+import { environmentUtils,WechatBus,isWeChatBrowser } from '@deotaland/utils';
const app = createApp(App)
window.setElMessage = (options={})=>{
ElMessage[options.type || 'info'](options.message || '请求失败')
}
+if(isWeChatBrowser()){
+ new WechatBus()
+}
// environmentUtils.detectEnvironment().then((env)=>{
// console.log('当前环境:', env)
// })
diff --git a/apps/frontend/src/views/Login/Login.vue b/apps/frontend/src/views/Login/Login.vue
index 25dc3ec..a7026a1 100644
--- a/apps/frontend/src/views/Login/Login.vue
+++ b/apps/frontend/src/views/Login/Login.vue
@@ -48,7 +48,7 @@
-
+ -->