Browse Source

Merge pull request #1 in ~ABBY/decision-webui-dcm from final/10.0 to persist/10.0

* commit '4fb0ec3fd39736c92e83e75f71a76dba9909f0bd':
  fix: 修改i18n的写法
  fix: DEC-11815 修改数据连接名称的长度限制
  fix: 修改写法
  fix: 修复url为空时地址以/结尾的bug
  fix: DEC-11797 改用dec中自带的http请求方法
  fix: DEC-11782 oracle数据连接url端口号和数据库之间可能是/或:
  fix: 更新数据连接解析
  fix: 加一下国际化
  DEC-11528 feat: ADS数据库改为阿里云AnalyticDB
qufenxi
Abby 5 years ago
parent
commit
76aebbb7b5
  1. 3
      i18n/zh_cn.properties
  2. 3
      private/i18n.ts
  3. 27
      src/modules/__test__/app.test.ts
  4. 4
      src/modules/app.constant.ts
  5. 16
      src/modules/app.service.ts
  6. 2
      src/modules/constants/constant.ts
  7. 5
      src/modules/constants/env.ts
  8. 125
      src/modules/crud/crud.service.ts
  9. 7
      src/modules/pages/connection/list/list_item/list_item.model.ts
  10. 9
      src/modules/pages/maintain/forms/form.ts
  11. 118
      src/request.ts
  12. 14
      types/globals.d.ts
  13. 2
      webpack/webpack.dev.js

3
i18n/zh_cn.properties

@ -110,7 +110,7 @@ Dec-Dcm_Connection_Deleted=该数据连接已被删除,无法进行操作
Dec-Dcm_Connection_Click_Connect_Database=点击连接数据库 Dec-Dcm_Connection_Click_Connect_Database=点击连接数据库
Dec-Dcm_Connection_Read_Mode_List=以读取模式列表 Dec-Dcm_Connection_Read_Mode_List=以读取模式列表
Dec-Dcm_Connection_NO_Connection_Pool=无数据连接,可在数据连接管理页面添加 Dec-Dcm_Connection_NO_Connection_Pool=无数据连接,可在数据连接管理页面添加
Dec-Dcm_Connection_Cannot_Too_Lang=文本长度不能大于200个字符 Dec-Dcm_Connection_Cannot_Too_Lang=文本长度不能大于{R1}个字符
Dec-Dcm_Login_Error=登录信息已失效,请重新登录 Dec-Dcm_Login_Error=登录信息已失效,请重新登录
BI-Multi_Date_Quarter_End= 季度末 BI-Multi_Date_Quarter_End= 季度末
BI-Multi_Date_Month_Begin= 月初 BI-Multi_Date_Month_Begin= 月初
@ -301,3 +301,4 @@ BI-Basic_Billion= 亿
BI-Basic_Quarter= 季度 BI-Basic_Quarter= 季度
BI-Basic_No_Select= 不选 BI-Basic_No_Select= 不选
BI-Basic_Now= 此刻 BI-Basic_Now= 此刻
Dec-Dcm_Connection_Analytic_DB=阿里云AnalyticDB

3
private/i18n.ts

@ -109,7 +109,7 @@ export default {
'Dec-Dcm_Connection_Click_Connect_Database': '点击连接数据库', 'Dec-Dcm_Connection_Click_Connect_Database': '点击连接数据库',
'Dec-Dcm_Connection_Read_Mode_List': '以读取模式列表', 'Dec-Dcm_Connection_Read_Mode_List': '以读取模式列表',
'Dec-Dcm_Connection_NO_Connection_Pool': '无数据连接,可在数据连接管理页面添加', 'Dec-Dcm_Connection_NO_Connection_Pool': '无数据连接,可在数据连接管理页面添加',
'Dec-Dcm_Connection_Cannot_Too_Lang': '文本长度不能大于200个字符', 'Dec-Dcm_Connection_Cannot_Too_Lang': '文本长度不能大于{R1}个字符',
'Dec-Dcm_Login_Error': '登录信息已失效,请重新登录', 'Dec-Dcm_Login_Error': '登录信息已失效,请重新登录',
'BI-Multi_Date_Quarter_End': '季度末', 'BI-Multi_Date_Quarter_End': '季度末',
'BI-Multi_Date_Month_Begin': '月初', 'BI-Multi_Date_Month_Begin': '月初',
@ -300,4 +300,5 @@ export default {
'BI-Basic_Quarter': '季度', 'BI-Basic_Quarter': '季度',
'BI-Basic_No_Select': '不选', 'BI-Basic_No_Select': '不选',
'BI-Basic_Now': '此刻', 'BI-Basic_Now': '此刻',
'Dec-Dcm_Connection_Analytic_DB': '阿里云AnalyticDB',
}; };

