🔨 重构代码生成器前端,使用antd-vue

This commit is contained in:
b2baccline
2020-06-18 15:02:03 +08:00
parent a0386f0379
commit 2f2cc97acd
219 changed files with 17084 additions and 1211 deletions

View File

@@ -0,0 +1 @@
/src/main/resources/public

View File

@@ -0,0 +1,99 @@
<?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">
<parent>
<artifactId>ballcat-codegen</artifactId>
<groupId>com.hccake</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ballcat-codegen-backend</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.hccake</groupId>
<artifactId>ballcat-common-conf</artifactId>
</dependency>
<!--webmvc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
</dependency>
<!--动态数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!--模板引擎-->
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<version>1.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy Vue.js frontend content</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources/public</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>${project.parent.basedir}/ballcat-codegen-frontend/target/dist</directory>
<includes>
<include>static/</include>
<include>index.html</include>
<include>favicon.ico</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,64 @@
package com.hccake.ballcat.codegen.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* @author Hccake
* @version 1.0
* @date 2020/6/18 13:37
* 前端页面请求404问题
*/
@Slf4j
@Configuration
public class SpaRedirectFilterConfiguration {
private final static AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
@Bean
public FilterRegistrationBean<?> spaRedirectFiler() {
FilterRegistrationBean<OncePerRequestFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(createRedirectFilter());
registration.addUrlPatterns("/*");
registration.setName("frontendRedirectFiler");
registration.setOrder(1);
return registration;
}
private OncePerRequestFilter createRedirectFilter() {
return new OncePerRequestFilter() {
// Forwards all routes except '/index.html', '/200.html', '/favicon.ico', '/sw.js' '/api/', '/api/**'
private final String REGEX = "(?!/actuator|/_nuxt|/static|/index\\.html|/200\\.html|/favicon\\.ico|/sw\\.js).*$";
private final Pattern pattern = Pattern.compile(REGEX);
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
String requestUri = req.getRequestURI();
if(SpaRedirectFilterConfiguration.ANT_PATH_MATCHER.match("/api/**", requestUri)){
log.info("URL {} access the backend, redirecting...", requestUri);
RequestDispatcher rd = req.getRequestDispatcher(requestUri.substring(4));
rd.forward(req, res);
}else if (pattern.matcher(requestUri).matches() && !"/".equals(requestUri)) {
// Delegate/Forward to `/` if `pattern` matches and it is not `/`
// Required because of 'mode: history'usage in frontend routing, see README for further details
log.info("URL {} entered directly into the Browser, redirecting...", requestUri);
RequestDispatcher rd = req.getRequestDispatcher("/");
rd.forward(req, res);
} else {
chain.doFilter(req, res);
}
}
};
}
}

View File

@@ -0,0 +1,25 @@
//package com.hccake.ballcat.codegen.controller;
//
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.RequestMapping;
//
///**
// * @author Hccake
// * @version 1.0
// * @date 2020/6/18 13:46
// */
//@Slf4j
//@Controller
//@RequestMapping("/api")
//public class BackendController {
//
// // Forwards all routes to FrontEnd except: '/', '/index.html', '/api', '/api/**'
// // Required because of 'mode: history' usage in frontend routing, see README for further details
// @RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
// public String redirectApi() {
// log.debug("URL entered directly into the Browser, so we need to redirect...");
// return "forward:/";
// }
//
//}

View File

@@ -0,0 +1,6 @@
spring:
datasource:
url: jdbc:mysql://ballcat-mysql:3306/ballcat_codegen?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: '123456'

View File

