合并扩展插件到主工程

This commit is contained in:
ulleo 2023-08-23 16:45:25 +08:00
parent 563d608fe6
commit 793efc312a
729 changed files with 70579 additions and 0 deletions

58
extensions/.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
#*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/.idea/
target/
*.iml
.DS_Store
node_modules
/dist
node/
static/
# local env files
.env.demo
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.lock
*.classpath
*.project
*.factorypath
.settings/
.lh
package-lock.json

19
extensions/README.md Normal file
View File

@ -0,0 +1,19 @@
# DateEase 官方插件
此仓库用于放置 DataEase 官方插件,插件分为两种类型:数据源插件和视图插件。
当前以插件方式支持的数据源包括:
- 达梦数据库
- Apache Kylin
- 阿里云 MaxCompute
- MongoDB
- Presto
当前已插件方式支持的视图包括:
- 3dpie
- bubblemap
- symbolmap
更多插件持续开发中,敬请期待。

View File

@ -0,0 +1,35 @@
# Created by .ignore support plugin (hsz.mobi)
.DS_Store
node_modules
node/
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
*.iml
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
src/main/resources/static
src/main/resources/templates
src/test/
target
.settings
.project
.classpath
.factorypath
src/main/resources/jmeter/lib/

View File

@ -0,0 +1,6 @@
#!/bin/sh
mvn clean package -U -Dmaven.test.skip=true
cp dm-backend/target/dm-backend-1.18.0.jar .
zip -r dm.zip ./dm-backend-1.18.0.jar ./dmDriver ./plugin.json

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dm</artifactId>
<groupId>io.dataease</groupId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dm-backend</artifactId>
<dependencies>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-datasource</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes>
<exclude>**/server/**</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/Application*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>src/main/resources/static</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>main-class-placement</id>
<phase>generate-resources</phase>
<configuration>
<target>
<move todir="src/main/resources/static">
<fileset dir="../dm-frontend/static">
<include name="*.*"/>
</fileset>
</move>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,21 @@
package io.dataease.plugins.datasource.dm.provider;
import io.dataease.plugins.datasource.entity.JdbcConfiguration;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class DmConfig extends JdbcConfiguration {
private String driver = "dm.jdbc.driver.DmDriver";
private String extraParams;
public String getJdbc() {
return "jdbc:dm://HOST:PORT/DATABASE"
.replace("HOST", getHost().trim())
.replace("PORT", getPort().toString())
.replace("DATABASE", getDataBase().trim());
}
}

View File

@ -0,0 +1,226 @@
package io.dataease.plugins.datasource.dm.provider;
import com.google.gson.Gson;
import io.dataease.plugins.common.base.domain.DeDriver;
import io.dataease.plugins.common.base.mapper.DeDriverMapper;
import io.dataease.plugins.common.constants.DatasourceTypes;
import io.dataease.plugins.common.dto.datasource.TableDesc;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.exception.DataEaseException;
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
import io.dataease.plugins.datasource.entity.JdbcConfiguration;
import io.dataease.plugins.datasource.provider.DefaultJdbcProvider;
import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
@Component()
public class DmDsProvider extends DefaultJdbcProvider {
@Resource
private DeDriverMapper deDriverMapper;
@Override
public String getType() {
return "dm";
}
@Override
public boolean isUseDatasourcePool() {
return false;
}
@Override
public Connection getConnection(DatasourceRequest datasourceRequest) throws Exception {
DmConfig dmConfig = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), DmConfig.class);
String defaultDriver = dmConfig.getDriver();
String customDriver = dmConfig.getCustomDriver();
String url = dmConfig.getJdbc();
Properties props = new Properties();
DeDriver deDriver = null;
if (StringUtils.isNotEmpty(dmConfig.getAuthMethod()) && dmConfig.getAuthMethod().equalsIgnoreCase("kerberos")) {
System.setProperty("java.security.krb5.conf", "/opt/dataease/conf/krb5.conf");
ExtendedJdbcClassLoader classLoader;
if (isDefaultClassLoader(customDriver)) {
classLoader = extendedJdbcClassLoader;
} else {
deDriver = deDriverMapper.selectByPrimaryKey(customDriver);
classLoader = getCustomJdbcClassLoader(deDriver);
}
Class<?> ConfigurationClass = classLoader.loadClass("org.apache.hadoop.conf.Configuration");
Method set = ConfigurationClass.getMethod("set", String.class, String.class);
Object obj = ConfigurationClass.newInstance();
set.invoke(obj, "hadoop.security.authentication", "Kerberos");
Class<?> UserGroupInformationClass = classLoader.loadClass("org.apache.hadoop.security.UserGroupInformation");
Method setConfiguration = UserGroupInformationClass.getMethod("setConfiguration", ConfigurationClass);
Method loginUserFromKeytab = UserGroupInformationClass.getMethod("loginUserFromKeytab", String.class, String.class);
setConfiguration.invoke(null, obj);
loginUserFromKeytab.invoke(null, dmConfig.getUsername(), "/opt/dataease/conf/" + dmConfig.getPassword());
} else {
if (StringUtils.isNotBlank(dmConfig.getUsername())) {
props.setProperty("user", dmConfig.getUsername());
if (StringUtils.isNotBlank(dmConfig.getPassword())) {
props.setProperty("password", dmConfig.getPassword());
}
}
}
Connection conn;
String driverClassName;
ExtendedJdbcClassLoader jdbcClassLoader;
if (isDefaultClassLoader(customDriver)) {
driverClassName = defaultDriver;
jdbcClassLoader = extendedJdbcClassLoader;
} else {
if (deDriver == null) {
deDriver = deDriverMapper.selectByPrimaryKey(customDriver);
}
driverClassName = deDriver.getDriverClass();
jdbcClassLoader = getCustomJdbcClassLoader(deDriver);
}
Driver driverClass = (Driver) jdbcClassLoader.loadClass(driverClassName).newInstance();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(jdbcClassLoader);
conn = driverClass.connect(url, props);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
Thread.currentThread().setContextClassLoader(classLoader);
}
return conn;
}
@Override
public List<TableDesc> getTables(DatasourceRequest datasourceRequest) throws Exception {
List<TableDesc> tables = new ArrayList<>();
String queryStr = getTablesSql(datasourceRequest);
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = jdbcConfiguration.getQueryTimeout() > 0 ? jdbcConfiguration.getQueryTimeout() : 0;
try (Connection con = getConnectionFromPool(datasourceRequest); Statement statement = getStatement(con, queryTimeout); ResultSet resultSet = statement.executeQuery(queryStr)) {
while (resultSet.next()) {
tables.add(getTableDesc(datasourceRequest, resultSet));
}
} catch (Exception e) {
DataEaseException.throwException(e);
}
return tables;
}
private TableDesc getTableDesc(DatasourceRequest datasourceRequest, ResultSet resultSet) throws SQLException {
TableDesc tableDesc = new TableDesc();
tableDesc.setName(resultSet.getString(1));
return tableDesc;
}
@Override
public List<TableField> getTableFields(DatasourceRequest datasourceRequest) throws Exception {
List<TableField> list = new LinkedList<>();
try (Connection connection = getConnectionFromPool(datasourceRequest)) {
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null, "%", datasourceRequest.getTable(), "%");
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
String database;
database = resultSet.getString("TABLE_CAT");
if (database != null) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
list.add(tableField);
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
list.add(tableField);
}
}
}
resultSet.close();
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException("Data source connection exception: " + e.getMessage());
}
return list;
}
private String getDatabase(DatasourceRequest datasourceRequest) {
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
return jdbcConfiguration.getDataBase();
}
private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest) throws SQLException {
TableField tableField = new TableField();
String colName = resultSet.getString("COLUMN_NAME");
tableField.setFieldName(colName);
String remarks = resultSet.getString("REMARKS");
if (remarks == null || remarks.equals("")) {
remarks = colName;
}
tableField.setRemarks(remarks);
String dbType = resultSet.getString("TYPE_NAME").toUpperCase();
tableField.setFieldType(dbType);
if (dbType.equalsIgnoreCase("LONG")) {
tableField.setFieldSize(65533);
}
if (StringUtils.isNotEmpty(dbType) && dbType.toLowerCase().contains("date") && tableField.getFieldSize() < 50) {
tableField.setFieldSize(50);
}
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.hive.name()) && tableField.getFieldType().equalsIgnoreCase("BOOLEAN")) {
tableField.setFieldSize(1);
} else {
String size = resultSet.getString("COLUMN_SIZE");
if (size == null) {
tableField.setFieldSize(1);
} else {
tableField.setFieldSize(Integer.valueOf(size));
}
}
return tableField;
}
@Override
public String checkStatus(DatasourceRequest datasourceRequest) throws Exception {
String queryStr = getTablesSql(datasourceRequest);
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = jdbcConfiguration.getQueryTimeout() > 0 ? jdbcConfiguration.getQueryTimeout() : 0;
try (Connection con = getConnection(datasourceRequest); Statement statement = getStatement(con, queryTimeout); ResultSet resultSet = statement.executeQuery(queryStr)) {
} catch (Exception e) {
e.printStackTrace();
DataEaseException.throwException(e.getMessage());
}
return "Success";
}
@Override
public String getTablesSql(DatasourceRequest datasourceRequest) throws Exception {
DmConfig dmConfig = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), DmConfig.class);
if (StringUtils.isEmpty(dmConfig.getSchema())) {
throw new Exception("Database schema is empty.");
}
return "select table_name from all_tab_comments where owner='OWNER' AND table_type = 'TABLE' ".replaceAll("OWNER", dmConfig.getSchema());
}
@Override
public String getSchemaSql(DatasourceRequest datasourceRequest) {
return "select OBJECT_NAME from dba_objects where object_type='SCH'";
}
}

View File

@ -0,0 +1,61 @@
package io.dataease.plugins.datasource.dm.query;
import io.dataease.plugins.common.constants.datasource.SQLConstants;
import static io.dataease.plugins.common.constants.DatasourceTypes.oracle;
public class DmConstants extends SQLConstants {
public static final String KEYWORD_TABLE = oracle.getKeywordPrefix() + "%s" + oracle.getKeywordSuffix();
public static final String KEYWORD_FIX = "%s." + oracle.getKeywordPrefix() + "%s" + oracle.getKeywordSuffix();
public static final String ALIAS_FIX = oracle.getAliasPrefix() + "%s" + oracle.getAliasSuffix();
public static final String UNIX_TIMESTAMP = "UNIX_TIMESTAMP(%s)";
public static final String DATE_FORMAT = "to_timestamp(%s,'%s')";
public static final String FROM_UNIXTIME = "FROM_UNIXTIME(%s,'%s')";
public static final String CAST = "CAST(%s AS %s)";
public static final String DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH24:MI:SS";
public static final String DEFAULT_INT_FORMAT = "DECIMAL(20,0)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(20,8)";
public static final String WHERE_VALUE_NULL = "(NULL,'')";
public static final String WHERE_VALUE_VALUE = "'%s'";
public static final String AGG_COUNT = "COUNT(*)";
public static final String AGG_FIELD = "%s(%s)";
public static final String WHERE_BETWEEN = "'%s' AND '%s'";
public static final String BRACKETS = "(%s)";
public static final String TO_NUMBER = "TO_NUMBER(%s)";
public static final String TO_DATE = "TO_DATE(%s,'%s')";
public static final String TO_CHAR = "TO_CHAR(%s,'%s')";
public static final String DEFAULT_START_DATE = "'1970-01-01 8:0:0'";
public static final String TO_MS = " * 24 * 60 * 60 * 100";
public static final String CALC_SUB = "%s - %s";
// public static final String GROUP_CONCAT = "vm_concat(%s)";
public static final String GROUP_CONCAT = "to_char(listagg(%s,',' ) within GROUP (order by (%s)))";
public static final String NAME = "oracle";
}

View File

@ -0,0 +1,59 @@
package io.dataease.plugins.datasource.dm.service;
import io.dataease.plugins.common.constants.DatabaseClassification;
import io.dataease.plugins.common.constants.DatasourceCalculationMode;
import io.dataease.plugins.common.dto.StaticResource;
import io.dataease.plugins.common.dto.datasource.DataSourceType;
import io.dataease.plugins.datasource.service.DatasourceService;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@Service
public class DmService extends DatasourceService {
@Override
public List<String> components() {
List<String> result = new ArrayList<>();
result.add("dm");
return result;
}
@Override
protected InputStream readContent(String s) {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("static/" + s);
return resourceAsStream;
}
@Override
public List<StaticResource> staticResources() {
List<StaticResource> results = new ArrayList<>();
StaticResource staticResource = new StaticResource();
staticResource.setName("dm");
staticResource.setSuffix("jpg");
results.add(staticResource);
results.add(pluginSvg());
return results;
}
@Override
public DataSourceType getDataSourceType() {
DataSourceType dataSourceType = new DataSourceType("dm", "DM" , true , "", DatasourceCalculationMode.DIRECT, true);
dataSourceType.setKeywordPrefix("\"");
dataSourceType.setKeywordSuffix("\"");
dataSourceType.setAliasPrefix("\"");
dataSourceType.setAliasSuffix("\"");
dataSourceType.setDatabaseClassification(DatabaseClassification.OLTP);
return dataSourceType;
}
private StaticResource pluginSvg() {
StaticResource staticResource = new StaticResource();
staticResource.setName("dm-backend");
staticResource.setSuffix("svg");
return staticResource;
}
}

View File

@ -0,0 +1,12 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}

View File

@ -0,0 +1,14 @@
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

View File

@ -0,0 +1,21 @@
# deplugin-view-frontend
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
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).

View File

@ -0,0 +1,35 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const chalk = require('chalk')
const webpack = require('webpack')
const webpackConfig = require('./webpack.async-plugins')
const spinner = ora('building for sync-plugins...')
spinner.start()
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})

View File

@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

View File

@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,101 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}

View File

@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

View File

@ -0,0 +1,91 @@
const webpack = require('webpack')
const path = require('path')
const utils = require('./utils')
const CopyPlugin = require("copy-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
mode: 'development',
entry: {
'dm': resolve('/src/views/dm.vue')
},
output: {
path: resolve('/static/'),
filename: '[name].js'
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
externals: {
vue: 'vue'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
transformAssetUrls: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
},
{
test: /.(sa|sc|c)ss$/,
use: [
{loader: 'vue-style-loader'},
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new CopyPlugin([
{from: 'src/icons/svg/'}
]),
]
}

View File

@ -0,0 +1,103 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: [resolve('src/icons')],
options: {
symbolId: 'icon-[name]'
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
exclude: [resolve('src/icons')],
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.svg$/,
include: [path.resolve('src/icons')],
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]',
},
}
],
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}

View File

@ -0,0 +1,95 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})

View File

@ -0,0 +1,145 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code split chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

View File

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

View File

@ -0,0 +1,69 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}

View File

@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>deplugin-view-frontend</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -0,0 +1,75 @@
{
"name": "deplugin-datasource-frontend",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js",
"buildPlugin": "node build/build-async-plugins.js"
},
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"highcharts": "^10.0.0",
"svg-sprite-loader": "^6.0.11",
"svgo": "1.2.2",
"svgo-loader": "^3.0.1",
"vue": "^2.5.2",
"vue-i18n": "7.3.2",
"vue-router": "^3.0.1",
"vue-uuid": "2.0.2",
"vuedraggable": "^2.24.3"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^0.28.0",
"element-ui": "2.15.7",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^3.2.0",
"js-cookie": "2.2.0",
"node-notifier": "^8.0.1",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass": "^1.33.0",
"sass-loader": "^7.3.1",
"semver": "^5.3.0",
"shelljs": "^0.8.5",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^15.6.4",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.2",
"webpack": "^4.8.1",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-server": "^3.1.11",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.dataease</groupId>
<artifactId>dm</artifactId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dm-frontend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>static</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<!-- See https://nodejs.org/en/download/ for latest node and npm (lts) versions -->
<nodeVersion>v16.20.2</nodeVersion>
<npmVersion>7.6.3</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install --force</arguments>
</configuration>
</execution>
<execution>
<id>npm run buildPlugin</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run buildPlugin</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,23 @@
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,113 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
Community Chat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
Twitter
</a>
</li>
<br>
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,16 @@
export default {
plugin_view_3d_pie: {
type_title: '3D-PIE',
label: 'Label',
angle: 'Angle'
},
host: 'Host',
port: 'Port',
dataBase: 'Catalog',
schema: 'Schema',
username: 'User',
password: 'Password',
get_schema: 'Get Schema',
please_choose_schema: 'Please select Schema',
query_timeout: 'Query timeout (seconds)'
}

View File

@ -0,0 +1,49 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
import elementTWLocale from 'element-ui/lib/locale/lang/zh-TW'// element-ui lang
import localMessages from './messages'
Vue.use(VueI18n)
const messages = {
en_US: {
...localMessages['en_US'],
...elementEnLocale
},
zh_CN: {
...localMessages['zh_CN'],
...elementZhLocale
},
zh_TW: {
...localMessages['zh_TW'],
...elementTWLocale
}
}
export function getLanguage () {
const chooseLanguage = Cookies.get('language')
if (chooseLanguage) return chooseLanguage
// if has not choose language
const language = (navigator.language || navigator.browserLanguage).toLowerCase()
const locales = Object.keys(messages)
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
return locale
}
}
return 'zh_CN'
}
const i18n = new VueI18n({
// set locale
// options: en | zh | es
locale: getLanguage(),
// set locale messages
messages
})
export default i18n

View File

@ -0,0 +1,17 @@
import enLocale from './en'
import zhLocale from './zh'
import twLocale from './tw'
const messages = {
en_US: {
...enLocale
},
zh_CN: {
...zhLocale
},
zh_TW: {
...twLocale
}
}
export default messages

View File

@ -0,0 +1,16 @@
export default {
plugin_view_3d_pie: {
type_title: '3D餅圖',
label: '標籤',
angle: '角度'
},
host: '主機名',
port: '端口',
dataBase: '數據庫',
schema: 'Schema',
username: '用戶名',
password: '密碼',
get_schema: '获取 Schema',
please_choose_schema: '请选择 Schema',
query_timeout: '査詢超時(秒)'
}

View File

@ -0,0 +1,21 @@
export default {
plugin_view_3d_pie: {
type_title: '3D饼图',
label: '标签',
angle: '角度'
},
host: '主机名',
port: '端口',
dataBase: '数据库',
schema: 'Schema',
username: '用户名',
password: '密码',
get_schema: '获取 Schema',
please_choose_schema: '请选择 Schema',
second: '秒',
enter_the_port: '请输入端口',
one_user_name: '请输入用户名',
input_a_password: '请输入密码',
please_select: '请选择',
query_timeout: '查询超时'
}

View File

@ -0,0 +1,9 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00022 9.99975C7.56203 9.99975 7.13323 9.96523 6.71734 9.89921L6.38535 11.1382C6.33771 11.316 6.15493 11.4216 5.9771 11.3739L5.33315 11.2014C5.15533 11.1537 5.0498 10.9709 5.09745 10.7931L5.42255 9.57985C4.88013 9.39561 4.37096 9.15494 3.90491 8.86629L2.8454 9.9258C2.71522 10.056 2.50417 10.056 2.37399 9.9258L1.90259 9.4544C1.77242 9.32422 1.77242 9.11317 1.90259 8.98299L2.83565 8.04994C2.35424 7.59918 1.95209 7.0852 1.64812 6.52421C1.64492 6.51832 1.64162 6.51215 1.63823 6.50575C1.5136 6.27038 1.56023 5.97574 1.75709 5.79635C1.92051 5.64743 2.03596 5.5461 2.13639 5.44567C2.14538 5.43669 2.15521 5.42666 2.16569 5.41583C2.31108 5.2656 2.55902 5.32152 2.64417 5.51246C3.47427 7.37398 5.46211 8.66641 8.00022 8.66641C10.4321 8.66641 12.4664 7.40872 13.2829 5.68239C13.3042 5.63747 13.328 5.5809 13.3519 5.52084C13.4276 5.33064 13.6741 5.27325 13.8188 5.41801C13.9259 5.52508 14.0687 5.66784 14.2471 5.8463C14.4235 6.0227 14.4713 6.29211 14.356 6.51334C14.3279 6.56715 14.3006 6.61785 14.2774 6.65816C13.9638 7.20109 13.5572 7.69751 13.0754 8.1321L13.9263 8.98299C14.0565 9.11317 14.0565 9.32422 13.9263 9.4544L13.4549 9.9258C13.3247 10.056 13.1136 10.056 12.9835 9.9258L11.9888 8.93112C11.5521 9.19111 11.0792 9.40958 10.5779 9.57985L10.903 10.7931C10.9506 10.9709 10.8451 11.1537 10.6673 11.2014L10.0233 11.3739C9.84552 11.4216 9.66274 11.316 9.61509 11.1382L9.2831 9.89921C8.86721 9.96523 8.43842 9.99975 8.00022 9.99975Z" fill="#BBBFC4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.98994 12.333C10.1486 12.333 12.1472 10.9599 14.0001 7.99101C12.1949 5.03272 10.2008 3.66634 7.98994 3.66634C5.77984 3.66634 3.7929 5.0321 2.00009 7.99099C3.84053 10.9605 5.83206 12.333 7.98994 12.333ZM1.00172 8.59304C0.787049 8.22763 0.785596 7.77336 0.995302 7.40508C1.00277 7.39196 1.00993 7.37945 1.01672 7.36768C2.9521 4.01123 5.27627 2.33301 7.98923 2.33301C10.7133 2.33301 13.0518 4.02495 15.0049 7.40884C15.0107 7.41898 15.0168 7.42969 15.0232 7.44089C15.2208 7.7869 15.2193 8.21401 15.0172 8.55738C13.0127 11.9634 10.67 13.6663 7.98923 13.6663C5.31784 13.6663 2.98867 11.9752 1.00172 8.59304ZM8.00009 10.6663C6.52733 10.6663 5.33342 9.47243 5.33342 7.99967C5.33342 6.52692 6.52733 5.33301 8.00009 5.33301C9.47285 5.33301 10.6668 6.52692 10.6668 7.99967C10.6668 9.47243 9.47285 10.6663 8.00009 10.6663ZM8.00009 9.33301C8.73647 9.33301 9.33342 8.73605 9.33342 7.99967C9.33342 7.26329 8.73647 6.66634 8.00009 6.66634C7.26371 6.66634 6.66675 7.26329 6.66675 7.99967C6.66675 8.73605 7.26371 9.33301 8.00009 9.33301Z" fill="#BBBFC4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{isolation:isolate;}.cls-2{fill:#f2f4f5;}.cls-3{fill:#0a7be0;}.cls-4{fill:#53baf9;}.cls-5,.cls-6{fill:#a2a2ba;}.cls-6{mix-blend-mode:multiply;}.cls-7{fill:#fff;}</style></defs><title>【icon】插件管理-导出</title><g class="cls-1"><g id="图层_1" data-name="图层 1"><circle class="cls-2" cx="31.9" cy="32" r="32"/><path class="cls-3" d="M25.94,44.24l6.49-11H43.74V13.26A2.26,2.26,0,0,0,41.49,11H14.6a2.46,2.46,0,0,0-2.46,2.46V44.12a3.5,3.5,0,0,0,3.5,3.5H27.93Z"/><path class="cls-4" d="M25.94,44.24l1.18-2H14.83a2.7,2.7,0,0,0-2.69,2.69h0a2.7,2.7,0,0,0,2.69,2.69h13.1Z"/><polygon class="cls-5" points="33.78 53 28.63 44.24 33.78 35.47 51.67 35.47 51.67 53 33.78 53"/><polygon class="cls-6" points="33.78 53 28.63 44.24 51.67 44.17 51.67 53 33.78 53"/><path class="cls-7" d="M38.59,43.4a4.27,4.27,0,0,1-.88-2.7c-.27.19-.53.38-.78.58a3.21,3.21,0,0,0,.67,2.33c.91.82,1.69.35,2.76,1.16.79.6.46,2,.16,2.87.27-.1.55-.21.83-.34.25-1,.51-2.4-.05-2.89C40.42,43.64,39.3,44.08,38.59,43.4Z"/><path class="cls-7" d="M40.14,45.11c-.87-.77-2.12-.54-2.86-1.3a3.5,3.5,0,0,1-.82-2.13c-1.86,1.71-2.71,3.73-1.94,5.12s3.07,1.74,5.59,1C40.4,46.86,40.68,45.58,40.14,45.11Z"/><path class="cls-7" d="M43.72,43.66c-.88-.77-2.37-.86-2.93-1.44-.72-.73-.48-2.17-.29-2.93-.31.11-.63.23-1,.38-.1.73-.24,2.4.46,3,.92.81,1.7.27,2.77,1.09a2.48,2.48,0,0,1,.71,2.3c.24-.17.46-.34.68-.52A2.39,2.39,0,0,0,43.72,43.66Z"/><path class="cls-7" d="M46.49,40.13c-.78-1.38-3-1.73-5.38-1-.29.83-.7,2.36,0,2.94.91.82,2,.54,3.09,1.3a1.84,1.84,0,0,1,.6,1.71C46.47,43.38,47.23,41.46,46.49,40.13Z"/><path class="cls-7" d="M42.62,44c-.88-.77-2.2-.44-2.88-1.16a4.22,4.22,0,0,1-.66-3l-.44.23-.43.25c0,.67,0,2.18.56,2.77.87.87,1.62.21,2.69,1,.81.61.65,2,.47,2.86l.43-.23c.19-.1.37-.21.55-.32C43.06,45.7,43.18,44.52,42.62,44Z"/><rect class="cls-7" x="18.81" y="15.56" width="18.8" height="3.02" rx="1.51"/><rect class="cls-4" x="18.81" y="21.05" width="9.39" height="3.02" rx="1.51"/><rect class="cls-7" x="18.81" y="25.84" width="20.18" height="3.02" rx="1.51"/><circle class="cls-7" cx="15.85" cy="17.07" r="1.51"/><circle class="cls-4" cx="15.85" cy="22.56" r="1.51"/><circle class="cls-7" cx="15.85" cy="27.35" r="1.51"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,22 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

View File

@ -0,0 +1,33 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import Cookies from 'js-cookie'
import i18n from './de-base/lang'
import draggable from 'vuedraggable'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
Vue.config.productionTip = false
Vue.use(ElementUI, {
size: Cookies.get('size') || 'medium',
i18n: (key, value) => i18n.t(key, value)
})
Vue.component('Treeselect', Treeselect)
Vue.component('draggable', draggable)
Vue.prototype.hasDataPermission = function(pTarget, pSource) {
if (pSource && pTarget) {
return pSource.indexOf(pTarget) > -1
}
return false
}
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
i18n,
components: { App },
template: '<App/>'
})

View File

@ -0,0 +1,21 @@
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import maxcompute from '@/views/maxcompute'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/maxcompute',
name: 'maxcompute',
component: maxcompute
}
]
})

View File

@ -0,0 +1,29 @@
export const compareItem = {
type: 'none', // year-yoy/month-yoy等
resultData: 'percent', // 对比差sub百分比percent等
field: '',
custom: {
field: '',
calcType: '0', // 0-增长值1-增长率
timeType: '0', // 0-固定日期1-日期区间
currentTime: '',
compareTime: '',
currentTimeRange: [],
compareTimeRange: []
}
}
export const compareYearList = [
{ name: 'year_mom', value: 'year_mom' }
]
export const compareMonthList = [
{ name: 'month_mom', value: 'month_mom' },
{ name: 'year_yoy', value: 'year_yoy' }
]
export const compareDayList = [
{ name: 'day_mom', value: 'day_mom' },
{ name: 'month_yoy', value: 'month_yoy' },
{ name: 'year_yoy', value: 'year_yoy' }
]

View File

@ -0,0 +1,15 @@
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path) || /^(http?:|mailto:|tel:)/.test(path) || path.startsWith('/api/pluginCommon/staticInfo')
}

View File

@ -0,0 +1,75 @@
<template>
<el-input
:value="value"
:placeholder="placeholder"
:type="type"
:disabled="disabled"
class="de-pwd-input"
@input="handleInput"
@change="handleChange"
>
<svg-icon
@click="handleClick"
v-if="!showPwd || buttonDisabled"
slot="suffix"
icon-class="de_pwd_invisible"
/>
<svg-icon
@click="handleClick"
v-else
slot="suffix"
icon-class="de_pwd_visible"
/>
</el-input>
</template>
<script>
export default {
name: "DePwd",
inject: {
elForm: {
default: "",
},
},
props: {
disabled: Boolean,
placeholder: String,
value: String,
},
data() {
return {
showPwd: false,
};
},
computed: {
buttonDisabled() {
return this.$options.propsData.hasOwnProperty("disabled")
? this.disabled
: (this.elForm || {}).disabled;
},
type() {
return !this.showPwd || this.buttonDisabled ? "password" : "text";
},
},
methods: {
handleClick() {
if (this.buttonDisabled) return;
this.showPwd = !this.showPwd;
},
handleInput(val) {
this.$emit("input", val);
},
handleChange(val) {
this.$emit("change", val);
},
},
};
</script>
<style lang="scss">
.de-pwd-input {
.el-input__suffix {
right: 12px;
font-size: 16px;
}
}
</style>

View File

@ -0,0 +1,202 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div>
<el-row>
<el-col>
<el-form
ref="DsForm"
:model="form"
:rules="rule"
size="small"
:disabled="disabled"
label-width="180px"
label-position="right"
>
<el-form-item :label="$t('host')" prop="configuration.host">
<el-input v-model="form.configuration.host" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('port')" prop="configuration.port">
<el-input :placeholder="$t('enter_the_port')" v-model="form.configuration.port" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('dataBase')" prop="configuration.dataBase">
<el-input v-model="form.configuration.dataBase" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('username')" prop="configuration.username">
<el-input :placeholder="$t('one_user_name')" v-model="form.configuration.username" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('password')" prop="configuration.password">
<dePwd :placeholder="$t('input_a_password')" v-model="form.configuration.password" />
</el-form-item>
<el-form-item class="schema-label" :label="$t('schema')">
<template slot="label">
{{ $t("schema") }}
<el-button type="text" icon="el-icon-plus" size="small" @click="getSchema()">{{ $t('get_schema') }}
</el-button>
</template>
<el-select v-model="form.configuration.schema" filterable
:placeholder="$t('please_select')"
class="de-select">
<el-option v-for="item in schemas" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
<el-form-item :label="$t('query_timeout')">
<el-input
v-model="form.configuration.queryTimeout"
autocomplete="off"
type="number"
:min="0"
>
<template slot="append">{{ $t("second") }}</template>
</el-input>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import messages from '@/de-base/lang/messages'
import dePwd from "./dePwd.vue";
export default {
name: "dm",
components: { dePwd },
props: {
method: String,
request: {},
response: {},
editApiItem: {
type: Boolean,
default() {
return false;
}
},
showScript: {
type: Boolean,
default: true,
},
obj: {
type: Object,
default() {
return {
configuration: {
initialPoolSize: 5,
extraParams: '',
minPoolSize: 5,
maxPoolSize: 50,
maxIdleTime: 30,
acquireIncrement: 5,
idleConnectionTestPeriod: 5,
queryTimeout: 30,
connectTimeout: 5
},
apiConfiguration: []
}
}
},
},
data() {
return {
rule: {
'configuration.host': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.port': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.dataBase': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.username': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.password': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}]
},
canEdit: false,
originConfiguration: {},
height: 500,
disabledNext: false,
schemas: []
}
},
computed: {
form() {
return this.obj.form
},
disabled() {
return this.obj.disabled
}
},
created() {
this.$emit('on-add-languages', messages)
},
watch: {},
methods: {
executeAxios(url, type, data, callBack) {
const param = {
url: url,
type: type,
data: data,
callBack: callBack
}
this.$emit('execute-axios', param)
},
getSchema() {
this.$refs["DsForm"].validate(valid => {
if (valid) {
const data = JSON.parse(JSON.stringify(this.form))
data.configuration = JSON.stringify(data.configuration)
this.executeAxios('/datasource/getSchema/', 'post', data, res => {
this.schemas = res.data
})
} else {
return false
}
})
},
validate() {
let status = null;
this.$refs["DsForm"].validate((val) => {
if (val) {
status = true
} else {
status = false
}
})
if (!this.form.configuration.schema ) {
this.$message.error(this.$t('please_choose_schema'))
status = false
}
return status
}
}
}
</script>
<style scoped>
.ms-query {
background: #409EFF;
color: white;
height: 18px;
border-radius: 42%;
}
.ms-header {
background: #409EFF;
color: white;
height: 18px;
border-radius: 42%;
}
.request-tabs {
margin: 20px;
min-height: 200px;
}
.ms-el-link {
float: right;
margin-right: 45px;
}
</style>

View File

@ -0,0 +1,13 @@
{
"name":"达梦数据源插件",
"free":0,
"store":"default",
"cost":0,
"category":"datasource",
"descript":"达梦插件,值得拥有",
"version":"1.18.0",
"creator":"DATAEASE",
"moduleName":"dm-backend",
"require":"1.12.0",
"dsType":"dm"
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dataease-extensions-datasource</artifactId>
<groupId>io.dataease</groupId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dm</artifactId>
<packaging>pom</packaging>
<modules>
<module>dm-frontend</module>
<module>dm-backend</module>
</modules>
</project>

View File

@ -0,0 +1,6 @@
#!/bin/sh
mvn clean package -U -Dmaven.test.skip=true
cp kingbase-backend/target/kingbase-backend-1.18.0.jar .
zip -r kingbase.zip ./kingbase-backend-1.18.0.jar ./kingbaseDriver ./plugin.json

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>kingbase</artifactId>
<groupId>io.dataease</groupId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kingbase-backend</artifactId>
<dependencies>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-datasource</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes>
<exclude>**/server/**</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/Application*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>src/main/resources/static</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>main-class-placement</id>
<phase>generate-resources</phase>
<configuration>
<target>
<move todir="src/main/resources/static">
<fileset dir="../kingbase-frontend/static">
<include name="*.*"/>
</fileset>
</move>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
package io.dataease.plugins.datasource.kingbase.provider;
import io.dataease.plugins.datasource.entity.JdbcConfiguration;
import lombok.Getter;
import lombok.Setter;
/**
* 连接配置信息
*/
@Getter
@Setter
public class KingbaseConfig extends JdbcConfiguration {
private String driver = "com.kingbase8.Driver";//驱动类名
private String extraParams;
/**
* JDBC 拼接
*/
public String getJdbc() {
return "jdbc:kingbase8://HOST:PORT/DATABASE"
.replace("HOST", getHost().trim())
.replace("PORT", getPort().toString())
.replace("DATABASE", getDataBase().trim());
}
}

