Browse Source

update

main
wangshaoping 1 year ago
parent
commit
d3a8384fe8
  1. 2
      gradle.properties
  2. 6
      io.sc.engine.mv.frontend/package.json
  3. 2
      io.sc.engine.mv/src/main/resources/META-INF/platform/plugins/liquibase.json
  4. 2
      io.sc.engine.mv/src/main/resources/liquibase/io.sc.engine.mv_8.0.0_20221020__Model Validate Database Schema DDL.xml
  5. 3
      io.sc.platform.core.frontend/package.json
  6. 2
      io.sc.platform.core.frontend/src/components/index.ts
  7. 2
      io.sc.platform.core.frontend/src/i18n/messages.json
  8. 2
      io.sc.platform.core.frontend/src/i18n/messages_tw_CN.json
  9. 2
      io.sc.platform.core.frontend/src/i18n/messages_zh_CN.json
  10. 9
      io.sc.platform.core.frontend/src/menus/menus.json
  11. 9
      io.sc.platform.core.frontend/src/platform/components/index.ts
  12. 47
      io.sc.platform.core.frontend/src/platform/components/widget/codemirror/WCodemirror.vue
  13. 31
      io.sc.platform.core.frontend/src/platform/components/widget/codemirror/WCodemirror2.vue
  14. 251
      io.sc.platform.core.frontend/src/platform/components/widget/cron/DaySegment.vue
  15. 185
      io.sc.platform.core.frontend/src/platform/components/widget/cron/HourSegment.vue
  16. 185
      io.sc.platform.core.frontend/src/platform/components/widget/cron/MinuteSegment.vue
  17. 197
      io.sc.platform.core.frontend/src/platform/components/widget/cron/MonthSegment.vue
  18. 185
      io.sc.platform.core.frontend/src/platform/components/widget/cron/SecondSegment.vue
  19. 90
      io.sc.platform.core.frontend/src/platform/components/widget/cron/WCron.vue
  20. 233
      io.sc.platform.core.frontend/src/platform/components/widget/cron/WeekSegment.vue
  21. 93
      io.sc.platform.core.frontend/src/platform/components/widget/cron/YearSegment.vue
  22. 70
      io.sc.platform.core.frontend/src/platform/i18n/messages.json
  23. 70
      io.sc.platform.core.frontend/src/platform/i18n/messages_tw_CN.json
  24. 70
      io.sc.platform.core.frontend/src/platform/i18n/messages_zh_CN.json
  25. 3
      io.sc.platform.core.frontend/src/platform/index.ts
  26. 1
      io.sc.platform.core.frontend/src/platform/plugin/quasar.ts
  27. 12
      io.sc.platform.core.frontend/src/routes/routes.json
  28. 2
      io.sc.platform.core.frontend/src/views/Codemirror.vue
  29. 29
      io.sc.platform.core.frontend/src/views/Component.vue
  30. 4
      io.sc.platform.core.frontend/template-project/package.json
  31. 48
      io.sc.platform.core.frontend/template-project/src/views/Codemirror.vue
  32. 2
      io.sc.platform.core/src/main/java/io/sc/platform/core/autoconfigure/support/DateJsonDeserializer.java
  33. 9
      io.sc.platform.core/src/main/java/io/sc/platform/core/util/StringUtil.java
  34. 13
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words.properties
  35. 13
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words_tw_CN.properties
  36. 13
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words_zh_CN.properties
  37. 6
      io.sc.platform.developer.frontend/package.json
  38. 4
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/liquibase.json
  39. 2
      io.sc.platform.flowable/src/main/resources/liquibase/io.sc.platform.flowable_8.0.0_20220606__Flowable(6.8.0) Database Schema DDL.xml
  40. 2
      io.sc.platform.flowable/src/main/resources/liquibase/io.sc.platform.flowable_8.0.0_20220606__Process Manager Database Schema DDL.xml
  41. 2
      io.sc.platform.gradle/templates/pgp/app/build.gradle
  42. 2
      io.sc.platform.gradle/templates/pgp/setup/gradle.properties
  43. 6
      io.sc.platform.lcdp.frontend/package.json
  44. 2
      io.sc.platform.lcdp/src/main/resources/META-INF/platform/plugins/liquibase.json
  45. 2
      io.sc.platform.lcdp/src/main/resources/liquibase/io.sc.platform.lcdp_8.0.0_20220606__LowCode Developer Database Schema DDL.xml
  46. 6
      io.sc.platform.mvc.frontend/package.json
  47. 5
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/ArrayStringConverter.java
  48. 5
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/ListStringConverter.java
  49. 5
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/SetStringConverter.java
  50. 51
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/impl/DaoServiceImpl.java
  51. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Between.java
  52. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/BetweenInclusive.java
  53. 9
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Contains.java
  54. 9
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Equals.java
  55. 16
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/GreaterThan.java
  56. 9
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/IContains.java
  57. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/IEquals.java
  58. 52
      io.sc.platform.scheduler.core/src/main/java/io/sc/platform/scheduler/core/vo/GlueVo.java
  59. 130
      io.sc.platform.scheduler.core/src/main/java/io/sc/platform/scheduler/core/vo/TaskVo.java
  60. 5
      io.sc.platform.scheduler.core/src/main/resources/META-INF/platform/plugins/messages.json
  61. 35
      io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages.properties
  62. 35
      io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages_tw_CN.properties
  63. 35
      io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages_zh_CN.properties
  64. 121
      io.sc.platform.scheduler.manager.frontend/src/views/scheduler/Executor.vue
  65. 285
      io.sc.platform.scheduler.manager.frontend/src/views/scheduler/Task.vue
  66. 15
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/ExecutorWebController.java
  67. 15
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/ReportWebController.java
  68. 15
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/TaskWebController.java
  69. 4
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/ExecutorEntity.java
  70. 91
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/GlueEntity.java
  71. 4
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/ReportEntity.java
  72. 174
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/TaskEntity.java
  73. 5
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/repository/TaskLogReportRepository.java
  74. 9
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/ExecutorService.java
  75. 7
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/ReportService.java
  76. 9
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/TaskService.java
  77. 12
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/ExecutorServiceImpl.java
  78. 13
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/ReportServiceImpl.java
  79. 12
      io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/TaskServiceImpl.java
  80. 6
      io.sc.platform.security.frontend/package.json
  81. 2
      io.sc.platform.security/src/main/resources/META-INF/platform/plugins/liquibase.json
  82. 2
      io.sc.platform.security/src/main/resources/liquibase/io.sc.platform.security_8.0.0_20220606__Security Database Schema DDL.xml
  83. 6
      io.sc.platform.system.frontend/package.json
  84. 2
      io.sc.platform.system/src/main/resources/META-INF/platform/plugins/liquibase.json
  85. 2
      io.sc.platform.system/src/main/resources/liquibase/io.sc.platform.system_8.0.0_20220606__System Database Schema DDL.xml

2
gradle.properties

@ -36,7 +36,7 @@ application_version=1.0.0
# platform
###########################################################
platform_group=io.sc
platform_version=8.1.23
platform_version=8.1.24
platform_plugin_version=8.1.13
platform_core_frontend_version=8.1.119

6
io.sc.engine.mv.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.engine.mv.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -102,4 +102,4 @@
"codemirror": "6.0.1",
"vue-codemirror6": "1.2.0"
}
}
}

2
io.sc.engine.mv/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -16,7 +16,7 @@
"order" : 100,
"description":"模型验证模块表结构及其初始化菜单",
"locations":[
"liquibase/MV_1.0.0_20160918__Model Validate Database Schema DDL.xml"
"liquibase/io.sc.engine.mv_8.0.0_20221020__Model Validate Database Schema DDL.xml"
]
}
]

2
io.sc.engine.mv/src/main/resources/liquibase/MV_1.0.0_20160918__Model Validate Database Schema DDL.xml → io.sc.engine.mv/src/main/resources/liquibase/io.sc.engine.mv_8.0.0_20221020__Model Validate Database Schema DDL.xml

@ -6,7 +6,7 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="MV_1.0.0_20160918__Model Validate Database Schema DDL" author="framework">
<changeSet id="io.sc.engine.mv_8.0.0_20221020__Model Validate Database Schema DDL" author="framework">
<!-- 数据源接口表 -->
<createTable tableName="MV_SCORE_RECORD" remarks="评级预测记录表">
<column name="FD_CUSTOM_ID" type="NVARCHAR(36)" remarks="客户标识"></column>

3
io.sc.platform.core.frontend/package.json

