从0到1搭建自己的OA系统(一)

从0到1搭建自己的OA系统(一)

虽然说是从0到1,但是程序员都知道,不可能重复造轮子。还是从ruoyi脚手架项目开始

一、ruoyi脚手架整体结构

1.1、原脚手架结构

ruoyi-admin 所有controller有关的接口全放在这里,也叫Web模块,特有逻辑1,必需的ruoyi-system 除此之外的domain、mapper、service等CRUD相关逻辑,特有逻辑2ruoyi-quartz 定时器,特有逻辑3ruoyi-generator 代码生成器,特有逻辑4ruoyi-common 公共组件,如工具类、公共用到的,公共逻辑1,必需的ruoyi-framework 框架运行所需要的一些类,公共逻辑2,必需的上述加黑字体的模块是主要模块,项目最终都会整合到 ruoyi-admin模块中,而ruoyi-admin是通过pom.xml把上述模块加入依赖进来的,各模块之间的依赖关系如下简图所示:

1.2、SQL表结构

重点的表主要是sys_ 开头的表:

sys_config :对应的系统中“系统管理/参数设置”sys_dept:对应系统中“系统管理/部门管理”sys_dict_data:字典明细表,对应系统中“系统管理/字典管理”sys_dict_type:字典类型表,对应系统中“系统管理/字典管理/字典类型”sys_job / sys_job_log:定时任务,对应系统中“系统监控/定时任务”sys_logininfor:登录信息,对应于系统的“系统监控/在线用户”和“日志管理/登录日志”sys_menu:菜单管理表,对应于系统的所有菜单值,还对应于“系统管理/菜单管理”sys_notice:通知信息,对应于“系统管理/通知公告”sys_oper_log:操作日志,对应于“日志管理/操作日志”sys_post:岗位管理表,对应“系统管理/岗位管理”sys_role:角色管理表,对应“系统管理/角色管理”sys_user:用户表,对应“系统管理/用户管理”sys_role_dept / sys_role_menu /sys_user_role : 角色与部门、菜单、用户的对应表sys_user_post:用户与岗位的对应表其中,用户相关的表的关系如下所示:

1.3 接口返回值

前后端分离的ruoyi框架共三个类型的返回值,分别是:

void:主要是导出或下载等不需要返回值的接口TableDataInfo:所返回的数据结构如下,主要是页面的分页列表数据

AjaxResult:所返回的数据结构如下,主要是基本添加、编辑、单个查询或删除等操作的返回值,一般是json格式数据

二、改造“通知公告”

目的:通过改造“通知公告”能够对系统有个基本了解。

目标:前端将“通知公告”拆分为两个页面:

A页面主要是显示所有用户发布的所有公告,并可查看详情,查看完毕后标识已读状态B页面主要是用户个人自己的公告编辑,发起流程并发布的编辑页面2.1 调整字典数据

通过前端页面调整字典数据,增加记录是否已读的sys_notice_isread数据字典类型,同时修改通知的类型sys_notice_status为流程类型、修改sys_notice_type的通知类型:

sys_notice_type:

sys_notice_status:

sys_notice_isread(新增):

2.2 增加用户与通知的关联SQL表

针对每个用户的已读信息,在SQL中予以存储之用,表名命名为sys_user_notice:

2.3 生成新增SQL的后台操作代码

使用代码生成器生成新增的SQL后台操作代码,如下图,代码生成器生成的代码包括前端VUE文件和后端main文件以及针对前端菜单显示的SQL三部分。其中因前端是改造原通知公告页面,故不使用vue和SQL文件,仅导入后端操作的main文件,如图标识所示部分:

2.4 改造“全员信息”页面

复制备份前端的views/system/notice下的index.vue,命名为create.vue作为编辑公共页面备用。

首先改造index如下:

2.4.1 去掉编辑功能

注释掉本页面中所有的“新增、修改、删除”的前端代码

