BI 项目构建
项目构建
前端项目构建
1.项目初始化
构建前端项目,搭建基于react的ant design pro项目脚手架,注意项目版本依赖问题(如果nodejs版本不兼容则适当调整即可)
# 使用 npm 加载脚手架
npm i @ant-design/pro-cli -g
# 创建前端项目
pro create bi-platform-frontend
# 选择umi版本(可以尝试umi4踩新坑,umi3提示选择简单还是全量脚手架),原使用umi3 simple
# 进入指定项目安装项目依赖
cd bi-platform-frontend
tyarn 或者 npm install
# 脚手架初始完成,进入开发状态
npm run start
# 项目启动完成访问http://localhost:8000/,第一次初始化加载会比较慢
查看package.json文件,对照相应的启动命令看其配置,如果执行npm run dev
命令本质上执行的是start:dev
,可以看其指令配置中MOCK=none,由于此时还没有接入后台数据接口,因此需要借助MOCK模拟数据接口实现访问。重启项目npm run start
访问,然后登录访问主页(start以模拟数据方式运行,dev命令禁用了MOCK调用自己定义的后端)
项目构建完成,引入git仓库做版本管理
2.项目瘦身
框架本身生成的东西有很多,但实际上一些小型项目中不需要引用这么复杂的内容,为了优化代码结构,此处通过清理项目一些可能不会用到的东西给项目瘦身
(1)国际化移除:/src/locales
国际化:集成了多种语言:中文、英文... ,考虑项目主要在国内访问,去除国际化配置;如果要使用国际化,还要去配置不同语言的引用
在package.json文件中找到i18n-remove
,这里提供了移除国际化的脚本( "i18n-remove": "pro i18n-remove --locale=zh-CN --write",),执行指令(如果指令执行失败,参考官方解决方案)
pro i18n-remove --locale=zh-CN --write
# 指令执行出错,参考官方解决方案,此处参考引入依赖后再次尝试
yarn add eslint-config-prettier
yarn add eslint-plugin-unicorn
或者执行:yarn add eslint-config-prettier --dev yarn add eslint-plugin-unicorn --dev
修改:
node_modules/@umijs/lint/dist/config/eslint/index.js
// es2022: true
奇奇怪怪的问题:在vscode中执行指令报错,但是通过cmd窗口执行指令正常(指令执行完毕移除了一些关联配置)
指令执行是为了移除国际化相关配置文件,需要手动移除locales文件夹,完成清理后重启项目检查是否正常运行
重启项目如果报错则进一步排查(例如移除国际化出现SyntaxError: Export 'SelectLang' is not defined,参考官方解决方案:将src/components/index.js 中的 SelectLang 变量删除)
常见问题处理:左侧菜单栏不显示
需要修改路由配置,给config/route.ts中配置的路由都加上name属性(随后重启项目尝试访问)
后端项目构建
1.项目初始化
项目构建配置
后端项目构建引用此前的通用后台模板作为参考,基于模板脚手架进行开发。配置maven、jdk,全局搜索springboot-init调整为自己的项目名称配置(bi-platform-backend)
数据库连接配置
resources/application.yml:
数据库用户名、密码配置、数据库名dada_db_bi_platform
项目启动接口测试
访问:http://localhost:8101/api/doc.html#/home
2.数据表设计
用户表和图表信息表
-- 用户表
create table if not exists user
(
id bigint auto_increment comment 'id' primary key,
userAccount varchar(256) not null comment '账号',
userPassword varchar(512) not null comment '密码',
userName varchar(256) null comment '用户昵称',
userAvatar varchar(1024) null comment '用户头像',
userRole varchar(256) default 'user' not null comment '用户角色:user/admin',
createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
isDelete tinyint default 0 not null comment '是否删除',
index idx_userAccount (userAccount)
) comment '用户' collate = utf8mb4_unicode_ci;
-- 图表信息表
create table if not exists chart
(
id bigint auto_increment comment 'id' primary key,
goal text null comment '分析目标',
`name` varchar(128) null comment '图表名称',
chartData text null comment '图表数据',
chartType varchar(128) null comment '图表类型',
genChart text null comment '生成的图表数据',
genResult text null comment '生成的分析结论',
status varchar(128) not null default 'wait' comment 'wait,running,succeed,failed',
execMessage text null comment '执行信息',
userId bigint null comment '创建用户 id',
createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
isDelete tinyint default 0 not null comment '是否删除'
) comment '图表信息表' collate = utf8mb4_unicode_ci;
根据设计好的数据表,删除默认的数据表结构,重新生成系统所需的表信息
3.基础模块开发
(1)代码生成器构建业务代码
在Database模块中选中表,随后右键选择MyBatisX-Generator
代码生成成功在src/main/java/generator文件夹下可跟踪生成的代码,将代码对号入座即可
generator | com.noob.springbootinit |
---|---|
domain | model/entity |
mapper | mapper |
service、service/impl | service、service/impl |
resources/mapper | 调整对应实体映射 |
实体类调整
主键ID:@TableId(type = IdType.AUTO)调整为@TableId(type = IdType.ASSIGN_ID)(将原有自动递增序列调整为雪花算法生成唯一id,长整型)
逻辑删除:isDelete字段加上逻辑删除注解@TableLogic(逻辑删除字段)
飘红报错调整
对于一些项目中暂时没有引入的内容可以先清理掉,例如第三方登录:UserService中的第三方登录接口(userLoginByMpOpen)、UserController中的userLoginByWxOpen、附带删除controller/WxMpController、wxmp文件夹(微信公众号接入相关)
重启项目测试
用户注册=》用户登录,测试接口
(2)图表信息模块构建
controller层、dto层等内容
基于原有PostController进行改造,然后依次引入相关DTO定义等内容
【1】复制PostController为ChartController(将Post统一调整为Chart,注意大小写相关也要分别替换),注意全局替换一些关键字处理,不要搞错了
【2】注释调整:帖子=》图表
【3】根据飘红依次引入相关的实体定义
参考上述内容,在model/dto下创建chart包,将原有post下相关的xxxRequest复制过来修改为对应的ChartXXXRequest,然后再依次根据实际业务场景调整请求参数(先构建基础框架,再调整业务字段细节)
类似地,在model/vo下创建ChartVO(从PostVO中构建),将字段定义替换为Chart中的内容
ChartController的addChart改造,设置要添加的Chart实体值(可用快捷键ALT+ENTER生成setter)然后结合ChartAddRequest看哪些是前端传递过来的,哪些是需要手动赋值的内容,填充即可。
此外需要清理掉一些无关紧要的接口定义
【4】Service相关改造(参考PostService实现)
先把项目飘红报错处理,搭建基础业务模块框架,然后再定位具体的业务实现
前后端联调
OpenAPI
使用Ant Design Pro自带的openAPI工具,根据后端swagger接口文档,自动生成对应请求的service代码
前端项目配置:config/config.ts配置openAPI参数:schemaPath
openAPI: [
{
requestLibPath: "import { request } from '@umijs/max'",
// 或者使用在线的版本
schemaPath: "http://localhost:8101/api/v2/api-docs",
projectName:"noob-bi",
// schemaPath: join(__dirname, 'oneapi.json'),
mock: false,
}
],
打开package.json,执行openapi指令,生成swagger文件(在services目录多出一个noob-bi目录,里面自动生成调用后端指定接口的方法代码)(终端输入yarn run openapi
)
前后端联调测试:
修改app.tsx文件,配置baseURL:http://localhost:8101/
在pages/User/Login/index.tsx文件中添加接口请求(测试前后端联调)
useEffect(()=>{
listChartByPageUsingPost({}).then(res=>{
console.error('res',res)
})
})
dev模式启动项目,访问前端:http://localhost:8000,F12检查接口是否正常响应即可
项目模板优化
前端模板优化
了解项目结构和内容,把一些不需要用到的东西清理掉
项目结构 | 说明(❌表示可删除) |
---|---|
.husky | 检查提交的代码,是否规范(代码检验的小工具) |
config | umi配置(包括路由、构建等配置) |
config.ts | Ant Design Pro核心配置(整个项目所用框架配置) |
defaultSetting.ts | Ant Design Pro默认配置 |
opeapi.json | 示例数据(❌) |
proxy.ts | 代理(便于本地开发) |
router.ts | 定义网页路由(输入网址跳转页面) |
mock | 本地模拟数据(❌) |
public/icons | icons目录存放页面图标(❌)可以引入自定义图标 |
src/.umi | 框架自动生成的隐藏文件(可不管) |
src/components | 业务通用组件 |
src/locales | 国际化资源(❌)搭配去除国际化指令删除 |
src/pages | 业务页面入口和常用模板 |
src/service | 后台接口服务 |
access.ts | 控制页面访问权限 |
app.tsx | Ant Design Pro框架的主要文件 |
global.less | 全局样式 |
global.tsx | 全局JS |
manifest.json | 开发app或者h5网页指定多种不同配置(此处可❌) 例如:生成项目名称、项目图标尺寸等(打包的时候用到) |
requestErrorConfig.js | 控制前端页面发送请求的配置 |
service-worker.js | h5网页离线时优化页面的体验 |
tests | 测试工具(❌) |
types | ❌ |
.editorconfig .eslintignore .eslintrc.js .prettierignore .prettierrc.js | 保证前端项目代码规范 |
jest.config.ts | 单元测试框架 |
jsconfig.json | 控制语法 |
README.md | 项目默认文档 |
图标替换:iconfont
public目录:(svg下载)logo.svg替换、(png下载)favicon.ico替换
标题替换
【ctrl+shift+F】将原有Ant Design Pro相关的内容替换为项目相关
模块开发
登录模块构建
无用代码清理
删除pages/User/Login下的_snapshots_/login.test.tsx.snap
pages/User/Login/index.tsx文件中的<Lang />
飘红,没有用到直接删除(Lang配置相关)
删除自动登录、其他登录方式、手机号登录登相关代码
忘记密码?调整为注册(实现注册接口)
调整完成页面参考如下所示
登录功能实现
关注<LoginForm>
组件实现,将用户输入的内容(key)替换为后端对应的内容即可(查看登录接口请求参数即可)
name =》userAccount、password=》userPassword
可修改placeholder属性(输入提示)
删除错误填写验证相关
后端接口对接
定位onFinish=》当用户点击登录后执行handleSubmit方法,将LoginParams调整为后端的
handleSubmit&fetchUserInfo修改:
/**
* 登陆成功后,获取用户登录信息
*/
const fetchUserInfo = async () => {
const userInfo = await getLoginUserUsingGet();
if (userInfo) {
flushSync(() => {
setInitialState((s) => ({
...s,
currentUser: userInfo,
}));
});
}
};
/*
useEffect(()=>{
listChartByPageUsingPost({}).then(res=>{
console.error('res',res)
})
})
*/
const handleSubmit = async (values: API.UserLoginRequest) => {
try {
// 登录
const res = await userLoginUsingPost(values);
if (res.code === 0) {
const defaultLoginSuccessMessage = '登录成功!';
message.success(defaultLoginSuccessMessage);
await fetchUserInfo();
const urlParams = new URL(window.location.href).searchParams;
history.push(urlParams.get('redirect') || '/');
return;
} else {
message.error(res.message);
}
} catch (error) {
const defaultLoginFailureMessage = '登录失败,请重试!';
console.log(error);
message.error(defaultLoginFailureMessage);
}
};
如果userName、userAvatar没有显示可以在后台数据库中补充(后续再完善代码细节),完成上述步骤启动登录验证接口是否调通
清理未引用的内容
VSCode快捷键(shift+alt+O)
全局状态保存
app.tsx文件,找到getInitialState函数修改。然后按【shift+alt+O】清理无用引用
export async function getInitialState(): Promise<{
currentUser?: API.LoginUserVO;
}> {
const fetchUserInfo = async () => {
try {
const res = await getLoginUserUsingGet();
return res.data;
} catch (error) {
history.push(loginPath);
}
return undefined;
};
// 如果不是登录页面,执行
const { location } = history;
if (location.pathname !== loginPath) {
const currentUser = await fetchUserInfo();
return {
currentUser,
};
}
return {};
}
头像加载
登录后访问发现头像转圈圈没有加载进去,数据库中用户对应userAvatar要配置为对应头像链接
修改app.tsx的头像配置
修改用户名配置:src/compontents/RightContent/AvatarDropdown.tsx(头像下拉框),将name修改为userName
此处继续访问发现登录跳转页面后还是无法加载,排查loading组件(打印登录用户信息发现没有数据)发现还是没有登录(说明用户登录状态没有保存成功)
需要在app.tsx中配置withCredentials: true
export const request = {
baseURL:"http://localhost:8101",
withCredentials: true,
...errorConfig,
};
errConfig配置(requestErrorConfig.ts配置)
可以将requestErrorConfig.ts重命名为requestConfig.ts(这个文件中定义了请求处理、请求拦截器、响应拦截器)。(重命名需注意app.tsx的引用也要相应修改)
请求拦截器中给所有的请求都加上了token字段,可以将这部分注释掉,这样通过F12查看接口看起来简洁一点