首页 > 其他分享 >文档管理系统重构

文档管理系统重构

时间:2023-09-27 09:14:39浏览次数:27  
标签:重构 管理系统 DEFAULT gclassify int 文档 var NULL Id

服务端代码

分层架构系统Controller 业务层 数据层

对于服务端的Controller,业务层和数据层应该有各自该执行的任务

Controller 负责对数据合法性的校验之后传递给业务层

业务层 业务层进行业务逻辑的实现之后传递给数据层

数据层 对数据库进行操作

对于原有的项目查询为例,进行重构

原有的DocumentController

[HttpPost]
public JsonResult ClassifyGet()
{
  var id = HttpContext.User.Claims.First().Value.ToInt();
  return Json(_documentsService.GetClassifyList(id));
}

原有的Service

public ResponseModel GetClassifyList(int id)
{
  if (id <= 0)
      return GetClassifyList();
  var classifys = _db.Classify.Where(r => _db.Roles.Where(r => r.UserId == id).Select(r => r.ClassifyId).Contains(r.Id)).OrderByDescending(c => c.Sort).ToList();
  var response = new ResponseModel { code = 200, result = "文档类别获取成功" };
  response.data = new List<ResClassifyModel>();
  foreach (var gclassify in classifys)
  {
      response.data.Add(new ResClassifyModel
      {
          Id = gclassify.Id,
          Name = gclassify.Name,
          Sort = gclassify.Sort,
          Remark = gclassify.Remark,
          CreateTime = gclassify.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
      });
  }
  return response;
}
public ResponseModel GetClassifyList()
{
  var classifys = _db.Classify.OrderByDescending(c => c.Sort).ToList();
  var response = new ResponseModel { code = 200, result = "文档类别获取成功" };
  response.data = new List<ResClassifyModel>();
  foreach (var gclassify in classifys)
  {
      response.data.Add(new ResClassifyModel
      {
          Id = gclassify.Id,
          Name = gclassify.Name,
          Sort = gclassify.Sort,
          Remark = gclassify.Remark,
          CreateTime = gclassify.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")
      });
  }
  return response;
}

拆分为

Controller

[HttpPost]
public JsonResult ClassifyGet()
{
  var id = HttpContext.User.Claims.First().Value.ToInt();
  return Json(_documentsService.GetClassifyList(id));
}

业务层

public ResponseModel GetClassifyList(int id)
{
  if (id <= 0)
      return GetClassifyListAdmin(id);
  else
  return GetClassifyListUser(id);
}

数据层

public ResponseModel GetClassifyListAdmin()
{
var classifys = _db.Classify.OrderByDescending(c => c.Sort).ToList();
  var response = new ResponseModel { code = 200, result = "文档类别获取成功" };
  response.data = new List<ResClassifyModel>();
  foreach (var gclassify in classifys)
  {
      response.data.Add(new ResClassifyModel
      {
          Id = gclassify.Id,
          Name = gclassify.Name,
          Sort = gclassify.Sort,
          Remark = gclassify.Remark,
          CreateTime = gclassify.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")
      });
  }
  return response;
}
public ResponseModel GetClassifyListUser()
{
  var classifys = _db.Classify.Where(r => _db.Roles.Where(r => r.UserId == id).Select(r => r.ClassifyId).Contains(r.Id)).OrderByDescending(c => c.Sort).ToList();
  var response = new ResponseModel { code = 200, result = "文档类别获取成功" };
  response.data = new List<ResClassifyModel>();
  foreach (var gclassify in classifys)
  {
      response.data.Add(new ResClassifyModel
      {
          Id = gclassify.Id,
          Name = gclassify.Name,
          Sort = gclassify.Sort,
          Remark = gclassify.Remark,
          CreateTime = gclassify.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
      });
  }
  return response;
}
数据模型 DTO PO DAO

数据库操作层 使用DAO与数据库进行交互

业务层 以PO的形式与数据库操作层进行交互

Controller 以DTO的形式与业务层进行交互

可以在能进行拓展的时候容易进行拓展,方便维护

