diff --git a/backend/database.py b/backend/database.py index 137ec68..52eef67 100644 --- a/backend/database.py +++ b/backend/database.py @@ -227,6 +227,8 @@ def init_db(): c.execute("ALTER TABLE oils ADD COLUMN is_active INTEGER DEFAULT 1") if "en_name" not in oil_cols: c.execute("ALTER TABLE oils ADD COLUMN en_name TEXT DEFAULT ''") + if "unit" not in oil_cols: + c.execute("ALTER TABLE oils ADD COLUMN unit TEXT DEFAULT 'drop'") # Migration: add new columns to category_modules if missing cat_cols = [row[1] for row in c.execute("PRAGMA table_info(category_modules)").fetchall()] diff --git a/backend/main.py b/backend/main.py index 55a5729..213ba2b 100644 --- a/backend/main.py +++ b/backend/main.py @@ -87,6 +87,7 @@ class OilIn(BaseModel): retail_price: Optional[float] = None en_name: Optional[str] = None is_active: Optional[int] = None + unit: Optional[str] = None class IngredientIn(BaseModel): @@ -715,7 +716,7 @@ def impersonate(body: dict, user=Depends(require_role("admin"))): @app.get("/api/oils") def list_oils(): conn = get_db() - rows = conn.execute("SELECT name, bottle_price, drop_count, retail_price, is_active, en_name FROM oils ORDER BY name").fetchall() + rows = conn.execute("SELECT name, bottle_price, drop_count, retail_price, is_active, en_name, unit FROM oils ORDER BY name").fetchall() conn.close() return [dict(r) for r in rows] @@ -724,11 +725,11 @@ def list_oils(): def upsert_oil(oil: OilIn, user=Depends(require_role("admin", "senior_editor"))): conn = get_db() conn.execute( - "INSERT INTO oils (name, bottle_price, drop_count, retail_price, en_name, is_active) VALUES (?, ?, ?, ?, ?, ?) " + "INSERT INTO oils (name, bottle_price, drop_count, retail_price, en_name, is_active, unit) VALUES (?, ?, ?, ?, ?, ?, ?) " "ON CONFLICT(name) DO UPDATE SET bottle_price=excluded.bottle_price, drop_count=excluded.drop_count, " "retail_price=excluded.retail_price, en_name=COALESCE(excluded.en_name, oils.en_name), " - "is_active=COALESCE(excluded.is_active, oils.is_active)", - (oil.name, oil.bottle_price, oil.drop_count, oil.retail_price, title_case(oil.en_name) if oil.en_name else oil.en_name, oil.is_active), + "is_active=COALESCE(excluded.is_active, oils.is_active), unit=COALESCE(excluded.unit, oils.unit)", + (oil.name, oil.bottle_price, oil.drop_count, oil.retail_price, title_case(oil.en_name) if oil.en_name else oil.en_name, oil.is_active, oil.unit), ) log_audit(conn, user["id"], "upsert_oil", "oil", oil.name, oil.name, json.dumps({"bottle_price": oil.bottle_price, "drop_count": oil.drop_count})) diff --git a/frontend/src/stores/oils.js b/frontend/src/stores/oils.js index a7cd4fa..071942f 100644 --- a/frontend/src/stores/oils.js +++ b/frontend/src/stores/oils.js @@ -70,6 +70,7 @@ export const useOilsStore = defineStore('oils', () => { retailPrice: oil.retail_price ?? null, isActive: oil.is_active !== 0, enName: oil.en_name ?? null, + unit: oil.unit || 'drop', } } oils.value = newOils @@ -93,18 +94,22 @@ export const useOilsStore = defineStore('oils', () => { delete oilsMeta.value[name] } - function isPortionUnit(name) { + function isMlUnit(name) { const meta = oilsMeta.value[name] - return meta && meta.dropCount === 1 + return meta && meta.unit === 'ml' + } + + function isPortionUnit(name) { + return isMlUnit(name) } function unitLabel(name, lang = 'zh') { - if (isPortionUnit(name)) return lang === 'en' ? 'portion' : '份' + if (isMlUnit(name)) return 'ml' return lang === 'en' ? 'drop' : '滴' } function unitLabelPlural(name, count, lang = 'zh') { - if (isPortionUnit(name)) return lang === 'en' ? (count === 1 ? 'portion' : 'portions') : '份' + if (isMlUnit(name)) return 'ml' return lang === 'en' ? (count === 1 ? 'drop' : 'drops') : '滴' }