Compare commits

3 Commits
master ... v1

Author SHA1 Message Date
aaa
8ce7f902af feat: transaction framework 2025-02-03 17:23:16 +08:00
aaa
0425cd90a6 temp layout 2025-02-03 11:23:25 +08:00
aaa
4a63f8454d feat: layout 2025-02-03 10:47:19 +08:00
19 changed files with 9941 additions and 0 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
[*.{vue,js,ts,json,md,html}]
charset = utf-8
indent_style = space
indent_size = 2
[Makefile]
indent_style = tab

7
app.vue Normal file
View File

@@ -0,0 +1,7 @@
<template>
<NuxtLayout>
<v-app>
<NuxtPage />
</v-app>
</NuxtLayout>
</template>

View File

@@ -0,0 +1,16 @@
<template>
<v-navigation-drawer class="pt-4" rail>
<v-list>
<v-list-item prepend-avatar="https://randomuser.me/api/portraits/women/85.jpg" subtitle="sandra_a88@gmailcom"
title="Sandra Adams"></v-list-item>
</v-list>
<v-divider></v-divider>
<v-list density="compact" nav>
<v-list-item prepend-icon="mdi-folder" title="My Files" value="myfiles"></v-list-item>
<v-list-item prepend-icon="mdi-account-multiple" title="Shared with me" value="shared"></v-list-item>
<v-list-item prepend-icon="mdi-star" title="Starred" value="starred"></v-list-item>
</v-list>
</v-navigation-drawer>
</template>

View File

@@ -0,0 +1,85 @@
<template>
<v-list rounded="lg" lines="two">
<TransactionListItem v-for="v in transactions" :transaction-item="v"/>
</v-list>
</template>
<script lang="ts" setup>
let transactions = [
{
"id": "20842",
"description": "aaa",
"category": {
"id": "10087241",
"name": "Category1",
},
"amount": {
"value": "135.33",
"currency": "CNY",
},
"time": "1738564519",
"tags": [
{
"id": "1742004",
"name": "t1",
},
{
"id": "1742932",
"name": "t3",
},
],
},
{
"id": "20845",
"description": "bbb",
"category": {
"id": "10088823",
"name": "Category2",
},
"amount": {
"value": "77.99",
"currency": "CNY",
},
"time": "1738564519",
"tags": [
{
"id": "1742004",
"name": "t1",
},
{
"id": "1742932",
"name": "t3",
},
],
}
]
let items = [
{ type: 'subheader', title: 'Group #1' },
{
title: 'Item #1',
value: 1,
},
{
title: 'Item #2',
value: 2,
},
{
title: 'Item #3',
value: 3,
},
{ type: 'divider' },
{ type: 'subheader', title: 'Group #2' },
{
title: 'Item #4',
value: 4,
},
{
title: 'Item #5',
value: 5,
},
{
title: 'Item #6',
value: 6,
},
];
</script>

View File

@@ -0,0 +1,37 @@
<template>
<v-list-item :value="transactionItem.id">
<template v-slot:prepend>
<v-avatar color="grey-lighten-1">
<v-icon color="white">mdi-folder</v-icon>
</v-avatar>
</template>
<v-list-item-title>
{{transactionItem.category?.name}}
</v-list-item-title>
<v-list-item-subtitle>
{{formatDateTime}} &middot; {{transactionItem.description}}
</v-list-item-subtitle>
<template v-slot:append>
<v-list-item-action class="flex-column align-end">
<span v-html="formatAmountString"></span>
</v-list-item-action>
</template>
</v-list-item>
</template>
<script lang="ts" setup>
import {Transaction} from "@/models/transaction.ts"
import {computed } from 'vue'
import * as dayjs from 'dayjs'
import {CurrencyTypeToSymbol} from "@/utils/currency"
const props = defineProps<{
transactionItem: Transaction;
}>();
const formatDateTime = computed(() => {
let parsed = dayjs.unix(Number(props.transactionItem.time))
return parsed.format("HH:mm")
})
const formatAmountString = computed(() => {
return CurrencyTypeToSymbol(props.transactionItem.amount.currency)+props.transactionItem.amount.val||"0.00"
})
</script>

16
layouts/desktop.vue Normal file
View File

@@ -0,0 +1,16 @@
<template>
<v-layout style="min-height: 100%;">
<!-- <p>desktop layout</p> -->
<!-- <div> -->
<DesktopSideBar />
<v-app-bar flat>
<slot name="app-bar-container"></slot>
</v-app-bar>
<v-main class="bg-grey-lighten-4 d-flex align-start justify-center">
<v-container fluid>
<slot />
</v-container>
</v-main>
<!-- </div> -->
</v-layout>
</template>

28
models/transaction.ts Normal file
View File

