前言
本章节的主要内容是完善Blazor学生管理页面的编写和接口对接。
七天.NET 8 操作 SQLite 入门到实战详细教程
- 第一天 SQLite 简介
- 第二天 在 Windows 上配置 SQLite 环境
- 第三天 SQLite 快速入门
- 第四天 EasySQLite 前后端项目框架搭建
- 第五天引入 SQLite-net ORM 并封装常用方法
- 第六天后端班级管理相关接口完善和Swagger自定义配置
- 第七天BootstrapBlazor UI组件库引入(1)
- 第七天Blazor班级管理页面编写和接口对接(2)
EasySQLite 项目源码地址
Blazor简介和快速入门
不熟悉Blazor的同学可以先看这篇文章大概了解一下。
前端Table页面和接口对接代码
主要是常见Table的数据展示、数据添加、数据删除、数据修改等操作。
@page "/Student" @using Entity @using Entity.ViewModel @using System.Reflection @using Utility @using WebUI.Common @using WebUI.Services @inject HttpClient _httpClient; @inject DataLoaderService _dataLoader; <Table TItem="StudentViewModel" AutoGenerateColumns="true" ShowToolbar="true" IsMultipleSelect="true" OnSaveAsync="@OnSaveAsync" OnQueryAsync="@OnQueryAsync" OnDeleteAsync="@OnDeleteAsync" IsStriped="true" IsBordered="true" ShowSearch="true" IsPagination="true" ShowSearchText="true"> <!--通过设置 EditTemplate 自定义编辑弹窗,如果属性需要联动时必须像本例这样封装成一个独立的组件再放置到模板中--> <EditTemplate> <StudentEditor @bind-Value="context" /> </EditTemplate> <SearchTemplate> <GroupBox Title="搜索条件"> <div class="row g-3 form-inline"> <div class="col-12 col-sm-6"> <BootstrapInput @bind-Value="@context.Name" PlaceHolder="请输入学生姓名" maxlength="50" ShowLabel="true" DisplayText="姓名" /> </div> </div> </GroupBox> </SearchTemplate> </Table> @code { /// <summary> /// 数据查询 /// </summary> /// <param name="options">options</param> /// <returns></returns> private async Task<QueryData<StudentViewModel>> OnQueryAsync(QueryPageOptions options) { var searchModel = options.SearchModel as StudentViewModel; var getStudentData = new List<StudentViewModel>(); var getResults = await _httpClient.GetFromJsonAsync<ApiResponse<List<StudentViewModel>>>("api/Student/GetAllStudent").ConfigureAwait(false); if (getResults.Success) { // 数据模糊过滤筛选 if (!string.IsNullOrWhiteSpace(options.SearchText)) { getStudentData = getResults.Data.Where(x => x.Name.Contains(options.SearchText)).ToList(); } else if (searchModel != null && !string.IsNullOrWhiteSpace(searchModel.Name)) { getStudentData = getResults.Data.Where(x => x.Name.Contains(searchModel.Name)).ToList(); } else { getStudentData = getResults.Data.ToList(); } } //加载班级信息 await _dataLoader.LoadSchoolClassDataAsync().ConfigureAwait(false); // 内存分页 return await Task.FromResult(new QueryData<StudentViewModel>() { Items = getStudentData.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList(), TotalCount = getStudentData.Count() }); } /// <summary> /// 模拟数据增加和修改操作 /// </summary> /// <param name="studentInfo">studentInfo</param> /// <param name="changedType">changedType</param> /// <returns></returns> public async Task<bool> OnSaveAsync(StudentViewModel studentInfo, ItemChangedType changedType) { if (changedType.ToString() == "Update") { var addResult = await _httpClient.PutAsJsonAsync($"api/Student/UpdateStudent/{studentInfo.StudentID}", studentInfo).ConfigureAwait(false); if (UtilityBusiness.CheckResponse(addResult)) { return await Task.FromResult(true); } else { return await Task.FromResult(false); } } else if (changedType.ToString() == "Add") { var addResult = await _httpClient.PostAsJsonAsync("api/Student/CreateStudent", studentInfo).ConfigureAwait(false); if (UtilityBusiness.CheckResponse(addResult)) { return await Task.FromResult(true); } else { return await Task.FromResult(false); } } return await Task.FromResult(true); } /// <summary> /// 数据删除 /// </summary> /// <param name="items">items</param> /// <returns></returns> private async Task<bool> OnDeleteAsync(IEnumerable<StudentViewModel> items) { var deleteSuccessNum = 0; var StudentViewModelList = items.ToList(); foreach (var item in StudentViewModelList) { var delResult = await _httpClient.DeleteAsync($"api/Student/DeleteStudent/{item.StudentID}").ConfigureAwait(false); if (UtilityBusiness.CheckResponse(delResult)) { deleteSuccessNum++; } } if (deleteSuccessNum > 0) { return await Task.FromResult(true); } else { return await Task.FromResult(false); } } }
自定义编辑弹窗模板
StudentEditor.razor:
@using Entity @using Microsoft.Extensions.Caching.Memory @using WebUI.Services @inject HttpClient _httpClient; @inject DataLoaderService _dataLoader; @inject IMemoryCache _memoryCache; <div class="row g-3 form-inline"> <div class="col-12"> <BootstrapInput @bind-Value="@Value.ClassID" IsDisabled maxlength="50" /> </div> <div class="col-12"> <Select @bind-Value="@Value.ClassID" OnSelectedItemChanged="OnSelectedItemChanged" Items="Items" /> </div> <div class="col-12"> <BootstrapInput @bind-Value="@Value.Name" placeholder="请输入学生名称" maxlength="50" required /> </div> <div class="col-12"> <Select @bind-Value="@Value.Gender" Items="GenderItems" required /> </div> <div class="col-12"> <BootstrapInput @bind-Value="@Value.Age" placeholder="请输入年龄" maxlength="50" /> </div> </div>
StudentEditor.razor.cs:
using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; using System.Net.Http.Json; using System.Xml.Linq; using BootstrapBlazor.Components; using Entity; using Entity.ViewModel; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using WebUI.Services; namespace WebUI.Pages { public partial class StudentEditor { [Parameter] public StudentViewModel Value { get; set; } [Parameter] public EventCallback<StudentViewModel> ValueChanged { get; set; } [NotNull] private List<SelectedItem>? Items { get; set; } [NotNull] private List<SelectedItem>? GenderItems { get; set; } protected override async void OnInitialized() { base.OnInitialized(); List<SchoolClass>? getSchoolClass; if (_memoryCache.TryGetValue("SchoolClassData", out string data)) { getSchoolClass = JsonConvert.DeserializeObject<List<SchoolClass>>(data); } else { getSchoolClass = await _dataLoader.LoadSchoolClassDataAsync().ConfigureAwait(false); } Items = []; foreach (var item in getSchoolClass.OrderBy(x => x.ClassID).ToList()) { Items.Add(new SelectedItem { Value = item.ClassID.ToString(), Text = item.ClassName }); } if (string.IsNullOrWhiteSpace(Value.ClassName)) { Value.ClassName = Items.First().Text; Value.ClassID = Convert.ToInt32(Items.First().Value); } GenderItems = [new SelectedItem { Value = "男", Text = "男" }, new SelectedItem { Value = "女", Text = "女" }]; if (string.IsNullOrWhiteSpace(Value.Gender)) { Value.Gender = GenderItems.First().Text; } } /// <summary> /// 下拉框选项改变时触发此事件 /// </summary> /// <param name="item">item</param> /// <returns></returns> async Task OnSelectedItemChanged(SelectedItem item) { await Task.Delay(1); Value.ClassID = Convert.ToInt32(item.Value); } } }
后端API接口
using AutoMapper; using Entity; using Entity.ViewModel; using Microsoft.AspNetCore.Mvc; using Utility; namespace WebApi.Controllers { /// <summary> /// 学生管理 /// </summary> [ApiController] [Route("api/[controller]/[action]")] public class StudentController : ControllerBase { private readonly IMapper _mapper; private readonly SQLiteAsyncHelper<Student> _studentHelper; private readonly SQLiteAsyncHelper<SchoolClass> _schoolClassHelper; /// <summary> /// 依赖注入 /// </summary> /// <param name="mapper">mapper</param> /// <param name="studentHelper">studentHelper</param> /// <param name="schoolClassHelper">schoolClassHelper</param> public StudentController(IMapper mapper, SQLiteAsyncHelper<Student> studentHelper, SQLiteAsyncHelper<SchoolClass> schoolClassHelper) { _mapper = mapper; _studentHelper = studentHelper; _schoolClassHelper = schoolClassHelper; } /// <summary> /// 创建新的学生记录 /// </summary> /// <param name="student">添加的学生信息</param> /// <returns></returns> [HttpPost] public async Task<ApiResponse<int>> CreateStudent([FromBody] Student student) { var response = new ApiResponse<int>(); try { var insertNumbers = await _studentHelper.InsertAsync(student).ConfigureAwait(false); if (insertNumbers > 0) { response.Success = true; response.Message = "添加成功"; } else { response.Success = false; response.Message = "插入失败"; } } catch (Exception ex) { response.Success = false; response.Message = ex.Message; } return response; } /// <summary> /// 查询所有学生记录 /// </summary> /// <returns></returns> [HttpGet] public async Task<ApiResponse<List<StudentViewModel>>> GetAllStudent() { var response = new ApiResponse<List<StudentViewModel>>(); try { var students = await _studentHelper.QueryAllAsync().ConfigureAwait(false); var studentsListDto = await GetStudentClassInfo(students).ConfigureAwait(false); response.Success = true; response.Data = studentsListDto ?? new List<StudentViewModel>(); } catch (Exception ex) { response.Success = false; response.Message = ex.Message; } return response; } private async Task<List<StudentViewModel>?> GetStudentClassInfo(List<Student> students) { var studentsListDto = _mapper.Map<List<StudentViewModel>>(students); if (studentsListDto?.Count > 0) { var classIDs = studentsListDto.Select(x => x.ClassID).Distinct().ToList(); var querySchoolClassList = await _schoolClassHelper.QueryAsync(x => classIDs.Contains(x.ClassID)).ConfigureAwait(false); if (querySchoolClassList?.Count > 0) { foreach (var studentItem in studentsListDto) { var getClassInfo = querySchoolClassList.FirstOrDefault(x => x.ClassID == studentItem.ClassID); if (getClassInfo != null) { studentItem.ClassName = getClassInfo.ClassName; } } } } return studentsListDto; } /// <summary> /// 根据学生ID查询学生信息 /// </summary> /// <param name="studentID">学生ID</param> /// <returns></returns> [HttpGet("{studentID}")] public async Task<ApiResponse<StudentViewModel>> GetStudentById(int studentID) { var response = new ApiResponse<StudentViewModel>(); try { var student = await _studentHelper .QuerySingleAsync(x => x.StudentID == studentID) .ConfigureAwait(false); if (student != null) { var studentsDto = await GetStudentClassInfo(new List<Student> { student }).ConfigureAwait(false); response.Success = true; response.Data = studentsDto.FirstOrDefault(); } else { response.Success = false; response.Message = "未找到学生信息"; } } catch (Exception ex) { response.Success = false; response.Message = ex.Message; } return response; } /// <summary> /// 更新学生记录 /// </summary> /// <param name="studentID">学生ID</param> /// <param name="editstudent">更新的学生信息</param> /// <returns></returns> [HttpPut("{studentID}")] public async Task<ApiResponse<int>> UpdateStudent( int studentID, [FromBody] Student editstudent ) { var response = new ApiResponse<int>(); try { var student = await _studentHelper .QuerySingleAsync(x => x.StudentID == studentID) .ConfigureAwait(false); if (student != null) { student.Age = editstudent.Age; student.Name = editstudent.Name; student.Gender = editstudent.Gender; student.ClassID = editstudent.ClassID; int updateResult = await _studentHelper .UpdateAsync(student) .ConfigureAwait(false); if (updateResult > 0) { response.Success = true; response.Message = "学生信息更新成功"; } else { response.Success = false; response.Message = "学生信息更新失败"; } } else { response.Success = false; response.Message = "未找到学生信息"; } } catch (Exception ex) { response.Success = false; response.Message = ex.Message; } return response; } /// <summary> /// 删除学生记录 /// </summary> /// <param name="studentID">学生ID</param> /// <returns></returns> [HttpDelete("{studentID}")] public async Task<ApiResponse<int>> DeleteStudent(int studentID) { var response = new ApiResponse<int>(); try { int deleteResult = await _studentHelper .DeleteAsync(studentID) .ConfigureAwait(false); if (deleteResult > 0) { response.Success = true; response.Message = "删除成功"; } else { response.Success = false; response.Message = "未找到学生信息"; } } catch (Exception ex) { response.Success = false; response.Message = ex.Message; } return response; } } }