├── README.MD
├── thtf-generator-ui
├── .babelrc
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── README.md
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── package-lock.json
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ ├── languages
│ │ │ ├── en_us.json
│ │ │ └── zh_cn.json
│ │ ├── logo.png
│ │ └── user.png
│ ├── components
│ │ ├── BreadCrumb
│ │ │ └── index.vue
│ │ ├── FaIconTooltip
│ │ │ └── index.vue
│ │ ├── Hamburger
│ │ │ └── index.vue
│ │ ├── LangSelector
│ │ │ └── index.vue
│ │ ├── MenuTree
│ │ │ └── index.vue
│ │ ├── PopupTreeInput
│ │ │ └── index.vue
│ │ ├── SelectTableDiaog
│ │ │ └── index.vue
│ │ └── ThemePicker
│ │ │ └── index.vue
│ ├── http
│ │ ├── axios.js
│ │ ├── config.js
│ │ ├── index.js
│ │ └── interface.js
│ ├── i18n
│ │ └── index.js
│ ├── main.js
│ ├── mock
│ │ └── index.js
│ ├── router
│ │ └── index.js
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ └── app.js
│ ├── utils
│ │ ├── auth.js
│ │ ├── datetime.js
│ │ ├── iframe.js
│ │ └── validate.js
│ └── views
│ │ ├── Datasource
│ │ └── DatasourceDialog.vue
│ │ ├── Error
│ │ └── 404.vue
│ │ ├── Generate
│ │ ├── MasterTable.vue
│ │ └── SingleTable.vue
│ │ ├── HeadBar
│ │ └── HeadBar.vue
│ │ ├── Home.vue
│ │ ├── Intro
│ │ └── Intro.vue
│ │ ├── Login.vue
│ │ ├── MainContent
│ │ └── MainContent.vue
│ │ └── NavBar
│ │ └── NavBar.vue
└── static
│ └── .gitkeep
└── thtf-generator
├── .gitignore
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── thtf
│ │ └── generator
│ │ ├── ThtfGeneratorApplication.java
│ │ ├── common
│ │ ├── constants
│ │ │ ├── CommonConstants.java
│ │ │ └── DBMSConstants.java
│ │ ├── exception
│ │ │ ├── CustomException.java
│ │ │ ├── DAOException.java
│ │ │ ├── QueryDAOException.java
│ │ │ └── handler
│ │ │ │ └── GlobalExceptionHandler.java
│ │ ├── response
│ │ │ ├── QueryResult.java
│ │ │ ├── Result.java
│ │ │ └── ResultCode.java
│ │ └── valid
│ │ │ ├── EnumValue.java
│ │ │ ├── EnumValueValidator.java
│ │ │ ├── IP.java
│ │ │ └── Phone.java
│ │ ├── config
│ │ ├── CorsConfig.java
│ │ ├── MyBeetlConfig.java
│ │ ├── MybatisConfig.java
│ │ ├── SwaggerConfig.java
│ │ └── WebMvcConfig.java
│ │ ├── controller
│ │ └── GenerateController.java
│ │ ├── converter
│ │ ├── CommonMetaDataConverter.java
│ │ ├── MySQL5MetaDataConverter.java
│ │ └── OracleMetaDataConverter.java
│ │ ├── dao
│ │ ├── DatabaseDAOFactory.java
│ │ ├── IDatabaseDAO.java
│ │ ├── IMetaDataConverter.java
│ │ ├── impl
│ │ │ ├── AbstractDatabasetDAOImpl.java
│ │ │ ├── CommonDatabaseDAOImpl.java
│ │ │ └── MySql5DatabaseDAO.java
│ │ └── sql
│ │ │ ├── DatabaseType.java
│ │ │ ├── MSSQL.xml
│ │ │ ├── MySQL5.xml
│ │ │ └── Oracle.xml
│ │ ├── model
│ │ ├── Column.java
│ │ ├── ForeignKey.java
│ │ ├── Index.java
│ │ ├── PrimaryKey.java
│ │ ├── Procedure.java
│ │ ├── Table.java
│ │ └── Trigger.java
│ │ ├── service
│ │ ├── DatabaseService.java
│ │ ├── GenerateService.java
│ │ └── impl
│ │ │ ├── DatabaseServiceImpl.java
│ │ │ └── GenerateServiceImpl.java
│ │ ├── utils
│ │ ├── DataTypeUtils.java
│ │ ├── Dom4jUtils.java
│ │ ├── IOUtils.java
│ │ ├── ReflectionUtils.java
│ │ ├── SnowflakeId.java
│ │ └── StringUtils.java
│ │ └── vo
│ │ ├── ColumnModel.java
│ │ ├── ConnParam.java
│ │ ├── GenerateModel.java
│ │ ├── RequestParam.java
│ │ └── TableModel.java
└── resources
│ ├── application.yml
│ ├── banner.txt
│ └── templates
│ ├── commonVO.btl
│ ├── controller.btl
│ ├── listVO.btl
│ ├── mapper.btl
│ ├── model.btl
│ ├── queryConditionVO.btl
│ ├── saveOrUpdateVO.btl
│ ├── service.btl
│ ├── serviceImpl.btl
│ ├── sqlMap.btl
│ └── view.btl
└── test
└── java
└── com
└── thtf
└── generator
└── ThtfGeneratorApplicationTests.java
/thtf-generator-ui/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/thtf-generator-ui/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/thtf-generator-ui/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/thtf-generator-ui/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/thtf-generator-ui/README.md:
--------------------------------------------------------------------------------
1 | # kitty-generator-ui
2 |
3 | > kitty generator ui project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/build/logo.png
--------------------------------------------------------------------------------
/thtf-generator-ui/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader',
51 | publicPath: '../../'
52 | })
53 | } else {
54 | return ['vue-style-loader'].concat(loaders)
55 | }
56 | }
57 |
58 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
59 | return {
60 | css: generateLoaders(),
61 | postcss: generateLoaders(),
62 | less: generateLoaders('less'),
63 | sass: generateLoaders('sass', { indentedSyntax: true }),
64 | scss: generateLoaders('sass'),
65 | stylus: generateLoaders('stylus'),
66 | styl: generateLoaders('stylus')
67 | }
68 | }
69 |
70 | // Generate loaders for standalone style files (outside of .vue)
71 | exports.styleLoaders = function (options) {
72 | const output = []
73 | const loaders = exports.cssLoaders(options)
74 |
75 | for (const extension in loaders) {
76 | const loader = loaders[extension]
77 | output.push({
78 | test: new RegExp('\\.' + extension + '$'),
79 | use: loader
80 | })
81 | }
82 |
83 | return output
84 | }
85 |
86 | exports.createNotifierCallback = () => {
87 | const notifier = require('node-notifier')
88 |
89 | return (severity, errors) => {
90 | if (severity !== 'error') return
91 |
92 | const error = errors[0]
93 | const filename = error.file && error.file.split('!').pop()
94 |
95 | notifier.notify({
96 | title: packageConfig.name,
97 | message: severity + ': ' + error.name,
98 | subtitle: filename || '',
99 | icon: path.join(__dirname, 'logo.png')
100 | })
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | },
68 | {
69 | test: /\.scss$/,
70 | loaders: ['style', 'css', 'sass']
71 | }
72 | ]
73 | },
74 | node: {
75 | // prevent webpack from injecting useless setImmediate polyfill because Vue
76 | // source contains it (although only uses it if it's native).
77 | setImmediate: false,
78 | // prevent webpack from injecting mocks to Node native modules
79 | // that does not make sense for the client
80 | dgram: 'empty',
81 | fs: 'empty',
82 | net: 'empty',
83 | tls: 'empty',
84 | child_process: 'empty'
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/thtf-generator-ui/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/thtf-generator-ui/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/thtf-generator-ui/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8888, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../dist/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../dist'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: './',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: true,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/thtf-generator-ui/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/thtf-generator-ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | kitty-generator-ui
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/thtf-generator-ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kitty-generator-ui",
3 | "version": "1.0.0",
4 | "description": "kitty generator ui project",
5 | "author": "Louis",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "axios": "^0.18.1",
14 | "element-ui": "^2.12.0",
15 | "font-awesome": "^4.7.0",
16 | "js-cookie": "^2.2.1",
17 | "vue": "^2.5.2",
18 | "vue-i18n": "^8.14.1",
19 | "vue-router": "^3.0.1",
20 | "vuex": "^3.1.1"
21 | },
22 | "devDependencies": {
23 | "autoprefixer": "^7.1.2",
24 | "babel-core": "^6.22.1",
25 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
26 | "babel-loader": "^7.1.1",
27 | "babel-plugin-syntax-jsx": "^6.18.0",
28 | "babel-plugin-transform-runtime": "^6.22.0",
29 | "babel-plugin-transform-vue-jsx": "^3.5.0",
30 | "babel-preset-env": "^1.3.2",
31 | "babel-preset-stage-2": "^6.22.0",
32 | "chalk": "^2.0.1",
33 | "copy-webpack-plugin": "^4.0.1",
34 | "css-loader": "^0.28.11",
35 | "extract-text-webpack-plugin": "^3.0.0",
36 | "file-loader": "^1.1.4",
37 | "friendly-errors-webpack-plugin": "^1.6.1",
38 | "html-webpack-plugin": "^2.30.1",
39 | "mockjs": "^1.0.1-beta3",
40 | "node-notifier": "^5.1.2",
41 | "node-sass": "^4.12.0",
42 | "optimize-css-assets-webpack-plugin": "^3.2.0",
43 | "ora": "^1.2.0",
44 | "portfinder": "^1.0.13",
45 | "postcss-import": "^11.0.0",
46 | "postcss-loader": "^2.0.8",
47 | "postcss-url": "^7.2.1",
48 | "rimraf": "^2.6.0",
49 | "sass-loader": "^7.3.1",
50 | "semver": "^5.3.0",
51 | "shelljs": "^0.7.6",
52 | "uglifyjs-webpack-plugin": "^1.1.1",
53 | "url-loader": "^0.5.8",
54 | "vue-loader": "^13.3.0",
55 | "vue-style-loader": "^3.0.1",
56 | "vue-template-compiler": "^2.5.2",
57 | "webpack": "^3.6.0",
58 | "webpack-bundle-analyzer": "^2.9.0",
59 | "webpack-dev-server": "^2.9.1",
60 | "webpack-merge": "^4.1.0"
61 | },
62 | "engines": {
63 | "node": ">= 6.0.0",
64 | "npm": ">= 3.0.0"
65 | },
66 | "browserslist": [
67 | "> 1%",
68 | "last 2 versions",
69 | "not ie <= 8"
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
27 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/assets/languages/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "common": {
3 | "home": "Home",
4 | "login": "Login",
5 | "logout": "Logout",
6 | "doc": "Document",
7 | "blog": "Blog",
8 | "projectRepo": "Project",
9 | "myMsg": "My Message",
10 | "config": "Config",
11 | "backup": "Backup",
12 | "restore": "Restore",
13 | "datasource": "Datasource",
14 | "versionName": "Version",
15 | "exit": "Exit"
16 | },
17 | "action": {
18 | "operation": "Operation",
19 | "add": "Add",
20 | "edit": "Edit",
21 | "delete": "Delete",
22 | "batchDelete": "Batch Delete",
23 | "search": "Search",
24 | "loading": "loading",
25 | "submit": "Submit",
26 | "save": "Save",
27 | "test": "test",
28 | "comfirm": "Comfirm",
29 | "cancel": "Cancel",
30 | "reset": "Reset"
31 | },
32 | "navMenu": {
33 | "singleTable": "single table",
34 | "masterTable": "master table",
35 | "userMng": "User Manage",
36 | "deptMng": "Dept Manage",
37 | "roleMng": "Role Manage",
38 | "menuMng": "Menu Manage",
39 | "logMng": "Log Manage",
40 | "sysMonitor": "System Monitor"
41 | }
42 | }
--------------------------------------------------------------------------------
/thtf-generator-ui/src/assets/languages/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "common": {
3 | "home": "首页",
4 | "login": "登录",
5 | "logout": "退出",
6 | "doc": "文档",
7 | "blog": "博客",
8 | "projectRepo": "项目",
9 | "myMsg": "我的消息",
10 | "config": "系统配置",
11 | "backup": "备份",
12 | "restore": "还原",
13 | "datasource": "数据源 ",
14 | "versionName": "版本名称",
15 | "exit": "退出"
16 | },
17 | "action": {
18 | "operation": "操作",
19 | "add": "新增",
20 | "edit": "编辑",
21 | "delete": "删除",
22 | "batchDelete": "批量删除",
23 | "search": "查询",
24 | "loading": "拼命加载中",
25 | "submit": "提交",
26 | "save": "保存",
27 | "test": "测试",
28 | "comfirm": "确定",
29 | "cancel": "取消",
30 | "reset": "重置"
31 |
32 | },
33 | "navMenu": {
34 | "singleTable": "单表查询",
35 | "masterTable": "主从表格",
36 | "userMng": "User Manage",
37 | "deptMng": "Dept Manage",
38 | "roleMng": "Role Manage",
39 | "menuMng": "Menu Manage",
40 | "logMng": "Log Manage",
41 | "sysMonitor": "System Monitor"
42 | }
43 | }
--------------------------------------------------------------------------------
/thtf-generator-ui/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/src/assets/logo.png
--------------------------------------------------------------------------------
/thtf-generator-ui/src/assets/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/src/assets/user.png
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/BreadCrumb/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ item.name }}
5 |
6 |
7 |
8 |
9 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/FaIconTooltip/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
推荐使用 Font Aweson 图标
6 |
使用步骤:
7 |
1.进入 Font Aweson 页面
8 |
2.查找到需要的图标,点击查看。
9 |
3.复制图片样式到此处。
10 |
示例:fa fa-home fa-lg
11 |
12 |
13 |
14 |
15 |
29 |
30 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/Hamburger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
28 |
29 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/LangSelector/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 中文
8 | English
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/MenuTree/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{menu.name}}
6 |
7 |
8 |
9 |
10 |
11 | {{menu.name}}
12 |
13 |
14 |
15 |
39 |
40 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/PopupTreeInput/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
58 |
59 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/SelectTableDiaog/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
64 |
65 |
68 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/components/ThemePicker/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
162 |
163 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/http/axios.js:
--------------------------------------------------------------------------------
1 | // 二次封装 axios 模块,包含拦截器等信息。
2 | import axios from 'axios'
3 | import config from './config'
4 | import qs from 'qs'
5 | import router from '@/router'
6 | import { getToken } from '../utils/auth'
7 |
8 |
9 | // 创建axios实例 axiso的一些基础参数配置,
10 | const instance = axios.create({
11 | baseURL: config.baseURL,
12 | headers: config.headers,
13 | // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
14 | // transformResponse: [function (data) {
15 | // // 对 data 进行任意转换处理
16 | //
17 | // }]
18 | })
19 |
20 | const tokenKey = config.tokenKey
21 | // request拦截器
22 | instance.interceptors.request.use(
23 | config => {
24 | // 打开loading
25 | // store.commit('CONTROL_LOADING', true)
26 | // if (store.getters.token) {
27 | // config.headers[tokenKey] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
28 | // }
29 |
30 | return config
31 | },
32 |
33 | // 请求错误时一般http状态码为两种以4开头,401:超时、404:not found 没找到接口
34 | error => {
35 | console.log('request error:' + error);
36 | // 在调用的那边可以拿到(catch)你想返回的错误信息
37 | return Promise.reject(error)
38 | }
39 | )
40 |
41 | // 响应拦截器
42 | instance.interceptors.response.use(
43 |
44 | // 如果返回的状态码为200,
45 | res => {
46 | // 请求成功是要做的处理
47 |
48 | // 对响应数据做些事情,把loading 动画关掉
49 | // store.commit('CONTROL_LOADING', false)
50 |
51 | // 对请求成功的值做统一判断
52 | // 1. 判空
53 | if (res.data === '' || res.data.length === 0 || res.data === 'undefined' || res.data === undefined) {
54 | console.log('后台传来的data为空/为undefined')
55 | }
56 |
57 | // 2.错误提示(前提是接口跑通了,只是对里边某些值做下详细判断。要先跟后台商定好,对某个固定的字段进行判断,并且确定固定字段来承接 错误信息,方便展示)
58 | if (res.data.code && res.data.code !== 200) {
59 | console.log(res.data)
60 | }
61 |
62 | return res.data;
63 | },
64 | // 请求错误时做些事(接口错误、超时等)
65 | error => {
66 |
67 | // 关闭loading
68 | // store.commit('CONTROL_LOADING',false)
69 | console.log(error) // 打开控制台,可以看到error包含了几个对象:message, config, code, request, response,可以拿来请求超时等问题
70 |
71 | // 1. 判断请求超时
72 | if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
73 | console.log('根据你设置的timeout/真的请求超时 判断请求现在超时了,你可以在这里加入超时的处理方案')
74 | // return service.request(originalRequest);//例如再重复请求一次
75 | }
76 |
77 | // 2. 需要重定向到错误页面
78 | if (error && error.response) {
79 | switch (error.response.status) {
80 | case 400: error.message = '请求错误(400)'; break;
81 | case 401: error.message = '未授权,请重新登录(401)'; break;
82 | case 403: error.message = '拒绝访问(403)'; break;
83 | case 404: router.push('/404'); break;
84 | case 408: error.message = '请求超时(408)'; break;
85 | case 500: error.message = '服务器错误(500)'; break;
86 | case 501: error.message = '服务未实现(501)'; break;
87 | case 502: error.message = '网络错误(502)'; break;
88 | case 503: error.message = '服务不可用(503)'; break;
89 | case 504: error.message = '网络超时(504)'; break;
90 | case 505: error.message = 'HTTP版本不受支持(505)'; break;
91 | default: error.message = `连接出错(${err.response.status})!`;
92 | }
93 | } else {
94 | error.message = '连接服务器失败!'
95 | }
96 |
97 | return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息
98 | }
99 | )
100 |
101 | export default instance
102 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/http/config.js:
--------------------------------------------------------------------------------
1 | // axios 默认配置,包含基础路径等信息。
2 |
3 | export default {
4 | method: 'get',
5 | // 基础url前缀
6 | baseURL: 'http://localhost:8899/thtf-generator/v1',
7 | // token
8 | tokenKey: 'Authorization',
9 | // token超时时间
10 | tokenCookieExpires: 2 * 60 * 1000,
11 | // 请求头信息
12 | headers: {
13 | 'Content-Type': 'application/json;charset=UTF-8'
14 | },
15 | // 参数
16 | data: {},
17 | // 设置超时时间,单位毫秒
18 | timeout: 10000,
19 | // 携带凭证: axios默认是请求的时候不会带上cookie的,需要通过设置 withCredentials:true来解决
20 | withCredentials: true,
21 | // 返回数据类型
22 | responseType: 'json'
23 | }
24 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/http/index.js:
--------------------------------------------------------------------------------
1 | // 将 axios 封装成插件,按插件方式引入
2 |
3 | import apis from './interface'
4 |
5 | const install = Vue => {
6 | if (install.installed) {
7 | return;
8 | }
9 |
10 | install.installed = true;
11 |
12 | Object.defineProperties(Vue.prototype, {
13 | // 注意,此处挂载在 Vue 原型的 $api 对象上
14 | $api: {
15 | get() {
16 | return apis;
17 | }
18 | }
19 | })
20 | }
21 |
22 | export default install
--------------------------------------------------------------------------------
/thtf-generator-ui/src/http/interface.js:
--------------------------------------------------------------------------------
1 | // 请求接口汇总模块,聚合模块 API。
2 | import axios from './axios'
3 |
4 | export const login = () => {
5 | return axios({
6 | url: '/login',
7 | method: 'get'
8 | })
9 | }
10 |
11 | export const getUser = () => {
12 | return axios({
13 | url:'/user',
14 | method: 'get'
15 | })
16 | }
17 |
18 | export const testConnection = (params) => {
19 | return axios({
20 | url:'/testConnection',
21 | method: 'post',
22 | data: params
23 | })
24 | }
25 |
26 | export const getGenerateModel = (params) => {
27 | return axios({
28 | url:'/getGenerateModel',
29 | method: 'post',
30 | data: params
31 | })
32 | }
33 |
34 | export const getTables = (params) => {
35 | return axios({
36 | url:'/getTables',
37 | method: 'post',
38 | data: params
39 | })
40 | }
41 |
42 | export const generateModels = (params) => {
43 | return axios({
44 | url:'/generateModels',
45 | method: 'post',
46 | data: params
47 | })
48 | }
49 |
50 |
51 | export default {
52 | login,
53 | getUser,
54 | testConnection,
55 | getGenerateModel,
56 | getTables,
57 | generateModels,
58 | }
59 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueI18n from 'vue-i18n'
3 |
4 | Vue.use(VueI18n)
5 |
6 | // 注册i18n实例并引入语言文件,文件格式等下解析
7 | const i18n = new VueI18n({
8 | locale: 'zh_cn',
9 | messages: {
10 | 'zh_cn': require('@/assets/languages/zh_cn.json'),
11 | 'en_us': require('@/assets/languages/en_us.json')
12 | }
13 | })
14 |
15 | export default i18n
--------------------------------------------------------------------------------
/thtf-generator-ui/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 | import router from './router'
4 | import store from './store'
5 | import i18n from './i18n'
6 | import ElementUI from 'element-ui'
7 | import 'element-ui/lib/theme-chalk/index.css'
8 | import 'font-awesome/css/font-awesome.min.css'
9 | import api from './http/index'
10 |
11 |
12 | Vue.use(ElementUI)
13 | Vue.use(api)
14 |
15 | Vue.config.productionTip = false
16 |
17 | new Vue({
18 | el: '#app',
19 | i18n,
20 | router,
21 | store,
22 | render: h => h(App)
23 | });
24 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/mock/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 |
3 | // Mock.mock('http://localhost:9000/getTables', {
4 | // "code": 200,
5 | // "msg": null,
6 | // "data": {
7 | // "connParam": {
8 | // "dbName": "kitty",
9 | // "dbType": "MYSQL",
10 | // "host": "localhost",
11 | // "password": "123456",
12 | // "port": 3306,
13 | // "userName": "root"
14 | // },
15 | // "tableModels": [
16 | // {
17 | // "name": "sys_menu",
18 | // "description": "菜单管理",
19 | // "tablespace": null,
20 | // "columns": []
21 | // },
22 | // {
23 | // "name": "sys_user",
24 | // "description": "用户",
25 | // "tablespace": null,
26 | // "columns": []
27 | // }
28 | // ]
29 | // }
30 | // })
--------------------------------------------------------------------------------
/thtf-generator-ui/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | export default new Router({
7 | routes: [
8 | ,{
9 | path: '/',
10 | name: '首页',
11 | component: () => import('@/views/Home'),
12 | },
13 | {
14 | path: '/',
15 | name: '首页',
16 | component: () => import('@/views/Home'),
17 | children: [
18 | {
19 | path: 'intro', name: '系统介绍', component: () => import('@/views/Intro/Intro')
20 | },
21 | {
22 | path: 'single',
23 | name: '单表查询',
24 | component: () => import('@/views/Generate/SingleTable'),
25 | },
26 | {
27 | path: 'master',
28 | name: '主从表格',
29 | component: () => import('@/views/Generate/MasterTable')
30 | }
31 | ]
32 | }
33 | ,{
34 | path: '/404',
35 | name: 'notFound',
36 | component: () => import('@/views/Error/404')
37 | },
38 | ,{
39 | path: '/login',
40 | name: 'login',
41 | component: () => import('@/views/Login')
42 | }
43 | ]
44 | })
45 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import vuex from 'vuex'
3 |
4 | Vue.use(vuex);
5 |
6 | import app from './modules/app'
7 |
8 | const store = new vuex.Store({
9 | modules: {
10 | app: app
11 | }
12 | })
13 |
14 | export default store
--------------------------------------------------------------------------------
/thtf-generator-ui/src/store/modules/app.js:
--------------------------------------------------------------------------------
1 | export default {
2 | state: {
3 | appName: "THTF Generator", // 应用名称
4 | themeColor: "#14889A", // 主题颜色
5 | oldThemeColor: "#14889A", // 上一次主题颜色
6 | collapse:false, // 导航栏收缩状态
7 | menuRouteLoaded:false // 菜单和路由是否已经加载
8 | },
9 | getters: {
10 | collapse(state){// 对应着上面state
11 | return state.collapse
12 | }
13 | },
14 | mutations: {
15 | onCollapse(state){ // 改变收缩状态
16 | state.collapse = !state.collapse
17 | },
18 | setThemeColor(state, themeColor){ // 改变主题颜色
19 | state.oldThemeColor = state.themeColor
20 | state.themeColor = themeColor
21 | },
22 | menuRouteLoaded(state, menuRouteLoaded){ // 改变菜单和路由的加载状态
23 | state.menuRouteLoaded = menuRouteLoaded;
24 | }
25 | },
26 | actions: {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/utils/auth.js:
--------------------------------------------------------------------------------
1 | import cookies from 'js-cookie'
2 | import config from '../http/config'
3 |
4 | const tokenKey = config.tokenKey
5 |
6 | export const getToken = () => {
7 | return cookies.get(tokenKey)
8 | }
9 |
10 | export const setToken = (token, rememberMe) => {
11 | if (rememberMe) {
12 | return cookies.set(TokenKey, token, { expires: config.tokenCookieExpires })
13 | } else {
14 | return cookies.set(TokenKey, token)
15 | }
16 | }
17 |
18 | export const removeToken = () => {
19 | return cookies.remove(TokenKey)
20 | }
21 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/utils/datetime.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 时间日期相关操作
3 | */
4 |
5 |
6 | /**
7 | * 时间格式化
8 | * 将 2018-09-23T11:54:16.000+0000 格式化成 2018/09/23 11:54:16
9 | * @param datetime 国际化日期格式
10 | */
11 | export function format (datetime) {
12 | return formatWithSeperator(datetime, "/", ":");
13 | }
14 |
15 | /**
16 | * 时间格式化
17 | * 将 2018-09-23T11:54:16.000+0000 格式化成类似 2018/09/23 11:54:16
18 | * 可以指定日期和时间分隔符
19 | * @param datetime 国际化日期格式
20 | */
21 | export function formatWithSeperator (datetime, dateSeprator, timeSeprator) {
22 | if (datetime != null) {
23 | const dateMat = new Date(datetime);
24 | const year = dateMat.getFullYear();
25 | const month = dateMat.getMonth() + 1;
26 | const day = dateMat.getDate();
27 | const hh = dateMat.getHours();
28 | const mm = dateMat.getMinutes();
29 | const ss = dateMat.getSeconds();
30 | const timeFormat = year + dateSeprator + month + dateSeprator + day + " " + hh + timeSeprator + mm + timeSeprator + ss;
31 | return timeFormat;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/utils/iframe.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 嵌套页面IFrame模块
3 | */
4 |
5 | import config from '@/http/config'
6 |
7 | /**
8 | * 嵌套页面URL地址
9 | * @param {*} url
10 | */
11 | export function getIFramePath (url) {
12 | let iframeUrl = ''
13 | if(/^iframe:.*/.test(url)) {
14 | iframeUrl = url.replace('iframe:', '')
15 | } else if(/^http[s]?:\/\/.*/.test(url)) {
16 | iframeUrl = url.replace('http://', '')
17 | if(iframeUrl.indexOf(":") != -1) {
18 | iframeUrl = iframeUrl.substring(iframeUrl.lastIndexOf(":") + 1)
19 | }
20 | }
21 | return iframeUrl
22 | }
23 |
24 | /**
25 | * 嵌套页面路由路径
26 | * @param {*} url
27 | */
28 | export function getIFrameUrl (url) {
29 | let iframeUrl = ''
30 | if(/^iframe:.*/.test(url)) {
31 | iframeUrl = config.baseUrl + url.replace('iframe:', '')
32 | } else if(/^http[s]?:\/\/.*/.test(url)) {
33 | iframeUrl = url
34 | }
35 | return iframeUrl
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/utils/validate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 邮箱
3 | * @param {*} s
4 | */
5 | export function isEmail (s) {
6 | return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
7 | }
8 |
9 | /**
10 | * 手机号码
11 | * @param {*} s
12 | */
13 | export function isMobile (s) {
14 | return /^1[0-9]{10}$/.test(s)
15 | }
16 |
17 | /**
18 | * 电话号码
19 | * @param {*} s
20 | */
21 | export function isPhone (s) {
22 | return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
23 | }
24 |
25 | /**
26 | * URL地址
27 | * @param {*} s
28 | */
29 | export function isURL (s) {
30 | return /^http[s]?:\/\/.*/.test(s)
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Datasource/DatasourceDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
104 |
105 |
108 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Error/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
404
6 |
抱歉!您访问的页面失联啦 ...
7 |
返回上一页
8 |
进入首页
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
63 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Generate/MasterTable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{$t("navMenu.masterTable")}}
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/HeadBar/HeadBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
{{username}}
27 |
28 | {{$t("common.myMsg")}}
29 | {{$t("common.config")}}
30 | {{$t("common.logout")}}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
103 |
104 |
162 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
35 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Intro/Intro.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
18 |
19 |
50 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 系统登录
5 |
6 |
7 |
8 |
9 |
10 |
11 | 记住密码
12 |
13 | 重 置
14 | 登 录
15 |
16 |
17 |
18 |
19 |
20 |
57 |
58 |
89 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/MainContent/MainContent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
45 |
--------------------------------------------------------------------------------
/thtf-generator-ui/src/views/NavBar/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
51 |
52 |
91 |
--------------------------------------------------------------------------------
/thtf-generator-ui/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/static/.gitkeep
--------------------------------------------------------------------------------
/thtf-generator/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/thtf-generator/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.1.8.RELEASE
9 |
10 |
11 | com.thtf.generator
12 | springboot-code-generator
13 | 0.0.1-SNAPSHOT
14 | springboot-code-generator
15 | 代码自动生成
16 |
17 |
18 | UTF-8
19 | UTF-8
20 | 1.8
21 | 1.2.5
22 | 2.8.0
23 | 11.1.0.6.0
24 | 2.0.2
25 | 1.3.2
26 | 1.2.58
27 | 1.1.68.RELEASE
28 |
29 |
30 |
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-web
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 |
44 | mysql
45 | mysql-connector-java
46 |
47 |
48 |
49 | com.oracle.jdbc
50 | ojdbc6
51 | ${oracle.version}
52 |
53 |
54 |
55 | dom4j
56 | dom4j
57 |
58 |
59 |
60 | org.projectlombok
61 | lombok
62 | true
63 |
64 |
65 |
66 | com.github.pagehelper
67 | pagehelper-spring-boot-starter
68 | ${pagehelper.spring.version}
69 |
70 |
71 |
72 | io.springfox
73 | springfox-swagger2
74 | ${swagger.version}
75 |
76 |
77 | io.springfox
78 | springfox-swagger-ui
79 | ${swagger.version}
80 |
81 |
82 |
83 | tk.mybatis
84 | mapper-spring-boot-starter
85 | ${tk.mybatis.version}
86 |
87 |
88 |
89 | org.mybatis.spring.boot
90 | mybatis-spring-boot-starter
91 | ${mybatis.spring.version}
92 |
93 |
94 |
95 | com.alibaba
96 | fastjson
97 | ${fastjson.version}
98 |
99 |
100 |
101 | com.ibeetl
102 | beetl-framework-starter
103 | ${beetl.version}
104 |
105 |
106 |
107 | org.apache.commons
108 | commons-lang3
109 |
110 |
111 |
112 | dom4j
113 | dom4j
114 |
115 |
116 |
117 |
118 |
119 |
120 | src/main/java
121 |
122 | **/sql*/*.xml
123 |
124 | false
125 |
126 |
127 | src/main/resources
128 |
129 | **/*
130 |
131 | false
132 |
133 |
134 |
135 |
136 | org.springframework.boot
137 | spring-boot-maven-plugin
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/ThtfGeneratorApplication.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ThtfGeneratorApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ThtfGeneratorApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/constants/CommonConstants.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.constants;
2 |
3 | /**
4 | * ========================
5 | * 公共常量
6 | * Author:pyy
7 | * Date:2019-9-25 16:04:13
8 | * Version: v1.0
9 | * ========================
10 | */
11 | public interface CommonConstants {
12 |
13 | // 编码
14 | String ENCODING_UTF8 = "utf-8";
15 | String ENCODING_GBK = "gbk";
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/constants/DBMSConstants.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.constants;
2 |
3 |
4 | /**
5 | * ========================
6 | * DBMS常量
7 | * Author:pyy
8 | * Date:2019-9-25 16:04:13
9 | * Version: v1.0
10 | * ========================
11 | */
12 | public interface DBMSConstants {
13 |
14 | /** DB TYPE, ORACLE */
15 | public static final String ORACLE = "ORACLE";
16 | /** DB TYPE, MySQL */
17 | public static final String MYSQL = "MYSQL";
18 | /** DB TYPE, DB2 */
19 | public static final String DB2 = "DB2";
20 | /** DB TYPE, SQL SERVER */
21 | public static final String SQL_SERVER = "SQL SERVER";
22 | /** DB TYPE, SQL SERVER */
23 | public static final String SQLSERVER = "SQLSERVER";
24 | /** DB TYPE, SYBASE */
25 | public static final String SYBASE = "SYBASE";
26 | /** DB TYPE, PostgreSQL */
27 | public static final String POSTGRE_SQL = "POSTGRE_SQL";
28 | /** DB TYPE, HSQLDB */
29 | public static final String HSQLDB = "HSQLDB";
30 | /** DB TYPE, Firebird */
31 | public static final String FIREBIRD = "FIREBIRD";
32 | /** DB TYPE, Derby */
33 | public static final String DERBY = "DERBY";
34 |
35 | /** DBMS Configurations */
36 | public static final String ELEMENT_DMBS_CONFIGURATIONS = "dbmsConfigurations";
37 | /** DBMS dbms */
38 | public static final String ELEMENT_DBMS = "dbms";
39 | /** DBMS key */
40 | public static final String ATTRIBUTE_KEY = "key";
41 | /** DBMS value */
42 | public static final String ATTRIBUTE_VALUE = "value";
43 | /** DBMS host */
44 | public static final String ATTRIBUTE_HOST = "host";
45 | /** DBMS port */
46 | public static final String ATTRIBUTE_PORT = "port";
47 | /** database */
48 | public static final String ATTRIBUTE_DB = "database";
49 | /** DBMS userName */
50 | public static final String ATTRIBUTE_USER = "userName";
51 | /** DBMS password */
52 | public static final String ATTRIBUTE_PASSWORD = "password";
53 | /** DBMS desc */
54 | public static final String ATTRIBUTE_DESE = "desc";
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/exception/CustomException.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.exception;
2 |
3 |
4 |
5 | import com.thtf.generator.common.response.ResultCode;
6 | import lombok.Getter;
7 | import lombok.Setter;
8 |
9 | import java.text.MessageFormat;
10 |
11 | /**
12 | * 自定义异常类型
13 | * @author pyy
14 | */
15 | @Setter
16 | @Getter
17 | public class CustomException extends RuntimeException {
18 |
19 | //错误代码
20 | private ResultCode resultCode;
21 |
22 | private int code;
23 |
24 | private String message;
25 |
26 | public CustomException(ResultCode resultCode){
27 | super(resultCode.message());
28 | this.resultCode = resultCode;
29 | }
30 |
31 | public CustomException(ResultCode resultCode, Object... args){
32 | code = resultCode.code();
33 | message = MessageFormat.format(resultCode.message(), args);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/exception/DAOException.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.exception;
2 |
3 | /**
4 | * DAO操作异常
5 | * @author pyy
6 | */
7 | public class DAOException extends Exception {
8 |
9 | private static final long serialVersionUID = -1041464715086167865L;
10 |
11 | public static final int OPEN_CONNECTION_EXCEPTION = 1;
12 | public static final int CLOSE_CONNECTION_EXCEPTION = 2;
13 | public static final int CLOSE_JDBC_EXCEPTION = 3;
14 | public static final int QUERY_EXCEPTION = 8;
15 | public static final int QUERY_TABLE_EXCEPTION = 9;
16 | public static final int QUERY_COLUMN_EXCEPTION = 10;
17 | public static final int QUERY_PRIMARY_KEY_EXCEPTION = 11;
18 | public static final int QUERY_FOREIGN_KEY_EXCEPTION = 12;
19 | public static final int QUERY_INDEX_EXCEPTION = 13;
20 | public static final int QUERY_TRIGGER_EXCEPTION = 14;
21 |
22 | private final int type;
23 |
24 | public DAOException(int type, String message, Throwable cause) {
25 | super(message, cause);
26 | this.type = type;
27 | }
28 |
29 | /**
30 | * @return the type
31 | */
32 | public int getType() {
33 | return type;
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | String errorMsg = null;
39 | switch (type) {
40 | case OPEN_CONNECTION_EXCEPTION:
41 | errorMsg = "创建数据库连接失败:";
42 | break;
43 | case CLOSE_CONNECTION_EXCEPTION:
44 | errorMsg = "关闭数据库连接失败:";
45 | break;
46 | case CLOSE_JDBC_EXCEPTION:
47 | errorMsg = "关闭jdbc资源出错:";
48 | break;
49 | default:
50 | errorMsg = "查询出错:";
51 | }
52 | return errorMsg + getMessage();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/exception/QueryDAOException.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.exception;
2 |
3 | /**
4 | * DAO查询操作异常
5 | * @author pyy
6 | */
7 | public class QueryDAOException extends DAOException {
8 |
9 | /**
10 | *
11 | */
12 | private static final long serialVersionUID = 970988278493482388L;
13 |
14 | private final String tableName;
15 |
16 | /**
17 | * @param type
18 | * @param message
19 | * @param cause
20 | */
21 | public QueryDAOException(String tableName, int type, String message,
22 | Throwable cause) {
23 | super(type, message, cause);
24 | this.tableName = tableName;
25 | }
26 |
27 | /**
28 | * @return the tableName
29 | */
30 | public String getTableName() {
31 | return tableName;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | String typeStr = getTypeString();
37 | if (typeStr != null) {
38 | return String.format("表【%s】查询%s信息出错,出错原因是:%s。", tableName, typeStr, getMessage());
39 | }
40 |
41 | return super.toString();
42 | }
43 |
44 | private String getTypeString() {
45 | switch (getType()) {
46 | case QUERY_COLUMN_EXCEPTION:
47 | return "字段";
48 | case QUERY_PRIMARY_KEY_EXCEPTION:
49 | return "主键";
50 | case QUERY_FOREIGN_KEY_EXCEPTION:
51 | return "外键";
52 | case QUERY_INDEX_EXCEPTION:
53 | return "索引";
54 | case QUERY_TRIGGER_EXCEPTION:
55 | return "触发器";
56 | default:
57 | return null;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/exception/handler/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.exception.handler;
2 |
3 | import com.thtf.generator.common.exception.CustomException;
4 | import com.thtf.generator.common.response.Result;
5 | import com.thtf.generator.common.response.ResultCode;
6 | import org.apache.commons.lang3.StringUtils;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.validation.BindException;
10 | import org.springframework.validation.BindingResult;
11 | import org.springframework.validation.FieldError;
12 | import org.springframework.validation.ObjectError;
13 | import org.springframework.web.bind.MethodArgumentNotValidException;
14 | import org.springframework.web.bind.annotation.ExceptionHandler;
15 | import org.springframework.web.bind.annotation.RestControllerAdvice;
16 |
17 | import java.util.List;
18 |
19 | /**
20 | * 全局异常处理器
21 | * @author pyy
22 | */
23 | @RestControllerAdvice
24 | public class GlobalExceptionHandler {
25 |
26 | private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
27 |
28 | /**
29 | * 处理自定义异常
30 | */
31 | @ExceptionHandler(CustomException.class)
32 | public Result handleException(CustomException e) {
33 |
34 | if (e.getResultCode() != null) {
35 | log.error("### 异常信息:code={}, msg={} ###", e.getResultCode().code(), e.getResultCode().message());
36 | return new Result(e.getResultCode());
37 | } else {
38 | log.error("### 异常信息:code={}, msg={} ###", e.getCode(), e.getMessage());
39 | return new Result(e.getCode(), e.getMessage());
40 | }
41 | }
42 |
43 | /**
44 | * 参数错误异常
45 | */
46 | @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
47 | public Result handleException(Exception e) {
48 | StringBuffer errorMsg = new StringBuffer();
49 | if (e instanceof MethodArgumentNotValidException) {
50 | MethodArgumentNotValidException validException = (MethodArgumentNotValidException) e;
51 | BindingResult result = validException.getBindingResult();
52 | if (result.hasErrors()) {
53 | List errors = result.getAllErrors();
54 | errors.forEach(p ->{
55 | FieldError fieldError = (FieldError) p;
56 | errorMsg.append(fieldError.getDefaultMessage()).append(",");
57 | log.error("### 请求参数错误:{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+ "},errorMessage{"+fieldError.getDefaultMessage()+"} ###"); });
58 | }
59 | } else if (e instanceof BindException) {
60 | BindException bindException = (BindException)e;
61 | if (bindException.hasErrors()) {
62 | log.error("### 请求参数错误: {} ###", bindException.getAllErrors());
63 | }
64 | }
65 |
66 | return new Result(ResultCode.PARAM_IS_INVALID.code(), StringUtils.removeEnd(errorMsg.toString(), ","));
67 | }
68 |
69 | /**
70 | * 处理所有不可知的异常
71 | */
72 | @ExceptionHandler(Exception.class)
73 | public Result handleOtherException(Exception e){
74 | //打印异常堆栈信息
75 | e.printStackTrace();
76 | // 打印异常信息
77 | log.error("### 不可知的异常 e=:{} ###", e.getMessage());
78 | return new Result(ResultCode.SYSTEM_INNER_ERROR);
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/response/QueryResult.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.response;
2 |
3 | import io.swagger.annotations.ApiModel;
4 | import io.swagger.annotations.ApiModelProperty;
5 | import lombok.Data;
6 | import lombok.Getter;
7 | import lombok.Setter;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * ========================
13 | * 查询结果
14 | * Author:pyy
15 | * Date:2019/6/6
16 | * Time:10:10
17 | * Version: v1.0
18 | * ========================
19 | */
20 | @Data
21 | @ApiModel(value = "QueryResult",description = "分页结果")
22 | public class QueryResult {
23 |
24 | @ApiModelProperty("数据列表")
25 | private List list;
26 |
27 | @ApiModelProperty("数据总数")
28 | private long total;
29 |
30 | public QueryResult(List list, long total) {
31 | this.list = list;
32 | this.total = total;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/response/Result.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.response;
2 |
3 | import com.fasterxml.jackson.databind.annotation.JsonSerialize;
4 | import lombok.Data;
5 |
6 | /**
7 | * ========================
8 | * 统一响应结果集
9 | * Author:pyy
10 | * Date:2019/6/6
11 | * Time:10:10
12 | * Version: v1.0
13 | * ========================
14 | */
15 | @Data
16 | @JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
17 | public class Result {
18 |
19 | //操作代码
20 | int code;
21 |
22 | //提示信息
23 | String msg;
24 |
25 | //结果数据
26 | T data;
27 |
28 | public Result(ResultCode resultCode){
29 | this.code = resultCode.code();
30 | this.msg = resultCode.message();
31 | }
32 |
33 | public Result(int code, String msg){
34 | this.code = code;
35 | this.msg = msg;
36 | }
37 |
38 | public Result(ResultCode resultCode, T data){
39 | this.code = resultCode.code();
40 | this.msg = resultCode.message();
41 | this.data = data;
42 | }
43 |
44 | public static Result SUCCESS(){
45 | return new Result(ResultCode.SUCCESS);
46 | }
47 |
48 | public static Result SUCCESS(T data){
49 | return new Result(ResultCode.SUCCESS, data);
50 | }
51 |
52 | public static Result FAIL(){
53 | return new Result(ResultCode.FAIL);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/response/ResultCode.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.response;
2 |
3 |
4 | /**
5 | * ========================
6 | * 通用响应状态
7 | * Author:pyy
8 | * Date:2019/6/6
9 | * Time:10:10
10 | * Version: v1.0
11 | * ========================
12 | */
13 | public enum ResultCode {
14 |
15 | /* 成功状态码 */
16 | SUCCESS(200,"SUCCESS"),
17 |
18 | /* 错误状态码 */
19 | FAIL(500,"ERROR"),
20 |
21 | /* 参数错误:10001-19999 */
22 | PARAM_IS_INVALID(10001, "参数无效"),
23 | CONNECTION_ERROR(10002, "连接失败,请检查数据库及连接"),
24 |
25 | /* 用户错误:20001-29999*/
26 | USER_NOT_LOGGED_IN(20001, "用户未登录"),
27 | USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
28 | USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
29 | USER_NOT_EXIST(20004, "用户不存在"),
30 | USER_HAS_EXISTED(20005, "用户已存在"),
31 |
32 | /* 业务错误:30001-39999 */
33 | //BUSINESS_GROUP_NO_ALLOWED_DEL(30001, "应用分组已经被 {0} 个应用【{1}{2}】使用,不能删除"),
34 | NAME_EXISTED(30001, "{0}名称已存在"),
35 | CODE_EXISTED(30002, "{0}编码已存在"),
36 | BUSINESS_OUTER_DATASOURCE_NO_ALLOWED_DEL(30002, "数据源已经被 {0} 个资源【{1}{2}】使用,不能删除"),
37 | RESOURCE_CATEGORY_EXIST_DEPEND(30003, "当前分类下存在 {0} 个子分类【{1}{2}】,不能删除"),
38 |
39 |
40 | /* 系统错误:40001-49999 */
41 | SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
42 | UPLOAD_ERROR(40002, "系统异常,上传文件失败"),
43 |
44 | /* 数据错误:50001-599999 */
45 | RESULT_DATA_NONE(50001, "数据未找到"),
46 | DATA_IS_WRONG(50002, "数据有误"),
47 | DATA_ALREADY_EXISTED(50003, "数据已存在"),
48 |
49 | /* 接口错误:60001-69999 */
50 | INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),
51 | INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
52 | INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
53 | INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
54 | INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
55 | INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),
56 |
57 |
58 | /* 权限错误 */
59 | PERMISSION_UNAUTHENTICATED(70001,"此操作需要登陆系统!"),
60 | PERMISSION_UNAUTHORISE(70002,"权限不足,无权操作!"),
61 | PERMISSION_EXPIRE(401,"登录状态过期!"),
62 | PERMISSION_LIMIT(70004, "访问次数受限制");
63 |
64 | //操作代码
65 | int code;
66 | //提示信息
67 | String message;
68 | ResultCode(int code, String message){
69 | this.code = code;
70 | this.message = message;
71 | }
72 |
73 | public int code() {
74 | return code;
75 | }
76 |
77 | public String message() {
78 | return message;
79 | }
80 |
81 | public void setCode(int code) {
82 | this.code = code;
83 | }
84 |
85 | public void setMessage(String message) {
86 | this.message = message;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/valid/EnumValue.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.valid;
2 |
3 | import javax.validation.Constraint;
4 | import javax.validation.Payload;
5 | import java.lang.annotation.Documented;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | import static java.lang.annotation.ElementType.*;
10 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
11 |
12 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
13 | @Retention(RUNTIME)
14 | @Documented
15 | @Constraint(validatedBy = {EnumValueValidator.class})
16 | public @interface EnumValue {
17 |
18 | // 默认错误消息
19 | String message() default "必须为指定值";
20 |
21 | String[] strValues() default {};
22 |
23 | int[] intValues() default {};
24 |
25 | //分组
26 | Class>[] groups() default {};
27 |
28 | //负载
29 | Class extends Payload>[] payload() default {};
30 |
31 | //指定多个时使用
32 | @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
33 | @Retention(RUNTIME)
34 | @Documented
35 | @interface List {
36 | EnumValue[] value();
37 | }
38 | }
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/valid/EnumValueValidator.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.valid;
2 |
3 | import javax.validation.ConstraintValidator;
4 | import javax.validation.ConstraintValidatorContext;
5 |
6 | /**
7 | * ========================
8 | * 自定义验证
9 | * Author:pyy
10 | * Date:2019/9/24 17:34
11 | * Version: v1.0
12 | * ========================
13 | */
14 | public class EnumValueValidator implements ConstraintValidator< EnumValue, Object> {
15 | private String[] strValues;
16 | private int[] intValues;
17 |
18 | @Override
19 | public void initialize(EnumValue constraintAnnotation) {
20 | strValues = constraintAnnotation.strValues();
21 | intValues = constraintAnnotation.intValues();
22 | }
23 |
24 | @Override
25 | public boolean isValid(Object value, ConstraintValidatorContext context ) {
26 | if(value instanceof String) {
27 | for (String s:strValues) {
28 | if(s.equals(value)){
29 | return true;
30 | }
31 | }
32 | }else if(value instanceof Integer){
33 | for (Integer s:intValues) {
34 | if(s==value){
35 | return true;
36 | }
37 | }
38 | }
39 | return false;
40 |
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/valid/IP.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.valid;
2 |
3 | import org.hibernate.validator.constraints.CompositionType;
4 | import org.hibernate.validator.constraints.ConstraintComposition;
5 |
6 | import javax.validation.Constraint;
7 | import javax.validation.Payload;
8 | import javax.validation.ReportAsSingleViolation;
9 | import javax.validation.constraints.Null;
10 | import javax.validation.constraints.Pattern;
11 | import java.lang.annotation.Documented;
12 | import java.lang.annotation.Retention;
13 | import java.lang.annotation.Target;
14 |
15 | import static java.lang.annotation.ElementType.*;
16 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
17 |
18 |
19 | /**
20 | * 验证IP
21 | */
22 | @ConstraintComposition(CompositionType.OR)
23 | @Pattern(regexp = "^(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).)(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).){2}([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))$")
24 | @Null
25 | @Documented
26 | @Constraint(validatedBy = {})
27 | @Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
28 | @Retention(RUNTIME)
29 | @ReportAsSingleViolation
30 | public @interface IP {
31 | String message() default "IP地址格式错误";
32 |
33 | Class>[] groups() default {};
34 |
35 | Class extends Payload>[] payload() default {};
36 | }
37 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/common/valid/Phone.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.common.valid;
2 |
3 | import org.hibernate.validator.constraints.CompositionType;
4 | import org.hibernate.validator.constraints.ConstraintComposition;
5 | import org.hibernate.validator.constraints.Length;
6 |
7 | import javax.validation.Constraint;
8 | import javax.validation.Payload;
9 | import javax.validation.ReportAsSingleViolation;
10 | import javax.validation.constraints.Null;
11 | import javax.validation.constraints.Pattern;
12 | import java.lang.annotation.Documented;
13 | import java.lang.annotation.Retention;
14 | import java.lang.annotation.Target;
15 |
16 | import static java.lang.annotation.ElementType.*;
17 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
18 |
19 | /**
20 | * 验证手机号,空和正确的手机号都能验证通过
21 | * 正确的手机号由11位数字组成,第一位为1
22 | * 第二位为 3、4、5、7、8
23 | *
24 | */
25 | @ConstraintComposition(CompositionType.OR)
26 | @Pattern(regexp = "1[3|4|5|7|8][0-9]\\d{8}")
27 | @Null
28 | @Length(max = 11)
29 | @Documented
30 | @Constraint(validatedBy = {})
31 | @Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
32 | @Retention(RUNTIME)
33 | @ReportAsSingleViolation
34 | public @interface Phone {
35 | String message() default "手机号校验错误";
36 |
37 | Class>[] groups() default {};
38 |
39 | Class extends Payload>[] payload() default {};
40 | }
41 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/config/CorsConfig.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
6 |
7 | /**
8 | * ========================
9 | * 跨域配置
10 | * Author:pyy
11 | * Date:2019-9-25 16:45:06
12 | * Version: v1.0
13 | * ========================
14 | */
15 | @Configuration
16 | public class CorsConfig implements WebMvcConfigurer {
17 |
18 | @Override
19 | public void addCorsMappings(CorsRegistry registry) {
20 | registry.addMapping("/**") // 允许跨域访问的路径
21 | .allowedOrigins("*") // 允许跨域访问的源
22 | .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许请求方法
23 | .maxAge(168000) // 预检间隔时间
24 | .allowedHeaders("*") // 允许头部设置
25 | .allowCredentials(true); // 是否发送cookie
26 | }
27 | }
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/config/MyBeetlConfig.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.config;
2 |
3 | import com.ibeetl.starter.BeetlTemplateCustomize;
4 | import org.beetl.core.GroupTemplate;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * ========================
10 | * MyBeetl配置
11 | * Author:pyy
12 | * Date:2019-9-25 16:45:06
13 | * Version: v1.0
14 | * ========================
15 | */
16 | @Configuration
17 | public class MyBeetlConfig {
18 |
19 | @Bean
20 | public BeetlTemplateCustomize beetlTemplateCustomize(){
21 | return new BeetlTemplateCustomize(){
22 | public void customize(GroupTemplate groupTemplate){
23 |
24 | }
25 | };
26 | }
27 | }
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/config/MybatisConfig.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.config;
2 |
3 | import org.apache.ibatis.session.SqlSessionFactory;
4 | import org.mybatis.spring.SqlSessionFactoryBean;
5 | import org.mybatis.spring.annotation.MapperScan;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
10 |
11 | import javax.sql.DataSource;
12 |
13 | /**
14 | * ========================
15 | * Mybatis配置
16 | * Author:pyy
17 | * Date:2019-9-25 16:45:06
18 | * Version: v1.0
19 | * ========================
20 | */
21 | @Configuration
22 | @MapperScan("com.thtf.generator.**.dao")// 扫描DAO
23 | public class MybatisConfig {
24 | @Autowired
25 | private DataSource dataSource;
26 |
27 | @Bean
28 | public SqlSessionFactory sqlSessionFactory() throws Exception {
29 | SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
30 | sessionFactory.setDataSource(dataSource);
31 | sessionFactory.setTypeAliasesPackage("com.thtf.generator.**.model"); // 扫描Model
32 |
33 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
34 | sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/mappers/*.xml")); // 扫描映射文件
35 |
36 | return sessionFactory.getObject();
37 | }
38 | }
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import springfox.documentation.builders.ApiInfoBuilder;
6 | import springfox.documentation.builders.PathSelectors;
7 | import springfox.documentation.builders.RequestHandlerSelectors;
8 | import springfox.documentation.service.ApiInfo;
9 | import springfox.documentation.spi.DocumentationType;
10 | import springfox.documentation.spring.web.plugins.Docket;
11 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
12 |
13 | /**
14 | * ========================
15 | * Swagger配置
16 | * Author:pyy
17 | * Date:2019-9-25 16:45:06
18 | * Version: v1.0
19 | * ========================
20 | */
21 | @Configuration
22 | @EnableSwagger2
23 | public class SwaggerConfig {
24 |
25 | @Bean
26 | public Docket createRestApi() {
27 | return new Docket(DocumentationType.SWAGGER_2)
28 | .apiInfo(apiInfo())
29 | .select()
30 | .apis(RequestHandlerSelectors.basePackage("com.thtf.generator"))
31 | .paths(PathSelectors.any())
32 | .build();
33 | }
34 |
35 | private ApiInfo apiInfo() {
36 | return new ApiInfoBuilder()
37 | .title("代码自动生成项目api文档")
38 | .description("代码自动生成项目api文档")
39 | .version("1.0")
40 | .build();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/config/WebMvcConfig.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.config;
2 |
3 | import org.apache.ibatis.type.JdbcType;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.web.context.request.RequestContextListener;
7 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
9 | import tk.mybatis.mapper.autoconfigure.ConfigurationCustomizer;
10 |
11 | @Configuration
12 | public class WebMvcConfig implements WebMvcConfigurer {
13 |
14 | @Override
15 | public void addResourceHandlers(ResourceHandlerRegistry registry) {
16 | registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/");
17 | registry.addResourceHandler("swagger-ui.html")
18 | .addResourceLocations("classpath:/META-INF/resources/");
19 | registry.addResourceHandler("/webjars/**")
20 | .addResourceLocations("classpath:/META-INF/resources/webjars/");
21 | }
22 |
23 | /**
24 | * 解决Mybatis通用Mapper updateByPrimarykey()和insert()方法报错,提示jdbctype错误
25 | */
26 | @Bean
27 | public ConfigurationCustomizer configurationCustomizer(){
28 | return new MybatisPlusCustomizers();
29 | }
30 |
31 | class MybatisPlusCustomizers implements ConfigurationCustomizer {
32 |
33 | @Override
34 | public void customize(org.apache.ibatis.session.Configuration configuration) {
35 | configuration.setJdbcTypeForNull(JdbcType.NULL);
36 | }
37 | }
38 |
39 | @Bean
40 | public RequestContextListener requestContextListener(){
41 | return new RequestContextListener();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/controller/GenerateController.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.controller;
2 |
3 | import com.thtf.generator.common.response.Result;
4 | import com.thtf.generator.common.response.ResultCode;
5 | import com.thtf.generator.service.GenerateService;
6 | import com.thtf.generator.vo.ConnParam;
7 | import com.thtf.generator.vo.GenerateModel;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.web.bind.annotation.PostMapping;
10 | import org.springframework.web.bind.annotation.RequestBody;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 |
15 | /**
16 | * ========================
17 | * 代码生成控制器
18 | * Author:pyy
19 | * Date:2019-9-25 17:07:15
20 | * Version: v1.0
21 | * ========================
22 | */
23 | @RestController
24 | @RequestMapping("/v1")
25 | public class GenerateController {
26 |
27 | @Autowired
28 | private GenerateService generatorService;
29 |
30 | @PostMapping("/testConnection")
31 | public Result testConnection(@RequestBody ConnParam connParam) {
32 | boolean success = generatorService.testConnection(connParam);
33 | if(success) {
34 | return Result.SUCCESS();
35 | }
36 | return new Result(ResultCode.CONNECTION_ERROR);
37 | }
38 |
39 | @PostMapping("/getTables")
40 | public Result getTables(@RequestBody ConnParam connParam) {
41 | return Result.SUCCESS(generatorService.getTables(connParam));
42 | }
43 |
44 | @PostMapping("/getGenerateModel")
45 | public Result getGenerateModel(@RequestBody GenerateModel generateModel) {
46 | return Result.SUCCESS(generatorService.getGenerateModel(generateModel));
47 | }
48 |
49 | @PostMapping("/generateModels")
50 | public Result generateModels(@RequestBody GenerateModel generateModel) throws Exception {
51 | return Result.SUCCESS(generatorService.generateModels(generateModel));
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/converter/CommonMetaDataConverter.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.converter;
2 |
3 | import com.thtf.generator.dao.IMetaDataConverter;
4 | import com.thtf.generator.model.*;
5 |
6 | import java.util.Map;
7 |
8 | /**
9 | * ========================
10 | * 通用元数据转换器
11 | * Author:pyy
12 | * Date:2019-9-25 16:07:53
13 | * Version: v1.0
14 | * ========================
15 | */
16 | public class CommonMetaDataConverter implements IMetaDataConverter {
17 |
18 | // 查询返回的字段名是全大写,所以在用map获取值时,需要用大写字段名
19 | private static final IMetaDataConverter instance = new CommonMetaDataConverter();
20 |
21 | public static IMetaDataConverter getInstance() {
22 | return instance;
23 | }
24 |
25 | @Override
26 | public Table convertMap2Table(Map map) {
27 | Table table = new Table();
28 | table.setName(getValue(map, "TABLE_NAME"));
29 | table.setTablespace(getValue(map, "TABLESPACE"));
30 | table.setDescription(getValue(map, "DESCRIPTION"));
31 | return table;
32 | }
33 |
34 | @Override
35 | public Column convertMap2Column(Map map) {
36 | Column column = new Column();
37 | column.setName(getValue(map, "COLUMN_NAME"));
38 | column.setTableName(getValue(map, "TABLE_NAME"));
39 | column.setDataType(getValue(map, "DATA_TYPE"));
40 | // Oracle/MySQL,非数值类型字段的DATA_PRECISION的值为null
41 | String dataPrecision = getValue(map, "DATA_PRECISION");
42 | if (null != dataPrecision) {
43 | column.setLength(dataPrecision);
44 | } else {
45 | column.setLength(getValue(map, "DATA_LENGTH"));
46 | }
47 | // data_scale才是小数位
48 | // column.setPrecision(getValue(map, "PRECISION"));
49 | column.setPrecision(getValue(map, "DATA_SCALE"));
50 | // Column类的isNullable为true表示不允许为空
51 | if("N".equalsIgnoreCase(getValue(map, "NULLABLE")) || "NO".equalsIgnoreCase(getValue(map, "NULLABLE"))
52 | || "NOT".equalsIgnoreCase(getValue(map, "NULLABLE"))) {
53 | column.setNullable(false);
54 | } else {
55 | column.setNullable(true);
56 | }
57 | column.setDescription(getValue(map, "DESCRIPTION"));
58 | column.setDefaultValue(getValue(map, "DEFAULT_VALUE"));
59 | return column;
60 | }
61 |
62 | @Override
63 | public PrimaryKey convertMap2PrimaryKey(Map map) {
64 | PrimaryKey primaryKey = new PrimaryKey();
65 | primaryKey.setName(getValue(map, "CONSTRAINT_NAME"));
66 | primaryKey.setTableName(getValue(map, "TABLE_NAME"));
67 | primaryKey.setCloumn(getValue(map, "COLUMN_NAME"));
68 |
69 | return primaryKey;
70 | }
71 |
72 | @Override
73 | public ForeignKey convertMap2ForeignKey(Map map) {
74 | ForeignKey fk = new ForeignKey();
75 | fk.setFkName(getValue(map, "FK_NAME"));
76 | fk.setFkTableName(getValue(map, "FK_TABLE_NAME"));
77 | fk.setFkColumnName(getValue(map, "FK_COLUMN_NAME"));
78 | fk.setPkTableName(getValue(map, "PK_TABLE_NAME"));
79 | fk.setPkColumnName(getValue(map, "PK_COLUMN_NAME"));
80 | return fk;
81 | }
82 |
83 | @Override
84 | public Index convertMap2Index(Map map) {
85 | Index index = new Index();
86 | index.setName(getValue(map, "INDEX_NAME"));
87 | index.setTableName(getValue(map, "TABLE_NAME"));
88 | index.setIndexType(getValue(map, "INDEX_TYPE"));
89 | index.setUnique(Boolean.valueOf(getValue(map, "IS_UNIQUE")));
90 | index.getCloumns().add(getValue(map, "COLUMN_NAME"));
91 | return index;
92 | }
93 |
94 | @Override
95 | public Trigger convertMap2Trigger(Map map) {
96 | Trigger trigger = new Trigger();
97 | trigger.setName(getValue(map, "TRIGGER_NAME"));
98 | trigger.setTriggerType(getValue(map, "TRIGGER_TYPE"));
99 | trigger.setEventType(getValue(map, "EVENT_TYPE"));
100 | trigger.setDefinition(getValue(map, "TRIGGER_BODY"));
101 | trigger.setDescription(getValue(map, "DESCRIPTION"));
102 |
103 | return trigger;
104 | }
105 |
106 | protected String getValue(Map map, String key) {
107 | assert !map.containsKey(key) : map.toString() + "不含有key【" + key + "】";
108 | return map.get(key);
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/converter/MySQL5MetaDataConverter.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.converter;
2 |
3 | import com.thtf.generator.dao.IMetaDataConverter;
4 | import com.thtf.generator.model.Index;
5 | import com.thtf.generator.model.Table;
6 |
7 | import java.util.Map;
8 |
9 | /**
10 | * ========================
11 | * 元数据转换器
12 | * Author:pyy
13 | * Date:2019-9-25 16:07:53
14 | * Version: v1.0
15 | * ========================
16 | */
17 | public class MySQL5MetaDataConverter extends CommonMetaDataConverter {
18 |
19 | private static IMetaDataConverter instance = new MySQL5MetaDataConverter();
20 |
21 | public static final IMetaDataConverter getInstance() {
22 | return instance;
23 | }
24 |
25 | @Override
26 | public Table convertMap2Table(Map map) {
27 | Table table = super.convertMap2Table(map);
28 |
29 | /**
30 | * MySQL5的information_schema.TABLES表的table_comment字段存储的值是:
31 | * 如果有注释:"表注释; InnoDB free: 4096 kB"
32 | * 如果没有注释,"InnoDB free: 4096 kB"这样存储引擎信息
33 | * 故需要字符串截取
34 | */
35 | // String desc = table.getDescription();
36 | // int endIndex = desc.lastIndexOf(";");
37 | // if (endIndex != -1) {
38 | // desc = desc.substring(0, endIndex);
39 | // }
40 | // table.setDescription(desc);
41 | return table;
42 | }
43 |
44 | @Override
45 | public Index convertMap2Index(Map map) {
46 | Index index = super.convertMap2Index(map);
47 | // MySql5的只有non_unique字段 , 没有IS_UNIQUE。0表示不为空
48 | index.setUnique("0".equals(getValue(map, "NON_UNIQUE")));
49 | return index;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/converter/OracleMetaDataConverter.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.converter;
2 |
3 | import com.thtf.generator.dao.IMetaDataConverter;
4 | import com.thtf.generator.model.Column;
5 | import com.thtf.generator.model.Index;
6 |
7 | import java.util.Map;
8 |
9 | /**
10 | * ========================
11 | * 元数据转换器
12 | * Author:pyy
13 | * Date:2019-9-25 16:07:53
14 | * Version: v1.0
15 | * ========================
16 | */
17 | public class OracleMetaDataConverter extends CommonMetaDataConverter {
18 |
19 | private static final IMetaDataConverter instance = new OracleMetaDataConverter();
20 |
21 | public static IMetaDataConverter getInstance() {
22 | return instance;
23 | }
24 |
25 | @Override
26 | public Column convertMap2Column(Map map) {
27 | Column column = super.convertMap2Column(map);
28 |
29 | String charLength = getValue(map, "CHAR_LENGTH");
30 | if (!"0".equals(charLength) && column.getDataType().contains("CHAR")) {
31 | // String length = getValue(map, "DATA_LENGTH");
32 | // String.valueOf(Integer.valueOf(charLength).intValue() * 2)
33 | // if (NumberUtils.toInt(length) == NumberUtils.toInt(charLength) * 2) {
34 | // charLength += " char";
35 | // }
36 | column.setLength(charLength);
37 | // } else {
38 | // // Oracel,非数值精度为null
39 | // String precision = getValue(map, "DATA_PRECISION");
40 | // if (StringUtils.isNotEmpty(precision)
41 | // && !"0".equals(precision)) {
42 | // column.setLength(precision);
43 | // } else {
44 | // column.setLength(getValue(map, "DATA_LENGTH"));
45 | // }
46 | }
47 | return column;
48 | }
49 |
50 | @Override
51 | public Index convertMap2Index(Map map) {
52 | Index index = super.convertMap2Index(map);
53 | // Oracle的user_indexes的uniqueness字段 as IS_UNIQUE,如果返回的是NONUNIQUE表示可为空
54 | index.setUnique("NONUNIQUE".equals(
55 | getValue(map, "IS_UNIQUE")) ? false : true);
56 | return index;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/dao/DatabaseDAOFactory.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.dao;
2 |
3 | import com.thtf.generator.common.constants.DBMSConstants;
4 | import com.thtf.generator.dao.impl.CommonDatabaseDAOImpl;
5 | import com.thtf.generator.dao.impl.MySql5DatabaseDAO;
6 | import com.thtf.generator.dao.sql.DatabaseType;
7 | import com.thtf.generator.vo.ConnParam;
8 |
9 | /**
10 | * ========================
11 | * 查询器生成工厂
12 | * Author:pyy
13 | * Date:2019-9-25 16:22:57
14 | * Version: v1.0
15 | * ========================
16 | */
17 | public class DatabaseDAOFactory {
18 |
19 | public static IDatabaseDAO getDAO(ConnParam connParam) {
20 | String upperCaseDbName = connParam.getDbType().toUpperCase();
21 |
22 | if (upperCaseDbName.contains(DBMSConstants.ORACLE)) {
23 | return new CommonDatabaseDAOImpl(connParam, DatabaseType.Oracle);
24 | } else if (upperCaseDbName.contains(DBMSConstants.SQL_SERVER) || upperCaseDbName.contains(DBMSConstants.SQLSERVER)) {
25 | return new CommonDatabaseDAOImpl(connParam, DatabaseType.MSSQLServer);
26 | } else if (upperCaseDbName.contains(DBMSConstants.MYSQL)) {
27 | return new MySql5DatabaseDAO(connParam, DatabaseType.MySql5);
28 | }
29 | return new MySql5DatabaseDAO(connParam, DatabaseType.MySql5);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/thtf-generator/src/main/java/com/thtf/generator/dao/IDatabaseDAO.java:
--------------------------------------------------------------------------------
1 | package com.thtf.generator.dao;
2 |
3 | import com.thtf.generator.common.exception.DAOException;
4 | import com.thtf.generator.model.*;
5 |
6 | import java.sql.Connection;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * ========================
12 | * 数据库元信息查询接口
13 | * Author:pyy
14 | * Date:2019-9-25 16:23:28
15 | * Version: v1.0
16 | * ========================
17 | */
18 | public interface IDatabaseDAO {
19 |
20 | /**
21 | * 通用查询方法
22 | * @param sql 要查询的sql语句
23 | * @param params 查询条件数组
24 | * @return
25 | * @throws DAOException
26 | */
27 | List