View File

@ -0,0 +1,264 @@
package io.dataease.plugins.datasource.kingbase.provider;
import com.google.gson.Gson;
import io.dataease.plugins.common.base.domain.DeDriver;
import io.dataease.plugins.common.base.mapper.DeDriverMapper;
import io.dataease.plugins.common.constants.DatasourceTypes;
import io.dataease.plugins.common.dto.datasource.TableDesc;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.exception.DataEaseException;
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
import io.dataease.plugins.datasource.entity.JdbcConfiguration;
import io.dataease.plugins.datasource.provider.DefaultJdbcProvider;
import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
@Component()
public class KingbaseDsProvider extends DefaultJdbcProvider {
@Resource
private DeDriverMapper deDriverMapper;
@Override
public String getType() {
return "kingbase";
}
@Override
public boolean isUseDatasourcePool() {
return false;
}
/**
* 连接数据源
*/
@Override
public Connection getConnection(DatasourceRequest datasourceRequest) throws Exception {
KingbaseConfig kingbaseConfig = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(),
KingbaseConfig.class);
String defaultDriver = kingbaseConfig.getDriver();
String customDriver = kingbaseConfig.getCustomDriver();
String url = kingbaseConfig.getJdbc();
Properties props = new Properties();
DeDriver deDriver = null;
if (StringUtils.isNotEmpty(kingbaseConfig.getAuthMethod()) && kingbaseConfig.getAuthMethod().equalsIgnoreCase("kerberos")) {
System.setProperty("java.security.krb5.conf", "/opt/dataease/conf/krb5.conf");
ExtendedJdbcClassLoader classLoader;
if (isDefaultClassLoader(customDriver)) {
classLoader = extendedJdbcClassLoader;
} else {
deDriver = deDriverMapper.selectByPrimaryKey(customDriver);
classLoader = getCustomJdbcClassLoader(deDriver);
}
Class<?> ConfigurationClass = classLoader.loadClass("org.apache.hadoop.conf.Configuration");
Method set = ConfigurationClass.getMethod("set", String.class, String.class);
Object obj = ConfigurationClass.newInstance();
set.invoke(obj, "hadoop.security.authentication", "Kerberos");
Class<?> UserGroupInformationClass = classLoader.loadClass("org.apache.hadoop.security" +
".UserGroupInformation");
Method setConfiguration = UserGroupInformationClass.getMethod("setConfiguration", ConfigurationClass);
Method loginUserFromKeytab = UserGroupInformationClass.getMethod("loginUserFromKeytab", String.class,
String.class);
setConfiguration.invoke(null, obj);
loginUserFromKeytab.invoke(null, kingbaseConfig.getUsername(),
"/opt/dataease/conf/" + kingbaseConfig.getPassword());
} else {
if (StringUtils.isNotBlank(kingbaseConfig.getUsername())) {
props.setProperty("user", kingbaseConfig.getUsername());
if (StringUtils.isNotBlank(kingbaseConfig.getPassword())) {
props.setProperty("password", kingbaseConfig.getPassword());
}
}
}
Connection conn;
String driverClassName;
ExtendedJdbcClassLoader jdbcClassLoader;
if (isDefaultClassLoader(customDriver)) {
driverClassName = defaultDriver;
jdbcClassLoader = extendedJdbcClassLoader;
} else {
if (deDriver == null) {
deDriver = deDriverMapper.selectByPrimaryKey(customDriver);
}
driverClassName = deDriver.getDriverClass();
jdbcClassLoader = getCustomJdbcClassLoader(deDriver);
}
Driver driverClass = (Driver) jdbcClassLoader.loadClass(driverClassName).newInstance();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(jdbcClassLoader);
conn = driverClass.connect(url, props);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
Thread.currentThread().setContextClassLoader(classLoader);
}
return conn;
}
/**
* 获取表名称
*/
@Override
public List<TableDesc> getTables(DatasourceRequest datasourceRequest) throws Exception {
List<TableDesc> tables = new ArrayList<>();
String queryStr = getTablesSql(datasourceRequest);
JdbcConfiguration jdbcConfiguration =
new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = Math.max(jdbcConfiguration.getQueryTimeout(), 0);
try (Connection con = getConnectionFromPool(datasourceRequest); Statement statement = getStatement(con,
queryTimeout); ResultSet resultSet = statement.executeQuery(queryStr)) {
while (resultSet.next()) {
tables.add(getTableDesc(datasourceRequest, resultSet));
}
} catch (Exception e) {
DataEaseException.throwException(e);
}
return tables;
}
/**
* 获取表名称
*/
private TableDesc getTableDesc(DatasourceRequest datasourceRequest, ResultSet resultSet) throws SQLException {
TableDesc tableDesc = new TableDesc();
tableDesc.setName(resultSet.getString(1));
return tableDesc;
}
/**
* 获取表字段信息
*/
@Override
public List<TableField> getTableFields(DatasourceRequest datasourceRequest) throws Exception {
List<TableField> list = new LinkedList<>();
try (Connection connection = getConnectionFromPool(datasourceRequest)) {
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null, null, datasourceRequest.getTable(), "%");
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME").toUpperCase();
String database;
database = resultSet.getString("TABLE_CAT");
if (database != null) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
list.add(tableField);
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
list.add(tableField);
}
}
}
resultSet.close();
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException("Data source connection exception: " + e.getMessage());
}
return list;
}
/**
* 获取数据源
*/
private String getDatabase(DatasourceRequest datasourceRequest) {
JdbcConfiguration jdbcConfiguration =
new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
return jdbcConfiguration.getDataBase();
}
/**
* 获取表字段
*/
private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest) throws SQLException {
TableField tableField = new TableField();
String colName = resultSet.getString("COLUMN_NAME");
tableField.setFieldName(colName);
String remarks = resultSet.getString("REMARKS");
if (remarks == null || remarks.equals("")) {
remarks = colName;
}
tableField.setRemarks(remarks);
String dbType = resultSet.getString("TYPE_NAME").toUpperCase();
tableField.setFieldType(dbType);
if (dbType.equalsIgnoreCase("LONG")) {
tableField.setFieldSize(65533);
}
if (StringUtils.isNotEmpty(dbType) && dbType.toLowerCase().contains("date") && tableField.getFieldSize() < 50) {
tableField.setFieldSize(50);
}
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.hive.name()) && tableField.getFieldType().equalsIgnoreCase("BOOLEAN")) {
tableField.setFieldSize(1);
} else {
String size = resultSet.getString("COLUMN_SIZE");
if (size == null) {
tableField.setFieldSize(1);
} else {
tableField.setFieldSize(Integer.valueOf(size));
}
}
return tableField;
}
/**
* 检验数据源状态
*/
@Override
public String checkStatus(DatasourceRequest datasourceRequest) throws Exception {
String queryStr = getTablesSql(datasourceRequest);
JdbcConfiguration jdbcConfiguration =
new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = Math.max(jdbcConfiguration.getQueryTimeout(), 0);
try (Connection con = getConnection(datasourceRequest); Statement statement = getStatement(con, queryTimeout); ResultSet resultSet = statement.executeQuery(queryStr)) {
} catch (Exception e) {
e.printStackTrace();
DataEaseException.throwException(e.getMessage());
}
return "Success";
}
/**
* 显示对应的表的 SQL 语句
*/
@Override
public String getTablesSql(DatasourceRequest datasourceRequest) throws Exception {
KingbaseConfig kingbaseConfig = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(),
KingbaseConfig.class);
if (StringUtils.isEmpty(kingbaseConfig.getSchema())) {
throw new Exception("Database schema is empty.");
}
/*return "select a.table_name, b.comments from all_tables a, user_tab_comments b where a.table_name = b
.table_name and owner=upper('OWNER') ".replaceAll("OWNER",
kingbaseConfig.getSchema());*/
return ("select table_name from all_tables where owner=upper('OWNER') ").replaceAll("OWNER",
kingbaseConfig.getSchema());
}
/**
* 获取所有的用户
*/
@Override
public String getSchemaSql(DatasourceRequest datasourceRequest) {
return "select * from all_users";
}
}