@ -1,6 +1,6 @@
{
"name": "platform-core",
"version": "8.1.120",
"version": "8.1.122",
"description": "前端核心包,用于快速构建前端的脚手架",
"//main": "库的主文件",
"main": "dist/platform-core.js",
@ -99,6 +99,7 @@
"dependencies": {
"@codemirror/autocomplete": "6.11.1",
"@codemirror/commands": "6.3.3",
"@codemirror/lint": "6.5.0",
"@codemirror/lang-html": "6.4.7",
"@codemirror/lang-java": "6.0.1",
"@codemirror/lang-javascript": "6.2.1",

2
io.sc.platform.core.frontend/src/components/index.ts

@ -2,6 +2,7 @@
* ,
*/
import component from '@/views/Component.vue';
import dialog from '@/views/Dialog.vue';
import codemirror from '@/views/Codemirror.vue';
import select from '@/views/Select.vue';
@ -17,6 +18,7 @@ import gridLayout from '@/views/likm/GridLayout.vue';
import likmTreeGrid from '@/views/likm/TreeGrid.vue';
const localComponents = {
'component.testcase.component': component,
'component.testcase.dialog': dialog,
'component.testcase.codemirror': codemirror,
'component.testcase.select': select,

2
io.sc.platform.core.frontend/src/i18n/messages.json

@ -1,6 +1,6 @@
{
"menu.testcase": "Test Case",
"menu.testcase.codemirror": "CodeMirror",
"menu.testcase.component": "Component",
"menu.testcase.dialog": "Dialog",
"menu.testcase.select": "Select",
"menu.testcase.treeGrid": "Tree Grid",

2
io.sc.platform.core.frontend/src/i18n/messages_tw_CN.json

@ -1,6 +1,6 @@
{
"menu.testcase": "測試用例",
"menu.testcase.codemirror": "CodeMirror",
"menu.testcase.component": "組件",
"menu.testcase.dialog": "Dialog",
"menu.testcase.select": "Select",
"menu.testcase.treeGrid": "Tree Grid",

2
io.sc.platform.core.frontend/src/i18n/messages_zh_CN.json

@ -1,6 +1,6 @@
{
"menu.testcase": "测试用例",
"menu.testcase.codemirror": "CodeMirror",
"menu.testcase.component": "组件",
"menu.testcase.dialog": "Dialog",
"menu.testcase.select": "Select",
"menu.testcase.treeGrid": "Tree Grid",

9
io.sc.platform.core.frontend/src/menus/menus.json

@ -18,6 +18,15 @@
[
{ "type": "GROUP", "order": 20000, "id": "menu.testcase", "titleI18nKey": "menu.testcase", "icon": "bi-gear" },
{
"type": "ROUTE",
"order": 100,
"parentId": "menu.testcase",
"id": "menu.testcase.component",
"titleI18nKey": "menu.testcase.component",
"icon": "bi-palette",
"routeName": "route.testcase.component"
},
{
"type": "ROUTE",
"order": 200,

9
io.sc.platform.core.frontend/src/platform/components/index.ts

@ -5,8 +5,9 @@ import WVExpandDiv from './layout/WVExpandDiv.vue';
import WIconEmpty from './icon/WIconEmpty.vue';
import WColorInput from './widget/color/WColorInput.vue';
import WColorInputPalette from './widget/color/WColorInputPalette.vue';
import WCron from './widget/cron/WCron.vue';
import WPosition from './widget/position/WPosition.vue';
import WCodemirror from './widget/codemirror/WCodemirror.vue';
import WCodeMirror from './widget/codemirror/WCodeMirror.vue';
import WTreeGrid from './tree/WTreeGrid.vue';
import WDialog from './dialog/WDialog.vue';
@ -38,8 +39,9 @@ export default {
app.component('WVExpandDiv', WVExpandDiv);
app.component('WColorInput', WColorInput);
app.component('WColorInputPalette', WColorInputPalette);
app.component('WCron', WCron);
app.component('WPosition', WPosition);
app.component('WCodemirror', WCodemirror);
app.component('WCodeMirror', WCodeMirror);
app.component('WSelect', WSelect);
app.component('WTreeGrid', WTreeGrid);
@ -70,8 +72,9 @@ export {
WHScreenDiv,
WColorInput,
WColorInputPalette,
WCron,
WPosition,
WCodemirror,
WCodeMirror,
WSelect,
WTreeGrid,
WDialog,

47
io.sc.platform.core.frontend/src/platform/components/widget/codemirror/WCodemirror.vue

@ -1,31 +1,38 @@
<template>
<div>
<CodeMirror basic :lang="language" class="overflow-y-auto" v-bind="attrs"></CodeMirror>
</div>
<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 { 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';
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' },
});
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();
}
const codemirrorRef = ref();
let view;
onMounted(() => {
view = new EditorView({
extensions: [basicSetup, getLanguage(props.lang), basicTheme()],
parent: codemirrorRef.value,
});
});
console.log(props.lang);
onUnmounted(() => {
view.destroy();
});
const value = ref('<xml><a name="name"></a></xml>');
</script>
<style>
.cm-editor {
outline: none !important;
}
</style>

31
io.sc.platform.core.frontend/src/platform/components/widget/codemirror/WCodemirror2.vue

@ -0,0 +1,31 @@
<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>

251
io.sc.platform.core.frontend/src/platform/components/widget/cron/DaySegment.vue

@ -0,0 +1,251 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.day.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.day.notSpecify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.day.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.day.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.day.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.day.per2.1') }}</span>
<q-input
v-model="per2FromRef"
type="number"
:disable="!per2FromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.day.per2.2') }}</span>
<q-input
v-model="per2PerRef"
type="number"
:disable="!per2PerEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.day.per2.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="workDay" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.day.workDay.1') }}</span>
<q-input
v-model="workDayRef"
type="number"
:disable="!workDayEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.day.workDay.2') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="lastDay" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.day.lastDay') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.day.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>
<div class="row">
<template v-for="index in 31" :key="index">
<template v-if="index % 10 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + index"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 10 === 0">
<div class="col-1"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const per2FromEnableRef = ref(false);
const per2FromRef = ref('');
const per2PerEnableRef = ref(false);
const per2PerRef = ref('');
const workDayEnableRef = ref(false);
const workDayRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 31; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
workDayEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
workDayEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'per2') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = true;
per2PerEnableRef.value = true;
workDayEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'workDay') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
workDayEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'lastDay') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
workDayEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
workDayEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'per2') {
valueRef.value = per2FromRef.value + '/' + per2PerRef.value;
} else if (modeRef.value === 'workDay') {
valueRef.value = workDayRef.value + 'W';
} else if (modeRef.value === 'lastDay') {
valueRef.value = 'L';
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 31; i++) {
if (optionsRef.value[i]) {
seconds.push(i + 1);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

185
io.sc.platform.core.frontend/src/platform/components/widget/cron/HourSegment.vue

@ -0,0 +1,185 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.hour.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.hour.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.hour.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.hour.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.hour.per2.1') }}</span>
<q-input
v-model="per2FromRef"
type="number"
:disable="!per2FromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.hour.per2.2') }}</span>
<q-input
v-model="per2PerRef"
type="number"
:disable="!per2PerEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.hour.per2.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.hour.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-item-label>
<div class="row">
<template v-for="index in 24" :key="index">
<template v-if="index % 8 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + (index - 1)"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 8 === 0">
<div class="col-3"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const per2FromEnableRef = ref(false);
const per2FromRef = ref('');
const per2PerEnableRef = ref(false);
const per2PerRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 24; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'per2') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = true;
per2PerEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'per2') {
valueRef.value = per2FromRef.value + '/' + per2PerRef.value;
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 24; i++) {
if (optionsRef.value[i]) {
seconds.push(i);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

185
io.sc.platform.core.frontend/src/platform/components/widget/cron/MinuteSegment.vue

@ -0,0 +1,185 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.minute.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.minute.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.minute.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.minute.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.minute.per2.1') }}</span>
<q-input
v-model="per2FromRef"
type="number"
:disable="!per2FromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.minute.per2.2') }}</span>
<q-input
v-model="per2PerRef"
type="number"
:disable="!per2PerEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.minute.per2.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.minute.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-item-label>
<div class="row">
<template v-for="index in 60" :key="index">
<template v-if="index % 10 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + (index - 1)"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 10 === 0">
<div class="col-1"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const per2FromEnableRef = ref(false);
const per2FromRef = ref('');
const per2PerEnableRef = ref(false);
const per2PerRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 60; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'per2') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = true;
per2PerEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'per2') {
valueRef.value = per2FromRef.value + '/' + per2PerRef.value;
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 60; i++) {
if (optionsRef.value[i]) {
seconds.push(i);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

197
io.sc.platform.core.frontend/src/platform/components/widget/cron/MonthSegment.vue

@ -0,0 +1,197 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.month.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.month.notSpecify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.month.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.month.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.month.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.month.per2.1') }}</span>
<q-input
v-model="per2FromRef"
type="number"
:disable="!per2FromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.month.per2.2') }}</span>
<q-input
v-model="per2PerRef"
type="number"
:disable="!per2PerEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.month.per2.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.month.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>
<div class="row">
<template v-for="index in 12" :key="index">
<template v-if="index % 6 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + index"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 6 === 0">
<div class="col-5"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const per2FromEnableRef = ref(false);
const per2FromRef = ref('');
const per2PerEnableRef = ref(false);
const per2PerRef = ref('');
const workDayEnableRef = ref(false);
const workDayRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 12; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'per2') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = true;
per2PerEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'per2') {
valueRef.value = per2FromRef.value + '/' + per2PerRef.value;
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 12; i++) {
if (optionsRef.value[i]) {
seconds.push(i + 1);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

185
io.sc.platform.core.frontend/src/platform/components/widget/cron/SecondSegment.vue

@ -0,0 +1,185 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.second.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.second.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.second.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.second.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.second.per2.1') }}</span>
<q-input
v-model="per2FromRef"
type="number"
:disable="!per2FromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.second.per2.2') }}</span>
<q-input
v-model="per2PerRef"
type="number"
:disable="!per2PerEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.second.per2.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.second.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-item-label>
<div class="row">
<template v-for="index in 60" :key="index">
<template v-if="index % 10 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + (index - 1)"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 10 === 0">
<div class="col-1"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const per2FromEnableRef = ref(false);
const per2FromRef = ref('');
const per2PerEnableRef = ref(false);
const per2PerRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 60; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'per2') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = true;
per2PerEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
per2FromEnableRef.value = false;
per2PerEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'per2') {
valueRef.value = per2FromRef.value + '/' + per2PerRef.value;
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 60; i++) {
if (optionsRef.value[i]) {
seconds.push(i);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

90
io.sc.platform.core.frontend/src/platform/components/widget/cron/WCron.vue

@ -0,0 +1,90 @@
<template>
<q-input v-model="valueRef" :v-bind="attrs">
<template #append>
<!-- 选择颜色按钮 -->
<q-btn icon="bi-pencil-square" padding="2px" flat square unelevated :title="$t('select')">
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]" style="width: 800px">
<q-tabs v-model="selectedTab" no-caps>
<q-tab name="second" :label="$t('second')" />
<q-tab name="minute" :label="$t('minute')" />
<q-tab name="hour" :label="$t('hour')" />
<q-tab name="day" :label="$t('day')" />
<q-tab name="month" :label="$t('month')" />
<q-tab name="week" :label="$t('week')" />
<q-tab name="year" :label="$t('year')" />
</q-tabs>
<q-tab-panels v-model="selectedTab" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up" :keep-alive="true">
<q-tab-panel name="second">
<SecondSegment v-model="secondValueRef" @update:model-value="valueChanged"></SecondSegment>
</q-tab-panel>
<q-tab-panel name="minute">
<MinuteSegment v-model="minuteValueRef" @update:model-value="valueChanged"></MinuteSegment>
</q-tab-panel>
<q-tab-panel name="hour">
<HourSegment v-model="hourValueRef" @update:model-value="valueChanged"></HourSegment>
</q-tab-panel>
<q-tab-panel name="day">
<DaySegment v-model="dayValueRef" @update:model-value="valueChanged"></DaySegment>
</q-tab-panel>
<q-tab-panel name="month">
<MonthSegment v-model="monthValueRef" @update:model-value="valueChanged"></MonthSegment>
</q-tab-panel>
<q-tab-panel name="week">
<WeekSegment v-model="weekValueRef" @update:model-value="valueChanged"></WeekSegment>
</q-tab-panel>
<q-tab-panel name="year">
<YearSegment v-model="yearValueRef" @update:model-value="valueChanged"></YearSegment>
</q-tab-panel>
</q-tab-panels>
</q-popup-proxy>
</q-btn>
</template>
</q-input>
</template>
<script setup lang="ts">
import { ref, useAttrs } from 'vue';
import { Tools } from '@/platform';
import SecondSegment from './SecondSegment.vue';
import MinuteSegment from './MinuteSegment.vue';
import HourSegment from './HourSegment.vue';
import DaySegment from './DaySegment.vue';
import MonthSegment from './MonthSegment.vue';
import WeekSegment from './WeekSegment.vue';
import YearSegment from './YearSegment.vue';
const attrs = useAttrs();
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const isShow = ref(false);
const selectedTab = ref('second');
const valueRef = ref(props.modelValue);
const splits = props.modelValue.split(' ');
const secondValueRef = ref(splits[0]);
const minuteValueRef = ref(splits[1]);
const hourValueRef = ref(splits[2]);
const dayValueRef = ref(splits[3]);
const monthValueRef = ref(splits[4]);
const weekValueRef = ref(splits[5]);
const yearValueRef = ref(splits[6]);
const valueChanged = () => {
const values = [];
values.push(secondValueRef.value ? secondValueRef.value : '*');
values.push(minuteValueRef.value ? minuteValueRef.value : '*');
values.push(hourValueRef.value ? hourValueRef.value : '*');
values.push(dayValueRef.value ? dayValueRef.value : '*');
values.push(monthValueRef.value ? monthValueRef.value : '*');
values.push(weekValueRef.value ? weekValueRef.value : '*');
values.push(yearValueRef.value ? yearValueRef.value : '*');
const result = Tools.join(values, ' ');
valueRef.value = result;
emit('update:modelValue', result);
};
</script>

233
io.sc.platform.core.frontend/src/platform/components/widget/cron/WeekSegment.vue

@ -0,0 +1,233 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.week.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.week.notSpecify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.week.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.week.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.week.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="weekOfYear" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.week.weekOfYear.1') }}</span>
<q-input
v-model="weekOfYearRef"
type="number"
:disable="!weekOfYearEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.week.weekOfYear.2') }}</span>
<q-input
v-model="dayOfWeekRef"
type="number"
:disable="!dayOfWeekEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.week.weekOfYear.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="lastWeek" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.week.lastDay.1') }}</span>
<q-input
v-model="lastWeekRef"
type="number"
:disable="!lastWeekEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.week.lastDay.2') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.week.specify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>
<div class="row">
<template v-for="index in 7" :key="index">
<template v-if="index % 7 === 1">
<div class="col-1"></div>
</template>
<div class="col-1">
<q-checkbox
v-model="optionsRef[index - 1]"
dense
:label="'' + index"
:disable="!optionsEnableRef"
@update:model-value="valueChanged"
></q-checkbox>
</div>
<template v-if="index % 7 === 0">
<div class="col-5"></div>
</template>
</template>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const weekOfYearEnableRef = ref(false);
const weekOfYearRef = ref('');
const dayOfWeekEnableRef = ref(false);
const dayOfWeekRef = ref('');
const lastWeekEnableRef = ref(false);
const lastWeekRef = ref('');
const optionsEnableRef = ref(false);
const optionsRef = ref([]);
for (let i = 0; i < 7; i++) {
optionsRef.value.push(false);
}
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
weekOfYearEnableRef.value = false;
dayOfWeekEnableRef.value = false;
lastWeekEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
weekOfYearEnableRef.value = false;
dayOfWeekEnableRef.value = false;
lastWeekEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'weekOfYear') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
weekOfYearEnableRef.value = true;
dayOfWeekEnableRef.value = true;
lastWeekEnableRef.value = false;
optionsEnableRef.value = false;
} else if (modeRef.value === 'lastWeek') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
weekOfYearEnableRef.value = false;
dayOfWeekEnableRef.value = false;
lastWeekEnableRef.value = true;
optionsEnableRef.value = false;
} else if (modeRef.value === 'specify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
weekOfYearEnableRef.value = false;
dayOfWeekEnableRef.value = false;
lastWeekEnableRef.value = false;
optionsEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
} else if (modeRef.value === 'weekOfYear') {
valueRef.value = weekOfYearRef.value + '/' + dayOfWeekRef.value;
} else if (modeRef.value === 'lastWeek') {
valueRef.value = lastWeekRef.value + 'L';
} else if (modeRef.value === 'specify') {
let seconds = [];
for (let i = 0; i < 7; i++) {
if (optionsRef.value[i]) {
seconds.push(i + 1);
}
}
valueRef.value = Tools.join(seconds, ',');
}
emit('update:modelValue', valueRef.value);
};
</script>

93
io.sc.platform.core.frontend/src/platform/components/widget/cron/YearSegment.vue

@ -0,0 +1,93 @@
<template>
<q-list dense style="width: 100%">
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.year.per') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('cron.year.notSpecify') }}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" />
</q-item-section>
<q-item-section>
<q-item-label>
<div class="row no-wrap items-center">
<span class="pr-2">{{ $t('cron.year.period.1') }}</span>
<q-input
v-model="periodFromRef"
type="number"
:disable="!periodFromEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.year.period.2') }}</span>
<q-input
v-model="periodToRef"
type="number"
:disable="!periodToEnableRef"
outlined
dense
style="width: 100px"
@update:model-value="valueChanged"
></q-input>
<span class="px-2">{{ $t('cron.year.period.3') }}</span>
</div>
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Tools } from '@/platform';
const props = defineProps({
modelValue: { type: String, default: '' },
});
const emit = defineEmits(['update:modelValue']);
const valueRef = ref(props.modelValue);
const modeRef = ref('');
const periodFromEnableRef = ref(false);
const periodFromRef = ref('');
const periodToEnableRef = ref(false);
const periodToRef = ref('');
const valueChanged = () => {
if (modeRef.value === 'per') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
} else if (modeRef.value === 'notSpecify') {
periodFromEnableRef.value = false;
periodToEnableRef.value = false;
} else if (modeRef.value === 'period') {
periodFromEnableRef.value = true;
periodToEnableRef.value = true;
}
if (modeRef.value === 'per') {
valueRef.value = '*';
} else if (modeRef.value === 'notSpecify') {
valueRef.value = '';
} else if (modeRef.value === 'period') {
valueRef.value = periodFromRef.value + '-' + periodToRef.value;
}
emit('update:modelValue', valueRef.value);
};
</script>

