diff --git a/apps/web/src/components/QuickEntryDrawer.vue b/apps/web/src/components/QuickEntryDrawer.vue index d7fba4e..9a4250e 100644 --- a/apps/web/src/components/QuickEntryDrawer.vue +++ b/apps/web/src/components/QuickEntryDrawer.vue @@ -24,7 +24,7 @@ const props = defineProps<{ ledgerId: string; ledgerName: string; personalLedgerId: string; - ledgerOptions: Array<{ id: string; name: string; color: string; isPersonal: boolean }>; + ledgerOptions: Array<{ id: string; name: string; gradient: string; isPersonal: boolean }>; }>(); const emit = defineEmits<{ @@ -541,7 +541,7 @@ function saveEntry() {
选择账本至少选择一个账本
diff --git a/apps/web/src/components/QuickEntryHost.vue b/apps/web/src/components/QuickEntryHost.vue index 0afdd33..a473d23 100644 --- a/apps/web/src/components/QuickEntryHost.vue +++ b/apps/web/src/components/QuickEntryHost.vue @@ -3,6 +3,7 @@ import { BarChart3, BookOpen, Check, CircleUserRound, LibraryBig, Plus } from "@ import { computed, onMounted, ref } from "vue"; import { useRoute } from "vue-router"; import { createEntry } from "../data/entries"; +import { ledgerTheme } from "../data/ledgers"; import { useEntryStore } from "../stores/entries"; import { useAuthStore } from "../stores/auth"; import { useLedgerStore } from "../stores/ledgers"; @@ -16,7 +17,7 @@ const drawerOpen = ref(false); const savedToast = ref(false); const ledgerOptions = computed(() => - ledgerStore.ledgers.map((ledger) => ({ id: ledger.id, name: ledger.name, color: ledger.color, isPersonal: ledger.isPersonal })), + ledgerStore.ledgers.map((ledger) => ({ id: ledger.id, name: ledger.name, gradient: ledgerTheme(ledger.theme).gradient, isPersonal: ledger.isPersonal })), ); onMounted(async () => { diff --git a/apps/web/src/data/ledgers.ts b/apps/web/src/data/ledgers.ts index e2d88ea..c265162 100644 --- a/apps/web/src/data/ledgers.ts +++ b/apps/web/src/data/ledgers.ts @@ -1,9 +1,28 @@ -import type { CurrencyCode } from "@cents/domain"; +import { ledgerThemeAccents, type CurrencyCode, type LedgerThemeId } from "@cents/domain"; + +export const ledgerThemes: ReadonlyArray<{ + id: LedgerThemeId; + name: string; + accent: string; + gradient: string; +}> = [ + { id: "jade", name: "翡翠", accent: ledgerThemeAccents.jade, gradient: "linear-gradient(135deg, #118b79 0%, #087f72 48%, #285765 100%)" }, + { id: "ocean", name: "海湾", accent: ledgerThemeAccents.ocean, gradient: "linear-gradient(135deg, #167b93 0%, #3459a4 52%, #4b3f7f 100%)" }, + { id: "coral", name: "晚霞", accent: ledgerThemeAccents.coral, gradient: "linear-gradient(135deg, #c94f45 0%, #ad4869 54%, #6e4d82 100%)" }, + { id: "berry", name: "莓果", accent: ledgerThemeAccents.berry, gradient: "linear-gradient(135deg, #a84378 0%, #71468d 52%, #40578a 100%)" }, + { id: "meadow", name: "森野", accent: ledgerThemeAccents.meadow, gradient: "linear-gradient(135deg, #25805f 0%, #4e794b 54%, #766b35 100%)" }, + { id: "graphite", name: "暮色", accent: ledgerThemeAccents.graphite, gradient: "linear-gradient(135deg, #35585d 0%, #4e556e 52%, #303f55 100%)" }, +]; + +export function ledgerTheme(themeId?: string) { + return ledgerThemes.find((theme) => theme.id === themeId) ?? ledgerThemes[0]; +} export type LedgerRecord = { id: string; name: string; color: string; + theme: LedgerThemeId; defaultCurrency: CurrencyCode; createdAt: string; updatedAt: string; @@ -31,6 +50,7 @@ export function createDefaultLedgers(): LedgerRecord[] { id: "local-ledger", name: "家庭日常", color: "#087f72", + theme: "jade", defaultCurrency: "CNY", createdAt: now, updatedAt: now, @@ -41,6 +61,7 @@ export function createDefaultLedgers(): LedgerRecord[] { id: "travel-ledger", name: "旅行账本", color: "#3478e5", + theme: "ocean", defaultCurrency: "CNY", createdAt: now, updatedAt: now, diff --git a/apps/web/src/stores/ledgers.ts b/apps/web/src/stores/ledgers.ts index 350252c..37bcc84 100644 --- a/apps/web/src/stores/ledgers.ts +++ b/apps/web/src/stores/ledgers.ts @@ -112,13 +112,13 @@ export const useLedgerStore = defineStore("ledgers", { memberName(userId: string) { return this.currentMembers.find((member) => member.id === userId)?.name ?? "历史用户"; }, - async createLedger(input: Pick) { + async createLedger(input: Pick) { const result = await apiRequest<{ ledger: LedgerRecord }>("/api/ledgers", { method: "POST", body: input }); await this.reloadLedgers(); await this.setCurrentLedger(result.ledger.id); return result.ledger; }, - async updateLedger(input: Pick) { + async updateLedger(input: Pick) { await apiRequest(`/api/ledgers/${encodeURIComponent(input.id)}`, { method: "PATCH", body: input }); await this.reloadLedgers(); return this.ledgers.find((ledger) => ledger.id === input.id)!; diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index b95b76d..17ac00f 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -75,7 +75,7 @@ input:focus-visible { z-index: 1; min-height: 180px; padding: max(18px, env(safe-area-inset-top)) 18px 20px; - background: #087f72; + background: var(--ledger-gradient, #087f72); color: #ffffff; } @@ -112,7 +112,7 @@ input:focus-visible { display: grid; flex: 0 0 auto; place-items: center; - border: 2px solid #087f72; + border: 2px solid var(--ledger-accent, #087f72); border-radius: 50%; color: #ffffff; font-size: 10px; diff --git a/apps/web/src/views/EntryDetailView.vue b/apps/web/src/views/EntryDetailView.vue index e4557cd..ec83de6 100644 --- a/apps/web/src/views/EntryDetailView.vue +++ b/apps/web/src/views/EntryDetailView.vue @@ -22,6 +22,7 @@ import { findCategoryPath, type Category, } from "../data/categories"; +import { ledgerTheme } from "../data/ledgers"; import { useEntryStore } from "../stores/entries"; import { useLedgerStore } from "../stores/ledgers"; @@ -349,7 +350,7 @@ async function deleteEntry() {
选择账本至少选择一个账本
diff --git a/apps/web/src/views/LedgerSettingsView.vue b/apps/web/src/views/LedgerSettingsView.vue index 7afb401..8f280e2 100644 --- a/apps/web/src/views/LedgerSettingsView.vue +++ b/apps/web/src/views/LedgerSettingsView.vue @@ -1,14 +1,15 @@