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

:sparkles: 按照我的和协作分别查询

visuddhinanda 3 лет назад
Родитель
Сommit
66593014ee

+ 57 - 2
dashboard/src/components/anthology/AnthologyList.tsx

@@ -18,9 +18,13 @@ import {
 } from "../../components/api/Article";
 import { delete_, get } from "../../request";
 import { PublicityValueEnum } from "../../components/studio/table";
-import { useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
 import ShareModal from "../share/ShareModal";
 import { EResType } from "../share/Share";
+import {
+  IResNumberResponse,
+  renderBadge,
+} from "../../pages/studio/channel/list";
 
 const { Text } = Typography;
 
@@ -52,6 +56,24 @@ const Widget = ({
   const intl = useIntl();
   const [openCreate, setOpenCreate] = useState(false);
 
+  const [activeKey, setActiveKey] = useState<React.Key | undefined>("my");
+  const [myNumber, setMyNumber] = useState<number>(0);
+  const [collaborationNumber, setCollaborationNumber] = useState<number>(0);
+
+  useEffect(() => {
+    /**
+     * 获取各种课程的数量
+     */
+    const url = `/v2/anthology-my-number?studio=${studioName}`;
+    console.log("url", url);
+    get<IResNumberResponse>(url).then((json) => {
+      if (json.ok) {
+        setMyNumber(json.data.my);
+        setCollaborationNumber(json.data.collaboration);
+      }
+    });
+  }, [studioName]);
+
   const showDeleteConfirm = (id: string, title: string) => {
     Modal.confirm({
       icon: <ExclamationCircleOutlined />,
@@ -243,7 +265,7 @@ const Widget = ({
         request={async (params = {}, sorter, filter) => {
           // TODO
           console.log(params, sorter, filter);
-          let url = `/v2/anthology?view=studio&name=${studioName}`;
+          let url = `/v2/anthology?view=studio&view2=${activeKey}&name=${studioName}`;
           const offset =
             ((params.current ? params.current : 1) - 1) *
             (params.pageSize ? params.pageSize : 20);
@@ -308,6 +330,39 @@ const Widget = ({
             </Popover>
           ) : undefined,
         ]}
+        toolbar={{
+          menu: {
+            activeKey,
+            items: [
+              {
+                key: "my",
+                label: (
+                  <span>
+                    此工作室的
+                    {renderBadge(myNumber, activeKey === "my")}
+                  </span>
+                ),
+              },
+              {
+                key: "collaboration",
+                label: (
+                  <span>
+                    协作
+                    {renderBadge(
+                      collaborationNumber,
+                      activeKey === "collaboration"
+                    )}
+                  </span>
+                ),
+              },
+            ],
+            onChange(key) {
+              console.log("show course", key);
+              setActiveKey(key);
+              ref.current?.reload();
+            },
+          },
+        }}
       />
     </>
   );

+ 4 - 0
dashboard/src/components/api/Article.ts

@@ -1,3 +1,5 @@
+import { IStudio } from "../auth/StudioName";
+import { IUser } from "../auth/User";
 import { ITocPathNode } from "../corpus/TocPath";
 import type { IStudioApiResponse, TRole } from "./Auth";
 
@@ -88,6 +90,8 @@ export interface IArticleDataResponse {
   anthology_count?: number;
   anthology_first?: { title: string };
   role?: TRole;
+  studio?: IStudio;
+  editor?: IUser;
   created_at: string;
   updated_at: string;
 }

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

@@ -28,15 +28,40 @@ import {
   IDeleteResponse,
 } from "../../../components/api/Article";
 import { PublicityValueEnum } from "../../../components/studio/table";
-import { useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
 import ArticleTplMaker from "../../../components/article/ArticleTplMaker";
 import ShareModal from "../../../components/share/ShareModal";
 import { EResType } from "../../../components/share/Share";
 import AddToAnthology from "../../../components/article/AddToAnthology";
 import AnthologySelect from "../../../components/anthology/AnthologySelect";
+import StudioName, { IStudio } from "../../../components/auth/StudioName";
+import { IUser } from "../../../components/auth/User";
 
 const { Text } = Typography;
 
+interface IArticleNumberResponse {
+  ok: boolean;
+  message: string;
+  data: {
+    my: number;
+    collaboration: number;
+  };
+}
+
+const renderBadge = (count: number, active = false) => {
+  return (
+    <Badge
+      count={count}
+      style={{
+        marginBlockStart: -2,
+        marginInlineStart: 4,
+        color: active ? "#1890FF" : "#999",
+        backgroundColor: active ? "#E6F7FF" : "#eee",
+      }}
+    />
+  );
+};
+
 interface DataItem {
   sn: number;
   id: string;
@@ -47,12 +72,31 @@ interface DataItem {
   anthologyTitle?: string;
   publicity: number;
   createdAt: number;
+  studio?: IStudio;
+  editor?: IUser;
 }
 const Widget = () => {
   const intl = useIntl(); //i18n
   const { studioname } = useParams(); //url 参数
   const [openCreate, setOpenCreate] = useState(false);
   const [anthologyId, setAnthologyId] = useState<string>();
+  const [activeKey, setActiveKey] = useState<React.Key | undefined>("my");
+  const [myNumber, setMyNumber] = useState<number>(0);
+  const [collaborationNumber, setCollaborationNumber] = useState<number>(0);
+
+  useEffect(() => {
+    /**
+     * 获取各种课程的数量
+     */
+    const url = `/v2/article-my-number?studio=${studioname}`;
+    console.log("url", url);
+    get<IArticleNumberResponse>(url).then((json) => {
+      if (json.ok) {
+        setMyNumber(json.data.my);
+        setCollaborationNumber(json.data.collaboration);
+      }
+    });
+  }, [studioname]);
 
   const showDeleteConfirm = (id: string, title: string) => {
     Modal.confirm({
@@ -114,12 +158,21 @@ const Widget = () => {
             render: (text, row, index, action) => {
               return (
                 <>
-                  <div>
+                  <div key={1}>
                     <Link to={`/studio/${studioname}/article/${row.id}/edit`}>
                       {row.title}
                     </Link>
                   </div>
-                  <Text type="secondary">{row.subtitle}</Text>
+                  <div key={2}>
+                    <Text type="secondary">{row.subtitle}</Text>
+                  </div>
+                  {activeKey !== "my" ? (
+                    <div key={3}>
+                      <Text type="secondary">
+                        <StudioName data={row.studio} />
+                      </Text>
+                    </div>
+                  ) : undefined}
                 </>
               );
             },
@@ -304,10 +357,10 @@ const Widget = () => {
         request={async (params = {}, sorter, filter) => {
           console.log(params, sorter, filter);
           console.log("anthology", anthologyId);
-          let url = `/v2/article?view=studio&name=${studioname}`;
+          let url = `/v2/article?view=studio&view2=${activeKey}&name=${studioname}`;
           const offset =
             ((params.current ? params.current : 1) - 1) *
-            (params.pageSize ? params.pageSize : 20);
+            (params.pageSize ? params.pageSize : 10);
           url += `&limit=${params.pageSize}&offset=${offset}`;
           if (typeof params.keyword !== "undefined") {
             url += "&search=" + (params.keyword ? params.keyword : "");
@@ -329,6 +382,8 @@ const Widget = () => {
               anthologyTitle: item.anthology_first?.title,
               publicity: item.status,
               createdAt: date.getTime(),
+              studio: item.studio,
+              editor: item.editor,
             };
           });
           return {
@@ -378,6 +433,39 @@ const Widget = () => {
             </Button>
           </Popover>,
         ]}
+        toolbar={{
+          menu: {
+            activeKey,
+            items: [
+              {
+                key: "my",
+                label: (
+                  <span>
+                    此工作室的
+                    {renderBadge(myNumber, activeKey === "my")}
+                  </span>
+                ),
+              },
+              {
+                key: "collaboration",
+                label: (
+                  <span>
+                    协作
+                    {renderBadge(
+                      collaborationNumber,
+                      activeKey === "collaboration"
+                    )}
+                  </span>
+                ),
+              },
+            ],
+            onChange(key) {
+              console.log("show course", key);
+              setActiveKey(key);
+              ref.current?.reload();
+            },
+          },
+        }}
       />
     </>
   );

+ 97 - 9
dashboard/src/pages/studio/channel/list.tsx

@@ -2,7 +2,7 @@ import { useParams } from "react-router-dom";
 import { ActionType, ProTable } from "@ant-design/pro-components";
 import { useIntl } from "react-intl";
 import { Link } from "react-router-dom";
-import { message, Modal, Space, Table, Typography } from "antd";
+import { Badge, message, Modal, Space, Table, Typography } from "antd";
 import { Button, Dropdown, Popover } from "antd";
 import {
   PlusOutlined,
@@ -16,12 +16,36 @@ import { delete_, get } from "../../../request";
 import { IApiResponseChannelList } from "../../../components/api/Channel";
 import { PublicityValueEnum } from "../../../components/studio/table";
 import { IDeleteResponse } from "../../../components/api/Article";
-import { useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
 import { TRole } from "../../../components/api/Auth";
 import ShareModal from "../../../components/share/ShareModal";
 import { EResType } from "../../../components/share/Share";
+import StudioName, { IStudio } from "../../../components/auth/StudioName";
 const { Text } = Typography;
 
+export interface IResNumberResponse {
+  ok: boolean;
+  message: string;
+  data: {
+    my: number;
+    collaboration: number;
+  };
+}
+
+export const renderBadge = (count: number, active = false) => {
+  return (
+    <Badge
+      count={count}
+      style={{
+        marginBlockStart: -2,
+        marginInlineStart: 4,
+        color: active ? "#1890FF" : "#999",
+        backgroundColor: active ? "#E6F7FF" : "#eee",
+      }}
+    />
+  );
+};
+
 interface IItem {
   id: number;
   uid: string;
@@ -29,6 +53,7 @@ interface IItem {
   summary: string;
   type: string;
   role?: TRole;
+  studio?: IStudio;
   publicity: number;
   createdAt: number;
 }
@@ -38,6 +63,24 @@ const Widget = () => {
   const { studioname } = useParams();
   const [openCreate, setOpenCreate] = useState(false);
 
+  const [activeKey, setActiveKey] = useState<React.Key | undefined>("my");
+  const [myNumber, setMyNumber] = useState<number>(0);
+  const [collaborationNumber, setCollaborationNumber] = useState<number>(0);
+
+  useEffect(() => {
+    /**
+     * 获取各种课程的数量
+     */
+    const url = `/v2/channel-my-number?studio=${studioname}`;
+    console.log("url", url);
+    get<IResNumberResponse>(url).then((json) => {
+      if (json.ok) {
+        setMyNumber(json.data.my);
+        setCollaborationNumber(json.data.collaboration);
+      }
+    });
+  }, [studioname]);
+
   const showDeleteConfirm = (id: string, title: string) => {
     Modal.confirm({
       icon: <ExclamationCircleOutlined />,
@@ -99,12 +142,23 @@ const Widget = () => {
             ellipsis: true,
             render: (text, row, index, action) => {
               return (
-                <Link
-                  to={`/studio/${studioname}/channel/${row.uid}`}
-                  key={index}
-                >
-                  {row.title}
-                </Link>
+                <>
+                  <div key={1}>
+                    <Link
+                      to={`/studio/${studioname}/channel/${row.uid}`}
+                      key={index}
+                    >
+                      {row.title}
+                    </Link>
+                  </div>
+                  {activeKey !== "my" ? (
+                    <div key={3}>
+                      <Text type="secondary">
+                        <StudioName data={row.studio} />
+                      </Text>
+                    </div>
+                  ) : undefined}
+                </>
               );
             },
           },
@@ -333,7 +387,7 @@ const Widget = () => {
           console.log(params, sorter, filter);
 
           const res: IApiResponseChannelList = await get(
-            `/v2/channel?view=studio-all&name=${studioname}`
+            `/v2/channel?view=studio&view2=${activeKey}&name=${studioname}`
           );
           const items: IItem[] = res.data.rows.map((item, id) => {
             const date = new Date(item.created_at);
@@ -344,6 +398,7 @@ const Widget = () => {
               summary: item.summary,
               type: item.type,
               role: item.role,
+              studio: item.studio,
               publicity: item.status,
               createdAt: date.getTime(),
             };
@@ -387,6 +442,39 @@ const Widget = () => {
             </Button>
           </Popover>,
         ]}
+        toolbar={{
+          menu: {
+            activeKey,
+            items: [
+              {
+                key: "my",
+                label: (
+                  <span>
+                    此工作室的
+                    {renderBadge(myNumber, activeKey === "my")}
+                  </span>
+                ),
+              },
+              {
+                key: "collaboration",
+                label: (
+                  <span>
+                    协作
+                    {renderBadge(
+                      collaborationNumber,
+                      activeKey === "collaboration"
+                    )}
+                  </span>
+                ),
+              },
+            ],
+            onChange(key) {
+              console.log("show course", key);
+              setActiveKey(key);
+              ref.current?.reload();
+            },
+          },
+        }}
       />
     </>
   );