70
io.sc.platform.core.frontend/src/platform/i18n/messages.json

@ -46,5 +46,73 @@
"tabs.close.all":"Close All Tab",
"theme": "Theme",
"upToTop": "Up to Top",
"passwordAndConfirmPasswordMustEqual": "Confrim Password and Password must equals"
"passwordAndConfirmPasswordMustEqual": "Confrim Password and Password must equals",
"cron.second.per": "Per Second",
"cron.second.period.1": "From",
"cron.second.period.2": " Second, To ",
"cron.second.period.3": " Second",
"cron.second.per2.1": "From",
"cron.second.per2.2": "Second, Once Per",
"cron.second.per2.3": "Seconds",
"cron.second.specify": "Specify",
"cron.minute.per": "Per Minute",
"cron.minute.period.1": "From",
"cron.minute.period.2": " Minute, To ",
"cron.minute.period.3": " Minute",
"cron.minute.per2.1": "From",
"cron.minute.per2.2": "Minute, Once Per",
"cron.minute.per2.3": "Minutes",
"cron.minute.specify": "Specify",
"cron.hour.per": "Per Hour",
"cron.hour.period.1": "From",
"cron.hour.period.2": " Hour, To ",
"cron.hour.period.3": " Hour",
"cron.hour.per2.1": "From",
"cron.hour.per2.2": "Hour, Once Per",
"cron.hour.per2.3": "Hours",
"cron.hour.specify": "Specify",
"cron.day.per": "Per Day",
"cron.day.notSpecify": "Not Specify",
"cron.day.period.1": "From",
"cron.day.period.2": " Day, To ",
"cron.day.period.3": " Day",
"cron.day.per2.1": "From",
"cron.day.per2.2": "Day, Once Per",
"cron.day.per2.3": "Days",
"cron.day.workDay.1": "On a Recent Work Day Nearby",
"cron.day.workDay.2": "Day",
"cron.day.lastDay": "Last Day in This Month",
"cron.day.specify": "Specify",
"cron.month.per": "Per Month",
"cron.month.notSpecify": "Not Specify",
"cron.month.period.1": "From",
"cron.month.period.2": " Month, To ",
"cron.month.period.3": " Month",
"cron.month.per2.1": "From",
"cron.month.per2.2": "Month, Once Per",
"cron.month.per2.3": "Months",
"cron.month.specify": "Specify",
"cron.week.per": "Per Week",
"cron.week.notSpecify": "Not Specify",
"cron.week.period.1": "From",
"cron.week.period.2": " Day of Week, To ",
"cron.week.period.3": " Day of Week",
"cron.week.weekOfYear.1": "At",
"cron.week.weekOfYear.2": "Week of Year, At",
"cron.week.weekOfYear.3": "Day of Week",
"cron.week.lastDay.1": "Last",
"cron.week.lastDay.2": "Day of Week in This Month",
"cron.week.specify": "Specify",
"cron.year.per": "Per Year",
"cron.year.notSpecify": "Not Specify",
"cron.year.period.1": "From",
"cron.year.period.2": " Year, To ",
"cron.year.period.3": " Year"
}

70
io.sc.platform.core.frontend/src/platform/i18n/messages_tw_CN.json

@ -46,5 +46,73 @@
"tabs.close.all":"關閉所有標籤",
"theme": "主題",
"upToTop": "回到頂部",
"passwordAndConfirmPasswordMustEqual": "確認密碼和密碼必須一致"
"passwordAndConfirmPasswordMustEqual": "確認密碼和密碼必須一致",
"cron.second.per": "每秒",
"cron.second.period.1": "從",
"cron.second.period.2": " 秒, 到",
"cron.second.period.3": " 秒",
"cron.second.per2.1": "从",
"cron.second.per2.2": "秒開始, 每",
"cron.second.per2.3": "秒一次",
"cron.second.specify": "指定",
"cron.minut.per": "每分鐘",
"cron.minut.period.1": "從",
"cron.minut.period.2": " 分鐘, 到",
"cron.minut.period.3": " 分鐘",
"cron.minut.per2.1": "从",
"cron.minut.per2.2": "分鐘開始, 每",
"cron.minut.per2.3": "分鐘一次",
"cron.minut.specify": "指定",
"cron.hour.per": "每小時",
"cron.hour.period.1": "從",
"cron.hour.period.2": " 小時, 到",
"cron.hour.period.3": " 小時",
"cron.hour.per2.1": "从",
"cron.hour.per2.2": "小時開始, 每",
"cron.hour.per2.3": "小時一次",
"cron.hour.specify": "指定",
"cron.day.per": "每天",
"cron.day.notSpecify": "不指定",
"cron.day.period.1": "從",
"cron.day.period.2": " 天, 到",
"cron.day.period.3": " 天",
"cron.day.per2.1": "从",
"cron.day.per2.2": "天開始, 每",
"cron.day.per2.3": "天一次",
"cron.day.workDay.1": "每月",
"cron.day.workDay.2": "號最近的那個工作日",
"cron.day.lastDay": "本月最後一天",
"cron.day.specify": "指定",
"cron.month.per": "每月",
"cron.month.notSpecify": "不指定",
"cron.month.period.1": "從",
"cron.month.period.2": " 月, 到",
"cron.month.period.3": " 月",
"cron.month.per2.1": "从",
"cron.month.per2.2": "月開始, 每",
"cron.month.per2.3": "月一次",
"cron.month.specify": "指定",
"cron.week.per": "每周一次",
"cron.week.notSpecify": "不指定",
"cron.week.period.1": "從星期",
"cron.week.period.2": ", 到星期",
"cron.week.period.3": ", 每天一次",
"cron.week.weekOfYear.1": "第",
"cron.week.weekOfYear.2": "周的星期",
"cron.week.weekOfYear.3": "",
"cron.week.lastDay.1": "本月最後一個星期",
"cron.week.lastDay.2": "",
"cron.week.specify": "指定",
"cron.year.per": "每年",
"cron.year.notSpecify": "不指定",
"cron.year.period.1": "从",
"cron.year.period.2": "年, 到",
"cron.year.period.3": "年"
}

70
io.sc.platform.core.frontend/src/platform/i18n/messages_zh_CN.json

@ -46,5 +46,73 @@
"tabs.close.all":"关闭所有标签",
"theme": "主题",
"upToTop": "回到顶部",
"passwordAndConfirmPasswordMustEqual": "确认密码和密码必须一致"
"passwordAndConfirmPasswordMustEqual": "确认密码和密码必须一致",
"cron.second.per": "每秒",
"cron.second.period.1": "从",
"cron.second.period.2": " 秒, 到",
"cron.second.period.3": " 秒",
"cron.second.per2.1": "从",
"cron.second.per2.2": "秒开始, 每",
"cron.second.per2.3": "秒一次",
"cron.second.specify": "指定",
"cron.minute.per": "每分钟",
"cron.minute.period.1": "从",
"cron.minute.period.2": " 分钟, 到",
"cron.minute.period.3": " 分钟",
"cron.minute.per2.1": "从",
"cron.minute.per2.2": "分钟开始, 每",
"cron.minute.per2.3": "分钟一次",
"cron.minute.specify": "指定",
"cron.hour.per": "每小时",
"cron.hour.period.1": "从",
"cron.hour.period.2": " 小时, 到",
"cron.hour.period.3": " 小时",
"cron.hour.per2.1": "从",
"cron.hour.per2.2": "小时开始, 每",
"cron.hour.per2.3": "小时一次",
"cron.hour.specify": "指定",
"cron.day.per": "每天",
"cron.day.notSpecify": "不指定",
"cron.day.period.1": "从",
"cron.day.period.2": " 天, 到",
"cron.day.period.3": " 天",
"cron.day.per2.1": "从",
"cron.day.per2.2": "天开始, 每",
"cron.day.per2.3": "天一次",
"cron.day.workDay.1": "每月",
"cron.day.workDay.2": "号最近的那个工作日",
"cron.day.lastDay": "本月最后一天",
"cron.day.specify": "指定",
"cron.month.per": "每月",
"cron.month.notSpecify": "不指定",
"cron.month.period.1": "从",
"cron.month.period.2": " 月, 到",
"cron.month.period.3": " 月",
"cron.month.per2.1": "从",
"cron.month.per2.2": "月开始, 每",
"cron.month.per2.3": "月一次",
"cron.month.specify": "指定",
"cron.week.per": "每周",
"cron.week.notSpecify": "不指定",
"cron.week.period.1": "从星期",
"cron.week.period.2": ", 到星期",
"cron.week.period.3": "",
"cron.week.weekOfYear.1": "第",
"cron.week.weekOfYear.2": "周的星期",
"cron.week.weekOfYear.3": "",
"cron.week.lastDay.1": "本月最后一个星期",
"cron.week.lastDay.2": "",
"cron.week.specify": "指定",
"cron.year.per": "每年",
"cron.year.notSpecify": "不指定",
"cron.year.period.1": "从",
"cron.year.period.2": "年, 到",
"cron.year.period.3": "年"
}

3
io.sc.platform.core.frontend/src/platform/index.ts

