From ddfa389f6ca34c3c539062eb0093942e1e78dc0b Mon Sep 17 00:00:00 2001 From: yaojn Date: Fri, 5 Jan 2024 19:00:02 +0800 Subject: [PATCH 01/12] =?UTF-8?q?-=20[=E5=8A=9F=E8=83=BD]=E6=96=B0?= =?UTF-8?q?=E5=A2=9ECMDB=E6=A8=A1=E5=9E=8B=E5=88=86=E6=B4=BE=E5=99=A8=20?= =?UTF-8?q?=20-=20[=E5=85=B3=E8=81=94]#[1009251198140416]=E6=96=B0?= =?UTF-8?q?=E5=A2=9ECMDB=E6=A8=A1=E5=9E=8B=E5=88=86=E6=B4=BE=E5=99=A8=20ht?= =?UTF-8?q?tp://192.168.0.96:8090/demo/rdm.html#/story-detail/939050947543?= =?UTF-8?q?040/939050947543042/1009251198140416?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/pages/process/flow/flow-edit.vue | 1 - src/views/pages/process/flow/flow-valid.js | 53 ++- .../components/nodesetting/assign-setting.vue | 28 +- .../dispatcher/cmdb-dispatcher.vue | 383 ++++++++++++++++++ 4 files changed, 439 insertions(+), 26 deletions(-) create mode 100644 src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue diff --git a/src/views/pages/process/flow/flow-edit.vue b/src/views/pages/process/flow/flow-edit.vue index 6a5dcde4..e482b46c 100644 --- a/src/views/pages/process/flow/flow-edit.vue +++ b/src/views/pages/process/flow/flow-edit.vue @@ -1082,7 +1082,6 @@ export default { }, //获取分派器下拉列表 getWorkerdispatcher() { - let _this = this; let data = {}; this.$api.process.process .workerdispatcher(data) diff --git a/src/views/pages/process/flow/flow-valid.js b/src/views/pages/process/flow/flow-valid.js index 60bef187..4e1c29d5 100644 --- a/src/views/pages/process/flow/flow-valid.js +++ b/src/views/pages/process/flow/flow-valid.js @@ -1,7 +1,8 @@ import utils from '@/resources/assets/js/util.js'; import { $t } from '@/resources/init.js'; let valid = { - common(nodeConfig, d, that) { //公共校验方法 校验名称 + common(nodeConfig, d, that) { + //公共校验方法 校验名称 let validList = this.poliyUser(nodeConfig, d, that) || []; if (!nodeConfig.name) { validList.push({ @@ -24,7 +25,8 @@ let valid = { } return validList; }, - poliyUser(nodeConfig, d, that) { //分派处理人校验 + poliyUser(nodeConfig, d, that) { + //分派处理人校验 // 分派处理人校验 let validList = []; let nodeData = nodeConfig.stepConfig || {}; @@ -32,11 +34,13 @@ let valid = { let isStart = parentNodes.find(d => { return d.getConfig() && d.getConfig().handler === 'start'; }); - if (isStart) { //如果是开始节点 + if (isStart) { + //如果是开始节点 return validList; } let extendsHandlerList = ['condition', 'distributary', 'changehandle', 'timer']; - if (!nodeData.workerPolicyConfig && extendsHandlerList.indexOf(nodeConfig.handler) < 0) { //分派处理人必填 + if (!nodeData.workerPolicyConfig && extendsHandlerList.indexOf(nodeConfig.handler) < 0) { + //分派处理人必填 validList.push({ name: $t('form.validate.required', { target: $t('term.process.poliyuser') }), href: '#assignData' @@ -52,10 +56,10 @@ let valid = { let errorText = $t('form.validate.required', { target: $t('term.process.poliyuser') }); if (isChecked) { let keyConfig = { - 'prestepassign': { value: 'processStepUuidList', text: $t('term.process.prestepassignvalid') }, //由前置步骤处理人指定 - 'copy': { value: 'processStepUuid', text: $t('term.process.copyworkerpolicyvalid') }, //复制前置步骤处理人 - 'form': { value: 'attributeUuidList', text: $t('term.process.formworkerpolicyvalid') }, //表单值 - 'assign': { value: 'workerList', text: $t('term.process.assignworkerpolicyvalid') }//自定义 + prestepassign: { value: 'processStepUuidList', text: $t('term.process.prestepassignvalid') }, //由前置步骤处理人指定 + copy: { value: 'processStepUuid', text: $t('term.process.copyworkerpolicyvalid') }, //复制前置步骤处理人 + form: { value: 'attributeUuidList', text: $t('term.process.formworkerpolicyvalid') }, //表单值 + assign: { value: 'workerList', text: $t('term.process.assignworkerpolicyvalid') } //自定义 }; for (let i = 0; i < policyList.length; i++) { if (policyList[i].isChecked == 1) { @@ -81,7 +85,8 @@ let valid = { errorText = keyConfig[type].text; break; } - } else if (policyList[i].type == 'automatic') { //分派器 + } else if (policyList[i].type == 'automatic') { + //分派器 if (policyList[i].config.handler && policyList[i].config.handler != '') { if (policyList[i].config.handlerConfig != {}) { let newObj = that.automaticList.find(d => d.handler === policyList[i].config.handler); @@ -132,11 +137,13 @@ let valid = { } return validList; }, - omnipotent(nodeConfig, d, that) { //通用节点 + omnipotent(nodeConfig, d, that) { + //通用节点 let validList = []; return validList; }, - automatic(nodeConfig, d, that) { //auto 自动处理节点校验 + automatic(nodeConfig, d, that) { + //auto 自动处理节点校验 let validList = []; let nodeData = nodeConfig.stepConfig || {}; if (nodeConfig.handler === 'automatic') { @@ -172,7 +179,8 @@ let valid = { } return validList; }, - changecreate(nodeConfig, d, that) { //变更创建的校验 + changecreate(nodeConfig, d, that) { + //变更创建的校验 let validList = []; let nodeData = nodeConfig.stepConfig || {}; if (nodeConfig.handler === 'changecreate') { @@ -200,7 +208,8 @@ let valid = { } return validList; }, - changehandle(nodeConfig, d, that) { //变更处理的校验 + changehandle(nodeConfig, d, that) { + //变更处理的校验 let validList = []; let nodeData = nodeConfig.stepConfig || {}; let allPrevNodes = d.getAllPrevNodes(); @@ -219,7 +228,8 @@ let valid = { } return validList; }, - cientitysync(nodeConfig, d, that) { //配置项同步 + cientitysync(nodeConfig, d, that) { + //配置项同步 let validList = []; //20210518_这里的数据结构:原来nodeConfig.config的数据都变成nodeConfig.stepConfig里的数据 let nodeData = nodeConfig.stepConfig || {}; @@ -246,7 +256,8 @@ let valid = { } return validList; }, - cmdbsync(nodeConfig, d, that) { //cmdb + cmdbsync(nodeConfig, d, that) { + //cmdb let validList = []; let nodeData = nodeConfig.stepConfig || {}; let ciEntityConfig = nodeData.ciEntityConfig || {}; @@ -266,7 +277,8 @@ let valid = { } return validList; }, - autoexec(nodeConfig, d, that) { //自动化节点 + autoexec(nodeConfig, d, that) { + //自动化节点 let validList = []; let nodeData = nodeConfig.stepConfig || {}; let autoexecConfig = nodeData.autoexecConfig || {}; @@ -279,14 +291,15 @@ let valid = { } if (that.$utils.isEmpty(autoexecConfig.configList)) { validList.push({ - name: $t('form.validate.leastonetarget', { 'target': $t('term.autoexec.job') }), + name: $t('form.validate.leastonetarget', { target: $t('term.autoexec.job') }), href: '#autoexecCombop' }); } } return validList; }, - timer(nodeConfig, d, that) { //定时节点 + timer(nodeConfig, d, that) { + //定时节点 let validList = []; let validObj = { name: $t('form.validate.required', { target: $t('term.process.circulationtime') }), @@ -313,7 +326,8 @@ let valid = { }; let setInitData = { - changehandle(nodeConfig, d, that) { //变更处理的校验 + changehandle(nodeConfig, d, that) { + //变更处理的校验 // 变更处理,关联变更自动填充变更创建//特殊处理变更创建和处理(第一次保存不点击节点)-------------------------- if (!nodeConfig.stepConfig.linkedChange) { let allNode = d.getAllPrevNodes(); @@ -329,4 +343,3 @@ let setInitData = { } }; export { valid, setInitData }; - diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/assign-setting.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/assign-setting.vue index 93525779..f62c258e 100644 --- a/src/views/pages/process/flow/flowedit/components/nodesetting/assign-setting.vue +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/assign-setting.vue @@ -201,7 +201,13 @@ -
+ +
{{ automatic.label }}
@@ -209,6 +215,7 @@
+ require(['@/resources/plugins/TsForm/TsFormSelect'], resolve), UserSelect: resolve => require(['@/resources/components/UserSelect/UserSelect'], resolve), - TsFormInput: resolve => require(['@/resources/plugins/TsForm/TsFormInput'], resolve) + TsFormInput: resolve => require(['@/resources/plugins/TsForm/TsFormInput'], resolve), + CmdbDispatcher: resolve => require(['./dispatcher/cmdb-dispatcher'], resolve) }, props: { prevNodes: { @@ -530,6 +538,10 @@ export default { if (item.type == 'form') { item.config.attributeUuidList = this.policyListAttributeUuidList; } + if (item.type == 'automatic' && item.config && this.getDispatcherName(item.config.handler) == 'CiEntityFormDispatcher') { + // cmdb分派器,单独处理值 + item.config.handlerConfig = this.$refs.cmdbDispatcher && this.$refs.cmdbDispatcher[0] && this.$refs.cmdbDispatcher[0].saveData() || {}; + } }); this.$set(data, 'policyList', this.policyList); this.assignValid(); @@ -549,13 +561,13 @@ export default { this.isValid = false; } this.$refs.defaultWorker && this.$refs.defaultWorker.valid(); + this.$refs.cmdbDispatcher && this.$refs.cmdbDispatcher[0] && this.$refs.cmdbDispatcher[0].valid(); // 由于policyList是v-for循环,导致获取节点也是数组,所以this.$refs.cmdbDispatcher[0]取第一个数组值 }, selectAutomatic(handler, type) { //选择分派器 let automaticObj = this.policyList.find(p => p.type === 'automatic'); if (handler) { - var newObj = this.automaticList.find(d => d.handler === handler); - + let newObj = this.automaticList.find(d => d.handler === handler); if (!newObj) { this.policyList.map(p => { if (p.type == 'automatic') { @@ -565,7 +577,6 @@ export default { return p; }); } else if (newObj && newObj.config) { - let config = newObj.config; this.automaticDeal = newObj.config; if (type != 'init') { this.$set(automaticObj.config, 'handlerConfig', {}); @@ -641,6 +652,13 @@ export default { } return handler; }; + }, + getDispatcherName() { + // 获取分派器名称 + return (handlerDispatcher) => { + const arr = handlerDispatcher && handlerDispatcher.split('.') || []; + return arr[arr.length - 1]; + }; } }, watch: { diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue new file mode 100644 index 00000000..a39cabb2 --- /dev/null +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue @@ -0,0 +1,383 @@ + + + -- Gitee From bdeeacc7dd488c0c353668ed161756504f7ae190 Mon Sep 17 00:00:00 2001 From: yaojn Date: Mon, 8 Jan 2024 14:46:33 +0800 Subject: [PATCH 02/12] =?UTF-8?q?-=20[=E5=8A=9F=E8=83=BD]=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ecmdb=E5=88=86=E6=B4=BE=E5=99=A8=20=20-=20[=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D]=E4=BC=98=E5=8C=96=E4=BC=98=E5=85=88=E7=BA=A7?= =?UTF-8?q?=E6=8B=96=E5=8A=A8=E6=94=B6=E5=88=B0=E7=88=B6=E7=BA=A7=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E7=9A=84=E9=97=AE=E9=A2=98=20=20-=20[=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D]=E5=A4=84=E7=90=86=E4=BC=98=E5=85=88=E7=BA=A7?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=AD=98=E5=82=A8=E5=80=BC=E4=B8=8D?= =?UTF-8?q?=E5=AF=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodesetting/dispatcher/cmdb-dispatcher.vue | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue index a39cabb2..9fe70495 100644 --- a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue @@ -45,9 +45,9 @@
- - {{ item.text }} + {{ item.text }}
- @@ -307,10 +305,6 @@ export default { this.cmdbDispatcherList.filter(filterCriteria) .forEach(item => Object.assign(item, selectedOption)); }, - handleChangeDrag(event) { - event.stopPropagation(); - return false; - }, handleKeyDealDataByUrl(nodeList) { // 过滤模型属性被选中属性 let filterList = this.filterList.map((item) => item.key); @@ -342,7 +336,7 @@ export default { filterList: this.filterList .filter((item) => item.key && item.formAttributeUuid) .map(({ key, formAttributeUuid }) => ({ key, formAttributeUuid })), - priorityList: this.priorityList.map((item) => { item.value; }) // 只存储值给后端 + priorityList: this.priorityList.filter((item) => !this.$utils.isEmpty(item.value)).map((item) => item.value) // 只存储值给后端 }; if (saveData.type === 'ci') { -- Gitee From 53b64129e6192633dcbab66d459d88c1c7db8557 Mon Sep 17 00:00:00 2001 From: yaojn Date: Mon, 8 Jan 2024 14:55:11 +0800 Subject: [PATCH 03/12] =?UTF-8?q?-=20[=E5=8A=9F=E8=83=BD]=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ecmdb=E5=88=86=E6=B4=BE=E5=99=A8=EF=BC=8C=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=A4=9A=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/resources/assets/languages/page/en.json | 3 ++- src/resources/assets/languages/page/zh.json | 3 ++- src/resources/assets/languages/term/en.json | 3 ++- src/resources/assets/languages/term/zh.json | 3 ++- .../dispatcher/cmdb-dispatcher.vue | 26 +++---------------- 5 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/resources/assets/languages/page/en.json b/src/resources/assets/languages/page/en.json index 4be6117e..18fe6081 100644 --- a/src/resources/assets/languages/page/en.json +++ b/src/resources/assets/languages/page/en.json @@ -960,5 +960,6 @@ "existiscoverimport": "{type}【{target}】 already exists. Do you want to continue importing and overwrite it", "userauthfailedpleaselogin": "authentication failed, please log in", "partial": "local", - "rolerule": "The request for login authentication needs to carry a header as a rule expression. If the value of the expression after execution is true, the role will take effect, otherwise it will not take effect. For example: \"${DATA.env}\"==\"sit\"ß&&(\"${DATA.test}\"=\"1\" | | \"${DATA.test2}\"==\"aaa\")" + "rolerule": "The request for login authentication needs to carry a header as a rule expression. If the value of the expression after execution is true, the role will take effect, otherwise it will not take effect. For example: \"${DATA.env}\"==\"sit\"ß&&(\"${DATA.test}\"=\"1\" | | \"${DATA.test2}\"==\"aaa\")", + "datasources": "data sources" } \ No newline at end of file diff --git a/src/resources/assets/languages/page/zh.json b/src/resources/assets/languages/page/zh.json index cf21b6d1..1c74c6c0 100644 --- a/src/resources/assets/languages/page/zh.json +++ b/src/resources/assets/languages/page/zh.json @@ -962,5 +962,6 @@ "existiscoverimport": "{type}【{target}】已存在,是否继续导入并覆盖", "userauthfailedpleaselogin": "认证失败,请重新登录", "partial": "局部", - "rolerule": "登录认证的请求需要携带Header做规则表达式(注意表达式中header参数全小写),如果表达式执行后的值为true则该角色生效,false和语法异常都不生效 。 如:\"${DATA.env}\"==\"sit\"&&(\"${DATA.test}\"==\"1\"||\"${DATA.test2}\"==\"aaa\")" + "rolerule": "登录认证的请求需要携带Header做规则表达式(注意表达式中header参数全小写),如果表达式执行后的值为true则该角色生效,false和语法异常都不生效 。 如:\"${DATA.env}\"==\"sit\"&&(\"${DATA.test}\"==\"1\"||\"${DATA.test2}\"==\"aaa\")", + "datasources": "数据来源" } \ No newline at end of file diff --git a/src/resources/assets/languages/term/en.json b/src/resources/assets/languages/term/en.json index 5a8ddf1c..46417620 100644 --- a/src/resources/assets/languages/term/en.json +++ b/src/resources/assets/languages/term/en.json @@ -523,7 +523,8 @@ "eoadealwithusertip": "After setting the processor for the template, the processor cannot be modified during the editing process", "approvalstep": "Approval steps", "approvalprocess": "Approval process", - "approvalprocesstip": "At least one node must be added outside the [Create Sign off] node" + "approvalprocesstip": "At least one node must be added outside the [Create Sign off] node", + "matchmapping": "Matching mapping" }, "autoexec": { "addrootdirectory": "Add root directory", diff --git a/src/resources/assets/languages/term/zh.json b/src/resources/assets/languages/term/zh.json index 7f76991e..e5a7bfa3 100644 --- a/src/resources/assets/languages/term/zh.json +++ b/src/resources/assets/languages/term/zh.json @@ -522,7 +522,8 @@ "eoadealwithusertip": "模板设置处理人后,编辑流程时中不可修改处理人", "approvalstep": "审批步骤", "approvalprocess": "审批流", - "approvalprocesstip": "在【创建签报】节点之外,至少要添加一个节点" + "approvalprocesstip": "在【创建签报】节点之外,至少要添加一个节点", + "matchmapping": "匹配映射" }, "autoexec": { "addrootdirectory": "添加根目录", diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue index 9fe70495..ad9482b9 100644 --- a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue @@ -84,27 +84,7 @@ export default { value: { type: Object, default: () => { - return { - 'type': 'ci', - 'ciId': 1044706589786112, - 'workerList': [ - 1044706589786112, - 441190910533632 - ], - 'filterList': [ - { - 'key': 441190910533632, - 'formAttributeUuid': 'ca04365ff49c4c80b39cf802e857eeaa' - }, - { - 'key': 507682339217408, - 'formAttributeUuid': 'ba8b942b44ab4e29ba9a589f52a24807' - }], - 'priorityList': [ - 1044706589786112, - 441190910533632 - ] - }; + return {}; } } }, @@ -160,7 +140,7 @@ export default { 'required' ], url: 'api/rest/cmdb/ci/list', - label: '数据来源', + label: this.$t('page.datasources'), type: 'select', textName: 'text', valueName: 'value', @@ -175,7 +155,7 @@ export default { 'required' ], url: 'api/rest/cmdb/ci/list', - label: '匹配映射', + label: this.$t('term.process.matchmapping'), type: 'slot' }, { -- Gitee From 7f6ffa9133a277958e2389a0597a3bd167cff37d Mon Sep 17 00:00:00 2001 From: yaojn Date: Mon, 8 Jan 2024 15:24:35 +0800 Subject: [PATCH 04/12] =?UTF-8?q?-=20[=E5=8A=9F=E8=83=BD]=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ecmdb=E5=88=86=E6=B4=BE=E5=99=A8=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=AA=8C=E8=AF=81=E9=80=BB=E8=BE=91=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodesetting/dispatcher/cmdb-dispatcher.vue | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue index ad9482b9..093f67ce 100644 --- a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue @@ -330,15 +330,9 @@ export default { valid() { // 校验 let isValid = true; - let keyFormList = this.$refs.keyForm; - let formAttributeList = this.$refs.formAttribute; - for (let key = 0; key < keyFormList.length; key++) { - if (keyFormList[key] && keyFormList[key].valid && !keyFormList[key].valid()) { - isValid = false; - } - } - for (let key = 0; key < formAttributeList.length; key++) { - if (formAttributeList[key] && formAttributeList[key].valid && !formAttributeList[key].valid()) { + let formList = [this.$refs.keyForm, this.$refs.formAttribute]; + for (let key = 0; key < formList.length; key++) { + if (formList[key] && formList[key].valid && !formList[key].valid()) { isValid = false; } } -- Gitee From 49c9fae9d05ce55623180d537d4c5d2909a0809c Mon Sep 17 00:00:00 2001 From: yaojn Date: Mon, 8 Jan 2024 19:00:31 +0800 Subject: [PATCH 05/12] =?UTF-8?q?-=20[=E5=8A=9F=E8=83=BD]=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ecmdb=E5=88=86=E6=B4=BE=E5=99=A8=EF=BC=8C=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dispatcher/cmdb-dispatcher.vue | 120 +++++++++++------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue index 093f67ce..aae6cba4 100644 --- a/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue +++ b/src/views/pages/process/flow/flowedit/components/nodesetting/dispatcher/cmdb-dispatcher.vue @@ -8,6 +8,7 @@ style="width: 100%" >