27
src/modules/__test__/app.test.ts

@ -52,6 +52,33 @@ test('解析url', () => {
databaseName: 'database', databaseName: 'database',
urlInfo: '', urlInfo: '',
}); });
expect(resolveUrlInfo('jdbc:sqlserver://hostname:port;databaseName=database')).toEqual({
host: 'hostname',
port: '',
databaseName: 'database',
urlInfo: '',
});
expect(resolveUrlInfo('jdbc:oracle:thin:@192.168.5.143:1521/orcl')).toEqual({
host: '192.168.5.143',
port: '1521',
databaseName: 'orcl',
urlInfo: '',
});
expect(resolveUrlInfo('jdbc:oracle:thin:@192.168.5.143:1521:orcl')).toEqual({
host: '192.168.5.143',
port: '1521',
databaseName: 'orcl',
urlInfo: '',
});
});
test('数据库可能为空', () => {
expect(resolveUrlInfo('jdbc:mysql://secure.finedevelop.com:62306/')).toEqual({
host: 'secure.finedevelop.com',
port: '62306',
databaseName: '',
urlInfo: '',
});
}); });
/** /**

4
src/modules/app.constant.ts

@ -1,2 +1,6 @@
export const CONSTANT_PLUGIN_TYPES = 'dec.constant.database.conf.connect.types'; export const CONSTANT_PLUGIN_TYPES = 'dec.constant.database.conf.connect.types';
BI.constant(CONSTANT_PLUGIN_TYPES, []); BI.constant(CONSTANT_PLUGIN_TYPES, []);
/**
*
*/
export const NAME_MAX_LENGTH = 150;

16
src/modules/app.service.ts

