diff --git a/i18n/zh_cn.properties b/i18n/zh_cn.properties index 4154eed..2010d77 100644 --- a/i18n/zh_cn.properties +++ b/i18n/zh_cn.properties @@ -110,7 +110,7 @@ Dec-Dcm_Connection_Deleted=该数据连接已被删除,无法进行操作 Dec-Dcm_Connection_Click_Connect_Database=点击连接数据库 Dec-Dcm_Connection_Read_Mode_List=以读取模式列表 Dec-Dcm_Connection_NO_Connection_Pool=无数据连接,可在数据连接管理页面添加 -Dec-Dcm_Connection_Cannot_Too_Lang=文本长度不能大于200个字符 +Dec-Dcm_Connection_Cannot_Too_Lang=文本长度不能大于{R1}个字符 Dec-Dcm_Login_Error=登录信息已失效,请重新登录 BI-Multi_Date_Quarter_End= 季度末 BI-Multi_Date_Month_Begin= 月初 @@ -300,4 +300,6 @@ BI-Basic_Million= 百万 BI-Basic_Billion= 亿 BI-Basic_Quarter= 季度 BI-Basic_No_Select= 不选 -BI-Basic_Now= 此刻 \ No newline at end of file +BI-Basic_Now= 此刻 +Dec-Dcm_Connection_Analytic_DB=阿里云AnalyticDB +Dec-Dcm_Connection_Value_Out_Range=数值超出范围 \ No newline at end of file diff --git a/package.json b/package.json index fe532bf..9cd2bb5 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@babel/core": "7.4.5", "@babel/plugin-proposal-class-properties": "^7.5.0", "@babel/plugin-proposal-decorators": "7.4.4", + "@babel/polyfill": "^7.8.3", "@babel/preset-env": "7.4.5", "@babel/preset-typescript": "7.3.3", "@types/jest": "24.0.11", @@ -66,8 +67,8 @@ "scripts": { "dev": "cross-env NODE_ENV=mock webpack-dev-server -p --progress --config=webpack/webpack.dev.js --mode development --open", "build": "webpack -p --progress --config=webpack/webpack.prod.js --mode production", - "eslint": "eslint './*.js' './**/*.js' './**/*.ts'", - "eslint-fix": "eslint './*.js' './**/*.js' './**/*.ts' --fix", + "eslint": "eslint . --ext .ts", + "eslint-fix": "eslint . --ext .ts --fix", "const": "javac -encoding UTF-8 -d constants/classes constants/*.java && java -cp constants/classes FRConstantsWriter", "i18n": "node ./lib/transform-i18n/transform-i18n.js", "test": "jest --passWithNoTests", diff --git a/private/i18n.ts b/private/i18n.ts index 77be638..369845f 100644 --- a/private/i18n.ts +++ b/private/i18n.ts @@ -109,7 +109,7 @@ export default { 'Dec-Dcm_Connection_Click_Connect_Database': '点击连接数据库', 'Dec-Dcm_Connection_Read_Mode_List': '以读取模式列表', 'Dec-Dcm_Connection_NO_Connection_Pool': '无数据连接,可在数据连接管理页面添加', - 'Dec-Dcm_Connection_Cannot_Too_Lang': '文本长度不能大于200个字符', + 'Dec-Dcm_Connection_Cannot_Too_Lang': '文本长度不能大于{R1}个字符', 'Dec-Dcm_Login_Error': '登录信息已失效,请重新登录', 'BI-Multi_Date_Quarter_End': '季度末', 'BI-Multi_Date_Month_Begin': '月初', @@ -300,4 +300,6 @@ export default { 'BI-Basic_Quarter': '季度', 'BI-Basic_No_Select': '不选', 'BI-Basic_Now': '此刻', + 'Dec-Dcm_Connection_Analytic_DB': '阿里云AnalyticDB', + 'Dec-Dcm_Connection_Value_Out_Range': '数值超出范围', }; diff --git a/src/modules/__test__/app.test.ts b/src/modules/__test__/app.test.ts index 5b8cf72..d1a205f 100644 --- a/src/modules/__test__/app.test.ts +++ b/src/modules/__test__/app.test.ts @@ -1,4 +1,4 @@ -import { connectionCanEdit } from '../app.service'; +import { connectionCanEdit, resolveUrlInfo, splitUrl, getJdbcDatabaseType } from '../app.service'; const connection = { connectionId: '', connectionType: '', @@ -6,6 +6,84 @@ const connection = { connectionData: '', }; +/** + * test_author_alan + */ +test('DEC-11030 拼接url', () => { + expect(splitUrl('localhost', '22', 'dbname', 'jdbc:pivotal:greenplum://hostname:port;dbname')).toEqual('jdbc:pivotal:greenplum://localhost:22;dbname'); +}); +/** + * test_author_alan + */ +test('BI-56355 如果数据库类型和驱动都为空,则为其他jdbc', () => { + expect(getJdbcDatabaseType('', '').databaseType).toEqual('otherJDBC'); + expect(getJdbcDatabaseType('mysql', '').databaseType).toEqual('mysql'); + expect(getJdbcDatabaseType('', 'com.mysql.jdbc.Driver').databaseType).toEqual('mysql'); +}); + +/** + * test_author_alan + */ +test('DEC-10992 数据连接名称带-', () => { + expect(resolveUrlInfo('jdbc:sqlserver://192.168.17.111:1433;databaseName=L-Pick-DAS-MengYan')).toEqual({ + host: '192.168.17.111', + port: '1433', + databaseName: 'L-Pick-DAS-MengYan', + urlInfo: '', + }); +}); + +test('解析url', () => { + expect(resolveUrlInfo('jdbc:postgresql://endpoint:port/database')).toEqual({ + host: 'endpoint', + port: '', + databaseName: 'database', + urlInfo: '', + }); + expect(resolveUrlInfo('jdbc:pivotal:greenplum://hostname:port;dbname')).toEqual({ + host: 'hostname', + port: '', + databaseName: 'dbname', + urlInfo: '', + }); + expect(resolveUrlInfo('jdbc:mysql://hostname:22/database')).toEqual({ + host: 'hostname', + port: '22', + databaseName: 'database', + 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: '', + }); +}); + +/** + * test_author_alan + */ test('BI-51537 判断数据连接是否有权限', () => { expect(connectionCanEdit({ ...connection, diff --git a/src/modules/app.constant.ts b/src/modules/app.constant.ts index ebb5253..618bdc3 100644 --- a/src/modules/app.constant.ts +++ b/src/modules/app.constant.ts @@ -1,2 +1,6 @@ export const CONSTANT_PLUGIN_TYPES = 'dec.constant.database.conf.connect.types'; BI.constant(CONSTANT_PLUGIN_TYPES, []); +/** + * 数据连接名称的最大长度 + */ +export const NAME_MAX_LENGTH = 150; diff --git a/src/modules/app.service.ts b/src/modules/app.service.ts index a7fe9be..5a06d77 100644 --- a/src/modules/app.service.ts +++ b/src/modules/app.service.ts @@ -27,9 +27,11 @@ export function getPluginWidgetEdit(plugin: string) { // 由于database可能为空,所以为了兼容平台和设计器,需要根据driver来判断数据库类型 export function getJdbcDatabaseType(database: string, driver: string): DatabaseType { + if (!database && !driver) { + return DATA_BASE_TYPES_OTHER; + } let databaseType = null; // KERNEL-1655 兼容旧版 由于旧版设计器创建的数据连接database都为other,所以要根据driber来判断数据类型 - // DEC-10872 不能过滤other,因为新版数据连接创建的其他jdbc也是other类型,会混淆,需要和后端讨论一个最佳的解决方案。 if (database && database !== 'other' && DATA_BASE_TYPES.some(item => item.databaseType === database)) { databaseType = DATA_BASE_TYPES.find(item => item.databaseType === database); } else { @@ -47,12 +49,31 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT export function resolveUrlInfo (url: string) { if (BI.isNull(url)) return {}; - const result = url.match(/^jdbc:(oracle|mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/|;DatabaseName=)([0-9a-zA-Z_\\.]+)(.*)/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) { + return { + host: greenplumUrl[4], + port: greenplumUrl[6] === 'port' ? '' : greenplumUrl[6], + databaseName: greenplumUrl[8], + urlInfo: greenplumUrl[9], + }; + } + 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) { return { host: result[5], port: result[7] === 'port' ? '' : result[7], - databaseName: result[9], + databaseName: result[9] || '', urlInfo: result[10], }; } @@ -87,7 +108,8 @@ export function splitUrl(host: string, port: string, database: string, baseUrl: } return baseUrl.replace('hostname', host).replace(':port', port ? `:${port}` : '') - .replace('database', database); + .replace('database', database) + .replace('dbname', database); } export function connectionCanEdit(connection: Connection) { diff --git a/src/modules/constants/constant.ts b/src/modules/constants/constant.ts index 863c4f7..b1843a9 100644 --- a/src/modules/constants/constant.ts +++ b/src/modules/constants/constant.ts @@ -197,7 +197,7 @@ export const DESIGN_DRIVER_TYPE = [ ]; export const DATA_BASE_TYPES = [ { - text: 'ADS', + text: BI.i18nText('Dec-Dcm_Connection_Analytic_DB'), databaseType: 'ads', driver: 'com.mysql.jdbc.Driver', url: 'jdbc:mysql://hostname:port/database', @@ -446,8 +446,8 @@ export const DATA_BASE_TYPES = [ hasSchema: false, kerberos: false, urls: { - 'com.mysql.jdbc.Driver': 'jdbc:mysql://localhost/dbname', - 'org.gjt.mm.mysql.Driver': 'jdbc:mysql://localhost/dbname', + 'com.mysql.jdbc.Driver': 'jdbc:mysql://hostname:port/database', + 'org.gjt.mm.mysql.Driver': 'jdbc:mysql://hostname:port/database', }, }, { @@ -597,7 +597,7 @@ export const DATA_BASE_TYPES = [ export const CONNECT_CHARSET = [ { - text: '自动', + text: BI.i18nText('Dec-Dcm_Connection_Form_Auto'), value: '', }, { @@ -667,6 +667,7 @@ export const DEFAULT_JDBC_POOL = { initialSize: 0, maxActive: 50, maxIdle: 10, + minIdle: 0, maxWait: 10000, testOnBorrow: true, testOnReturn: false, @@ -706,3 +707,5 @@ export const JNDI_FACTORYS = [ ]; export const PAGE_SIZE = 50; +export const INT_MAX_VALUE = 2147483647; +export const INT_MIN_VALUE = -2147483648; diff --git a/src/modules/constants/env.ts b/src/modules/constants/env.ts index 3030fbb..8ff0057 100644 --- a/src/modules/constants/env.ts +++ b/src/modules/constants/env.ts @@ -1,5 +1,6 @@ -const fineServletURL = Dec.fineServletURL; -export const ReqPrefix = `${fineServletURL}/v10/config/connection`; +export const fineServletURL = Dec.fineServletURL; +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 PluginImgPrefix = `${fineServletURL}/resources?path=`; diff --git a/src/modules/crud/crud.service.ts b/src/modules/crud/crud.service.ts index 483b918..19297e7 100644 --- a/src/modules/crud/crud.service.ts +++ b/src/modules/crud/crud.service.ts @@ -1,121 +1,38 @@ -import 'es6-promise/auto'; -import axios, { AxiosResponse, AxiosError } from 'axios'; -import { CrudReqOpts, CrudParams, ResultType } from './crud.typings.d'; -import { ReqPrefix, errorCode } from '../constants/env'; -const defaultHeaders = { - 'Content-Type': 'application/json', - 'X-Requested-With': 'XMLHttpRequest', -}; +import { ResultType } from './crud.typings.d'; +import { ReqPath } from '../constants/env'; -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; +function getFullUrl(url: string) { + return url ? `${ReqPath}/${url}` : ReqPath; } -export async function request(reqOptions: CrudReqOpts = {}): Promise { - 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): Promise { + return new Promise(resolve => { + Dec.reqGet(getFullUrl(url), '', re => { + resolve(re); }); -} - -export function requestGet(url: string, data?: any, params: CrudParams = {}) { - const timeStamp = new Date().getTime(); - - return request({ - 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 requestPost(url: string, data = {}): Promise { + return new Promise(resolve => { + Dec.reqPost(getFullUrl(url), data, re => { + resolve(re); + }); }); } export function requestDelete(url: string, data = {}) { - return request({ - url, - type: 'DELETE', - data, + return new Promise(resolve => { + Dec.reqDelete(getFullUrl(url), data, re => { + resolve(re); + }); }); } -export function requestPut(url: string, data = {}, params: CrudParams = {}) { - return request({ - url, - type: 'PUT', - data, - params, +export function requestPut(url: string, data = {}) { + return new Promise(resolve => { + Dec.reqPut(getFullUrl(url), data, re => { + resolve(re); + }); }); } diff --git a/src/modules/crud/decision.api.ts b/src/modules/crud/decision.api.ts index 55096b1..d046519 100644 --- a/src/modules/crud/decision.api.ts +++ b/src/modules/crud/decision.api.ts @@ -96,7 +96,7 @@ export class DecisionApi implements Api { private sendEditStatusEvent(name: string, type: string): Promise { return new Promise(resolve => { if (Dec && Dec.socket.connected) { - Dec.socket.emit(type, BI.encode(name), (re: any) => { + Dec.socketEmit(type, BI.encode(name), (re: any) => { resolve(re); }); } else { diff --git a/src/modules/pages/connection/list/list_item/list_item.model.ts b/src/modules/pages/connection/list/list_item/list_item.model.ts index 1e5ab05..efc02ca 100644 --- a/src/modules/pages/connection/list/list_item/list_item.model.ts +++ b/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 { ApiFactory } from '../../../../crud/apiFactory'; import { ResultType } from '../../../../crud/crud.typings'; +import { getChartLength } from '../../../../app.service'; +import { NAME_MAX_LENGTH } from '../../../../app.constant'; const api = new ApiFactory().create(); 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' }); }); } + 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); if (hasNamed && oldName !== newName) { return new Promise(resolve => { diff --git a/src/modules/pages/database/database.ts b/src/modules/pages/database/database.ts index a13921e..e7fa658 100644 --- a/src/modules/pages/database/database.ts +++ b/src/modules/pages/database/database.ts @@ -140,19 +140,23 @@ export class Datebase extends BI.Widget { items: [ { el: { - type: VerticalAdapt, + type: Htape, hgap: 20, invisible: true, items: [ { type: Label, + width: 70, + textAlign: 'left', text: BI.i18nText('Dec-Dcm_Connection_Type_Filter'), + title: BI.i18nText('Dec-Dcm_Connection_Type_Filter'), }, { type: MultiSelectItem, width: 80, selected: this.model.isInternal, text: BI.i18nText('Dec-Dcm_Connection_Support_Inner'), + title: BI.i18nText('Dec-Dcm_Connection_Support_Inner'), ref: (_ref: any) => { this.internalWidget = _ref; }, @@ -165,6 +169,7 @@ export class Datebase extends BI.Widget { width: 80, selected: this.model.isPlugin, text: BI.i18nText('Dec-Dcm_Connection_Support_Plugin'), + title: BI.i18nText('Dec-Dcm_Connection_Support_Plugin'), ref: (_ref: any) => { this.pluginWidget = _ref; }, @@ -175,14 +180,16 @@ export class Datebase extends BI.Widget { { type: Label, cls: 'bi-tips', + textAlign: 'left', text: BI.i18nText('Dec-Dcm_Connection_Filter_Tip'), + title: BI.i18nText('Dec-Dcm_Connection_Filter_Tip'), }, ], ref: (_ref: any) => { this.typeFilterWidget = _ref; }, }, - height: 20, + height: 24, }, { type: ButtonGroup, diff --git a/src/modules/pages/maintain/forms/components/form.jdbc.ts b/src/modules/pages/maintain/forms/components/form.jdbc.ts index 637e1bd..3af4cf6 100644 --- a/src/modules/pages/maintain/forms/components/form.jdbc.ts +++ b/src/modules/pages/maintain/forms/components/form.jdbc.ts @@ -4,7 +4,7 @@ import { CollapseXtype, EVENT_CHANGE } from 'src/modules/components/collapse/col import { FormItemXtype } from '../../components/form_item/form_item'; import { Connection, ConnectionJDBC, ConnectionPoolJDBC } from 'src/modules/crud/crud.typings'; import { connectionType } from '@constants/env'; -import { CONNECT_CHARSET, CONNECTION_LAYOUT } from '@constants/constant'; +import { CONNECT_CHARSET, CONNECTION_LAYOUT, INT_MAX_VALUE, INT_MIN_VALUE } from '@constants/constant'; import { getAllDatabaseTypes, getJdbcDatabaseType, resolveUrlInfo, splitUrl } from '../../../../app.service'; import { TextCheckerXtype } from '../../../../components/text_checker/text_checker'; export const FormJdbcXtype = 'dec.dcm.maintain.form.jdbc'; @@ -62,6 +62,12 @@ export class FormJdbc extends BI.Widget { const { host, port, databaseName } = resolveUrlInfo(url); const { hgap, vgap } = CONNECTION_LAYOUT; + const valueRangeConfig = { + errorText: BI.i18nText('Dec-Dcm_Connection_Value_Out_Range'), + checker: (value: string) => this.checkValueRange(value), + autoFix: true, + }; + return { type: Vertical, hgap, @@ -98,13 +104,12 @@ export class FormJdbc extends BI.Widget { const value = this.form.driver.getValue(); const connectionData = this.options.formData.connectionData as ConnectionJDBC; const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); - if (connectionType.urls) { - this.form.url.setValue(connectionType.urls[value]); - const urlInfo = resolveUrlInfo(connectionType.urls[value]); - this.form.host.setValue(urlInfo.host); - this.form.database.setValue(urlInfo.databaseName); - this.form.port.setValue(urlInfo.port); - } + const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; + this.form.url.setValue(url); + const urlInfo = resolveUrlInfo(url); + this.form.host.setValue(urlInfo.host); + this.form.database.setValue(urlInfo.databaseName); + this.form.port.setValue(urlInfo.port); }, }], }], @@ -162,7 +167,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.port = _ref; }, @@ -375,6 +380,7 @@ export class FormJdbc extends BI.Widget { }, { type: CollapseXtype, + bgap: -15, width: 70, name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Advanced_Setting'), listeners: [ @@ -397,6 +403,7 @@ export class FormJdbc extends BI.Widget { items: [ { type: FormItemXtype, + tgap: 15, name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'), forms: [{ type: TextCheckerXtype, @@ -407,7 +414,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'), ref: (_ref: any) => { this.form.initialSize = _ref; @@ -427,7 +434,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.maxActive = _ref; }, @@ -446,7 +453,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.maxIdle = _ref; }, @@ -465,7 +472,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.minIdle = _ref; }, @@ -485,7 +492,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.maxWait = _ref; }, @@ -573,7 +580,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Number'), checker: (value: string) => this.checkNumber(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.timeBetweenEvictionRunsMillis = _ref; }, @@ -599,7 +606,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.numTestsPerEvictionRun = _ref; }, @@ -619,7 +626,7 @@ export class FormJdbc extends BI.Widget { errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'), checker: (value: string) => this.checkInteger(value), autoFix: true, - }], + }, valueRangeConfig], ref: (_ref: any) => { this.form.minEvictableIdleTimeMillis = _ref; }, @@ -650,6 +657,10 @@ export class FormJdbc extends BI.Widget { return /^[(\-|\+)?\d]+$/.test(value); } + private checkValueRange(value: string) { + return parseInt(value, 0) <= INT_MAX_VALUE && parseInt(value, 0) >= INT_MIN_VALUE; + } + private getDrivers() { const connectionData = this.options.formData.connectionData as ConnectionJDBC; const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); @@ -692,11 +703,13 @@ export class FormJdbc extends BI.Widget { } private onHostPortChange(databaseType) { - const { url = '' } = databaseType; + const { urls, url } = databaseType; + const driver = this.form.driver.getValue(); + const selectUrl = BI.get(urls, driver) || url; const host = this.form.host.getValue(); const port = this.form.port.getValue(); const database = this.form.database.getValue(); - this.form.url.setValue(splitUrl(host, port, database, url)); + this.form.url.setValue(splitUrl(host, port, database, selectUrl)); } public setSchemas(schemas: string[]) { @@ -729,7 +742,7 @@ export class FormJdbc extends BI.Widget { driver: this.form.driver.getValue(), url: this.form.url.getValue(), user: this.form.user.getValue(), - password: this.oldPassword === this.form.password.getValue() ? this.oldPassword : BI.encode(this.form.password.getValue()), + password: this.oldPassword === this.form.password.getValue() ? this.oldPassword : BI.Providers.getProvider('dec.provider.cipher').getCipher(this.form.password.getValue()), queryType: '', newCharsetName: originalCharsetName ? 'gbk' : '', // 后台要求,originalCharsetName不为空时,newCharsetName为gbk originalCharsetName, diff --git a/src/modules/pages/maintain/forms/form.ts b/src/modules/pages/maintain/forms/form.ts index 34fa0f2..6eec4d3 100644 --- a/src/modules/pages/maintain/forms/form.ts +++ b/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 { DEFAULT_JNDI_DATA, DEFAULT_JDBC_POOL, DATEBASE_FILTER_TYPE } from '@constants/constant'; import { getJdbcDatabaseType, getChartLength } from '../../../app.service'; +import { NAME_MAX_LENGTH } from '../../../app.constant'; export const MaintainFormXtype = 'dec.dcm.maintain.form'; @shortcut(MaintainFormXtype) @store(MaintainFormModelXtype) @@ -186,8 +187,8 @@ export class MaintainForm extends BI.Widget { return false; } } - if (getChartLength(value.connectionName) > 200) { - this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang')); + if (getChartLength(value.connectionName) > NAME_MAX_LENGTH) { + this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH)); return false; } @@ -220,8 +221,8 @@ export class MaintainForm extends BI.Widget { return; } - if (getChartLength(formValue.connectionName) > 200) { - this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang')); + if (getChartLength(formValue.connectionName) > NAME_MAX_LENGTH) { + this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH)); return false; } diff --git a/src/request.ts b/src/request.ts new file mode 100644 index 0000000..b7f4d9a --- /dev/null +++ b/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 { + 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)); +}; diff --git a/types/globals.d.ts b/types/globals.d.ts index ea354bf..e761929 100644 --- a/types/globals.d.ts +++ b/types/globals.d.ts @@ -5,4 +5,16 @@ interface Obj { declare let BI: Obj & import('fineui')._BI; declare const Fix: Obj; declare const DecCst: Obj; -declare const Dec: Obj; \ No newline at end of file +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; +}; \ No newline at end of file diff --git a/webpack/webpack.dev.js b/webpack/webpack.dev.js index f7e3bd1..2c6e1ab 100644 --- a/webpack/webpack.dev.js +++ b/webpack/webpack.dev.js @@ -36,7 +36,7 @@ chokidar module.exports = merge(common, { devtool: 'eval-source-map', entry: { - show: ['./src/i18n.ts', './src/index.ts'], + show: ['babel-polyfill', './src/i18n.ts', './src/request.ts', './src/index.ts'], }, output: { path: dirs.DEST, diff --git a/yarn.lock b/yarn.lock index bb642bb..e41649b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -606,10 +606,10 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/polyfill@7.4.4": - version "7.4.4" - resolved "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz#78801cf3dbe657844eeabf31c1cae3828051e893" - integrity sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg== +"@babel/polyfill@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.3.tgz#2333fc2144a542a7c07da39502ceeeb3abe4debd" + integrity sha512-0QEgn2zkCzqGIkSWWAEmvxD7e00Nm9asTtQvi7HdlYvMhjy/J38V/1Y9ode0zEJeIuxAI0uftiAzqc7nVeWUGg== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.2" @@ -3054,11 +3054,16 @@ core-js-compat@^3.1.1: browserslist "^4.6.6" semver "^6.3.0" -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.5.0: version "2.6.9" resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== +core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"