diff --git a/io.sc.engine.rule.frontend/package.json b/io.sc.engine.rule.frontend/package.json index 9e3f7f57..1a5ef341 100644 --- a/io.sc.engine.rule.frontend/package.json +++ b/io.sc.engine.rule.frontend/package.json @@ -92,7 +92,7 @@ "luckyexcel": "1.0.1", "mockjs": "1.1.0", "pinia": "2.1.7", - "platform-core": "8.1.237", + "platform-core": "8.1.244", "quasar": "2.15.3", "tailwindcss": "3.4.3", "vue": "3.4.24", diff --git a/io.sc.engine.rule.frontend/src/i18n/messages.json b/io.sc.engine.rule.frontend/src/i18n/messages.json index daeb2de2..6033d76c 100644 --- a/io.sc.engine.rule.frontend/src/i18n/messages.json +++ b/io.sc.engine.rule.frontend/src/i18n/messages.json @@ -87,6 +87,7 @@ "re.resources.designer.processor.grid.entity.numberRange": "Number Range", "re.resources.designer.processor.grid.entity.conditionRangeVar": "Condition Range", "re.resources.designer.processor.grid.entity.conditionRange": "Condition Range", + "re.resources.designer.processor.grid.entity.pmml": "PMML", "re.resources.designer.processor.grid.entity.decisionTable2C": "Simple Decision Table", "re.resources.designer.processor.grid.entity.decisionTable": "Decision Table", "re.resources.designer.processor.grid.entity.groovyScript": "Groovy Script", diff --git a/io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json b/io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json index c8b75502..9cf20b5b 100644 --- a/io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json +++ b/io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json @@ -87,6 +87,7 @@ "re.resources.designer.processor.grid.entity.numberRange": "數值分段", "re.resources.designer.processor.grid.entity.conditionRangeVar": "條件分段", "re.resources.designer.processor.grid.entity.conditionRange": "條件分段", + "re.resources.designer.processor.grid.entity.pmml": "PMML", "re.resources.designer.processor.grid.entity.decisionTable2C": "簡單決策表", "re.resources.designer.processor.grid.entity.decisionTable": "決策表", "re.resources.designer.processor.grid.entity.groovyScript": "腳本代碼", diff --git a/io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json b/io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json index 2abba359..ed705694 100644 --- a/io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json +++ b/io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json @@ -87,6 +87,7 @@ "re.resources.designer.processor.grid.entity.numberRange": "数值分段", "re.resources.designer.processor.grid.entity.conditionRangeVar": "条件分段", "re.resources.designer.processor.grid.entity.conditionRange": "条件分段", + "re.resources.designer.processor.grid.entity.pmml": "PMML", "re.resources.designer.processor.grid.entity.decisionTable2C": "简单决策表", "re.resources.designer.processor.grid.entity.decisionTable": "决策表", "re.resources.designer.processor.grid.entity.groovyScript": "脚本代码", diff --git a/io.sc.engine.rule.frontend/src/utils/PlaceHolder.ts b/io.sc.engine.rule.frontend/src/utils/PlaceHolder.ts new file mode 100644 index 00000000..866f0d42 --- /dev/null +++ b/io.sc.engine.rule.frontend/src/utils/PlaceHolder.ts @@ -0,0 +1,20 @@ +import { Tools } from 'platform-core'; + +class PlaceHolder { + static #prefix: string = ''; + static #suffix: string = ''; + public static replace(str, prefix, suffix) { + if (str) { + if (Tools.isUndefinedOrNull(prefix)) { + prefix = PlaceHolder.#prefix; + } + if (Tools.isUndefinedOrNull(suffix)) { + suffix = PlaceHolder.#suffix; + } + return str.replace(/\$\{(.+?)\}/g, prefix + '$1' + suffix); + } + return str; + } +} + +export { PlaceHolder }; diff --git a/io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts b/io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts index 672e902a..52c9b9e5 100644 --- a/io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts +++ b/io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts @@ -1,42 +1,66 @@ const GroovyFunctions = [ - { label: 'PI', type: 'constant', apply: 'PI', detail: '常量 π' }, - { label: 'E', type: 'constant', apply: 'E', detail: '常量 e' }, - { label: 'IEEEremainder(v1,v2)', type: 'function', apply: 'IEEEremainder(v1,v2)', detail: '根据 IEEE 754 标准返回 v1 除以 v2 的余数' }, - { label: 'abs(v)', type: 'function', apply: 'abs(v)', detail: '绝对值' }, - { label: 'acos(v)', type: 'function', apply: 'acos(v)', detail: '反余弦' }, - { label: 'asin(v)', type: 'function', apply: 'asin(v)', detail: '反正弦' }, - { label: 'atan(v)', type: 'function', apply: 'atan(v)', detail: '' }, - { label: 'atan2(v)', type: 'function', apply: 'atan2(v)', detail: '' }, - { label: 'cbrt(v)', type: 'function', apply: 'cbrt(v)', detail: '' }, - { label: 'ceil(v)', type: 'function', apply: 'ceil(v)', detail: '' }, - { label: 'cos(v)', type: 'function', apply: 'cos(v)', detail: '' }, - { label: 'cosh(v)', type: 'function', apply: 'cosh(v)', detail: '' }, - { label: 'exp(v)', type: 'function', apply: 'exp(v)', detail: '' }, - { label: 'expm1(v)', type: 'function', apply: 'expm1(v)', detail: '' }, - { label: 'floor(v)', type: 'function', apply: 'floor(v)', detail: '' }, - { label: 'inverseNormalDistributioin(x)', type: 'function', apply: 'inverseNormalDistributioin(x)', detail: '' }, - { label: 'join(split,s1,s2,s3...,sn)', type: 'function', apply: 'join(split,s1,s2,s3...,sn)', detail: '' }, - { label: 'ln(v)', type: 'function', apply: 'ln(v)', detail: '' }, - { label: 'max(v1,v2,...)', type: 'function', apply: 'max(v1,v2,...)', detail: '' }, - { label: 'min(v1,v2,...)', type: 'function', apply: 'min(v1,v2,...)', detail: '' }, - { label: 'normalDistributioin(x)', type: 'function', apply: 'normalDistributioin(x)', detail: '' }, - { label: 'pow(x,y)', type: 'function', apply: 'pow(x,y)', detail: '' }, - { label: 'random()', type: 'function', apply: 'random()', detail: '' }, - { label: 'rint(v)', type: 'function', apply: 'rint(v)', detail: '' }, - { label: 'round(v)', type: 'function', apply: 'round(v)', detail: '' }, - { label: 'sin(v)', type: 'function', apply: 'sin(v)', detail: '' }, - { label: 'sinh(v)', type: 'function', apply: 'sinh(v)', detail: '' }, - { label: 'sqrt(v)', type: 'function', apply: 'sqrt(v)', detail: '' }, - { label: 'sum(v1,v2,...)', type: 'function', apply: 'sum(v1,v2,...)', detail: '' }, - { label: 'tan(v)', type: 'function', apply: 'tan(v)', detail: '' }, - { label: 'tanh(v)', type: 'function', apply: 'tanh(v)', detail: '' }, - { label: 'toDegrees(v)', type: 'function', apply: 'toDegrees(v)', detail: '' }, - { label: 'toRadians(v)', type: 'function', apply: 'toRadians(v)', detail: '' }, + { boost: -50, label: '==', type: 'keyword', apply: '==', detail: '等于', info: '等于' }, + { boost: -50, label: '>', type: 'keyword', apply: '>', detail: '大于', info: '大于' }, + { boost: -50, label: '>=', type: 'keyword', apply: '>=', detail: '大于等于', info: '大于等于' }, + { boost: -50, label: '<', type: 'keyword', apply: '<', detail: '小于', info: '小于' }, + { boost: -50, label: '<=', type: 'keyword', apply: '<=', detail: '小于等于', info: '小于等于' }, + { boost: -50, label: '&&', type: 'keyword', apply: '&&', detail: '并且', info: '并且' }, + { boost: -50, label: '||', type: 'keyword', apply: '||', detail: '或者', info: '或者' }, + { boost: -50, label: '!', type: 'keyword', apply: '!', detail: '非', info: '非' }, + { boost: -60, label: 'PI', type: 'constant', apply: 'PI', detail: '常量 π', info: '常量 π' }, + { boost: -60, label: 'E', type: 'constant', apply: 'E', detail: '常量 e', info: '常量 e' }, { - label: 'transformSequencing(value,sourceMin,sourceMax,targetMin,targetMax)', + boost: -70, + label: 'IEEEremainder(v1,v2)', type: 'function', - apply: 'transformSequencing(value,sourceMin,sourceMax,targetMin,targetMax)', - detail: '', + apply: 'IEEEremainder(v1,v2)', + detail: '余数', + info: '根据 IEEE 754 标准返回 v1 除以 v2 的余数', + }, + { boost: -70, label: 'abs(v)', type: 'function', apply: 'abs(v)', detail: '绝对值', info: '绝对值' }, + { boost: -70, label: 'acos(v)', type: 'function', apply: 'acos(v)', detail: '反余弦', info: '反余弦' }, + { boost: -70, label: 'asin(v)', type: 'function', apply: 'asin(v)', detail: '反正弦', info: '大于' }, + { boost: -70, label: 'atan(v)', type: 'function', apply: 'atan(v)', detail: '反正切', info: '反正切' }, + { boost: -70, label: 'atan2(v)', type: 'function', apply: 'atan2(v)', detail: '', info: '大于' }, + { boost: -70, label: 'cbrt(v)', type: 'function', apply: 'cbrt(v)', detail: '立方根', info: '立方根' }, + { boost: -70, label: 'ceil(v)', type: 'function', apply: 'ceil(v)', detail: '向上取整', info: '返回大于或等于 v 的最接近的整数' }, + { boost: -70, label: 'cos(v)', type: 'function', apply: 'cos(v)', detail: '余弦', info: '余弦' }, + { boost: -70, label: 'cosh(v)', type: 'function', apply: 'cosh(v)', detail: '双曲余弦', info: '双曲余弦' }, + { boost: -70, label: 'exp(v)', type: 'function', apply: 'exp(v)', detail: 'e 的 v 次方', info: 'e 的 v 次方' }, + { boost: -70, label: 'expm1(v)', type: 'function', apply: 'expm1(v)', detail: '', info: '大于' }, + { boost: -70, label: 'floor(v)', type: 'function', apply: 'floor(v)', detail: '向下取整', info: '返回小于或等于 v 的最接近的整数' }, + { boost: -70, label: 'inverseNormalDistributioin(x)', type: 'function', apply: 'inverseNormalDistributioin(x)', detail: '反正态分布', info: '反正态分布' }, + { + boost: -70, + label: 'join(split,V1,V2,V3...,Vn)', + type: 'function', + apply: 'join(split,V1,V2,V3...,Vn)', + detail: '字符串连接', + info: '采用 split 分隔符连接 V1, V2, V3..., Vn', + }, + { boost: -70, label: 'ln(v)', type: 'function', apply: 'ln(v)', detail: '自然对数', info: '自然对数' }, + { boost: -70, label: 'max(V1,V2,V3...,Vn)', type: 'function', apply: 'max(V1,V2,V3...,Vn)', detail: '最大值', info: '返回 V1, V2, V3..., Vn 中最大的那个值' }, + { boost: -70, label: 'min(v1,v2,...)', type: 'function', apply: 'min(v1,v2,...)', detail: '最小值', info: '返回 V1, V2, V3..., Vn 中最小的那个值' }, + { boost: -70, label: 'normalDistributioin(x)', type: 'function', apply: 'normalDistributioin(x)', detail: '正态分布', info: '正态分布' }, + { boost: -70, label: 'pow(x,y)', type: 'function', apply: 'pow(x,y)', detail: '指数', info: '返回 x 的 y 次方' }, + { boost: -70, label: 'random()', type: 'function', apply: 'random()', detail: '随机数', info: '返回 0 ~ 1 之间的一个随机数' }, + { boost: -70, label: 'rint(v)', type: 'function', apply: 'rint(v)', detail: '最近整数', info: '返回和 v 最接近的整数' }, + { boost: -70, label: 'round(v)', type: 'function', apply: 'round(v)', detail: '四舍五入', info: '四舍五入' }, + { boost: -70, label: 'sin(v)', type: 'function', apply: 'sin(v)', detail: '正弦', info: '正弦' }, + { boost: -70, label: 'sinh(v)', type: 'function', apply: 'sinh(v)', detail: '双曲正弦', info: '双曲正弦' }, + { boost: -70, label: 'sqrt(v)', type: 'function', apply: 'sqrt(v)', detail: '平方根', info: '平方根' }, + { boost: -70, label: 'sum(V1,V2,V3...,Vn)', type: 'function', apply: 'sum(V1,V2,V3...,Vn)', detail: '求和', info: '返回 V1, V2, V3..., Vn 的和' }, + { boost: -70, label: 'tan(v)', type: 'function', apply: 'tan(v)', detail: '正切', info: '正切' }, + { boost: -70, label: 'tanh(v)', type: 'function', apply: 'tanh(v)', detail: '双曲正切', info: '双曲正切' }, + { boost: -70, label: 'toDegrees(v)', type: 'function', apply: 'toDegrees(v)', detail: '幅度转角度', info: '返回 v 的角度值' }, + { boost: -70, label: 'toRadians(v)', type: 'function', apply: 'toRadians(v)', detail: '角度转幅度', info: '返回 v 的幅度值' }, + { + boost: -70, + label: 'transformSequencing(v,si,sm,ti,tm)', + type: 'function', + apply: 'transformSequencing(v,si,sm,ti,tm)', + detail: '缩放', + info: '根据 v 所在 si 和 sm 的位置, 缩放到 ti 和 tm 对应的位置', }, ]; diff --git a/io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue b/io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue index c1b4e28e..e434d3ec 100644 --- a/io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue +++ b/io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue @@ -205,6 +205,33 @@ 'edit', 'remove', 'separator', + { + name: 'enable', + label: (arg) => { + if (arg.selected?.enable) { + return $t('disable'); + } + return $t('enable'); + }, + icon: (arg) => { + if (arg.selected?.enable) { + return 'x'; + } + return 'check'; + }, + enableIf: (arg) => { + return arg.selected; + }, + click: (arg) => { + const data = arg.selected; + data.enable = !data.enable; + console.log(data); + axios.put(Environment.apiContextPath('/api/re/model/parameter/' + data.id), data).then((response) => { + gridRef.replaceRow(response.data); + }); + }, + }, + 'separator', 'view', 'separator', 'export', @@ -223,32 +250,51 @@ if ('OPTION_VALUE' === type) { return row.optionCode; } else if ('ARITHMETIC' === type) { - return row.arithmetic; + return PlaceHolder.replace(row.arithmetic); } else if ('TERNARY' === type) { return row.ternaryCondition + ' ? ' + row.ternaryTrue + ' : ' + row.ternaryFalse; } else if ('WHEN_THEN' === type) { - var str = ''; + let str = ''; if (row.isWhenThenShorted) { str += '' + $t('re.resources.designer.processor.grid.entity.isWhenThenShorted') + ', '; } if (row.when) { - str += 'When ' + row.when + ' '; + str += 'When ' + PlaceHolder.replace(row.when) + ' '; } if (row.then) { - str += 'Then ' + row.then; + str += 'Then ' + PlaceHolder.replace(row.then); } return str; } else if ('NUMBER_RANGE' === type) { - var objs = Tools.json2Object(row.numberRange); + const objs = Tools.json2Object(row.numberRange); if (objs) { - var str = '
' + row.numberRangeVar + ':
'; - str += `
`; + let str = `
`; str += ``; - for (var i = 0; i < objs.length; i++) { - var obj = objs[i]; + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; str += ''; + if (i == 0) { + str += ' '; + } str += ' '; - str += ' '; + str += ' '; + str += ''; + } + str += '
' + PlaceHolder.replace(row.numberRangeVar) + '' + Tools.generateIntervalRange(obj.minIncluded, obj.min, obj.max, obj.maxIncluded) + '' + ('' + obj.value) + '' + ('' + PlaceHolder.replace('' + obj.value)) + '
'; + str += '
'; + return str; + } + return ''; + } else if ('CONDITION_RANGE' === type) { + const objs = Tools.json2Object(row.conditionRange); + if (objs) { + let str = `
`; + str += ``; + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; + str += ''; + str += ' '; + str += ' '; str += ''; } str += '
' + PlaceHolder.replace(obj.condition) + '' + ('' + PlaceHolder.replace(obj.value)) + '
'; @@ -256,13 +302,21 @@ return str; } return ''; + } else if ('PMML' === type) { + return { + componentType: 'w-code-mirror', + bindModelValue: true, + attrs: { + rows: 3, + }, + }; } }, }, ]" :editor="{ dialog: { - width: '600px', + width: '800px', }, form: { colsNum: 1, @@ -271,8 +325,8 @@ { name: 'id', label: $t('id'), type: 'text', hidden: true }, { name: 'order', label: $t('order'), type: 'number', hidden: true }, { name: 'type', label: $t('type'), type: 'text', hidden: true }, - { name: 'description', label: $t('description'), type: 'text' }, - { name: 'enable', label: $t('enable'), type: 'checkbox', defaultValue: true }, + { name: 'description', label: $t('description'), type: 'text', hidden: true }, + { name: 'enable', label: $t('enable'), type: 'checkbox', defaultValue: true, hidden: true }, { name: 'optionCode', label: $t('re.resources.designer.processor.grid.entity.optionCode'), @@ -288,6 +342,8 @@ type: 'code-mirror', lang: 'java', rows: 5, + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -300,7 +356,8 @@ type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -313,7 +370,8 @@ type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -326,7 +384,8 @@ type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -339,7 +398,8 @@ type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -352,7 +412,8 @@ type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { @@ -370,45 +431,232 @@ { name: 'numberRangeVar', label: $t('re.resources.designer.processor.grid.entity.numberRangeVar'), + showIf: (arg) => { + return 'NUMBER_RANGE' === arg.form.getFieldValue('type'); + }, type: 'code-mirror', lang: 'java', rows: 1, - height: '32px', + placeholder: true, + autoCompletion: true, autoCompletionOptions: autoCompletionOptionsRef, extAutoCompletionOptions: GroovyFunctions, - showIf: (arg) => { - return 'NUMBER_RANGE' === arg.form.getFieldValue('type'); - }, }, { name: 'numberRange', label: $t('re.resources.designer.processor.grid.entity.numberRange'), + showIf: (arg) => { + return 'NUMBER_RANGE' === arg.form.getFieldValue('type'); + }, type: 'w-grid', height: 300, + denseBody: true, + draggable: true, pageable: false, configButton: false, toolbarConfigure: { noIcon: false }, - toolbarActions: ['add', 'clone', 'remove'], + toolbarActions: [ + 'add', + 'clone', + 'edit', + { + extend: 'remove', + click: (arg) => { + const grid = gridRef.getEditorForm().getFieldComponent('numberRange'); + grid.removeRows(arg.selecteds); + }, + }, + 'separator', + { + name: 'example', + label: $t('example'), + icon: 'bi-balloon', + click: (arg) => { + const grid = gridRef.getEditorForm().getFieldComponent('numberRange'); + const sampleData = [ + { uuid: Tools.uuid(), minIncluded: false, min: null, max: 0, maxIncluded: false, value: 1 }, + { uuid: Tools.uuid(), minIncluded: true, min: 0, max: 1, maxIncluded: false, value: 2 }, + { uuid: Tools.uuid(), minIncluded: true, min: 1, max: 2, maxIncluded: false, value: 3 }, + { uuid: Tools.uuid(), minIncluded: true, min: 2, max: 3, maxIncluded: false, value: 4 }, + { uuid: Tools.uuid(), minIncluded: true, min: 3, max: null, maxIncluded: false, value: 5 }, + { uuid: Tools.uuid(), minIncluded: false, min: null, max: null, maxIncluded: false, value: 0 }, + ]; + grid.setLocalData(sampleData); + }, + }, + ], + primaryKey: 'uuid', columns: [ { width: 200, name: 'uuid', label: 'uuid', hidden: true }, - { width: 60, name: 'minIncluded', label: $t('include') }, - { width: 100, name: 'min', label: $t('minValue'), align: 'center' }, - { width: 100, name: 'max', label: $t('maxValue'), align: 'center' }, - { width: 60, name: 'maxIncluded', label: $t('include'), type: 'boolean' }, - { width: '100%', name: 'value', label: $t('value') }, + { + width: 60, + name: 'minIncluded', + label: $t('include'), + align: 'center', + sortable: false, + format: (value) => { + if (value) { + return '['; + } else { + return '('; + } + }, + }, + { width: 100, name: 'min', label: $t('minValue'), align: 'right', sortable: false }, + { width: 100, name: 'max', label: $t('maxValue'), align: 'right', sortable: false }, + { + width: 60, + name: 'maxIncluded', + label: $t('include'), + align: 'center', + sortable: false, + format: (value) => { + if (value) { + return '['; + } else { + return ')'; + } + }, + }, + { width: '100%', name: 'value', label: $t('value'), sortable: false }, ], - showIf: (arg) => { - return 'NUMBER_RANGE' === arg.form.getFieldValue('type'); + editor: { + dialog: { + width: '600px', + }, + form: { + colsNum: 4, + fields: [ + { name: 'uuid', label: 'uuid', hidden: true, colSpan: 4 }, + { name: 'min', label: $t('minValue'), type: 'text', colSpan: 3 }, + { name: 'minIncluded', label: $t('include'), type: 'checkbox' }, + { name: 'max', label: $t('maxValue'), type: 'text', colSpan: 3 }, + { name: 'maxIncluded', label: $t('include'), type: 'checkbox' }, + { name: 'value', label: $t('value'), type: 'number', colSpan: 3 }, + ], + }, + }, + onBeforeEditorDataSubmit: (data, callback) => { + const grid = gridRef.getEditorForm().getFieldComponent('numberRange'); + const form = grid.getEditorForm(); + if ('add' == form.getStatus() || 'clone' == form.getStatus()) { + data.uuid = Tools.uuid(); + grid.addRow(data); + callback(false); + } else if ('edit' == form.getStatus()) { + grid.replaceRow(data); + callback(false); + } }, }, { name: 'conditionRange', label: $t('re.resources.designer.processor.grid.entity.conditionRange'), - type: 'code-mirror', - rows: 1, showIf: (arg) => { return 'CONDITION_RANGE' === arg.form.getFieldValue('type'); }, + type: 'w-grid', + height: 300, + denseBody: true, + draggable: true, + pageable: false, + configButton: false, + toolbarConfigure: { noIcon: false }, + toolbarActions: [ + 'add', + 'clone', + 'edit', + { + extend: 'remove', + click: (arg) => { + const grid = gridRef.getEditorForm().getFieldComponent('conditionRange'); + grid.removeRows(arg.selecteds); + }, + }, + 'separator', + { + name: 'example', + label: $t('example'), + icon: 'bi-balloon', + click: (arg) => { + const grid = gridRef.getEditorForm().getFieldComponent('conditionRange'); + const sampleData = [ + { uuid: Tools.uuid(), condition: '${变量名}<=0', value: '0' }, + { uuid: Tools.uuid(), condition: '${变量名}>0 && ${变量名}<=50', value: '50' }, + { uuid: Tools.uuid(), condition: '${变量名}>50 && ${变量名}<=80', value: '80' }, + { uuid: Tools.uuid(), condition: '${变量名}>80 && ${变量名}<=100', value: '100' }, + { uuid: Tools.uuid(), condition: '${变量名}>100', value: '60' }, + ]; + grid.setLocalData(sampleData); + }, + }, + ], + primaryKey: 'uuid', + columns: [ + { name: 'uuid', label: 'uuid', hidden: true }, + { + name: 'condition', + label: $t('condition'), + align: 'left', + sortable: false, + format: (value) => { + return PlaceHolder.replace(value); + }, + }, + { + name: 'value', + label: $t('value'), + sortable: false, + format: (value) => { + return PlaceHolder.replace(value); + }, + }, + ], + editor: { + dialog: { + width: '600px', + }, + form: { + colsNum: 1, + fields: [ + { name: 'uuid', label: 'uuid', hidden: true }, + { + name: 'condition', + label: $t('condition'), + type: 'code-mirror', + lang: 'java', + rows: 1, + placeholder: true, + autoCompletion: true, + autoCompletionOptions: autoCompletionOptionsRef, + extAutoCompletionOptions: GroovyFunctions, + }, + { + name: 'value', + label: $t('value'), + type: 'code-mirror', + lang: 'java', + rows: 1, + placeholder: true, + autoCompletion: true, + autoCompletionOptions: autoCompletionOptionsRef, + extAutoCompletionOptions: GroovyFunctions, + }, + ], + }, + }, + onBeforeEditorDataSubmit: (data, callback) => { + const grid = gridRef.getEditorForm().getFieldComponent('conditionRange'); + const form = grid.getEditorForm(); + if ('add' == form.getStatus() || 'clone' == form.getStatus()) { + data.uuid = Tools.uuid(); + grid.addRow(data); + callback(false); + } else if ('edit' == form.getStatus()) { + grid.replaceRow(data); + callback(false); + } + }, }, { name: 'decisionTable2C', @@ -450,7 +698,9 @@ name: 'pmml', label: $t('re.resources.designer.processor.grid.entity.pmml'), type: 'code-mirror', - rows: 1, + rows: 10, + lineNumber: true, + lang: 'xml', showIf: (arg) => { return 'PMML' === arg.form.getFieldValue('type'); }, @@ -544,6 +794,39 @@ ], }, }" + @before-editor-data-submit=" + (data, callback) => { + const form = gridRef.getEditorForm(); + if ('NUMBER_RANGE' === data.type) { + const grid = form.getFieldComponent('numberRange'); + const localData = grid.getLocalData(); + const ranges = []; + for (const item of localData) { + ranges.push({ + uuid: item.uuid, + minIncluded: item.minIncluded, + min: item.min, + max: item.max, + maxIncluded: item.maxIncluded, + value: item.value, + }); + } + data.numberRange = Tools.object2Json(ranges); + } else if ('CONDITION_RANGE' === data.type) { + const grid = form.getFieldComponent('conditionRange'); + const localData = grid.getLocalData(); + const ranges = []; + for (const item of localData) { + ranges.push({ + uuid: item.uuid, + condition: item.condition, + value: item.value, + }); + } + data.conditionRange = Tools.object2Json(ranges); + } + } + " @after-editor-open=" (row) => { axios.get(Environment.apiContextPath('/api/re/model/parameter/listParemterHintsByParameterId/' + parameter.id)).then((response) => { @@ -572,9 +855,13 @@ optionOptionsRef = parameters; }); if ('NUMBER_RANGE' === row.type) { - const fields = gridRef.getEditorForm().getFields(); - console.log(fields); - numberRangeGridRef.setLocalData(Tools.json2Object(row.numberRange)); + const grid = gridRef.getEditorForm().getFieldComponent('numberRange'); + const rows = Tools.json2Object(row.numberRange); + grid.setLocalData(rows); + } else if ('CONDITION_RANGE' === row.type) { + const grid = gridRef.getEditorForm().getFieldComponent('conditionRange'); + const rows = Tools.json2Object(row.conditionRange); + grid.setLocalData(rows); } } " @@ -583,6 +870,7 @@ -./w-code-mirror/GroovyFunctions diff --git a/io.sc.platform.core.frontend/src/platform/components/form/elements/w-code-mirror/PlaceholderPlugin.ts b/io.sc.platform.core.frontend/src/platform/components/form/elements/w-code-mirror/PlaceholderPlugin.ts index efc9a3f3..f8ba5a69 100644 --- a/io.sc.platform.core.frontend/src/platform/components/form/elements/w-code-mirror/PlaceholderPlugin.ts +++ b/io.sc.platform.core.frontend/src/platform/components/form/elements/w-code-mirror/PlaceholderPlugin.ts @@ -11,15 +11,16 @@ class PlaceholderWidget extends WidgetType { } toDOM() { + const container = document.createElement('span'); + container.className = 'px-0.5'; + const elt = document.createElement('span'); elt.setAttribute('placeholder', true); - elt.style.cssText = ` - border: 1px solid gray; - border-radius: 4px; - padding: 2px 2px; - `; + elt.className = 'p-0.5 border border-gray-800 rounded-md'; elt.textContent = this.name; - return elt; + + container.appendChild(elt); + return container; } ignoreEvent() { @@ -55,22 +56,13 @@ const placeholderPlugin = ViewPlugin.fromClass( mouseover: (e, view) => { const target = e.target as HTMLElement; if (target.tagName.toLowerCase() === 'span' && target.getAttribute('placeholder')) { - target.style.cssText = ` - border: 1px solid gray; - border-radius: 4px; - padding: 2px 2px; - background: orange; - `; + target.className = 'p-0.5 border border-orange-400 rounded-md'; } }, mouseout: (e, view) => { const target = e.target as HTMLElement; if (target.tagName.toLowerCase() === 'span' && target.getAttribute('placeholder')) { - target.style.cssText = ` - border: 1px solid gray; - border-radius: 4px; - padding: 2px 2px; - `; + target.className = 'p-0.5 border border-gray-800 rounded-md'; } }, contextmenu: (e, view) => { diff --git a/io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue b/io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue index 135cfe7d..af92bf02 100644 --- a/io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue +++ b/io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue @@ -228,7 +228,6 @@ :editor="{ dialog: { width: '600px', - height: '400px', }, form: { colsNum: 1, @@ -261,8 +260,10 @@ label: $t('re.resources.designer.processor.grid.entity.ternaryCondition'), type: 'code-mirror', lang: 'java', - rows: 1, - height: '32px', + rows: 50, + lineNumber: true, + placeholder: true, + autoCompletion: true, autoCompletionOptions: GroovyFunctions, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { diff --git a/io.sc.platform.core.frontend/template-project/package.json b/io.sc.platform.core.frontend/template-project/package.json index 18aaba2d..c32666d2 100644 --- a/io.sc.platform.core.frontend/template-project/package.json +++ b/io.sc.platform.core.frontend/template-project/package.json @@ -1,6 +1,6 @@ { "name": "platform-core", - "version": "8.1.237", + "version": "8.1.244", "description": "前端核心包,用于快速构建前端的脚手架", "private": false, "keywords": [], @@ -104,7 +104,7 @@ "luckyexcel": "1.0.1", "mockjs": "1.1.0", "pinia": "2.1.7", - "platform-core": "8.1.237", + "platform-core": "8.1.244", "quasar": "2.15.3", "tailwindcss": "3.4.3", "vue": "3.4.24", diff --git a/io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue b/io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue index 135cfe7d..af92bf02 100644 --- a/io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue +++ b/io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue @@ -228,7 +228,6 @@ :editor="{ dialog: { width: '600px', - height: '400px', }, form: { colsNum: 1, @@ -261,8 +260,10 @@ label: $t('re.resources.designer.processor.grid.entity.ternaryCondition'), type: 'code-mirror', lang: 'java', - rows: 1, - height: '32px', + rows: 50, + lineNumber: true, + placeholder: true, + autoCompletion: true, autoCompletionOptions: GroovyFunctions, extAutoCompletionOptions: GroovyFunctions, showIf: (arg) => { diff --git a/io.sc.platform.core/src/main/resources/io/sc/platform/core/config/logback-spring.xml b/io.sc.platform.core/src/main/resources/io/sc/platform/core/config/logback-spring.xml index 6d411899..8343d425 100644 --- a/io.sc.platform.core/src/main/resources/io/sc/platform/core/config/logback-spring.xml +++ b/io.sc.platform.core/src/main/resources/io/sc/platform/core/config/logback-spring.xml @@ -16,51 +16,99 @@ ${pattern} + + INFO + ACCEPT + DENY + - - + + ${pattern} ${homedir}/logs/log.log - - ${homedir}/logs/log.%d.log + + ${homedir}/logs/log.%d.%i.log 30 + 100MB + + TRACE + ACCEPT + NEUTRAL + - - - - - - - - - - - + + + ${pattern} + ${homedir}/logs/debug.log + + ${homedir}/logs/debug.%d.%i.log + 30 + 100MB + + + DEBUG + ACCEPT + DENY + + - - - - + + + ${pattern} + ${homedir}/logs/info.log + + ${homedir}/logs/info.%d.%i.log + 30 + 100MB + + + INFO + ACCEPT + DENY + + + + + ${pattern} + ${homedir}/logs/warn.log + + ${homedir}/logs/warn.%d.%i.log + 30 + 100MB + + + WARN + ACCEPT + DENY + + - - + + ${pattern} + ${homedir}/logs/error.log + + ${homedir}/logs/error.%d.%i.log 30 + 100MB + + ERROR + ACCEPT + DENY + - - + + - - - - --> - \ No newline at end of file + + + + + + +