@@ -6,8 +6,6 @@ spring:
name: @artifactId@
profiles:
active: @profiles.active@ # 当前激活配置默认dev
resources:
static-locations: classpath:/static/
mybatis-plus:
mapper-locations: classpath:/mapper/*Mapper.xml

View File

@@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

View File

@@ -0,0 +1 @@
VUE_APP_API_URL_PREFIX=/api

View File

@@ -0,0 +1,14 @@
module.exports = {
root: true,
parserOptions: {
ecmaVersion: 2017,
sourceType: 'module',
ecmaFeatures: { jsx: true },
parser: 'babel-eslint'
},
parser: 'vue-eslint-parser',
extends: ['eslint:recommended', 'prettier'],
plugins: ['prettier', 'vue'],
rules: { 'prettier/prettier': ['error'] },
env: { browser: true, node: true, es6: true, mocha: false, jest: false }
}

View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
node
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,10 @@
module.exports = {
eslintIntegration: true,
stylelintIntegration: true,
printWidth: 120,
semi: false,
trailingComma: 'none',
singleQuote: true,
useTabs: false,
arrowParens: 'avoid'
}

View File

@@ -0,0 +1,6 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
plugins: [
["import", {libraryName: "ant-design-vue", libraryDirectory: "es", style: true}]
]
};

View File

@@ -0,0 +1,3 @@
module.exports = {
preset: "@vue/cli-plugin-unit-jest"
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
{
"name": "ballcat-codegen-ui",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint --fix"
},
"dependencies": {
"ant-design-vue": "^1.6.2",
"axios": "^0.19.2",
"babel-plugin-import": "^1.13.0",
"core-js": "^3.6.5",
"lodash.pick": "^4.4.0",
"moment": "^2.26.0",
"nprogress": "^0.2.0",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-router": "~4.4.0",
"@vue/cli-plugin-unit-jest": "~4.4.0",
"@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^6.2.2",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"lint-staged": "^9.5.0",
"prettier": "^1.19.1",
"vue-template-compiler": "^2.6.11"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
}
}

View File

@@ -0,0 +1,64 @@
<?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">
<parent>
<artifactId>ballcat-codegen</artifactId>
<groupId>com.hccake</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ballcat-codegen-frontend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<executions>
<!-- Install our node and npm version to run npm/node scripts-->
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v12.12.0</nodeVersion>
</configuration>
</execution>
<!-- Install all project dependencies -->
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<!-- Build and minify static files -->
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>BallCat Code Generator</title>
</head>
<body>
<noscript>
<strong>We're sorry but Ballcat Codegen doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,11 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<style lang="less">
#app {
height: 100%;
}
</style>

View File

@@ -0,0 +1,11 @@
import { axios } from '@/utils/request'
export function codeGen(dsName, genConfig) {
return axios({
url: '/generator/code',
method: 'post',
data: genConfig,
headers: { dsName: dsName },
responseType: 'blob'
})
}

View File

@@ -0,0 +1,46 @@
import { axios } from '@/utils/request'
export function getPage(query) {
return axios({
url: '/gen/datasourceconfig/page',
method: 'get',
params: query
})
}
export function addObj(obj) {
return axios({
url: '/gen/datasourceconfig',
method: 'post',
data: obj
})
}
export function getObj(id) {
return axios({
url: '/gen/datasourceconfig/' + id,
method: 'get'
})
}
export function delObj(id) {
return axios({
url: '/gen/datasourceconfig/' + id,
method: 'delete'
})
}
export function putObj(obj) {
return axios({
url: '/gen/datasourceconfig',
method: 'put',
data: obj
})
}
export function getSelectData() {
return axios({
url: '/gen/datasourceconfig/select',
method: 'get'
})
}

View File

@@ -0,0 +1,10 @@
import { axios } from '@/utils/request'
export function getPage(dsName, query) {
return axios({
url: '/tableinfo/page',
method: 'get',
params: query,
headers: { dsName: dsName }
})
}

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="130px" height="130px" viewBox="0 0 130 130" enable-background="new 0 0 130 130" xml:space="preserve"> <image id="image0" width="130" height="130" x="0" y="0"
href="data:image/png;base64,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
SW1hZ2VSZWFkeXHJZTwAAAAASUVORK5CYII=" />
</svg>

View File

@@ -0,0 +1,58 @@
<template>
<a-layout id="components-layout-side" style="min-height: 100vh">
<a-layout-sider :trigger="null" v-model="collapsed" collapsible width="256px">
<div class="logo">BallCat Code Generator</div>
<SiderMenu />
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0">
<a-icon class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="collapsed = !collapsed" />
<Header />
</a-layout-header>
<a-layout-content style="margin: 16px">
<router-view />
</a-layout-content>
<a-layout-footer style="text-align: center">
<Footer />
</a-layout-footer>
</a-layout>
</a-layout>
</template>
<script>
import Header from './Header'
import Footer from './Footer'
import SiderMenu from './SiderMenu'
export default {
name: 'BasicLayout',
components: { Header, Footer, SiderMenu },
data() {
return {
collapsed: false,
}
},
}
</script>
<style lang="less">
@import url('../less/global.less');
#components-layout-side .logo {
color: #eeeeee;
line-height: 64px;
text-align: center;
overflow: hidden;
}
#components-layout-side .trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
#components-layout-side .trigger:hover {
color: #1890ff;
}
</style>

View File

@@ -0,0 +1,13 @@
<template>
<div>BallCat CodeGen 2020 Created By Hccake</div>
</template>
<script>
export default {
name: "Footer"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,16 @@
<template>
<div class="header">Header</div>
</template>
<script>
export default {
name: "Header"
}
</script>
<style scoped>
.header {
float: right;
}
</style>

View File

@@ -0,0 +1,58 @@
<template>
<div style="width: 256px">
<a-menu :selected-keys="selectedKeys" :open-keys.sync="openKeys" mode="inline" theme="dark">
<template v-for="item in menuData">
<a-menu-item v-if="!item.children" :key="item.path" @click="$router.push({ path: item.path })">
<a-icon v-if="item.meta.icon" :type="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-menu>
</div>
</template>
<script>
import SubMenu from './SubMenu'
export default {
name: 'SiderMenu',
components: {
'sub-menu': SubMenu
},
watch: {
'$route.path': function(val) {
this.selectedKeys = this.selectedKeysMap[val]
this.openKeys = this.openKeysMap[val]
}
},
data() {
this.selectedKeysMap = {}
this.openKeysMap = {}
const menuData = this.getMenuData(this.$router.options.routes[0].children)
return {
selectedKeys: this.selectedKeysMap[this.$route.path],
openKeys: this.openKeysMap[this.$route.path],
menuData
}
},
methods: {
getMenuData(routes = [], parentKeys = [], selectedKey) {
const menuData = []
routes.forEach(item => {
if (!item.hiddenInMenu) {
const newItem = { ...item }
delete newItem.children
this.openKeysMap[item.path] = parentKeys
this.selectedKeysMap[item.path] = [selectedKey || item.path]
if (item.children && !item.hideChildrenInMenu) {
newItem.children = this.getMenuData(item.children, [...parentKeys, item.path])
}
menuData.push(newItem)
}
})
return menuData
}
}
}
</script>

View File

@@ -0,0 +1,27 @@
<template functional>
<a-sub-menu :key="props.menuInfo.path" >
<span slot="title">
<a-icon v-if="props.menuInfo.meta.icon" :type="props.menuInfo.meta.icon"/>
<span>{{ props.menuInfo.meta.title }}</span>
</span>
<template v-for="item in props.menuInfo.children">
<a-menu-item v-if="!item.children" :key="item.path" @click="parent.$router.push({path: item.path})">
<a-icon v-if="item.meta.icon" :type="item.meta.icon"/>
<span>{{ item.meta.title }}</span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item"/>
</template>
</a-sub-menu>
</template>
<script>
export default {
name: 'SubMenu',
isSubMenu: true,
props: {
menuInfo: {
type: Object,
default: () => ({}),
},
}
};
</script>

View File

@@ -0,0 +1,52 @@
.table-alert {
margin-bottom: 16px;
}
.table-page-search-wrapper {
.ant-form-inline {
.ant-form-item {
display: flex;
margin-bottom: 15px;
margin-right: 0;
.ant-form-item-control-wrapper {
flex: 1 1;
display: inline-block;
vertical-align: middle;
}
> .ant-form-item-label {
line-height: 32px;
padding-right: 8px;
width: auto;
}
.ant-form-item-control {
height: 32px;
line-height: 32px;
}
}
}
.table-page-search-submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
}
.content {
.table-operator {
margin-bottom: 18px;
button {
margin-right: 8px;
}
}
}
.ant-card-body .table-operator {
margin-bottom: 18px;
button {
margin-right: 8px;
}
}

View File

@@ -0,0 +1,49 @@
import Vue from 'vue'
import {
Button,
Layout,
Icon,
Menu,
Table,
Form,
Card,
Row,
Input,
Col,
Divider,
Popconfirm,
Select,
message
} from 'ant-design-vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.use(Button)
Vue.use(Layout)
Vue.use(Icon)
Vue.use(Menu)
Vue.use(Table)
Vue.use(Form)
Vue.use(Card)
Vue.use(Row)
Vue.use(Input)
Vue.use(Col)
Vue.use(Divider)
Vue.use(Popconfirm)
Vue.use(Select)
Vue.prototype.$message = message
Vue.prototype.FORM_ACTION = {
NONE: '',
ADD: 'add',
UPDATE: 'update'
}
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

View File

@@ -0,0 +1,107 @@
import pick from 'lodash.pick'
export default {
data() {
return {
form: this.$form.createForm(this),
formAction: this.FORM_ACTION.NONE,
labelCol: { lg: { span: 3 }, sm: { span: 3 } },
wrapperCol: { lg: { span: 8 }, sm: { span: 19 } },
decoratorOptions: {},
displayData: {
createTime: '',
updateTime: ''
},
// 提交按钮防止重复提交
submitLoading: false,
addObj: function() {},
putObj: function() {}
}
},
methods: {
// ============ 添加 ======================
buildCreatedForm(argument) {
this.form.resetFields()
this.formAction = this.FORM_ACTION.CREATE
// 钩子函数 处理某些页面定制需求
this.createdFormCallback(argument)
},
/*eslint-disable*/
createdFormCallback(argument) {
// 组件复写此方法 完成添加之前的事件
},
// ============ 修改 ======================
buildUpdatedForm(record, argument) {
let that = this
that.formAction = that.FORM_ACTION.UPDATE
record = that.echoDataProcess(record)
// 延迟加载 避免隐藏展示元素时出现的bug
setTimeout(() => {
// 获取仅展示元素
that.displayData = pick(record, Object.keys(that.displayData))
// 移除所有不用的元素,否则会抛出异常
const fromData = pick(record, Object.keys(that.form.getFieldsValue()))
this.$nextTick(function() {
that.form.resetFields()
that.form.setFieldsValue(fromData)
})
}, 0)
this.updatedFormCallback(argument)
},
echoDataProcess(data) {
// 对准备回显的数据做预处理
return data
},
/*eslint-disable*/
updatedFormCallback(argument) {
// 组件复写此方法 完成修改之后的事件
},
// ============ 提交 ======================
handleSubmit(e) {
// 钩子函数 处理提交之前处理的事件
this.beforeStartSubmit()
const req = this.formAction === this.FORM_ACTION.CREATE ? this.addObj : this.putObj
e.preventDefault()
this.form.validateFields((err, values) => {
if (!err) {
this.submitLoading = true
req(this.submitDataProcess(values))
.then(res => {
if (res.code === 200) {
this.$message.success(res.msg)
this.submitSuccess(res)
} else {
this.$message.error(res.msg)
}
})
.catch(error => {
this.$message.error(error.response.data.msg)
})
.finally(() => {
this.submitLoading = false
})
}
})
},
/*eslint-disable*/
beforeStartSubmit(record) {
// 组件复写此方法 提交之前处理的事件
},
submitDataProcess(data) {
// 在此处理表单提交的数据
return data
},
/*eslint-disable*/
submitSuccess(res) {
// 提交表单成功的回调函数
},
/*eslint-disable*/
submitError(res) {
// 提交表单失败的回调函数
}
}
}