View File

@ -0,0 +1,60 @@
package io.dataease.plugins.datasource.kingbase.query;
import io.dataease.plugins.common.constants.datasource.SQLConstants;
import static io.dataease.plugins.common.constants.DatasourceTypes.oracle;
public class KingbaseConstants extends SQLConstants {
public static final String KEYWORD_TABLE = oracle.getKeywordPrefix() + "%s" + oracle.getKeywordSuffix();
public static final String KEYWORD_FIX = "%s." + oracle.getKeywordPrefix() + "%s" + oracle.getKeywordSuffix();
public static final String ALIAS_FIX = oracle.getAliasPrefix() + "%s" + oracle.getAliasSuffix();
public static final String UNIX_TIMESTAMP = "UNIX_TIMESTAMP(%s)";
public static final String DATE_FORMAT = "to_timestamp(%s,'%s')";
public static final String FROM_UNIXTIME = "FROM_UNIXTIME(%s,'%s')";
public static final String CAST = "CAST(%s AS %s)";
public static final String DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH24:MI:SS";
public static final String DEFAULT_INT_FORMAT = "DECIMAL(20,0)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(20,8)";
public static final String WHERE_VALUE_NULL = "(NULL,'')";
public static final String WHERE_VALUE_VALUE = "'%s'";
public static final String AGG_COUNT = "COUNT(*)";
public static final String AGG_FIELD = "%s(%s)";
public static final String WHERE_BETWEEN = "'%s' AND '%s'";
public static final String BRACKETS = "(%s)";
public static final String TO_NUMBER = "TO_NUMBER(%s)";
public static final String TO_DATE = "TO_DATE(%s,'%s')";
public static final String TO_CHAR = "TO_CHAR(%s,'%s')";
public static final String DEFAULT_START_DATE = "'1970-01-01 8:0:0'";
public static final String TO_MS = " * 24 * 60 * 60 * 100";
public static final String CALC_SUB = "%s - %s";
// public static final String GROUP_CONCAT = "vm_concat(%s)";
public static final String GROUP_CONCAT = "to_char(listagg(%s,',' ) within GROUP (order by (%s)))";
public static final String NAME = "oracle";
}