@ -49,7 +49,17 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT
export function resolveUrlInfo (url: string) { export function resolveUrlInfo (url: string) {
if (BI.isNull(url)) return {}; if (BI.isNull(url)) return {};
const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/|;)([^]+)(.*)/i); const oracleUlr = url.match(/^jdbc:(oracle):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/)([^]+)(.*)/i);
if (oracleUlr) {
return {
host: oracleUlr[5],
port: oracleUlr[7] === 'port' ? '' : oracleUlr[7],
databaseName: oracleUlr[9],
urlInfo: oracleUlr[10],
};
}
const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;)([^]+)(.*)/i);
if (greenplumUrl) { if (greenplumUrl) {
return { return {
host: greenplumUrl[4], host: greenplumUrl[4],
@ -58,12 +68,12 @@ export function resolveUrlInfo (url: string) {
urlInfo: greenplumUrl[9], urlInfo: greenplumUrl[9],
}; };
} }
const result = url.match(/^jdbc:(oracle|mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/|;DatabaseName=)([^]+)(.*)/i); const result = url.match(/^jdbc:(mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)?(.*)/i);
if (result) { if (result) {
return { return {
host: result[5], host: result[5],
port: result[7] === 'port' ? '' : result[7], port: result[7] === 'port' ? '' : result[7],
databaseName: result[9], databaseName: result[9] || '',
urlInfo: result[10], urlInfo: result[10],
}; };
} }

2
src/modules/constants/constant.ts

@ -197,7 +197,7 @@ export const DESIGN_DRIVER_TYPE = [
]; ];
export const DATA_BASE_TYPES = [ export const DATA_BASE_TYPES = [
{ {
text: 'ADS', text: BI.i18nText('Dec-Dcm_Connection_Analytic_DB'),
databaseType: 'ads', databaseType: 'ads',
driver: 'com.mysql.jdbc.Driver', driver: 'com.mysql.jdbc.Driver',
url: 'jdbc:mysql://hostname:port/database', url: 'jdbc:mysql://hostname:port/database',

5
src/modules/constants/env.ts

@ -1,5 +1,6 @@
const fineServletURL = Dec.fineServletURL; export const fineServletURL = Dec.fineServletURL;
export const ReqPrefix = `${fineServletURL}/v10/config/connection`; export const ReqPath = '/v10/config/connection';
export const ReqPrefix = `${fineServletURL}${ReqPath}`;
export const ImgPrefix = `${fineServletURL}/resources?path=/com/fr/web/resources/dist/images/2x/icon/database/`; export const ImgPrefix = `${fineServletURL}/resources?path=/com/fr/web/resources/dist/images/2x/icon/database/`;
export const PluginImgPrefix = `${fineServletURL}/resources?path=`; export const PluginImgPrefix = `${fineServletURL}/resources?path=`;

125
src/modules/crud/crud.service.ts

@ -1,121 +1,38 @@
import 'es6-promise/auto'; import { ResultType } from './crud.typings.d';
import axios, { AxiosResponse, AxiosError } from 'axios'; import { ReqPath } from '../constants/env';
import { CrudReqOpts, CrudParams, ResultType } from './crud.typings.d';
import { ReqPrefix, errorCode } from '../constants/env';
const defaultHeaders = {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
};
export function paramsSerializer(params: { [key: string]: any }) { function getFullUrl(url: string) {
return Object.keys(params || {}) return url ? `${ReqPath}/${url}` : ReqPath;
.map(paramKey => {
const paramValue = params[paramKey];
let value = '';
if (BI.isObject(paramValue)) {
value = encodeURIComponent(JSON.stringify(paramValue));
} else {
value = paramValue;
}
return BI.isNull(value) ? '' : `${paramKey}=${value}`;
})
.filter(v => v !== '')
.join('&');
} }
function getCookieByName(name: string):string {
let value = null;
const regExpName = new RegExp(name);
document.cookie.split(';').forEach((item: string) => {
if (item.match(regExpName)) {
value = item.split(`${name}=`)[1];
return false; export function requestGet(url: string, data?: any): Promise<ResultType> {
} return new Promise(resolve => {
Dec.reqGet(getFullUrl(url), '', re => {
resolve(re);
}); });
return value;
}
function checkStatus(response: AxiosResponse) {
const status = response.status;
const noLoginErr = [errorCode.LOGIN_INFO_ERROR, errorCode.LOGIN_INFO_NOT_AVAILABLE, errorCode.TIMEOUT];
const resData = status === 200
? typeof response.data === 'string'
? BI.jsonDecode(response.data)
: response.data
: {};
if (noLoginErr.includes(BI.get(resData, 'errorCode'))) {
BI.Msg.alert(BI.i18nText('BI-Basic_Prompt'), BI.i18nText('Dec-Dcm_Login_Error'), () => {
window.location.reload(true);
});
return new Promise(() => {});
}
return resData;
}
export async function request(reqOptions: CrudReqOpts = {}): Promise<ResultType> {
const { url, type, headers, data, params } = reqOptions;
return axios
.request({
url,
baseURL: ReqPrefix,
method: type,
headers: {
...defaultHeaders,
...headers,
Authorization: `Bearer ${getCookieByName('fine_auth_token')}`,
'Content-Type': 'application/json;charset=UTF-8',
},
params,
paramsSerializer,
data,
})
.then(checkStatus)
.catch((error: AxiosError) => {
console.log(error);
}); });
} }
export function requestGet(url: string, data?: any, params: CrudParams = {}) { export function requestPost(url: string, data = {}): Promise<ResultType> {
const timeStamp = new Date().getTime(); return new Promise(resolve => {
Dec.reqPost(getFullUrl(url), data, re => {
return request({ resolve(re);
url: url.includes('?') ? `${url}&_=${timeStamp}` : `${url}?_=${timeStamp}`,
type: 'GET',
data,
params,
}); });
}
export function requestPost(url: string, data = {}, params: CrudParams = {}) {
return request({
url,
type: 'POST',
data,
params,
}); });
} }
export function requestDelete(url: string, data = {}) { export function requestDelete(url: string, data = {}) {
return request({ return new Promise(resolve => {
url, Dec.reqDelete(getFullUrl(url), data, re => {
type: 'DELETE', resolve(re);
data, });
}); });
} }
export function requestPut(url: string, data = {}, params: CrudParams = {}) { export function requestPut(url: string, data = {}) {
return request({ return new Promise(resolve => {
url, Dec.reqPut(getFullUrl(url), data, re => {
type: 'PUT', resolve(re);
data, });
params,
}); });
} }

7
src/modules/pages/connection/list/list_item/list_item.model.ts

@ -2,6 +2,8 @@ import { model, Model } from '@core/core';
import { AppModel } from '../../../../app.model'; import { AppModel } from '../../../../app.model';
import { ApiFactory } from '../../../../crud/apiFactory'; import { ApiFactory } from '../../../../crud/apiFactory';
import { ResultType } from '../../../../crud/crud.typings'; import { ResultType } from '../../../../crud/crud.typings';
import { getChartLength } from '../../../../app.service';
import { NAME_MAX_LENGTH } from '../../../../app.constant';
const api = new ApiFactory().create(); const api = new ApiFactory().create();
export const ListItemModelXtype = 'dec.dcm.model.connection.list_item'; export const ListItemModelXtype = 'dec.dcm.model.connection.list_item';
@ -63,6 +65,11 @@ export class ListItemModel extends Model<{
resolve({ errorCode: '1', errorMsg: 'Dec-Dcm_Connection_ConnectionName_Cannt_Null' }); resolve({ errorCode: '1', errorMsg: 'Dec-Dcm_Connection_ConnectionName_Cannt_Null' });
}); });
} }
if (getChartLength(newName) > NAME_MAX_LENGTH) {
return new Promise(resolve => {
resolve({ errorCode: '1', errorMsg: BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH) });
});
}
const hasNamed = this.model.connections.some(item => item.connectionName === newName); const hasNamed = this.model.connections.some(item => item.connectionName === newName);
if (hasNamed && oldName !== newName) { if (hasNamed && oldName !== newName) {
return new Promise(resolve => { return new Promise(resolve => {

9
src/modules/pages/maintain/forms/form.ts

@ -7,6 +7,7 @@ import { connectionType, errorCode } from '@constants/env';
import { ConnectionJDBC, Connection, ResultType } from 'src/modules/crud/crud.typings'; import { ConnectionJDBC, Connection, ResultType } from 'src/modules/crud/crud.typings';
import { DEFAULT_JNDI_DATA, DEFAULT_JDBC_POOL, DATEBASE_FILTER_TYPE } from '@constants/constant'; import { DEFAULT_JNDI_DATA, DEFAULT_JDBC_POOL, DATEBASE_FILTER_TYPE } from '@constants/constant';
import { getJdbcDatabaseType, getChartLength } from '../../../app.service'; import { getJdbcDatabaseType, getChartLength } from '../../../app.service';
import { NAME_MAX_LENGTH } from '../../../app.constant';
export const MaintainFormXtype = 'dec.dcm.maintain.form'; export const MaintainFormXtype = 'dec.dcm.maintain.form';
@shortcut(MaintainFormXtype) @shortcut(MaintainFormXtype)
@store(MaintainFormModelXtype) @store(MaintainFormModelXtype)
@ -186,8 +187,8 @@ export class MaintainForm extends BI.Widget {
return false; return false;
} }
} }
if (getChartLength(value.connectionName) > 200) { if (getChartLength(value.connectionName) > NAME_MAX_LENGTH) {
this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang')); this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH));
return false; return false;
} }
@ -220,8 +221,8 @@ export class MaintainForm extends BI.Widget {
return; return;
} }
if (getChartLength(formValue.connectionName) > 200) { if (getChartLength(formValue.connectionName) > NAME_MAX_LENGTH) {
this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang')); this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH));
return false; return false;
} }

118
src/request.ts

@ -0,0 +1,118 @@
import 'es6-promise/auto';
import axios, { AxiosResponse, AxiosError } from 'axios';
import { CrudReqOpts, ResultType } from './modules/crud/crud.typings';
import { fineServletURL, errorCode } from './modules/constants/env';
const defaultHeaders = {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
};
export function paramsSerializer(params: { [key: string]: any }) {
return Object.keys(params || {})
.map(paramKey => {
const paramValue = params[paramKey];
let value = '';
if (BI.isObject(paramValue)) {
value = encodeURIComponent(JSON.stringify(paramValue));
} else {
value = paramValue;
}
return BI.isNull(value) ? '' : `${paramKey}=${value}`;
})
.filter(v => v !== '')
.join('&');
}
function getCookieByName(name: string):string {
let value = null;
const regExpName = new RegExp(name);
document.cookie.split(';').forEach((item: string) => {
if (item.match(regExpName)) {
value = item.split(`${name}=`)[1];
return false;
}
});
return value;
}
function checkStatus(response: AxiosResponse) {
const status = response.status;
const noLoginErr = [errorCode.LOGIN_INFO_ERROR, errorCode.LOGIN_INFO_NOT_AVAILABLE, errorCode.TIMEOUT];
const resData = status === 200
? typeof response.data === 'string'
? BI.jsonDecode(response.data)
: response.data
: {};
if (noLoginErr.includes(BI.get(resData, 'errorCode'))) {
BI.Msg.alert(BI.i18nText('BI-Basic_Prompt'), BI.i18nText('Dec-Dcm_Login_Error'), () => {
window.location.reload(true);
});
return new Promise(() => {});
}
return resData;
}
export async function request(reqOptions: CrudReqOpts = {}): Promise<ResultType> {
const { url, type, headers, data, params } = reqOptions;
return axios
.request({
url,
baseURL: fineServletURL,
method: type,
headers: {
...defaultHeaders,
...headers,
Authorization: `Bearer ${getCookieByName('fine_auth_token')}`,
'Content-Type': 'application/json;charset=UTF-8',
},
params,
paramsSerializer,
data,
})
.then(checkStatus)
.catch((error: AxiosError) => {
console.log(error);
});
}
Dec.reqGet = (url: string, data: any, callback: (re: any) => void) => {
const timeStamp = new Date().getTime();
request({
url: url.includes('?') ? `${url}&_=${timeStamp}` : `${url}?_=${timeStamp}`,
type: 'GET',
data,
}).then(re => callback(re));
};
Dec.reqPost = (url: string, data: any, callback: (re: any) => void) => {
request({
url,
type: 'POST',
data,
}).then(re => callback(re));
};
Dec.reqDelete = (url: string, data: any, callback: (re: any) => void) => {
request({
url,
type: 'DELETE',
data,
}).then(re => callback(re));
};
Dec.reqPut = (url: string, data: any, callback: (re: any) => void) => {
request({
url,
type: 'PUT',
data,
}).then(re => callback(re));
};

14
types/globals.d.ts vendored

@ -5,4 +5,16 @@ interface Obj {
declare let BI: Obj & import('fineui')._BI; declare let BI: Obj & import('fineui')._BI;
declare const Fix: Obj; declare const Fix: Obj;
declare const DecCst: Obj; declare const DecCst: Obj;
declare const Dec: Obj; declare const Dec: {
fineServletURL: string;
socket: {
connected: boolean;
};
personal: {
username: string;
};
reqGet: (url: string, data: any, callback: (re: any) => void) => void;
reqPost: (url: string, data: any, callback: (re: any) => void) => void;
reqPut: (url: string, data: any, callback: (re: any) => void) => void;
reqDelete: (url: string, data: any, callback: (re: any) => void) => void;
};

2
webpack/webpack.dev.js

@ -36,7 +36,7 @@ chokidar
module.exports = merge(common, { module.exports = merge(common, {
devtool: 'eval-source-map', devtool: 'eval-source-map',
entry: { entry: {
show: ['./src/i18n.ts', './src/index.ts'], show: ['./src/i18n.ts', './src/request.ts', './src/index.ts'],
}, },
output: { output: {
path: dirs.DEST, path: dirs.DEST,

Loading…
Cancel
Save