36 changed files with 281 additions and 887 deletions
@ -1,8 +1,4 @@ |
|||
{ |
|||
"menu.testcase": "Test Case", |
|||
"menu.testcase.component": "Component", |
|||
"menu.testcase.dialog": "Dialog", |
|||
"menu.testcase.select": "Select", |
|||
"menu.testcase.treeGrid": "Tree Grid", |
|||
"menu.testcase.table": "Table" |
|||
"menu.testcase.formElements": "Form Elements" |
|||
} |
|||
|
@ -1,8 +1,4 @@ |
|||
{ |
|||
"menu.testcase": "測試用例", |
|||
"menu.testcase.component": "組件", |
|||
"menu.testcase.dialog": "Dialog", |
|||
"menu.testcase.select": "Select", |
|||
"menu.testcase.treeGrid": "Tree Grid", |
|||
"menu.testcase.table": "Table" |
|||
"menu.testcase.formElements": "表單控件" |
|||
} |
|||
|
@ -1,8 +1,4 @@ |
|||
{ |
|||
"menu.testcase": "测试用例", |
|||
"menu.testcase.component": "组件", |
|||
"menu.testcase.dialog": "Dialog", |
|||
"menu.testcase.select": "Select", |
|||
"menu.testcase.treeGrid": "Tree Grid", |
|||
"menu.testcase.table": "Table" |
|||
"menu.testcase.formElements": "表单控件" |
|||
} |
|||
|
@ -0,0 +1,170 @@ |
|||
<template> |
|||
<q-field v-bind="attrs" :stack-label="stackLabelRef" @focus="focus" @blur="blur"> |
|||
<template #control> |
|||
<div ref="codemirrorRef" style="width: 100%"></div> |
|||
</template> |
|||
</q-field> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs, onMounted, onUnmounted, onUpdated } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { EditorView } from '@codemirror/view'; |
|||
import { EditorState, Compartment } from '@codemirror/state'; |
|||
import * as view from '@codemirror/view'; |
|||
import * as language from '@codemirror/language'; |
|||
import * as commands from '@codemirror/commands'; |
|||
import * as search from '@codemirror/search'; |
|||
import * as autocomplete from '@codemirror/autocomplete'; |
|||
|
|||
import { LanguageSupport } from '@codemirror/language'; |
|||
import { html } from '@codemirror/lang-html'; |
|||
import { java } from '@codemirror/lang-java'; |
|||
import { javascript } from '@codemirror/lang-javascript'; |
|||
import { json } from '@codemirror/lang-json'; |
|||
import { sql } from '@codemirror/lang-sql'; |
|||
import { xml } from '@codemirror/lang-xml'; |
|||
|
|||
const attrs = useAttrs(); |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
lang: { type: String, default: 'json' }, |
|||
width: { type: [Number, String], default: '100%' }, |
|||
height: { type: [Number, String], default: undefined }, |
|||
rows: { type: Number, default: 4 }, |
|||
tabSize: { type: Number, default: 4 }, |
|||
}); |
|||
|
|||
const emits = defineEmits(['update:modelValue']); |
|||
|
|||
const basicSetup = [ |
|||
EditorState.allowMultipleSelections.of(true), |
|||
|
|||
//view.lineNumbers(), |
|||
//view.highlightActiveLine(), |
|||
view.highlightActiveLineGutter(), |
|||
view.highlightSpecialChars(), |
|||
view.drawSelection(), |
|||
view.dropCursor(), |
|||
view.rectangularSelection(), |
|||
view.crosshairCursor(), |
|||
|
|||
commands.history(), |
|||
|
|||
//language.foldGutter(), |
|||
language.indentOnInput(), |
|||
language.syntaxHighlighting(language.defaultHighlightStyle, { fallback: true }), |
|||
language.bracketMatching(), |
|||
|
|||
autocomplete.closeBrackets(), |
|||
autocomplete.autocompletion(), |
|||
|
|||
search.highlightSelectionMatches(), |
|||
|
|||
view.keymap.of([ |
|||
...commands.defaultKeymap, |
|||
...commands.historyKeymap, |
|||
...language.foldKeymap, |
|||
...autocomplete.completionKeymap, |
|||
...autocomplete.closeBracketsKeymap, |
|||
...search.searchKeymap, |
|||
//commands.indentWithTab, |
|||
]), |
|||
]; |
|||
|
|||
const getLanguage = (lang: string): LanguageSupport => { |
|||
lang = lang || 'json'; |
|||
switch (lang.toLowerCase()) { |
|||
case 'html': |
|||
return html(); |
|||
case 'java': |
|||
return java(); |
|||
case 'javascript': |
|||
return javascript(); |
|||
case 'json': |
|||
return json(); |
|||
case 'sql': |
|||
return sql(); |
|||
case 'xml': |
|||
return xml(); |
|||
default: |
|||
return json(); |
|||
} |
|||
}; |
|||
|
|||
const codemirrorRef = ref(); |
|||
// q-field 的 stack-label 属性是对 field 的 label 进行设置效果 |
|||
// 如果 field 有值时, 无论是否获得焦点 label 都缩小显示 |
|||
// 如果 field 无值时, 如果 field 获得焦点 label 就缩小显示, 否则 label 放大显示 |
|||
const stackLabelRef = ref(!Tools.isUndefinedOrNull(props.modelValue)); |
|||
|
|||
let editorView; |
|||
let isFocus = false; |
|||
|
|||
onMounted(() => { |
|||
if (codemirrorRef.value) { |
|||
let language = new Compartment(); |
|||
let tabSize = new Compartment(); |
|||
editorView = new EditorView({ |
|||
extensions: [ |
|||
basicSetup, |
|||
language.of(getLanguage(props.lang)), |
|||
tabSize.of(EditorState.tabSize.of(props.tabSize)), |
|||
EditorView.theme({ |
|||
'&': { |
|||
outline: 'none !important', |
|||
width: Tools.px(props.width), |
|||
height: props.height ? Tools.px(props.height) : props.rows * 22 + 'px', |
|||
}, |
|||
}), |
|||
// 以下代码可以添加内容变化后的操作, 为避免重复操作, 更新操作放到 blur 方法中了 |
|||
EditorView.updateListener.of(function (e) { |
|||
emits('update:modelValue', e.state.doc.toString()); |
|||
}), |
|||
], |
|||
parent: codemirrorRef.value, |
|||
doc: props.modelValue, |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
editorView.destroy(); |
|||
}); |
|||
|
|||
onUpdated(() => { |
|||
if (!isFocus) { |
|||
// 当未获得焦点时,更新变更, 当获得焦点时不能更新 |
|||
editorView.dispatch({ changes: { from: 0, to: editorView.state.doc.length, insert: props.modelValue } }); |
|||
} |
|||
}); |
|||
|
|||
const focus = () => { |
|||
isFocus = true; |
|||
stackLabelRef.value = true; |
|||
}; |
|||
|
|||
const blur = () => { |
|||
isFocus = false; |
|||
const content = editorView.state.doc.toString(); |
|||
//emits('update:modelValue', content); |
|||
if (content) { |
|||
stackLabelRef.value = true; |
|||
} else { |
|||
stackLabelRef.value = false; |
|||
} |
|||
}; |
|||
|
|||
const getValue = () => { |
|||
return editorView.state.doc.toString(); |
|||
}; |
|||
|
|||
const setValue = (value: string) => { |
|||
editorView.dispatch({ changes: { from: 0, to: editorView.state.doc.length, insert: value } }); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
getValue, |
|||
setValue, |
|||
}); |
|||
</script> |
@ -1,72 +0,0 @@ |
|||
import { |
|||
EditorView, |
|||
lineNumbers, |
|||
highlightActiveLineGutter, |
|||
highlightSpecialChars, |
|||
drawSelection, |
|||
dropCursor, |
|||
rectangularSelection, |
|||
crosshairCursor, |
|||
highlightActiveLine, |
|||
keymap, |
|||
} from '@codemirror/view'; |
|||
import { EditorState } from '@codemirror/state'; |
|||
import { foldGutter, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, foldKeymap } from '@codemirror/language'; |
|||
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands'; |
|||
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; |
|||
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete'; |
|||
import { lintKeymap } from '@codemirror/lint'; |
|||
|
|||
import { html } from '@codemirror/lang-html'; |
|||
import { java } from '@codemirror/lang-java'; |
|||
import { javascript } from '@codemirror/lang-javascript'; |
|||
import { json } from '@codemirror/lang-json'; |
|||
import { sql } from '@codemirror/lang-sql'; |
|||
import { xml } from '@codemirror/lang-xml'; |
|||
|
|||
export const basicSetup = [ |
|||
//lineNumbers(),
|
|||
highlightActiveLineGutter(), |
|||
highlightSpecialChars(), |
|||
history(), |
|||
//foldGutter(),
|
|||
drawSelection(), |
|||
dropCursor(), |
|||
EditorState.allowMultipleSelections.of(true), |
|||
indentOnInput(), |
|||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }), |
|||
bracketMatching(), |
|||
closeBrackets(), |
|||
autocompletion(), |
|||
rectangularSelection(), |
|||
crosshairCursor(), |
|||
//highlightActiveLine(),
|
|||
highlightSelectionMatches(), |
|||
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...searchKeymap, ...historyKeymap, ...foldKeymap, ...completionKeymap, ...lintKeymap]), |
|||
]; |
|||
|
|||
export const basicTheme = () => { |
|||
return EditorView.theme({ |
|||
'.cm-editor': { |
|||
outline: 'none !important', |
|||
}, |
|||
}); |
|||
}; |
|||
|
|||
export const getLanguage = (lang: string) => { |
|||
if (lang === 'html') { |
|||
return html(); |
|||
} else if (lang === 'java') { |
|||
return java(); |
|||
} else if (lang === 'javascript') { |
|||
return javascript(); |
|||
} else if (lang === 'json') { |
|||
return json(); |
|||
} else if (lang === 'sql') { |
|||
return sql(); |
|||
} else if (lang === 'xml') { |
|||
return xml(); |
|||
} else { |
|||
return json(); |
|||
} |
|||
}; |
@ -1,38 +0,0 @@ |
|||
<template> |
|||
<q-field :v-bind="attrs"> |
|||
<template #control> |
|||
<div ref="codemirrorRef" class="border border-red-500" style="padding-top: 1px"></div> |
|||
</template> |
|||
</q-field> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs, onMounted, onUnmounted } from 'vue'; |
|||
import { EditorView } from '@codemirror/view'; |
|||
import { basicSetup, basicTheme, getLanguage } from './Util'; |
|||
|
|||
const attrs = useAttrs(); |
|||
|
|||
const props = defineProps({ |
|||
lang: { type: String, default: 'json' }, |
|||
}); |
|||
|
|||
const codemirrorRef = ref(); |
|||
let view; |
|||
|
|||
onMounted(() => { |
|||
view = new EditorView({ |
|||
extensions: [basicSetup, getLanguage(props.lang), basicTheme()], |
|||
parent: codemirrorRef.value, |
|||
}); |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
view.destroy(); |
|||
}); |
|||
const value = ref('<xml><a name="name"></a></xml>'); |
|||
</script> |
|||
<style> |
|||
.cm-editor { |
|||
outline: none !important; |
|||
} |
|||
</style> |
@ -1,31 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<CodeMirror basic :lang="language" class="overflow-y-auto" v-bind="attrs"></CodeMirror> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { useAttrs, ref, onMounted } from 'vue'; |
|||
import CodeMirror from 'vue-codemirror6'; |
|||
import { java } from '@codemirror/lang-java'; |
|||
import { json } from '@codemirror/lang-json'; |
|||
import { sql } from '@codemirror/lang-sql'; |
|||
import { xml } from '@codemirror/lang-xml'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const props = defineProps({ |
|||
lang: { type: String, default: 'json' }, |
|||
}); |
|||
|
|||
let language = json(); |
|||
if (props.lang === 'java') { |
|||
language = java(); |
|||
} else if (props.lang === 'json') { |
|||
language = json(); |
|||
} else if (props.lang === 'sql') { |
|||
language = sql(); |
|||
} else if (props.lang === 'xml') { |
|||
language = xml(); |
|||
} |
|||
|
|||
console.log(props.lang); |
|||
</script> |
@ -1,7 +0,0 @@ |
|||
<template> |
|||
<q-select outlined emit-value map-options v-bind="attrs" /> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { useAttrs } from 'vue'; |
|||
const attrs = useAttrs(); |
|||
</script> |
@ -1,50 +0,0 @@ |
|||
<template> |
|||
<!-- <w-codemirror |
|||
v-model="value" |
|||
lang="xml" |
|||
placeholder="Code goes here..." |
|||
:autofocus="false" |
|||
:tab-size="2" |
|||
:style="{ height: '200px', padding: '20px' }" |
|||
></w-codemirror> --> |
|||
<q-input outlined label="OK"></q-input> |
|||
<label class="q-field row no-wrap items-start q-field--outlined q-input q-field--labeled" for="f_eef31e6a-a3a8-4a87-b35c-481f40af889e"> |
|||
<div class="q-field__inner relative-position col self-stretch"> |
|||
<div class="q-field__control relative-position row no-wrap" tabindex="-1"> |
|||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip"></div> |
|||
</div> |
|||
</div> |
|||
</label> |
|||
|
|||
<div class="rounded-md" style="border: 1px solid #e5e7eb"> |
|||
<div class="px-3 text-gray-600 text-xs">OK</div> |
|||
<div ref="codemirrorRef" class="py-1"></div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, onMounted, onUnmounted } from 'vue'; |
|||
import { EditorView, basicSetup } from 'codemirror'; |
|||
import { javascript } from '@codemirror/lang-javascript'; |
|||
|
|||
const codemirrorRef = ref(); |
|||
let view; |
|||
|
|||
onMounted(() => { |
|||
view = new EditorView({ |
|||
extensions: [basicSetup, javascript()], |
|||
parent: codemirrorRef.value, |
|||
}); |
|||
//view.destroy(); |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
console.log('>>>>>>'); |
|||
view.destroy(); |
|||
}); |
|||
const value = ref('<xml><a name="name"></a></xml>'); |
|||
</script> |
|||
<style> |
|||
.cm-editor2 { |
|||
outline: none !important; |
|||
} |
|||
</style> |
@ -1,29 +0,0 @@ |
|||
<template> |
|||
<q-splitter v-model="splitWidthRef" style="height: 250px"> |
|||
<template #before> |
|||
<q-tabs v-model="selectedTab" vertical no-caps> |
|||
<q-tab name="cron" label="w-cron" /> |
|||
<q-tab name="codemirror" label="w-code-mirror" /> |
|||
</q-tabs> |
|||
</template> |
|||
|
|||
<template #after> |
|||
<q-tab-panels v-model="selectedTab" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up"> |
|||
<q-tab-panel name="cron"> |
|||
<w-cron v-model="valueRef" label="cron" outlined dense style="width: 200px"></w-cron> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="codemirror"> |
|||
<w-code-mirror v-model="valueRef" label="codemirror" lang="sql" outlined dense></w-code-mirror> |
|||
<q-input v-model="valueRef" label="codemirror" outlined dense></q-input> |
|||
</q-tab-panel> |
|||
</q-tab-panels> |
|||
</template> |
|||
</q-splitter> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
|
|||
const selectedTab = ref('codemirror'); |
|||
const splitWidthRef = ref(20); |
|||
const valueRef = ref('* * * * * *'); |
|||
</script> |
@ -1,37 +0,0 @@ |
|||
<template> |
|||
<w-dialog |
|||
ref="dialogRef" |
|||
:persistent="true" |
|||
:maximized="true" |
|||
title="xxx" |
|||
width="50%" |
|||
height="50%" |
|||
:can-maximize="true" |
|||
:actions="[ |
|||
{ |
|||
icon: PlatformIconEnum.保存, |
|||
label: '保存', |
|||
loading: false, |
|||
click: async () => {}, |
|||
}, |
|||
]" |
|||
@maximize="dialogMaximize" |
|||
></w-dialog> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, reactive, onMounted } from 'vue'; |
|||
import { PlatformIconEnum, DialogManager } from '@/platform'; |
|||
|
|||
const dialogRef = ref(); |
|||
|
|||
const dialogMaximize = (maximizedToggle: boolean) => { |
|||
console.log(maximizedToggle); |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
//dialogRef.value.show(); |
|||
DialogManager.confirm('kdjflksjdf', () => { |
|||
console.log('ok'); |
|||
}); |
|||
}); |
|||
</script> |
@ -1,30 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<w-form :fields="fields" :cols-num-auto="false" :cols-num="3"></w-form> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
const fields = [ |
|||
{ |
|||
label: '姓名', |
|||
name: 'name', |
|||
type: 'text', |
|||
required: true, |
|||
colspan: 2, |
|||
button: { |
|||
round: false, |
|||
icon: 'home', |
|||
label: '选择', |
|||
click: () => { |
|||
console.info('11111'); |
|||
}, |
|||
}, |
|||
}, |
|||
{ |
|||
label: '年龄', |
|||
name: 'age', |
|||
type: 'number', |
|||
required: true, |
|||
}, |
|||
]; |
|||
</script> |
@ -0,0 +1,44 @@ |
|||
<template> |
|||
<q-splitter v-model="splitWidthRef"> |
|||
<template #before> |
|||
<q-tabs v-model="selectedTab" vertical no-caps> |
|||
<q-tab name="formElements" label="Form Elements" /> |
|||
<q-tab name="codemirror" label="w-code-mirror" /> |
|||
</q-tabs> |
|||
</template> |
|||
|
|||
<template #after> |
|||
<q-tab-panels v-model="selectedTab" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up"> |
|||
<q-tab-panel name="formElements"> |
|||
<w-form |
|||
:cols-num="1" |
|||
:fields="[ |
|||
{ name: 'color', label: 'please select color', type: 'color-input', outlined: true, dense: true }, |
|||
{ name: 'colorPalette', label: 'please select color palette', type: 'color-input-palette', outlined: true, dense: true }, |
|||
{ name: 'codemirror', label: 'please input SQL', type: 'code-mirror', outlined: true, lang: 'sql', dense: true, rows: 5 }, |
|||
{ name: 'cron', label: 'please input cron expression', type: 'cron', outlined: true, dense: true }, |
|||
{ name: 'position', label: 'please select position', type: 'position', outlined: true, dense: true }, |
|||
]" |
|||
> |
|||
</w-form> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="codemirror"> |
|||
<q-input v-model="valueRef" label="please input number 1:" outlined dense clearable></q-input> |
|||
<w-code-mirror v-model="valueRef" label="please input SQL:" lang="sql" outlined dense></w-code-mirror> |
|||
<q-input v-model="valueRef" label="please input number 2:" outlined dense clearable></q-input> |
|||
</q-tab-panel> |
|||
</q-tab-panels> |
|||
</template> |
|||
</q-splitter> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
|
|||
const selectedTab = ref('formElements'); |
|||
const splitWidthRef = ref(20); |
|||
const valueRef = ref('xxxx'); |
|||
|
|||
const focus = () => { |
|||
console.log('sfsdf'); |
|||
}; |
|||
</script> |
@ -1,4 +0,0 @@ |
|||
<template> |
|||
<div>2222</div> |
|||
</template> |
|||
<script setup lang="ts"></script> |
@ -1,22 +0,0 @@ |
|||
<template> |
|||
<w-select v-model="model" :options="options" label="Status" @update:model-value="valueChanged" /> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { useI18n } from 'vue-i18n'; |
|||
import { EnumTools } from '@/platform'; |
|||
import { QBtn } from 'quasar'; |
|||
|
|||
const { t } = useI18n(); |
|||
const model = ref('value'); |
|||
const options = ref(); |
|||
|
|||
EnumTools.fetch('io.sc.platform.flowable.enums.ProcessStatus', t).then((data) => { |
|||
console.log(data.map); |
|||
options.value = data.map; |
|||
}); |
|||
|
|||
const valueChanged = (value) => { |
|||
console.log(value); |
|||
}; |
|||
</script> |
@ -1,64 +0,0 @@ |
|||
<template> |
|||
<w-grid |
|||
:tree="true" |
|||
:title="$t('system.corporation.grid.title')" |
|||
:data-url="Environment.apiContextPath('/api/system/corporation')" |
|||
selection="multiple" |
|||
:checkbox-selection="false" |
|||
:pageable="false" |
|||
:full-screen-button="false" |
|||
:tree-icon=" |
|||
(row) => { |
|||
return { name: 'folder', color: 'amber' }; |
|||
} |
|||
" |
|||
:toolbar-configure="{ noIcon: false }" |
|||
:toolbar-actions="['refresh', 'separator', ['addTop', 'addChild'], 'edit', 'remove', 'separator', 'view']" |
|||
:columns="[ |
|||
{ width: '100%', name: 'name', label: $t('name') }, |
|||
{ width: 150, name: 'code', label: $t('code') }, |
|||
{ width: 90, name: 'dataComeFrom', label: $t('dataComeFrom'), format: Formater.enum(DataComeFromEnum) }, |
|||
{ width: 100, name: 'lastModifier', label: $t('lastModifier') }, |
|||
{ width: 110, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() }, |
|||
{ width: 80, name: 'enable', label: $t('status'), format: Formater.enableTag() }, |
|||
]" |
|||
:editor="{ |
|||
dialog: { |
|||
width: '600px', |
|||
height: '300px', |
|||
}, |
|||
form: { |
|||
colsNum: 1, |
|||
fields: [ |
|||
{ name: 'code', label: $t('code'), type: 'text', required: true }, |
|||
{ name: 'name', label: $t('name'), type: 'text', required: true }, |
|||
{ name: 'description', label: $t('description'), type: 'textarea', rows: 1 }, |
|||
{ name: 'enable', label: $t('enable'), type: 'checkbox', defaultValue: true }, |
|||
], |
|||
}, |
|||
}" |
|||
:viewer="{ |
|||
panel: { |
|||
columnNum: 1, |
|||
fields: [ |
|||
{ name: 'id', label: $t('id') }, |
|||
{ name: 'code', label: $t('code') }, |
|||
{ name: 'name', label: $t('name') }, |
|||
{ name: 'description', label: $t('description') }, |
|||
{ name: 'enable', label: $t('enable'), format: (value) => value }, |
|||
{ name: 'dataComeFrom', label: $t('dataComeFrom'), format: (value) => value }, |
|||
{ name: 'creator', label: $t('creator') }, |
|||
{ name: 'createDate', label: $t('createDate') }, |
|||
{ name: 'lastModifier', label: $t('lastModifier') }, |
|||
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: (value) => value }, |
|||
], |
|||
}, |
|||
}" |
|||
></w-grid> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { Environment,Formater,Options } from '@/platform'; |
|||
|
|||
|
|||
</script> |
@ -1,118 +0,0 @@ |
|||
<template> |
|||
<div class="flex flex-nowrap py-2"> |
|||
<div ref="titleContainerRef" class="flex items-end text-subtitle2 text-no-wrap">{{ title }}</div> |
|||
<q-space /> |
|||
<div ref="actionContainerRef" class="flex flex-nowrap"> |
|||
<!-- baseActions --> |
|||
<template v-for="(action, index) in baseActions" :key="'baseAction_' + index"> |
|||
<q-separator |
|||
v-if="action.separator" |
|||
vertical |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
/> |
|||
<q-btn |
|||
v-else |
|||
v-bind="action" |
|||
:id="action.name" |
|||
:disable="action.enableIf ? !action.enableIf() : false" |
|||
no-wrap |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
@click="action.click" |
|||
/> |
|||
</template> |
|||
|
|||
<!-- moreActions --> |
|||
<q-btn-dropdown v-if="moreActions && moreActions.length > 0" :label="$t('more')" class="class-action-item" style="margin-left: 5px"> |
|||
<q-list> |
|||
<template v-for="(action, index) in moreActions" :key="'moreAction_' + index"> |
|||
<q-separator v-if="action.separator" /> |
|||
<q-item v-else v-close-popup clickable @click="action.click"> |
|||
<q-item-section avatar style="min-width: 28px; padding-right: 0px"> |
|||
<q-icon :name="action.icon" size="20px" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label :v-bind="action">{{ action.label }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</template> |
|||
</q-list> |
|||
</q-btn-dropdown> |
|||
</div> |
|||
<q-resize-observer @resize="onResize" /> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform/utils'; |
|||
|
|||
const props = defineProps({ |
|||
title: { type: String, default: '' }, |
|||
actions: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
}); |
|||
|
|||
const titleContainerRef = ref(); |
|||
const actionContainerRef = ref(); |
|||
|
|||
const actions = props.actions; |
|||
const baseActions = ref(actions); |
|||
const moreActions = ref([]); |
|||
const isActionWidthInitializedRef = ref(false); |
|||
const moreActionWidth = 100; |
|||
|
|||
const onResize = (size) => { |
|||
if (Tools.isUndefinedOrNull(titleContainerRef.value) || Tools.isUndefinedOrNull(actionContainerRef.value)) { |
|||
return; |
|||
} |
|||
|
|||
if (!isActionWidthInitializedRef.value) { |
|||
const nodes = actionContainerRef.value.getElementsByClassName('class-action-item'); |
|||
for (let i = 0; i < actions.length; i++) { |
|||
actions[i].width = nodes[i].clientWidth + 10; |
|||
} |
|||
isActionWidthInitializedRef.value = true; |
|||
} |
|||
|
|||
const _baseActions = []; |
|||
const _moreActions = []; |
|||
const length = actions.length; |
|||
let availableWidth = size.width - titleContainerRef.value.clientWidth; |
|||
let width = 0; |
|||
let index = 0; |
|||
|
|||
for (; index < length; index++) { |
|||
console.log(index, width + actions[index].width, availableWidth); |
|||
if (width + actions[index].width > availableWidth) { |
|||
availableWidth -= moreActionWidth; |
|||
while (width > availableWidth) { |
|||
index--; |
|||
width -= actions[index].width; |
|||
_baseActions.pop(); |
|||
} |
|||
break; |
|||
} else { |
|||
_baseActions.push(actions[index]); |
|||
width += actions[index].width; |
|||
} |
|||
} |
|||
|
|||
for (; index < length; index++) { |
|||
_moreActions.push(actions[index]); |
|||
} |
|||
|
|||
baseActions.value = _baseActions; |
|||
moreActions.value = _moreActions; |
|||
}; |
|||
</script> |
@ -1,236 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<div v-if="executeProgress.show" class="row pt-2"> |
|||
<div class="col-2 pl-4">{{ $t('io.sc.engine.mv.result.task.progress') }}</div> |
|||
<div class="col-3"> |
|||
<q-linear-progress size="20px" :value="executeProgress.percentage" color="primary" rounded> </q-linear-progress> |
|||
</div> |
|||
<div class="col-7 pl-4">{{ executeProgress.message }}</div> |
|||
<div class="col-1"></div> |
|||
</div> |
|||
<w-grid |
|||
ref="gridRef" |
|||
:title="$t('menu.engine.mv.result')" |
|||
:config-button="true" |
|||
selection="multiple" |
|||
:checkbox-selection="false" |
|||
:data-url="Environment.apiContextPath('/api/mv/viewer/result')" |
|||
:pageable="true" |
|||
:pagination="{ |
|||
sortBy: 'validateDate', |
|||
descending: true, |
|||
}" |
|||
:toolbar-configure="{ noIcon: false }" |
|||
:toolbar-actions="[ |
|||
'refresh', |
|||
'separator', |
|||
{ |
|||
name: 'execute', |
|||
label: $t('io.sc.engine.mv.result.grid.toolbar.execute'), |
|||
icon: 'bi-play-circle', |
|||
click: () => { |
|||
executorDialogRef.open(); |
|||
}, |
|||
}, |
|||
'separator', |
|||
{ |
|||
name: 'detail', |
|||
label: $t('detail'), |
|||
icon: 'bi-display', |
|||
enableIf: (selecteds) => { |
|||
return selecteds && selecteds.length > 0; |
|||
}, |
|||
click: (selecteds) => { |
|||
if (selecteds && selecteds.length > 0) { |
|||
const selected = selecteds[0]; |
|||
resultDetailDialogRef.open(selected); |
|||
} |
|||
}, |
|||
}, |
|||
{ |
|||
extend: 'remove', |
|||
click: (selecteds) => { |
|||
if (selecteds && selecteds.length > 0) { |
|||
const selected = selecteds[0]; |
|||
axios |
|||
.request({ |
|||
url: Environment.apiContextPath('/api/mv/viewer/result'), |
|||
method: 'delete', |
|||
data: [{ validateDate: selected.validateDate, modelId: selected.modelId }], |
|||
}) |
|||
.then(() => { |
|||
gridRef.refresh(); |
|||
}); |
|||
} |
|||
}, |
|||
}, |
|||
'separator', |
|||
'view', |
|||
'separator', |
|||
'export', |
|||
]" |
|||
:columns="[ |
|||
{ width: 150, name: 'validateDate', label: $t('io.sc.engine.mv.result.grid.entity.validateDate') }, |
|||
{ width: 150, name: 'modelId', label: $t('io.sc.engine.mv.result.grid.entity.modelId') }, |
|||
{ width: 200, name: 'modelName', label: $t('io.sc.engine.mv.result.grid.entity.modelName') }, |
|||
{ width: 100, name: 'executeMode', label: $t('io.sc.engine.mv.result.grid.entity.executeMode') }, |
|||
{ width: 100, name: 'totalSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.totalSampleCount'), align: 'right' }, |
|||
{ width: 100, name: 'defaultSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.defaultSampleCount'), align: 'right' }, |
|||
{ |
|||
width: 900, |
|||
name: 'discrimination', |
|||
label: $t('io.sc.engine.mv.result.grid.entity.discrimination'), |
|||
columns: [ |
|||
{ |
|||
name: 'total', |
|||
label: $t('io.sc.engine.mv.result.grid.entity.total'), |
|||
columns: [ |
|||
{ width: 100, name: 'auc', label: $t('io.sc.engine.mv.result.grid.entity.auc') }, |
|||
{ width: 100, name: 'ar', label: $t('io.sc.engine.mv.result.grid.entity.ar') }, |
|||
{ width: 100, name: 'ks', label: $t('io.sc.engine.mv.result.grid.entity.ks') }, |
|||
], |
|||
}, |
|||
{ |
|||
name: 'quantitative', |
|||
label: $t('quantitative'), |
|||
columns: [ |
|||
{ width: 100, name: 'aucQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.auc') }, |
|||
{ width: 100, name: 'arQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.ar') }, |
|||
{ width: 100, name: 'ksQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.ks') }, |
|||
], |
|||
}, |
|||
{ |
|||
name: 'qualitative', |
|||
label: $t('qualitative'), |
|||
columns: [ |
|||
{ width: 100, name: 'aucQualitative', label: $t('io.sc.engine.mv.result.grid.entity.auc') }, |
|||
{ width: 100, name: 'arQualitative', label: $t('io.sc.engine.mv.result.grid.entity.ar') }, |
|||
{ width: 100, name: 'ksQualitative', label: $t('io.sc.engine.mv.result.grid.entity.ks') }, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
width: 200, |
|||
name: 'stability', |
|||
label: $t('io.sc.engine.mv.result.grid.entity.stability'), |
|||
columns: [ |
|||
{ width: 100, name: 'svd', label: $t('io.sc.engine.mv.result.grid.entity.svd') }, |
|||
{ width: 100, name: 'psi', label: $t('io.sc.engine.mv.result.grid.entity.psi') }, |
|||
], |
|||
}, |
|||
{ |
|||
width: 200, |
|||
name: 'scaleValidate', |
|||
label: $t('io.sc.engine.mv.result.grid.entity.scaleValidate'), |
|||
columns: [ |
|||
{ width: 100, name: 'chiSquare', label: $t('io.sc.engine.mv.result.grid.entity.chiSquare'), align: 'center', format: passOrNotFormater }, |
|||
{ width: 100, name: 'binomial', label: $t('io.sc.engine.mv.result.grid.entity.binomial'), align: 'center', format: passOrNotFormater }, |
|||
], |
|||
}, |
|||
]" |
|||
:viewer="{ |
|||
panel: { |
|||
columnNum: 1, |
|||
fields: [ |
|||
{ name: 'validateDate', label: $t('io.sc.engine.mv.result.grid.entity.validateDate') }, |
|||
{ |
|||
name: 'runtimeParameters', |
|||
label: $t('io.sc.engine.mv.result.grid.entity.runtimeParameters'), |
|||
format: (value) => { |
|||
let result = ''; |
|||
for (const item of value) { |
|||
result += |
|||
$t('io.sc.engine.mv.result.grid.entity.runtimeParameters.' + item.name) + |
|||
':' + |
|||
(Tools.isUndefinedOrNull(item.value) ? '' : item.value) + |
|||
'<br/>'; |
|||
} |
|||
return result; |
|||
}, |
|||
}, |
|||
{ name: 'modelId', label: $t('io.sc.engine.mv.result.grid.entity.modelId') }, |
|||
{ name: 'modelName', label: $t('io.sc.engine.mv.result.grid.entity.modelName') }, |
|||
{ name: 'executeMode', label: $t('io.sc.engine.mv.result.grid.entity.executeMode') }, |
|||
{ name: 'totalSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.totalSampleCount') }, |
|||
{ name: 'defaultSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.defaultSampleCount') }, |
|||
{ name: 'auc', label: $t('io.sc.engine.mv.result.grid.entity.total.auc') }, |
|||
{ name: 'ar', label: $t('io.sc.engine.mv.result.grid.entity.total.ar') }, |
|||
{ name: 'ks', label: $t('io.sc.engine.mv.result.grid.entity.total.ks') }, |
|||
{ name: 'aucQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.quantitative.auc') }, |
|||
{ name: 'arQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.quantitative.ar') }, |
|||
{ name: 'ksQuantitative', label: $t('io.sc.engine.mv.result.grid.entity.quantitative.ks') }, |
|||
{ name: 'aucQualitative', label: $t('io.sc.engine.mv.result.grid.entity.qualitative.auc') }, |
|||
{ name: 'arQualitative', label: $t('io.sc.engine.mv.result.grid.entity.qualitative.ar') }, |
|||
{ name: 'ksQualitative', label: $t('io.sc.engine.mv.result.grid.entity.qualitative.ks') }, |
|||
{ name: 'svd', label: $t('io.sc.engine.mv.result.grid.entity.svd') }, |
|||
{ name: 'psi', label: $t('io.sc.engine.mv.result.grid.entity.psi') }, |
|||
{ name: 'chiSquare', label: $t('io.sc.engine.mv.result.grid.entity.chiSquare'), format: Formater.none() }, |
|||
{ name: 'binomial', label: $t('io.sc.engine.mv.result.grid.entity.binomial'), format: Formater.none() }, |
|||
], |
|||
}, |
|||
}" |
|||
></w-grid> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, reactive } from 'vue'; |
|||
import { axios, Environment, Tools, Formater, NotifyManager } from '@/platform'; |
|||
|
|||
const gridRef = ref(); |
|||
const resultDetailDialogRef = ref(); |
|||
const executorDialogRef = ref(); |
|||
const executeProgress = reactive({ |
|||
show: false, |
|||
percentage: 0, |
|||
message: '', |
|||
}); |
|||
let executeProgressInterval; |
|||
|
|||
const passOrNotFormater = (value) => { |
|||
if (Tools.isUndefinedOrNull(value)) { |
|||
return ''; |
|||
} |
|||
if (value === 'PASS') { |
|||
return { |
|||
componentType: 'QIcon', |
|||
attrs: { name: 'bi-check-circle', size: '20px', color: 'green' }, |
|||
}; |
|||
} else { |
|||
return { |
|||
componentType: 'QIcon', |
|||
attrs: { name: 'bi-x-circle', size: '20px', color: 'red' }, |
|||
}; |
|||
} |
|||
}; |
|||
|
|||
const afterStartExecute = () => { |
|||
executeProgress.show = true; |
|||
executeProgress.percentage = 0; |
|||
executeProgressInterval = setInterval(() => { |
|||
axios |
|||
.get(Environment.apiContextPath('/api/mv/traceExecuteProgress')) |
|||
.then((response) => { |
|||
const progressInfo = response.data; |
|||
executeProgress.percentage = progressInfo.currentWeight / progressInfo.totalWeight; |
|||
executeProgress.message = progressInfo.messageKey; |
|||
if (executeProgress.percentage >= 1) { |
|||
clearInterval(executeProgressInterval); |
|||
executeProgress.show = false; |
|||
gridRef.value.refresh(); |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
clearInterval(executeProgressInterval); |
|||
executeProgress.show = false; |
|||
gridRef.value.refresh(); |
|||
}); |
|||
}, 1000); |
|||
}; |
|||
|
|||
axios.get(Environment.apiContextPath('/api/mv/isExistsRunningExecutor')).then((response) => { |
|||
if (response.data) { |
|||
afterStartExecute(); |
|||
} |
|||
}); |
|||
</script> |
Loading…
Reference in new issue