View File

@ -0,0 +1,71 @@
package io.dataease.plugins.datasource.kingbase.service;
import io.dataease.plugins.common.constants.DatabaseClassification;
import io.dataease.plugins.common.constants.DatasourceCalculationMode;
import io.dataease.plugins.common.dto.StaticResource;
import io.dataease.plugins.common.dto.datasource.DataSourceType;
import io.dataease.plugins.datasource.service.DatasourceService;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@Service
public class KingbaseService extends DatasourceService {
/**
* 添加数据源类型
*/
@Override
public List<String> components() {
List<String> result = new ArrayList<>();
result.add("kingbase");
return result;
}
/**
* 读取静态资源
*/
@Override
protected InputStream readContent(String s) {
return this.getClass().getClassLoader().getResourceAsStream("static/" + s);
}
/**
* 映射 Logo 资源
*/
@Override
public List<StaticResource> staticResources() {
List<StaticResource> results = new ArrayList<>();
StaticResource staticResource = new StaticResource();
staticResource.setName("kingbase");
staticResource.setSuffix("jpg");
results.add(staticResource);
results.add(pluginSvg());
return results;
}
/**
* 用户填写的数据源信息
*/
@Override
public DataSourceType getDataSourceType() {
DataSourceType dataSourceType = new DataSourceType("kingbase", "KingBase", true, "",
DatasourceCalculationMode.DIRECT_AND_SYNC, true);
dataSourceType.setKeywordPrefix("\"");
dataSourceType.setKeywordSuffix("\"");
dataSourceType.setAliasPrefix("\"");
dataSourceType.setAliasSuffix("\"");
dataSourceType.setDatabaseClassification(DatabaseClassification.OLTP);
return dataSourceType;
}
private StaticResource pluginSvg() {
StaticResource staticResource = new StaticResource();
staticResource.setName("kingbase-backend");
staticResource.setSuffix("svg");
return staticResource;
}
}

