数据源页面管理预览
管理端列表页面
新增页面
编辑页面
一、初始化前端项目
1.下载avue脚手架
git clone https://gitee.com/smallweigit/avue-cli
提示:官方文档地址:https://avuejs.com/ 码云项目地址:https://gitee.com/smallweigit/avue-cli。
2.项目输出化
npm install
3.启动项目
二、数据库建表
CREATE TABLE `gen_db` (
`id` bigint(20) NOT NULL COMMENT '主键',
`sort` int(255) DEFAULT NULL COMMENT '排序',
`prepend` varchar(255) DEFAULT NULL COMMENT 'jdbc-前缀',
`url` varchar(255) DEFAULT NULL COMMENT 'jdbc-url',
`username` varchar(255) DEFAULT NULL COMMENT '用户名',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建用户id',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新用户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
三、Java代码编写
0.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>cx</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<druid.version>1.1.22</druid.version>
<mybatis-plus.version>3.3.2</mybatis-plus.version>
<hutool.version>5.3.7</hutool.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<!-- SpringBoot 核心包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- SpringBoot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!--阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!--代码生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<!--模板引擎-->
<!--velocity 默认-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!--beetl-->
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.1.7.RELEASE</version>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
<scope>provided</scope>
</dependency>
<!--工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.6</version>
</dependency>
<!--工作流 activiti7 开始-->
<!--<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M4</version>
</dependency>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.1.0.M4</version>
<type>pom</type>
</dependency>-->
<!--工作流 activiti7 结束-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
1.实体类
package com.cx.project.codegen.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@Accessors(chain = true)
@TableName("gen_db")
public class DB {
/*
* 主键id
* */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/*
* 排序
* */
@TableField(value = "sort")
private Integer sort;
/**
* jdbc-前缀
*/
@TableField("prepend")
private String prepend;
/**
* jdbc-url
*/
@TableField("url")
private String url;
/**
* 用户名
*/
@TableField("username")
private String username;
/**
* 密码
*/
// @JsonIgnore //返回前端之前隐藏敏感数据
@TableField("password")
private String password;
/*
* 创建时间
* */
@TableField("create_time")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
/*
* 创建用户id
* */
@TableField("create_user_id")
private Long createUserId;
/*
* 更新用户id
* */
@TableField("update_user_id")
private Long updateUserId;
/*
* 更新时间
* */
@TableField("update_time")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;
}
2.param和result准备(前者用于接收前端参数,后者用户返回o's)
package com.cx.project.codegen.model.params;
import com.cx.project.codegen.entity.DB;
import lombok.Data;
@Data
public class DBParam extends DB {
// 当前第几页
private Integer currentPage;
// 页面大小
private Integer pageSize;
}
package com.cx.project.codegen.model.results;
import com.cx.project.codegen.entity.DB;
import lombok.Data;
@Data
public class DBResult extends DB {
}
3.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cx.project.codegen.mapper.DBMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id AS "id",
sort AS "sort",
prepend AS "prepend",
url AS "url",
username AS "username",
password AS "password",
create_time AS "createTime",
create_user_id AS "createUserId",
update_time AS "updateTime",
update_user_id AS "updateUserId"
</sql>
<sql id="Base_Column_List_With_TableName">
db.id AS "id",
db.sort AS "sort",
db.prepend AS "prepend",
db.url AS "url",
db.username AS "username",
db.password AS "password",
db.create_time AS "createTime",
db.create_user_id AS "createUserId",
db.update_time AS "updateTime",
db.update_user_id AS "updateUserId"
</sql>
<select id="selectDBs" resultType="com.cx.project.codegen.model.results.DBResult" parameterType="com.cx.project.codegen.model.params.DBParam">
select
<include refid="Base_Column_List"/>
from gen_db
<where>
</where>
order by sort asc, create_time desc
</select>
</mapper>
4.mapper接口
package com.cx.project.codegen.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cx.project.codegen.entity.DB;
import com.cx.project.codegen.model.params.DBParam;
import com.cx.project.codegen.model.results.DBResult;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
* </p>
*
* @author
* @since
*/
@Mapper
public interface DBMapper extends BaseMapper<DB> {
List<DBResult> selectDBs(DBParam dbParam);
}
5. service接口
package com.cx.project.codegen.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cx.project.codegen.entity.DB;
import com.cx.project.codegen.model.params.DBParam;
import com.cx.project.codegen.model.results.DBResult;
import java.util.List;
public interface DBService extends IService<DB> {
List<DBResult> list(DBParam dbParam);
Boolean add(DBParam dbParam);
Boolean edit(DBParam dbParam);
Boolean checkDB(DBParam dbParam);
}
6.service实现
package com.cx.project.codegen.service.impl;
import cn.hutool.db.Db;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cx.project.codegen.entity.DB;
import com.cx.project.codegen.mapper.DBMapper;
import com.cx.project.codegen.model.params.DBParam;
import com.cx.project.codegen.model.results.DBResult;
import com.cx.project.codegen.service.DBService;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DBServiceImpl extends ServiceImpl<DBMapper, DB> implements DBService {
@Override
public Boolean add(DBParam dbParam) {
DB db = new DB();
BeanUtils.copyProperties(dbParam,db);
return this.save(db);
}
@Override
public Boolean edit(DBParam dbParam){
DB db = new DB();
BeanUtils.copyProperties(dbParam,db);
return this.updateById(db);
}
@Override
public List<DBResult> list(DBParam dbParam) {
return this.baseMapper.selectDBs(dbParam);
}
@Override
public Boolean checkDB(DBParam dbParam) {
HikariDataSource dataSource = new HikariDataSource();
// "jdbc:mysql://127.0.0.1:3306/cx-oauth?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false"
dataSource.setJdbcUrl(dbParam.getPrepend()+dbParam.getUrl());
// "root"
dataSource.setUsername(dbParam.getUsername());
// "root"
dataSource.setPassword(dbParam.getPassword());
try {
new Db(dataSource);
}catch (Exception exception){
return false;
}
return true;
}
}
7.controller编写
package com.cx.project.codegen.controller;
import com.cx.common.web.respond.result.R;
import com.cx.project.codegen.model.params.DBParam;
import com.cx.project.codegen.model.results.DBResult;
import com.cx.project.codegen.service.DBService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping("/codegen/db")
public class DBController {
@Resource
private DBService dbService;
@GetMapping("/list")
@ResponseBody
public PageInfo<DBResult> list(DBParam dbParam){
Integer currentPage = dbParam.getCurrentPage();
Integer pageSize = dbParam.getPageSize();
if(!StringUtils.isEmpty(currentPage)&&!StringUtils.isEmpty(pageSize)) {
PageHelper.startPage(currentPage, pageSize);
}
List<DBResult> dBResults = dbService.list(dbParam);
return new PageInfo<>(dBResults);
}
@PostMapping("/add")
@ResponseBody
public R add(@RequestBody DBParam dbParam){
dbParam.setCreateTime(new Date()).setCreateUserId(1L);
return this.dbService.add(dbParam)? R.success():R.fail();
}
@PutMapping("/edit")
@ResponseBody
public R edit(@RequestBody DBParam dbParam){
return this.dbService.edit(dbParam)? R.success():R.fail();
}
@DeleteMapping("/delById")
@ResponseBody
public R delById(@RequestParam("id") String id){
return this.dbService.removeById(id)? R.success():R.fail();
}
@PostMapping("/checkDB")
@ResponseBody
public R checkDB(@RequestBody DBParam dbParam){
return dbService.checkDB(dbParam)?R.success():R.fail();
}
}
四、前端代码编写
1、mockjs新增页面(以后此部分内容入库)
import Mock from 'mockjs'
const top = [{
label: "首页",
path: "/wel/index",
icon: 'el-icon-document',
meta: {
i18n: 'dashboard',
},
parentId: 0
},
{
label: "开发平台",
icon: 'el-icon-document',
path: "/codegen/index",
meta: {
// i18n: 'test',
},
parentId: 1
},
{
label: "官网",
icon: 'el-icon-document',
meta: {
menu: false,
i18n: 'website',
},
path: "https://avuejs.com",
parentId: 2
},
{
label: "测试",
icon: 'el-icon-document',
path: "/test/index",
meta: {
i18n: 'test',
},
parentId: 3
},
{
label: "更多",
icon: 'el-icon-document',
path: "/wel/dashboard",
meta: {
menu: false,
i18n: 'more',
},
parentId: 4
}]
const first = [{
label: "缓冲",
path: '/cache',
component: 'views/util/cache',
icon: 'icon-caidan',
meta: {
i18n: 'cache',
keepAlive: true
},
children: []
}, {
label: "标签",
path: '/tags',
component: 'views/util/tags',
icon: 'icon-caidan',
meta: {
i18n: 'tags',
},
children: []
}, {
label: "存储",
path: '/store',
component: 'views/util/store',
icon: 'icon-caidan',
meta: {
i18n: 'store',
},
children: []
}, {
label: "全局函数",
path: 'https://avuejs.com/doc/api?test1=1&test2=2',
icon: 'icon-caidan',
meta: {
i18n: 'api',
}
}, {
label: "日志监控",
path: '/logs',
component: 'views/util/logs',
icon: 'icon-caidan',
meta: {
i18n: 'logs',
},
children: []
}, {
label: "通用模板",
path: '/crud',
component: 'views/util/crud',
icon: 'icon-caidan',
meta: {
i18n: 'crud',
},
children: []
}, {
label: "表格",
path: '/table',
component: 'views/util/table',
icon: 'icon-caidan',
meta: {
i18n: 'table',
},
children: []
}, {
label: "表单",
path: '/form',
component: 'views/util/form',
icon: 'icon-caidan',
meta: {
i18n: 'form'
},
children: []
}, {
label: "权限",
path: '/permission',
component: 'views/util/permission',
icon: 'icon-caidan',
meta: {
i18n: 'permission',
},
children: []
}, {
label: "返回顶部",
path: '/top',
component: 'views/util/top',
icon: 'icon-caidan',
meta: {
i18n: 'top',
},
children: []
}, {
label: "表格表单",
path: '/crud-form',
component: 'views/util/crud-form',
icon: 'icon-caidan',
meta: {
i18n: 'crudForm',
},
children: []
}, {
label: "图钉",
path: '/affix',
component: 'views/util/affix',
icon: 'icon-caidan',
meta: {
i18n: 'affix',
},
children: []
}, {
label: "异常页",
path: '/error',
meta: {
i18n: 'error',
},
icon: 'icon-caidan',
children: [{
label: "403",
path: 'error',
component: 'components/error-page/403',
icon: 'icon-caidan',
children: []
}, {
label: "404",
path: '404',
component: 'components/error-page/404',
icon: 'icon-caidan',
children: []
}, {
label: "500",
path: '500',
component: 'components/error-page/500',
icon: 'icon-caidan',
children: []
}]
}]
const second = [{
label: "数据源管理",
path: '/codegen/index',
component: 'views/codegen/index',
icon: 'icon-caidan',
meta: {
// i18n: 'test',
},
children: []
},
]
const third = []
const fourth = [{
label: "测试页面",
path: '/test',
component: 'views/test',
icon: 'icon-caidan',
meta: {
i18n: 'test',
},
children: []
}]
export default ({ mock }) => {
if (!mock) return;
let menu = [first, second, third, fourth];
Mock.mock('/user/getMenu', 'get', (res) => {
let body = JSON.parse(res.body);
return {
data: menu[body.type] || []
}
})
Mock.mock('/user/getTopMenu', 'get', () => {
return {
data: top
}
})
}
2、转发配置
devServer: {
proxy: { //配置跨域
'/codegen/db': {
target: 'http://127.0.0.1:80/', //这里后台的地址模拟的;应该填写你们真实的后台接口
changOrigin: true, //允许跨域
pathRewrite: {
/* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
实际上访问的地址是:http://121.121.67.254:8185/core/getData/userInfo,因为重写了 /api
*/
'^/codegen/db': 'codegen/db'
}
},
// '/api': {
// target: 'http://127.0.0.1:80/', //这里后台的地址模拟的;应该填写你们真实的后台接口
// changOrigin: true, //允许跨域
// pathRewrite: {
// /* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
// 实际上访问的地址是:http://121.121.67.254:8185/core/getData/userInfo,因为重写了 /api
// */
// '^/api': ''
// }
// },
}
},
3、编写vue页面代码
<template>
<basic-container>
<h3>数据源管理</h3>
<avue-crud
:option="option"
@on-load="onLoad"
:page="page"
:data="data"
v-model = "form"
@row-save="save"
@row-update="edit"
@row-del="delById"
@refresh-change="refresh"
>
<!--表单内容自定义-->
<template slot-scope="scope" slot="sortForm">
<avue-input-number v-model="form.sort" placeholder="请选择内容" ></avue-input-number>
</template>
<template slot-scope="scope" slot="prependForm">
<avue-select v-model="form.prepend" placeholder="请选择内容" type="tree" :dic="dics.prepend"></avue-select>
</template>
<template slot-scope="scope" slot="testForm">
<el-button type="primary" @click="startTheTest">开始执行</el-button>
</template>
</avue-crud>
</basic-container>
</template>
<script>
import { list, add, edit, delById, checkDB} from '@/api/codegen/db.js'
const MYSQL_PREPEND = "jdbc:mysql://";
const MSSQL_PREPEND = "jdbc:jtds:sqlserver://";
const ORACLE_PREPEND = "jdbc:oracle:thin:@//";
export default {
name: "index",
data(){
return{
//定义相关属性
option: {
column: [
{
label: "序号",
prop: "sort",
formslot:true,
},
{
label: "jdbc-前缀",
prop: "prepend",
formslot:true,
rules: [{
required: true,
message: "请输入jdbc-前缀",
trigger: "blur"
}]
},
{
label: "jdbc-url",
prop: "url",
overHidden: true,
// type: "url",
rules: [{
required: true,
message: "请输入url",
trigger: "blur"
}]
},
{
label: "用户名",
prop: "username",
rules: [{
required: true,
message: "请输入用户名",
trigger: "blur"
}]
},
{
label: "密码",
prop: "password",
type: "password",
hide: true,
// span: 14,
// row: true,
rules: [{
required: true,
message: "请输入密码",
trigger: "blur"
}]
},
{
label: "测试链接",
prop: "test",
type: "test",
hide: true,
formslot:true,
},
]
},
// 分页属性
page: {
currentPage: 1,
pageSize: 10,
total:undefined
},
// 表格数据
data: [],
// 表单数据
form:{},
// 字典数据:此处后期放到字典项中
dics: {
prepend: [
{
label: MYSQL_PREPEND,
value: MYSQL_PREPEND
},
{
label: MSSQL_PREPEND,
value: MSSQL_PREPEND
},
{
label: ORACLE_PREPEND,
value: ORACLE_PREPEND
}
]
},
}
},
created() {
},
methods:{
onLoad(page){
this.page.currentPage = page.currentPage;
this.page.pageSize = page.pageSize;
list(this.page).then(res=>{
this.data = res.data.list;
this.page.total = res.data.total;
})
},
refresh(/*{page,searchForm}*/){
this.onLoad(this.page)
},
// 保存
save(row,done,loading){
loading()
add(row).then(res=>{
if(res.data.code === 200){
this.$message({
message: '新增成功',
type: 'success'
});
}else {
this.$message.error('新增失败!');
}
})
this.onLoad(this.page)
done()
},
//编辑
edit(row,index,done,loading){
loading()
edit(row).then(res=>{
if(res.data.code === 200){
this.$message({
message: '更新成功',
type: 'success'
});
}else {
this.$message.error('更新失败!');
}
})
this.onLoad(this.page)
done()
},
// 删除
delById(form/*,index*/){
this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delById(form.id).then(res=>{
res.data.code === 200 ? this.$message.success('删除成功!') : this.$message.error("删除失败!");
this.onLoad(this.page)
})
}).catch(() => {
this.$message.info('已取消删除');
});
},
// 开始执行测试 校验数据库
startTheTest(){
checkDB(this.form).then(res=>{
if(res.data.code === 200){
this.$message.success('数据库链接测试成功!');
}else {
this.$message.error('数据库链接测试失败!');
}
})
}
}
}
</script>
<style scoped>
</style>
4.编写前端接口
import request from '@/router/axios';
import { baseUrl } from '@/config/env';
import JSONbig from 'json-bigint'
export const list = (data) => {
return request({
url: baseUrl + '/codegen/db/list',
method: 'get',
meta: {
isSerialize: false
},
params: data,
// 解决axios精度不够的问题
transformResponse: [ data => {
data = JSONbig.parse(data);
data.list.filter((item)=>{
item.id = item.id.toString();
return item;
})
return data;
}],
})
}
export const add = (data) => request({
url: baseUrl + '/codegen/db/add',
method: 'post',
meta: {
isSerialize: false
},
data: data
})
export const edit = (data) => request({
url: baseUrl + '/codegen/db/edit',
method: 'put',
meta: {
isSerialize: false
},
data: data
})
export const delById = (id) => request.delete(baseUrl + '/codegen/db/delById', {
params: {
id
}
})
export const checkDB = (data) => request({
url: baseUrl + '/codegen/db/checkDB',
method: 'post',
meta: {
isSerialize: false
},
data: data
})