@ -115,8 +115,9 @@ export {
WHScreenDiv,
WColorInput,
WColorInputPalette,
WCron,
WPosition,
WCodemirror,
WCodeMirror,
WSelect,
WGrid,
WTreeGrid,

1
io.sc.platform.core.frontend/src/platform/plugin/quasar.ts

@ -26,6 +26,7 @@ import {
export default {
install: (app: App) => {
app.config.globalProperties.$eventBus = eventBus;
app.provide('eventBus', eventBus);
app.use(Quasar, {
config: {
brand: gc.theme.brand,

12
io.sc.platform.core.frontend/src/routes/routes.json

@ -1,4 +1,16 @@
[
{
"name": "route.testcase.component",
"path": "testcase/component",
"parent": "/",
"priority": 0,
"component": "component.testcase.component",
"componentPath": "@/views/Component.vue",
"redirect": null,
"meta": {
"permissions": ["/testcase/component/**/*"]
}
},
{
"name": "route.testcase.dialog",
"path": "testcase/dialog",

2
io.sc.platform.core.frontend/src/views/Codemirror.vue

@ -44,7 +44,7 @@ onUnmounted(() => {
const value = ref('<xml><a name="name"></a></xml>');
</script>
<style>
.cm-editor {
.cm-editor2 {
outline: none !important;
}
</style>

29
io.sc.platform.core.frontend/src/views/Component.vue

@ -0,0 +1,29 @@
<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>

4
io.sc.platform.core.frontend/template-project/package.json

@ -1,6 +1,6 @@
{
"name": "platform-core",
"version": "8.1.119",
"version": "8.1.122",
"description": "前端核心包,用于快速构建前端的脚手架",
"private": false,
"keywords": [],
@ -92,7 +92,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.119",
"platform-core": "8.1.122",
"quasar": "2.14.2",
"tailwindcss": "3.4.0",
"vue": "3.4.3",

48
io.sc.platform.core.frontend/template-project/src/views/Codemirror.vue

@ -1,8 +1,50 @@
<template>
<w-codemirror v-model="value" lang="xml" style="height: 60px"></w-codemirror>
<!-- <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 } from 'vue';
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();
});
const value = ref('<xml><a name="name"></a>');
onUnmounted(() => {
console.log('>>>>>>');
view.destroy();
});
const value = ref('<xml><a name="name"></a></xml>');
</script>
<style>
.cm-editor {
outline: none !important;
}
</style>

2
io.sc.platform.core/src/main/java/io/sc/platform/core/autoconfigure/support/DateJsonDeserializer.java

@ -17,7 +17,7 @@ public class DateJsonDeserializer extends JsonDeserializer<Date> {
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String text =p.getValueAsString();
try {
return DateUtil.parseDate(text);
return DateUtil.tryParseDate(text);
} catch (ParseException e) {
throw new IOException(e);
}

9
io.sc.platform.core/src/main/java/io/sc/platform/core/util/StringUtil.java

@ -1448,4 +1448,13 @@ public class StringUtil {
Arrays.sort(strs);
return strs;
}
public static String escapeSqlSpecialChar(String sql){
return sql.trim().replace("\\", "\\\\\\\\")
.replace("_", "\\_")
.replace("\'", "\\'")
.replace("%", "\\%")
.replace("?", "\\?")
.replace("*", "\\*");
}
}

13
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words.properties

@ -107,6 +107,7 @@ parent=Parent
parentId=Parent ID
path=Path
password=Password
per=Per
phone=Phone
pixel=px
previous=Previous
@ -178,4 +179,14 @@ qualitative=Qualitative
range=Range
color=Color
resetDefaultValues=Reset Default
running=Running
running=Running
second=Second
minute=Minute
hour=Hour
day=Day
week=Week
month=Month
year=Year
once=Once
specify=Specify
notSpecify=Not Specify

13
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words_tw_CN.properties

@ -107,6 +107,7 @@ parent=\u7236
parentId=\u7236 ID
path=\u8DEF\u5F91
password=\u5BC6\u78BC
per=\u6BCF
phone=\u96FB\u8A71
pixel=\u50CF\u7D20
previous=\u524D\u4E00
@ -178,4 +179,14 @@ qualitative=\u5B9A\u6027
range=\u7BC4\u570D
color=\u984F\u8272
resetDefaultValues=\u6062\u5FA9\u9ED8\u8A8D\u503C
running=\u6B63\u5728\u904B\u884C
running=\u6B63\u5728\u904B\u884C
second=\u79D2
minute=\u5206\u9418
hour=\u5C0F\u6642
day=\u5929
week=\u5468
month=\u6708
year=\u5E74
once=\u4E00\u6B21
specify=\u6307\u5B9A
notSpecify=\u4E0D\u6307\u5B9A

13
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/words_zh_CN.properties

@ -107,6 +107,7 @@ parent=\u7236
parentId=\u7236 ID
path=\u8DEF\u5F84
password=\u5BC6\u7801
per=\u6BCF
phone=\u7535\u8BDD
pixel=\u50CF\u7D20
previous=\u524D\u4E00
@ -178,4 +179,14 @@ qualitative=\u5B9A\u6027
range=\u8303\u56F4
color=\u989C\u8272
resetDefaultValues=\u6062\u590D\u9ED8\u8BA4\u503C
running=\u6B63\u5728\u8FD0\u884C
running=\u6B63\u5728\u8FD0\u884C
second=\u79D2
minute=\u5206\u949F
hour=\u5C0F\u65F6
day=\u5929
week=\u5468
month=\u6708
year=\u5E74
once=\u4E00\u6B21
specify=\u6307\u5B9A
notSpecify=\u4E0D\u6307\u5B9A

6
io.sc.platform.developer.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.platform.developer.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -102,4 +102,4 @@
"codemirror": "6.0.1",
"vue-codemirror6": "1.2.0"
}
}
}

4
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -4,8 +4,8 @@
"order" : 600,
"description":"工作流流程定义表结构",
"locations":[
"classpath:/liquibase/FLOWABLE_6.8.0_20220528__Flowable Database Schema DDL.xml",
"classpath:/liquibase/PF_1.0.0_20221228__Process Manager Database Schema DDL.xml"
"liquibase/io.sc.platform.flowable_8.0.0_20220606__Flowable(6.8.0) Database Schema DDL.xml",
"liquibase/io.sc.platform.flowable_8.0.0_20220606__Process Manager Database Schema DDL.xml"
]
}
]

2
io.sc.platform.flowable/src/main/resources/liquibase/FLOWABLE_6.8.0_20220528__Flowable Database Schema DDL.xml → io.sc.platform.flowable/src/main/resources/liquibase/io.sc.platform.flowable_8.0.0_20220606__Flowable(6.8.0) Database Schema DDL.xml

@ -10,7 +10,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
"
>
<changeSet id="FLOWABLE_6.8.0_20220528__Flowable Database Schema DDL" author="platform">
<changeSet id="io.sc.platform.flowable_8.0.0_20220606__Flowable(6.8.0) Database Schema DDL" author="platform">
<!-- org.flowable.common -->
<sqlFile dbms="db2" path="classpath:/org/flowable/common/db/create/flowable.db2.create.common.sql"/>
<sqlFile dbms="h2" path="classpath:/org/flowable/common/db/create/flowable.h2.create.common.sql"/>

2
io.sc.platform.flowable/src/main/resources/liquibase/PF_1.0.0_20221228__Process Manager Database Schema DDL.xml → io.sc.platform.flowable/src/main/resources/liquibase/io.sc.platform.flowable_8.0.0_20220606__Process Manager Database Schema DDL.xml

@ -10,7 +10,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
"
>
<changeSet id="PF_1.0.0_20221228__Process Manager Database Schema DDL" author="framework">
<changeSet id="io.sc.platform.flowable_8.0.0_20220606__Process Manager Database Schema DDL" author="framework">
<!-- 流程定义表 -->
<createTable tableName="SYS_PROCESS" remarks="流程定义表">
<column name="ID_" type="NVARCHAR(36)" remarks="ID">

2
io.sc.platform.gradle/templates/pgp/app/build.gradle

@ -18,6 +18,8 @@ dependencies {
project(":io.sc.engine.mv"),
project(":io.sc.engine.mv.frontend"),
project(":io.sc.engine.mv.sample"),
project(":io.sc.platform.scheduler.manager"),
)
}

2
io.sc.platform.gradle/templates/pgp/setup/gradle.properties

@ -36,7 +36,7 @@ application_version=1.0.0
# platform
###########################################################
platform_group=io.sc
platform_version=8.1.23
platform_version=8.1.24
platform_plugin_version=8.1.13
platform_core_frontend_version=8.1.119

6
io.sc.platform.lcdp.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.platform.lcdp.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -102,4 +102,4 @@
"vue-router": "4.2.5",
"vue-codemirror6": "1.2.0"
}
}
}

2
io.sc.platform.lcdp/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -4,7 +4,7 @@
"order" : 2000,
"description":"应用配置数据库表结构",
"locations":[
"liquibase/LCDP_1.0.0_20220606__LowCode_DDL.xml"
"liquibase/io.sc.platform.lcdp_8.0.0_20220606__LowCode Developer Database Schema DDL.xml"
]
}
]

2
io.sc.platform.lcdp/src/main/resources/liquibase/LCDP_1.0.0_20220606__LowCode_DDL.xml → io.sc.platform.lcdp/src/main/resources/liquibase/io.sc.platform.lcdp_8.0.0_20220606__LowCode Developer Database Schema DDL.xml

@ -10,7 +10,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
"
>
<changeSet id="LCDP_1.0.0_20220606__LowCode_DDL" author="platform">
<changeSet id="io.sc.platform.lcdp_8.0.0_20220606__LowCode Developer Database Schema DDL" author="platform">
<!-- 主题风格配置表 -->
<createTable tableName="LCDP_CONFIGURE" remarks="系统配置表">
<column name="ID_" type="NVARCHAR(36)" remarks="ID">

6
io.sc.platform.mvc.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.platform.mvc.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -102,4 +102,4 @@
"codemirror": "6.0.1",
"vue-codemirror6": "1.2.0"
}
}
}

5
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/ArrayStringConverter.java

@ -12,7 +12,8 @@ public class ArrayStringConverter implements AttributeConverter<String[], String
}
StringBuilder sb =new StringBuilder();
for(String value : attribute){
sb.append(value).append(",");
String _value =value==null?"":value.trim();
sb.append(_value).append(",");
}
sb.setLength(sb.length()-1);
return sb.toString();
@ -29,7 +30,7 @@ public class ArrayStringConverter implements AttributeConverter<String[], String
}
String[] result =new String[splits.length];
for(int i=0;i<splits.length;i++){
result[i] =splits[i];
result[i] =splits[i].trim();
}
return result;
}

5
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/ListStringConverter.java

@ -13,7 +13,8 @@ public class ListStringConverter implements AttributeConverter<List<String>, Str
}
StringBuilder sb =new StringBuilder();
for(String value : attribute){
sb.append(value).append(",");
String _value =value==null?"":value.trim();
sb.append(_value).append(",");
}
sb.setLength(sb.length()-1);
return sb.toString();
@ -30,7 +31,7 @@ public class ListStringConverter implements AttributeConverter<List<String>, Str
}
List<String> result =new ArrayList<>();
for(String split : splits){
result.add(split);
result.add(split.trim());
}
return result;
}

5
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/SetStringConverter.java

@ -13,7 +13,8 @@ public class SetStringConverter implements AttributeConverter<Set<String>, Strin
}
StringBuilder sb =new StringBuilder();
for(String value : attribute){
sb.append(value).append(",");
String _value =value==null?"":value.trim();
sb.append(_value).append(",");
}
sb.setLength(sb.length()-1);
return sb.toString();
@ -30,7 +31,7 @@ public class SetStringConverter implements AttributeConverter<Set<String>, Strin
}
Set<String> result =new HashSet<>();
for(String split : splits){
result.add(split);
result.add(split.trim());
}
return result;
}

51
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/impl/DaoServiceImpl.java