原有的数据类型返回

[HttpGet]
public JsonResult GetRole(int pageIndex, int pageSize, int classifyId, string keyword)
{
  var guser = _roleService.GetRoleList(pageSize, pageIndex, classifyId, keyword);
  return new JsonResult(guser.data);
}
public ResponseModel GetRoleList(int pageSize, int pageIndex, int ClassifyId, string? userName)
{
    var rolelist = _db.Roles.Where(p => p.ClassifyId == ClassifyId);
    if(userName != null)
    {
        rolelist = rolelist.Where(p => p.UserName.Contains(userName));
    }
    var pageData = rolelist.OrderByDescending(c => c.UserId).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
    return  new ResponseModel { code = 200, result = "Role添加成功",data=pageData };
}

直接将DAO作为HTTP请求的返回结果,不方便进行业务的拓展维护,并且容易携带应该隐藏的数据带来不安全性

修改,转换成对应的数据模型进行返还

拆分方法 加强复用性 降低耦合性

提高代码的复用性,将重复使用的模块,和方法体较大的模块作为独立的方法抽取出来

public ResponseModel EditDocument(EditDocument document,int id)
{
    var edocument = _db.Documents.FirstOrDefault(c => c.Id == document.Id);
    if (edocument == null)
        return new ResponseModel { code = 0, result = "该文档不存在" };  
            
    // 抽取成 ConvertToDbModel    
    edocument.ClassifyId = document.ClassifyId;
    edocument.Title = document.Title;
    edocument.Remark = document.Remark;
    edocument.Contents = document.Contents;
    edocument.UpdateTime = DateTime.Now;
    edocument.Image = document.Image;
    edocument.Version = Guid.NewGuid();
        
    _db.Documents.Update(edocument);
    
}
public ResponseModel EditDocument(EditDocument document,int id)
{
    var edocument = _db.Documents.FirstOrDefault(c => c.Id == document.Id);
    if (edocument == null)
        return new ResponseModel { code = 0, result = "该文档不存在" };  
            
    var DbModel = ConvertToDbModel(document);
        
    _db.Documents.Update(edocument);
    
}
全局异常拦截器,避免出现异常导致项目整体无法继续进行,并记录错误日志
using Microsoft.AspNetCore.Mvc.Filters;
public class CustomExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        // 在异常发生时执行的逻辑
        var exception = context.Exception;
        // 可以记录日志、返回自定义错误页面或错误响应等
        context.ExceptionHandled = true; // 表示异常已被处理
    }
}
将RabbitMQ Consumer单独作为Windows Service项目进行部署

将 RabbitMQ Consumer作为单独Windows Service项目部署

方便进行开发,测试,部署,更好的维护

并且Windows Service更适合这种长时间运行的任务

RESTFUL风格

可以采用RESTFUL风格设计接口

对于数据加入校验,避免直接污染数据库

 

数据库

数据库设计无法精确实现业务需求

对于Document表格

-- hb.documents definition

CREATE TABLE `documents` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `ClassifyId` int NOT NULL,
  `Title` varchar(1000) DEFAULT NULL,
  `Image` varchar(200) DEFAULT NULL,
  `Contents` text,
  `PublishDate` datetime DEFAULT NULL,
  `Remark` varchar(200) DEFAULT NULL,
  `SeeCount` int DEFAULT NULL,
  `Version` char(36) DEFAULT NULL,
  `UpdateTime` datetime DEFAULT NULL,
  PRIMARY KEY (`Id`),
  KEY `FK_Classify_Documents` (`ClassifyId`)
) ENGINE=InnoDB AUTO_INCREMENT=272 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

没有办法实现目录功能,当文档增多的时候没办法层级展示

加入ParentDocmentId

-- hb.documents definition

