diff --git a/.vs/ExpenseRecord/DesignTimeBuild/.dtbcache.v2 b/.vs/ExpenseRecord/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000..e2373d2 Binary files /dev/null and b/.vs/ExpenseRecord/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/ExpenseRecord/FileContentIndex/339eda24-9029-409b-9eee-bc26f12495fe.vsidx b/.vs/ExpenseRecord/FileContentIndex/339eda24-9029-409b-9eee-bc26f12495fe.vsidx new file mode 100644 index 0000000..fcf2e94 Binary files /dev/null and b/.vs/ExpenseRecord/FileContentIndex/339eda24-9029-409b-9eee-bc26f12495fe.vsidx differ diff --git a/.vs/ExpenseRecord/FileContentIndex/3e34afab-1d40-44d0-a90c-c24c8cd73546.vsidx b/.vs/ExpenseRecord/FileContentIndex/3e34afab-1d40-44d0-a90c-c24c8cd73546.vsidx new file mode 100644 index 0000000..a6920b1 Binary files /dev/null and b/.vs/ExpenseRecord/FileContentIndex/3e34afab-1d40-44d0-a90c-c24c8cd73546.vsidx differ diff --git a/.vs/ExpenseRecord/FileContentIndex/5f049127-5cd8-4f62-81ce-14eff33f8f80.vsidx b/.vs/ExpenseRecord/FileContentIndex/5f049127-5cd8-4f62-81ce-14eff33f8f80.vsidx new file mode 100644 index 0000000..a6e7829 Binary files /dev/null and b/.vs/ExpenseRecord/FileContentIndex/5f049127-5cd8-4f62-81ce-14eff33f8f80.vsidx differ diff --git a/.vs/ExpenseRecord/FileContentIndex/b74583b2-94c0-4531-b3d2-17ac1046c661.vsidx b/.vs/ExpenseRecord/FileContentIndex/b74583b2-94c0-4531-b3d2-17ac1046c661.vsidx new file mode 100644 index 0000000..c6023f1 Binary files /dev/null and b/.vs/ExpenseRecord/FileContentIndex/b74583b2-94c0-4531-b3d2-17ac1046c661.vsidx differ diff --git a/.vs/ExpenseRecord/FileContentIndex/bf66d6a7-17e7-405c-aa44-ae7ff7a5da67.vsidx b/.vs/ExpenseRecord/FileContentIndex/bf66d6a7-17e7-405c-aa44-ae7ff7a5da67.vsidx new file mode 100644 index 0000000..a9b30d2 Binary files /dev/null and b/.vs/ExpenseRecord/FileContentIndex/bf66d6a7-17e7-405c-aa44-ae7ff7a5da67.vsidx differ diff --git a/.vs/ExpenseRecord/config/applicationhost.config b/.vs/ExpenseRecord/config/applicationhost.config new file mode 100644 index 0000000..8c14e9a --- /dev/null +++ b/.vs/ExpenseRecord/config/applicationhost.config @@ -0,0 +1,964 @@ + + + + + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.vs/ExpenseRecord/v17/.futdcache.v2 b/.vs/ExpenseRecord/v17/.futdcache.v2 new file mode 100644 index 0000000..fb67118 Binary files /dev/null and b/.vs/ExpenseRecord/v17/.futdcache.v2 differ diff --git a/.vs/ExpenseRecord/v17/.suo b/.vs/ExpenseRecord/v17/.suo new file mode 100644 index 0000000..36de27e Binary files /dev/null and b/.vs/ExpenseRecord/v17/.suo differ diff --git a/.vs/ExpenseRecord/v17/fileList.bin b/.vs/ExpenseRecord/v17/fileList.bin new file mode 100644 index 0000000..23e5a71 Binary files /dev/null and b/.vs/ExpenseRecord/v17/fileList.bin differ diff --git a/.vs/ProjectEvaluation/expenserecord.metadata.v7.bin b/.vs/ProjectEvaluation/expenserecord.metadata.v7.bin new file mode 100644 index 0000000..1c187d6 Binary files /dev/null and b/.vs/ProjectEvaluation/expenserecord.metadata.v7.bin differ diff --git a/.vs/ProjectEvaluation/expenserecord.projects.v7.bin b/.vs/ProjectEvaluation/expenserecord.projects.v7.bin new file mode 100644 index 0000000..c50c6aa Binary files /dev/null and b/.vs/ProjectEvaluation/expenserecord.projects.v7.bin differ diff --git a/ExpenseRecord/ClientApp/src/app/app-routing.module.ts b/ExpenseRecord/ClientApp/src/app/app-routing.module.ts new file mode 100644 index 0000000..f88ba14 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/app-routing.module.ts @@ -0,0 +1,17 @@ +import { RouterModule, Routes } from "@angular/router"; +import { NgModel } from "@angular/forms"; +import { NgModule } from "@angular/core"; + +import { ExpenseComponent } from "./expense/expense.component"; +import { ChildComponent } from "./expense/child/child.component"; + + +const route: Routes=[ + {path:'',component:ExpenseComponent}, + {path:'new',component:ChildComponent}, +]; +@NgModule({ + imports: [RouterModule.forRoot(route)], + exports: [RouterModule] +}) +export class AppRoutingModule{} \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/app.component.html b/ExpenseRecord/ClientApp/src/app/app.component.html index fa05fe7..c60267b 100644 --- a/ExpenseRecord/ClientApp/src/app/app.component.html +++ b/ExpenseRecord/ClientApp/src/app/app.component.html @@ -1 +1,11 @@ - + + + + Expense + + +
+ +
+ + \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/app.module.ts b/ExpenseRecord/ClientApp/src/app/app.module.ts index 73c9837..5f68935 100644 --- a/ExpenseRecord/ClientApp/src/app/app.module.ts +++ b/ExpenseRecord/ClientApp/src/app/app.module.ts @@ -7,19 +7,30 @@ import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; import { CounterComponent } from './counter/counter.component'; import {GreetingComponent} from "./greeting/greeting.component"; +import { ExpenseComponent } from './expense/expense.component'; +import { ExpenseService } from './expense/expense.service'; +import "@angular/compiler"; +import { ChildComponent } from './expense/child/child.component'; +import { ExpenseModule } from './expense/expense.module'; +import { AppRoutingModule } from './app-routing.module'; @NgModule({ declarations: [ AppComponent, CounterComponent, - GreetingComponent + GreetingComponent, + ExpenseComponent, + ], imports: [ BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), HttpClientModule, FormsModule, + RouterModule, + ExpenseModule, + AppRoutingModule ], - providers: [], + providers: [ExpenseService], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/ExpenseRecord/ClientApp/src/app/app.server.module.ts b/ExpenseRecord/ClientApp/src/app/app.server.module.ts deleted file mode 100644 index cfb0e02..0000000 --- a/ExpenseRecord/ClientApp/src/app/app.server.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { NgModule } from '@angular/core'; -import { ServerModule } from '@angular/platform-server'; -import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; -import { AppComponent } from './app.component'; -import { AppModule } from './app.module'; - -@NgModule({ - imports: [AppModule, ServerModule, ModuleMapLoaderModule], - bootstrap: [AppComponent] -}) -export class AppServerModule { } diff --git a/ExpenseRecord/ClientApp/src/app/expense/child/child.component.css b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.css new file mode 100644 index 0000000..8946723 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.css @@ -0,0 +1,70 @@ +.centered-box { + position: fixed; + top: 50%; /* 将框顶部垂直居中 */ + left: 50%; /* 将框左侧水平居中 */ + transform: translate(-50%, -50%); /* 使用transform属性来微调位置 */ + background-color: #fff; + width: 80%; /* 调整框的宽度和高度 */ + height: 85%; + border: 2px solid rgba(3, 41, 81, 0.5); + border-radius: 5px; + padding: 20px; +} +.input{ + border: 2px, solid rgba(3, 41, 81, 0.5); + font-size: large; + text-align: center; + width: 100%; +} +.goback{ + height: 50px; + width: 100%; + align-content: left; + align-self: flex-start; + background-color: rgba(17, 64, 108, 0.5); + font-size: large; + color: #fff; + margin-top: 5px; + font-family: 'Montserrat', sans-serif; +} +.title{ + color: rgba(3, 41, 81, 0.8); + width: 100%; + text-align: center; + font-size: 30px;; + /* font-family: 'Montserrat', serif; */ + height:10%; + margin-bottom: 0%; +} +.table{ + width: 100%; + height: 18%; + text-align: center; + color:rgba(3, 41, 81, 1); +} +.label{ + border: 2px, solid rgba(3, 41, 81, 0.5); + font-size: large; + text-align: center; +} + + +.container{ + height: 80%; + line-height: 3; + overflow-y: auto; + font-size: large; + font-family: 'Montserrat', sans-serif; +} +.save{ + height: 50px; + width: 100%; + align-content: center; + align-self: flex-start; + background-color: rgba(17, 64, 108, 0.5); + font-size: large; + color: #fff; + margin-top: 5px; + font-family: 'Montserrat', sans-serif; + +} \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/expense/child/child.component.html b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.html new file mode 100644 index 0000000..4125080 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.html @@ -0,0 +1,26 @@ +
+ +
+
+ + + + + + + +
+ + + + + + +
+ +
+
\ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/expense/child/child.component.spec.ts b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.spec.ts new file mode 100644 index 0000000..357a919 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChildComponent } from './child.component'; + +describe('ChildComponent', () => { + let component: ChildComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChildComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ChildComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ExpenseRecord/ClientApp/src/app/expense/child/child.component.ts b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.ts new file mode 100644 index 0000000..7042837 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/child/child.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { INewExpenseItem } from '../newexpense'; +import { ExpenseService } from '../expense.service'; + +@Component({ + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'] +}) +export class ChildComponent implements OnInit { + selectedExpenseType: string =''; + + + constructor(private route: ActivatedRoute, + private router: Router, + private expenseService:ExpenseService) { } + public Description:string=''; + + public Amount :number =0; + ngOnInit(): void { + } + onBack(): void { + this.router.navigateByUrl('/'); + //navigate(['items']); + } + save() { + // if (!this.content) { + const newItem: INewExpenseItem = { + description: this.Description, + type: this.selectedExpenseType, + amount:this.Amount + + } + console.log(newItem) + this.expenseService.addItems(newItem).subscribe() + } +} diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense-service.service.spec.ts b/ExpenseRecord/ClientApp/src/app/expense/expense-service.service.spec.ts new file mode 100644 index 0000000..d5bc651 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense-service.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; +import { ExpenseService } from './expense.service'; + + +describe('ExpenseServiceService', () => { + let service: ExpenseService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ExpenseService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.component.css b/ExpenseRecord/ClientApp/src/app/expense/expense.component.css new file mode 100644 index 0000000..a227e77 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.component.css @@ -0,0 +1,59 @@ +.centered-box { + position: fixed; + top: 50%; /* 将框顶部垂直居中 */ + left: 50%; /* 将框左侧水平居中 */ + transform: translate(-50%, -50%); /* 使用transform属性来微调位置 */ + background-color: #fff; + width: 80%; /* 调整框的宽度和高度 */ + height: 85%; + border: 2px solid rgba(3, 41, 81, 0.5); + border-radius: 5px; + padding: 20px; +} +.title{ + color: rgba(3, 41, 81, 0.8); + width: 100%; + text-align: center; + font-size: 30px;; + /* font-family: 'Montserrat', serif; */ + height:10%; + margin-bottom: 0%; +} +.table{ + width: 100%; + height: 18%; + text-align: center; + color:rgba(3, 41, 81, 1); +} +.container{ + height: 80%; + line-height: 3; + overflow-y: auto; + font-size: large; + font-family: 'Montserrat', sans-serif; +} +.Created{ + height: 50px; + width: 100%; + align-content: center; + align-self: flex-end; + background-color: rgba(17, 64, 108, 0.5); + font-size: large; + color: #fff; + margin-top: 5px; + font-family: 'Montserrat', sans-serif; + +} +.deletebutton{ + background-color: #fff; + border-color: #fff; + border-radius: 10%; + align-content: center; + font-size: large; + color: rgba(17, 64, 108, 1); + margin-top: 5px; + font-family: 'Montserrat', sans-serif; + + + +} diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.component.html b/ExpenseRecord/ClientApp/src/app/expense/expense.component.html new file mode 100644 index 0000000..699f4c2 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.component.html @@ -0,0 +1,27 @@ +
+

{{title}}

+
+ + + + + + + + + + + + + + + + + + + +
DescriptionTypeAmountCreateTimeDelete?
{{item.description}}{{item.type}}{{item.amount}}{{item.createTime}}
+
+ + +
\ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.component.spec.ts b/ExpenseRecord/ClientApp/src/app/expense/expense.component.spec.ts new file mode 100644 index 0000000..fcca3d8 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExpenseComponent } from './expense.component'; + +describe('ExpenseComponent', () => { + let component: ExpenseComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExpenseComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ExpenseComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.component.ts b/ExpenseRecord/ClientApp/src/app/expense/expense.component.ts new file mode 100644 index 0000000..10d8ff8 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.component.ts @@ -0,0 +1,73 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { IExpenseItem } from './expenseItem'; +import { HttpClient } from '@angular/common/http'; +import { ExpenseService } from './expense.service'; +import { ActivatedRoute } from '@angular/router'; + + +@Component({ + selector: 'app-expense', + templateUrl: './expense.component.html', + styleUrls: ['./expense.component.css'], + providers: [ExpenseService] // 声明服务提供者 +}) + +export class ExpenseComponent implements OnInit { + + constructor(private itemservice:ExpenseService, + private route: ActivatedRoute){ + + } + + title = "Expense Record" + existingRecords : IExpenseItem[] = []; + ngOnInit(): void { + this.getAll(); + + } + + + // getAll(): void { + // this.itemservice.getItems().subscribe({ + // next: (data) => { + // // 统一日期格式为 ISO 8601 格式 + // data.forEach((item) => { + // item.createTime = this.formatDateToISO(item.createTime); + // }); + + // // 对数据按日期倒序排序 + // this.existingRecords = data.sort((a, b) => new Date(b.createTime) - new Date(a.createTime)); + // } + + // }); + // } + + getAll(): void { + this.itemservice.getItems().subscribe({ + next: (data) => { + this.existingRecords = data.reverse(); + } + }); + } + + formatDateToISO(dateString: string): string { + if (/^\d{8}$/.test(dateString)) { + const year = dateString.substring(0, 4); + const month = dateString.substring(4, 6); + const day = dateString.substring(6, 8); + return `${year}-${month}-${day}`; + } else if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) { + return dateString; + } else { + return ''; + } + } + + deleteItems(id: string){ + this.itemservice.deleteExpense(id).subscribe(()=>{ + this.getAll() + }) + } +} + + diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.module.ts b/ExpenseRecord/ClientApp/src/app/expense/expense.module.ts new file mode 100644 index 0000000..d49af97 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { ChildComponent } from './child/child.component'; +import { ExpenseComponent } from './expense.component'; + +@NgModule({ + declarations: [ + ChildComponent + ], + imports: [ + CommonModule, + FormsModule, + HttpClientModule, + RouterModule.forChild([ + { path:'',component:ExpenseComponent}, + { path:'new',component: ChildComponent}] + ) + ] +}) +export class ExpenseModule { } \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/expense/expense.service.ts b/ExpenseRecord/ClientApp/src/app/expense/expense.service.ts new file mode 100644 index 0000000..5896f74 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expense.service.ts @@ -0,0 +1,33 @@ +import { HttpClient } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { Observable, tap } from 'rxjs'; +import { IExpenseItem } from './expenseItem'; +import { INewExpenseItem } from './newexpense'; + +@Injectable({ + providedIn: 'root' +}) +export class ExpenseService { + + private baseUrl = "https://localhost:7081/api/v1/Expense"; + //private baseUrl = "./assets/api/expense.json"; + constructor(private http: HttpClient,) { + + } + + getItems(): Observable { + return this.http.get(this.baseUrl) + .pipe( + tap(data => console.log('All: ', JSON.stringify(data))) + )}; + + addItems(newItem:INewExpenseItem):Observable{ + return this.http.post<[IExpenseItem]>(this.baseUrl,newItem) + } + + deleteExpense(id:string):Observable{ + const deleteUrl = `${this.baseUrl}/${id}`; + console.log(deleteUrl); + return this.http.delete(deleteUrl); + } +} diff --git a/ExpenseRecord/ClientApp/src/app/expense/expenseItem.ts b/ExpenseRecord/ClientApp/src/app/expense/expenseItem.ts new file mode 100644 index 0000000..e71c8fa --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/expenseItem.ts @@ -0,0 +1,8 @@ +export interface IExpenseItem +{ + id:string + description: string; + type:string; + amount:number; + createTime: string; +} \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/app/expense/newexpense.ts b/ExpenseRecord/ClientApp/src/app/expense/newexpense.ts new file mode 100644 index 0000000..7a8eaa5 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/app/expense/newexpense.ts @@ -0,0 +1,7 @@ +export interface INewExpenseItem +{ + description: string; + type:string; + amount:number; + +} \ No newline at end of file diff --git a/ExpenseRecord/ClientApp/src/assets/api/expense.json b/ExpenseRecord/ClientApp/src/assets/api/expense.json new file mode 100644 index 0000000..272e839 --- /dev/null +++ b/ExpenseRecord/ClientApp/src/assets/api/expense.json @@ -0,0 +1,26 @@ +[ + { + "Amount": 1, + "Description": "AAAitem1", + "Type": "meals", + "CreateTime": "20230709" + }, + { + "Amount": 22, + "Description": "BBBitem1", + "Type": "meals", + "CreateTime": "20230909" + }, + { + "Amount": 233, + "Description": "CCCitem1", + "Type": "meals", + "CreateTime": "20030909" + }, + { + "Amount": 22, + "Description": "DDitem1", + "Type": "meals", + "CreateTime": "2019-07-31" + } + ] \ No newline at end of file diff --git a/ExpenseRecord/Controllers/ExpenseController.cs b/ExpenseRecord/Controllers/ExpenseController.cs new file mode 100644 index 0000000..a4d8a86 --- /dev/null +++ b/ExpenseRecord/Controllers/ExpenseController.cs @@ -0,0 +1,55 @@ +using ExpenseRecord.DataModel; +using ExpenseRecord.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace ExpenseRecord.Controllers +{ + [ApiController] + [Produces("application/json")] + [Route("api/v1/[controller]")] + [AllowAnonymous] + public class ExpenseController : ControllerBase + { + private readonly IExpenseService _expenseServices; + public ExpenseController(IExpenseService expenseService) + { + _expenseServices = expenseService; + } + + [HttpGet] + public async Task> GetALL() + { + var result = await _expenseServices.GetAsync(); + if (result == null) + { + return new List(); + } + return result; + } + + [HttpPost] + public async Task> PostAsync([FromBody] ExpenseItemCreateRequest toDoItemCreateRequest) + { + DateTime currentTime = DateTime.Now; + var toDoItemDto = new ExpenseItem + { + Id = Guid.NewGuid().ToString(), + Description = toDoItemCreateRequest.Description, + Type = toDoItemCreateRequest.Type, + Amount = toDoItemCreateRequest.Amount, + CreateTime = currentTime.ToString("yyyyMMdd"), + + }; + await _expenseServices.CreateAsync(toDoItemDto); + return Created("", toDoItemDto); + } + [HttpDelete("{id}")] + public async Task DeleteAsync(string id) + { + await _expenseServices.DeleteAsync(id); + + } + + } +} diff --git a/ExpenseRecord/DataModel/ExpenseItem.cs b/ExpenseRecord/DataModel/ExpenseItem.cs new file mode 100644 index 0000000..955f697 --- /dev/null +++ b/ExpenseRecord/DataModel/ExpenseItem.cs @@ -0,0 +1,15 @@ +using MongoDB.Bson.Serialization.Attributes; + +namespace ExpenseRecord.DataModel +{ + public class ExpenseItem + { + [BsonId] + public string Id { get; set; } + public string Description { get; set; } + public string Type { get; set; } + public double Amount { get; set; } + public string CreateTime { get; set; } // 修正拼写 + } + +} diff --git a/ExpenseRecord/DataModel/ExpenseItemCreateRequest.cs b/ExpenseRecord/DataModel/ExpenseItemCreateRequest.cs new file mode 100644 index 0000000..8f2ded0 --- /dev/null +++ b/ExpenseRecord/DataModel/ExpenseItemCreateRequest.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace ExpenseRecord.DataModel +{ + public class ExpenseItemCreateRequest + { + [Required] + [StringLength(50)] + public string Description { get; set; } + public string Type { get; set; } + public double Amount { get; set; } + + } +} diff --git a/ExpenseRecord/ExpenseRecord.csproj b/ExpenseRecord/ExpenseRecord.csproj index 0fd2d82..1a36bf1 100644 --- a/ExpenseRecord/ExpenseRecord.csproj +++ b/ExpenseRecord/ExpenseRecord.csproj @@ -12,6 +12,7 @@ + diff --git a/ExpenseRecord/Program.cs b/ExpenseRecord/Program.cs index 2a69b14..7cd2447 100644 --- a/ExpenseRecord/Program.cs +++ b/ExpenseRecord/Program.cs @@ -1,10 +1,33 @@ +using ExpenseRecord.Services; + + var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); +builder.Services.AddCors(policy => + +{ + + policy.AddPolicy("CorsPolicy", opt => opt + + .AllowAnyOrigin() + + .AllowAnyHeader() + + .AllowAnyMethod() + + .WithExposedHeaders("X-Pagination")); + +}); + +builder.Services.AddSingleton(); +builder.Services.Configure(builder.Configuration.GetSection("ExpenseDatabases")); + var app = builder.Build(); +app.UseCors("CorsPolicy"); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) diff --git a/ExpenseRecord/Services/DataBaseSetting.cs b/ExpenseRecord/Services/DataBaseSetting.cs new file mode 100644 index 0000000..014b54e --- /dev/null +++ b/ExpenseRecord/Services/DataBaseSetting.cs @@ -0,0 +1,9 @@ +namespace ExpenseRecord.Services +{ + public class DataBaseSetting + { + public string ConnectionString { get; set; } = null!; + public string DatabaseName { get; set; } = null!; + public string CollectionName { get; set; } = null!; + } +} diff --git a/ExpenseRecord/Services/ExpenseService.cs b/ExpenseRecord/Services/ExpenseService.cs new file mode 100644 index 0000000..f56a292 --- /dev/null +++ b/ExpenseRecord/Services/ExpenseService.cs @@ -0,0 +1,52 @@ +using ExpenseRecord.DataModel; +using Microsoft.Extensions.Options; +using MongoDB.Driver; + +namespace ExpenseRecord.Services +{ + public class ExpenseService : IExpenseService + { + //依赖注入MongoDB数据库 + private readonly IMongoCollection _expenseItemCollection; + public ExpenseService(IOptions DataBaseSetting) + { + var mongoClient = new MongoClient(DataBaseSetting.Value.ConnectionString); + var mongoDatabase = mongoClient.GetDatabase(DataBaseSetting.Value.DatabaseName); + _expenseItemCollection = mongoDatabase.GetCollection(DataBaseSetting.Value.CollectionName); + } + //create + public async Task CreateAsync(ExpenseItem newToDoItem) + { + await _expenseItemCollection.InsertOneAsync(newToDoItem); + } + + //Getall + public async Task> GetAsync() + { + var expenseItemDtos = new List(); + var expenseItems = await _expenseItemCollection.Find(_ => true).ToListAsync(); + if (expenseItems is null) + { + return expenseItemDtos; + } + for (var i = 0; i< expenseItems.Count; i++) + { + expenseItemDtos.Add(new ExpenseItem + { + Id = expenseItems[i].Id, + Description = expenseItems[i].Description, + Type = expenseItems[i].Type, + Amount = expenseItems[i].Amount, + CreateTime = expenseItems[i].CreateTime, + + }); + } + return expenseItemDtos; + } + public async Task DeleteAsync(string id) + { + await _expenseItemCollection.DeleteOneAsync(x => x.Id == id); + + } + } +} diff --git a/ExpenseRecord/Services/IExpenseService.cs b/ExpenseRecord/Services/IExpenseService.cs new file mode 100644 index 0000000..9c19170 --- /dev/null +++ b/ExpenseRecord/Services/IExpenseService.cs @@ -0,0 +1,11 @@ +using ExpenseRecord.DataModel; + +namespace ExpenseRecord.Services +{ + public interface IExpenseService + { + Task> GetAsync(); + Task CreateAsync(ExpenseItem newItem); + Task DeleteAsync(string id); + } +} diff --git a/ExpenseRecord/WeatherForecast.cs b/ExpenseRecord/WeatherForecast.cs deleted file mode 100644 index fa9c69d..0000000 --- a/ExpenseRecord/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ExpenseRecord; - -public class WeatherForecast -{ - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } -} \ No newline at end of file diff --git a/ExpenseRecord/appsettings.json b/ExpenseRecord/appsettings.json index ad75fee..92781dd 100644 --- a/ExpenseRecord/appsettings.json +++ b/ExpenseRecord/appsettings.json @@ -1,10 +1,15 @@ { "Logging": { - "LogLevel": { + "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" - } - }, -"AllowedHosts": "*" + } + }, + "AllowedHosts": "*", + "ExpenseDatabases": { + "ConnectionString": "mongodb://localhost:27017/", + "DatabaseName": "Expense", + "CollectionName": "ExpenseItem" + } }