Преглед на файлове

Merge pull request #2284 from visuddhinanda/development

Development
visuddhinanda преди 11 месеца
родител
ревизия
c660c6344b

+ 4 - 0
api-v8/app/Http/Api/TaskApi.php

@@ -61,6 +61,7 @@ class TaskApi
             $task1 = 'next_task_id';
             $task2 = 'task_id';
         }
+        TaskApi::removeTaskRelationRedisKey($taskId, $relation);
         $delete = TaskRelation::where($where, $taskId)
             ->delete();
         foreach ($relationTasksId as $key => $id) {
@@ -82,7 +83,9 @@ class TaskApi
     public static function getRelationTasks($taskId, $relation = 'pre')
     {
         $key = TaskApi::taskRelationRedisKey($taskId, $relation);
+        Log::debug('task redis key=' . $key . ' has=' . RedisClusters::has($key));
         $data = RedisClusters::remember($key, 3 * 24 * 3600, function () use ($taskId, $relation) {
+            Log::debug('getRelationTasks task=' . $taskId . ' relation=' . $relation);
             if ($relation === 'pre') {
                 $where = 'next_task_id';
                 $select = 'task_id';
@@ -116,6 +119,7 @@ class TaskApi
             ->orWhere('next_task_id', $taskId)
             ->select('task_id', 'next_task_id')->get();
         $relationsId = [];
+        $relationsId[$taskId] = 1;
         foreach ($relations as $key => $value) {
             $relationsId[$value->task_id] = 1;
             $relationsId[$value->next_task_id] = 1;

+ 31 - 20
api-v8/app/Tools/RedisClusters.php

@@ -1,43 +1,54 @@
 <?php
+
 namespace App\Tools;
 
 use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\Log;
 
-class RedisClusters{
-    public static function remember($key,$expire,$callback){
-        if(Redis::exists($key)){
-            return json_decode(Redis::get($key),true);
-        }else{
+class RedisClusters
+{
+    public static function remember($key, $expire, $callback)
+    {
+        if (Redis::exists($key)) {
+            return json_decode(Redis::get($key), true);
+        } else {
             $valueOrg = $callback();
-            if($valueOrg === null){
+            if ($valueOrg === null) {
                 $value = null;
-            }else{
-                $value = json_encode($valueOrg,JSON_UNESCAPED_UNICODE);
+            } else {
+                $value = json_encode($valueOrg, JSON_UNESCAPED_UNICODE);
             }
-            Redis::set($key,$value);
-            Redis::expire($key,$expire);
+            Redis::set($key, $value);
+            Redis::expire($key, $expire);
             return $valueOrg;
         }
     }
 
-    public static function put($key,$value,$expire=null){
-        $value = json_encode($value,JSON_UNESCAPED_UNICODE);
-        Redis::set($key,$value);
-        if($expire){
-            Redis::expire($key,$expire);
+    public static function put($key, $value, $expire = null)
+    {
+        $value = json_encode($value, JSON_UNESCAPED_UNICODE);
+        Redis::set($key, $value);
+        if ($expire) {
+            Redis::expire($key, $expire);
         }
         return $value;
     }
 
-    public static function get($key){
-        return json_decode(Redis::get($key),true);
+    public static function get($key)
+    {
+        return json_decode(Redis::get($key), true);
     }
 
-    public static function forget($key){
-        return Redis::del($key);
+    public static function forget($key)
+    {
+        Log::debug('forget start redis key=' . $key . ' has=' . Redis::exists($key));
+        $del = Redis::del($key);
+        Log::debug('forget end redis key=' . $key . ' has=' . Redis::exists($key) . ' del=' . $del);
+        return $del;
     }
 
-    public static function has($key){
+    public static function has($key)
+    {
         return Redis::exists($key);
     }
 }

+ 51 - 22
dashboard-v4/dashboard/src/components/task/PreTask.tsx

@@ -1,8 +1,8 @@
-import { Button, List, Popover, Tag, Typography } from "antd";
+import { Button, List, Popover, Switch, Tag, Typography } from "antd";
 import { ITaskData, ITaskListResponse } from "../api/task";
 import { get } from "../../request";
 import { useEffect, useState } from "react";
-import  { ArrowLeftOutlined, ArrowRightOutlined,CheckOutlined } from "@ant-design/icons";
+import { ArrowLeftOutlined, ArrowRightOutlined } from "@ant-design/icons";
 import { TRelation } from "./TaskEditButton";
 
 const { Text } = Typography;
@@ -12,8 +12,15 @@ interface IProTaskListProps {
   type: TRelation;
   onClick?: (data?: ITaskData | null) => void;
   onClose?: () => void;
+  onChange?: (data: ITaskData, has: boolean) => void;
 }
-const ProTaskList = ({ task, type, onClick, onClose }: IProTaskListProps) => {
+const ProTaskList = ({
+  task,
+  type,
+  onClick,
+  onClose,
+  onChange,
+}: IProTaskListProps) => {
   const [res, setRes] = useState<ITaskData[]>();
   useEffect(() => {
     const url = `/v2/task?view=project&project_id=${task?.project_id}`;
@@ -43,22 +50,34 @@ const ProTaskList = ({ task, type, onClick, onClose }: IProTaskListProps) => {
       footer={false}
       dataSource={res}
       renderItem={(item) => {
-        let checked = false
-        if(type === "pre"){
-          checked = task?.pre_task?.find((value)=>value.id===item.id)!==undefined
-        }else{
-          checked = task?.next_task?.find((value)=>value.id===item.id)!==undefined
+        let checked = false;
+        if (type === "pre") {
+          checked =
+            task?.pre_task?.find((value) => value.id === item.id) !== undefined;
+        } else {
+          checked =
+            task?.next_task?.find((value) => value.id === item.id) !==
+            undefined;
         }
         return (
-        <List.Item
-        actions={[checked?<CheckOutlined />:<></>]}
-          onClick={() => {
-            onClick && onClick(item);
-          }}
-        >
-          {item.title}
-        </List.Item>
-      )}}
+          <List.Item
+            actions={[
+              <Switch
+                size="small"
+                checked={checked}
+                onChange={(checked) => {
+                  onChange && onChange(item, checked);
+                }}
+              />,
+            ]}
+            onClick={() => {
+              onClick && onClick(item);
+            }}
+          >
+            {item.title}
+          </List.Item>
+        );
+      }}
     />
   );
 };
@@ -68,23 +87,32 @@ interface IWidget {
   open?: boolean;
   type: TRelation;
   onClick?: (data?: ITaskData | null) => void;
-  onTagClick?:()=>void;
+  onTagClick?: () => void;
   onClose?: () => void;
+  onChange?: (data: ITaskData, has: boolean) => void;
 }
-const PreTask = ({ task, type, open = false, onClick, onClose,onTagClick }: IWidget) => {
+const PreTask = ({
+  task,
+  type,
+  open = false,
+  onClick,
+  onClose,
+  onTagClick,
+  onChange,
+}: IWidget) => {
   const preTaskShow = open || task?.pre_task;
   const nextTaskShow = open || task?.next_task;
   let tag = <></>;
   if (preTaskShow && type === "pre") {
     tag = (
-      <Tag color="warning" icon={<ArrowLeftOutlined  />} onClick={onTagClick}>
-        {task?.pre_task? `${task?.pre_task?.length} 个前置任务`:''}
+      <Tag color="warning" icon={<ArrowLeftOutlined />} onClick={onTagClick}>
+        {task?.pre_task ? `${task?.pre_task?.length} 个前置任务` : ""}
       </Tag>
     );
   } else if (nextTaskShow && type === "next") {
     tag = (
       <Tag color="warning" icon={<ArrowRightOutlined />} onClick={onTagClick}>
-        {task?.next_task?`阻塞 ${task?.next_task?.length} 个任务`:''}
+        {task?.next_task ? `阻塞 ${task?.next_task?.length} 个任务` : ""}
       </Tag>
     );
   }
@@ -99,6 +127,7 @@ const PreTask = ({ task, type, open = false, onClick, onClose,onTagClick }: IWid
             task={task}
             onClick={onClick}
             onClose={onClose}
+            onChange={onChange}
           />
         </div>
       }

+ 15 - 27
dashboard-v4/dashboard/src/components/task/TaskReader.tsx

@@ -54,7 +54,7 @@ const TaskReader = ({ taskId, onChange, onDiscussion }: IWidget) => {
       .finally(() => setLoading(false));
   }, [taskId]);
 
-  const updatePreTask = (type: TRelation, data?: ITaskData | null) => {
+  const updatePreTask = (type: TRelation, data: ITaskData, has: boolean) => {
     if (!taskId || !data) {
       return;
     }
@@ -63,31 +63,19 @@ const TaskReader = ({ taskId, onChange, onDiscussion }: IWidget) => {
       studio_name: "",
     };
     if (type === "pre") {
-      const hasPre = task?.pre_task?.find((value) => value.id === data.id);
-      if (hasPre) {
-        setting.pre_task_id = task?.pre_task
-          ?.filter((value) => value.id !== data.id)
-          .map((item) => item.id)
-          .join();
-      } else {
-        const newRelation = task?.pre_task
-          ? [...task.pre_task.map((item) => item.id), data.id]
-          : [data.id];
-        setting.pre_task_id = newRelation.join();
+      let newPre =
+        task?.pre_task?.filter((value) => value.id !== data.id) ?? [];
+      if (has) {
+        newPre = [...newPre, data];
       }
+      setting.pre_task_id = newPre?.map((item) => item.id).join();
     } else if (type === "next") {
-      const hasPre = task?.next_task?.find((value) => value.id === data.id);
-      if (hasPre) {
-        setting.next_task_id = task?.next_task
-          ?.filter((value) => value.id !== data.id)
-          .map((item) => item.id)
-          .join();
-      } else {
-        const newRelation = task?.next_task
-          ? [...task.next_task.map((item) => item.id), data.id]
-          : [data.id];
-        setting.next_task_id = newRelation.join();
+      let newNext =
+        task?.next_task?.filter((value) => value.id !== data.id) ?? [];
+      if (has) {
+        newNext = [...newNext, data];
       }
+      setting.next_task_id = newNext?.map((item) => item.id).join();
     }
 
     const url = `/v2/task/${setting.id}`;
@@ -115,8 +103,8 @@ const TaskReader = ({ taskId, onChange, onDiscussion }: IWidget) => {
             task={task}
             open={openPreTask}
             type="pre"
-            onClick={(data) => {
-              updatePreTask("pre", data);
+            onChange={(data, has) => {
+              updatePreTask("pre", data, has);
               setOpenPreTask(false);
             }}
             onTagClick={() => setOpenPreTask(true)}
@@ -126,8 +114,8 @@ const TaskReader = ({ taskId, onChange, onDiscussion }: IWidget) => {
             task={task}
             open={openNextTask}
             type="next"
-            onClick={(data) => {
-              updatePreTask("next", data);
+            onChange={(data, has) => {
+              updatePreTask("next", data, has);
               setOpenNextTask(false);
             }}
             onClose={() => setOpenNextTask(false)}

+ 37 - 3
dashboard-v4/dashboard/src/components/task/TaskTitle.tsx

@@ -1,5 +1,6 @@
-import { Typography } from "antd";
-import { ITaskData } from "../api/task";
+import { message, Typography } from "antd";
+import { ITaskData, ITaskResponse, ITaskUpdateRequest } from "../api/task";
+import { patch } from "../../request";
 
 const { Title } = Typography;
 
@@ -9,7 +10,40 @@ interface IWidget {
 }
 const TaskTitle = ({ task, onChange }: IWidget) => {
   return (
-    <Title level={3} editable onChange={(e) => {}}>
+    <Title
+      level={3}
+      editable={{
+        onChange(value) {
+          console.debug("title change", value);
+          if (!task) {
+            console.error("no task");
+            return;
+          }
+          if (value === "") {
+            message.error("标题不能为空");
+            return;
+          }
+          let setting: ITaskUpdateRequest = {
+            id: task.id,
+            studio_name: "",
+            title: value,
+          };
+          const url = `/v2/task/${task.id}`;
+          console.info("api request", url, setting);
+          patch<ITaskUpdateRequest, ITaskResponse>(url, setting).then(
+            (json) => {
+              console.info("api response", json);
+              if (json.ok) {
+                message.success("Success");
+                onChange && onChange([json.data]);
+              } else {
+                message.error(json.message);
+              }
+            }
+          );
+        },
+      }}
+    >
       {task?.title}
     </Title>
   );