@@ -0,0 +1,28 @@
export interface Category {
id: string,
name: string,
}
export interface Tag {
id: string,
name: string,
}
export interface Amount{
currency: string,
val: string,
}
export interface Transaction{
id: string,
description: string,
time: string,
category?: Category,
tags?: Tag[],
amount?:
}
export interface TransactionGroup {
group_title: string,
transactions?: Transaction[],
}

25
nuxt.config.ts Normal file
View File

@@ -0,0 +1,25 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
export default defineNuxtConfig({
build: {
transpile: ['vuetify'],
},
modules: [
(_options, nuxt) => {
nuxt.hooks.hook('vite:extendConfig', (config) => {
// @ts-expect-error
config.plugins.push(vuetify({ autoImport: true }))
})
},
//...
],
vite: {
vue: {
template: {
transformAssetUrls,
},
},
},
compatibilityDate: '2024-11-01',
devtools: { enabled: true }
})

9533
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

23
package.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@mdi/font": "^7.4.47",
"dayjs": "^1.11.13",
"nuxt": "^3.15.4",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
"vite-plugin-vuetify": "^2.0.4",
"vuetify": "^3.7.9"
}
}

View File

@@ -0,0 +1,14 @@
<template>
<div style="min-height: 100%;">
<NuxtLayout name="desktop">
<p>
Dashboard Page
</p>
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
definePageMeta({
})
</script>

View File

@@ -0,0 +1,96 @@
<template>
<div style="min-height: 100%;">
<NuxtLayout name="desktop">
<template #app-bar-container>
<v-app-bar-title>Transactions</v-app-bar-title>
</template>
<v-row align="start">
<v-col md="8" lg="8" xl="8" xxl="8">
<v-sheet rounded="lg">
<v-list rounded="lg" lines="two">
<template v-for="grp in transactionList.transactionGroups">
<v-list-subheader>{{ grp.group_title }}</v-list-subheader>
<TransactionListItem v-for="v in grp.transactions" :transaction-item="v" />
</template>
</v-list>
</v-sheet>
</v-col>
<v-col>
<v-sheet rounded="lg">
<v-container>
<v-form>
<v-text-field v-model="name" label="Name" variant="outlined"></v-text-field>
</v-form>
</v-container>
</v-sheet>
</v-col>
</v-row>
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Transaction, TransactionGroup } from '@/models/transaction';
interface TransactionPageData {
transactionGroups: TransactionGroup[],
}
const transactionList = ref(
{
transactionGroups: [],
// filters
}
)
let transactionGrp: TransactionGroup = { transactions: [], group_title: "aabbccdd" };
transactionGrp.transactions.push({
"id": "20842",
"description": "aaa",
"category": {
"id": "10087241",
"name": "Category1",
},
"amount": {
"val": "135.33",
"currency": "CNY",
},
"time": "1738564519",
"tags": [
{
"id": "1742004",
"name": "t1",
},
{
"id": "1742932",
"name": "t3",
},
],
})
transactionList.value.transactionGroups.push(transactionGrp)
let transactionGrp2: TransactionGroup = { transactions: [], group_title: "eeffgghh" };
transactionGrp2.transactions.push({
"id": "898539",
"description": "bbb",
"category": {
"id": "10087241",
"name": "Category2",
},
"amount": {
"val": "67.00",
"currency": "CNY",
},
"time": "1738561205",
"tags": [
{
"id": "1742004",
"name": "t1",
},
{
"id": "1742932",
"name": "t3",
},
],
})
transactionList.value.transactionGroups.push(transactionGrp2)
</script>

9
pages/index.vue Normal file
View File

@@ -0,0 +1,9 @@
<template>
<div>Index</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'desktop'
})
</script>

12
plugins/vuetify.ts Normal file
View File

@@ -0,0 +1,12 @@
// import this after install `@mdi/font` package
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
export default defineNuxtPlugin((app) => {
const vuetify = createVuetify({
// ... your configuration
})
app.vueApp.use(vuetify)
})

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

1
public/robots.txt Normal file
View File

@@ -0,0 +1 @@

3
server/tsconfig.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

4
tsconfig.json Normal file
View File

@@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}

17
utils/currency.ts Normal file
View File

@@ -0,0 +1,17 @@
// 定义支持的货币类型
type Currency = "USD" | "EUR" | "GBP" | "JPY" | "CNY";
// 定义货币类型到 HTML 字符的映射
const currencySymbols: Record<Currency, string> = {
USD: "&#36;", // 美元符号
EUR: "&#8364;", // 欧元符号
GBP: "&#163;", // 英镑符号
JPY: "&#165;", // 日元符号
CNY: "&#165;", // 人民币符号(与日元相同)
};
export function CurrencyTypeToSymbol(currencyType: string){
return currencySymbols[currencyType] || "";
}