feat:周期计划

This commit is contained in:
1708-huayu 2025-08-05 19:01:26 +08:00
parent 5083347a41
commit cf68c5e915
13 changed files with 740 additions and 17 deletions

View File

@ -28,6 +28,10 @@ export default function Layout({children}: { children: React.ReactNode }) {
/* 这里是你的组件 token */
},
},
token: {
controlItemBgActiveHover:"#4096ff",
controlItemBgActive:"#4096ff"
}
}}
>
<LocalContext.Provider value={{

View File

@ -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;

View File

@ -9,6 +9,7 @@ type PresetType = 'everyMinute' | 'everyHour' | 'daily' | 'weekly' | 'monthly';
interface CronGeneratorProps {
setCronFunction: (data: boolean) => void;
cron?: string;
canSetting:boolean;
}
function cronToChinese(cronExpression: string) {
@ -147,11 +148,11 @@ function cronToChinese(cronExpression: string) {
return description;
}
const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron}) => {
const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron,canSetting}) => {
const [showModal, setShowModal] = useState(false);
const [current, setCurrent] = useState<number>(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 [cronDayOfMonth, setCronDayOfMonth] = useState<string>(cron ? cron.split(' ')[3] : '*');
const [cronMonth, setCronMonth] = useState<string>(cron ? cron.split(' ')[4] : '*');
@ -267,8 +268,8 @@ const CronGenerator: React.FC<CronGeneratorProps> = ({setCronFunction, cron}) =>
return (
<Fragment>
<text>{canReadCron}</text>
<Button type="primary" onClick={() => setShowModal(!showModal)}>
<text style={{"paddingRight":"5px"}}>{canReadCron}</text>
<Button type="primary" onClick={() => setShowModal(!showModal)} disabled={!canSetting}>
</Button>
<Modal

View File

@ -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"
}
]

View File

@ -1,8 +1,13 @@
import {AxiosResponse} from "axios";
import {ResponseVO} from "@/lib/definitions";
import {httpReq} from "@/utils/axiosReq";
import {TaskScheduleRecordVO} from "@/components/type/TaskSchedule.d";
export const generateNextTimeAPI = (cron: string): Promise<AxiosResponse<ResponseVO<string[]>>> => {
return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL +
`/task/schedule/nextTime?cron=${cron}`)
}
export const clickRecordAPI = (data:TaskScheduleRecordVO)=>{
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL +
`/task/schedule/click`,data)
}

View File

@ -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[]
}

View File

@ -38,6 +38,7 @@ export type TaskMessage ={
fId?:string;
fName?:string;
taskType?:string;
onceConsume?:string;
stepList?:TaskStepSortVO[];
}

View File

@ -1,5 +1,5 @@
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 {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
import {QuestionCircleOutlined} from "@ant-design/icons";

View File

@ -1,6 +1,6 @@
'use client'
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 {DetailModelForm} from "@/ui/task/project/DetailModelForm";
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
];
const pName = useSearchParams().get("pName");
const typeList: CheckboxOptionType<string>[] = [
{ label: '计划', value: '0,1,2,3', },
{ label: '打卡', value: '4', },
{ label: '事件', value: '5', },
];
useEffect(() => {
if(pName&&pName!=document.title){
document.title = pName;
@ -63,6 +68,12 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
// setCurrentPath("/task/project")
}}></Button>
}
{
usePathname().startsWith("/task/calendar") &&
(
<Checkbox.Group options={typeList} defaultValue={['0,1,2,3','4']} />
)
}
{
/*日历需要状态*/
!usePathname().startsWith("/task/project") && <Fragment>

View File

@ -0,0 +1,3 @@
.localDiv{
margin-bottom: 24px;
}

View File

@ -6,7 +6,7 @@ import {
ProFormSelect,
ProFormText, ProFormTextArea, ProFormTreeSelect,
} 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 {
addTask, deleteTask, getTask,
@ -21,7 +21,10 @@ import DiaryOption from "@/components/DiaryOption";
import ShareOption from "@/components/ShareOption";
import StepSort from "@/components/StepSort";
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 = {
// 当前内容id
itemId?: string,
@ -56,6 +59,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
const [taskType, setTaskType] = useState('0')
const [spinning, setSpinning] = useState(true)
const [operationRequest, setOperationRequest] = useState(false)
const [onceConsumeChange, setOnceConsumeChange] = useState<string[]>(["1", "h"])
useEffect(() => {
if (props.itemId != undefined && (
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)
}
setRequestTask(task.data)
if (task.data.onceConsume) {
setOnceConsumeChange(task.data.onceConsume.split(","))
}
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
} else {
message.error(task.status.message);
@ -191,6 +198,10 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
if (taskType == '2') {
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;
},
} : {
@ -296,12 +307,16 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
<ProForm.Group>
<ProFormSelect
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"
name="taskType"
label="任务类型"
initialValue={taskType}
disabled={editFormDisable}
// 不建议类型随意改变
disabled={requestTask && requestTask.id !== undefined}
// disabled={requestTask && requestTask.id !== undefined && requestTask.taskType == '1'}
onChange={(value: string, option) => {
setTaskType(value)
}}
@ -378,7 +393,52 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
placeholder="请输入任务描述"
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>
<ProFormSelect
request={async () =>
@ -421,23 +481,66 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
initialValue={[dayjs(), undefined]}
name="expectedTimeRange"
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={['开始时间', '结束时间']}
disabled={editFormDisable}
/>
<ProFormDateTimeRangePicker
name="actualTimeRange"
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={['开始时间', '结束时间']}
disabled={editFormDisable}
/>
</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>
</Fragment>

View File

@ -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 ''
}

243
src/utils/timeFormatUtil.ts Normal file
View File

@ -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
}