Files
oil-formula-calculator/frontend/src/stores/oils.js
Hera Zhao e04d572f27
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Failing after 1m42s
fix: 下架后卡片变灰+按钮变灰,isActive存为boolean
根因: oils store 存 isActive = oil.is_active ?? true
  oil.is_active=0 时 0??true=0,但检查用 ===false,0!==false

修复: isActive = oil.is_active !== 0 (true/false boolean)

UI:
- 下架后弹窗不关闭,按钮变灰显示"✓ 已下架 · 点击重新上架"
- 卡片立即变灰(oil-chip--inactive class生效)
- 重新上架后恢复正常

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:50:26 +00:00

110 lines
2.6 KiB
JavaScript

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { api } from '../composables/useApi'
export const DROPS_PER_ML = 18.6
export const VOLUME_DROPS = {
'单次': null,
'2.5': 46,
'5': 93,
'10': 186,
'15': 280,
'115': 2146,
}
export const useOilsStore = defineStore('oils', () => {
const oils = ref({})
const oilsMeta = ref({})
// Getters
const oilNames = computed(() =>
Object.keys(oils.value).sort((a, b) => a.localeCompare(b, 'zh'))
)
function pricePerDrop(name) {
return oils.value[name] || 0
}
function calcCost(ingredients) {
return ingredients.reduce((sum, ing) => {
return sum + pricePerDrop(ing.oil) * ing.drops
}, 0)
}
function calcRetailCost(ingredients) {
return ingredients.reduce((sum, ing) => {
const meta = oilsMeta.value[ing.oil]
if (meta && meta.retailPrice && meta.dropCount) {
return sum + (meta.retailPrice / meta.dropCount) * ing.drops
}
return sum + pricePerDrop(ing.oil) * ing.drops
}, 0)
}
function fmtPrice(n) {
return '¥ ' + n.toFixed(2)
}
function fmtCostWithRetail(ingredients) {
const cost = calcCost(ingredients)
const retail = calcRetailCost(ingredients)
const costStr = fmtPrice(cost)
if (retail > cost) {
return { cost: costStr, retail: fmtPrice(retail), hasRetail: true }
}
return { cost: costStr, retail: null, hasRetail: false }
}
// Actions
async function loadOils() {
const data = await api.get('/api/oils')
const newOils = {}
const newMeta = {}
for (const oil of data) {
const ppd = oil.drop_count ? oil.bottle_price / oil.drop_count : 0
newOils[oil.name] = ppd
newMeta[oil.name] = {
bottlePrice: oil.bottle_price,
dropCount: oil.drop_count,
retailPrice: oil.retail_price ?? null,
isActive: oil.is_active !== 0,
enName: oil.en_name ?? null,
}
}
oils.value = newOils
oilsMeta.value = newMeta
}
async function saveOil(name, bottlePrice, dropCount, retailPrice, enName = null) {
await api.post('/api/oils', {
name,
bottle_price: bottlePrice,
drop_count: dropCount,
retail_price: retailPrice,
en_name: enName,
})
await loadOils()
}
async function deleteOil(name) {
await api.delete(`/api/oils/${encodeURIComponent(name)}`)
delete oils.value[name]
delete oilsMeta.value[name]
}
return {
oils,
oilsMeta,
oilNames,
pricePerDrop,
calcCost,
calcRetailCost,
fmtPrice,
fmtCostWithRetail,
loadOils,
saveOil,
deleteOil,
}
})