2.4.2 增加序号和公告编号

2.4.3 操作中添加“查看”

查看

同时添加点击“查看”后的详情页面:

v-for="mytype in dict.type.sys_notice_type" :key="dict.value"

:type="mytype.raw.listClass" v-if="form.noticeType==mytype.value">{{ mytype.label}}

{{form.createTime}}

2.4.4 api和数据改造

api增加listPublishList路径,用以获取后端的所有发布的信息,index中改造如下:

import { listPublishNotice, getNotice,getNoticeAndRecord, delNotice, addNotice, updateNotice } from "@/api/system/notice";

api中改造如下:

// 查询所有发布的公告列表

export function listPublishNotice(query) {

return request({

url: '/system/notice/publishlist',

method: 'get',

params: query

})

}

index.vue中发生变动的数据如下:

dicts: ['sys_notice_status','sys_notice_isread', 'sys_notice_type'],

queryParams: {

pageNum: 1,

pageSize: 10,

noticeTitle: undefined,

createBy: undefined,

status: undefined,

orderByColumn:"create_time",

isAsc:"desc"

},

获取数据的方法变动如下:

/** 查询公告列表 */

getList() {

this.loading = true;

listPublishNotice(this.queryParams).then(response => {

this.noticeList = response.rows;

this.total = response.total;

this.loading = false;

});

},

增加打开详情信息的处理方法如下:

// 打开信息详情

openDetailDialog(id) {

this.openDetail = true;

this.loadingDetail = true;

getNoticeAndRecord(id).then(response => {

this.form = response.data;

this.openDetail = true;

this.loadingDetail = false;

});

},

// 取消按钮

closeDetail(id) {

this.titleDetail = "详情";

this.openDetail = false;

this.reset();

this.noticeList.forEach(element => {

if(element.noticeId == id) {

element.isRead = 1;

}

});

},

2.4.5 后端处理修改

SysNoticeCotroller中增加路由:

/**

* 获取发布类型通知公告列表

*/

@SaCheckPermission("system:notice:list")

@GetMapping("/publishlist")

public TableDataInfo publishlist(SysNotice notice, PageQuery pageQuery) {

return noticeService.selectPageNoticePublishList(notice, pageQuery, getUserId());

}

在SysNoticeServerImpl中增加相关处理方法并添加接口:

/**

* 查询所有发布状态的公告

* @param notice

* @param pageQuery

* @return

*/

@Override

public TableDataInfo selectPageNoticePublishList(SysNotice notice, PageQuery pageQuery, Long currentUserId) {

LambdaQueryWrapper lqw = new LambdaQueryWrapper()

.like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())

.eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())

.like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy())

.eq(SysNotice::getStatus, dictDataService.selectDictValue("sys_notice_status", "发布"));

Page page = baseMapper.selectPage(pageQuery.build(), lqw);

int i = PageQuery.DEFAULT_PAGE_NUM;

for( SysNotice one : page.getRecords()) {

one.setCreateBy(String.valueOf(sysUserService.selectUserByUserName(one.getCreateBy()).getNickName()));

SysUserNoticeVo isReadResult = sysUserNoticeService.queryByIdAndNoticeId(currentUserId, one.getNoticeId());

if(isReadResult != null){

one.setIsRead(Long.valueOf(dictDataService.selectDictValue("sys_notice_isread", "已读")));

} else {

one.setIsRead(Long.valueOf(dictDataService.selectDictValue("sys_notice_isread", "未读")));

}

one.setNoId(Long.valueOf((pageQuery.getPageNum()-1)*pageQuery.getPageSize()+i));

i++;

}

return TableDataInfo.build(page);

}

所有修改完毕后效果如下

2.5 改造“编辑公告”页面

针对上述2.4步复制出来的create.vue页面改造如下:

2.5.1 添加序号和流程发起

发起

2.5.2 修改数据和方法

