feat: 商业核算+个人库存+认证优化 #23

Merged
hera merged 14 commits from feat/inventory-commercial into main 2026-04-11 10:47:08 +00:00
2 changed files with 20 additions and 7 deletions
Showing only changes of commit cfe93125ac - Show all commits

View File

@@ -42,7 +42,7 @@
成本 {{ oils.fmtPrice(oils.calcCost(p.ingredients)) }}
</span>
</div>
<div v-if="auth.isAdmin" class="proj-actions" @click.stop>
<div class="proj-actions proj-actions-hover" @click.stop>
<button class="btn-icon-sm" @click="deleteProject(p)" title="删除">🗑</button>
</div>
</div>
@@ -72,8 +72,8 @@
<thead>
<tr>
<th>精油</th>
<th>单次用量()</th>
<th>单价/</th>
<th>用量</th>
<th></th>
<th>小计</th>
<th></th>
</tr>
@@ -127,7 +127,8 @@
</tbody>
</table>
<div class="consumption-summary">
<span> <strong>{{ limitingOil }}</strong> 最先消耗完最多可做 <strong>{{ maxSessions }}</strong> </span>
<span v-if="allSameSession">可做 <strong>{{ maxSessions }}</strong> </span>
<span v-else> <strong>{{ limitingOil }}</strong> 最先消耗完可做 <strong>{{ maxSessions }}</strong> </span>
</div>
</div>
</div>
@@ -467,6 +468,12 @@ const limitingOil = computed(() => {
return min.oil
})
const allSameSession = computed(() => {
const data = consumptionData.value.filter(c => c.sessions > 0)
if (data.length <= 1) return true
return data.every(c => c.sessions === data[0].sessions)
})
const maxSessions = computed(() => {
const data = consumptionData.value.filter(c => c.sessions > 0)
if (!data.length) return 0
@@ -490,6 +497,9 @@ 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; }
.proj-actions-hover { opacity: 0; transition: opacity 0.15s; }
.project-card:hover .proj-actions-hover { opacity: 1; }
.readonly-row { background: #f8f7f5; }
.readonly-oil { font-size: 13px; color: #6b6375; }
.readonly-drops { font-size: 13px; color: #3e3a44; font-weight: 500; }
@@ -657,6 +667,7 @@ function formatDate(d) {
.section-actions { display: flex; gap: 6px; }
.ingredients-table { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.ingredients-table th { white-space: nowrap; }
.ingredients-table th {
text-align: center; padding: 10px 8px; font-size: 12px; font-weight: 600;
color: var(--text-light, #999); border-bottom: 2px solid #e5e4e7;
@@ -667,7 +678,7 @@ function formatDate(d) {
.drops-input:focus { border-color: #7ec6a4; }
.cell-ppd { color: #999; font-size: 12px; }
.cell-subtotal { color: #4a9d7e; font-weight: 600; }
.remove-btn { border: none; background: none; color: #ccc; cursor: pointer; font-size: 18px; }
.remove-btn { border: none; background: none; color: #ccc; cursor: pointer; font-size: 14px; padding: 2px; }
.remove-btn:hover { color: #c0392b; }
.total-row {
@@ -706,12 +717,14 @@ function formatDate(d) {
.price-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #eae8e5;
font-size: 14px;
gap: 12px;
}
.price-row .price-label { flex: 0 0 80px; }
.price-row .price-value, .price-row .price-input-wrap, .price-row .form-input-inline { flex: 1; }
.price-row.total {
border-top: 2px solid #d4cfc7;

View File

@@ -1,7 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
const buildTime = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
const buildTime = new Date().toLocaleString('en-GB', { timeZone: 'Europe/London', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
export default defineConfig({
define: {