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 @@ + + + + + + + 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 @@ 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 @@