View File

@@ -0,0 +1,42 @@
import FormMixin from './formMixin'
export default {
mixins: [FormMixin],
data () {
return {
visible: false,
labelCol: {
xs: { span: 8 },
sm: { span: 24 },
lg: { span: 5}
},
wrapperCol: {
xs: { span: 16 },
sm: { span: 24 },
lg: { span: 17 }
},
}
},
methods: {
show() {
this.visible = true
this.submitLoading = false
},
add() {
this.buildCreatedForm()
this.show()
},
update(record) {
this.buildUpdatedForm(record)
this.show()
},
submitSuccess (res){
this.$emit('reloadPageTable', false)
this.handleClose()
},
handleClose(e) {
this.visible = false
this.submitLoading = false
}
}
}

View File

@@ -0,0 +1,25 @@
import FormMixin from './formMixin'
export default {
mixins: [FormMixin],
data () {
return {
labelCol: { lg: { span: 3 }, sm: { span: 3 } },
wrapperCol: { lg: { span: 8 }, sm: { span: 19 } },
}
},
methods: {
add (argument) {
this.buildCreatedForm(argument)
},
update (record, argument) {
this.buildUpdatedForm(record, argument)
},
submitSuccess (res){
this.backToPage(true);
},
backToPage (needRefresh) {
this.$emit('backToPage', needRefresh)
}
}
}

