diff --git a/frontend/src/views/Projects.vue b/frontend/src/views/Projects.vue index 60b5c07..af5c5e5 100644 --- a/frontend/src/views/Projects.vue +++ b/frontend/src/views/Projects.vue @@ -13,19 +13,19 @@
- -
+ +
- 芳香调理技术 + {{ demoProject.name }} 体验
点击体验成本利润分析
- +

🧴 配方成分

- +
@@ -77,19 +77,29 @@ - + - +
- + + - + + {{ ing.oil ? oils.fmtPrice(oils.pricePerDrop(ing.oil)) : '—' }} {{ ing.oil && ing.drops ? oils.fmtPrice(oils.pricePerDrop(ing.oil) * ing.drops) : '—' }}
@@ -281,6 +291,30 @@ async function loadProjects() { } } +// Demo = first project (芳香调理技术), managed by admin +const demoProject = computed(() => projects.value.find(p => p.name && p.name.includes('芳香调理')) || projects.value[0] || null) +const userProjects = computed(() => { + const demoId = demoProject.value?._id || demoProject.value?.id + return projects.value.filter(p => (p._id || p.id) !== demoId) +}) +const isDemoMode = computed(() => selectedProject.value?._demo === true) + +function selectDemoProject() { + const p = demoProject.value + if (!p) return + selectedProject.value = { + ...p, + _demo: true, + ingredients: (p.ingredients || []).map(i => ({ ...i })), + packaging_cost: p.packaging_cost || 0, + labor_cost: p.labor_cost || 0, + other_cost: p.other_cost || 0, + selling_price: p.selling_price || 0, + quantity: p.quantity || 1, + notes: p.notes || '', + } +} + function handleCreateProject() { if (!auth.isBusiness && !auth.isAdmin) { showCertPrompt() @@ -289,23 +323,6 @@ function handleCreateProject() { createProject() } -function openDemo() { - // Find the real 芳香调理技术 recipe - const recipe = recipeStore.recipes.find(r => r.name.includes('芳香调理技术') || r.name === '芳香调理') - const ings = recipe ? recipe.ingredients.map(i => ({ ...i })) : [{ oil: '芳香调理', drops: 12 }, { oil: '椰子油', drops: 186 }] - selectedProject.value = { - _demo: true, - name: recipe ? recipe.name : '芳香调理技术', - ingredients: ings, - packaging_cost: 5, - labor_cost: 30, - other_cost: 10, - selling_price: 198, - quantity: 1, - notes: '体验项目:修改数字不会影响其他用户', - } -} - async function createProject() { const name = await showPrompt('项目名称:', '新项目') if (!name) return @@ -353,7 +370,10 @@ function selectProject(p) { async function saveProject() { if (!selectedProject.value) return + // Demo mode for non-admin: only save locally, don't hit API + if (isDemoMode.value && !auth.isAdmin) return const id = selectedProject.value._id || selectedProject.value.id + if (!id) return try { await api(`/api/projects/${id}`, { method: 'PUT', @@ -476,6 +496,10 @@ function formatDate(d) { .commercial-icon { font-size: 48px; margin-bottom: 8px; } .commercial-desc { font-size: 14px; color: var(--text-light, #999); } .demo-card { border-style: dashed !important; opacity: 0.85; } +.readonly-row { background: #f8f7f5; } +.readonly-oil { font-size: 13px; color: #6b6375; } +.readonly-drops { font-size: 13px; color: #3e3a44; font-weight: 500; } + .consumption-section { margin-bottom: 20px; padding: 14px; background: #f8f7f5; border-radius: 12px; border: 1.5px solid #e5e4e7; } .consumption-section h4 { margin: 0 0 12px; font-size: 14px; color: #3e3a44; } .consumption-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 10px; }