CREATE TABLE `documents` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `ClassifyId` int NOT NULL,
  `ParentDocmentId` int NOT NULL,
  `Title` varchar(1000) DEFAULT NULL,
  `Image` varchar(200) DEFAULT NULL,
  `Contents` text,
  `PublishDate` datetime DEFAULT NULL,
  `Remark` varchar(200) DEFAULT NULL,
  `SeeCount` int DEFAULT NULL,
  `Version` char(36) DEFAULT NULL,
  `UpdateTime` datetime DEFAULT NULL,
  PRIMARY KEY (`Id`),
  KEY `FK_Classify_Documents` (`ClassifyId`)
) ENGINE=InnoDB AUTO_INCREMENT=272 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
关键字段逻辑删除

同时对于文档等关键的数据,应该加入isDel字段,并且在接口的实现上均采用逻辑删除,避免出现错误删除的情况

字段设计不太明确,不宜维护
-- hb.adminor definition

CREATE TABLE `adminor` (
  `Id` int NOT NULL,
  `Account` varchar(45) DEFAULT NULL,
  `Password` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `user` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `Account` varchar(45) DEFAULT NULL,
  `Password` varchar(45) DEFAULT NULL,
  `Reg_Time` datetime DEFAULT NULL,
  `LastLogin_Time` datetime DEFAULT NULL,
  `isDel` tinyint DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=353 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

原本使用 id<0 判断权限

对于是用户还是管理员,可以在数据表中添加Role字段,而且因为字段是相同的可以作为一张表存储

-- hb.`user` definition

CREATE TABLE `user` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `Role` tinyint DEFAULT NULL,
  `Account` varchar(45) DEFAULT NULL,
  `Password` varchar(45) DEFAULT NULL,
  `Reg_Time` datetime DEFAULT NULL,
  `LastLogin_Time` datetime DEFAULT NULL,
  `isDel` tinyint DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=353 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

 

 

前端

规范前端发送Ajax的逻辑,同样的请求没有必要的多次调用
function search() {
	pageIndex = 1;
	getUser(pageIndex, pageSize);
}
 function getUser(pageIndex, pageSize, keyword) {
	$.ajax({
        data: { pageIndex: pageIndex, pageSize: pageSize },
        success: function (result) {
        	currentPageCount = result.data.length;
            var totalPage = parseInt(result.total / pageSize + 1);
            pageNav.fn = function (p, pn) {
            	$("#pageinfo").text("当前页:" + p + " 总页: " + totalPage);
            	if(p != lastPage)
                	getUser(p,pageSize,keyword);
                };
                pageNav.go(pageIndex, totalPage);
                lastPage = pageIndex;
            }
        });
}

对分页进行监听,当产生监听是进行,ajax请求更换页面渲染数据,避免重复请求

CSS,JS提取

抽取成CSS,JS文件,可以重复使用,并且在Lay_out界面一次引入公共部分,使得代码更加简洁易懂

规范编码风格,不同的前端页面使用了不同框架,部分使用了原生HTML,部分使用了Vue
完善日志等执行信息,前端加入Console.log对于关键流程进行打印
对于数据进行校验,避免直接污染数据库,如果数据有误就不发送请求了
前端应该对用户的输入,增删查改等各个操作给出相应
都只针对数据量少的情况,当数据量大时会出现错误

都应该提供分页的功能

类似按钮部分功能使用新建页面,部分功能使用弹窗,应该统一风格

 

统一的规范

规范命名风格

 

数据增加时

Redis缓存热点数据
ElasticSearch快速搜索
部署为多体项目,数据库不再使用自增id,单独建立数据库存储全局自增id
对于冲突性高的业务采用分布式锁,冲突性低的业务使用乐观锁进行并发的考虑,乐观锁不建议使用

标签:重构,管理系统,DEFAULT,gclassify,int,文档,var,NULL,Id
From: https://www.cnblogs.com/cooooooooookie/p/17731785.html

相关文章

  • MongoDB 解析:灵活文档数据库与 Docker Compose 部署
    MongoDB是一款开源、高性能的NoSQL数据库,以其无模式的文档存储格式(BSON)而著称,广泛应用于众多开源项目,包括但不限于Yapi等。它在大规模数据存储和实时数据处理方面表现出色,因此备受青睐。在本文中,我们将深入探讨MongoDB的特性,并详细阐述如何使用DockerCompose轻松部署Mon......
  • MySQL-5.7版本官方文档二进制离线安
    官网二进制包脚本安装#!/bin/bash#解决软件的依赖关系yuminstallcmakencurses-develgccgcc-c++vimlsofbzip2openssl-develncurses-compat-libs-y#解压mysqql二进制安装包tarxfmysql-5.7.43-linux-glibc2.12-x86_64.tar.gz#移动mysql解压后的文件到/usr/l......
  • 向着趋势奔跑:银行客户中心转型,重构商业模式是关键
    随着金融市场化改革的推进国内银行同业间的竞争日趋激烈各商业银行在全新的监管要求和市场环境下纷纷开始推行“以客户为中心”的经营新模式迅速提升核心竞争力然而!!!奇怪的事情发生了......
  • 视频融合平台EasyCVR如何使用视频监控系统搭建森林防火与人车管理系统解决方案
    安防视频监控平台EasyCVR是一个具有强大拓展性、灵活的视频能力和轻便部署的平台。它支持多种主流标准协议,包括国标GB28181、RTSP/Onvif、RTMP等,还可以支持厂家的私有协议和SDK接入,例如海康Ehome、海大宇等设备的SDK。该平台不仅拥有传统安防视频监控的功能,还具备接入AI智能分析的......
  • 多阅读编程语言语言的官方文档及一些源码
    1官方文档回顾了下自己这几年的学习历程,关于编程语言官方文档的学习很少很少,平时喜欢去看各种公众号文章和网站教程,自己的python基础以及一些框架基础就是就是在公众号、网站教程、博客和书上学来的。现在看看官方文档的那些海量的内容,自己都觉得很惊奇,很少看过不说,有些地方自己......
  • 向着趋势奔跑:银行客户中心转型,重构商业模式是关键
    随着金融市场化改革的推进国内银行同业间的竞争日趋激烈各商业银行在全新的监管要求和市场环境下纷纷开始推行“以客户为中心”的经营新模式迅速提升核心竞争力  然而!!!奇怪的事情发生了......
  • 基于Java的高校竞赛管理系统设计与实现(亮点:发起比赛、报名、审核、评委打分、获奖排名
    高校竞赛管理系统一、前言二、我的优势2.1自己的网站2.2自己的小程序(小蔡coding)2.3有保障的售后2.4福利三、开发环境与技术3.1MySQL数据库3.2Vue前端技术3.3SpringBoot框架3.4微信小程序四、功能设计4.1主要功能描述4.2系统角色五、系统主要功能展示5.1前端展示5.1.1......
  • 基于Java的高校实习管理系统设计与实现(亮点:实习记录、实习打分、实习作业,功能新颖、老
    高校实习管理系统一、前言二、我的优势2.1自己的网站2.2自己的小程序(小蔡coding)2.3有保障的售后2.4福利三、开发环境与技术3.1MySQL数据库3.2Vue前端技术3.3SpringBoot框架3.4微信小程序四、功能设计4.1主要功能描述五、系统主要功能5.1管理员功能5.2公司功能5.3老师......
  • 高效、透明-企事业数字化的采购管理系统(源程序源代码)
    在这个信息化、数字化的时代,企业如何紧跟潮流,利用数字化技术提升采购管理效率,成为了一个无法回避的话题。本文将为您揭秘企业采购数字化转型的秘密武器,助您实现高效、透明、省钱的采购管理!一、数字化采购管理系统,让企业如虎添翼传统的采购模式往往依赖人力,不仅效率低下,还容易产......
  • 软件调研、研发、设计、管理、验收文档(全文档整理)
    前言:在软件开发生命周期中,调研、研发、设计、管理、验收等环节的文档编写至关重要。它们分别扮演着不同的角色,为项目的顺利进行和最终的成功提供支持和保障。【获取方式在文末】【在调研阶段】,文档的主要作用是记录和整理关于软件产品的需求分析、市场调研和竞争分析等信息。......