View File

@@ -0,0 +1,11 @@
import TablePageMixin from './tablePageMixin'
import FormMixin from './formMixin'
import FormPageMixin from './formPageMixin'
import FormModalMixin from './formModalMixin'
export {
TablePageMixin,
FormMixin,
FormPageMixin,
FormModalMixin
}

View File

@@ -0,0 +1,185 @@
export default {
data() {
return {
// 主键 默认id
rowKey: 'id',
// 数据数组
dataSource: [],
// 数据加载动画
loading: false,
// 分页器设置
pagination: {
total: 0,
current: 1,
pageSize: 10,
showSizeChanger: true,
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + total + '条'
}
},
// 查询参数
queryParam: {},
// 筛选参数字段
filters: {},
// 默认排序字段
sortField: 'createTime',
// 升序/降序
sortAsc: false,
// 表格展示
tableShow: true,
// 高级搜索 展开/关闭
advanced: false,
// 获取分页数据的方法
getPage: function() {},
// 删除 数据的方法
delObj: function() {},
// 表单页的title
cardTitle: '',
//表单初始化标识
formInited: false,
// 已选中数据集合
selectedRows: [],
// 已选中的数据主键集合
selectedRowKeys: [],
// 延迟加载created时不主动加载数据
lazyLoad: false,
// 需要加载的 dictSlot数据
dictCodes: []
}
},
created() {
// this.DictPool.initDictList(this.dictCodes)
!this.lazyLoad && this.loadData()
},
methods: {
/**
* 表格重新加载方法
* 如果参数为 true, 则强制刷新到第一页
* @param bool
*/
reloadTable(bool = false) {
bool && (this.pagination.current = 1)
this.loadData()
},
/**
* 表格数据加载方法
*/
loadData() {
// 合并查询参数,分页参数,排序参数,过滤参数
const params = Object.assign(
this.queryParam,
{
current: this.pagination.current,
size: this.pagination.pageSize
},
{
sortField: this.sortField,
sortAsc: this.sortAsc
},
{ ...this.filters }
)
this.loading = true
this.getPage(params)
.then(res => {
if (res.code === 200 || res.code === 0) {
const page = res.data
// 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
if (page.records.length === 0 && this.pagination.current > 1) {
this.pagination.current--
this.loadData()
return
}
this.dataSource = page.records
this.pagination.total = page.total
} else {
this.$message.warning(res.message)
}
})
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.loading = false
})
},
/**
* 分页、排序、筛选变化时进行数据更新
* @param pagination
* @param filters
* @param sorter
*/
handleTableChange(pagination, filters, sorter) {
this.filters = filters
sorter && sorter.field && (this.sortField = sorter.field)
sorter && sorter.order && (this.sortAsc = sorter.order === 'ascend')
this.pagination = pagination
this.loadData()
},
// 展开/关闭 搜索条件
toggleAdvanced() {
this.advanced = !this.advanced
},
// 清空搜索条件
resetSearchForm() {
this.queryParam = {}
},
// 选择
onSelectChange(selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
this.selectedRows = selectedRows
},
// 清空选项
onClearSelected() {
this.selectedRowKeys = []
this.selectedRows = []
},
// 删除
handleDel(record) {
this.delObj(record[this.rowKey]).then(res => {
if (res.code === 200) {
this.$message.success(res.msg)
this.reloadTable()
} else {
this.$message.error(res.msg)
}
})
},
// ========== PageForm交互 ===================
// TODO 支持 modal 形式表单
// 切换表格/表单
switchPage() {
window.scrollTo(0, 0)
this.tableShow = !this.tableShow
if (!this.formInited) {
this.formInited = true
}
},
// 返回表格
backToPage(needRefresh) {
this.switchPage()
needRefresh && this.reloadTable(false)
},
// 新增
handleAdd(argument) {
this.switchPage()
this.cardTitle = '新增'
this.$nextTick(function() {
this.$refs.formPage.add(argument)
})
},
// 编辑
handleEdit(record, title) {
this.switchPage()
this.cardTitle = title || '修改'
this.$nextTick(function() {
this.$refs.formPage.update(record)
})
}
}
}

