diff --git a/docker/deploy.md b/docker/deploy.md index 4a9804b..a30329e 100644 --- a/docker/deploy.md +++ b/docker/deploy.md @@ -18,4 +18,16 @@ docker build -t task-manager-nginx . docker run -d -p 3001:80 -p 3002:443 --network task-manager --restart unless-stopped -v ./out:/usr/share/nginx/html --name task-manager-nginx task-manager-nginx # 进入容器 docker exec -it a3ca9658cc6ce331cc0e4f84996088940a386b39b3e2edd56549d335a52ab581 /bin/sh +``` + + +日更 +```shell +docker build -t task-manager-nginx:20250526 . +docker stop task-manager-nginx +docker run -d -p 3001:80 -p 3002:443 --network task-manager --restart unless-stopped -v ./out:/usr/share/nginx/html --name task-manager-nginx task-manager-nginx:20250528 + +# 复制证书到云服务器 +scp -r cert/ root@121.36.71.28:/usr/local/software/nginx-1.28.0/ + ``` \ No newline at end of file diff --git a/docker/nginx-yun.conf b/docker/nginx-yun.conf new file mode 100644 index 0000000..ff0ba04 --- /dev/null +++ b/docker/nginx-yun.conf @@ -0,0 +1,120 @@ +# 全局配置 +user root; +worker_processes auto; +error_log /var/log/nginx/error.log; +pid /var/run/nginx.pid; + +# 事件处理 +events { + worker_connections 1024; +} + +# HTTP 服务器 +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + # HTTPS 服务器监听端口 + # 443 + # HTTP 服务器监听端口 + server { + listen 80; + # start 启用https + listen 443 ssl; + # 服务器名称 + server_name www.huaruyu.com; + # 将所有HTTP请求通过rewrite指令重定向到HTTPS。 + # rewrite ^(.*)$ https://$host$1; + # 填写证书文件绝对路径 + ssl_certificate /usr/local/software/nginx-1.28.0/cert/www.huaruyu.com.pem; + # 填写证书私钥文件绝对路径 + ssl_certificate_key /usr/local/software/nginx-1.28.0/cert/www.huaruyu.com.key; + + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 5m; + + # 自定义设置使用的TLS协议的类型以及加密套件(以下为配置示例,请您自行评估是否需要配置) + # TLS协议版本越高,HTTPS通信的安全性越高,但是相较于低版本TLS协议,高版本TLS协议对浏览器的兼容性较差。 + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; + + # 表示优先使用服务端加密套件。默认开启 + ssl_prefer_server_ciphers on; + # end 启用https + + # 启用 ETag 头,Nginx 会为每个资源生成一个唯一的 ETag 值,当资源更新时,ETag 值会改变。 + etag on; + + # 设置允许跨域的域,* 表示允许任何域,也可以设置特定的域,has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. + add_header 'Access-Control-Allow-Origin' '*'; + # 允许的方法 + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; + # 允许的头信息字段 + add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type,Authorization,Origin' always; + # 缓存时间 + add_header 'Access-Control-Max-Age' 1728000 always; + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + # 访问日志路径 + access_log /var/log/nginx/access.log; + # 站点根目录 + root /usr/share/nginx/html; + # 代理配置 + location / { + # 默认页面 + index index.html index.htm; + try_files $uri $uri.html $uri/ =404; + # try_files $uri $uri/ =404; + } + + # 第二个页面的配置 + location ^~ /mobile/ { +# index index.html index.htm; +# try_files $uri $uri.html $uri/ =404; + alias /usr/share/nginx/html/mobile/; + index index.html index.htm; + try_files $uri $uri/ /mobile/index.html; + } + + location ^~ /todo-server/ { + # 预检请求的处理 + 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') { + 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/ { + # 预检请求的处理 + if ($request_method = 'OPTIONS') { + return 204; + } + rewrite ^/task/(.*)$ /task/$1.html break; + } + # 静态文件缓存配置 + location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { + expires 7d; + access_log off; + } + } +} diff --git a/docker/out/背景19-1733751214093.jpg b/docker/out/背景19-1733751214093.jpg new file mode 100644 index 0000000..5e40629 Binary files /dev/null and b/docker/out/背景19-1733751214093.jpg differ diff --git a/src/app/task/four/layout.tsx b/src/app/task/four/layout.tsx index 82cd704..526f678 100644 --- a/src/app/task/four/layout.tsx +++ b/src/app/task/four/layout.tsx @@ -46,7 +46,7 @@ export default function Layout({children}: { children: React.ReactNode }) { if (result.status.success) { // recursionActionChild(result.data.content); result.data.content.forEach(dataType=>{ - dataType.state=taskStateList.find(taskState=>taskState.code===dataType.state+'')?.name + dataType.state=taskStateList.find(taskState=>taskState.code===dataType.state+'')!.name }) setResultDataTypeList(result.data.content) console.log("setResultDataTypeList(result.data.content)",result.data.content) diff --git a/src/lib/definitions.ts b/src/lib/definitions.ts index c5b29f1..eca7aee 100644 --- a/src/lib/definitions.ts +++ b/src/lib/definitions.ts @@ -37,7 +37,6 @@ export type TaskMessage ={ export type DataType = TaskMessage&{ key: React.ReactNode; - type:number; action?:React.ReactNode; expectedStartTime?:string; diff --git a/src/ui/task/drag/DetailForm.tsx b/src/ui/task/drag/DetailForm.tsx index fe312b3..d1c98a2 100644 --- a/src/ui/task/drag/DetailForm.tsx +++ b/src/ui/task/drag/DetailForm.tsx @@ -43,8 +43,8 @@ export const DetailForm: React.FC = (props) => { console.log('getTask(props.itemId)', props.itemId, task); if (task.status.success) { // setTaskMessage(task.data) - task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())?.name; - task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())?.name; + task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())!.name; + task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())!.name; defaultPriority = task.data.priority task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : '', task.data.actualEndTime ? dayjs(task.data.actualEndTime) : '']; @@ -95,6 +95,7 @@ export const DetailForm: React.FC = (props) => { id: values.id, pPid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.pPid : values.pPid, pid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.itemId : props.operationId === OPERATION_BUTTON_TYPE.UPDATE ? values.pid : 0, + pName: values.pName, code: values.code, name: values.name, description: values.description, diff --git a/src/ui/task/drag/DroppableTable.tsx b/src/ui/task/drag/DroppableTable.tsx index fffa2bd..ed8d39c 100644 --- a/src/ui/task/drag/DroppableTable.tsx +++ b/src/ui/task/drag/DroppableTable.tsx @@ -25,7 +25,7 @@ export const DroppableTable: React.FC = (props) => { }else if (props.tableCode=='4'){ setStateName('紧急重要'); } - }, []); + }, [props]); const getItemStyle = (isDragging:any, draggableStyle:any):CSSProperties => { console.log({draggableStyle}) return { diff --git a/src/ui/task/four/DetailForm.tsx b/src/ui/task/four/DetailForm.tsx index fe312b3..4694167 100644 --- a/src/ui/task/four/DetailForm.tsx +++ b/src/ui/task/four/DetailForm.tsx @@ -43,8 +43,8 @@ export const DetailForm: React.FC = (props) => { console.log('getTask(props.itemId)', props.itemId, task); if (task.status.success) { // setTaskMessage(task.data) - task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())?.name; - task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())?.name; + task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())!.name; + task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())!.name; defaultPriority = task.data.priority task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : '', task.data.actualEndTime ? dayjs(task.data.actualEndTime) : '']; @@ -95,6 +95,7 @@ export const DetailForm: React.FC = (props) => { id: values.id, pPid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.pPid : values.pPid, pid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.itemId : props.operationId === OPERATION_BUTTON_TYPE.UPDATE ? values.pid : 0, + pName:values.pName, code: values.code, name: values.name, description: values.description, diff --git a/src/ui/task/four/TreeTable.tsx b/src/ui/task/four/TreeTable.tsx index f11324a..072399b 100644 --- a/src/ui/task/four/TreeTable.tsx +++ b/src/ui/task/four/TreeTable.tsx @@ -46,7 +46,7 @@ const TreeTable: React.FC = (props) => { width: '10%', }, { - title: '任务名称', + title: props.priority=='0'?"不重要不紧急":props.priority=='1'?"不重要紧急":props.priority=='2'?"重要不紧急":props.priority=='3'?"重要紧急":"任务名称", dataIndex: 'name', key: 'name', width: '20%', diff --git a/src/ui/task/project/DetailModelForm.tsx b/src/ui/task/project/DetailModelForm.tsx index 969fb38..f68a2bb 100644 --- a/src/ui/task/project/DetailModelForm.tsx +++ b/src/ui/task/project/DetailModelForm.tsx @@ -51,8 +51,8 @@ export const DetailModelForm: React.FC = (props) => { console.log('DetailModelForm:getTask(props.itemId)', props.itemId, task); if (task.status.success) { // setTaskMessage(task.data) - task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())?.name; - task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())?.name; + task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())!.name; + task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())!.name; task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : undefined, task.data.actualEndTime ? dayjs(task.data.actualEndTime) : undefined]; task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined, @@ -145,10 +145,10 @@ export const DetailModelForm: React.FC = (props) => { values.pid='0' } if (values.expectedTimeRange?.[0]!=undefined) { - values.expectedStartTime=dayjs(values.expectedTimeRange[0]).toDate() + values.expectedStartTime=dayjs(values.expectedTimeRange[0]).format() } if (values.expectedTimeRange?.[1]!=undefined) { - values.expectedEndTime=dayjs(values.expectedTimeRange[1]).toDate() + values.expectedEndTime=dayjs(values.expectedTimeRange[1]).format() } if (values.actualTimeRange?.[0]!=undefined) { values.actualStartTime=dayjs(values.actualTimeRange[0]).toDate() diff --git a/可能用到的技术栈.md b/可能用到的技术栈.md new file mode 100644 index 0000000..f8753fd --- /dev/null +++ b/可能用到的技术栈.md @@ -0,0 +1,20 @@ +# 可能用到的技术栈 +## Next +https://nextjs.org/docs/app/api-reference/cli/next#next-build-options +## 面向开发者的 Web 技术 +https://developer.mozilla.org/zh-CN/docs/Web/API/Window/scrollX +## 富文本 +https://playground.lexical.dev/ +https://lexical.dev/docs/getting-started/creating-plugin +## 界面布局 +https://github.com/react-grid-layout/react-grid-layout +## 拖拉 +https://github.com/atlassian/react-beautiful-dnd +## 3D +https://github.com/mrdoob/three.js/ +https://threejs.org/examples/#webgl_animation_keyframes +## 状态管理 +zustand + +## 动画 +https://motion.dev/docs/react-quick-start