Răsfoiți Sursa

:sparkles: 把ArticleCard 放到最外层

visuddhinanda 3 ani în urmă
părinte
comite
ee61c7d472

+ 34 - 21
dashboard/src/components/article/Article.tsx

@@ -2,31 +2,44 @@ import { message } from "antd";
 import { useEffect, useState } from "react";
 import { get } from "../../request";
 import { IArticleResponse } from "../api/Article";
-import ArticleCard from "./ArticleCard";
-import { IWidgetArticleData } from "./ArticleView";
+import ArticleView, { IWidgetArticleData } from "./ArticleView";
 
+export type ArticleMode = "read" | "edit";
 interface IWidgetArticle {
-	type?: string;
-	articleId?: string;
-	mode?: "read" | "edit";
+  type?: string;
+  articleId?: string;
+  mode?: ArticleMode;
+  active?: boolean;
+  showModeSwitch?: boolean;
+  showMainMenu?: boolean;
+  showContextMenu?: boolean;
 }
-const Widget = ({ type, articleId, mode }: IWidgetArticle) => {
-	const [articleData, setArticleData] = useState<IWidgetArticleData>();
+const Widget = ({
+  type,
+  articleId,
+  mode = "read",
+  active = false,
+  showModeSwitch = true,
+  showMainMenu = true,
+  showContextMenu = true,
+}: IWidgetArticle) => {
+  const [articleData, setArticleData] = useState<IWidgetArticleData>();
 
-	useEffect(() => {
-		if (typeof type !== "undefined" && typeof articleId !== "undefined") {
-			get<IArticleResponse>(`/v2/corpus/${type}/${articleId}`).then(
-				(json) => {
-					if (json.ok) {
-						setArticleData(json.data);
-					} else {
-						message.error(json.message);
-					}
-				}
-			);
-		}
-	}, [type, articleId]);
-	return <ArticleCard data={articleData} />;
+  useEffect(() => {
+    if (!active) {
+      return;
+    }
+    if (typeof type !== "undefined" && typeof articleId !== "undefined") {
+      get<IArticleResponse>(`/v2/${type}/${articleId}/${mode}`).then((json) => {
+        if (json.ok) {
+          setArticleData(json.data);
+        } else {
+          message.error(json.message);
+        }
+      });
+    }
+  }, [active, type, articleId, mode]);
+  return <ArticleView {...articleData} />;
 };
 
 export default Widget;

+ 90 - 61
dashboard/src/components/article/ArticleCard.tsx

@@ -1,72 +1,101 @@
 import { Button, Card, Dropdown, Menu, Space, Segmented } from "antd";
-import { MoreOutlined, MenuOutlined } from "@ant-design/icons";
+import { MoreOutlined, MenuOutlined, ReloadOutlined } from "@ant-design/icons";
 import type { MenuProps } from "antd";
 import ArticleView, { IWidgetArticleData } from "./ArticleView";
+import { useIntl } from "react-intl";
+import { useState } from "react";
 
 interface IWidgetArticleCard {
-	data?: IWidgetArticleData;
+  data?: IWidgetArticleData;
+  showModeSwitch?: boolean;
+  showMainMenu?: boolean;
+  showContextMenu?: boolean;
+  showResTab?: boolean;
+  children?: React.ReactNode;
+  onModeChange?: Function;
+  openInCol?: Function;
 }
-const Widget = ({ data }: IWidgetArticleCard) => {
-	const onClick: MenuProps["onClick"] = (e) => {
-		console.log("click ", e);
-	};
+const Widget = ({
+  data,
+  showModeSwitch = true,
+  showMainMenu = true,
+  showContextMenu = true,
+  showResTab = true,
+  children,
+  onModeChange,
+  openInCol,
+}: IWidgetArticleCard) => {
+  const intl = useIntl();
+  const [mode, setMode] = useState<string>("read");
 
-	const menu = (
-		<Menu
-			onClick={onClick}
-			items={[
-				{
-					key: "close",
-					label: "关闭",
-				},
-				{
-					key: "closeAll",
-					label: "关闭全部",
-				},
-				{
-					key: "closeOthers",
-					label: "关闭其他",
-				},
-				{
-					key: "closeRight",
-					label: "关闭右侧",
-				},
-			]}
-		/>
-	);
+  const onClick: MenuProps["onClick"] = (e) => {
+    console.log("click ", e);
+  };
 
-	return (
-		<Card
-			size="small"
-			title={
-				<Space>
-					<Button size="small" icon={<MenuOutlined />} />
-					{data?.title}
-				</Space>
-			}
-			extra={
-				<Space>
-					<Segmented
-						options={[
-							{ label: "阅读", value: "read" },
-							{ label: "编辑", value: "edit" },
-						]}
-						value="read"
-						onChange={(value) => {
-							console.log(value);
-						}}
-					/>
-					<Dropdown overlay={menu} placement="bottomRight">
-						<Button shape="circle" icon={<MoreOutlined />}></Button>
-					</Dropdown>
-				</Space>
-			}
-			style={{ width: 600 }}
-			bodyStyle={{ height: 590, overflowY: "scroll" }}
-		>
-			<ArticleView {...data} />
-		</Card>
-	);
+  const menu = (
+    <Menu
+      onClick={onClick}
+      items={[
+        {
+          key: "close",
+          label: "关闭",
+        },
+      ]}
+    />
+  );
+  const modeSwitch = (
+    <Segmented
+      size="middle"
+      options={[
+        {
+          label: intl.formatMessage({ id: "buttons.read" }),
+          value: "read",
+        },
+        {
+          label: intl.formatMessage({ id: "buttons.edit" }),
+          value: "edit",
+        },
+      ]}
+      value={mode}
+      onChange={(value) => {
+        if (typeof onModeChange !== "undefined") {
+          onModeChange(value.toString());
+        }
+        setMode(value.toString());
+      }}
+    />
+  );
+  const mainMenu = <Button size="small" icon={<MenuOutlined />} />;
+  const contextMenu = (
+    <Dropdown overlay={menu} placement="bottomRight">
+      <Button shape="circle" size="small" icon={<MoreOutlined />}></Button>
+    </Dropdown>
+  );
+  return (
+    <Card
+      size="small"
+      title={
+        <Space>
+          {mainMenu}
+          {data?.title}
+        </Space>
+      }
+      extra={
+        <Space>
+          {modeSwitch}
+          <Button
+            shape="circle"
+            size="small"
+            icon={<ReloadOutlined />}
+          ></Button>
+          {contextMenu}
+        </Space>
+      }
+      bodyStyle={{ height: 630, overflowY: "scroll" }}
+    >
+      {children}
+    </Card>
+  );
 };
 
 export default Widget;

+ 27 - 27
dashboard/src/components/article/ArticleView.tsx

@@ -4,37 +4,37 @@ import MdView from "../template/MdView";
 const { Paragraph, Title, Text } = Typography;
 
 export interface IWidgetArticleData {
-	id?: string;
-	title?: string;
-	subTitle?: string;
-	summary?: string;
-	content?: string;
-	created_at?: string;
-	updated_at?: string;
+  id?: string;
+  title?: string;
+  subTitle?: string;
+  summary?: string;
+  content?: string;
+  created_at?: string;
+  updated_at?: string;
 }
 
 const Widget = ({
-	id,
-	title,
-	subTitle,
-	summary,
-	content,
-	created_at,
-	updated_at,
+  id,
+  title,
+  subTitle,
+  summary,
+  content,
+  created_at,
+  updated_at,
 }: IWidgetArticleData) => {
-	return (
-		<>
-			<Title level={1}>{title}</Title>
-			<Text type="secondary">{subTitle}</Text>
-			<Paragraph ellipsis={{ rows: 2, expandable: true, symbol: "more" }}>
-				{summary}
-			</Paragraph>
-			<Divider />
-			<div>
-				<MdView html={content ? content : "none"} />
-			</div>
-		</>
-	);
+  return (
+    <>
+      <Title level={1}>{title}</Title>
+      <Text type="secondary">{subTitle}</Text>
+      <Paragraph ellipsis={{ rows: 2, expandable: true, symbol: "more" }}>
+        {summary}
+      </Paragraph>
+      <Divider />
+      <div>
+        <MdView html={content ? content : "none"} />
+      </div>
+    </>
+  );
 };
 
 export default Widget;

+ 108 - 72
dashboard/src/pages/library/article/show.tsx

@@ -1,14 +1,11 @@
-import { useState, useEffect } from "react";
+import { useState } from "react";
 import { useParams } from "react-router-dom";
-import { message, Switch } from "antd";
+import { Col, Row, Switch } from "antd";
 import { Button, Drawer, Space } from "antd";
 import { SettingOutlined } from "@ant-design/icons";
 
-import { IArticleResponse } from "../../../components/api/Article";
-import Article from "../../../components/article/Article";
-import { IWidgetArticleData } from "../../../components/article/ArticleView";
-
-import { get } from "../../../request";
+import Article, { ArticleMode } from "../../../components/article/Article";
+import ArticleCard from "../../../components/article/ArticleCard";
 
 /**
  * type:
@@ -21,74 +18,113 @@ import { get } from "../../../request";
  * @returns
  */
 const Widget = () => {
-	const { type, id, param } = useParams(); //url 参数
-	const [open, setOpen] = useState(false);
+  const { type, id, mode = "read" } = useParams(); //url 参数
+  const [open, setOpen] = useState(false);
+  const [articleMode, setArticleMode] = useState<ArticleMode>(
+    mode as ArticleMode
+  );
+
+  const [articleMode2, setArticleMode2] = useState<ArticleMode>("read");
+
+  const showDrawer = () => {
+    setOpen(true);
+  };
 
-	const showDrawer = () => {
-		setOpen(true);
-	};
+  const onClose = () => {
+    setOpen(false);
+  };
 
-	const onClose = () => {
-		setOpen(false);
-	};
+  return (
+    <div
+      className="site-drawer-render-in-current-wrapper"
+      style={{ display: "flex" }}
+    >
+      <Row>
+        <Col flex="auto">
+          <Row>
+            <Col span="11">
+              <div>
+                <ArticleCard
+                  onModeChange={(e: ArticleMode) => {
+                    setArticleMode(e);
+                  }}
+                >
+                  <Article
+                    active={true}
+                    type={`corpus/${type}`}
+                    articleId={id}
+                    mode={articleMode}
+                  />
+                </ArticleCard>
+              </div>
+            </Col>
+            <Col span="11">
+              <div>
+                <ArticleCard
+                  onModeChange={(e: ArticleMode) => {
+                    setArticleMode2(e);
+                  }}
+                >
+                  <div>
+                    <Article
+                      active={false}
+                      type={`corpus/${type}`}
+                      articleId={id}
+                      mode={articleMode2}
+                    />
+                  </div>
+                </ArticleCard>
+              </div>
+            </Col>
+          </Row>
+        </Col>
+        <Col flex="24px">
+          <Button
+            shape="circle"
+            icon={<SettingOutlined />}
+            onClick={showDrawer}
+          />
+        </Col>
+      </Row>
 
-	return (
-		<div
-			className="site-drawer-render-in-current-wrapper"
-			style={{ display: "flex" }}
-		>
-			<div
-				style={{ display: "flex", width: "100%", overflowX: "scroll" }}
-			>
-				<div>
-					<Article type={type} articleId={id} />
-				</div>
-			</div>
-			<div style={{ width: "2em" }}>
-				<Button
-					shape="circle"
-					icon={<SettingOutlined />}
-					onClick={showDrawer}
-				></Button>
-			</div>
-			<Drawer
-				title="Setting"
-				placement="right"
-				onClose={onClose}
-				open={open}
-				getContainer={false}
-				style={{ position: "absolute" }}
-			>
-				<Space>
-					保存到用户设置
-					<Switch
-						defaultChecked
-						onChange={(checked) => {
-							console.log(checked);
-						}}
-					/>
-				</Space>
-				<Space>
-					显示原文
-					<Switch
-						defaultChecked
-						onChange={(checked) => {
-							console.log(checked);
-						}}
-					/>
-				</Space>
-				<Space>
-					点词查询
-					<Switch
-						defaultChecked
-						onChange={(checked) => {
-							console.log(checked);
-						}}
-					/>
-				</Space>
-			</Drawer>
-		</div>
-	);
+      <Drawer
+        title="Setting"
+        placement="right"
+        onClose={onClose}
+        open={open}
+        getContainer={false}
+        style={{ position: "absolute" }}
+      >
+        <Space>
+          保存到用户设置
+          <Switch
+            defaultChecked
+            onChange={(checked) => {
+              console.log(checked);
+            }}
+          />
+        </Space>
+        <Space>
+          显示原文
+          <Switch
+            defaultChecked
+            onChange={(checked) => {
+              console.log(checked);
+            }}
+          />
+        </Space>
+        <Space>
+          点词查询
+          <Switch
+            defaultChecked
+            onChange={(checked) => {
+              console.log(checked);
+            }}
+          />
+        </Space>
+      </Drawer>
+    </div>
+  );
 };
 
 export default Widget;