View File

@ -0,0 +1,12 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}

View File

@ -0,0 +1,14 @@
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

View File

@ -0,0 +1,21 @@
# deplugin-view-frontend
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
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).

View File

@ -0,0 +1,35 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const chalk = require('chalk')
const webpack = require('webpack')
const webpackConfig = require('./webpack.async-plugins')
const spinner = ora('building for sync-plugins...')
spinner.start()
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})

View File

@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

View File

@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,101 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}

View File

@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

View File

@ -0,0 +1,91 @@
const webpack = require('webpack')
const path = require('path')
const utils = require('./utils')
const CopyPlugin = require("copy-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
mode: 'development',
entry: {
'kingbase': resolve('/src/views/kingbase.vue')
},
output: {
path: resolve('/static/'),
filename: '[name].js'
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
externals: {
vue: 'vue'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
transformAssetUrls: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
},
{
test: /.(sa|sc|c)ss$/,
use: [
{loader: 'vue-style-loader'},
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new CopyPlugin([
{from: 'src/icons/svg/'}
]),
]
}

View File

@ -0,0 +1,103 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: [resolve('src/icons')],
options: {
symbolId: 'icon-[name]'
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
exclude: [resolve('src/icons')],
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.svg$/,
include: [path.resolve('src/icons')],
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]',
},
}
],
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}