View File

@@ -0,0 +1,67 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// 捕获异常否则重复push控制台有异常
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
Vue.use(VueRouter)
const routes = [
{
path: '/',
hiddenInMenu: true,
component: () => import(`../layouts/BasicLayout`),
redirect: '/gen',
children: [
{
path: '/gen',
redirect: '/gen/codegen',
meta: { icon: 'dashboard', title: '代码生成' },
component: { render: h => h('router-view') },
children: [
{
path: '/gen/codegen',
name: 'CodeGen',
meta: { title: '代码生成器' },
component: () => import(/* webpackChunkName: "gen" */ '../views/gen/codegen/CodeGenPage')
},
{
path: '/gen/datasouce',
name: 'Datasource',
meta: { title: '数据源配置' },
component: () => import(/* webpackChunkName: "gen" */ '../views/gen/datasourceconfig/DataSourceConfigPage')
}
]
},
{
path: '*',
name: '404',
hiddenInMenu: true,
component: () => import('../views/404')
}
]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach((to, from, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
export default router

View File

@@ -0,0 +1,11 @@
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
});

View File

@@ -0,0 +1,40 @@
import axios from 'axios'
import { notification } from 'ant-design-vue'
const axiosInstance = axios.create({
baseURL: process.env.VUE_APP_API_URL_PREFIX,
timeout: 60000 // 请求超时时间
})
const err = error => {
if (error.response) {
const {
response: { status, data }
} = error
if (status === 403) {
notification.error({
message: 'Forbidden',
description: data.message
})
}
if (status === 401 && !(data.result && data.result.isLogin)) {
notification.error({
message: 'Unauthorized',
description: 'Authorization verification failed'
})
}
}
return Promise.reject(error)
}
// request interceptor
axiosInstance.interceptors.request.use(config => {
return config
}, err)
// response interceptor
axiosInstance.interceptors.response.use(response => {
return response.data
}, err)
export { axiosInstance as axios }

View File

@@ -0,0 +1,11 @@
<template>
<div>404</div>
</template>
<script>
export default {}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,157 @@
<template>
<div>
<a-card v-show="tableShow" :bordered="false">
<!-- 查询条件 -->
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="48">
<a-col :md="8" :sm="24">
<a-form-item label="数据源">
<a-select v-model="dsName" style="width: 100%">
<a-select-option key="master" value="master">master</a-select-option>
<a-select-option v-for="item in dataSourceSelectData" :key="item.value">
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="8" :sm="24">
<a-form-item label="表名">
<a-input v-model="queryParam.tableName" placeholder="" />
</a-form-item>
</a-col>
<!-- <template v-if="advanced">
</template>-->
<a-col :md="(!advanced && 8) || 24" :sm="24">
<span
class="table-page-search-submitButtons"
:style="(advanced && { float: 'right', overflow: 'hidden' }) || {}"
>
<a-button type="primary" @click="reloadTable">查询</a-button>
<a-button style="margin-left: 8px" @click="resetSearchForm">重置</a-button>
<!--<a @click="toggleAdvanced" style="margin-left: 8px">
{{ advanced ? '收起' : '展开' }}
<a-icon :type="advanced ? 'up' : 'down'"/>
</a>-->
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button type="primary" icon="download" @click="handleGenerate()">批量生成</a-button>
</div>
<!--数据表格区域-->
<div class="table-wrapper">
<a-table
ref="table"
size="middle"
:rowKey="rowKey"
:columns="columns"
:dataSource="dataSource"
:pagination="pagination"
:loading="loading"
@change="handleTableChange"
:rowSelection="{ onChange: onSelectChange, selectedRowKeys: selectedRowKeys }"
>
<span slot="action-slot" slot-scope="text, record">
<template>
<a @click="handleGenerate(record)">生成</a>
</template>
</span>
</a-table>
</div>
</a-card>
</div>
</template>
<script>
import { TablePageMixin } from '@/mixins'
import { getPage as getTableInfoPage } from '@/api/gen/tableinfo'
import { codeGen } from '@/api/gen/codegen'
import { getSelectData } from '@/api/gen/datasourceconfig'
export default {
name: 'CodegenPage',
mixins: [TablePageMixin],
data() {
return {
getPage: queryParam => {
return getTableInfoPage(this.dsName, queryParam)
},
rowKey: 'tableName',
queryParam: {
dsName: 'master'
},
columns: [
{
title: '表名',
dataIndex: 'tableName',
width: '250px'
},
{
title: 'Engine',
dataIndex: 'engine'
},
{
title: '表备注',
dataIndex: 'tableComment'
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '150px',
sorter: true
},
{
title: '操作',
dataIndex: 'action',
width: '150px',
scopedSlots: { customRender: 'action-slot' }
}
],
dataSourceSelectData: [],
dsName: 'master'
}
},
mounted() {
getSelectData().then(res => {
this.dataSourceSelectData = res.data
})
},
watch: {
dsName() {
this.reloadTable(true)
}
},
methods: {
handleGenerate() {
codeGen(this.dsName, { tableNames: this.selectedRowKeys, genConfigVO: {} }).then(fileBlob => {
const blob = new Blob([fileBlob])
const fileName = 'BallCat-CodeGen.zip'
const eLink = document.createElement('a')
if ('download' in eLink) {
// 非IE下载
eLink.download = fileName
eLink.style.display = 'none'
eLink.href = URL.createObjectURL(blob)
document.body.appendChild(eLink)
eLink.click()
URL.revokeObjectURL(eLink.href) // 释放URL 对象
document.body.removeChild(eLink)
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName)
}
})
}
}
}
</script>

View File

@@ -0,0 +1,75 @@
<template>
<a-form @submit="handleSubmit" :form="form">
<a-form-item v-if="formAction === this.FORM_ACTION.UPDATE" style="display: none">
<a-input v-decorator="['id']" />
</a-form-item>
<a-form-item label="数据源名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="数据源名称" v-decorator="['name']" />
</a-form-item>
<a-form-item label="用户名" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="用户名" v-decorator="['username']" />
</a-form-item>
<a-form-item
label="原密码"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
v-if="formAction === this.FORM_ACTION.UPDATE"
>
<a-input v-model="password" disabled />
</a-form-item>
<a-form-item label="密码" :labelCol="labelCol" :wrapperCol="wrapperCol">
<template #extra v-if="formAction === this.FORM_ACTION.UPDATE">
<p style="color: red">注意如果需要修改密码则填写此处不修改请置空</p>
</template>
<a-input placeholder="密码" v-decorator="['pass']" />
</a-form-item>
<a-form-item label="连接地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea placeholder="连接地址" v-decorator="['url']" :rows="4" />
</a-form-item>
<div v-show="formAction === this.FORM_ACTION.UPDATE">
<a-form-item label="创建时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
<span>{{ displayData.createTime }}</span>
</a-form-item>
<a-form-item label="修改时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
<span>{{ displayData.updateTime }}</span>
</a-form-item>
</div>
<a-form-item :wrapperCol="{ offset: 3 }">
<a-button htmlType="submit" type="primary" :loading="submitLoading">提交</a-button>
<a-button style="margin-left: 8px" @click="backToPage(false)">取消</a-button>
</a-form-item>
</a-form>
</template>
<script>
import { FormPageMixin } from '@/mixins'
import { addObj, putObj } from '@/api/gen/datasourceconfig'
export default {
name: 'DataSourceConfigFormPage',
mixins: [FormPageMixin],
data() {
return {
addObj: addObj,
putObj: putObj,
// 校验配置
decoratorOptions: {},
password: ''
}
},
methods: {
echoDataProcess(data) {
this.password = data.password
return data
}
}
}
</script>

View File

@@ -0,0 +1,128 @@
<template>
<div>
<a-card v-show="tableShow" :bordered="false">
<!-- 查询条件 -->
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="48">
<a-col :md="8" :sm="24">
<a-form-item label="ID">
<a-input v-model="queryParam.id" placeholder="" />
</a-form-item>
</a-col>
<!-- <template v-if="advanced">
</template>-->
<a-col :md="(!advanced && 8) || 24" :sm="24">
<span
class="table-page-search-submitButtons"
:style="(advanced && { float: 'right', overflow: 'hidden' }) || {}"
>
<a-button type="primary" @click="reloadTable">查询</a-button>
<a-button style="margin-left: 8px" @click="resetSearchForm">重置</a-button>
<!--<a @click="toggleAdvanced" style="margin-left: 8px">
{{ advanced ? '收起' : '展开' }}
<a-icon :type="advanced ? 'up' : 'down'"/>
</a>-->
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button type="primary" icon="plus" @click="handleAdd()">新建</a-button>
</div>
<!--数据表格区域-->
<div class="table-wrapper">
<a-table
ref="table"
size="middle"
:rowKey="rowKey"
:columns="columns"
:dataSource="dataSource"
:pagination="pagination"
:loading="loading"
@change="handleTableChange"
>
<span slot="action-slot" slot-scope="text, record">
<template>
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-popconfirm title="确认要删除吗?" @confirm="() => handleDel(record)">
<a href="javascript:;">删除</a>
</a-popconfirm>
</template>
</span>
</a-table>
</div>
</a-card>
<!--表单页面-->
<a-card v-if="formInited" :bordered="false" :title="cardTitle" v-show="!tableShow">
<form-page ref="formPage" @backToPage="backToPage"></form-page>
</a-card>
</div>
</template>
<script>
import { getPage, delObj } from '@/api/gen/datasourceconfig'
import FormPage from './DataSourceConfigForm'
import { TablePageMixin } from '@/mixins'
export default {
name: 'DataSourceConfigPage',
mixins: [TablePageMixin],
components: { FormPage },
data() {
return {
getPage: getPage,
delObj: delObj,
columns: [
{
title: '#',
dataIndex: 'id',
width: '50px'
},
{
title: '数据源名称',
dataIndex: 'name',
width: '100px'
},
{
title: '用户名',
dataIndex: 'username',
width: '80px'
},
{
title: '密码',
dataIndex: 'password',
ellipsis: true,
width: '200px'
},
{
title: '连接地址',
dataIndex: 'url',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '150px',
sorter: true
},
{
title: '操作',
dataIndex: 'action',
width: '150px',
scopedSlots: { customRender: 'action-slot' }
}
]
}
},
methods: {}
}
</script>

View File

@@ -0,0 +1,12 @@
import { shallowMount } from "@vue/test-utils";
import HelloWorld from "@/components/HelloWorld.vue";
describe("HelloWorld.vue", () => {
it("renders props.msg when passed", () => {
const msg = "new message";
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
});
expect(wrapper.text()).toMatch(msg);
});
});

