Просмотр исходного кода

Merge pull request #2259 from visuddhinanda/development

处理 http exception
visuddhinanda 1 год назад
Родитель
Сommit
8c8714174e

+ 26 - 9
api-v8/app/Console/Commands/MqAiTranslate.php

@@ -7,6 +7,7 @@ use App\Http\Api\Mq;
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Str;
+use Illuminate\Http\Client\RequestException;
 
 use App\Http\Controllers\AuthController;
 use App\Models\Sentence;
@@ -77,20 +78,36 @@ class MqAiTranslate extends Command
             $modelLog->model_id = $message->model->uid;
             $modelLog->request_at = now();
             $modelLog->request_data = json_encode($param, JSON_UNESCAPED_UNICODE);
+            try {
+                $response = Http::withToken($message->model->key)
+                    ->post($message->model->url, $param);
 
-            $response = Http::withToken($message->model->key)
-                ->retry(2, 120000)
-                ->post($message->model->url, $param);
-            $modelLog->request_headers = json_encode($response->handlerStats(), JSON_UNESCAPED_UNICODE);
-            $modelLog->response_headers = json_encode($response->headers(), JSON_UNESCAPED_UNICODE);
-            $modelLog->status = $response->status();
-            $modelLog->response_data = json_encode($response->json(), JSON_UNESCAPED_UNICODE);
-            if ($response->failed()) {
+                $response->throw(); // 触发异常(如果请求失败)
+
+                $modelLog->request_headers = json_encode($response->handlerStats(), JSON_UNESCAPED_UNICODE);
+                $modelLog->response_headers = json_encode($response->headers(), JSON_UNESCAPED_UNICODE);
+                $modelLog->status = $response->status();
+                $modelLog->response_data = json_encode($response->json(), JSON_UNESCAPED_UNICODE);
+                /*
+                if ($response->failed()) {
+                    $modelLog->success = false;
+                    $modelLog->save();
+                    Log::error($queue . ' http response error', ['data' => $response->json()]);
+                    return 1;
+                }*/
+            } catch (RequestException $e) {
+                Log::error('HTTP 请求发生异常: ' . $e->getMessage());
+                $failResponse = $e->response;
+                $modelLog->request_headers = json_encode($failResponse->handlerStats(), JSON_UNESCAPED_UNICODE);
+                $modelLog->response_headers = json_encode($failResponse->headers(), JSON_UNESCAPED_UNICODE);
+                $modelLog->status = $failResponse->status();
+                $modelLog->response_data = $response->body();
                 $modelLog->success = false;
                 $modelLog->save();
-                Log::error($queue . ' http response error', ['data' => $response->json()]);
                 return 1;
             }
+
+
             $modelLog->save();
             Log::debug($queue . ' log saved');
             $aiData = $response->json();

+ 1 - 1
api-v8/app/Http/Controllers/AiAssistantController.php

@@ -23,7 +23,7 @@ class AiAssistantController extends Controller
             Log::error('notification auth failed {request}', ['request' => $request]);
             return $this->error(__('auth.failed'), 401, 401);
         }
