From 414f0f28ab77777d64770679461ffaabae7d27f1 Mon Sep 17 00:00:00 2001 From: Lazy <2211717435@qq.com> Date: Sun, 12 Nov 2023 21:23:11 +0800 Subject: [PATCH 01/11] Feat: get schedules --- frontend/src/config/index.ts | 4 +- frontend/src/config/router.ts | 18 ++ frontend/src/services/apis/instance.ts | 16 +- frontend/src/types/index.ts | 10 + frontend/src/widgets/instance/ManagerBtns.vue | 14 +- frontend/src/widgets/instance/schedule.vue | 223 ++++++++++++++++++ panel/src/app/service/frontend_layout.ts | 22 ++ 7 files changed, 302 insertions(+), 5 deletions(-) create mode 100644 frontend/src/widgets/instance/schedule.vue diff --git a/frontend/src/config/index.ts b/frontend/src/config/index.ts index b990ceec..56e47161 100644 --- a/frontend/src/config/index.ts +++ b/frontend/src/config/index.ts @@ -32,6 +32,7 @@ import UserStatusBlock from "@/widgets/UserStatusBlock.vue"; import UserInstanceList from "@/widgets/UserInstanceList.vue"; import ImageManager from "@/widgets/imageManager/index.vue"; import NewImage from "@/widgets/imageManager/NewImage.vue"; +import Schedule from "@/widgets/instance/schedule.vue"; import { NEW_CARD_TYPE } from "../types/index"; import { ROLE } from "./router"; @@ -67,7 +68,8 @@ export const LAYOUT_CARD_TYPES: { [key: string]: any } = { UserStatusBlock, UserInstanceList, ImageManager, - NewImage + NewImage, + Schedule }; export interface NewCardItem extends LayoutCard { diff --git a/frontend/src/config/router.ts b/frontend/src/config/router.ts index bd908fe4..b1005067 100644 --- a/frontend/src/config/router.ts +++ b/frontend/src/config/router.ts @@ -103,6 +103,24 @@ let originRouterConfig: RouterConfig[] = [ ] } ] + }, + { + path: "/instances/schedule", + name: t("计划任务"), + component: LayoutContainer, + meta: { + permission: ROLE.USER + } + // children: [ + // { + // path: "/instances/schedule/new", + // name: t("新增计划任务"), + // component: LayoutContainer, + // meta: { + // permission: ROLE.USER + // } + // } + // ] } ] }, diff --git a/frontend/src/services/apis/instance.ts b/frontend/src/services/apis/instance.ts index 8282aa52..92fb1236 100644 --- a/frontend/src/services/apis/instance.ts +++ b/frontend/src/services/apis/instance.ts @@ -1,5 +1,5 @@ import { useDefineApi } from "@/stores/useDefineApi"; -import type { InstanceDetail, NewInstanceForm, QuickStartTemplate } from "@/types"; +import type { InstanceDetail, NewInstanceForm, QuickStartTemplate, Schedule } from "@/types"; import type { IGlobalInstanceConfig } from "../../../../common/global"; import type { InstanceMoreDetail } from "@/hooks/useInstance"; @@ -343,3 +343,17 @@ export const batchDelete = useDefineApi< method: "DELETE", url: "/api/instance" }); + +// 获取计划任务 +export const scheduleList = useDefineApi< + { + params: { + remote_uuid: string; + uuid: string; + }; + }, + Schedule[] +>({ + method: "GET", + url: "/api/protected_schedule" +}); diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 2746ab48..9526c755 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -218,3 +218,13 @@ export interface MountComponent { destroyComponent: Function; emitResult: Function; } + +export interface Schedule { + instanceUuid: string; + name: string; + count: number; + time: string; + action: string; + payload: string; + type: number; +} diff --git a/frontend/src/widgets/instance/ManagerBtns.vue b/frontend/src/widgets/instance/ManagerBtns.vue index 7cb5a24f..3b86abd6 100644 --- a/frontend/src/widgets/instance/ManagerBtns.vue +++ b/frontend/src/widgets/instance/ManagerBtns.vue @@ -3,7 +3,7 @@ import { ref, computed } from "vue"; import type { LayoutCard } from "@/types"; import { arrayFilter } from "../../tools/array"; import { t } from "@/lang/i18n"; -import { ArrowRightOutlined, CloudServerOutlined } from "@ant-design/icons-vue"; +import { ArrowRightOutlined, CloudServerOutlined, FieldTimeOutlined } from "@ant-design/icons-vue"; import InnerCard from "@/components/InnerCard.vue"; import { LayoutCardHeight } from "../../config/originLayoutConfig"; import { useAppRouters } from "@/hooks/useAppRouters"; @@ -80,9 +80,17 @@ const btns = computed(() => }, { title: t("TXT_CODE_b7d026f8"), - icon: CloudServerOutlined, + icon: FieldTimeOutlined, condition: () => !isGlobalTerminal.value, - click: () => {} + click: () => { + toPage({ + path: "/instances/schedule", + query: { + instanceId, + daemonId + } + }); + } }, // 暂时删除 // { diff --git a/frontend/src/widgets/instance/schedule.vue b/frontend/src/widgets/instance/schedule.vue new file mode 100644 index 00000000..5b88845d --- /dev/null +++ b/frontend/src/widgets/instance/schedule.vue @@ -0,0 +1,223 @@ + + + + + diff --git a/panel/src/app/service/frontend_layout.ts b/panel/src/app/service/frontend_layout.ts index 68a87486..4f4f78e9 100644 --- a/panel/src/app/service/frontend_layout.ts +++ b/panel/src/app/service/frontend_layout.ts @@ -254,6 +254,28 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] { } ] }, + { + page: "/instances/schedule", + items: [ + { + id: getRandomId(), + meta: {}, + type: "Schedule", + title: t("计划任务"), + width: 12, + height: LayoutCardHeight.AUTO, + disableDelete: true + }, + { + id: getRandomId(), + meta: {}, + type: "EmptyCard", + title: "", + width: 12, + height: LayoutCardHeight.MINI + } + ] + }, { page: "/users", items: [ From 649d0147d054f3003b22e88907ba458f5c777cbb Mon Sep 17 00:00:00 2001 From: Lazy <2211717435@qq.com> Date: Sun, 12 Nov 2023 21:29:26 +0800 Subject: [PATCH 02/11] Fix: Capitalize --- frontend/src/config/index.ts | 2 +- frontend/src/widgets/instance/{schedule.vue => Schedule.vue} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename frontend/src/widgets/instance/{schedule.vue => Schedule.vue} (98%) diff --git a/frontend/src/config/index.ts b/frontend/src/config/index.ts index 56e47161..a2ea3c9f 100644 --- a/frontend/src/config/index.ts +++ b/frontend/src/config/index.ts @@ -32,7 +32,7 @@ import UserStatusBlock from "@/widgets/UserStatusBlock.vue"; import UserInstanceList from "@/widgets/UserInstanceList.vue"; import ImageManager from "@/widgets/imageManager/index.vue"; import NewImage from "@/widgets/imageManager/NewImage.vue"; -import Schedule from "@/widgets/instance/schedule.vue"; +import Schedule from "@/widgets/instance/Schedule.vue"; import { NEW_CARD_TYPE } from "../types/index"; import { ROLE } from "./router"; diff --git a/frontend/src/widgets/instance/schedule.vue b/frontend/src/widgets/instance/Schedule.vue similarity index 98% rename from frontend/src/widgets/instance/schedule.vue rename to frontend/src/widgets/instance/Schedule.vue index 5b88845d..282e051c 100644 --- a/frontend/src/widgets/instance/schedule.vue +++ b/frontend/src/widgets/instance/Schedule.vue @@ -51,8 +51,8 @@ const type = { 3: t("指定时间性任务") }; -const rendTime = (text: string, e: Schedule) => { - switch (e.type) { +const rendTime = (text: string, schedule: Schedule) => { + switch (schedule.type) { case 1: { const time = Number(text); let s = time; From f42ba4a819849617e4812cabeb75fe496a47c7b4 Mon Sep 17 00:00:00 2001 From: Lazy <2211717435@qq.com> Date: Sun, 12 Nov 2023 21:51:46 +0800 Subject: [PATCH 03/11] Feat: del schedule --- frontend/src/services/apis/instance.ts | 15 ++++++++++ frontend/src/widgets/instance/Schedule.vue | 35 ++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/frontend/src/services/apis/instance.ts b/frontend/src/services/apis/instance.ts index 92fb1236..089bbf21 100644 --- a/frontend/src/services/apis/instance.ts +++ b/frontend/src/services/apis/instance.ts @@ -357,3 +357,18 @@ export const scheduleList = useDefineApi< method: "GET", url: "/api/protected_schedule" }); + +// 删除计划任务 +export const scheduleDelete = useDefineApi< + { + params: { + remote_uuid: string; + uuid: string; + task_name: string; + }; + }, + boolean +>({ + method: "DELETE", + url: "/api/protected_schedule" +}); diff --git a/frontend/src/widgets/instance/Schedule.vue b/frontend/src/widgets/instance/Schedule.vue index 282e051c..effeb9d7 100644 --- a/frontend/src/widgets/instance/Schedule.vue +++ b/frontend/src/widgets/instance/Schedule.vue @@ -9,7 +9,7 @@ import BetweenMenus from "@/components/BetweenMenus.vue"; import { useLayoutCardTools } from "@/hooks/useCardTools"; import { useScreen } from "@/hooks/useScreen"; import { useAppRouters } from "@/hooks/useAppRouters"; -import { scheduleList } from "@/services/apis/instance"; +import { scheduleList, scheduleDelete } from "@/services/apis/instance"; import type { LayoutCard, Schedule } from "@/types/index"; const props = defineProps<{ @@ -37,6 +37,26 @@ const getScheduleList = async () => { } }; +const deleteSchedule = async (name: string) => { + const { execute, state } = scheduleDelete(); + try { + await execute({ + params: { + remote_uuid: daemonId ?? "", + uuid: instanceId ?? "", + task_name: name + } + }); + if (state.value) { + message.success(t("删除成功")); + refresh(); + } + } catch (err: any) { + console.error(err); + message.error(err.message); + } +}; + const action = { command: t("发送命令"), stop: t("停止实例"), @@ -191,10 +211,15 @@ onMounted(async () => { From d250c298bb27b7bbeb1ef187a1bd9b7512298263 Mon Sep 17 00:00:00 2001 From: Lazy <2211717435@qq.com> Date: Mon, 13 Nov 2023 14:01:48 +0800 Subject: [PATCH 04/11] Feat: create schedule --- frontend/components.d.ts | 1 + frontend/src/services/apis/instance.ts | 23 +- frontend/src/types/const.ts | 14 + frontend/src/types/index.ts | 8 + frontend/src/widgets/instance/Schedule.vue | 46 ++-- .../widgets/instance/dialogs/NewSchedule.vue | 252 ++++++++++++++++++ 6 files changed, 323 insertions(+), 21 deletions(-) create mode 100644 frontend/src/widgets/instance/dialogs/NewSchedule.vue diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 77c21ffc..66ed7237 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -51,6 +51,7 @@ declare module 'vue' { ATabs: typeof import('ant-design-vue/es')['Tabs'] ATag: typeof import('ant-design-vue/es')['Tag'] ATextarea: typeof import('ant-design-vue/es')['Textarea'] + ATimePicker: typeof import('ant-design-vue/es')['TimePicker'] ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATypography: typeof import('ant-design-vue/es')['Typography'] ATypographyParagraph: typeof import('ant-design-vue/es')['TypographyParagraph'] diff --git a/frontend/src/services/apis/instance.ts b/frontend/src/services/apis/instance.ts index 089bbf21..57734a9f 100644 --- a/frontend/src/services/apis/instance.ts +++ b/frontend/src/services/apis/instance.ts @@ -1,5 +1,11 @@ import { useDefineApi } from "@/stores/useDefineApi"; -import type { InstanceDetail, NewInstanceForm, QuickStartTemplate, Schedule } from "@/types"; +import type { + InstanceDetail, + NewInstanceForm, + QuickStartTemplate, + Schedule, + NewScheduleTask +} from "@/types"; import type { IGlobalInstanceConfig } from "../../../../common/global"; import type { InstanceMoreDetail } from "@/hooks/useInstance"; @@ -372,3 +378,18 @@ export const scheduleDelete = useDefineApi< method: "DELETE", url: "/api/protected_schedule" }); + +// 创建计划任务 +export const scheduleCreate = useDefineApi< + { + params: { + remote_uuid: string; + uuid: string; + }; + data: NewScheduleTask; + }, + boolean +>({ + url: "/api/protected_schedule", + method: "POST" +}); diff --git a/frontend/src/types/const.ts b/frontend/src/types/const.ts index 0c83ff5a..e7a770e1 100644 --- a/frontend/src/types/const.ts +++ b/frontend/src/types/const.ts @@ -80,3 +80,17 @@ ENV LC_ALL=zh_CN.UTF-8 ENV TZ=Asia/Shanghai WORKDIR /workspace `; + +export const ScheduleAction = { + command: t("发送命令"), + stop: t("停止实例"), + start: t("开启实例"), + restart: t("重启实例"), + kill: t("终止实例") +}; + +export const ScheduleType = { + 1: t("间隔时间性任务"), + 2: t("周期时间性任务"), + 3: t("指定时间性任务") +}; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 9526c755..460d0c66 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -228,3 +228,11 @@ export interface Schedule { payload: string; type: number; } + +export interface NewScheduleTask { + name: String; + count: String; + time: String; + action: String; + type: String; +} diff --git a/frontend/src/widgets/instance/Schedule.vue b/frontend/src/widgets/instance/Schedule.vue index effeb9d7..7f4211e7 100644 --- a/frontend/src/widgets/instance/Schedule.vue +++ b/frontend/src/widgets/instance/Schedule.vue @@ -11,6 +11,8 @@ import { useScreen } from "@/hooks/useScreen"; import { useAppRouters } from "@/hooks/useAppRouters"; import { scheduleList, scheduleDelete } from "@/services/apis/instance"; import type { LayoutCard, Schedule } from "@/types/index"; +import { ScheduleAction, ScheduleType } from "@/types/const"; +import NewSchedule from "@/widgets/instance/dialogs/NewSchedule.vue"; const props = defineProps<{ card: LayoutCard; @@ -21,6 +23,7 @@ const instanceId = getMetaOrRouteValue("instanceId"); const daemonId = getMetaOrRouteValue("daemonId"); const { toPage } = useAppRouters(); const screen = useScreen(); +const newScheduleDialog = ref>(); const { state, execute, isLoading } = scheduleList(); const getScheduleList = async () => { @@ -57,20 +60,6 @@ const deleteSchedule = async (name: string) => { } }; -const action = { - command: t("发送命令"), - stop: t("停止实例"), - start: t("开启实例"), - restart: t("重启实例"), - kill: t("终止实例") -}; - -const type = { - 1: t("间隔时间性任务"), - 2: t("周期时间性任务"), - 3: t("指定时间性任务") -}; - const rendTime = (text: string, schedule: Schedule) => { switch (schedule.type) { case 1: { @@ -105,7 +94,7 @@ const rendTime = (text: string, schedule: Schedule) => { const s = timeArr[0]; const dd = timeArr[3]; const mm = timeArr[4]; - return `${mm} ${t("每隔")} ${dd} ${t("每隔")} ${h}:${m}:${s}`; + return `${mm} ${t("月")} ${dd} ${t("日")} ${h}:${m}:${s}`; } default: return "Unknown Time"; @@ -142,7 +131,7 @@ const columns = [ key: "action", minWidth: "180px", customRender: (e: { text: "command" | "stop" | "start" | "restart" | "kill" }) => { - return action[e.text]; + return ScheduleAction[e.text]; } }, { @@ -152,7 +141,7 @@ const columns = [ key: "type", minWidth: "180px", customRender: (e: { text: 1 | 2 | 3 }) => { - return type[e.text]; + return ScheduleType[e.text]; } }, { @@ -173,7 +162,17 @@ const columns = [ const refresh = throttle(() => { getScheduleList(); -}, 600); +}, 100); + +const toConsole = () => { + toPage({ + path: "/instances/terminal", + query: { + daemonId, + instanceId + } + }); +}; onMounted(async () => { getScheduleList(); @@ -192,13 +191,13 @@ onMounted(async () => { @@ -229,6 +228,13 @@ onMounted(async () => { + +