Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ce7f902af | ||
|
|
0425cd90a6 | ||
|
|
4a63f8454d |
15
.editorconfig
Normal file
15
.editorconfig
Normal 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
7
app.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<v-app>
|
||||
<NuxtPage />
|
||||
</v-app>
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
16
components/DesktopSideBar.vue
Normal file
16
components/DesktopSideBar.vue
Normal 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>
|
||||
85
components/TransactionList.vue
Normal file
85
components/TransactionList.vue
Normal 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>
|
||||
37
components/TransactionListItem.vue
Normal file
37
components/TransactionListItem.vue
Normal 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}} · {{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
16
layouts/desktop.vue
Normal 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
28
models/transaction.ts
Normal 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
25
nuxt.config.ts
Normal 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
9533
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
Normal file
23
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
14
pages/desktop/dashboard.vue
Normal file
14
pages/desktop/dashboard.vue
Normal 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>
|
||||
96
pages/desktop/transaction.vue
Normal file
96
pages/desktop/transaction.vue
Normal 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
9
pages/index.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div>Index</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'desktop'
|
||||
})
|
||||
</script>
|
||||
12
plugins/vuetify.ts
Normal file
12
plugins/vuetify.ts
Normal 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
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
1
public/robots.txt
Normal file
1
public/robots.txt
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
||||
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
||||
17
utils/currency.ts
Normal file
17
utils/currency.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
// 定义支持的货币类型
|
||||
type Currency = "USD" | "EUR" | "GBP" | "JPY" | "CNY";
|
||||
|
||||
// 定义货币类型到 HTML 字符的映射
|
||||
const currencySymbols: Record<Currency, string> = {
|
||||
USD: "$", // 美元符号
|
||||
EUR: "€", // 欧元符号
|
||||
GBP: "£", // 英镑符号
|
||||
JPY: "¥", // 日元符号
|
||||
CNY: "¥", // 人民币符号(与日元相同)
|
||||
};
|
||||
|
||||
|
||||
export function CurrencyTypeToSymbol(currencyType: string){
|
||||
return currencySymbols[currencyType] || "";
|
||||
}
|
||||
Reference in New Issue
Block a user