feat🔫: bill表格

This commit is contained in:
clz 2022-09-06 17:51:46 +08:00
parent 6b54a5dc9d
commit d7659d83b9
5 changed files with 117 additions and 16 deletions

View File

@ -17,6 +17,7 @@
.content {
flex: 1 1;
padding: 10px;
overflow: auto;
}
.footer {
}

View File

@ -1,10 +1,10 @@
export const useBill = () => {
// const [bills, setBills] = useState<IBill[]>([])
// const [_bills, setBills] = useState<IBill[]>([])
//
// useEffect(() => {
// getBills().then(setBills).catch(console.dir)
// }, [])
// return {
// bills,
// _bills,
// }
}

View File

@ -1,2 +1,14 @@
.record {
}
height: 100%;
display: flex;
flex-direction: column;
justify-content: start;
}
.new {
}
.table {
flex: 1 1;
overflow: auto;
}

View File

@ -6,15 +6,21 @@ import {
message,
Radio,
Select,
Space
Space, Table
} from "antd";
import {
ArrowDownOutlined,
CloudUploadOutlined, DeleteOutlined,
} from "@ant-design/icons";
import {useContext, useEffect, useRef, useState} from "react";
import {BillType, EmptyBill} from "../../model";
import {BillType, EmptyBill, IBill} from "../../model";
import moment from "moment/moment";
import {BillContext} from "../../store";
import {observer} from "mobx-react-lite";
import styles from "./Record.module.scss"
import {BaseSelectRef} from "rc-select/lib/BaseSelect";
import {createBill} from "../../api/bills";
function Record() {
@ -35,12 +41,56 @@ function Record() {
}, [clsRef])
// table
const columns = [
{
title: "日期",
dataIndex: "date",
key: "date",
},
{
title: "类别",
dataIndex: "cls",
key: "cls",
},
{
title: "标签",
dataIndex: "label",
key: "label",
},
{
title: "金额",
dataIndex: "money",
key: "money",
},
{
title: "备注",
dataIndex: "options",
key: "options",
},
{
title: "操作",
key: 'action',
render: (_: any, record: any) => (
<Space>
<Button
type="primary"
danger
icon={<DeleteOutlined/>}
onClick={() => setDataSource(datasource.filter(bill => bill !== record))}
/>
</Space>
),
},
]
const [datasource, setDataSource] = useState<IBill[]>([])
const typeOpt = [
{label: '支出', value: BillType.consume},
{label: '收入', value: BillType.income},
];
// 提交到表格
const submit = async () => {
const bill = EmptyBill()
bill.type = billType
@ -63,12 +113,32 @@ function Record() {
}
if (checkBill()) {
await billStore.add(bill)
Reflect.set(bill, "key", crypto.randomUUID())
setDataSource([bill, ...datasource])
reset()
} else {
message.error("请输入完整")
}
}
// 上传云端
const [uploadLoading, setUploadLoading] = useState(false)
const upload = async () => {
setUploadLoading(true)
const failures = []
for (let bill of datasource) {
try {
const {id} = await createBill(bill)
if (!id) failures.push(bill)
} catch (e) {
failures.push(bill)
}
}
setDataSource(failures)
setUploadLoading(false)
}
return (
<div className={styles.record}>
<div className={styles.new}>
@ -81,6 +151,7 @@ function Record() {
onChange={e => setBillType(e.target.value)}
/>
<DatePicker
allowClear={false}
value={moment(date, 'YYYY-MM-DD')}
onChange={(_, dateStr) => setDate(dateStr)}
/>
@ -117,6 +188,7 @@ function Record() {
cls2label.consume[cls]
.map(la => <Select.Option key={la} value={la}>{la}</Select.Option>)
}
<Select.Option key={"other"} value={"其他"}>{"其他"}</Select.Option>)
</Select>
<InputNumber
style={{width: 120}}
@ -135,14 +207,27 @@ function Record() {
/>
<Button
type="primary"
icon={<ArrowDownOutlined/>}
onKeyUp={e => e.key === "Tab"
&& clsRef.current!.focus()
}
onClick={submit}
></Button>
>
</Button>
</Space>
</div>
<div className={styles.table}></div>
<div className={styles.table}>
<Table dataSource={datasource} columns={columns}></Table>
<Button
icon={<CloudUploadOutlined/>}
type="primary"
loading={uploadLoading}
onClick={upload}
>
</Button>
</div>
</div>
)
}

View File

@ -8,25 +8,28 @@ import * as R from "ramda"
*
*/
export class Bill {
bills: IBill[] = [];
private _bills: IBill[] = [];
// _cls2label: IClass = {consume: new Map<string, string[]>(), income: []}
_cls2label: { consume: Record<string, string[]>, income: [] } = {consume: {}, income: []}
private _cls2label: { consume: Record<string, string[]>, income: [] } = {consume: {}, income: []}
constructor() {
makeAutoObservable(this)
this.fetchClass().then()
}
get bills() {
return this._bills
}
get cls2label() {
return this._cls2label
}
get listAllByDate() {
return R.groupBy((bill: IBill) => bill.date)(this.bills)
return R.groupBy((bill: IBill) => bill.date)(this._bills)
}
get listAllByClass() {
return R.groupBy((bill: IBill) => bill.cls)(this.bills)
return R.groupBy((bill: IBill) => bill.cls)(this._bills)
}
get listDailyMoney() {
@ -40,7 +43,7 @@ export class Bill {
R.sum,
R.map((bill: IBill) => bill.money)
)
return functions(this.bills)
return functions(this._bills)
}
get meanMoneyByDate() {
@ -54,14 +57,14 @@ export class Bill {
const {id} = await createBill(bill)
bill.id = id
runInAction(() => {
this.bills.push(bill);
this._bills.push(bill);
})
}
async fetch(year: number, month: number) {
const data = await getBills(year, month)
runInAction(() => {
this.bills = data
this._bills = data
})
}