如2.4.4中改造“全员公告”的方式类似,分别修改api及本create.vue页面如下

// 查询当前用户的所有公告列表

export function listCurrUserNotice(query) {

return request({

url: '/system/notice/curruserlist',

method: 'get',

params: query

})

}

import { listCurrUserNotice,getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";

// 查询参数

queryParams: {

pageNum: 1,

pageSize: 10,

noticeTitle: undefined,

createBy: undefined,

status: undefined,

orderByColumn:"create_time",

isAsc:"desc"

},

/** 查询公告列表 */

getList() {

this.loading = true;

listCurrUserNotice(this.queryParams).then(response => {

this.noticeList = response.rows;

this.total = response.total;

this.loading = false;

});

},

其中,流程操作中的“发起”按钮的操作方法暂未开发(20240304记录,待后续更新)

2.5.3 后端处理修改

分别修改后端对应的controller文件和service实现文件:

/**

* 获取当前用户的所有状态通知公告列表

*/

@SaCheckPermission("system:notice:list")

@GetMapping("/curruserlist")

public TableDataInfo curruserlist(SysNotice notice, PageQuery pageQuery) {

return noticeService.selectPageCurrUserList(notice, pageQuery, getUserId());

}

/**

* 查询当前用户的所有状态的公告

* @param notice

* @param pageQuery

* @param userId

* @return

*/

@Override

public TableDataInfo selectPageCurrUserList(SysNotice notice, PageQuery pageQuery, Long userId) {

LambdaQueryWrapper lqw = new LambdaQueryWrapper()

.like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())

.eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())

.eq(SysNotice::getCreateBy, sysUserService.selectUserById(userId).getUserName());

Page page = baseMapper.selectPage(pageQuery.build(), lqw);

int i = PageQuery.DEFAULT_PAGE_NUM;

for( SysNotice one : page.getRecords()) {

one.setNoId(Long.valueOf((pageQuery.getPageNum()-1)*pageQuery.getPageSize()+i));

i++;

}

return TableDataInfo.build(page);

}

所有改造完毕后的效果如下:

2.6 过程遇到的问题

2.6.1 jdk17下cglib报错

修改后端的service时,报如下错误,经查是 jdk17下cglib未更新所致

Unable to make protected final java.lang.Class java.lang.ClassLoader

在项目运行的中增加项目VM运行前的参数解决

--add-opens java.base/java.lang=ALL-UNNAMED

2.6.2 SQL update相关问题

因本次修改仿照其他sql表建立的sys_user_notice关联表,在实际修改service过程中发生了以下几类错误,后期如遇到可快速避免:

新增表无id,updateById或selectById时报错。此类问题可使用updateByBo之类解决,增加一个lamdaQueryWrapper的表达式,用Bo对象实现查询或更新默认的表都有create_by等系统默认字段,后端MybatisPlus的相关处理默认也是要操作这几个字段的,在尽量少更改代码的情况,在后期新建的SQL表中尽量考虑增加上这几个系统字段

相关推荐

为什么很多人喜欢在淋浴时唱歌?这背后有什么科学依据?
毛笔字入门:如何开始学习和实践?
世界杯365网站打不开

毛笔字入门:如何开始学习和实践?

📅 10-25 👁️ 5348
十大益智手机游戏
世界杯365网站打不开

十大益智手机游戏

📅 07-04 👁️ 7726
羽毛球常用十大进攻战术,单打双打均通用!
mobile365体育投注

羽毛球常用十大进攻战术,单打双打均通用!

📅 09-12 👁️ 5992
使用QQ进行打赏别人的操作流程
mobile365体育投注

使用QQ进行打赏别人的操作流程

📅 07-15 👁️ 2349
如何在苹果手机上安全信任第三方应用?必备指南!
mobile365体育投注

如何在苹果手机上安全信任第三方应用?必备指南!

📅 09-19 👁️ 8288