View File

@@ -0,0 +1,31 @@
const SERVER_URL = 'http://ballcat-admin:7777'
const vueConfig = {
css: {
loaderOptions: {
less: {
javascriptEnabled: true
}
}
},
devServer: {
port: 8000,
proxy: {
'^/api': {
target: SERVER_URL,
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': '/'
}
}
}
},
// Change build paths to make them Maven compatible
// see https://cli.vuejs.org/config/
outputDir: 'target/dist',
assetsDir: 'static'
}
module.exports = vueConfig

View File

@@ -10,62 +10,17 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>ballcat-codegen</artifactId>
<packaging>pom</packaging>
<modules>
<module>ballcat-codegen-frontend</module>
<module>ballcat-codegen-backend</module>
</modules>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>
<groupId>com.hccake</groupId>
<artifactId>ballcat-common-conf</artifactId>
</dependency>
<!--webmvc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
</dependency>
<!--动态数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!--模板引擎-->
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<version>1.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>

View File

@@ -1,5 +0,0 @@
spring:
datasource:
url: jdbc:mysql://ballcat-mysql:3306/ballcat?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: '123456'

View File

@@ -1,135 +0,0 @@
/**
@Name全局配置
@Author贤心
@Sitehttp://www.layui.com/admin/
@LicenseLPPLlayui付费产品协议
*/
layui.define(['laytpl', 'layer', 'element', 'util'], function(exports){
exports('setter', {
container: 'LAY_app' //容器ID
,base: layui.cache.base //记录layuiAdmin文件夹所在路径
,views: layui.cache.base + 'views/' //视图所在目录
,entry: 'index' //默认视图文件名
,engine: '.html' //视图文件后缀名
,pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启
,name: 'BallCat'
,tableName: 'codegen' //本地存储表名
,MOD_NAME: 'admin' //模块事件名
,debug: true //是否开启调试模式。如开启,接口异常时会抛出异常 URL 等信息
,interceptor: false //是否开启未登入拦截
//自定义请求字段
,request: {
tokenName: 'access_token' //自动携带 token 的字段名。可设置 false 不携带。
}
//自定义响应字段
,response: {
statusName: 'code' //数据状态的字段名称
,statusCode: {
ok: 0 //数据状态一切正常的状态码
,logout: 1001 //登录状态失效的状态码
}
,msgName: 'msg' //状态信息的字段名称
,dataName: 'data' //数据详情的字段名称
}
//独立页面路由,可随意添加(无需写参数)
,indPage: [
'/user/login' //登入页
,'/user/reg' //注册页
,'/user/forget' //找回密码
,'/template/tips/test' //独立页的一个测试 demo
]
//扩展的第三方模块
,extend: []
//主题配置
,theme: {
//内置主题配色方案
color: [{
main: '#20222A' //主题色
,selected: '#009688' //选中色
,alias: 'default' //默认别名
},{
main: '#03152A'
,selected: '#3B91FF'
,alias: 'dark-blue' //藏蓝
},{
main: '#2E241B'
,selected: '#A48566'
,alias: 'coffee' //咖啡
},{
main: '#50314F'
,selected: '#7A4D7B'
,alias: 'purple-red' //紫红
},{
main: '#344058'
,logo: '#1E9FFF'
,selected: '#1E9FFF'
,alias: 'ocean' //海洋
},{
main: '#3A3D49'
,logo: '#2F9688'
,selected: '#5FB878'
,alias: 'green' //墨绿
},{
main: '#20222A'
,logo: '#F78400'
,selected: '#F78400'
,alias: 'red' //橙色
},{
main: '#28333E'
,logo: '#AA3130'
,selected: '#AA3130'
,alias: 'fashion-red' //时尚红
},{
main: '#24262F'
,logo: '#3A3D49'
,selected: '#009688'
,alias: 'classic-black' //经典黑
},{
logo: '#226A62'
,header: '#2F9688'
,alias: 'green-header' //墨绿头
},{
main: '#344058'
,logo: '#0085E8'
,selected: '#1E9FFF'
,header: '#1E9FFF'
,alias: 'ocean-header' //海洋头
},{
header: '#393D49'
,alias: 'classic-black-header' //经典黑
},{
main: '#50314F'
,logo: '#50314F'
,selected: '#7A4D7B'
,header: '#50314F'
,alias: 'purple-red-header' //紫红头
},{
main: '#28333E'
,logo: '#28333E'
,selected: '#AA3130'
,header: '#AA3130'
,alias: 'fashion-red-header' //时尚红头
},{
main: '#28333E'
,logo: '#009688'
,selected: '#009688'
,header: '#009688'
,alias: 'green-header' //墨绿头
}]
//初始的颜色索引,对应上面的配色方案数组索引
//如果本地已经有主题色记录则以本地记录为优先除非请求本地数据localStorage
,initColorIndex: 1
}
});
});