-        $table = AiModel::where('owner_id', $request->get('user_id'))
+        $table = AiModel::where('owner_id', $user['user_uid'])
             ->orWhere('privacy', 'public');
         if ($request->has('keyword')) {
             $table = $table->where('name', 'like', '%' . $request->get('keyword') . '%');

+ 1 - 1
dashboard-v4/dashboard/src/components/api/task.ts

@@ -232,7 +232,7 @@ export interface IProjectTreeInsertRequest {
   data: IProjectUpdateRequest[];
 }
 
-interface IProjectTreeData {
+export interface IProjectTreeData {
   id: string;
   resId?: string;
   isLeaf: boolean;

+ 23 - 0
dashboard-v4/dashboard/src/components/task/ProjectWithTasks.tsx

@@ -0,0 +1,23 @@
+import Project from "./Project";
+import ProjectTask from "./ProjectTask";
+
+interface IWidget {
+  studioName?: string;
+  projectId?: string;
+  onChange?: (id: string) => void;
+}
+const ProjectWithTasks = ({ studioName, projectId, onChange }: IWidget) => {
+  return (
+    <>
+      <Project
+        studioName={studioName}
+        projectId={projectId}
+        onSelect={(id: string) => {
+          onChange && onChange(id);
+        }}
+      />
+      <ProjectTask studioName={studioName} projectId={projectId} />
+    </>
+  );
+};
+export default ProjectWithTasks;

+ 176 - 149
dashboard-v4/dashboard/src/components/task/TaskBuilderChapter.tsx

@@ -12,6 +12,7 @@ import {
 import { useState } from "react";
 import Workflow from "./Workflow";
 import {
+  IProjectTreeData,
   IProjectTreeInsertRequest,
   IProjectTreeResponse,
   ITaskData,
@@ -30,6 +31,7 @@ import {
   ITokenData,
   TPower,
 } from "../api/token";
+import ProjectWithTasks from "./ProjectWithTasks";
 const { Text, Paragraph } = Typography;
 
 interface IModal {
@@ -94,10 +96,11 @@ const TaskBuilderChapter = ({
   const [prop, setProp] = useState<IProp[]>();
   const [title, setTitle] = useState<string>();
   const [loading, setLoading] = useState(false);
-
+  const [projects, setProjects] = useState<IProjectTreeData[]>();
+  const [done, setDone] = useState(false);
   const steps = [
     {
-      title: "章节选择",
+      title: "选择章节",
       content: (
         <div style={{ padding: 8 }}>
           <Space key={1}>
@@ -155,7 +158,7 @@ const TaskBuilderChapter = ({
       ),
     },
     {
-      title: "工作流",
+      title: "选择工作流",
       content: (
         <Workflow
           studioName={studioName}
@@ -179,7 +182,7 @@ const TaskBuilderChapter = ({
       ),
     },
     {
-      title: "生成",
+      title: "生成任务",
       content: (
         <div style={{ padding: 8 }}>
           <div>
@@ -211,6 +214,14 @@ const TaskBuilderChapter = ({
         </div>
       ),
     },
+    {
+      title: "完成",
+      content: projects ? (
+        <ProjectWithTasks projectId={projects[0].id} />
+      ) : (
+        <></>
+      ),
+    },
   ];
 
   const next = () => {
@@ -222,6 +233,145 @@ const TaskBuilderChapter = ({
   };
   const items = steps.map((item) => ({ key: item.title, title: item.title }));
 
+  const DoButton = () => (
+    <Button
+      loading={loading}
+      disabled={loading}
+      type="primary"
+      onClick={async () => {
+        if (!studioName || !chapter) {
+          console.error("缺少参数", studioName, chapter);
+          return;
+        }
+        setLoading(true);
+        //生成projects
+        setMessages((origin) => [...origin, "正在生成任务组……"]);
+        const url = "/v2/project-tree";
+        const values: IProjectTreeInsertRequest = {
+          studio_name: studioName,
+          data: chapter.map((item, id) => {
+            return {
+              id: item.paragraph.toString(),
+              title: id === 0 && title ? title : item.text ?? "",
+              type: "instance",
+              weight: item.chapter_strlen,
+              parent_id: item.parent.toString(),
+              res_id: `${item.book}-${item.paragraph}`,
+            };
+          }),
+        };
+        console.info("api request", url, values);
+        const res = await post<IProjectTreeInsertRequest, IProjectTreeResponse>(
+          url,
+          values
+        );
+        console.info("api response", res);
+        if (!res.ok) {
+          setMessages((origin) => [...origin, "正在生成任务组失败"]);
+          return;
+        } else {
+          setProjects(res.data.rows);
+          setMessages((origin) => [...origin, "生成任务组成功"]);
+        }
+        //生成tasks
+        setMessages((origin) => [...origin, "正在生成任务……"]);
+        const taskUrl = "/v2/task-group";
+        if (!workflow) {
+          return;
+        }
+
+        let taskData: ITaskGroupInsertData[] = res.data.rows
+          .filter((value) => value.isLeaf)
+          .map((project, pId) => {
+            return {
+              project_id: project.id,
+              tasks: workflow.map((task, tId) => {
+                let newContent = task.description;
+                prop
+                  ?.find((pValue) => pValue.taskId === task.id)
+                  ?.param?.forEach((value: IParam) => {
+                    //替换数字参数
+                    if (value.type === "number") {
+                      const searchValue = `${value.key}=${value.value}`;
+                      const replaceValue =
+                        `${value.key}=` +
+                        (value.initValue + value.step * pId).toString();
+                      newContent = newContent?.replace(
+                        searchValue,
+                        replaceValue
+                      );
+                    } else {
+                      //替换book
+                      if (project.resId) {
+                        const [book, paragraph] = project.resId.split("-");
+                        newContent = newContent?.replace(
+                          "book=#",
+                          `book=${book}`
+                        );
+                        newContent = newContent?.replace(
+                          "paragraphs=#",
+                          `paragraphs=${paragraph}`
+                        );
+                        //替换channel
+                        //查找toke
+
+                        const [channel, power] = value.value.split("@");
+                        const mToken = tokens?.find(
+                          (token) =>
+                            token.payload.book?.toString() === book &&
+                            token.payload.para_start?.toString() ===
+                              paragraph &&
+                            token.payload.res_id === channel &&
+                            (power && power.length > 0
+                              ? token.payload.power === power
+                              : true)
+                        );
+                        newContent = newContent?.replace(
+                          value.key,
+                          channel + (mToken ? "@" + mToken?.token : "")
+                        );
+                      }
+                    }
+                  });
+
+                console.debug("description", newContent);
+                return {
+                  ...task,
+                  type: "instance",
+                  description: newContent,
+                };
+              }),
+            };
+          });
+
+        console.info("api request", taskUrl, taskData);
+        const taskRes = await post<ITaskGroupInsertRequest, ITaskGroupResponse>(
+          taskUrl,
+          { data: taskData }
+        );
+        if (taskRes.ok) {
+          message.success("ok");
+          setMessages((origin) => [...origin, "生成任务成功"]);
+          setMessages((origin) => [
+            ...origin,
+            "生成任务" + taskRes.data.taskCount,
+          ]);
+          setMessages((origin) => [
+            ...origin,
+            "生成任务关联" + taskRes.data.taskRelationCount,
+          ]);
+          setMessages((origin) => [
+            ...origin,
+            "打开译经楼-我的任务查看已经生成的任务",
+          ]);
+          setDone(true);
+        }
+        setLoading(false);
+      }}
+    >
+      Done
+    </Button>
+  );
   return (
     <div style={style}>
       <Steps current={current} items={items} />
@@ -230,156 +380,33 @@ const TaskBuilderChapter = ({
       </div>
       <Divider></Divider>
       <div style={{ display: "flex", justifyContent: "space-between" }}>
-        <Button
-          style={{ margin: "0 8px" }}
-          disabled={current === 0}
-          onClick={() => prev()}
-        >
-          Previous
-        </Button>
+        {current < steps.length - 1 ? (
+          <Button
+            style={{ margin: "0 8px" }}
+            disabled={current === 0}
+            onClick={() => prev()}
+          >
+            Previous
+          </Button>
+        ) : (
+          <></>
+        )}
 
-        {current < steps.length - 1 && (
+        {current < steps.length - 2 && (
           <Button type="primary" onClick={() => next()}>
             Next
           </Button>
         )}
-        {current === steps.length - 1 && (
-          <Button
-            loading={loading}
-            disabled={loading}
-            type="primary"
-            onClick={async () => {
-              if (!studioName || !chapter) {
-                console.error("缺少参数", studioName, chapter);
-                return;
-              }
-              setLoading(true);
-              //生成projects
-              setMessages((origin) => [...origin, "正在生成任务组……"]);
-              const url = "/v2/project-tree";
-              const values: IProjectTreeInsertRequest = {
-                studio_name: studioName,
-                data: chapter.map((item, id) => {
-                  return {
-                    id: item.paragraph.toString(),
-                    title: id === 0 && title ? title : item.text ?? "",
-                    type: "instance",
-                    weight: item.chapter_strlen,
-                    parent_id: item.parent.toString(),
-                    res_id: `${item.book}-${item.paragraph}`,
-                  };
-                }),
-              };
-              console.info("api request", url, values);
-              const res = await post<
-                IProjectTreeInsertRequest,
-                IProjectTreeResponse
-              >(url, values);
-              console.info("api response", res);
-              if (!res.ok) {
-                setMessages((origin) => [...origin, "正在生成任务组失败"]);
-                return;
-              } else {
-                setMessages((origin) => [...origin, "生成任务组成功"]);
-              }
-              //生成tasks
-              setMessages((origin) => [...origin, "正在生成任务……"]);
-              const taskUrl = "/v2/task-group";
-              if (!workflow) {
-                return;
-              }
-
-              let taskData: ITaskGroupInsertData[] = res.data.rows
-                .filter((value) => value.isLeaf)
-                .map((project, pId) => {
-                  return {
-                    project_id: project.id,
-                    tasks: workflow.map((task, tId) => {
-                      let newContent = task.description;
-                      prop
-                        ?.find((pValue) => pValue.taskId === task.id)
-                        ?.param?.forEach((value: IParam) => {
-                          //替换数字参数
-                          if (value.type === "number") {
-                            const searchValue = `${value.key}=${value.value}`;
-                            const replaceValue =
-                              `${value.key}=` +
-                              (value.initValue + value.step * pId).toString();
-                            newContent = newContent?.replace(
-                              searchValue,
-                              replaceValue
-                            );
-                          } else {
-                            //替换book
-                            if (project.resId) {
-                              const [book, paragraph] =
-                                project.resId.split("-");
-                              newContent = newContent?.replace(
-                                "book=#",
-                                `book=${book}`
-                              );
-                              newContent = newContent?.replace(
-                                "paragraphs=#",
-                                `paragraphs=${paragraph}`
-                              );
-                              //替换channel
-                              //查找toke
-
-                              const [channel, power] = value.value.split("@");
-                              const mToken = tokens?.find(
-                                (token) =>
-                                  token.payload.book?.toString() === book &&
-                                  token.payload.para_start?.toString() ===
-                                    paragraph &&
-                                  token.payload.res_id === channel &&
-                                  (power && power.length > 0
-                                    ? token.payload.power === power
-                                    : true)
-                              );
-                              newContent = newContent?.replace(
-                                value.key,
-                                channel + (mToken ? "@" + mToken?.token : "")
-                              );
-                            }
-                          }
-                        });
-
-                      console.debug("description", newContent);
-                      return {
-                        ...task,
-                        type: "instance",
-                        description: newContent,
-                      };
-                    }),
-                  };
-                });
-
-              console.info("api request", taskUrl, taskData);
-              const taskRes = await post<
-                ITaskGroupInsertRequest,
-                ITaskGroupResponse
-              >(taskUrl, { data: taskData });
-              if (taskRes.ok) {
-                message.success("ok");
-                setMessages((origin) => [...origin, "生成任务成功"]);
-                setMessages((origin) => [
-                  ...origin,
-                  "生成任务" + taskRes.data.taskCount,
-                ]);
-                setMessages((origin) => [
-                  ...origin,
-                  "生成任务关联" + taskRes.data.taskRelationCount,
-                ]);
-                setMessages((origin) => [
-                  ...origin,
-                  "打开译经楼-我的任务查看已经生成的任务",
-                ]);
-              }
-              setLoading(false);
-            }}
-          >
-            Done
-          </Button>
+        {current === steps.length - 2 && (
+          <>
+            {done ? (
+              <Button type="primary" onClick={() => next()}>
+                完成
+              </Button>
+            ) : (
+              <DoButton />
+            )}
+          </>
         )}
       </div>
     </div>

+ 8 - 12
dashboard-v4/dashboard/src/pages/studio/task/project.tsx

@@ -1,23 +1,19 @@
 import { useNavigate, useParams } from "react-router-dom";
 
-import Project from "../../../components/task/Project";
-import ProjectTask from "../../../components/task/ProjectTask";
+import ProjectWithTasks from "../../../components/task/ProjectWithTasks";
 
 const Widget = () => {
   const { studioname } = useParams();
   const { projectId } = useParams();
   const navigate = useNavigate();
   return (
-    <>
-      <Project
-        studioName={studioname}
-        projectId={projectId}
-        onSelect={(id: string) => {
-          navigate(`/studio/${studioname}/task/project/${id}`);
-        }}
-      />
-      <ProjectTask studioName={studioname} projectId={projectId} />
-    </>
+    <ProjectWithTasks
+      studioName={studioname}
+      projectId={projectId}
+      onChange={(id: string) => {
+        navigate(`/studio/${studioname}/task/project/${id}`);
+      }}
+    />
   );
 };