View File

@ -0,0 +1,95 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})

View File

@ -0,0 +1,145 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code split chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

View File

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

View File

@ -0,0 +1,69 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}

View File

@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>deplugin-view-frontend</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -0,0 +1,75 @@
{
"name": "deplugin-datasource-frontend",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js",
"buildPlugin": "node build/build-async-plugins.js"
},
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"highcharts": "^10.0.0",
"svg-sprite-loader": "^6.0.11",
"svgo": "1.2.2",
"svgo-loader": "^3.0.1",
"vue": "^2.5.2",
"vue-i18n": "7.3.2",
"vue-router": "^3.0.1",
"vue-uuid": "2.0.2",
"vuedraggable": "^2.24.3"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^0.28.0",
"element-ui": "2.15.7",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^3.2.0",
"js-cookie": "2.2.0",
"node-notifier": "^8.0.1",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass": "^1.33.0",
"sass-loader": "^7.3.1",
"semver": "^5.3.0",
"shelljs": "^0.8.5",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^15.6.4",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.2",
"webpack": "^4.8.1",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-server": "^3.1.11",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.dataease</groupId>
<artifactId>kingbase</artifactId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kingbase-frontend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>static</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<!-- See https://nodejs.org/en/download/ for latest node and npm (lts) versions -->
<nodeVersion>v16.20.2</nodeVersion>
<npmVersion>7.6.3</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install --force</arguments>
</configuration>
</execution>
<execution>
<id>npm run buildPlugin</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run buildPlugin</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,5 @@
module.exports = {
plugins: {
'autoprefixer': { browsers: 'last 5 version' }
}
}

View File

@ -0,0 +1,23 @@
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,113 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
Community Chat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
Twitter
</a>
</li>
<br>
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,31 @@
export default {
host: 'Host name/IP address',
dataBase: 'Database name',
connection_mode: 'Connection mode',
oracle_sid: 'SID',
oracle_service_name: 'Service name',
username: 'User name',
password: 'Password',
port: 'Port',
schema: 'Schema',
get_schema: 'Get Schema',
charset: 'Character set',
targetCharset: 'Target character set',
priority: 'Advanced settings',
initial_pool_size: 'Initial connections',
min_pool_size: 'Minimum connections',
max_pool_size: 'Maximum connections',
query_timeout: 'Query timeout',
one_user_name: 'Please enter the user name',
input_a_password: 'Please enter the password',
enter_the_port: 'Please enter the port',
please_choose_schema: 'Please select Schema',
please_choose_charset: 'Please select the database character set',
please_choose_targetCharset: 'Please select the target character set',
please_input_initial_pool_size: 'Please enter the initial number of connections',
please_input_min_pool_size: 'Please enter the minimum number of connections',
please_input_max_pool_size: 'Please enter the maximum number of connections',
please_input_query_timeout: 'Please enter the query timeout',
second: 'Second',
please_select: 'Please select'
}

View File