View File

@@ -1,2 +0,0 @@
/** layuiAdmin.pro-v1.2.1 LPPL License By http://www.layui.com/admin/ */
;layui.define(function(e){var i=(layui.$,layui.layer,layui.laytpl,layui.setter,layui.view,layui.admin);i.events.logout=function(){i.req({url:"./json/user/logout.js",type:"get",data:{},done:function(e){i.exit()}})},e("common",{})});

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>BallCat codegen</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<script>
/^http(s*):\/\//.test(location.href) || alert('请先部署到 localhost 下再访问');
</script>
</head>
<body>
<div id="LAY_app"></div>
<script src="layui/layui.js"></script>
<script>
layui.config({
base: './'
,version: '1.2.1'
}).use('index');
</script>
</body>
</html>

View File

@@ -1,2 +0,0 @@
/** layuiAdmin.pro-v1.2.1 LPPL License By http://www.layui.com/admin/ */
;layui.extend({setter:"config",admin:"lib/admin",view:"lib/view"}).define(["setter","admin"],function(e){var a=layui.setter,n=layui.element,i=layui.admin,t=i.tabsPage,l=layui.view,o=function(){var e=layui.router(),r=e.path,y=i.correctRouter(e.path.join("/"));r.length||(r=[""]),""===r[r.length-1]&&(r[r.length-1]=a.entry);var h=function(e){o.haveInit&&d(".layui-layer").each(function(){var e=d(this),a=e.attr("times");e.hasClass("layui-layim")||layer.close(a)}),o.haveInit=!0,d(s).scrollTop(0),delete t.type};return"tab"===t.type&&("/"!==y||"/"===y&&i.tabsBody().html())?(i.tabsBodyChange(t.index),h(t.type)):(l().render(r.join("/")).then(function(l){var o,r=d("#LAY_app_tabsheader>li");r.each(function(e){var a=d(this),n=a.attr("lay-id");n===y&&(o=!0,t.index=e)}),a.pageTabs&&"/"!==y&&(o||(d(s).append('<div class="layadmin-tabsbody-item layui-show"></div>'),t.index=r.length,n.tabAdd(u,{title:"<span>"+(l.title||"新标签页")+"</span>",id:y,attr:e.href}))),this.container=i.tabsBody(t.index),a.pageTabs||this.container.scrollTop(0),n.tabChange(u,y),i.tabsBodyChange(t.index)}).done(function(){layui.use("common",layui.cache.callback.common),c.on("resize",layui.data.resize),n.render("breadcrumb","breadcrumb"),i.tabsBody(t.index).on("scroll",function(){var e=d(this),a=d(".layui-laydate"),n=d(".layui-layer")[0];a[0]&&(a.each(function(){var e=d(this);e.hasClass("layui-laydate-static")||e.remove()}),e.find("input").blur()),n&&layer.closeAll("tips")})}),void h())},r=function(e){var n,t=layui.router(),r=l(a.container),s=i.correctRouter(t.path.join("/"));if(layui.each(a.indPage,function(e,a){if(s===a)return n=!0}),layui.config({base:a.base+"controller/"}),n||"/user/login"===s)r.render(t.path.join("/")).done(function(){i.pageType="alone"});else{if(a.interceptor){var u=layui.data(a.tableName);if(!u[a.request.tokenName])return location.hash="/user/login/redirect="+encodeURIComponent(s)}"console"===i.pageType?o():r.render("layout").done(function(){o(),layui.element.render(),i.screen()<2&&i.sideFlexible(),i.pageType="console"})}},s="#LAY_app_body",u="layadmin-layout-tabs",d=layui.$,c=d(window);layui.link(a.base+"style/admin.css?v="+(i.v+"-1"),function(){r()},"layuiAdmin"),window.onhashchange=function(){r(),layui.event.call(this,a.MOD_NAME,"hash({*})",layui.router())},layui.each(a.extend,function(e,n){var i={};i[n]="{/}"+a.base+"lib/extend/"+n,layui.extend(i)}),e("index",{render:o})});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
/** layui-v2.5.5 MIT License By https://www.layui.com */
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Some files were not shown because too many files have changed in this diff Show More