diff --git a/.env.production b/.env.production index 12eb674..62b07b9 100644 --- a/.env.production +++ b/.env.production @@ -1,2 +1,2 @@ -NEXT_PUBLIC_TODO_REQUEST_URL=https://www.huaruyu.com/todo-server -NEXT_PUBLIC_SECURITY_REQUEST_URL=https://www.huaruyu.com/security-server \ No newline at end of file +NEXT_PUBLIC_TODO_REQUEST_URL=/todoWeb +NEXT_PUBLIC_SECURITY_REQUEST_URL=/securityWeb \ No newline at end of file diff --git a/docker/deploy.md b/docker/deploy.md index a30329e..b57c808 100644 --- a/docker/deploy.md +++ b/docker/deploy.md @@ -1,14 +1,15 @@ ```shell -scp -r out/ shixiaohua@10.104.11.99:/home/shixiaohua/docker/todo-web -scp -r cert/ shixiaohua@10.104.11.99:/home/shixiaohua/docker/todo-web -scp nginx.conf shixiaohua@10.104.11.99:/home/shixiaohua/docker/todo-web -scp Dockerfile shixiaohua@10.104.11.99:/home/shixiaohua/docker/todo-web +scp -r out/ shixiaohua@10.104.11.101:/home/shixiaohua/docker/todo-web +scp -r cert/ shixiaohua@10.104.11.101:/home/shixiaohua/docker/todo-web +scp nginx.conf shixiaohua@10.104.11.101:/home/shixiaohua/docker/todo-web +scp Dockerfile shixiaohua@10.104.11.101:/home/shixiaohua/docker/todo-web ssh shixiaohua@10.104.11.99 ``` docker操作 ```shell +scp nginx.conf shixiaohua@10.104.11.101:/home/shixiaohua/docker/todo-web docker stop task-manager-nginx docker rm task-manager-nginx docker rmi task-manager-nginx diff --git a/docker/nginx-yun.conf b/docker/nginx-yun.conf index 441dfd1..2d3f5ef 100644 --- a/docker/nginx-yun.conf +++ b/docker/nginx-yun.conf @@ -13,6 +13,11 @@ events { http { include /etc/nginx/mime.types; default_type application/octet-stream; + + limit_req_zone $binary_remote_addr zone=general_limit:10m rate=20r/s; + limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s; + log_format blocked '$time_local|$remote_addr|$request|$status|$http_referer'; + # HTTPS 服务器监听端口 # 443 # HTTP 服务器监听端口 @@ -90,6 +95,19 @@ http { client_body_buffer_size 16k; client_max_body_size 100M; } + location ^~ /todoWeb/ { + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + # rewrite ^/todo-server/(.*)$ /$1 break; + proxy_pass http://localhost:8092/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_body_buffer_size 16k; + client_max_body_size 100M; + } location ^~ /security-server/ { # 预检请求的处理 if ($request_method = 'OPTIONS') { @@ -103,6 +121,20 @@ http { client_body_buffer_size 16k; client_max_body_size 100M; + } + location ^~ /securityWeb/ { + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + # rewrite ^/security-server/(.*)$ /$1 break; + proxy_pass http://localhost:8091/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_body_buffer_size 16k; + client_max_body_size 100M; + } location /task/ { # 预检请求的处理 diff --git a/docker/nginx.conf b/docker/nginx.conf index f35d3ed..24a6457 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -13,6 +13,11 @@ events { http { include /etc/nginx/mime.types; default_type application/octet-stream; + + limit_req_zone $binary_remote_addr zone=general_limit:10m rate=20r/s; + limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s; + log_format blocked '$time_local|$remote_addr|$request|$status|$http_referer'; + # HTTPS 服务器监听端口 # 443 # HTTP 服务器监听端口 @@ -90,6 +95,19 @@ http { client_body_buffer_size 16k; client_max_body_size 100M; } + location ^~ /todoWeb/ { + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + # rewrite ^/todo-server/(.*)$ /$1 break; + proxy_pass http://huayu-platform-todo:8092/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_body_buffer_size 16k; + client_max_body_size 100M; + } location ^~ /security-server/ { # 预检请求的处理 if ($request_method = 'OPTIONS') { @@ -103,6 +121,20 @@ http { client_body_buffer_size 16k; client_max_body_size 100M; + } + location ^~ /securityWeb/ { + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + # rewrite ^/security-server/(.*)$ /$1 break; + proxy_pass http://huayu-platform-security:8091/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_body_buffer_size 16k; + client_max_body_size 100M; + } location /task/ { # 预检请求的处理 diff --git a/next.config.mjs b/next.config.mjs index 581ff2a..07a3c94 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -12,6 +12,11 @@ const nextConfig = { distDir: 'docker/out', // 严格模式下react-beautiful-dnd无法使用 reactStrictMode:false, + eslint: { + // Warning: This allows production builds to successfully complete even if + // your project has ESLint errors. + ignoreDuringBuilds: true, + }, }; export default nextConfig; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 17d437a..ac09184 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,10 +1,5 @@ -import type {Metadata} from "next"; import "@/ui/globals.css"; -export const metadata: Metadata = { - title: "马上行计划管理", - description: "马上行计划管理", -}; /** * Root Layout (Required) * @param children @@ -20,7 +15,7 @@ export default function RootLayout({ 马上行计划管理 - + {/*FOUC,Flash of Unstyled Content*/} {/**/} {/**/} diff --git a/src/app/page.tsx b/src/app/page.tsx index a246fa1..bc54a2f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,9 +5,9 @@ import {useEffect} from "react"; export default function Home() { const {replace} = useRouter(); + const pathName = usePathname() + const searchParams = useSearchParams() useEffect(()=>{ - const pathName = usePathname() - const searchParams = useSearchParams() console.log({pathName},{searchParams}) if(localStorage.getItem('platform-security')){ if (!pathName){ @@ -21,7 +21,7 @@ export default function Home() { }else { replace("/login") } - },[]) + },) dayjs.locale('zh-cn') return (
diff --git a/src/app/task/four/layout.tsx b/src/app/task/four/layout.tsx index 526f678..655064f 100644 --- a/src/app/task/four/layout.tsx +++ b/src/app/task/four/layout.tsx @@ -66,7 +66,7 @@ export default function Layout({children}: { children: React.ReactNode }) { // @ts-ignore document.getElementById('tenLeft').style.fontSize = divHeight/6*4 + 'px'; refreshDate() - }, [useContext(LocalContext)]); + }, [data]); return (
diff --git a/src/components/CalHeader.tsx b/src/components/CalHeader.tsx new file mode 100644 index 0000000..d91c7b6 --- /dev/null +++ b/src/components/CalHeader.tsx @@ -0,0 +1,20 @@ +import React, {Fragment} from 'react'; +import {DateHeaderProps} from "react-big-calendar"; +import {solarToLunar} from "lunar-calendar"; +import {lunarDateShow} from "@/utils/timeFormatUtil"; + +// 定义为 React 函数组件 +const CalHeader: React.FC = ({date, label, drilldownView, onDrillDown}) => { + if (!drilldownView) { + return {label} + } + return ( +
+
{label}
+
{lunarDateShow(date)}
+
+ ) +}; + +export default CalHeader; \ No newline at end of file diff --git a/src/components/DiaryOption.tsx b/src/components/DiaryOption.tsx index edca23f..9fb2764 100644 --- a/src/components/DiaryOption.tsx +++ b/src/components/DiaryOption.tsx @@ -159,7 +159,7 @@ const DiaryOption = (props: SelectDiary) => { }) }) setDiaryReduceList(returnResult.reverse()); - }, [diaryList, currentIndex]); + }, [diaryList, currentIndex,props.taskId]); const listRef = useRef(null); const onScroll = (e: React.UIEvent) => { diff --git a/src/components/SettingCron.tsx b/src/components/SettingCron.tsx index ea950da..bfadc10 100644 --- a/src/components/SettingCron.tsx +++ b/src/components/SettingCron.tsx @@ -183,7 +183,7 @@ const CronGenerator: React.FC = ({setCronFunction,setExpecte console.log({fullCronExpression}) setCanReadCron(cronToChinese(fullCronExpression)) } - }, [fullCronExpression]); + }, [fullCronExpression,cron]); const onClickConfirmCron = () => { if (fullCronExpression) { diff --git a/src/components/TaskRemindComponent.tsx b/src/components/TaskRemindComponent.tsx index 72e72e8..298fd5c 100644 --- a/src/components/TaskRemindComponent.tsx +++ b/src/components/TaskRemindComponent.tsx @@ -206,7 +206,7 @@ const TaskRemindComponent = (props: ITaskRemind) => { ) : ( props.remindTypeList.map((remindType, index) => ( //
{remindType.split(",").join(", ")}
- + void, reloadData? return () => { isMounted = false; }; - }, [open]) + }, [open,props.taskId]) const removeTeam = (teamMember: TeamMemberVO) => { removeTeamAPI(teamMember).then(res => { if (res.data.status.success) { diff --git a/src/lib/type/lunar.d.ts b/src/lib/type/lunar.d.ts index e99b647..6145964 100644 --- a/src/lib/type/lunar.d.ts +++ b/src/lib/type/lunar.d.ts @@ -11,6 +11,12 @@ declare module 'lunar-calendar' { lunarDayName: string; solarTerm: string; // 其他农历字段... + // 二十四节气 + term:string; + // 农历节日 + lunarFestival:string; + // 公历节日 + solarFestival:string; } export function solarToLunar( diff --git a/src/ui/task/TitleOperation.tsx b/src/ui/task/TitleOperation.tsx index 69e620e..58c60e1 100644 --- a/src/ui/task/TitleOperation.tsx +++ b/src/ui/task/TitleOperation.tsx @@ -1,15 +1,16 @@ 'use client' import React, {Fragment, useContext, useEffect, useState} from "react"; -import {Button, Checkbox, CheckboxOptionType, DatePicker, MenuProps, message, Select, Space} from "antd"; +import {Button, Checkbox, CheckboxOptionType, DatePicker, MenuProps, message, Popconfirm, 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"; +import {deleteTask, OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data"; import style from '@/ui/task/TitleOperation.module.css' import LocalContext from "@/ui/LocalContent"; import {RequestDateType} from "@/ui/task/RequestDateType"; import dayjs, {Dayjs} from "dayjs"; import {useSearchParams} from "next/dist/client/components/navigation"; import Dropdown from "antd/es/dropdown/dropdown"; +import {QuestionCircleOutlined} from "@ant-design/icons"; interface TitleOperationProps { setTaskState: (value: string) => void; @@ -42,7 +43,7 @@ export const TitleOperation: React.FC = ({ expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined, expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined ]; - const [nickName,setNickName]=useState("微信用户") + const [nickName, setNickName] = useState("微信用户") const typeList: CheckboxOptionType[] = [ {label: '计划', value: '0,1,2,3'}, {label: '打卡', value: '4'}, @@ -61,7 +62,7 @@ export const TitleOperation: React.FC = ({ useEffect(() => { let userMessage = localStorage.getItem('user-message'); - if (userMessage){ + if (userMessage) { let parse = JSON.parse(userMessage); setNickName(parse.nickname) } @@ -69,8 +70,8 @@ export const TitleOperation: React.FC = ({ const onClick: MenuProps['onClick'] = ({key}) => { if (key == "1") { - localStorage.removeItem('platform-security') - replace(`/login`) + // localStorage.removeItem('platform-security') + // replace(`/login`) } else if (key == "2") { replace(pathName) setPathParam(undefined) @@ -80,13 +81,33 @@ export const TitleOperation: React.FC = ({ const items: MenuProps['items'] = [ { - label: '退出登录', + label: } + okText="确认" + cancelText="取消" + onConfirm={() => { + localStorage.removeItem('platform-security') + replace(`/login`) + }} + >退出登录, key: '1', }, ]; const itemsPid: MenuProps['items'] = [ { - label: '退出登录', + label: } + okText="确认" + cancelText="取消" + onConfirm={() => { + localStorage.removeItem('platform-security') + replace(`/login`) + }} + >退出登录, key: '1', }, { @@ -142,16 +163,16 @@ export const TitleOperation: React.FC = ({ allowClear style={{minWidth: '100px'}} placeholder="任务状态" - defaultValue={data.taskState!=''&&data.taskState.split(",").length>0?data.taskState.split(","):[]} + defaultValue={data.taskState != '' && data.taskState.split(",").length > 0 ? data.taskState.split(",") : []} onChange={(value) => { - console.log('onChange',{value}) - if(value.length == 0){ + console.log('onChange', {value}) + if (value.length == 0) { setTaskState("") - }else { + } else { setTaskState(value.join(',')) } }} - onClear={()=>{ + onClear={() => { console.log('onChange,点击了清除无效果') setTaskState("") }} @@ -209,8 +230,8 @@ export const TitleOperation: React.FC = ({ } -
-
+ {nickName} diff --git a/src/ui/task/calendar/CalShow.tsx b/src/ui/task/calendar/CalShow.tsx index d2ef124..2445489 100644 --- a/src/ui/task/calendar/CalShow.tsx +++ b/src/ui/task/calendar/CalShow.tsx @@ -32,12 +32,17 @@ import {editClickRecordRangeAPI} from "@/components/service/ScheduleTask"; import {CopyOutlined, ExclamationCircleFilled, LoadingOutlined} from "@ant-design/icons"; import {copyToClipboard} from "@/lib/copyToClipboard"; import {solarToLunar} from "lunar-calendar"; +import CalendarHeader from "antd/es/calendar/Header"; +import CalHeader from "@/components/CalHeader"; +import {lunarDateShow} from "@/utils/timeFormatUtil"; + const {confirm} = Modal; /** * https://github.com/jquense/react-big-calendar?tab=readme-ov-file * @constructor */ const localizer = dayjsLocalizer(dayjs) + const DragAndDropCalendar = withDragAndDrop(Calendar) const CalShow: React.FC = () => { dayjs.locale('zh-cn') @@ -75,14 +80,7 @@ const CalShow: React.FC = () => { } }) const dateFormat = (date: Date, culture?: Culture, localizer?: DateLocalizer) => { - const solarDate = new Date(date); - const lunarDate = solarToLunar( - solarDate.getFullYear(), - solarDate.getMonth() + 1, - solarDate.getDate() - ); - console.log({lunarDate}) - return `${solarDate.getDate()}/农历:${lunarDate.lunarMonthName}-${lunarDate.lunarDayName}`; + return `${date.getDate()}/${lunarDateShow(date)}`; }; const handleViewChange = (newView: View) => { setView(newView); @@ -177,11 +175,11 @@ const CalShow: React.FC = () => { end: dayjs(taskState.expectedEndTime).toDate(), title:
- {taskState.description && { + {view != 'month' && taskState.description && { e.preventDefault(); // 阻止默认行为(如果有) e.stopPropagation(); // 阻止事件冒泡 copyToClipboard(taskState.description) - }}/>} {taskState.description}
+ }}/>} {view != 'month' && taskState.description}
, // style: { // backgroundColor: 'green', @@ -381,7 +379,7 @@ const CalShow: React.FC = () => { range.start = rangeLet[0]; // } // if (range.end.valueOf() < rangeLet[0].valueOf()) { - range.end = dayjs(rangeLet[0]).add(1,'d').toDate() + range.end = dayjs(rangeLet[0]).add(1, 'd').toDate() // } } // 为周的时候类型为数组,周一到周日七天 @@ -390,7 +388,7 @@ const CalShow: React.FC = () => { range.start = rangeLet[0]; // } // if (range.end.valueOf() < rangeLet[6].valueOf()) { - range.end = dayjs(rangeLet[6]).add(1,'d').toDate() + range.end = dayjs(rangeLet[6]).add(1, 'd').toDate() // } } // 为月的时候类型为对象 @@ -399,7 +397,7 @@ const CalShow: React.FC = () => { range.start = rangeLet.start // } // if (range.end.valueOf() < rangeLet.end.valueOf()) { - range.end = dayjs(rangeLet.end).add(1,'d').toDate() + range.end = dayjs(rangeLet.end).add(1, 'd').toDate() // } } @@ -426,7 +424,7 @@ const CalShow: React.FC = () => { messages={calMessages} formats={{ dayFormat: dateFormat, - dateFormat: dateFormat, + // dateFormat: dateFormat, monthHeaderFormat: (date) => { const solarDate = new Date(date); const lunarDate = solarToLunar( @@ -464,6 +462,13 @@ const CalShow: React.FC = () => { resizable onEventResize={moveEvent} onEventDrop={moveEvent} + // 组件设置 + components={ + { + month: { + dateHeader: CalHeader + } + }} />
} diff --git a/src/ui/task/drag/DetailForm.tsx b/src/ui/task/drag/DetailForm.tsx index d1c98a2..a4acbe4 100644 --- a/src/ui/task/drag/DetailForm.tsx +++ b/src/ui/task/drag/DetailForm.tsx @@ -123,7 +123,7 @@ export const DetailForm: React.FC = (props) => { if (props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD) { addTask(request).then(response => { console.log('response', response) - if (response.status.success) { + if (response.data.status.success) { message.success("添加任务成功:" + response.data) props.handleCancel() } @@ -140,11 +140,11 @@ export const DetailForm: React.FC = (props) => { } updateTask(request).then(response => { console.log('response', response) - if (response.status.success) { + if (response.data.status.success) { message.success("修改任务成功:" + response.data) props.handleCancel() }else { - message.error(response.status.message) + message.error(response.data.status.message) } } ) diff --git a/src/utils/timeFormatUtil.ts b/src/utils/timeFormatUtil.ts index ae0e0a1..4a1c07f 100644 --- a/src/utils/timeFormatUtil.ts +++ b/src/utils/timeFormatUtil.ts @@ -1,5 +1,6 @@ import dayjs, { Dayjs, isDayjs } from "dayjs"; import utc from "dayjs/plugin/utc"; +import {solarToLunar} from "lunar-calendar"; dayjs.extend(utc) const DATE_FORMAT = "YYYY-MM-DD" // 到秒没啥意义 @@ -236,8 +237,26 @@ function dayjsWeek(day: Dayjs): string { } return "" } + +function lunarDateShow(date:Date){ + const lunarDate = solarToLunar( + date.getFullYear(), + date.getMonth() + 1, + date.getDate() + ); + if(lunarDate.term){ + return lunarDate.term; + } + if(lunarDate.lunarFestival){ + return lunarDate.lunarFestival; + } + if(lunarDate.solarFestival){ + return lunarDate.solarFestival + } + return lunarDate.lunarMonthName+lunarDate.lunarDayName; +} export { DATE_TIME_FORMAT, DATE_FORMAT, DATE_TIME_FORMAT_SIMPLE, dayStartUtcFormat, nextDayStartUtcFormat, betweenTime, - dateStartUtcFormat, nextDateStartUtcFormat, cronToChinese, dayjsWeek + dateStartUtcFormat, nextDateStartUtcFormat, cronToChinese, dayjsWeek,lunarDateShow } \ No newline at end of file