feat: 通用单位系统 — drop/ml/g/capsule,去掉硬编码
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 5s
PR Preview / deploy-preview (pull_request) Successful in 13s
Test / e2e-test (push) Failing after 3m5s
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 5s
PR Preview / deploy-preview (pull_request) Successful in 13s
Test / e2e-test (push) Failing after 3m5s
unit字段支持4种值,所有显示自动适配: - drop: 精油(滴/drop) - ml: 液体产品(ml) - g: 膏霜产品(g) - capsule: 胶囊(颗/capsule) 新增产品选单位即可,无需改代码。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -94,25 +94,39 @@ export const useOilsStore = defineStore('oils', () => {
|
|||||||
delete oilsMeta.value[name]
|
delete oilsMeta.value[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMlUnit(name) {
|
const UNIT_LABELS = {
|
||||||
|
drop: { zh: '滴', en: 'drop', enPlural: 'drops' },
|
||||||
|
ml: { zh: 'ml', en: 'ml', enPlural: 'ml' },
|
||||||
|
g: { zh: 'g', en: 'g', enPlural: 'g' },
|
||||||
|
capsule: { zh: '颗', en: 'capsule', enPlural: 'capsules' },
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUnit(name) {
|
||||||
const meta = oilsMeta.value[name]
|
const meta = oilsMeta.value[name]
|
||||||
return meta && meta.unit === 'ml'
|
return (meta && meta.unit) || 'drop'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDropUnit(name) {
|
||||||
|
return getUnit(name) === 'drop'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMlUnit(name) {
|
||||||
|
return getUnit(name) === 'ml'
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPortionUnit(name) {
|
function isPortionUnit(name) {
|
||||||
return isMlUnit(name)
|
return !isDropUnit(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
function unitLabel(name, lang = 'zh') {
|
function unitLabel(name, lang = 'zh') {
|
||||||
if (isMlUnit(name)) return 'ml'
|
const u = UNIT_LABELS[getUnit(name)] || UNIT_LABELS.drop
|
||||||
if (name === '植物空胶囊') return lang === 'en' ? 'capsule' : '颗'
|
return lang === 'en' ? u.en : u.zh
|
||||||
return lang === 'en' ? 'drop' : '滴'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unitLabelPlural(name, count, lang = 'zh') {
|
function unitLabelPlural(name, count, lang = 'zh') {
|
||||||
if (isMlUnit(name)) return 'ml'
|
const u = UNIT_LABELS[getUnit(name)] || UNIT_LABELS.drop
|
||||||
if (name === '植物空胶囊') return lang === 'en' ? (count === 1 ? 'capsule' : 'capsules') : '颗'
|
if (lang === 'en') return count === 1 ? u.en : u.enPlural
|
||||||
return lang === 'en' ? (count === 1 ? 'drop' : 'drops') : '滴'
|
return u.zh
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -127,6 +141,8 @@ export const useOilsStore = defineStore('oils', () => {
|
|||||||
loadOils,
|
loadOils,
|
||||||
saveOil,
|
saveOil,
|
||||||
deleteOil,
|
deleteOil,
|
||||||
|
getUnit,
|
||||||
|
isDropUnit,
|
||||||
isMlUnit,
|
isMlUnit,
|
||||||
isPortionUnit,
|
isPortionUnit,
|
||||||
unitLabel,
|
unitLabel,
|
||||||
|
|||||||
@@ -227,7 +227,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="detail-body">
|
<div class="detail-body">
|
||||||
<!-- 精油(非ml产品) -->
|
<!-- 精油(非ml产品) -->
|
||||||
<template v-if="!oils.isMlUnit(selectedOilName)">
|
<template v-if="oils.isDropUnit(selectedOilName)">
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
<span class="detail-label">总容量</span>
|
<span class="detail-label">总容量</span>
|
||||||
<span class="detail-value">{{ volumeWithDrops(selectedOilName) }}</span>
|
<span class="detail-value">{{ volumeWithDrops(selectedOilName) }}</span>
|
||||||
@@ -253,19 +253,27 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
<span class="detail-label">总容量</span>
|
<span class="detail-label">总容量</span>
|
||||||
<span class="detail-value">{{ getMeta(selectedOilName)?.dropCount || '--' }}ml</span>
|
<span class="detail-value">{{ getMeta(selectedOilName)?.dropCount || '--' }}{{ oils.unitLabel(selectedOilName) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
<span class="detail-label">会员价</span>
|
<span class="detail-label">会员价</span>
|
||||||
<span class="detail-value">{{ getMeta(selectedOilName)?.bottlePrice != null ? ('¥ ' + getMeta(selectedOilName).bottlePrice.toFixed(2)) : '--' }}</span>
|
<span class="detail-value">{{ getMeta(selectedOilName)?.bottlePrice != null ? ('¥ ' + getMeta(selectedOilName).bottlePrice.toFixed(2)) : '--' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
<span class="detail-label">每ml价格</span>
|
<span class="detail-label">每{{ oils.unitLabel(selectedOilName) }}价格</span>
|
||||||
<span class="detail-value">{{ oils.pricePerDrop(selectedOilName) ? ('¥ ' + oils.pricePerDrop(selectedOilName).toFixed(2)) : '--' }}</span>
|
<span class="detail-value">{{ oils.pricePerDrop(selectedOilName) ? ('¥ ' + oils.pricePerDrop(selectedOilName).toFixed(2)) : '--' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="detail-row" v-if="getMeta(selectedOilName)?.retailPrice">
|
||||||
|
<span class="detail-label">零售价</span>
|
||||||
|
<span class="detail-value">¥ {{ getMeta(selectedOilName).retailPrice.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row" v-if="getMeta(selectedOilName)?.retailPrice && getMeta(selectedOilName)?.dropCount">
|
||||||
|
<span class="detail-label">每{{ oils.unitLabel(selectedOilName) }}价格</span>
|
||||||
|
<span class="detail-value">¥ {{ (getMeta(selectedOilName).retailPrice / getMeta(selectedOilName).dropCount).toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<h4 style="margin:16px 0 8px">含此{{ oils.isMlUnit(selectedOilName) ? '产品' : '精油' }}的配方</h4>
|
<h4 style="margin:16px 0 8px">含此{{ oils.isDropUnit(selectedOilName) ? '精油' : '产品' }}的配方</h4>
|
||||||
<div v-if="recipesWithOil.length" class="detail-recipes">
|
<div v-if="recipesWithOil.length" class="detail-recipes">
|
||||||
<div v-for="r in recipesWithOil" :key="r._id" class="detail-recipe-item">
|
<div v-for="r in recipesWithOil" :key="r._id" class="detail-recipe-item">
|
||||||
<span class="dr-name">{{ r.name }}</span>
|
<span class="dr-name">{{ r.name }}</span>
|
||||||
@@ -490,27 +498,24 @@ for (const [ml, drops] of Object.entries(VOLUME_OPTIONS)) {
|
|||||||
DROPS_TO_VOLUME[drops] = ml + 'ml'
|
DROPS_TO_VOLUME[drops] = ml + 'ml'
|
||||||
}
|
}
|
||||||
|
|
||||||
function volumeWithDrops(name) {
|
|
||||||
const meta = getMeta(name)
|
|
||||||
if (!meta || !meta.dropCount) return '--'
|
|
||||||
if (name === '植物空胶囊') return meta.dropCount + '颗'
|
|
||||||
const ml = DROPS_TO_VOLUME[meta.dropCount]
|
|
||||||
if (ml) return `${ml}/${meta.dropCount}滴`
|
|
||||||
return meta.dropCount + '滴'
|
|
||||||
}
|
|
||||||
|
|
||||||
function oilPriceUnit(name) {
|
function oilPriceUnit(name) {
|
||||||
if (oils.isMlUnit(name)) return 'ml'
|
return oils.unitLabel(name)
|
||||||
if (name === '植物空胶囊') return '颗'
|
|
||||||
return '滴'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function volumeLabel(dropCount, name) {
|
function volumeLabel(dropCount, name) {
|
||||||
if (dropCount === 160) return '160颗'
|
if (!oils.isDropUnit(name)) return dropCount + oils.unitLabel(name)
|
||||||
if (oils.isMlUnit(name)) return dropCount + 'ml'
|
|
||||||
return DROPS_TO_VOLUME[dropCount] || (dropCount + '滴')
|
return DROPS_TO_VOLUME[dropCount] || (dropCount + '滴')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function volumeWithDrops(name) {
|
||||||
|
const meta = getMeta(name)
|
||||||
|
if (!meta || !meta.dropCount) return '--'
|
||||||
|
if (!oils.isDropUnit(name)) return meta.dropCount + oils.unitLabel(name)
|
||||||
|
const ml = DROPS_TO_VOLUME[meta.dropCount]
|
||||||
|
if (ml) return `${ml}/${meta.dropCount}滴`
|
||||||
|
return meta.dropCount + '滴'
|
||||||
|
}
|
||||||
|
|
||||||
function chipStyle(name) {
|
function chipStyle(name) {
|
||||||
const hasCard = !!getOilCard(name)
|
const hasCard = !!getOilCard(name)
|
||||||
if (hasCard) return 'cursor:pointer;border-left:3px solid var(--sage);background:linear-gradient(90deg,var(--sage-mist),white)'
|
if (hasCard) return 'cursor:pointer;border-left:3px solid var(--sage);background:linear-gradient(90deg,var(--sage-mist),white)'
|
||||||
|
|||||||
Reference in New Issue
Block a user