@ -1,7 +1,5 @@
package io.sc.platform.orm.service.impl;
import io.sc.platform.jdbc.sql.builder.SqlBuilder;
import io.sc.platform.jdbc.sql.condition.Condition;
import io.sc.platform.orm.repository.DaoRepository;
import io.sc.platform.orm.service.DaoService;
import io.sc.platform.orm.service.support.*;
@ -19,7 +17,7 @@ import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.persistence.criteria.*;
import javax.persistence.criteria.Predicate;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute;
import java.io.Serializable;
@ -341,51 +339,6 @@ public abstract class DaoServiceImpl<E,ID extends Serializable,R extends DaoRepo
};
}
public Condition buildCondition(QueryParameter queryParameter) {
Map<String,Class<?>> mapping =new HashMap<>();
mapping.put("loginName",String.class);
if(queryParameter==null){
return new Condition();
}
List<Criteria> criterias = queryParameter.getCriterias();
if(criterias==null || criterias.isEmpty()){
return new Condition();
}
if(OperatorType.and.equals(queryParameter.getOperator())){
List<Condition> conditions =new ArrayList<>();
for(Criteria criteria : criterias){
criteria.setConversionService(conversionService);
Condition condition =criteria.getCondition(mapping);
conditions.add(condition);
}
if(!conditions.isEmpty()) {
return SqlBuilder.getSqlWhereBuilder().and(conditions);
}
}else if(OperatorType.or.equals(queryParameter.getOperator())){
List<Condition> conditions =new ArrayList<>();
for(Criteria criteria : criterias){
criteria.setConversionService(conversionService);
Condition condition =criteria.getCondition(mapping);
conditions.add(condition);
}
if(!conditions.isEmpty()) {
return SqlBuilder.getSqlWhereBuilder().or(conditions);
}
}else if(OperatorType.not.equals(queryParameter.getOperator())){
List<Condition> conditions =new ArrayList<>();
for(Criteria criteria : criterias){
criteria.setConversionService(conversionService);
Condition condition =criteria.getCondition(mapping);
conditions.add(condition);
}
if(!conditions.isEmpty()) {
return SqlBuilder.getSqlWhereBuilder().not(conditions);
}
}
return null;
}
@Override
public List<E> list(Specification<E> specification) throws Exception {
if(specification!=null) {
@ -429,8 +382,6 @@ public abstract class DaoServiceImpl<E,ID extends Serializable,R extends DaoRepo
public Page<E> query(QueryParameter queryParameter) throws Exception {
if(queryParameter!=null) {
Specification<E> specification =buildSpecification(queryParameter);
Condition condition =buildCondition(queryParameter);
System.out.println(condition.getWhere());
return query(specification,queryParameter);
}
return QueryResult.emptyPage();

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Between.java

@ -53,8 +53,8 @@ public class Between<E> extends Criteria<E> {
String where =StringUtil.replaceWithPlaceholder("{0} > {1} and {0} < {2}",fieldName,nStart, nEnd);
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(nStart,pStart);
condition.getParameters().put(nEnd,pEnd);
condition.getParameters().put(nStart.substring(1),pStart);
condition.getParameters().put(nEnd.substring(1),pEnd);
return condition;
}

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/BetweenInclusive.java

@ -49,8 +49,8 @@ public class BetweenInclusive<E> extends Between<E> {
String where =StringUtil.replaceWithPlaceholder("{0} >= {1} and {0} <= {2}",fieldName,nStart, nEnd);
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(nStart,pStart);
condition.getParameters().put(nEnd,pEnd);
condition.getParameters().put(nStart.substring(1),pStart);
condition.getParameters().put(nEnd.substring(1),pEnd);
return condition;
}
}

9
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Contains.java

@ -30,16 +30,9 @@ public class Contains<E> extends Criteria<E> {
if(!StringUtils.hasText(value)){
throw new IllegalArgumentException("[" + operator + "] need a [value] value");
}
Object pValue =value;
Class<?> clazz =typeMapping.get(fieldName);
if(clazz!=null) {
pValue = conversionService.convert(value, clazz);
}
String name =":" + fieldName;
String where =StringUtil.replaceWithPlaceholder("{0} like '%{1}%'",fieldName,name);
String where =StringUtil.replaceWithPlaceholder("{0} like '%{1}%'",fieldName,StringUtil.escapeSqlSpecialChar(value));
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(name,pValue);
return condition;
}
}

9
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/Equals.java

@ -51,10 +51,10 @@ public class Equals<E> extends Criteria<E> {
pValue = conversionService.convert(value, clazz);
}
String name =":" + fieldName;
String where =StringUtil.replaceWithPlaceholder("{0} = '{1}'",fieldName,name);
String where =StringUtil.replaceWithPlaceholder("{0} = {1}",fieldName,name);
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(name,pValue);
condition.getParameters().put(name.substring(1),pValue);
return condition;
}
@ -65,9 +65,4 @@ public class Equals<E> extends Criteria<E> {
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
String s =StringUtil.replaceWithPlaceholder("{0}={1}","fieldName","value");
System.out.println(s);
}
}

16
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/GreaterThan.java

@ -1,5 +1,6 @@
package io.sc.platform.orm.service.support.criteria.impl;
import io.sc.platform.core.util.StringUtil;
import io.sc.platform.jdbc.sql.condition.Condition;
import io.sc.platform.orm.service.support.OperatorTypeNotSupportedException;
import io.sc.platform.orm.service.support.criteria.Criteria;
@ -28,6 +29,19 @@ public class GreaterThan<E> extends Criteria<E> {
@Override
public Condition getCondition(Map<String, Class<?>> typeMapping) {
throw new OperatorTypeNotSupportedException();
if(!StringUtils.hasText(value)){
throw new IllegalArgumentException("[" + operator + "] need a [value] value");
}
Object pValue =value;
Class<?> clazz =typeMapping.get(fieldName);
if(clazz!=null) {
pValue = conversionService.convert(value, clazz);
}
String name =":" + fieldName;
String where = StringUtil.replaceWithPlaceholder("{0} > {1}",fieldName,name);
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(name.substring(1),pValue);
return condition;
}
}

9
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/IContains.java

@ -30,16 +30,9 @@ public class IContains<E> extends Contains<E> {
if(!StringUtils.hasText(value)){
throw new IllegalArgumentException("[" + operator + "] need a [value] value");
}
Object pValue =value;
Class<?> clazz =typeMapping.get(fieldName);
if(clazz!=null) {
pValue = conversionService.convert(value, clazz);
}
String name =":" + fieldName;
String where = StringUtil.replaceWithPlaceholder("{0} like '%{1}%'",fieldName,name);
String where =StringUtil.replaceWithPlaceholder("{0} like '%{1}%'",fieldName,StringUtil.escapeSqlSpecialChar(value));
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(name,pValue);
return condition;
}
}

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/criteria/impl/IEquals.java

@ -36,10 +36,10 @@ public class IEquals<E> extends Equals<E> {
pValue = conversionService.convert(value, clazz);
}
String name =":" + fieldName;
String where =StringUtil.replaceWithPlaceholder("{0} = '{1}'",fieldName,name);
String where =StringUtil.replaceWithPlaceholder("{0} = {1}",fieldName,name);
Condition condition =new Condition();
condition.setWhere(where);
condition.getParameters().put(name,pValue);
condition.getParameters().put(name.substring(1),pValue);
return condition;
}
}

52
io.sc.platform.scheduler.core/src/main/java/io/sc/platform/scheduler/core/vo/GlueVo.java