@ -0,0 +1,49 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
import elementTWLocale from 'element-ui/lib/locale/lang/zh-TW'// element-ui lang
import localMessages from './messages'
Vue.use(VueI18n)
const messages = {
en_US: {
...localMessages['en_US'],
...elementEnLocale
},
zh_CN: {
...localMessages['zh_CN'],
...elementZhLocale
},
zh_TW: {
...localMessages['zh_TW'],
...elementTWLocale
}
}
export function getLanguage () {
const chooseLanguage = Cookies.get('language')
if (chooseLanguage) return chooseLanguage
// if has not choose language
const language = (navigator.language || navigator.browserLanguage).toLowerCase()
const locales = Object.keys(messages)
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
return locale
}
}
return 'zh_CN'
}
const i18n = new VueI18n({
// set locale
// options: en | zh | es
locale: getLanguage(),
// set locale messages
messages
})
export default i18n

View File

@ -0,0 +1,17 @@
import enLocale from './en'
import zhLocale from './zh'
import twLocale from './tw'
const messages = {
en_US: {
...enLocale
},
zh_CN: {
...zhLocale
},
zh_TW: {
...twLocale
}
}
export default messages

View File

@ -0,0 +1,31 @@
export default {
host: '主機名/IP地址',
dataBase: '數據庫名稱',
connection_mode: '連接方式',
oracle_sid: 'SID',
oracle_service_name: '服務名',
username: '用戶名',
password: '密碼',
port: '端口',
schema: 'Schema',
get_schema: '獲取 Schema',
charset: '字符集',
targetCharset: '目標字符集',
priority: '高級設置',
initial_pool_size: '初始連接數',
min_pool_size: '最小連接數',
max_pool_size: '最大連接數',
query_timeout: '查詢超時',
one_user_name: '請輸入用戶名',
input_a_password: '請輸入密碼',
enter_the_port: '請輸入端口',
please_choose_schema: '請選擇 Schema',
please_choose_charset: '請選擇數據庫字符集',
please_choose_targetCharset: '請選擇目標字符集',
please_input_initial_pool_size: '請輸入初始連接數',
please_input_min_pool_size: '請輸入最小連接數',
please_input_max_pool_size: '請輸入最大連接數',
please_input_query_timeout: '請輸入查詢超時',
second: '秒',
please_select: '請選擇'
}

View File

@ -0,0 +1,31 @@
export default {
host: '主机名/IP地址',
dataBase: '数据库名称',
connection_mode: '连接方式',
oracle_sid: 'SID',
oracle_service_name: '服务名',
username: '用户名',
password: '密码',
port: '端口',
schema: 'Schema',
get_schema: '获取 Schema',
charset: '字符集',
targetCharset: '目标字符集',
priority: '高级设置',
initial_pool_size: '初始连接数',
min_pool_size: '最小连接数',
max_pool_size: '最大连接数',
query_timeout: '查询超时',
one_user_name: '请输入用户名',
input_a_password: '请输入密码',
enter_the_port: '请输入端口',
please_choose_schema: '请选择 Schema',
please_choose_charset: '请选择数据库字符集',
please_choose_targetCharset: '请选择目标字符集',
please_input_initial_pool_size: '请输入初始连接数',
please_input_min_pool_size: '请输入最小连接数',
please_input_max_pool_size: '请输入最大连接数',
please_input_query_timeout: '请输入查询超时',
second: '秒',
please_select: '请选择'
}

View File

@ -0,0 +1,9 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00022 9.99975C7.56203 9.99975 7.13323 9.96523 6.71734 9.89921L6.38535 11.1382C6.33771 11.316 6.15493 11.4216 5.9771 11.3739L5.33315 11.2014C5.15533 11.1537 5.0498 10.9709 5.09745 10.7931L5.42255 9.57985C4.88013 9.39561 4.37096 9.15494 3.90491 8.86629L2.8454 9.9258C2.71522 10.056 2.50417 10.056 2.37399 9.9258L1.90259 9.4544C1.77242 9.32422 1.77242 9.11317 1.90259 8.98299L2.83565 8.04994C2.35424 7.59918 1.95209 7.0852 1.64812 6.52421C1.64492 6.51832 1.64162 6.51215 1.63823 6.50575C1.5136 6.27038 1.56023 5.97574 1.75709 5.79635C1.92051 5.64743 2.03596 5.5461 2.13639 5.44567C2.14538 5.43669 2.15521 5.42666 2.16569 5.41583C2.31108 5.2656 2.55902 5.32152 2.64417 5.51246C3.47427 7.37398 5.46211 8.66641 8.00022 8.66641C10.4321 8.66641 12.4664 7.40872 13.2829 5.68239C13.3042 5.63747 13.328 5.5809 13.3519 5.52084C13.4276 5.33064 13.6741 5.27325 13.8188 5.41801C13.9259 5.52508 14.0687 5.66784 14.2471 5.8463C14.4235 6.0227 14.4713 6.29211 14.356 6.51334C14.3279 6.56715 14.3006 6.61785 14.2774 6.65816C13.9638 7.20109 13.5572 7.69751 13.0754 8.1321L13.9263 8.98299C14.0565 9.11317 14.0565 9.32422 13.9263 9.4544L13.4549 9.9258C13.3247 10.056 13.1136 10.056 12.9835 9.9258L11.9888 8.93112C11.5521 9.19111 11.0792 9.40958 10.5779 9.57985L10.903 10.7931C10.9506 10.9709 10.8451 11.1537 10.6673 11.2014L10.0233 11.3739C9.84552 11.4216 9.66274 11.316 9.61509 11.1382L9.2831 9.89921C8.86721 9.96523 8.43842 9.99975 8.00022 9.99975Z" fill="#BBBFC4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.98994 12.333C10.1486 12.333 12.1472 10.9599 14.0001 7.99101C12.1949 5.03272 10.2008 3.66634 7.98994 3.66634C5.77984 3.66634 3.7929 5.0321 2.00009 7.99099C3.84053 10.9605 5.83206 12.333 7.98994 12.333ZM1.00172 8.59304C0.787049 8.22763 0.785596 7.77336 0.995302 7.40508C1.00277 7.39196 1.00993 7.37945 1.01672 7.36768C2.9521 4.01123 5.27627 2.33301 7.98923 2.33301C10.7133 2.33301 13.0518 4.02495 15.0049 7.40884C15.0107 7.41898 15.0168 7.42969 15.0232 7.44089C15.2208 7.7869 15.2193 8.21401 15.0172 8.55738C13.0127 11.9634 10.67 13.6663 7.98923 13.6663C5.31784 13.6663 2.98867 11.9752 1.00172 8.59304ZM8.00009 10.6663C6.52733 10.6663 5.33342 9.47243 5.33342 7.99967C5.33342 6.52692 6.52733 5.33301 8.00009 5.33301C9.47285 5.33301 10.6668 6.52692 10.6668 7.99967C10.6668 9.47243 9.47285 10.6663 8.00009 10.6663ZM8.00009 9.33301C8.73647 9.33301 9.33342 8.73605 9.33342 7.99967C9.33342 7.26329 8.73647 6.66634 8.00009 6.66634C7.26371 6.66634 6.66675 7.26329 6.66675 7.99967C6.66675 8.73605 7.26371 9.33301 8.00009 9.33301Z" fill="#BBBFC4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{isolation:isolate;}.cls-2{fill:#f2f4f5;}.cls-3{fill:#0a7be0;}.cls-4{fill:#53baf9;}.cls-5,.cls-6{fill:#a2a2ba;}.cls-6{mix-blend-mode:multiply;}.cls-7{fill:#fff;}</style></defs><title>【icon】人大金仓</title><g class="cls-1"><g id="图层_1" data-name="图层 1"><circle class="cls-2" cx="32" cy="32" r="32"/><path class="cls-3" d="M25.76,44.82l6.79-11.56H44.4V12.36A2.36,2.36,0,0,0,42,10H13.87a2.58,2.58,0,0,0-2.58,2.57V44.7A3.68,3.68,0,0,0,15,48.37H27.84Z"/><path class="cls-4" d="M25.76,44.82,27,42.73H14.11a2.83,2.83,0,0,0-2.82,2.82h0a2.83,2.83,0,0,0,2.82,2.82H27.84Z"/><polygon class="cls-5" points="33.96 54 28.57 44.82 33.96 35.64 52.71 35.64 52.71 54 33.96 54"/><polygon class="cls-6" points="33.96 54 28.57 44.82 52.71 44.75 52.71 54 33.96 54"/><polygon class="cls-7" points="20.76 13.76 20.76 20.14 16.48 22.22 20.76 24.36 20.76 30.81 24.3 30.81 24.3 26.01 34.36 30.81 34.36 27.03 24.3 22.33 34.49 17.4 34.49 13.64 24.3 18.59 24.3 13.76 20.76 13.76"/><path class="cls-7" d="M42.9,43.06c-3,0-5.5-.76-5.5-1.7v3.39c0,.93,2.47,1.69,5.5,1.69s5.5-.76,5.5-1.69V41.36c0,.94-2.46,1.7-5.5,1.7Zm0,0"/><path class="cls-7" d="M42.9,47.29c-3,0-5.5-.76-5.5-1.7V49c0,.93,2.47,1.69,5.5,1.69s5.5-.76,5.5-1.69V45.59c0,.94-2.46,1.7-5.5,1.7Z"/><path class="cls-7" d="M42.9,42.21c3,0,5.5-.76,5.5-1.69s-2.46-1.69-5.5-1.69-5.5.75-5.5,1.69,2.47,1.69,5.5,1.69Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,22 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

