Przeglądaj źródła

Merge pull request #1654 from visuddhinanda/agile

pr 支持删除,修改后刷新
visuddhinanda 2 lat temu
rodzic
commit
ea8814b376

+ 7 - 1
clients/php/morus-server.php

@@ -17,7 +17,13 @@ class Greeter extends \Mint\Morus\V1\MarkdownStub
     }
     }
 }
 }
 
 
-$port = 9999;
+$param = getopt('', ['port']);
+print_r($param);
+
+if(!isset($param['port'])){
+    echo 'parameter port is required. --port=xxx  ';
+}
+$port = $param['port'];
 $server = new \Grpc\RpcServer();
 $server = new \Grpc\RpcServer();
 $server->addHttp2Port('0.0.0.0:' . $port);
 $server->addHttp2Port('0.0.0.0:' . $port);
 $server->handle(new Greeter());
 $server->handle(new Greeter());

+ 1 - 1
dashboard/src/components/anthology/AnthologyList.tsx

@@ -79,7 +79,7 @@ const AnthologyListWidget = ({
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/components/channel/ChannelTable.tsx

@@ -116,7 +116,7 @@ const ChannelTableWidget = ({
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/components/dict/UserDictList.tsx

@@ -71,7 +71,7 @@ const UserDictListWidget = ({
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/components/discussion/DiscussionShow.tsx

@@ -56,7 +56,7 @@ const DiscussionShowWidget = ({
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 11 - 2
dashboard/src/components/general/TextDiff.tsx

@@ -6,8 +6,13 @@ const { Text } = Typography;
 interface IWidget {
 interface IWidget {
   content?: string | null;
   content?: string | null;
   oldContent?: string | null;
   oldContent?: string | null;
+  showToolTip?: boolean;
 }
 }
-const TextDiffWidget = ({ content, oldContent }: IWidget) => {
+const TextDiffWidget = ({
+  content,
+  oldContent,
+  showToolTip = true,
+}: IWidget) => {
   if (content) {
   if (content) {
     if (oldContent) {
     if (oldContent) {
       const diff: Change[] = diffChars(oldContent, content);
       const diff: Change[] = diffChars(oldContent, content);
@@ -24,7 +29,11 @@ const TextDiffWidget = ({ content, oldContent }: IWidget) => {
           </Text>
           </Text>
         );
         );
       });
       });
-      return <Tooltip title={content}>{diffResult}</Tooltip>;
+      return showToolTip ? (
+        <Tooltip title={content}>{diffResult}</Tooltip>
+      ) : (
+        <> {diffResult}</>
+      );
     } else {
     } else {
       return <Text>{content}</Text>;
       return <Text>{content}</Text>;
     }
     }

+ 53 - 2
dashboard/src/components/template/SentEdit/SentCell.tsx

@@ -1,6 +1,7 @@
 import { useEffect, useState } from "react";
 import { useEffect, useState } from "react";
 import { useIntl } from "react-intl";
 import { useIntl } from "react-intl";
-import { Divider } from "antd";
+import { Divider, message as AntdMessage, Modal } from "antd";
+import { ExclamationCircleOutlined } from "@ant-design/icons";
 
 
 import { ISentence } from "../SentEdit";
 import { ISentence } from "../SentEdit";
 import SentEditMenu from "./SentEditMenu";
 import SentEditMenu from "./SentEditMenu";
@@ -18,6 +19,8 @@ import { nissayaBase } from "../Nissaya/NissayaMeaning";
 import { anchor, message } from "../../../reducers/discussion";
 import { anchor, message } from "../../../reducers/discussion";
 import TextDiff from "../../general/TextDiff";
 import TextDiff from "../../general/TextDiff";
 import { sentSave as _sentSave } from "./SentCellEditable";
 import { sentSave as _sentSave } from "./SentCellEditable";
+import { IDeleteResponse } from "../../api/Article";
+import { delete_ } from "../../../request";
 
 
 interface IWidget {
 interface IWidget {
   initValue?: ISentence;
   initValue?: ISentence;
@@ -29,6 +32,7 @@ interface IWidget {
   showDiff?: boolean;
   showDiff?: boolean;
   diffText?: string | null;
   diffText?: string | null;
   onChange?: Function;
   onChange?: Function;
+  onDelete?: Function;
 }
 }
 const SentCellWidget = ({
 const SentCellWidget = ({
   initValue,
   initValue,
@@ -40,6 +44,7 @@ const SentCellWidget = ({
   showDiff = false,
   showDiff = false,
   diffText,
   diffText,
   onChange,
   onChange,
+  onDelete,
 }: IWidget) => {
 }: IWidget) => {
   const intl = useIntl();
   const intl = useIntl();
   const [isEditMode, setIsEditMode] = useState(editMode);
   const [isEditMode, setIsEditMode] = useState(editMode);
@@ -95,6 +100,21 @@ const SentCellWidget = ({
     }
     }
   }, [acceptPr, sentData, isPr]);
   }, [acceptPr, sentData, isPr]);
 
 
+  const deletePr = (id: string) => {
+    delete_<IDeleteResponse>(`/v2/sentpr/${id}`)
+      .then((json) => {
+        if (json.ok) {
+          AntdMessage.success("删除成功");
+          if (typeof onDelete !== "undefined") {
+            onDelete();
+          }
+        } else {
+          AntdMessage.error(json.message);
+        }
+      })
+      .catch((e) => console.log("Oops errors!", e));
+  };
+
   return (
   return (
     <div style={{ marginBottom: "8px", backgroundColor: bgColor }}>
     <div style={{ marginBottom: "8px", backgroundColor: bgColor }}>
       {isPr ? undefined : (
       {isPr ? undefined : (
@@ -105,6 +125,7 @@ const SentCellWidget = ({
         />
         />
       )}
       )}
       <SentEditMenu
       <SentEditMenu
+        isPr={isPr}
         data={sentData}
         data={sentData}
         onModeChange={(mode: string) => {
         onModeChange={(mode: string) => {
           if (mode === "edit") {
           if (mode === "edit") {
@@ -132,7 +153,28 @@ const SentCellWidget = ({
                   );
                   );
                 }
                 }
               });
               });
+              break;
+            case "delete":
+              Modal.confirm({
+                icon: <ExclamationCircleOutlined />,
+                title: intl.formatMessage({
+                  id: "message.delete.confirm",
+                }),
 
 
+                content: "",
+                okText: intl.formatMessage({
+                  id: "buttons.delete",
+                }),
+                okType: "danger",
+                cancelText: intl.formatMessage({
+                  id: "buttons.no",
+                }),
+                onOk() {
+                  if (isPr && sentData && sentData.id) {
+                    deletePr(sentData.id);
+                  }
+                },
+              });
               break;
               break;
             default:
             default:
               break;
               break;
@@ -246,7 +288,11 @@ const SentCellWidget = ({
                 />
                 />
               )
               )
             ) : showDiff ? (
             ) : showDiff ? (
-              <TextDiff content={sentData.content} oldContent={diffText} />
+              <TextDiff
+                showToolTip={false}
+                content={sentData.content}
+                oldContent={diffText}
+              />
             ) : (
             ) : (
               <MdView
               <MdView
                 style={{
                 style={{
@@ -267,6 +313,11 @@ const SentCellWidget = ({
               isPr={isPr}
               isPr={isPr}
               prOpen={prOpen}
               prOpen={prOpen}
               onPrClose={() => setPrOpen(false)}
               onPrClose={() => setPrOpen(false)}
+              onDelete={() => {
+                if (isPr && sentData.id) {
+                  deletePr(sentData.id);
+                }
+              }}
             />
             />
           </div>
           </div>
         ) : undefined}
         ) : undefined}

+ 49 - 22
dashboard/src/components/template/SentEdit/SentCellEditable.tsx

@@ -67,6 +67,7 @@ export const sentSave = (
 interface IWidget {
 interface IWidget {
   data: ISentence;
   data: ISentence;
   isPr?: boolean;
   isPr?: boolean;
+  isCreatePr?: boolean;
   onSave?: Function;
   onSave?: Function;
   onClose?: Function;
   onClose?: Function;
   onCreate?: Function;
   onCreate?: Function;
@@ -77,6 +78,7 @@ const SentCellEditableWidget = ({
   onClose,
   onClose,
   onCreate,
   onCreate,
   isPr = false,
   isPr = false,
+  isCreatePr = false,
 }: IWidget) => {
 }: IWidget) => {
   const intl = useIntl();
   const intl = useIntl();
   const [value, setValue] = useState(data.content);
   const [value, setValue] = useState(data.content);
@@ -94,31 +96,56 @@ const SentCellEditableWidget = ({
     if (!value) {
     if (!value) {
       return;
       return;
     }
     }
-    post<ISentencePrRequest, ISentencePrResponse>(`/v2/sentpr`, {
-      book: data.book,
-      para: data.para,
-      begin: data.wordStart,
-      end: data.wordEnd,
-      channel: data.channel.id,
-      text: value,
-    })
-      .then((json) => {
-        setSaving(false);
+    if (isCreatePr) {
+      post<ISentencePrRequest, ISentencePrResponse>(`/v2/sentpr`, {
+        book: data.book,
+        para: data.para,
+        begin: data.wordStart,
+        end: data.wordEnd,
+        channel: data.channel.id,
+        text: value,
+      })
+        .then((json) => {
+          setSaving(false);
 
 
-        if (json.ok) {
-          message.success(intl.formatMessage({ id: "flashes.success" }));
-          if (typeof onCreate !== "undefined") {
-            onCreate();
+          if (json.ok) {
+            message.success(intl.formatMessage({ id: "flashes.success" }));
+            if (typeof onCreate !== "undefined") {
+              onCreate();
+            }
+          } else {
+            message.error(json.message);
           }
           }
-        } else {
-          message.error(json.message);
-        }
+        })
+        .catch((e) => {
+          setSaving(false);
+          console.error("catch", e);
+          message.error(e.message);
+        });
+    } else {
+      const url = `/v2/sentpr/${data.id}`;
+      console.log("url", url);
+      put<ISentencePrRequest, ISentencePrResponse>(url, {
+        text: value,
       })
       })
-      .catch((e) => {
-        setSaving(false);
-        console.error("catch", e);
-        message.error(e.message);
-      });
+        .then((json) => {
+          if (json.ok) {
+            message.success(intl.formatMessage({ id: "flashes.success" }));
+            if (typeof onSave !== "undefined") {
+              onSave();
+            }
+          } else {
+            message.error(json.message);
+          }
+        })
+        .finally(() => {
+          setSaving(false);
+        })
+        .catch((e) => {
+          console.error("catch", e);
+          message.error(e.message);
+        });
+    }
   };
   };
 
 
   const save = () => {
   const save = () => {

+ 17 - 2
dashboard/src/components/template/SentEdit/SentEditMenu.tsx

@@ -7,6 +7,7 @@ import {
   FieldTimeOutlined,
   FieldTimeOutlined,
   LinkOutlined,
   LinkOutlined,
   FileMarkdownOutlined,
   FileMarkdownOutlined,
+  DeleteOutlined,
 } from "@ant-design/icons";
 } from "@ant-design/icons";
 import type { MenuProps } from "antd";
 import type { MenuProps } from "antd";
 import { ISentence } from "../SentEdit";
 import { ISentence } from "../SentEdit";
@@ -22,6 +23,7 @@ import { useIntl } from "react-intl";
 interface IWidget {
 interface IWidget {
   data?: ISentence;
   data?: ISentence;
   children?: React.ReactNode;
   children?: React.ReactNode;
+  isPr?: boolean;
   onModeChange?: Function;
   onModeChange?: Function;
   onConvert?: Function;
   onConvert?: Function;
   onMenuClick?: Function;
   onMenuClick?: Function;
@@ -29,6 +31,7 @@ interface IWidget {
 const SentEditMenuWidget = ({
 const SentEditMenuWidget = ({
   data,
   data,
   children,
   children,
+  isPr = false,
   onModeChange,
   onModeChange,
   onConvert,
   onConvert,
   onMenuClick,
   onMenuClick,
@@ -66,6 +69,7 @@ const SentEditMenuWidget = ({
         id: "buttons.timeline",
         id: "buttons.timeline",
       }),
       }),
       icon: <FieldTimeOutlined />,
       icon: <FieldTimeOutlined />,
+      disabled: isPr,
     },
     },
     {
     {
       type: "divider",
       type: "divider",
@@ -74,11 +78,13 @@ const SentEditMenuWidget = ({
       key: "suggestion",
       key: "suggestion",
       label: "suggestion",
       label: "suggestion",
       icon: <HandOutlinedIcon />,
       icon: <HandOutlinedIcon />,
+      disabled: isPr,
     },
     },
     {
     {
       key: "discussion",
       key: "discussion",
       label: "discussion",
       label: "discussion",
       icon: <CommentOutlinedIcon />,
       icon: <CommentOutlinedIcon />,
+      disabled: isPr,
     },
     },
     {
     {
       type: "divider",
       type: "divider",
@@ -87,13 +93,13 @@ const SentEditMenuWidget = ({
       key: "markdown",
       key: "markdown",
       label: "To Markdown",
       label: "To Markdown",
       icon: <FileMarkdownOutlined />,
       icon: <FileMarkdownOutlined />,
-      disabled: !data || data.contentType === "markdown",
+      disabled: !data || data.contentType === "markdown" || isPr,
     },
     },
     {
     {
       key: "json",
       key: "json",
       label: "To Json",
       label: "To Json",
       icon: <JsonOutlinedIcon />,
       icon: <JsonOutlinedIcon />,
-      disabled: !data || data.contentType === "json",
+      disabled: !data || data.contentType === "json" || isPr,
     },
     },
     {
     {
       type: "divider",
       type: "divider",
@@ -105,6 +111,15 @@ const SentEditMenuWidget = ({
       }),
       }),
       icon: <LinkOutlined />,
       icon: <LinkOutlined />,
     },
     },
+    {
+      key: "delete",
+      label: intl.formatMessage({
+        id: "buttons.delete",
+      }),
+      icon: <DeleteOutlined />,
+      danger: true,
+      disabled: !isPr,
+    },
   ];
   ];
 
 
   return (
   return (

+ 1 - 0
dashboard/src/components/template/SentEdit/SuggestionAdd.tsx

@@ -34,6 +34,7 @@ const SuggestionAddWidget = ({ data, onCreate }: IWidget) => {
           <SentCellEditable
           <SentCellEditable
             data={sentData}
             data={sentData}
             isPr={true}
             isPr={true}
+            isCreatePr={true}
             onClose={() => {
             onClose={() => {
               setIsEditMode(false);
               setIsEditMode(false);
             }}
             }}

+ 37 - 21
dashboard/src/components/template/SentEdit/SuggestionList.tsx

@@ -1,5 +1,6 @@
-import { message, Skeleton, Switch } from "antd";
+import { Button, List, message, Skeleton, Space, Switch } from "antd";
 import { useEffect, useState } from "react";
 import { useEffect, useState } from "react";
+import { ReloadOutlined } from "@ant-design/icons";
 
 
 import { get } from "../../../request";
 import { get } from "../../../request";
 import { ISuggestionListResponse } from "../../api/Suggestion";
 import { ISuggestionListResponse } from "../../api/Suggestion";
@@ -86,27 +87,42 @@ const SuggestionListWidget = ({
         <Skeleton />
         <Skeleton />
       ) : (
       ) : (
         <>
         <>
-          <div style={{ textAlign: "right" }}>
-            {"文本比对"}
-            <Switch
-              size="small"
-              defaultChecked
-              onChange={(checked) => setShowDiff(checked)}
-            />
-          </div>
-          {sentData.length > 0
-            ? sentData.map((item, id) => {
-                return (
-                  <SentCell
-                    value={item}
-                    key={id}
-                    isPr={true}
-                    showDiff={showDiff}
-                    diffText={content}
+          <List
+            header={
+              <div style={{ textAlign: "right" }}>
+                <Space>
+                  <Button
+                    type="link"
+                    size="small"
+                    icon={<ReloadOutlined />}
+                    onClick={() => load()}
+                  ></Button>
+                  {"文本比对"}
+                  <Switch
+                    size="small"
+                    defaultChecked
+                    onChange={(checked) => setShowDiff(checked)}
                   />
                   />
-                );
-              })
-            : "没有修改建议"}
+                </Space>
+              </div>
+            }
+            itemLayout="vertical"
+            size="small"
+            dataSource={sentData}
+            renderItem={(item, id) => (
+              <List.Item>
+                <SentCell
+                  value={item}
+                  key={id}
+                  isPr={true}
+                  showDiff={showDiff}
+                  diffText={content}
+                  onDelete={() => load()}
+                  onChange={() => load()}
+                />
+              </List.Item>
+            )}
+          />
         </>
         </>
       )}
       )}
     </>
     </>

+ 32 - 3
dashboard/src/components/template/SentEdit/SuggestionToolbar.tsx

@@ -1,15 +1,15 @@
-import { Divider, Space, Tooltip, Typography } from "antd";
-import { LikeOutlined } from "@ant-design/icons";
+import { Divider, Popconfirm, Space, Tooltip, Typography } from "antd";
+import { LikeOutlined, DeleteOutlined } from "@ant-design/icons";
 import { ISentence } from "../SentEdit";
 import { ISentence } from "../SentEdit";
 import { useEffect, useState } from "react";
 import { useEffect, useState } from "react";
 import CommentBox from "../../discussion/DiscussionDrawer";
 import CommentBox from "../../discussion/DiscussionDrawer";
-import SuggestionBox from "./SuggestionBox";
 import PrAcceptButton from "./PrAcceptButton";
 import PrAcceptButton from "./PrAcceptButton";
 import { CommentOutlinedIcon, HandOutlinedIcon } from "../../../assets/icon";
 import { CommentOutlinedIcon, HandOutlinedIcon } from "../../../assets/icon";
 import store from "../../../store";
 import store from "../../../store";
 import { count, show } from "../../../reducers/discussion";
 import { count, show } from "../../../reducers/discussion";
 import { useAppSelector } from "../../../hooks";
 import { useAppSelector } from "../../../hooks";
 import { openPanel } from "../../../reducers/right-panel";
 import { openPanel } from "../../../reducers/right-panel";
+import { useIntl } from "react-intl";
 
 
 const { Text, Paragraph } = Typography;
 const { Text, Paragraph } = Typography;
 
 
@@ -21,6 +21,7 @@ interface IWidget {
   prOpen?: boolean;
   prOpen?: boolean;
   onPrClose?: Function;
   onPrClose?: Function;
   onAccept?: Function;
   onAccept?: Function;
+  onDelete?: Function;
 }
 }
 const SuggestionToolbarWidget = ({
 const SuggestionToolbarWidget = ({
   data,
   data,
@@ -30,11 +31,13 @@ const SuggestionToolbarWidget = ({
   prOpen = false,
   prOpen = false,
   compact = false,
   compact = false,
   onPrClose,
   onPrClose,
+  onDelete,
 }: IWidget) => {
 }: IWidget) => {
   const [CommentCount, setCommentCount] = useState<number | undefined>(
   const [CommentCount, setCommentCount] = useState<number | undefined>(
     data.suggestionCount?.discussion
     data.suggestionCount?.discussion
   );
   );
   const discussionCount = useAppSelector(count);
   const discussionCount = useAppSelector(count);
+  const intl = useIntl();
 
 
   useEffect(() => {
   useEffect(() => {
     if (
     if (
@@ -59,6 +62,32 @@ const SuggestionToolbarWidget = ({
               }
               }
             }}
             }}
           />
           />
+          <Popconfirm
+            title={intl.formatMessage({
+              id: "message.delete.confirm",
+            })}
+            placement="right"
+            onConfirm={() => {
+              if (typeof onDelete !== "undefined") {
+                onDelete();
+              }
+            }}
+            okType="danger"
+            okText={intl.formatMessage({
+              id: `buttons.delete`,
+            })}
+            cancelText={intl.formatMessage({
+              id: `buttons.no`,
+            })}
+          >
+            <Tooltip
+              title={intl.formatMessage({
+                id: `buttons.delete`,
+              })}
+            >
+              <DeleteOutlined />
+            </Tooltip>
+          </Popconfirm>
         </Space>
         </Space>
       ) : (
       ) : (
         <Space size={"small"}>
         <Space size={"small"}>

+ 1 - 1
dashboard/src/components/term/TermList.tsx

@@ -45,7 +45,7 @@ const TermListWidget = ({ studioName, channelId }: IWidget) => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/components/webhook/WebhookList.tsx

@@ -33,7 +33,7 @@ const WebhookListWidget = ({ channelId, studioName }: IWidget) => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/locales/zh-Hans/message.ts

@@ -1,7 +1,7 @@
 const items = {
 const items = {
   "flashes.success": "操作成功",
   "flashes.success": "操作成功",
   "message.irrevocable": "此操作不可撤销",
   "message.irrevocable": "此操作不可撤销",
-  "message.delete.sure": "确定删除吗?",
+  "message.delete.confirm": "确定删除吗?",
 };
 };
 
 
 export default items;
 export default items;

+ 1 - 1
dashboard/src/pages/admin/nissaya-ending/list.tsx

@@ -77,7 +77,7 @@ const Widget = () => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/pages/admin/relation/list.tsx

@@ -93,7 +93,7 @@ const Widget = () => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 16 - 5
dashboard/src/pages/studio/article/list.tsx

@@ -1,24 +1,35 @@
 import { useState } from "react";
 import { useState } from "react";
-import { useParams } from "react-router-dom";
+import { useNavigate, useParams } from "react-router-dom";
 import ArticleEditDrawer from "../../../components/article/ArticleEditDrawer";
 import ArticleEditDrawer from "../../../components/article/ArticleEditDrawer";
 
 
 import ArticleList from "../../../components/article/ArticleList";
 import ArticleList from "../../../components/article/ArticleList";
+import { fullUrl } from "../../../utils";
 
 
 const Widget = () => {
 const Widget = () => {
   const { studioname } = useParams(); //url 参数
   const { studioname } = useParams(); //url 参数
   const [articleId, setArticleId] = useState<string>();
   const [articleId, setArticleId] = useState<string>();
   const [open, setOpen] = useState<boolean>(false);
   const [open, setOpen] = useState<boolean>(false);
+  const navigate = useNavigate();
 
 
   return (
   return (
     <>
     <>
       <ArticleList
       <ArticleList
         studioName={studioname}
         studioName={studioname}
         editable={true}
         editable={true}
-        onSelect={(id: string) => {
+        onSelect={(
+          id: string,
+          title: string,
+          event: React.MouseEvent<HTMLElement, MouseEvent>
+        ) => {
           setArticleId(id);
           setArticleId(id);
-          setOpen(true);
-          //const url = `/studio/${studioname}/article/${id}/edit`;
-          //navigate(url);
+          const url = `/studio/${studioname}/article/edit/${id}`;
+          if (event.shiftKey) {
+            navigate(url);
+          } else if (event.ctrlKey || event.metaKey) {
+            window.open(fullUrl(url), "_blank");
+          } else {
+            setOpen(true);
+          }
         }}
         }}
       />
       />
       <ArticleEditDrawer
       <ArticleEditDrawer

+ 1 - 1
dashboard/src/pages/studio/course/list.tsx

@@ -95,7 +95,7 @@ const Widget = () => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",

+ 1 - 1
dashboard/src/pages/studio/group/list.tsx

@@ -67,7 +67,7 @@ const Widget = () => {
       icon: <ExclamationCircleOutlined />,
       icon: <ExclamationCircleOutlined />,
       title:
       title:
         intl.formatMessage({
         intl.formatMessage({
-          id: "message.delete.sure",
+          id: "message.delete.confirm",
         }) +
         }) +
         intl.formatMessage({
         intl.formatMessage({
           id: "message.irrevocable",
           id: "message.irrevocable",