@ -0,0 +1,52 @@
package io.sc.platform.scheduler.core.vo;
import io.sc.platform.orm.api.vo.CorporationAuditorVo;
import io.sc.platform.scheduler.core.enums.GlueType;
public class GlueVo extends CorporationAuditorVo {
private String id;
private GlueType type;
private String description;
private String source;
private String task;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public GlueType getType() {
return type;
}
public void setType(GlueType type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}

130
io.sc.platform.scheduler.core/src/main/java/io/sc/platform/scheduler/core/vo/TaskVo.java

@ -3,29 +3,31 @@ package io.sc.platform.scheduler.core.vo;
import io.sc.platform.scheduler.core.enums.*;
import io.sc.platform.orm.api.vo.CorporationAuditorVo;
import javax.validation.constraints.Size;
import java.util.Set;
public class TaskVo extends CorporationAuditorVo {
private String id;
private String name;
private String description;
private String executor;
private String alarmEmail;
private TaskScheduleType scheduleType;
private String scheduleConf;
private ExpirationPolicy expirationPolicy;
private ExecutorRouteStrategy routeStrategy;
private String executorHandler;
private String executorParam;
private BlockStrategy blockStrategy;
private int timeout;
private int failRetryCount;
private GlueType glueType;
private String glueSource;
private String parent;
private TriggerStatus triggerStatus;
private long triggerLastTime;
private long triggerNextTime;
private String id;//主键
private String parent;//父任务
private String executor;//执行器ID
private String executorName;//执行器名称
private String name;//名称
private String description;//描述
private String author;//负责人
private String alarmEmail;//报警邮件
private TaskScheduleType scheduleType;//调度类型
private String scheduleConf;//调度配置
private GlueType executorGlueType;//执行器 Glue 类型
private String executorHandler;//执行器 Handler 名称
private String executorParam;//执行器参数
private ExecutorRouteStrategy routeStrategy;//路由策略
private ExpirationPolicy expirationPolicy;//过期策略
private BlockStrategy blockStrategy;//阻塞策略
private int timeout;//超时时间,单位秒
private int failRetryCount;//失败重试次数
private TriggerStatus triggerStatus;//调度状态
private long triggerLastTime;//上次调度时间
private long triggerNextTime;//下次调度时间
public String getId() {
return id;
@ -35,6 +37,30 @@ public class TaskVo extends CorporationAuditorVo {
this.id = id;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public String getExecutor() {
return executor;
}
public void setExecutor(String executor) {
this.executor = executor;
}
public String getExecutorName() {
return executorName;
}
public void setExecutorName(String executorName) {
this.executorName = executorName;
}
public String getName() {
return name;
}
@ -51,12 +77,12 @@ public class TaskVo extends CorporationAuditorVo {
this.description = description;
}
public String getExecutor() {
return executor;
public String getAuthor() {
return author;
}
public void setExecutor(String executor) {
this.executor = executor;
public void setAuthor(String author) {
this.author = author;
}
public String getAlarmEmail() {
@ -83,20 +109,12 @@ public class TaskVo extends CorporationAuditorVo {
this.scheduleConf = scheduleConf;
}
public ExpirationPolicy getExpirationPolicy() {
return expirationPolicy;
}
public void setExpirationPolicy(ExpirationPolicy expirationPolicy) {
this.expirationPolicy = expirationPolicy;
}
public ExecutorRouteStrategy getRouteStrategy() {
return routeStrategy;
public GlueType getExecutorGlueType() {
return executorGlueType;
}
public void setRouteStrategy(ExecutorRouteStrategy routeStrategy) {
this.routeStrategy = routeStrategy;
public void setExecutorGlueType(GlueType executorGlueType) {
this.executorGlueType = executorGlueType;
}
public String getExecutorHandler() {
@ -115,6 +133,22 @@ public class TaskVo extends CorporationAuditorVo {
this.executorParam = executorParam;
}
public ExecutorRouteStrategy getRouteStrategy() {
return routeStrategy;
}
public void setRouteStrategy(ExecutorRouteStrategy routeStrategy) {
this.routeStrategy = routeStrategy;
}
public ExpirationPolicy getExpirationPolicy() {
return expirationPolicy;
}
public void setExpirationPolicy(ExpirationPolicy expirationPolicy) {
this.expirationPolicy = expirationPolicy;
}
public BlockStrategy getBlockStrategy() {
return blockStrategy;
}
@ -139,30 +173,6 @@ public class TaskVo extends CorporationAuditorVo {
this.failRetryCount = failRetryCount;
}
public GlueType getGlueType() {
return glueType;
}
public void setGlueType(GlueType glueType) {
this.glueType = glueType;
}
public String getGlueSource() {
return glueSource;
}
public void setGlueSource(String glueSource) {
this.glueSource = glueSource;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public TriggerStatus getTriggerStatus() {
return triggerStatus;
}

5
io.sc.platform.scheduler.core/src/main/resources/META-INF/platform/plugins/messages.json

@ -0,0 +1,5 @@
{
"includes":[
"io/sc/platform/scheduler/core/i18n/messages"
]
}

35
io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages.properties

@ -0,0 +1,35 @@
io.sc.platform.scheduler.core.enums.BlockStrategy.SERIAL_EXECUTION=Serializable
io.sc.platform.scheduler.core.enums.BlockStrategy.DISCARD_LATER=Discard Later
io.sc.platform.scheduler.core.enums.BlockStrategy.COVER_EARLY=Cover Early
io.sc.platform.scheduler.core.enums.ExecutorAddressType.AUTO=Auto
io.sc.platform.scheduler.core.enums.ExecutorAddressType.MANUAL=Manual
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FIRST=First
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LAST=Last
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.ROUND=Round
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.RANDOM=Random
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.CONSISTENT_HASH=Consistent Hash
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_FREQUENTLY_USED=Least Frequently Used
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_RECENTLY_USED=Least Recently Used
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FAILOVER=Failover
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.BUSYOVER=Busyover
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.SHARDING_BROADCAST=Sharding Broadcast
io.sc.platform.scheduler.core.enums.ExpirationPolicy.DO_NOTHING=Do Nothing
io.sc.platform.scheduler.core.enums.ExpirationPolicy.FIRE_ONCE_NOW=Fire Once Now
io.sc.platform.scheduler.core.enums.GlueType.BEAN=Bean
io.sc.platform.scheduler.core.enums.GlueType.GLUE_GROOVY=Groovy
io.sc.platform.scheduler.core.enums.GlueType.GLUE_SHELL=Shell
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PYTHON=Python
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PHP=Php
io.sc.platform.scheduler.core.enums.GlueType.GLUE_NODEJS=NodeJs
io.sc.platform.scheduler.core.enums.GlueType.GLUE_POWERSHELL=PowerShell
io.sc.platform.scheduler.core.enums.TaskScheduleType.NONE=None
io.sc.platform.scheduler.core.enums.TaskScheduleType.CRON=Cron
io.sc.platform.scheduler.core.enums.TaskScheduleType.FIX_RATE=Fix Rate
io.sc.platform.scheduler.core.enums.TriggerStatus.STOPED=Stoped
io.sc.platform.scheduler.core.enums.TriggerStatus.RUNNING=Running

35
io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages_tw_CN.properties

@ -0,0 +1,35 @@
io.sc.platform.scheduler.core.enums.BlockStrategy.SERIAL_EXECUTION=\u55AE\u6A5F\u4E32\u884C
io.sc.platform.scheduler.core.enums.BlockStrategy.DISCARD_LATER=\u4E1F\u68C4\u5F8C\u7E8C\u8ABF\u5EA6
io.sc.platform.scheduler.core.enums.BlockStrategy.COVER_EARLY=\u8986\u84CB\u5148\u524D\u8ABF\u5EA6
io.sc.platform.scheduler.core.enums.ExecutorAddressType.AUTO=\u81EA\u52D5\u8A3B\u518A
io.sc.platform.scheduler.core.enums.ExecutorAddressType.MANUAL=\u624B\u5DE5\u9304\u5165
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FIRST=\u7B2C\u4E00\u500B
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LAST=\u6700\u5F8C\u4E00\u500B
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.ROUND=\u8F2A\u8A62
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.RANDOM=\u96A8\u6A5F
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.CONSISTENT_HASH=\u4E00\u81F4\u6027 Hash
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_FREQUENTLY_USED=\u6700\u8FD1\u7D93\u5E38\u4F7F\u7528
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_RECENTLY_USED=\u6700\u8FD1\u6700\u4E45\u672A\u4F7F\u7528
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FAILOVER=\u6545\u969C\u8F49\u79FB
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.BUSYOVER=\u5FD9\u788C\u8F49\u79FB
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.SHARDING_BROADCAST=\u5206\u7247\u5EE3\u64AD
io.sc.platform.scheduler.core.enums.ExpirationPolicy.DO_NOTHING=\u5FFD\u7565
io.sc.platform.scheduler.core.enums.ExpirationPolicy.FIRE_ONCE_NOW=\u7ACB\u5373\u57F7\u884C\u4E00\u6B21
io.sc.platform.scheduler.core.enums.GlueType.BEAN=Bean
io.sc.platform.scheduler.core.enums.GlueType.GLUE_GROOVY=Groovy
io.sc.platform.scheduler.core.enums.GlueType.GLUE_SHELL=Shell
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PYTHON=Python
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PHP=Php
io.sc.platform.scheduler.core.enums.GlueType.GLUE_NODEJS=NodeJs
io.sc.platform.scheduler.core.enums.GlueType.GLUE_POWERSHELL=PowerShell
io.sc.platform.scheduler.core.enums.TaskScheduleType.NONE=\u7121
io.sc.platform.scheduler.core.enums.TaskScheduleType.CRON=Cron
io.sc.platform.scheduler.core.enums.TaskScheduleType.FIX_RATE=\u56FA\u5B9A\u9031\u671F
io.sc.platform.scheduler.core.enums.TriggerStatus.STOPED=\u5DF2\u505C\u6B62
io.sc.platform.scheduler.core.enums.TriggerStatus.RUNNING=\u904B\u884C\u4E2D

35
io.sc.platform.scheduler.core/src/main/resources/io/sc/platform/scheduler/core/i18n/messages_zh_CN.properties

@ -0,0 +1,35 @@
io.sc.platform.scheduler.core.enums.BlockStrategy.SERIAL_EXECUTION=\u5355\u673A\u4E32\u884C
io.sc.platform.scheduler.core.enums.BlockStrategy.DISCARD_LATER=\u4E22\u5F03\u540E\u7EED\u8C03\u5EA6
io.sc.platform.scheduler.core.enums.BlockStrategy.COVER_EARLY=\u8986\u76D6\u5148\u524D\u8C03\u5EA6
io.sc.platform.scheduler.core.enums.ExecutorAddressType.AUTO=\u81EA\u52A8\u6CE8\u518C
io.sc.platform.scheduler.core.enums.ExecutorAddressType.MANUAL=\u624B\u5DE5\u5F55\u5165
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FIRST=\u7B2C\u4E00\u4E2A
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LAST=\u6700\u540E\u4E00\u4E2A
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.ROUND=\u8F6E\u8BE2
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.RANDOM=\u968F\u673A
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.CONSISTENT_HASH=\u4E00\u81F4\u6027 Hash
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_FREQUENTLY_USED=\u6700\u4E0D\u7ECF\u5E38\u4F7F\u7528
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.LEAST_RECENTLY_USED=\u6700\u8FD1\u6700\u4E45\u672A\u4F7F\u7528
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.FAILOVER=\u6545\u969C\u8F6C\u79FB
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.BUSYOVER=\u5FD9\u788C\u8F6C\u4E49
io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy.SHARDING_BROADCAST=\u5206\u7247\u5E7F\u64AD
io.sc.platform.scheduler.core.enums.ExpirationPolicy.DO_NOTHING=\u5FFD\u7565
io.sc.platform.scheduler.core.enums.ExpirationPolicy.FIRE_ONCE_NOW=\u7ACB\u5373\u6267\u884C\u4E00\u6B21
io.sc.platform.scheduler.core.enums.GlueType.BEAN=Bean
io.sc.platform.scheduler.core.enums.GlueType.GLUE_GROOVY=Groovy
io.sc.platform.scheduler.core.enums.GlueType.GLUE_SHELL=Shell
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PYTHON=Python
io.sc.platform.scheduler.core.enums.GlueType.GLUE_PHP=Php
io.sc.platform.scheduler.core.enums.GlueType.GLUE_NODEJS=NodeJs
io.sc.platform.scheduler.core.enums.GlueType.GLUE_POWERSHELL=PowerShell
io.sc.platform.scheduler.core.enums.TaskScheduleType.NONE=\u65E0
io.sc.platform.scheduler.core.enums.TaskScheduleType.CRON=Cron
io.sc.platform.scheduler.core.enums.TaskScheduleType.FIX_RATE=\u56FA\u5B9A\u5468\u671F
io.sc.platform.scheduler.core.enums.TriggerStatus.STOPED=\u5DF2\u505C\u6B62
io.sc.platform.scheduler.core.enums.TriggerStatus.RUNNING=\u8FD0\u884C\u4E2D

121
io.sc.platform.scheduler.manager.frontend/src/views/scheduler/Executor.vue

@ -1,36 +1,81 @@
<template>
<w-grid
:title="$t('io.sc.engine.mv.config.chiSquare.grid.title')"
:title="$t('lcdp.scheduler.executor.grid.title')"
:config-button="true"
selection="multiple"
:checkbox-selection="true"
:query-form-cols-num="4"
:query-form-fields="[
{ name: 'AppName', label: $t('AppName'), type: 'text' },
{ name: '名称', label: $t('名称'), type: 'text' },
{ name: 'appName', label: $t('lcdp.scheduler.executor.grid.entity.appName'), type: 'text' },
{ name: 'name', label: $t('lcdp.scheduler.executor.grid.entity.name'), type: 'text' },
]"
:data-url="Environment.apiContextPath('/api/mv/configure/chiSquare')"
:data-url="Environment.apiContextPath('/api/scheduler/executor')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['refresh', 'separator', 'add', 'edit', 'remove', 'separator', 'separator', 'view', 'separator', 'export']"
:columns="[
{ width: 100, name: 'AppName', label: $t('AppName') },
{ width: 100, name: '名称', label: $t('名称') },
{ width: 120, name: '注册方式', label: $t('注册方式') },
{ width: 100, name: 'OnLine 机器地址', label: $t('OnLine 机器地址') },
{ width: 100, name: 'id', label: $t('id'), hidden: true },
{ width: 250, name: 'appName', label: $t('lcdp.scheduler.executor.grid.entity.appName') },
{ width: '100%', name: 'name', label: $t('lcdp.scheduler.executor.grid.entity.name') },
{ width: 200, name: 'description', label: $t('description') },
{ width: 100, name: 'addressType', label: $t('lcdp.scheduler.executor.grid.entity.addressType'), format: Formater.enum(ExecutorAddressTypeEnum) },
{
width: 150,
name: 'addresses',
label: $t('lcdp.scheduler.executor.grid.entity.addresses'),
format: (values) => {
if (values && values.length > 0) {
let result = '';
for (const value of values) {
result += value + '<br/>';
}
return result;
}
return values;
},
},
{ width: 100, name: 'lastModifier', label: $t('lastModifier') },
{ width: 110, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() },
]"
:editor="{
dialog: {
width: '600px',
height: '300px',
height: '450px',
},
form: {
colsNum: 1,
fields: [
{ name: 'AppName', label: $t('AppName'), type: 'text' },
{ name: '名称', label: $t('名称'), type: 'text' },
{ name: '注册方式', label: $t('注册方式'), type: 'text' },
{ name: 'OnLine 机器地址', label: $t('OnLine 机器地址'), type: 'text' },
{ name: 'appName', label: $t('lcdp.scheduler.executor.grid.entity.appName'), type: 'text', required: true },
{ name: 'name', label: $t('lcdp.scheduler.executor.grid.entity.name'), type: 'text', required: true },
{ name: 'description', label: $t('description'), type: 'text' },
{
name: 'addressType',
label: $t('lcdp.scheduler.executor.grid.entity.addressType'),
type: 'select',
options: Options.enum(ExecutorAddressTypeEnum),
required: true,
defaultValue: 'AUTO',
},
{
name: 'addresses',
label: $t('lcdp.scheduler.executor.grid.entity.addresses.label'),
type: 'textarea',
rows: 5,
disableIf: (form) => {
const addressType = form.getFieldValue('addressType');
if ('MANUAL' === addressType) {
return false;
}
return true;
},
requiredIf: (form) => {
const addressType = form.getFieldValue('addressType');
if ('MANUAL' === addressType) {
return true;
}
return false;
},
},
],
},
}"
@ -38,15 +83,55 @@
panel: {
columnNum: 1,
fields: [
{ name: 'AppName', label: $t('AppName') },
{ name: '名称', label: $t('名称') },
{ name: '注册方式', label: $t('注册方式') },
{ name: 'OnLine 机器地址', label: $t('OnLine 机器地址') },
{ name: 'id', label: $t('id') },
{ name: 'appName', label: $t('lcdp.scheduler.executor.grid.entity.appName') },
{ name: 'name', label: $t('lcdp.scheduler.executor.grid.entity.name') },
{ name: 'description', label: $t('description') },
{ name: 'addressType', label: $t('lcdp.scheduler.executor.grid.entity.addressType'), format: Formater.none() },
{
name: 'addresses',
label: $t('lcdp.scheduler.executor.grid.entity.addresses'),
format: (values) => {
if (values && values.length > 0) {
let result = '';
for (const value of values) {
result += value + '<br/>';
}
return result;
}
return values;
},
},
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
],
},
}"
@before-editor-data-submit="
(data, submit) => {
if (data.addresses) {
data.addresses = data.addresses.split(',');
} else {
data.addresses = null;
}
submit(data);
}
"
@after-editor-data-submit="
() => {
$eventBus.emit('io.sc.platform.scheduler.manager.ExecutorChanged');
}
"
@after-remove="
() => {
$eventBus.emit('io.sc.platform.scheduler.manager.ExecutorChanged');
}
"
></w-grid>
</template>
<script setup lang="ts">
import { Environment, Formater } from 'platform-core';
import { inject } from 'vue';
import { Environment, EnumTools, Formater, Options } from 'platform-core';
const ExecutorAddressTypeEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.ExecutorAddressType');
</script>

285
io.sc.platform.scheduler.manager.frontend/src/views/scheduler/Task.vue

@ -1,2 +1,283 @@
<template>Task</template>
<script setup lang="ts"></script>
<template>
<w-grid
:title="$t('lcdp.scheduler.task.grid.title')"
:config-button="true"
selection="multiple"
:checkbox-selection="true"
:query-form-cols-num="12"
:query-form-fields="[
{ colSpan: 4, name: 'name', label: $t('name'), type: 'text' },
{
colSpan: 4,
name: 'executor',
label: $t('lcdp.scheduler.task.grid.entity.executor'),
type: 'select',
clearable: true,
queryOperator: 'equals',
options: executorOptionsRef,
},
{
colSpan: 2,
name: 'triggerStatus',
label: $t('status'),
type: 'select',
clearable: true,
queryOperator: 'equals',
options: Options.enum(TriggerStatusEnum),
},
]"
:data-url="Environment.apiContextPath('/api/scheduler/task')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="[
'query',
'refresh',
'separator',
'add',
'edit',
'remove',
'separator',
{
name: 'execute',
label: $t('lcdp.scheduler.task.grid.toolbar.execute'),
icon: 'bi-caret-right-fill',
enableIf: (selecteds) => {
return selecteds && selecteds.length > 0;
},
click: () => {},
},
{
name: 'schedule',
label: $t('lcdp.scheduler.task.grid.toolbar.schedule'),
icon: 'bi-cloud-arrow-up',
enableIf: (selecteds) => {
return selecteds && selecteds.length > 0;
},
click: () => {},
},
{
name: 'log',
label: $t('lcdp.scheduler.task.grid.toolbar.log'),
icon: 'bi-receipt',
enableIf: (selecteds) => {
return selecteds && selecteds.length > 0;
},
click: () => {},
},
'separator',
'view',
'separator',
'export',
]"
:columns="[
{
width: 80,
name: 'triggerStatus',
label: $t('status'),
align: 'center',
format: (value) => {
return {
componentType: 'QChip',
attrs: { color: value == 'RUNNING' ? 'green' : 'gray', label: Formater.enum(TriggerStatusEnum)(value), dense: true },
};
},
},
{ width: 150, name: 'name', label: $t('name') },
{
width: 130,
name: 'scheduleType',
label: $t('lcdp.scheduler.task.grid.entity.scheduleType'),
format: (value, row) => {
return Formater.enum(TaskScheduleTypeEnum)(row.scheduleType) + ' : ' + row.scheduleConf;
},
},
{ width: 150, name: 'executorName', label: $t('lcdp.scheduler.task.grid.entity.executorName') },
{
width: 90,
name: 'executorGlueType',
label: $t('lcdp.scheduler.task.grid.entity.executorGlueType'),
format: Formater.enum(GlueTypeEnum),
},
{
width: 140,
name: 'triggerLastTime',
label: $t('lcdp.scheduler.task.grid.entity.triggerLastTime'),
format: () => {
return '2024-02-23 10:10:10';
},
},
{ width: 140, name: 'triggerNextTime', label: $t('lcdp.scheduler.task.grid.entity.triggerNextTime') },
{ width: 80, name: 'author', label: $t('lcdp.scheduler.task.grid.entity.author') },
{ width: 100, name: 'lastModifier', label: $t('lastModifier') },
{ width: 110, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() },
{ width: 200, name: 'alarmEmail', label: $t('lcdp.scheduler.task.grid.entity.alarmEmail') },
{
width: 100,
name: 'routeStrategy',
label: $t('lcdp.scheduler.task.grid.entity.routeStrategy'),
format: (value) => {
return Formater.enum(ExecutorRouteStrategyEnum)(value);
},
},
{
width: 100,
name: 'expirationPolicy',
label: $t('lcdp.scheduler.task.grid.entity.expirationPolicy'),
format: (value) => {
return Formater.enum(ExpirationPolicyEnum)(value);
},
},
{
width: 100,
name: 'blockStrategy',
label: $t('lcdp.scheduler.task.grid.entity.blockStrategy'),
format: (value) => {
return Formater.enum(BlockStrategyEnum)(value);
},
},
{ width: 80, name: 'timeout', label: $t('lcdp.scheduler.task.grid.entity.timeout') },
{ width: 90, name: 'failRetryCount', label: $t('lcdp.scheduler.task.grid.entity.failRetryCount') },
]"
:editor="{
dialog: {
width: '800px',
height: '600px',
},
form: {
colsNum: 2,
fields: [
{
name: 'executor',
label: $t('lcdp.scheduler.task.grid.entity.executor'),
type: 'select',
clearable: true,
options: executorOptionsRef,
},
{ colsFirst: true, name: 'name', label: $t('name'), type: 'text' },
{ name: 'description', label: $t('description'), type: 'text' },
{ name: 'author', label: $t('lcdp.scheduler.task.grid.entity.author'), type: 'text' },
{ name: 'alarmEmail', label: $t('lcdp.scheduler.task.grid.entity.alarmEmail'), type: 'text' },
{
colsFirst: true,
name: 'scheduleType',
label: $t('lcdp.scheduler.task.grid.entity.scheduleType'),
type: 'select',
options: Options.enum(TaskScheduleTypeEnum),
defaultValue: 'FIX_RATE',
},
{ name: 'scheduleConf', label: $t('lcdp.scheduler.task.grid.entity.scheduleConf'), type: 'text', defaultValue: '60' },
{
name: 'executorGlueType',
label: $t('lcdp.scheduler.task.grid.entity.executorGlueType'),
type: 'select',
options: Options.enum(GlueTypeEnum),
},
{ name: 'executorHandler', label: $t('lcdp.scheduler.task.grid.entity.executorHandler'), type: 'text' },
{ colSpan: 2, name: 'executorParam', label: $t('lcdp.scheduler.task.grid.entity.executorParam'), type: 'textarea', rows: 5 },
{
name: 'routeStrategy',
label: $t('lcdp.scheduler.task.grid.entity.routeStrategy'),
type: 'select',
options: Options.enum(ExecutorRouteStrategyEnum),
defaultValue: 'FIX_RATE',
},
{
name: 'expirationPolicy',
label: $t('lcdp.scheduler.task.grid.entity.expirationPolicy'),
type: 'select',
options: Options.enum(ExpirationPolicyEnum),
},
{
name: 'blockStrategy',
label: $t('lcdp.scheduler.task.grid.entity.blockStrategy'),
type: 'select',
options: Options.enum(BlockStrategyEnum),
},
{ colsFirst: true, name: 'timeout', label: $t('lcdp.scheduler.task.grid.entity.timeout'), type: 'number' },
{ name: 'failRetryCount', label: $t('lcdp.scheduler.task.grid.entity.failRetryCount'), type: 'number' },
],
},
}"
:viewer="{
panel: {
columnNum: 1,
fields: [
{ name: 'id', label: $t('id') },
{ name: 'executor', label: $t('lcdp.scheduler.task.grid.entity.executorId') },
{ name: 'executorName', label: $t('lcdp.scheduler.task.grid.entity.executorName') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
{ name: 'author', label: $t('lcdp.scheduler.task.grid.entity.author') },
{ name: 'alarmEmail', label: $t('lcdp.scheduler.task.grid.entity.alarmEmail') },
{ name: 'scheduleType', label: $t('lcdp.scheduler.task.grid.entity.scheduleType'), format: Formater.none() },
{ name: 'scheduleConf', label: $t('lcdp.scheduler.task.grid.entity.scheduleConf') },
{ name: 'executorGlueType', label: $t('lcdp.scheduler.task.grid.entity.executorGlueType'), format: Formater.none() },
{ name: 'executorHandler', label: $t('lcdp.scheduler.task.grid.entity.executorHandler') },
{ name: 'executorParam', label: $t('lcdp.scheduler.task.grid.entity.executorParam') },
{ name: 'routeStrategy', label: $t('lcdp.scheduler.task.grid.entity.routeStrategy') },
{ name: 'expirationPolicy', label: $t('lcdp.scheduler.task.grid.entity.expirationPolicy') },
{ name: 'blockStrategy', label: $t('lcdp.scheduler.task.grid.entity.blockStrategy') },
{ name: 'timeout', label: $t('lcdp.scheduler.task.grid.entity.timeout') },
{ name: 'failRetryCount', label: $t('lcdp.scheduler.task.grid.entity.failRetryCount') },
{ name: 'triggerStatus', label: $t('lcdp.scheduler.task.grid.entity.triggerStatus') },
{ name: 'triggerLastTime', label: $t('lcdp.scheduler.task.grid.entity.triggerLastTime') },
{ name: 'triggerNextTime', label: $t('lcdp.scheduler.task.grid.entity.triggerNextTime') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@before-editor-data-submit="
(data, submit) => {
data.addresses = data.addresses.split(',');
submit(data);
}
"
></w-grid>
</template>
<script setup lang="ts">
import { ref, inject } from 'vue';
import { axios, Environment, EnumTools, Formater, Options } from 'platform-core';
const eventBus = inject('eventBus');
const ExecutorRouteStrategyEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.ExecutorRouteStrategy');
const ExpirationPolicyEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.ExpirationPolicy');
const BlockStrategyEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.BlockStrategy');
const GlueTypeEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.GlueType');
const TaskScheduleTypeEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.TaskScheduleType');
const TriggerStatusEnum = await EnumTools.fetch('io.sc.platform.scheduler.core.enums.TriggerStatus');
const executorOptionsRef = ref([]);
const reloadExecutor = () => {
axios.get(Environment.apiContextPath('/api/scheduler/executor?pageable=false')).then((response) => {
executorOptionsRef.value.splice(0, executorOptionsRef.value.length);
const list = response?.data?.content;
if (list) {
for (const item of list) {
executorOptionsRef.value.push({ label: item.name + ' ( ' + item.appName + ' )', value: item.id });
}
}
});
};
//
eventBus.on('io.sc.platform.scheduler.manager.ExecutorChanged', () => {
reloadExecutor();
});
reloadExecutor();
</script>

15
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/ExecutorWebController.java

@ -0,0 +1,15 @@
package io.sc.platform.scheduler.manager.controller;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.scheduler.core.vo.ExecutorVo;
import io.sc.platform.scheduler.manager.jpa.entity.ExecutorEntity;
import io.sc.platform.scheduler.manager.jpa.repository.ExecutorRepository;
import io.sc.platform.scheduler.manager.service.ExecutorService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/scheduler/executor")
public class ExecutorWebController extends RestCrudController<ExecutorVo, ExecutorEntity, String, ExecutorRepository, ExecutorService> {
}

15
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/ReportWebController.java

@ -0,0 +1,15 @@
package io.sc.platform.scheduler.manager.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("api/scheduler/report")
public class ReportWebController {
public Map<String,Object> dashboard(){
return null;
}
}

15
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/controller/TaskWebController.java

@ -0,0 +1,15 @@
package io.sc.platform.scheduler.manager.controller;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.scheduler.core.vo.TaskVo;
import io.sc.platform.scheduler.manager.jpa.entity.TaskEntity;
import io.sc.platform.scheduler.manager.jpa.repository.TaskRepository;
import io.sc.platform.scheduler.manager.service.TaskService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/scheduler/task")
public class TaskWebController extends RestCrudController<TaskVo, TaskEntity, String, TaskRepository, TaskService> {
}

4
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/ExecutorEntity.java

@ -49,11 +49,13 @@ public class ExecutorEntity extends CorporationAuditorEntity<ExecutorVo> {
@Override
public ExecutorVo toVo() {
ExecutorVo vo =new ExecutorVo();
CorporationAuditorEntity.toVo(vo,this);
super.toVo(vo);
vo.setId(this.getId());
vo.setAppName(this.getAppName());
vo.setName(this.getName());
vo.setDescription(this.getDescription());
vo.setAddressType(this.getAddressType());
vo.setAddresses(this.getAddresses());
return vo;
}

91
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/GlueEntity.java

@ -0,0 +1,91 @@
package io.sc.platform.scheduler.manager.jpa.entity;
import io.sc.platform.orm.entity.CorporationAuditorEntity;
import io.sc.platform.scheduler.core.enums.GlueType;
import io.sc.platform.scheduler.core.vo.GlueVo;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.util.StringUtils;
import javax.persistence.*;
import javax.validation.constraints.Size;
@Entity
@Table(name="JOB_GLUE")
public class GlueEntity extends CorporationAuditorEntity<GlueVo> {
//主键
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name="ID_", length=36)
@Size(max=36)
private String id;
@Column(name="GLUE_TYPE_")
@Enumerated(EnumType.STRING)
private GlueType type;
@Column(name="DESCRIPTION_", length=255)
@Size(max=255)
private String description;
@Column(name="SOURCE_")
private String source;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="TASK_ID_")
private TaskEntity task;
@Override
public GlueVo toVo() {
GlueVo vo =new GlueVo();
super.toVo(vo);
vo.setId(this.getId());
vo.setType(this.getType());
vo.setDescription(this.getDescription());
vo.setSource(this.getSource());
if(task!=null && StringUtils.hasText(task.getId())){
vo.setTask(task.getId());
}
return vo;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public GlueType getType() {
return type;
}
public void setType(GlueType type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public TaskEntity getTask() {
return task;
}
public void setTask(TaskEntity task) {
this.task = task;
}
}

4
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/TaskLogReportEntity.java → io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/ReportEntity.java

@ -9,8 +9,8 @@ import javax.validation.constraints.Size;
import java.util.Date;
@Entity
@Table(name="JOB_TASK_LOG_REPORT")
public class TaskLogReportEntity extends BaseEntity<TaskLogReportVo> {
@Table(name="JOB_REPORT")
public class ReportEntity extends BaseEntity<TaskLogReportVo> {
//主键
@Id
@GeneratedValue(generator = "system-uuid")

174
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/entity/TaskEntity.java

@ -4,6 +4,7 @@ import io.sc.platform.scheduler.core.enums.*;
import io.sc.platform.scheduler.core.vo.TaskVo;
import io.sc.platform.orm.entity.CorporationAuditorEntity;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.util.StringUtils;
import javax.persistence.*;
import javax.validation.constraints.Size;
@ -19,6 +20,16 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
@Size(max=36)
private String id;
//父任务
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PARENT_ID_")
private TaskEntity parent;
//执行器ID
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="EXECUTOR_ID_")
private ExecutorEntity executor;
//名称
@Column(name="NAME_", length=255)
@Size(min=1,max=255)
@ -29,10 +40,10 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
@Size(max=255)
private String description;
//执行器
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="EXECUTOR_ID_")
private ExecutorEntity executor;
//负责人
@Column(name="AUTHOR_", length=255)
@Size(max=255)
private String author;
//报警邮件
@Column(name="ALARM_EMAIL_", length=255)
@ -44,38 +55,42 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
@Enumerated(EnumType.STRING)
private TaskScheduleType scheduleType;
//调度配置,值含义取决于调度类型
//调度配置
@Column(name="SCHEDULE_CONF_", length=255)
@Size(max=255)
private String scheduleConf;
//调度过期策略
@Column(name="EXPIRATION_POLICY_")
@Enumerated(EnumType.STRING)
private ExpirationPolicy expirationPolicy;
//执行器路由策略
@Column(name="ROUTE_STRATEGY_")
//Glue 类型
@Column(name="EXECUTOR_GLUE_TYPE_")
@Enumerated(EnumType.STRING)
private ExecutorRouteStrategy routeStrategy;
private GlueType executorGlueType;
//执行器,任务Handler名称
//Handler名称
@Column(name="EXECUTOR_HANDLER_", length=255)
@Size(max=255)
private String executorHandler;
//执行器,任务参数
@Column(name="EXECUTOR_PARAM_", length=255)
@Size(max=255)
//参数
@Column(name="EXECUTOR_PARAM_", length=1024)
@Size(max=1024)
private String executorParam;
//阻塞处理策略
//路由策略
@Column(name="ROUTE_STRATEGY_")
@Enumerated(EnumType.STRING)
private ExecutorRouteStrategy routeStrategy;
//过期策略
@Column(name="EXPIRATION_POLICY_")
@Enumerated(EnumType.STRING)
private ExpirationPolicy expirationPolicy;
//阻塞策略
@Column(name="BLOCK_STRATEGY_")
@Enumerated(EnumType.STRING)
private BlockStrategy blockStrategy;
//任务执行超时时间,单位秒
//超时时间,单位秒
@Column(name="TIMEOUT_")
private int timeout;
@ -83,20 +98,6 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
@Column(name="FAIL_RETRY_COUNT_")
private int failRetryCount;
//GLUE类型
@Column(name="GLUE_TYPE_")
@Enumerated(EnumType.STRING)
private GlueType glueType;
//GLUE源代码
@Column(name="GLUE_SOURCE_")
private String glueSource;
//父任务
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PARENT_ID_")
private TaskEntity parent;
//调度状态
@Column(name="TRIGGER_STATUS_")
@Enumerated(EnumType.STRING)
@ -110,30 +111,41 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
@Column(name="TRIGGER_NEXT_TIME_")
private long triggerNextTime;
@Override
public TaskVo toVo() {
TaskVo vo =new TaskVo();
CorporationAuditorEntity.toVo(vo,this);
super.toVo(vo);
vo.setId(this.getId());
if(parent!=null && StringUtils.hasText(parent.getId())){
vo.setParent(parent.getId());
}
if(executor!=null && StringUtils.hasText(executor.getId())){
vo.setExecutor(executor.getId());
vo.setExecutorName(executor.getName());
}
vo.setName(this.getName());
vo.setDescription(this.getDescription());
vo.setExecutor(this.getExecutor()==null?null:this.getExecutor().getId());
vo.setAuthor(this.getAuthor());
vo.setAlarmEmail(this.getAlarmEmail());
vo.setScheduleType(this.getScheduleType());
vo.setScheduleConf(this.getScheduleConf());
vo.setExpirationPolicy(this.getExpirationPolicy());
vo.setRouteStrategy(this.getRouteStrategy());
vo.setExecutorGlueType(this.getExecutorGlueType());
vo.setExecutorHandler(this.getExecutorHandler());
vo.setExecutorParam(this.getExecutorParam());
vo.setRouteStrategy(this.getRouteStrategy());
vo.setExpirationPolicy(this.getExpirationPolicy());
vo.setBlockStrategy(this.getBlockStrategy());
vo.setTimeout(this.getTimeout());
vo.setFailRetryCount(this.getFailRetryCount());
vo.setGlueType(this.getGlueType());
vo.setGlueSource(this.getGlueSource());
vo.setParent(this.getParent()==null?null:this.getParent().getId());
vo.setTriggerStatus(this.getTriggerStatus());
vo.setTriggerLastTime(this.getTriggerLastTime());
vo.setTriggerNextTime(this.getTriggerNextTime());
return vo;
}
@ -145,6 +157,22 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
this.id = id;
}
public TaskEntity getParent() {
return parent;
}
public void setParent(TaskEntity parent) {
this.parent = parent;
}
public ExecutorEntity getExecutor() {
return executor;
}
public void setExecutor(ExecutorEntity executor) {
this.executor = executor;
}
public String getName() {
return name;
}
@ -161,12 +189,12 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
this.description = description;
}
public ExecutorEntity getExecutor() {
return executor;
public String getAuthor() {
return author;
}
public void setExecutor(ExecutorEntity executor) {
this.executor = executor;
public void setAuthor(String author) {
this.author = author;
}
public String getAlarmEmail() {
@ -193,20 +221,12 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
this.scheduleConf = scheduleConf;
}
public ExpirationPolicy getExpirationPolicy() {
return expirationPolicy;
}
public void setExpirationPolicy(ExpirationPolicy expirationPolicy) {
this.expirationPolicy = expirationPolicy;
}
public ExecutorRouteStrategy getRouteStrategy() {
return routeStrategy;
public GlueType getExecutorGlueType() {
return executorGlueType;
}
public void setRouteStrategy(ExecutorRouteStrategy routeStrategy) {
this.routeStrategy = routeStrategy;
public void setExecutorGlueType(GlueType executorGlueType) {
this.executorGlueType = executorGlueType;
}
public String getExecutorHandler() {
@ -225,6 +245,22 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
this.executorParam = executorParam;
}
public ExecutorRouteStrategy getRouteStrategy() {
return routeStrategy;
}
public void setRouteStrategy(ExecutorRouteStrategy routeStrategy) {
this.routeStrategy = routeStrategy;
}
public ExpirationPolicy getExpirationPolicy() {
return expirationPolicy;
}
public void setExpirationPolicy(ExpirationPolicy expirationPolicy) {
this.expirationPolicy = expirationPolicy;
}
public BlockStrategy getBlockStrategy() {
return blockStrategy;
}
@ -249,30 +285,6 @@ public class TaskEntity extends CorporationAuditorEntity<TaskVo> {
this.failRetryCount = failRetryCount;
}
public GlueType getGlueType() {
return glueType;
}
public void setGlueType(GlueType glueType) {
this.glueType = glueType;
}
public String getGlueSource() {
return glueSource;
}
public void setGlueSource(String glueSource) {
this.glueSource = glueSource;
}
public TaskEntity getParent() {
return parent;
}
public void setParent(TaskEntity parent) {
this.parent = parent;
}
public TriggerStatus getTriggerStatus() {
return triggerStatus;
}

5
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/jpa/repository/TaskLogReportRepository.java

@ -1,8 +1,7 @@
package io.sc.platform.scheduler.manager.jpa.repository;
import io.sc.platform.scheduler.manager.jpa.entity.TaskLogEntity;
import io.sc.platform.scheduler.manager.jpa.entity.TaskLogReportEntity;
import io.sc.platform.scheduler.manager.jpa.entity.ReportEntity;
import io.sc.platform.orm.repository.DaoRepository;
public interface TaskLogReportRepository extends DaoRepository<TaskLogReportEntity,String> {
public interface TaskLogReportRepository extends DaoRepository<ReportEntity,String> {
}

9
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/ExecutorService.java

@ -0,0 +1,9 @@
package io.sc.platform.scheduler.manager.service;
import io.sc.platform.orm.service.DaoService;
import io.sc.platform.scheduler.manager.jpa.entity.ExecutorEntity;
import io.sc.platform.scheduler.manager.jpa.repository.ExecutorRepository;
public interface ExecutorService extends DaoService<ExecutorEntity, String, ExecutorRepository> {
}

7
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/ReportService.java

@ -0,0 +1,7 @@
package io.sc.platform.scheduler.manager.service;
import java.util.Map;
public interface ReportService {
public Map<String,Object> dashboard();
}

9
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/TaskService.java

@ -0,0 +1,9 @@
package io.sc.platform.scheduler.manager.service;
import io.sc.platform.orm.service.DaoService;
import io.sc.platform.scheduler.manager.jpa.entity.TaskEntity;
import io.sc.platform.scheduler.manager.jpa.repository.TaskRepository;
public interface TaskService extends DaoService<TaskEntity, String, TaskRepository> {
}

12
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/ExecutorServiceImpl.java

@ -0,0 +1,12 @@
package io.sc.platform.scheduler.manager.service.impl;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import io.sc.platform.scheduler.manager.jpa.entity.ExecutorEntity;
import io.sc.platform.scheduler.manager.jpa.repository.ExecutorRepository;
import io.sc.platform.scheduler.manager.service.ExecutorService;
import org.springframework.stereotype.Service;
@Service
public class ExecutorServiceImpl extends DaoServiceImpl<ExecutorEntity, String, ExecutorRepository> implements ExecutorService {
}

13
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/ReportServiceImpl.java

@ -0,0 +1,13 @@
package io.sc.platform.scheduler.manager.service.impl;
import io.sc.platform.scheduler.manager.service.ReportService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
public class ReportServiceImpl implements ReportService {
@Override
public Map<String, Object> dashboard() {
return null;
}
}

12
io.sc.platform.scheduler.manager/src/main/java/io/sc/platform/scheduler/manager/service/impl/TaskServiceImpl.java

@ -0,0 +1,12 @@
package io.sc.platform.scheduler.manager.service.impl;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import io.sc.platform.scheduler.manager.jpa.entity.TaskEntity;
import io.sc.platform.scheduler.manager.jpa.repository.TaskRepository;
import io.sc.platform.scheduler.manager.service.TaskService;
import org.springframework.stereotype.Service;
@Service
public class TaskServiceImpl extends DaoServiceImpl<TaskEntity, String, TaskRepository> implements TaskService {
}

6
io.sc.platform.security.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.platform.security.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -101,4 +101,4 @@
"vue-router": "4.2.5",
"platform-core": "8.1.119"
}
}
}

2
io.sc.platform.security/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -4,7 +4,7 @@
"order" : 100,
"description":"授权与认证相关数据库表结构",
"locations":[
"liquibase/PF_11.0.0_20220606__Security_DDL.xml"
"liquibase/io.sc.platform.security_8.0.0_20220606__Security Database Schema DDL.xml"
]
}
]

2
io.sc.platform.security/src/main/resources/liquibase/PF_11.0.0_20220606__Security_DDL.xml → io.sc.platform.security/src/main/resources/liquibase/io.sc.platform.security_8.0.0_20220606__Security Database Schema DDL.xml

@ -10,7 +10,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
"
>
<changeSet id="PF_11.0.0_20220606__Security_DDL" author="platform">
<changeSet id="io.sc.platform.security_8.0.0_20220606__Security Database Schema DDL" author="platform">
<!-- 法人信息表 -->
<createTable tableName="SYS_CORPORATION" remarks="法人信息表">
<column name="ID_" type="NVARCHAR(36)" remarks="ID">

6
io.sc.platform.system.frontend/package.json

@ -1,10 +1,10 @@
{
"name": "io.sc.platform.system.frontend",
"version": "8.1.23",
"version": "8.1.24",
"description": "",
"private": false,
"keywords": [
],
"author": "",
"license": "ISC",
@ -102,4 +102,4 @@
"codemirror": "6.0.1",
"vue-codemirror6": "1.2.0"
}
}
}

2
io.sc.platform.system/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -4,7 +4,7 @@
"order" : 1000,
"description":"系统管理相关数据库表结构",
"locations":[
"liquibase/PF_11.0.0_20220606__System_DDL.xml"
"liquibase/io.sc.platform.system_8.0.0_20220606__System Database Schema DDL.xml"
]
}
]

2
io.sc.platform.system/src/main/resources/liquibase/PF_11.0.0_20220606__System_DDL.xml → io.sc.platform.system/src/main/resources/liquibase/io.sc.platform.system_8.0.0_20220606__System Database Schema DDL.xml

@ -10,7 +10,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
"
>
<changeSet id="PF_11.0.0_20220606__System_DDL" author="platform">
<changeSet id="io.sc.platform.system_8.0.0_20220606__System Database Schema DDL" author="platform">
<!-- 系统审计日志表 -->
<createTable tableName="SYS_AUDIT_LOG" remarks="系统审计日志表">
<column name="ID_" type="NVARCHAR(36)" remarks="ID">
Loading…
Cancel
Save