View File

@ -0,0 +1,33 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import Cookies from 'js-cookie'
import i18n from './de-base/lang'
import draggable from 'vuedraggable'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
Vue.config.productionTip = false
Vue.use(ElementUI, {
size: Cookies.get('size') || 'medium',
i18n: (key, value) => i18n.t(key, value)
})
Vue.component('Treeselect', Treeselect)
Vue.component('draggable', draggable)
Vue.prototype.hasDataPermission = function(pTarget, pSource) {
if (pSource && pTarget) {
return pSource.indexOf(pTarget) > -1
}
return false
}
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
i18n,
components: { App },
template: '<App/>'
})

View File

@ -0,0 +1,21 @@
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import kingbase from '@/views/kingbase'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/kingbase',
name: 'kingbase',
component: kingbase
}
]
})

View File

@ -0,0 +1,29 @@
export const compareItem = {
type: 'none', // year-yoy/month-yoy等
resultData: 'percent', // 对比差sub百分比percent等
field: '',
custom: {
field: '',
calcType: '0', // 0-增长值1-增长率
timeType: '0', // 0-固定日期1-日期区间
currentTime: '',
compareTime: '',
currentTimeRange: [],
compareTimeRange: []
}
}
export const compareYearList = [
{ name: 'year_mom', value: 'year_mom' }
]
export const compareMonthList = [
{ name: 'month_mom', value: 'month_mom' },
{ name: 'year_yoy', value: 'year_yoy' }
]
export const compareDayList = [
{ name: 'day_mom', value: 'day_mom' },
{ name: 'month_yoy', value: 'month_yoy' },
{ name: 'year_yoy', value: 'year_yoy' }
]

View File

@ -0,0 +1,15 @@
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path) || /^(http?:|mailto:|tel:)/.test(path) || path.startsWith('/api/pluginCommon/staticInfo')
}

View File

@ -0,0 +1,75 @@
<template>
<el-input
:value="value"
:placeholder="placeholder"
:type="type"
:disabled="disabled"
class="de-pwd-input"
@input="handleInput"
@change="handleChange"
>
<svg-icon
@click="handleClick"
v-if="!showPwd || buttonDisabled"
slot="suffix"
icon-class="de_pwd_invisible"
/>
<svg-icon
@click="handleClick"
v-else
slot="suffix"
icon-class="de_pwd_visible"
/>
</el-input>
</template>
<script>
export default {
name: "DePwd",
inject: {
elForm: {
default: "",
},
},
props: {
disabled: Boolean,
placeholder: String,
value: String,
},
data() {
return {
showPwd: false,
};
},
computed: {
buttonDisabled() {
return this.$options.propsData.hasOwnProperty("disabled")
? this.disabled
: (this.elForm || {}).disabled;
},
type() {
return !this.showPwd || this.buttonDisabled ? "password" : "text";
},
},
methods: {
handleClick() {
if (this.buttonDisabled) return;
this.showPwd = !this.showPwd;
},
handleInput(val) {
this.$emit("input", val);
},
handleChange(val) {
this.$emit("change", val);
},
},
};
</script>
<style lang="scss">
.de-pwd-input {
.el-input__suffix {
right: 12px;
font-size: 16px;
}
}
</style>

View File

@ -0,0 +1,202 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div>
<el-row>
<el-col>
<el-form
ref="DsForm"
:model="form"
:rules="rule"
size="small"
:disabled="disabled"
label-width="180px"
label-position="right"
>
<el-form-item :label="$t('host')" prop="configuration.host">
<el-input v-model="form.configuration.host" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('port')" prop="configuration.port">
<el-input :placeholder="$t('enter_the_port')" v-model="form.configuration.port" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('dataBase')" prop="configuration.dataBase">
<el-input v-model="form.configuration.dataBase" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('username')" prop="configuration.username">
<el-input :placeholder="$t('one_user_name')" v-model="form.configuration.username" autocomplete="off"/>
</el-form-item>
<el-form-item :label="$t('password')" prop="configuration.password">
<dePwd :placeholder="$t('input_a_password')" v-model="form.configuration.password"/>
</el-form-item>
<el-form-item class="schema-label" :label="$t('schema')">
<template slot="label">
{{ $t("schema") }}
<el-button type="text" icon="el-icon-plus" size="small" @click="getSchema()">{{ $t('get_schema') }}
</el-button>
</template>
<el-select v-model="form.configuration.schema" filterable
:placeholder="$t('please_select')"
class="de-select">
<el-option v-for="item in schemas" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
<el-form-item :label="$t('query_timeout')">
<el-input
v-model="form.configuration.queryTimeout"
autocomplete="off"
type="number"
:min="0"
>
<template slot="append">{{ $t("second") }}</template>
</el-input>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import messages from '@/de-base/lang/messages'
import dePwd from "./dePwd.vue";
export default {
name: "kingbase",
components: {dePwd},
props: {
method: String,
request: {},
response: {},
editApiItem: {
type: Boolean,
default() {
return false;
}
},
showScript: {
type: Boolean,
default: true,
},
obj: {
type: Object,
default() {
return {
configuration: {
initialPoolSize: 5,
extraParams: '',
minPoolSize: 5,
maxPoolSize: 50,
maxIdleTime: 30,
acquireIncrement: 5,
idleConnectionTestPeriod: 5,
queryTimeout: 30,
connectTimeout: 5
},
apiConfiguration: []
}
}
},
},
data() {
return {
rule: {
'configuration.host': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.port': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.dataBase': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.username': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}],
'configuration.password': [{required: true, message: this.$t('commons.required'), trigger: 'blur'}]
},
canEdit: false,
originConfiguration: {},
height: 500,
disabledNext: false,
schemas: []
}
},
computed: {
form() {
return this.obj.form
},
disabled() {
return this.obj.disabled
}
},
created() {
this.$emit('on-add-languages', messages)
},
watch: {},
methods: {
executeAxios(url, type, data, callBack) {
const param = {
url: url,
type: type,
data: data,
callBack: callBack
}
this.$emit('execute-axios', param)
},
getSchema() {
this.$refs["DsForm"].validate(valid => {
if (valid) {
const data = JSON.parse(JSON.stringify(this.form))
data.configuration = JSON.stringify(data.configuration)
this.executeAxios('/datasource/getSchema/', 'post', data, res => {
this.schemas = res.data
})
} else {
return false
}
})
},
validate() {
let status = null;
this.$refs["DsForm"].validate((val) => {
if (val) {
status = true
} else {
status = false
}
})
if (!this.form.configuration.schema) {
this.$message.error(this.$t('please_choose_schema'))
status = false
}
return status
}
}
}
</script>
<style scoped>
.ms-query {
background: #409EFF;
color: white;
height: 18px;
border-radius: 42%;
}
.ms-header {
background: #409EFF;
color: white;
height: 18px;
border-radius: 42%;
}
.request-tabs {
margin: 20px;
min-height: 200px;
}
.ms-el-link {
float: right;
margin-right: 45px;
}
</style>

View File

@ -0,0 +1,13 @@
{
"name":"kingbase-ora 数据源插件",
"free":0,
"store":"default",
"cost":0,
"category":"datasource",
"descript":"人大金仓插件,值得拥有",
"version":"1.18.0",
"creator":"DATAEASE",
"moduleName":"kingbase-backend",
"require":"1.17.0",
"dsType":"kingbase"
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dataease-extensions-datasource</artifactId>
<groupId>io.dataease</groupId>
<version>${dataease.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kingbase</artifactId>
<packaging>pom</packaging>
<modules>
<module>kingbase-frontend</module>
<module>kingbase-backend</module>
</modules>
</project>

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