Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa8ec6eae4 |
12
api/account.js
Normal file
12
api/account.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { get, put } from '../utils/request'
|
||||||
|
|
||||||
|
// 获取账户信息
|
||||||
|
export function getAccount() {
|
||||||
|
return get('/accounts')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新账户信息
|
||||||
|
export function updateAccount(data) {
|
||||||
|
return put('/accounts', data)
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name" : "强宝爱记账",
|
"name" : "强宝爱记账",
|
||||||
"appid": "__UNI__ACCOUNTING",
|
"appid" : "__UNI__ED52D70",
|
||||||
"description" : "智能记账应用,支持OCR识别账单",
|
"description" : "智能记账应用,支持OCR识别账单",
|
||||||
"versionName" : "1.0.0",
|
"versionName" : "1.0.0",
|
||||||
"versionCode" : "100",
|
"versionCode" : "100",
|
||||||
|
|||||||
@ -37,6 +37,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "编辑账单"
|
"navigationBarTitleText": "编辑账单"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/account/account",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "账户管理"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
|||||||
302
pages/account/account.vue
Normal file
302
pages/account/account.vue
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
<template>
|
||||||
|
<scroll-view scroll-y class="page-scroll">
|
||||||
|
<view class="container">
|
||||||
|
<view class="account-card">
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="card-title">账户信息</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="card-body">
|
||||||
|
<view class="balance-section">
|
||||||
|
<text class="balance-label">当前余额</text>
|
||||||
|
<text class="balance-amount" :class="account.balance >= 0 ? 'positive' : 'negative'">
|
||||||
|
¥{{ account.balance ? account.balance.toFixed(2) : '0.00' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="stats-section">
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-label">总收入</text>
|
||||||
|
<text class="stat-value income">¥{{ account.totalIncome ? account.totalIncome.toFixed(2) : '0.00' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-label">总支出</text>
|
||||||
|
<text class="stat-value expense">¥{{ account.totalExpense ? account.totalExpense.toFixed(2) : '0.00' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-section">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">账户名称</text>
|
||||||
|
<input
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
placeholder="请输入账户名称"
|
||||||
|
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">初始余额</text>
|
||||||
|
<input
|
||||||
|
v-model="form.initialBalance"
|
||||||
|
type="text"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入初始余额"
|
||||||
|
|
||||||
|
@input="onInitialBalanceInput"
|
||||||
|
/>
|
||||||
|
<text class="form-tip">初始余额 + 收入 - 支出 = 当前余额</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="card-footer">
|
||||||
|
<button class="save-btn" @click="saveAccount" :loading="saving">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getAccount, updateAccount } from '../../api/account'
|
||||||
|
|
||||||
|
const account = ref({
|
||||||
|
id: null,
|
||||||
|
name: '默认账户',
|
||||||
|
initialBalance: 0,
|
||||||
|
balance: 0,
|
||||||
|
totalIncome: 0,
|
||||||
|
totalExpense: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
name: '默认账户',
|
||||||
|
initialBalance: '0.00'
|
||||||
|
})
|
||||||
|
|
||||||
|
const saving = ref(false)
|
||||||
|
|
||||||
|
const loadAccount = async () => {
|
||||||
|
try {
|
||||||
|
const data = await getAccount()
|
||||||
|
if (data) {
|
||||||
|
account.value = data
|
||||||
|
form.value.name = data.name || '默认账户'
|
||||||
|
form.value.initialBalance = data.initialBalance ? data.initialBalance.toFixed(2) : '0.00'
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载账户失败', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载账户失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInitialBalanceInput = (e) => {
|
||||||
|
let value = e.detail.value || ''
|
||||||
|
value = value.replace(/[^\d.]/g, '')
|
||||||
|
const parts = value.split('.')
|
||||||
|
if (parts.length > 2) {
|
||||||
|
value = parts[0] + '.' + parts.slice(1).join('')
|
||||||
|
}
|
||||||
|
if (parts.length === 2 && parts[1].length > 2) {
|
||||||
|
value = parts[0] + '.' + parts[1].substring(0, 2)
|
||||||
|
}
|
||||||
|
form.value.initialBalance = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveAccount = async () => {
|
||||||
|
if (!form.value.name || form.value.name.trim() === '') {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入账户名称',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialBalance = parseFloat(form.value.initialBalance) || 0
|
||||||
|
|
||||||
|
saving.value = true
|
||||||
|
try {
|
||||||
|
const data = await updateAccount({
|
||||||
|
name: form.value.name.trim(),
|
||||||
|
initialBalance: initialBalance
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
account.value = data
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存账户失败', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '保存失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
saving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadAccount()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page-scroll {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: calc(50px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
min-height: calc(100vh - 100rpx);
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 20rpx;
|
||||||
|
padding-bottom: calc(170rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: 30rpx;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-section {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-amount {
|
||||||
|
font-size: 64rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-amount.positive {
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-amount.negative {
|
||||||
|
color: #fa3534;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-section {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
padding-bottom: 30rpx;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
display: block;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.income {
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.expense {
|
||||||
|
color: #fa3534;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 20rpx;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
display: block;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer {
|
||||||
|
padding: 0 30rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
background: #667eea;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view class="header">
|
<view class="header">
|
||||||
|
<view class="header-top">
|
||||||
<text class="title">我的账单</text>
|
<text class="title">我的账单</text>
|
||||||
|
<view class="account-btn" @click="goToAccount">
|
||||||
|
<text class="account-icon">💰</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view class="summary">
|
<view class="summary">
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<text class="label">本月支出</text>
|
<text class="label">本月支出</text>
|
||||||
@ -110,6 +115,13 @@ const viewBill = (bill) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goToAccount = () => {
|
||||||
|
// 跳转到账户管理页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/account/account'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const onPullDownRefresh = () => {
|
const onPullDownRefresh = () => {
|
||||||
loadBills()
|
loadBills()
|
||||||
loadMonthlyStatistics()
|
loadMonthlyStatistics()
|
||||||
@ -168,13 +180,40 @@ export default {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-top {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 40rpx;
|
font-size: 40rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 30rpx;
|
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.account-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-btn:active {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-icon {
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.summary {
|
.summary {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="login-container">
|
<view class="login-container">
|
||||||
|
|
||||||
<view class="login-header">
|
<view class="login-header">
|
||||||
<text class="app-title">强宝爱记账</text>
|
<text class="app-title">强宝爱记账</text>
|
||||||
<text class="app-subtitle">智能记账,轻松管理</text>
|
<text class="app-subtitle">智能记账,轻松管理</text>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user