feat🔫: 添加记录入账功能

This commit is contained in:
clz 2022-09-06 23:57:26 +08:00
parent ee9eb0e7a6
commit e7283c41ca
4 changed files with 103 additions and 73 deletions

View File

@ -12,12 +12,12 @@
display: flex;
flex: 1 1;
flex-direction: column;
overflow: auto;
.header {
}
.content {
flex: 1 1;
padding: 10px;
overflow: auto;
}
.footer {
}

View File

@ -1,12 +1,12 @@
import styles from "./Home.module.scss"
import * as R from 'ramda'
import {IBill} from "../../model"
import {BillType, IBill} from "../../model"
import Bar from "../../components/charts/bar"
import {useContext, useEffect, useState} from "react";
import {BillContext} from "../../store";
import {observer} from "mobx-react-lite";
import Pie from "../../components/charts/pie";
import {Card, DatePicker} from "antd";
import {Card, DatePicker, Radio, Space} from "antd";
import moment from 'moment';
import 'moment/locale/zh-cn';
@ -37,6 +37,12 @@ const Home = () => {
setMonth(d.getMonth() + 1)
}
const typeOpt = [
{label: '支出', value: BillType.consume},
{label: '收入', value: BillType.income},
];
const [billType, setBillType] = useState(BillType.consume)
const TotalMoney = () => <Card>
{"总金额"}
{billStore.totalMoney}
@ -45,15 +51,24 @@ const Home = () => {
return (
<div className={styles.home}>
<div className={styles.total}>
<Space align="start">
<DatePicker
picker="month"
value={moment(`${year}-${month}`, 'YYYY-MM')}
onChange={changeDate}
/>
<Radio.Group
options={typeOpt}
optionType="button"
buttonStyle="solid"
value={billType}
onChange={e => setBillType(e.target.value)}
/>
<TotalMoney/>
</Space>
</div>
<Bar data={transformer(billStore.listAllByDate)}/>
<Pie data={transformer(billStore.listAllByClass)}/>
<Bar data={transformer(billStore.groupByDate(billType))}/>
<Pie data={transformer(billStore.groupByClass(billType))}/>
</div>
)
}

View File

@ -1,18 +1,6 @@
import {
Button,
DatePicker,
Input,
InputNumber,
message,
Radio,
Select,
Space, Table
} from "antd";
import {
ArrowDownOutlined,
CloudUploadOutlined, DeleteOutlined,
} from "@ant-design/icons";
import { useContext, useEffect, useRef, useState } from "react";
import {Button, DatePicker, Input, InputNumber, message, Radio, Select, Space, Table, Tag} from "antd";
import {ArrowDownOutlined, CloudUploadOutlined, DeleteOutlined,} from "@ant-design/icons";
import {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
import {BillType, EmptyBill, IBill} from "../../model";
import moment from "moment/moment";
import {BillContext} from "../../store";
@ -60,8 +48,13 @@ function Record() {
},
{
title: "金额",
dataIndex: "money",
key: "money",
render: (_: any, record: IBill) => {
const isConsume = record.type === BillType.consume
const color = isConsume ? "red" : "green"
const flag = isConsume ? "-" : "+"
return <Tag color={color}>{flag}{record.money}</Tag>
}
},
{
title: "备注",
@ -100,7 +93,7 @@ function Record() {
bill.money = Number(money)
bill.options = options
const checkBill = () => {
return bill.cls !== '' && bill.label !== '' && bill.money > 0
return bill.cls !== '' && (billType === BillType.income || bill.label !== '') && bill.money > 0
}
const reset = () => {
setCls("")
@ -111,7 +104,6 @@ function Record() {
clsRef.current.focus()
}
}
if (checkBill()) {
Reflect.set(bill, "key", Date.now().toString() + Math.random().toString())
setDataSource([bill, ...datasource])
@ -138,12 +130,22 @@ function Record() {
setUploadLoading(false)
}
let classData: string[]
switch (billType) {
case BillType.consume:
classData = Object.keys(cls2label.consume)
break
case BillType.income:
classData = cls2label.income
break
}
return (
<div className={styles.record}>
<div className={styles.new}>
<Space align="start">
<Radio.Group
style={{width: 120}}
options={typeOpt}
optionType="button"
buttonStyle="solid"
@ -151,6 +153,7 @@ function Record() {
onChange={e => setBillType(e.target.value)}
/>
<DatePicker
style={{width: 120}}
allowClear={false}
value={moment(date, 'YYYY-MM-DD')}
onChange={(_, dateStr) => setDate(dateStr)}
@ -167,13 +170,14 @@ function Record() {
value={cls === "" ? null : cls}
onChange={c => {
setCls(c)
setLabel(cls2label.consume[c][0])
if (billType === BillType.consume) setLabel(cls2label.consume[c][0])
}}
>
{Object.keys(cls2label.consume)
.map(c => <Select.Option key={c} value={c}>{c}</Select.Option>)
{
classData.map(c => <Select.Option key={c} value={c}>{c}</Select.Option>)
}
</Select>
{billType === BillType.consume && (
<Select
style={{width: 120}}
showSearch
@ -190,6 +194,7 @@ function Record() {
}
<Select.Option key={"other"} value={"其他"}>{"其他"}</Select.Option>)
</Select>
)}
<InputNumber
style={{width: 120}}
placeholder="money"
@ -199,18 +204,17 @@ function Record() {
onKeyDown={e => e.key === "Enter" && submit()}
/>
<Input.TextArea
value={options}
onChange={value => setOptions(value.target.value)}
style={{width: 180}}
rows={1}
placeholder="备注"
value={options}
onChange={value => setOptions(value.target.value)}
onKeyDown={e => e.key === "Enter" && submit()}
/>
<Button
type="primary"
icon={<ArrowDownOutlined/>}
onKeyUp={e => e.key === "Tab"
&& clsRef.current!.focus()
}
onKeyUp={e => e.key === "Tab" && clsRef.current!.focus()}
onClick={submit}
>

View File

@ -1,7 +1,7 @@
import {makeAutoObservable, runInAction} from "mobx";
import {createContext} from "react";
import {createBill, getBills, getClass} from "../api/bills";
import {IBill} from "../model";
import {BillType, IBill} from "../model";
import * as R from "ramda"
/**
@ -20,20 +20,31 @@ export class Bill {
get bills() {
return this._bills
}
get cls2label() {
return this._cls2label
}
get listAllByDate() {
return R.groupBy((bill: IBill) => bill.date)(this._bills)
groupByDate(type?: BillType) {
const classFun = R.filter((bill: IBill) => R.of(bill.type).length === 0 || bill.type === type)
const functions = R.compose(
R.groupBy((bill: IBill) => bill.date),
classFun,
)
return functions(this._bills)
}
get listAllByClass() {
return R.groupBy((bill: IBill) => bill.cls)(this._bills)
groupByClass(type?: BillType) {
const classFun = R.filter((bill: IBill) => R.of(bill.type).length === 0 || bill.type === type)
const functions = R.compose(
R.groupBy((bill: IBill) => bill.cls),
classFun,
)
return functions(this._bills)
}
get listDailyMoney() {
return this.listAllByDate
return this.groupByDate
}
get totalMoney() {
@ -47,7 +58,7 @@ export class Bill {
}
get meanMoneyByDate() {
const days = Reflect.ownKeys(this.listAllByDate).length
const days = Reflect.ownKeys(this.groupByDate).length
if (days === 0) return 0
return this.totalMoney / days
}