params) {
+ public void process() throws Exception {
var stocks = stockService.list();
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
tuShareService.stockList()
@@ -54,6 +54,5 @@ public class UpdateStockInformationTask extends TaskRunner {
}
});
stockService.save(stocks);
- return null;
}
}
diff --git a/leopard-server/src/main/resources/application.yml b/leopard-server/src/main/resources/application.yml
index b7d2c86..944a64a 100644
--- a/leopard-server/src/main/resources/application.yml
+++ b/leopard-server/src/main/resources/application.yml
@@ -15,5 +15,15 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
generate-ddl: true
+ quartz:
+ wait-for-jobs-to-complete-on-shutdown: true
+ startup-delay: 30s
+ job-store-type: jdbc
+ jdbc:
+ platform: mysql
fenix:
print-banner: false
+liteflow:
+ print-banner: false
+ rule-source: flow.xml
+ check-node-exists: false
\ No newline at end of file
diff --git a/leopard-server/src/main/resources/flow.xml b/leopard-server/src/main/resources/flow.xml
new file mode 100644
index 0000000..a7d4480
--- /dev/null
+++ b/leopard-server/src/main/resources/flow.xml
@@ -0,0 +1,7 @@
+
+
+
+
+ CATCH(THEN(task_start, update_stock_information, task_end)).DO(task_error)
+
+
diff --git a/leopard-web/src/index.tsx b/leopard-web/src/index.tsx
index d09fd21..395c81e 100644
--- a/leopard-web/src/index.tsx
+++ b/leopard-web/src/index.tsx
@@ -11,6 +11,8 @@ import TaskList from './pages/task/TaskList.tsx'
import TaskAdd from './pages/task/TaskAdd.tsx'
import TaskTemplateList from './pages/task/TaskTemplateList.tsx'
import TaskTemplateSave from './pages/task/TaskTemplateSave.tsx'
+import TaskScheduleList from './pages/task/TaskScheduleList.tsx'
+import TaskScheduleSave from './pages/task/TaskScheduleSave.tsx'
const routes: RouteObject[] = [
{
@@ -66,6 +68,19 @@ const routes: RouteObject[] = [
},
],
},
+ {
+ path: 'schedule',
+ children: [
+ {
+ path: 'list',
+ Component: TaskScheduleList,
+ },
+ {
+ path: 'save',
+ Component: TaskScheduleSave,
+ },
+ ],
+ },
],
},
{
diff --git a/leopard-web/src/pages/Root.tsx b/leopard-web/src/pages/Root.tsx
index 0ae20d8..2f23629 100644
--- a/leopard-web/src/pages/Root.tsx
+++ b/leopard-web/src/pages/Root.tsx
@@ -2,8 +2,8 @@ import {
DeploymentUnitOutlined,
InfoCircleOutlined,
MoneyCollectOutlined,
- UnorderedListOutlined
-} from "@ant-design/icons";
+ UnorderedListOutlined,
+} from '@ant-design/icons'
import {type AppItemProps, ProLayout} from '@ant-design/pro-components'
import {ConfigProvider} from 'antd'
import {dateFormat} from 'licia'
@@ -52,8 +52,12 @@ const menus = {
{
path: '/task/template/list',
name: '任务模板',
- }
- ]
+ },
+ {
+ path: '/task/schedule/list',
+ name: '定时任务',
+ },
+ ],
},
{
path: '/test',
diff --git a/leopard-web/src/pages/task/TaskScheduleList.tsx b/leopard-web/src/pages/task/TaskScheduleList.tsx
new file mode 100644
index 0000000..2e2ea1a
--- /dev/null
+++ b/leopard-web/src/pages/task/TaskScheduleList.tsx
@@ -0,0 +1,125 @@
+import React from 'react'
+import {amisRender, commonInfo, crudCommonOptions, paginationTemplate, remoteMappings, time} from '../../util/amis.tsx'
+import {useNavigate} from 'react-router'
+
+function TaskScheduleList() {
+ const navigate = useNavigate()
+ return (
+
+ {amisRender(
+ {
+ type: 'page',
+ title: '定时任务',
+ body: [
+ {
+ type: 'crud',
+ api: `get:${commonInfo.baseUrl}/task_schedule/list`,
+ ...crudCommonOptions(),
+ ...paginationTemplate(
+ 15,
+ undefined,
+ [
+ {
+ type: 'action',
+ label: '',
+ icon: 'fa fa-plus',
+ tooltip: '添加定时任务',
+ tooltipPlacement: 'top',
+ onEvent: {
+ click: {
+ actions: [
+ {
+ actionType: 'custom',
+ // @ts-ignore
+ script: (context, action, event) => {
+ navigate('/task/schedule/save')
+ },
+ },
+ ],
+ },
+ },
+ },
+ ],
+ ),
+ columns: [
+ {
+ name: 'templateName',
+ label: '模板名称',
+ width: 150,
+ },
+ {
+ name: 'templateDescription',
+ label: '模板描述',
+ },
+ {
+ name: 'cron',
+ label: '定时策略',
+ width: 150,
+ },
+ {
+ name: 'status',
+ label: '状态',
+ width: 100,
+ ...remoteMappings('trigger_status', 'status'),
+ },
+ {
+ name: 'previousFireTime',
+ label: '上次启动时间',
+ width: 150,
+ align: 'center',
+ ...time('previousFireTime'),
+ },
+ {
+ name: 'nextFireTime',
+ label: '下次启动时间',
+ width: 150,
+ align: 'center',
+ ...time('nextFireTime'),
+ },
+ {
+ type: 'operation',
+ label: '操作',
+ width: 150,
+ buttons: [
+ {
+ visibleOn: 'status !== \'PAUSED\' ',
+ type: 'action',
+ label: '暂停',
+ level: 'link',
+ actionType: 'ajax',
+ api: `get:${commonInfo.baseUrl}/task_schedule/pause/\${key}`,
+ confirmText: '确认暂停定时任务${templateName}?',
+ confirmTitle: '暂停',
+ },
+ {
+ visibleOn: 'status === \'PAUSED\' ',
+ type: 'action',
+ label: '恢复',
+ level: 'link',
+ actionType: 'ajax',
+ api: `get:${commonInfo.baseUrl}/task_schedule/resume/\${key}`,
+ confirmText: '确认恢复定时任务${templateName}?',
+ confirmTitle: '恢复',
+ },
+ {
+ className: 'text-danger',
+ type: 'action',
+ label: '删除',
+ level: 'link',
+ actionType: 'ajax',
+ api: `get:${commonInfo.baseUrl}/task_schedule/remove/\${key}`,
+ confirmText: '确认删除定时任务${templateName}?',
+ confirmTitle: '删除',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ )}
+
+ )
+}
+
+export default React.memo(TaskScheduleList)
\ No newline at end of file
diff --git a/leopard-web/src/pages/task/TaskScheduleSave.tsx b/leopard-web/src/pages/task/TaskScheduleSave.tsx
new file mode 100644
index 0000000..d7bf8aa
--- /dev/null
+++ b/leopard-web/src/pages/task/TaskScheduleSave.tsx
@@ -0,0 +1,74 @@
+import React from 'react'
+import {amisRender, commonInfo, remoteOptions} from '../../util/amis.tsx'
+import {useNavigate} from 'react-router'
+
+function TaskScheduleSave() {
+ const navigate = useNavigate()
+ return (
+
+ {amisRender(
+ {
+ type: 'page',
+ title: '任务模板添加',
+ body: [
+ {
+ debug: commonInfo.debug,
+ type: 'form',
+ api: `post:${commonInfo.baseUrl}/task_schedule/save`,
+ wrapWithPanel: false,
+ mode: 'horizontal',
+ labelAlign: 'left',
+ onEvent: {
+ submitSucc: {
+ actions: [
+ {
+ actionType: 'custom',
+ // @ts-ignore
+ script: (context, action, event) => {
+ navigate(-1)
+ },
+ },
+ ],
+ },
+ },
+ body: [
+ {
+ name: 'templateId',
+ label: '名称',
+ required: true,
+ selectFirst: true,
+ ...remoteOptions('select', 'task_template_id'),
+ },
+ {
+ type: 'input-text',
+ name: 'cron',
+ label: '定时策略',
+ required: true,
+ clearable: true,
+ },
+ {
+ type: 'button-toolbar',
+ buttons: [
+ {
+ type: 'action',
+ label: '提交',
+ actionType: 'submit',
+ level: 'primary',
+ },
+ {
+ type: 'action',
+ label: '重置',
+ actionType: 'reset',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ )}
+
+ )
+}
+
+export default React.memo(TaskScheduleSave)
\ No newline at end of file
diff --git a/leopard-web/src/pages/task/TaskTemplateList.tsx b/leopard-web/src/pages/task/TaskTemplateList.tsx
index 4ef8065..baa0df3 100644
--- a/leopard-web/src/pages/task/TaskTemplateList.tsx
+++ b/leopard-web/src/pages/task/TaskTemplateList.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {amisRender, commonInfo, crudCommonOptions, paginationTemplate, remoteMappings} from '../../util/amis.tsx'
+import {amisRender, commonInfo, crudCommonOptions, paginationTemplate} from '../../util/amis.tsx'
import {useNavigate} from 'react-router'
function TaskTemplateList() {
@@ -60,12 +60,6 @@ function TaskTemplateList() {
name: 'description',
label: '描述',
},
- {
- name: 'type',
- label: '类型',
- width: 100,
- ...remoteMappings('task_template_type', 'type'),
- },
{
type: 'operation',
label: '操作',
diff --git a/leopard-web/src/pages/task/TaskTemplateSave.tsx b/leopard-web/src/pages/task/TaskTemplateSave.tsx
index ee51af5..c74152f 100644
--- a/leopard-web/src/pages/task/TaskTemplateSave.tsx
+++ b/leopard-web/src/pages/task/TaskTemplateSave.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {amisRender, commonInfo, remoteOptions} from '../../util/amis.tsx'
+import {amisRender, commonInfo} from '../../util/amis.tsx'
import {useNavigate, useParams} from 'react-router'
function TaskTemplateSave() {
@@ -31,8 +31,8 @@ function TaskTemplateSave() {
navigate(-1)
},
},
- ]
- }
+ ],
+ },
},
body: [
{
@@ -43,29 +43,21 @@ function TaskTemplateSave() {
type: 'input-text',
name: 'name',
label: '名称',
- require: true,
+ required: true,
clearable: true,
},
{
type: 'textarea',
name: 'description',
label: '描述',
- require: true,
+ required: true,
clearable: true,
},
{
- name: 'type',
- label: '任务类型',
- require: true,
- selectFirst: true,
- ...remoteOptions('select', 'task_template_type'),
- },
- {
- visibleOn: 'type === \'CLASS\'',
type: 'input-text',
- name: 'clazz',
- label: '类路径',
- require: true,
+ name: 'chain',
+ label: '流程编号',
+ required: true,
clearable: true,
},
{
diff --git a/pom.xml b/pom.xml
index 5060bc0..054cb6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,97 +2,97 @@
- 4.0.0
+ 4.0.0
com.lanyuanxiaoyao
leopard
1.0.0
pom
-
- leopard-server
-
+
+ leopard-server
+
-
- 17
- 17
- 17
- UTF-8
+
+ 17
+ 17
+ 17
+ UTF-8
- 3.5.0
- 2025.0.0
- 1.0.1
+ 3.5.0
+ 2025.0.0
+ 1.0.1
- 13.0.0
- 5.8.39
- 2.13.2
-
+ 13.0.0
+ 5.8.39
+ 2.15.0
+
+
+
+ org.projectlombok
+ lombok
+ compile
+
+
+
+
-
- org.projectlombok
- lombok
- compile
-
+
+ com.lanyuanxiaoyao
+ spring-boot-service-template
+ 1.0.0-SNAPSHOT
+
+
+
+ cn.hutool
+ hutool-core
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-http
+ ${hutool.version}
+
+
+
+ com.yomahub
+ liteflow-spring-boot-starter
+ ${liteflow.version}
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+ org.springframework.ai
+ spring-ai-bom
+ ${spring-ai.version}
+ pom
+ import
+
+
-
-
-
- com.lanyuanxiaoyao
- spring-boot-service-template
- 1.0.0-SNAPSHOT
-
-
-
- cn.hutool
- hutool-core
- ${hutool.version}
-
-
- cn.hutool
- hutool-http
- ${hutool.version}
-
-
-
- com.yomahub
- liteflow-spring-boot-starter
- ${liteflow.version}
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${spring-boot.version}
- pom
- import
-
-
- org.springframework.ai
- spring-ai-bom
- ${spring-ai.version}
- pom
- import
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.14.0
-
-
- org.springframework.boot
- spring-boot-maven-plugin
- ${spring-boot.version}
-
-
-
-
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.14.0
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+
+
+
\ No newline at end of file