diff --git a/src/modules/crud/api.ts b/src/modules/crud/api.ts index 1d917b8..12d4f0c 100644 --- a/src/modules/crud/api.ts +++ b/src/modules/crud/api.ts @@ -52,6 +52,11 @@ export interface Api { */ getConnectionPool(name: string): Promise<{ data?: ConnectionPoolType }>; + /** + * 获取自定义驱动列表 + */ + getSimpleDriverList(): Promise<{ data?: any[] }>; + /** * 获取连接状态 * @param name diff --git a/src/modules/crud/decision.api.ts b/src/modules/crud/decision.api.ts index a15cd14..7301526 100644 --- a/src/modules/crud/decision.api.ts +++ b/src/modules/crud/decision.api.ts @@ -52,6 +52,14 @@ export class DecisionApi implements Api { return requestGet(`pool/info?connectionName=${encodeURIComponent(name)}`, {}); } + getSimpleDriverList(): Promise<{ data: any[] }> { + return new Promise(resolve => { + Dec.reqGet('/v10/drivers/simple/list', '', re => { + resolve(re); + }); + }); + } + getConnectionStatus(name: string): Promise { return this.sendEditStatusEvent(name, editStatusEvent.OPEN) .then(re => { diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.model.ts b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts new file mode 100644 index 0000000..77077ab --- /dev/null +++ b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts @@ -0,0 +1,119 @@ +import { model, Model } from '@core/core'; +import { ConnectionJDBC } from '../../../../crud/crud.typings'; +import { getJdbcDatabaseType } from '../../../../app.service'; +import { ApiFactory } from '../../../../crud/apiFactory'; + +const api = new ApiFactory().create(); + +@model() +export class DriverSelectorModel extends Model { + static xtype = 'dec.dcm.model.maintain.form.jdbc.driver_selector'; + + state = () => { + const defaultDrivers = this.getDrivers(); + const [driverSource, selectedDriver] = this.resolveSelectedDriverType(); + + return { + defaultDrivers, + driverSource, + selectedDriverType: driverSource === '' ? 'default' : 'custom', + customDrivers: [], + defaultDriver: { + driver: driverSource === '' ? selectedDriver : '', + }, + customDriver: { + driver: driverSource !== '' ? selectedDriver : '', + text: driverSource !== '' ? `${this.options.driver} (${driverSource})` : '', + }, + }; + }; + + computed = { + driverClassItems: () => this.model.customDrivers.map(driver => { + return { + text: `${driver.driverClass} (${driver.name})`, + value: driver.driverClass, + }; + }), + + driverTypeComboValue: () => this.model.driverSource === '' ? 'default' : 'custom', + + driverManageEntryVisible: () => this.model.selectedDriverType === 'custom' && BI.Services.getService('dec.service.global').isAdmin(), + }; + + actions = { + initDriverClassList: cb => { + + api.getSimpleDriverList().then(res => { + this.model.customDrivers = res.data; + cb(); + }); + }, + + changeDefaultDriver: driver => { + this.model.defaultDriver.driver = driver; + this.model.driverSource = ''; + }, + + changeCustomDriver: driver => { + this.model.customDriver.driver = driver; + + + this.model.customDrivers.some(customDriver => { + if (customDriver.driverClass === driver) { + this.model.driverSource = customDriver.name; + this.model.customDriver.text = `${driver} (${customDriver.name})`; + + return true; + } + + return false; + }); + }, + + changeSelectedDriverType: driverTypeComboValue => { + this.model.selectedDriverType = driverTypeComboValue; + this.model.driverSource = driverTypeComboValue === 'default' ? '' : this.model.driverSource; + }, + + changeDriverSource: driverTypeComboValue => { + this.model.driverSource = driverTypeComboValue === 'default' ? '' : this.model.driverSource; + }, + }; + + private resolveSelectedDriverType = () => { + if (BI.isNotEmptyString(this.options.driverSource)) { + return [this.options.driverSource, this.options.driver]; + } + + return [this.options.driverSource, this.options.driver]; + }; + + private getDrivers = () => { + const connectionData = this.options.connectionData as ConnectionJDBC; + const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); + const drivers = connectionType.drivers ? + connectionType.drivers.map(item => { + return { + text: item, + value: item, + }; + }) : + [{ + text: connectionType.driver, + value: connectionType.driver, + }]; + + if (!drivers.some(item => item.text === connectionData.driver)) { + return [ + { + text: connectionData.driver, + value: connectionData.driver, + }, + ...drivers, + ]; + } + + return drivers; + }; +} diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.ts b/src/modules/pages/maintain/components/driverselector/driverselector.ts new file mode 100644 index 0000000..564dc9a --- /dev/null +++ b/src/modules/pages/maintain/components/driverselector/driverselector.ts @@ -0,0 +1,217 @@ +import { shortcut, store } from '@core/core'; + +import { + Button, + EditorIconCheckCombo, + SearchTextValueCombo, + TextValueCombo, +} from '@fui/core'; +import { ConnectionJDBC } from '../../../../crud/crud.typings'; +import { getJdbcDatabaseType } from '../../../../app.service'; +import { DriverSelectorModel } from './driverselector.model'; + + +@shortcut() +@store(DriverSelectorModel, { + props(this: DriverSelector) { + return this.options; + }, +}) +export class DriverSelector extends BI.Widget { + static xtype = 'dec.dcm.maintain.form.jdbc.driver_selector'; + + props = { + driver: '', + driverSource: '', + connectionData: {} as ConnectionJDBC, + }; + + defaultDrivers: EditorIconCheckCombo = null; + + customDrivers: SearchTextValueCombo = null; + + beforeRender(cb: Function) { + this.store.initDriverClassList(cb); + } + + watch = { + driverClassItems: items => { + this.customDrivers.populate(items); + this.customDrivers.setValue(this.model.customDriver.driver); + }, + + driverManageEntryVisible: b => { + this.driverManageEntry.setVisible(b); + }, + }; + + private driverManageEntry = null; + + render() { + const { driver } = this.options.connectionData; + + return { + type: BI.VerticalAdaptLayout.xtype, + rgap: 10, + items: [ + { + el: { + type: BI.TextValueCombo.xtype, + width: 86, + value: this.model.selectedDriverType, + items: [ + { + text: BI.i18nText('Dec-Basic_Default'), + value: 'default', + }, { + text: BI.i18nText('Dec-Basic_Custom'), + value: 'custom', + }, + ], + listeners: [ + { + eventName: BI.TextValueCombo.EVENT_CHANGE, + action: value => { + this.store.changeSelectedDriverType(value); + if (value === 'default') { + this.defaultDrivers.setVisible(true); + this.customDrivers.setVisible(false); + + return; + } + + this.defaultDrivers.setVisible(false); + this.customDrivers.setVisible(true); + }, + }, + ], + }, + }, { + el: { + type: BI.EditorIconCheckCombo.xtype, + $testId: 'dec-editor-icon-check-combo', + $value: 'driver', + ref: _ref => { + this.defaultDrivers = _ref; + }, + invisible: this.model.driverSource !== '', + width: 204, + items: this.model.defaultDrivers, + value: this.model.defaultDriver.driver, + listeners: [ + { + eventName: BI.EditorIconCheckCombo.EVENT_CHANGE, + action: () => this.store.changeDefaultDriver(this.defaultDrivers.getValue()), + }, + ], + }, + }, { + el: { + type: BI.SearchTextValueCombo.xtype, + $testId: 'dec-editor-icon-check-combo', + $value: 'driver', + ref: _ref => { + this.customDrivers = _ref; + }, + invisible: this.model.driverSource === '', + width: 204, + watermark: BI.i18nText('Dec-Please_Input'), + items: this.model.driverClassItems, + value: this.model.customDriver.driver, + text: () => this.model.customDriver.text || BI.i18nText('Dec-Please_Select'), + warningTitle: BI.i18nText('Dec-Dcm-Driver_Driver_File_Lost'), + listeners: [ + { + eventName: BI.SearchTextValueCombo.EVENT_CHANGE, + action: () => this.store.changeCustomDriver(this.customDrivers.getValue()[0]), + }, + ], + }, + }, { + el: { + type: BI.Button.xtype, + ref: (_ref: Button) => { + this.driverManageEntry = _ref; + }, + level: 'ignore', + text: BI.i18nText('Dec-Dcm_Create_New_Driver'), + invisible: !this.model.driverManageEntryVisible, + handler: () => { + this.createDriverManagerLayer(); + }, + }, + }, + ], + }; + } + + private createDriverManagerLayer() { + const name = BI.UUID(); + + BI.Layers.create(name, '.dec-dcm', { + render: { + type: 'bi.vtape', + cls: 'bi-background', + items: [ + { + type: 'bi.vertical_adapt', + cls: 'bi-card', + items: [ + { + el: { + type: 'bi.icon_text_item', + text: BI.i18nText('Dec-Connection_Driver_Management_Exit'), + cls: 'back-font bi-high-light', + height: 24, + logic: { + dynamic: true, + }, + handler: () => { + this.store.initDriverClassList(() => BI.Layers.remove(name)); + }, + }, + hgap: 10, + }, + ], + height: 40, + }, { + el: { + type: 'dec.connection.driver', + listeners: [ + { + eventName: 'EVENT_CLOSE', + action() { + BI.Layers.remove(name); + }, + }, + ], + }, + hgap: 10, + vgap: 10, + }, + ], + }, + }); + + BI.Layers.show(name); + } + + validation(): boolean { + if (this.model.selectedDriverType === 'default' && BI.isKey(this.model.defaultDriver.driver)) { + return true; + } + if (this.model.selectedDriverType === 'custom' && BI.isKey(this.model.customDriver.driver)) { + return true; + } + BI.Msg.toast(BI.i18nText('Dec-Dcm_Driver_Class_Not_Allow_Empty'), { level: 'error' }); + + return false; + } + + getValue() { + return { + driverSource: this.model.driverSource, + driver: this.model.driverSource === '' ? this.model.defaultDriver.driver : this.model.customDriver.driver, + }; + } +} diff --git a/src/modules/pages/maintain/forms/components/form.jdbc.ts b/src/modules/pages/maintain/forms/components/form.jdbc.ts index a0c49d4..fa18f6a 100644 --- a/src/modules/pages/maintain/forms/components/form.jdbc.ts +++ b/src/modules/pages/maintain/forms/components/form.jdbc.ts @@ -16,6 +16,7 @@ import { TextValueCombo, VerticalLayout, } from '@fui/core'; +import { DriverSelector } from '../../components/driverselector/driverselector'; const api = new ApiFactory().create(); @@ -130,31 +131,32 @@ export class FormJdbc extends BI.Widget { { type: FormItem.xtype, name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'), - forms: [{ - type: BI.EditorIconCheckCombo.xtype, - $testId: 'dec-editor-icon-check-combo', - $value: 'driver', - width: 300, - value: driver, - ref: (_ref: EditorIconCheckCombo) => { - this.form.driver = _ref; - }, - items: this.getDrivers(), - listeners: [{ - eventName: BI.EditorIconCheckCombo.EVENT_CHANGE, - action: () => { - const value = this.form.driver.getValue(); - const connectionData = this.options.formData.connectionData as ConnectionJDBC; - const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); - const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; - this.form.url.setValue(url); - const urlInfo = resolveUrlInfo(url, connectionData.database); - this.form.host.setValue(urlInfo.host); - this.form.database.setValue(urlInfo.databaseName); - this.form.port.setValue(urlInfo.port); + forms: [ + { + type: DriverSelector.xtype, + ref: (_ref: DriverSelector) => { + this.form.driver = _ref; }, - }], - }], + driver, + connectionData, + listeners: [ + { + eventName: 'EVENT_CHANGE', + action: () => { + const value = this.form.driver.getValue(); + const connectionData = this.options.formData.connectionData as ConnectionJDBC; + const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); + const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; + this.form.url.setValue(url); + const urlInfo = resolveUrlInfo(url, connectionData.database); + this.form.host.setValue(urlInfo.host); + this.form.database.setValue(urlInfo.databaseName); + this.form.port.setValue(urlInfo.port); + }, + }, + ], + }, + ], }, { type: FormItem.xtype, @@ -823,6 +825,10 @@ export class FormJdbc extends BI.Widget { } } + public validation(): boolean { + return this.form.driver.validation(); + } + public getSubmitValue(): Connection { const connectionData = this.options.formData.connectionData as ConnectionJDBC; const connectionPoolAttr = connectionData.connectionPoolAttr; @@ -836,7 +842,7 @@ export class FormJdbc extends BI.Widget { connectionData: BI.extend({}, connectionData, { database: connectionData.database, connectionName: this.form.connectionName.getValue(), - driver: this.form.driver.getValue(), + ...this.form.driver.getValue(), url: this.form.url.getValue(), user: this.form.user.getValue(), password: this.oldPassword === this.form.password.getValue() ? this.oldPassword : api.getCipher(this.form.password.getValue()), diff --git a/src/modules/pages/maintain/forms/form.ts b/src/modules/pages/maintain/forms/form.ts index ceb59cc..84201e6 100644 --- a/src/modules/pages/maintain/forms/form.ts +++ b/src/modules/pages/maintain/forms/form.ts @@ -197,6 +197,10 @@ export class MaintainForm extends BI.Widget { return false; } + if (!this.form.validation || !this.form.validation()) { + return false; + } + return true; } @@ -223,13 +227,18 @@ export class MaintainForm extends BI.Widget { if (!formValue.connectionName) { this.setFromError(BI.i18nText('Dec-Dcm_Connection_ConnectionName_Cannt_Null')); - return; + return false; } if (getChartLength(formValue.connectionName) > NAME_MAX_LENGTH) { this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH)); return false; } + + if (!this.form.validation || !this.form.validation()) { + return false; + } + if (this.isEdit || this.model.isCopy) { formValue.connectionId = this.connectionName; }