feat:周期计划
This commit is contained in:
parent
5083347a41
commit
cf68c5e915
|
@ -28,6 +28,10 @@ export default function Layout({children}: { children: React.ReactNode }) {
|
||||||
/* 这里是你的组件 token */
|
/* 这里是你的组件 token */
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
token: {
|
||||||
|
controlItemBgActiveHover:"#4096ff",
|
||||||
|
controlItemBgActive:"#4096ff"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<LocalContext.Provider value={{
|
<LocalContext.Provider value={{
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import {Button, Form} from "antd";
|
||||||
|
import React, {useEffect} from "react";
|
||||||
|
import {
|
||||||
|
ModalForm,
|
||||||
|
ProFormDateTimeRangePicker,
|
||||||
|
ProFormText,
|
||||||
|
ProFormTextArea
|
||||||
|
} from "@ant-design/pro-components";
|
||||||
|
import {TaskScheduleRecordForm, TaskScheduleRecordVO} from "@/components/type/TaskSchedule.d";
|
||||||
|
import {clickRecordAPI} from "@/components/service/ScheduleTask";
|
||||||
|
import dayjs, {UnitTypeShort} from "dayjs";
|
||||||
|
import {onceConsumerRead} from "@/utils/codeToReadName";
|
||||||
|
import {betweenTime} from "@/utils/timeFormatUtil";
|
||||||
|
|
||||||
|
interface ClickRecordProps {
|
||||||
|
taskId: string;
|
||||||
|
taskName: string;
|
||||||
|
onceConsume: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClickRecord: React.FC<ClickRecordProps> = ({taskId, taskName, onceConsume}) => {
|
||||||
|
const [form] = Form.useForm<TaskScheduleRecordForm>();
|
||||||
|
useEffect(() => {
|
||||||
|
let data = {
|
||||||
|
'recordTimeRange': [onceConsume ? dayjs().subtract(Number(onceConsume.split(",")[0]), onceConsume.split(",")[1] as UnitTypeShort) : dayjs(), dayjs()],
|
||||||
|
'timeDifference': onceConsumerRead(onceConsume),
|
||||||
|
};
|
||||||
|
form.setFieldsValue(data)
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ModalForm<TaskScheduleRecordForm>
|
||||||
|
title={`${taskName}打卡`}
|
||||||
|
layout="horizontal"
|
||||||
|
trigger={
|
||||||
|
<Button type="primary">
|
||||||
|
打卡记录
|
||||||
|
</Button>}
|
||||||
|
form={form}
|
||||||
|
autoFocusFirstInput
|
||||||
|
modalProps={{
|
||||||
|
// destroyOnClose: true,
|
||||||
|
onCancel: () => console.log('run'),
|
||||||
|
}}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
values.taskId = taskId
|
||||||
|
if (values.recordTimeRange[0]) {
|
||||||
|
values.startDate = new Date(values.recordTimeRange[0])
|
||||||
|
}
|
||||||
|
if (values.recordTimeRange[1]) {
|
||||||
|
values.recordDate = new Date(values.recordTimeRange[1])
|
||||||
|
}
|
||||||
|
await clickRecordAPI(values);
|
||||||
|
return true
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProFormDateTimeRangePicker name="recordTimeRange" label="记录时间"
|
||||||
|
fieldProps={{
|
||||||
|
showTime: {
|
||||||
|
format: 'HH:mm',
|
||||||
|
},
|
||||||
|
format: "YYYY-MM-DD HH:mm",
|
||||||
|
allowEmpty: [true, false],
|
||||||
|
onChange: (dates) => {
|
||||||
|
console.log({dates})
|
||||||
|
if (dates && dates[0] && dates[1]) {
|
||||||
|
form.setFieldValue("timeDifference", betweenTime(dayjs(dates[1]), dayjs(dates[0])))
|
||||||
|
} else {
|
||||||
|
form.setFieldValue("timeDifference", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
placeholder={['开始时间', '结束时间']}
|
||||||
|
allowClear/>
|
||||||
|
|
||||||
|
<ProFormText
|
||||||
|
width="xs"
|
||||||
|
name="timeDifference"
|
||||||
|
label="耗时"
|
||||||
|
readonly={true}
|
||||||
|
/>
|
||||||
|
<ProFormTextArea name="remarks" label="备注"/>
|
||||||
|
</ModalForm>)
|
||||||
|
}
|
||||||
|
export default ClickRecord;
|
|
@ -9,6 +9,7 @@ type PresetType = 'everyMinute' | 'everyHour' | 'daily' | 'weekly' | 'monthly';
|
||||||
interface CronGeneratorProps {
|
interface CronGeneratorProps {
|
||||||
setCronFunction: (data: boolean) => void;
|
setCronFunction: (data: boolean) => void;
|
||||||
cron?: string;
|
cron?: string;
|
||||||
|
canSetting:boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cronToChinese(cronExpression: string) {
|
function cronToChinese(cronExpression: string) {
|
||||||
|
@ -147,11 +148,11 @@ function cronToChinese(cronExpression: string) {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron}) => {
|
const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron,canSetting}) => {
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [current, setCurrent] = useState<number>(0);
|
const [current, setCurrent] = useState<number>(0);
|
||||||
const [cronSeconds, setCronSeconds] = useState<string>(cron ? cron.split(' ')[0] : '*');
|
const [cronSeconds, setCronSeconds] = useState<string>(cron ? cron.split(' ')[0] : '*');
|
||||||
const [cronMinutes, setCronMinutes] = useState<string>(cron ? cron.split(' ')[1] : '*');
|
const [cronMinutes, setCronMinutes] = useState<string>(cron ? cron.split(' ')[1] : '0');
|
||||||
const [cronHours, setCronHours] = useState<string>(cron ? cron.split(' ')[2] : '*');
|
const [cronHours, setCronHours] = useState<string>(cron ? cron.split(' ')[2] : '*');
|
||||||
const [cronDayOfMonth, setCronDayOfMonth] = useState<string>(cron ? cron.split(' ')[3] : '*');
|
const [cronDayOfMonth, setCronDayOfMonth] = useState<string>(cron ? cron.split(' ')[3] : '*');
|
||||||
const [cronMonth, setCronMonth] = useState<string>(cron ? cron.split(' ')[4] : '*');
|
const [cronMonth, setCronMonth] = useState<string>(cron ? cron.split(' ')[4] : '*');
|
||||||
|
@ -267,8 +268,8 @@ const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron}) =>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<text>{canReadCron}</text>
|
<text style={{"paddingRight":"5px"}}>{canReadCron}</text>
|
||||||
<Button type="primary" onClick={() => setShowModal(!showModal)}>
|
<Button type="primary" onClick={() => setShowModal(!showModal)} disabled={!canSetting}>
|
||||||
设置时间
|
设置时间
|
||||||
</Button>
|
</Button>
|
||||||
<Modal
|
<Modal
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"label": "0",
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "1",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "2",
|
||||||
|
"value": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "3",
|
||||||
|
"value": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "4",
|
||||||
|
"value": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "5",
|
||||||
|
"value": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "6",
|
||||||
|
"value": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "7",
|
||||||
|
"value": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "8",
|
||||||
|
"value": "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "9",
|
||||||
|
"value": "9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "10",
|
||||||
|
"value": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "11",
|
||||||
|
"value": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "12",
|
||||||
|
"value": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "13",
|
||||||
|
"value": "13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "14",
|
||||||
|
"value": "14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "15",
|
||||||
|
"value": "15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "16",
|
||||||
|
"value": "16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "17",
|
||||||
|
"value": "17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "18",
|
||||||
|
"value": "18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "19",
|
||||||
|
"value": "19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "20",
|
||||||
|
"value": "20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "21",
|
||||||
|
"value": "21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "22",
|
||||||
|
"value": "22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "23",
|
||||||
|
"value": "23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "24",
|
||||||
|
"value": "24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "25",
|
||||||
|
"value": "25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "26",
|
||||||
|
"value": "26"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "27",
|
||||||
|
"value": "27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "28",
|
||||||
|
"value": "28"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "29",
|
||||||
|
"value": "29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "30",
|
||||||
|
"value": "30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "31",
|
||||||
|
"value": "31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "32",
|
||||||
|
"value": "32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "33",
|
||||||
|
"value": "33"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "34",
|
||||||
|
"value": "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "35",
|
||||||
|
"value": "35"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "36",
|
||||||
|
"value": "36"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "37",
|
||||||
|
"value": "37"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "38",
|
||||||
|
"value": "38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "39",
|
||||||
|
"value": "39"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "40",
|
||||||
|
"value": "40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "41",
|
||||||
|
"value": "41"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "42",
|
||||||
|
"value": "42"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "43",
|
||||||
|
"value": "43"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "44",
|
||||||
|
"value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "45",
|
||||||
|
"value": "45"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "46",
|
||||||
|
"value": "46"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "47",
|
||||||
|
"value": "47"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "48",
|
||||||
|
"value": "48"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "49",
|
||||||
|
"value": "49"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "50",
|
||||||
|
"value": "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "51",
|
||||||
|
"value": "51"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "52",
|
||||||
|
"value": "52"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "53",
|
||||||
|
"value": "53"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "54",
|
||||||
|
"value": "54"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "55",
|
||||||
|
"value": "55"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "56",
|
||||||
|
"value": "56"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "57",
|
||||||
|
"value": "57"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "58",
|
||||||
|
"value": "58"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "59",
|
||||||
|
"value": "59"
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,8 +1,13 @@
|
||||||
import {AxiosResponse} from "axios";
|
import {AxiosResponse} from "axios";
|
||||||
import {ResponseVO} from "@/lib/definitions";
|
import {ResponseVO} from "@/lib/definitions";
|
||||||
import {httpReq} from "@/utils/axiosReq";
|
import {httpReq} from "@/utils/axiosReq";
|
||||||
|
import {TaskScheduleRecordVO} from "@/components/type/TaskSchedule.d";
|
||||||
|
|
||||||
export const generateNextTimeAPI = (cron: string): Promise<AxiosResponse<ResponseVO<string[]>>> => {
|
export const generateNextTimeAPI = (cron: string): Promise<AxiosResponse<ResponseVO<string[]>>> => {
|
||||||
return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL +
|
return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL +
|
||||||
`/task/schedule/nextTime?cron=${cron}`)
|
`/task/schedule/nextTime?cron=${cron}`)
|
||||||
}
|
}
|
||||||
|
export const clickRecordAPI = (data:TaskScheduleRecordVO)=>{
|
||||||
|
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL +
|
||||||
|
`/task/schedule/click`,data)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface TaskScheduleRecordVO{
|
||||||
|
id:string,
|
||||||
|
timeDifference:string,
|
||||||
|
remarks:string,
|
||||||
|
startDate:Date,
|
||||||
|
recordDate:Date,
|
||||||
|
taskId:string,
|
||||||
|
}
|
||||||
|
export interface TaskScheduleRecordForm extends TaskScheduleRecordVO{
|
||||||
|
recordTimeRange:Date[]
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ export type TaskMessage ={
|
||||||
fId?:string;
|
fId?:string;
|
||||||
fName?:string;
|
fName?:string;
|
||||||
taskType?:string;
|
taskType?:string;
|
||||||
|
onceConsume?:string;
|
||||||
stepList?:TaskStepSortVO[];
|
stepList?:TaskStepSortVO[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, {Fragment, useState} from 'react';
|
import React, {Fragment, useState} from 'react';
|
||||||
import {Form, MenuProps, message, Popconfirm} from 'antd';
|
import {ConfigProvider, Form, MenuProps, message, Popconfirm} from 'antd';
|
||||||
import { Dropdown, theme } from 'antd';
|
import { Dropdown, theme } from 'antd';
|
||||||
import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
||||||
import {QuestionCircleOutlined} from "@ant-design/icons";
|
import {QuestionCircleOutlined} from "@ant-design/icons";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use client'
|
'use client'
|
||||||
import React, {Fragment, useContext, useEffect} from "react";
|
import React, {Fragment, useContext, useEffect} from "react";
|
||||||
import {Button, DatePicker, Select, Space} from "antd";
|
import {Button, Checkbox, CheckboxOptionType, DatePicker, Select, Space} from "antd";
|
||||||
import {usePathname, useRouter} from "next/navigation";
|
import {usePathname, useRouter} from "next/navigation";
|
||||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||||
import {OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data";
|
import {OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data";
|
||||||
|
@ -33,6 +33,11 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
||||||
];
|
];
|
||||||
const pName = useSearchParams().get("pName");
|
const pName = useSearchParams().get("pName");
|
||||||
|
const typeList: CheckboxOptionType<string>[] = [
|
||||||
|
{ label: '计划', value: '0,1,2,3', },
|
||||||
|
{ label: '打卡', value: '4', },
|
||||||
|
{ label: '事件', value: '5', },
|
||||||
|
];
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(pName&&pName!=document.title){
|
if(pName&&pName!=document.title){
|
||||||
document.title = pName;
|
document.title = pName;
|
||||||
|
@ -63,6 +68,12 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
// setCurrentPath("/task/project")
|
// setCurrentPath("/task/project")
|
||||||
}}>日历显示</Button>
|
}}>日历显示</Button>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
usePathname().startsWith("/task/calendar") &&
|
||||||
|
(
|
||||||
|
<Checkbox.Group options={typeList} defaultValue={['0,1,2,3','4']} />
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
/*日历需要状态*/
|
/*日历需要状态*/
|
||||||
!usePathname().startsWith("/task/project") && <Fragment>
|
!usePathname().startsWith("/task/project") && <Fragment>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
.localDiv{
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import {
|
||||||
ProFormSelect,
|
ProFormSelect,
|
||||||
ProFormText, ProFormTextArea, ProFormTreeSelect,
|
ProFormText, ProFormTextArea, ProFormTreeSelect,
|
||||||
} from '@ant-design/pro-components';
|
} from '@ant-design/pro-components';
|
||||||
import {Button, Form, message, Popconfirm, Spin} from 'antd';
|
import {Button, Form, message, Popconfirm, Select, Space, Spin} from 'antd';
|
||||||
import React, {Fragment, useEffect, useState} from "react";
|
import React, {Fragment, useEffect, useState} from "react";
|
||||||
import {
|
import {
|
||||||
addTask, deleteTask, getTask,
|
addTask, deleteTask, getTask,
|
||||||
|
@ -21,7 +21,10 @@ import DiaryOption from "@/components/DiaryOption";
|
||||||
import ShareOption from "@/components/ShareOption";
|
import ShareOption from "@/components/ShareOption";
|
||||||
import StepSort from "@/components/StepSort";
|
import StepSort from "@/components/StepSort";
|
||||||
import SettingCron from "@/components/SettingCron";
|
import SettingCron from "@/components/SettingCron";
|
||||||
|
import ClickRecord from "@/components/ClickRecord";
|
||||||
|
import onceConsumeList from "@/components/constant/onceConsumeList.json"
|
||||||
|
import {onceConsumerRead} from "@/utils/codeToReadName";
|
||||||
|
import style from "@/ui/task/project/DetailModelForm.module.css"
|
||||||
export type DetailModelFormProps = {
|
export type DetailModelFormProps = {
|
||||||
// 当前内容id
|
// 当前内容id
|
||||||
itemId?: string,
|
itemId?: string,
|
||||||
|
@ -56,6 +59,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
const [taskType, setTaskType] = useState('0')
|
const [taskType, setTaskType] = useState('0')
|
||||||
const [spinning, setSpinning] = useState(true)
|
const [spinning, setSpinning] = useState(true)
|
||||||
const [operationRequest, setOperationRequest] = useState(false)
|
const [operationRequest, setOperationRequest] = useState(false)
|
||||||
|
const [onceConsumeChange, setOnceConsumeChange] = useState<string[]>(["1", "h"])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.itemId != undefined && (
|
if (props.itemId != undefined && (
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||||
|
@ -77,6 +81,9 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
setTaskType(task.data.taskType)
|
setTaskType(task.data.taskType)
|
||||||
}
|
}
|
||||||
setRequestTask(task.data)
|
setRequestTask(task.data)
|
||||||
|
if (task.data.onceConsume) {
|
||||||
|
setOnceConsumeChange(task.data.onceConsume.split(","))
|
||||||
|
}
|
||||||
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
||||||
} else {
|
} else {
|
||||||
message.error(task.status.message);
|
message.error(task.status.message);
|
||||||
|
@ -191,6 +198,10 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
if (taskType == '2') {
|
if (taskType == '2') {
|
||||||
result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList || []}/>)
|
result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList || []}/>)
|
||||||
}
|
}
|
||||||
|
if (taskType == '3') {
|
||||||
|
result.push(<ClickRecord taskId={props.itemId!} taskName={requestTask!.name}
|
||||||
|
onceConsume={requestTask!.onceConsume}/>)
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
} : {
|
} : {
|
||||||
|
@ -296,12 +307,16 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
<ProFormSelect
|
<ProFormSelect
|
||||||
required={true}
|
required={true}
|
||||||
options={TASK_TYPE}
|
options={TASK_TYPE.map(task =>
|
||||||
|
(task.value == '1' && (requestTask?.id)) ? {...task, disabled: true} : task)}
|
||||||
|
// (task.value == '1' ) ? {...task, disabled: true} : task)}
|
||||||
width="sm"
|
width="sm"
|
||||||
name="taskType"
|
name="taskType"
|
||||||
label="任务类型"
|
label="任务类型"
|
||||||
initialValue={taskType}
|
initialValue={taskType}
|
||||||
disabled={editFormDisable}
|
// 不建议类型随意改变
|
||||||
|
disabled={requestTask && requestTask.id !== undefined}
|
||||||
|
// disabled={requestTask && requestTask.id !== undefined && requestTask.taskType == '1'}
|
||||||
onChange={(value: string, option) => {
|
onChange={(value: string, option) => {
|
||||||
setTaskType(value)
|
setTaskType(value)
|
||||||
}}
|
}}
|
||||||
|
@ -378,7 +393,52 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
placeholder="请输入任务描述"
|
placeholder="请输入任务描述"
|
||||||
disabled={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
|
<div className={style.localDiv}>
|
||||||
|
<Space wrap>
|
||||||
|
<text>提醒:</text>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
// defaultValue={onceConsumeChange[0]}
|
||||||
|
onChange={(value) => {
|
||||||
|
}}
|
||||||
|
options={[{label: "期望开始",
|
||||||
|
value: "expect_start",},{label: "期望结束",
|
||||||
|
value: "expect_end",}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
// defaultValue={onceConsumeChange[0]}
|
||||||
|
onChange={(value) => {
|
||||||
|
}}
|
||||||
|
options={[{label: "前",
|
||||||
|
value: "before",},{label: "后",
|
||||||
|
value: "after",}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
onChange={(value) => {
|
||||||
|
}}
|
||||||
|
options={onceConsumeList}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
// defaultValue={onceConsumeChange[1]}
|
||||||
|
onChange={(value) => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {
|
||||||
|
label: "天",
|
||||||
|
value: "d"
|
||||||
|
}]}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
<ProFormSelect
|
<ProFormSelect
|
||||||
request={async () =>
|
request={async () =>
|
||||||
|
@ -421,23 +481,66 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
initialValue={[dayjs(), undefined]}
|
initialValue={[dayjs(), undefined]}
|
||||||
name="expectedTimeRange"
|
name="expectedTimeRange"
|
||||||
label="期望时间"
|
label="期望时间"
|
||||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
fieldProps={{
|
||||||
|
showTime: {
|
||||||
|
format: 'HH:mm',
|
||||||
|
},
|
||||||
|
format: "YYYY-MM-DD HH:mm", allowEmpty: [true, true], needConfirm: true
|
||||||
|
}}
|
||||||
placeholder={['开始时间', '结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
disabled={editFormDisable}
|
disabled={editFormDisable}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<ProFormDateTimeRangePicker
|
<ProFormDateTimeRangePicker
|
||||||
name="actualTimeRange"
|
name="actualTimeRange"
|
||||||
label="实际时间"
|
label="实际时间"
|
||||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
fieldProps={{
|
||||||
|
showTime: {
|
||||||
|
format: 'HH:mm',
|
||||||
|
},
|
||||||
|
format: "YYYY-MM-DD HH:mm", allowEmpty: [true, true], needConfirm: true
|
||||||
|
}}
|
||||||
placeholder={['开始时间', '结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
disabled={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
</ProForm.Group>
|
</ProForm.Group>
|
||||||
{taskType == "3" && <SettingCron setCronFunction={
|
{taskType == "3" &&
|
||||||
() => {
|
<Fragment>
|
||||||
}
|
{editFormDisable ?
|
||||||
}/>}
|
<div className={style.localDiv} >
|
||||||
|
<text>单次耗时:{onceConsumerRead(requestTask?.onceConsume)}</text>
|
||||||
|
</div> :
|
||||||
|
<div className={style.localDiv}>
|
||||||
|
<Space wrap>
|
||||||
|
<text>单次耗时:</text>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
defaultValue={onceConsumeChange[0]}
|
||||||
|
onChange={(value) => {
|
||||||
|
onceConsumeChange[0] = value
|
||||||
|
setOnceConsumeChange(onceConsumeChange)
|
||||||
|
}}
|
||||||
|
options={onceConsumeList}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
style={{width: 120}}
|
||||||
|
allowClear
|
||||||
|
defaultValue={onceConsumeChange[1]}
|
||||||
|
onChange={(value) => {
|
||||||
|
onceConsumeChange[1] = value
|
||||||
|
setOnceConsumeChange(onceConsumeChange)
|
||||||
|
}}
|
||||||
|
options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {
|
||||||
|
label: "天",
|
||||||
|
value: "d"
|
||||||
|
}]}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
<SettingCron canSetting={!editFormDisable} setCronFunction={() => {
|
||||||
|
}}/></Fragment>}
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
export function onceConsumerRead(onceConsume:string|undefined){
|
||||||
|
if (onceConsume){
|
||||||
|
let result = onceConsume.split(",")
|
||||||
|
if (result[1]=='m'){
|
||||||
|
return result[0]+'分钟'
|
||||||
|
}else if (result[1]=='h'){
|
||||||
|
return result[0]+'小时'
|
||||||
|
}else if (result[1]=='d'){
|
||||||
|
return result[0]+'天'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
import dayjs, { Dayjs, isDayjs } from "dayjs";
|
||||||
|
import utc from "dayjs/plugin/utc";
|
||||||
|
dayjs.extend(utc)
|
||||||
|
const DATE_FORMAT = "YYYY-MM-DD"
|
||||||
|
// 到秒没啥意义
|
||||||
|
const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm"
|
||||||
|
|
||||||
|
const DATE_TIME_FORMAT_SIMPLE = "MM-DD HH:mm"
|
||||||
|
|
||||||
|
function dayStartUtcFormat(dayjsString: Dayjs | string | Date) {
|
||||||
|
|
||||||
|
if (!dayjsString) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let dayJsObj;
|
||||||
|
if (isDayjs(dayjsString)) {
|
||||||
|
dayJsObj = dayjsString;
|
||||||
|
} else {
|
||||||
|
dayJsObj = dayjs(dayjsString);
|
||||||
|
}
|
||||||
|
return dayJsObj.set('h', 0).set('m', 0).set('s', 0).set('ms', 0).utc().format()
|
||||||
|
}
|
||||||
|
|
||||||
|
function dateStartUtcFormat(dateObject: Dayjs | string | Date) {
|
||||||
|
if (!dateObject) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let dayJsObj;
|
||||||
|
if (isDayjs(dateObject)) {
|
||||||
|
dayJsObj = dateObject;
|
||||||
|
} else {
|
||||||
|
dayJsObj = dayjs(dateObject);
|
||||||
|
}
|
||||||
|
return dayJsObj.set('h', 0).set('m', 0).set('s', 0).set('ms', 0).utc().format()
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDateStartUtcFormat(dateObject: Dayjs | string | Date) {
|
||||||
|
if (!dateObject) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let dayJsObj;
|
||||||
|
if (isDayjs(dateObject)) {
|
||||||
|
dayJsObj = dateObject;
|
||||||
|
} else {
|
||||||
|
dayJsObj = dayjs(dateObject);
|
||||||
|
}
|
||||||
|
return dayJsObj.add(1, "d").set('h', 0).set('m', 0).set('s', 0).set('ms', 0).utc().format()
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDayStartUtcFormat(dayjsString: Dayjs | string | Date): string | undefined {
|
||||||
|
if (!dayjsString) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let dayJsObj;
|
||||||
|
if (isDayjs(dayjsString)) {
|
||||||
|
dayJsObj = dayjsString;
|
||||||
|
} else {
|
||||||
|
dayJsObj = dayjs(dayjsString);
|
||||||
|
}
|
||||||
|
return dayJsObj.add(1, "d").set('h', 0).set('m', 0).set('s', 0).set('ms', 0).utc().format()
|
||||||
|
}
|
||||||
|
function cronToChinese(cronExpression: string) {
|
||||||
|
// 解析Cron表达式各部分
|
||||||
|
const parts = cronExpression.split(' ');
|
||||||
|
if (parts.length < 5) {
|
||||||
|
return '非法的Cron表达式';
|
||||||
|
}
|
||||||
|
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
||||||
|
|
||||||
|
// 解析分钟
|
||||||
|
function parseMinute(m: string) {
|
||||||
|
if (m === '*') return '每分钟';
|
||||||
|
if (m === '0') return '';
|
||||||
|
if (m.includes('/')) {
|
||||||
|
const interval = m.split('/')[1];
|
||||||
|
return `每${interval}分钟`;
|
||||||
|
}
|
||||||
|
if (m.includes(',')) {
|
||||||
|
const minutes = m.split(',').map(m => parseInt(m));
|
||||||
|
return `在${minutes.join('、')}分`;
|
||||||
|
}
|
||||||
|
return `在${parseInt(m)}分`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析小时
|
||||||
|
function parseHour(h: string) {
|
||||||
|
if (h === '*') return '每小时';
|
||||||
|
if (h.includes('/')) {
|
||||||
|
const interval = h.split('/')[1];
|
||||||
|
return `每${interval}小时`;
|
||||||
|
}
|
||||||
|
if (h.includes(',')) {
|
||||||
|
const hours = h.split(',').map(h => parseInt(h));
|
||||||
|
return `在${hours.join('、')}点`;
|
||||||
|
}
|
||||||
|
return `在${parseInt(h)}点`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析日期
|
||||||
|
function parseDayOfMonth(d: string) {
|
||||||
|
if (d === '*') return '';
|
||||||
|
if (d === 'L') return '每月最后一天';
|
||||||
|
if (d.includes('W')) {
|
||||||
|
const day = d.replace('W', '');
|
||||||
|
return `在每月${day}日最近的工作日`;
|
||||||
|
}
|
||||||
|
if (d.includes('/')) {
|
||||||
|
const interval = d.split('/')[1];
|
||||||
|
return `每${interval}天`;
|
||||||
|
}
|
||||||
|
if (d.includes(',')) {
|
||||||
|
const days = d.split(',').map(d => parseInt(d));
|
||||||
|
return `在每月${days.join('、')}日`;
|
||||||
|
}
|
||||||
|
return `在每月${parseInt(d)}日`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析月份
|
||||||
|
function parseMonth(m: string) {
|
||||||
|
if (m === '*') return '';
|
||||||
|
const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月',
|
||||||
|
'七月', '八月', '九月', '十月', '十一月', '十二月'];
|
||||||
|
if (m.includes('/')) {
|
||||||
|
const interval = m.split('/')[1];
|
||||||
|
return `每${interval}个月`;
|
||||||
|
}
|
||||||
|
if (m.includes(',')) {
|
||||||
|
const months = m.split(',').map(m => monthNames[parseInt(m) - 1]);
|
||||||
|
return `在${months.join('、')}`;
|
||||||
|
}
|
||||||
|
return `在${monthNames[parseInt(m) - 1]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析星期
|
||||||
|
function parseDayOfWeek(d: string) {
|
||||||
|
if (d === '*' || d === '?') return '';
|
||||||
|
const dayNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||||
|
if (d.includes('L')) {
|
||||||
|
const dayIndex = parseInt(d.replace('L', ''));
|
||||||
|
return `每月最后一个${dayNames[dayIndex]}`;
|
||||||
|
}
|
||||||
|
if (d.includes('#')) {
|
||||||
|
const [dayIndex, weekNum] = d.split('#').map(Number);
|
||||||
|
return `每月第${weekNum}个${dayNames[dayIndex]}`;
|
||||||
|
}
|
||||||
|
if (d.includes('/')) {
|
||||||
|
const interval = d.split('/')[1];
|
||||||
|
return `每${interval}天(周)`;
|
||||||
|
}
|
||||||
|
if (d.includes(',')) {
|
||||||
|
const days = d.split(',').map(d => dayNames[parseInt(d)]);
|
||||||
|
return `在每周${days.join('、')}`;
|
||||||
|
}
|
||||||
|
return `在每周${dayNames[parseInt(d)]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建描述
|
||||||
|
const minuteDesc = parseMinute(minute);
|
||||||
|
const hourDesc = parseHour(hour);
|
||||||
|
const dayOfMonthDesc = parseDayOfMonth(dayOfMonth);
|
||||||
|
const monthDesc = parseMonth(month);
|
||||||
|
const dayOfWeekDesc = parseDayOfWeek(dayOfWeek);
|
||||||
|
|
||||||
|
// 处理整点时间
|
||||||
|
if (minute === '0' && hour !== '*') {
|
||||||
|
// 每天固定时间
|
||||||
|
if (dayOfMonth === '*' && month === '*' && (dayOfWeek === '*' || dayOfWeek === '?')) {
|
||||||
|
return `每天${hourDesc}`;
|
||||||
|
}
|
||||||
|
return `${hourDesc} ${dayOfMonthDesc} ${monthDesc} ${dayOfWeekDesc}`.replace(/\s+/g, ' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组合描述
|
||||||
|
let description = `${minuteDesc} ${hourDesc} ${dayOfMonthDesc} ${monthDesc} ${dayOfWeekDesc}`;
|
||||||
|
|
||||||
|
// 清理多余空格和空部分
|
||||||
|
description = description.replace(/\s+/g, ' ').trim();
|
||||||
|
description = description.replace(/\s\s+/g, ' ');
|
||||||
|
|
||||||
|
// 处理一些常见模式
|
||||||
|
if (description === '每分钟 每小时') return '每分钟';
|
||||||
|
if (description.startsWith('每分钟 在')) return description.replace('每分钟', '每分钟的');
|
||||||
|
|
||||||
|
// 处理空描述
|
||||||
|
if (!description) return '非法的Cron表达式';
|
||||||
|
|
||||||
|
// 优化描述
|
||||||
|
description = description
|
||||||
|
.replace(/在每月(\d+)日 在每周/g, '在每月$1日且')
|
||||||
|
.replace(/在每月(\d+)日 在/g, '在每月$1日')
|
||||||
|
.replace(/在每月/g, '每月')
|
||||||
|
.replace(/在每周/g, '每周')
|
||||||
|
.replace(/在/g, '');
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
function betweenTime(start: Dayjs, end: Dayjs) {
|
||||||
|
let minutes = Math.ceil(start.second(0).millisecond(0).diff(end.second(0).millisecond(0), "minute", true));
|
||||||
|
minutes = Math.abs(minutes)
|
||||||
|
if (minutes > 0) {
|
||||||
|
// 计算天数、小时数和剩余的分钟数
|
||||||
|
const days = Math.floor(minutes / (24 * 60));
|
||||||
|
const remainingHours = Math.floor((minutes % (24 * 60)) / 60);
|
||||||
|
const remainingMinutes = minutes % 60;
|
||||||
|
// 构建结果数组
|
||||||
|
const parts = [];
|
||||||
|
if (days > 0) {
|
||||||
|
parts.push(`${days}天`);
|
||||||
|
}
|
||||||
|
if (remainingHours > 0) {
|
||||||
|
parts.push(`${remainingHours}小时`);
|
||||||
|
}
|
||||||
|
if (remainingMinutes > 0 || parts.length === 0) {
|
||||||
|
parts.push(`${remainingMinutes}分钟`);
|
||||||
|
}
|
||||||
|
return parts.join(' ')
|
||||||
|
}
|
||||||
|
return "0分钟";
|
||||||
|
}
|
||||||
|
function dayjsWeek(day: Dayjs): string {
|
||||||
|
let week = day.day()
|
||||||
|
if (week == 0) {
|
||||||
|
return '周日'
|
||||||
|
} else if (week == 1) {
|
||||||
|
return '周一'
|
||||||
|
} else if (week == 2) {
|
||||||
|
return '周二'
|
||||||
|
} else if (week == 3) {
|
||||||
|
return '周三'
|
||||||
|
} else if (week == 4) {
|
||||||
|
return '周四'
|
||||||
|
} else if (week == 5) {
|
||||||
|
return '周五'
|
||||||
|
} else if (week == 6) {
|
||||||
|
return '周六'
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
DATE_TIME_FORMAT, DATE_FORMAT, DATE_TIME_FORMAT_SIMPLE,
|
||||||
|
dayStartUtcFormat, nextDayStartUtcFormat, betweenTime,
|
||||||
|
dateStartUtcFormat, nextDateStartUtcFormat, cronToChinese, dayjsWeek
|
||||||
|
}
|
Loading…
Reference in New Issue