Skip to content

Commit

Permalink
feat: add ai gen content (#33)
Browse files Browse the repository at this point in the history
feat: add ai generate content & footer link

Co-authored-by: linxin <[email protected]>
  • Loading branch information
ylinwind and linxin authored Sep 11, 2024
1 parent 8c34e2f commit 1f6a928
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 26 deletions.
7 changes: 5 additions & 2 deletions scripts/wiki/template.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ id: "<%= id %>"
hide_table_of_contents: true
---

import {ArticleMeta} from '@site/src/components/article-meta'
import { ArticleMeta } from "@site/src/components/article-meta";
import { AIContent } from "@site/src/components/ai-content";

# <%= title %>

<ArticleMeta id={<%= id %>} updatedAt={'<%=contentUpdatedAt%>'} />
<div className='border-solid border-b border-t-0 my-4 border-[var(--ifm-color-gray-300)]' />

<%= jsxBody || jsxDesc %>
<%= jsxDesc %>

<AIContent content={`<%=jsxBody%>`} id={<%= id %>} />
23 changes: 14 additions & 9 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import axios, { AxiosInstance, ResponseType } from "axios";
const defaultOptions = {
timeout: 60 * 1000,
responseType: "json" as ResponseType,
withCredentials: true
withCredentials: true,
};


const axiosInstance: AxiosInstance = axios.create(defaultOptions);
axiosInstance.interceptors.response.use(
response => {
(response) => {
const res = response.data;

// code === 0 为正常返回
Expand All @@ -24,15 +23,21 @@ axiosInstance.interceptors.response.use(
// 其它未知错误,原样返回
return Promise.reject(res);
},
error => {
(error) => {
return Promise.reject(error);
}
);
export function post(url, params = {}) {
return axiosInstance.request({
url,
method: "post",
params
}
);
url,
method: "post",
params,
});
}
export function get(url, params = {}) {
return axiosInstance.request({
url,
method: "GET",
params,
});
}
64 changes: 64 additions & 0 deletions src/components/ai-content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import { get } from "@site/src/api";
import React, { useEffect, useState } from "react";
import { useDefaultLocale } from "@site/src/utils";

interface AIContentProps {
content?: string;
id: number;
}
const LocalesMap = {
aiGen: {
"zh-CN": "以下内容是 AI 的进一步解读",
"zh-HK": "以下內容是 AI 的進一步解讀",
en: "The following content is a further interpretation by AI.",
},
disclaimer: {
"zh-CN": "免责声明",
"zh-HK": "免責聲明",
en: "Disclaimer",
},
};
export const AIContent: React.FC<AIContentProps> = ({ content, id }) => {
const [AIContent, setAIContent] = useState(content);
const locale = useDefaultLocale() || "en";

const {
siteConfig: {
customFields: { apiProxyUrl },
},
} = useDocusaurusContext();

useEffect(() => {
if (!apiProxyUrl || !id || AIContent) return;

get(`${apiProxyUrl}/v1/social/wiki/content`, { id }).then((resp) => {
const { data } = resp;
if (data?.content) {
setAIContent(data.content);
}
});
}, [apiProxyUrl, id]);

if (!AIContent) return <></>;
return (
<div className="ai-content pt-8 rounded-lg">
<div className="flex items-center space-x-4 pb-3 mb-3 border-solid border-b border-t-0 border-r-0 border-l-0 border-[var(--ifm-color-gray-300)]">
<img
src="https://assets.lbctrl.com/uploads/831466be-e4f8-46a7-aa0b-efcda7a424ff/portai.png"
alt="port-ai"
className="w-7 h-7 rounded-full"
/>
<span className="text-sm">{LocalesMap.aiGen[locale]}</span>
</div>
<div dangerouslySetInnerHTML={{ __html: AIContent }}></div>
<a
href="https://support.longbridgewhale.com/topics/misc/portaidisclaimer"
className="text-sm text-[#37a0ff]"
target="_blank"
>
{LocalesMap.disclaimer[locale]}
</a>
</div>
);
};
90 changes: 78 additions & 12 deletions src/components/article-meta/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,48 @@
import React, { FC, useCallback, useEffect, useState } from "react";
import { post } from "@site/src/api";
import { post, get } from "@site/src/api";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import { translate } from "@docusaurus/Translate";
import { useDefaultLocale } from "@site/src/utils";

interface IArticleMetaProps {
updatedAt: string | null;
id: number;
}

const LocalesMap = {
peopleLearned: {
"zh-CN": "人学过",
"zh-HK": "人學過",
en: "People learned",
},
aiGen: {
"zh-CN": "AI 解读",
"zh-HK": "AI 解读",
en: "AI analysis",
},
aiGenUnderReview: {
"zh-CN": "审核中,通过后可查看新内容",
"zh-HK": "審核中,通過後可查看新內容",
en: "Under review, content will be available after approval.",
},
};

export const ArticleMeta: FC<IArticleMetaProps> = (props) => {
const { updatedAt, id } = props;
const [viewCount, setViewCount] = useState(0);
const [AIContent, setAIContent] = useState("");
const [aiGen, setAIGen] = useState(false);
const [aiGenLoading, setAIGenLoading] = useState(false);
const locale = useDefaultLocale() || "en";
// translate({
// id: "theme.docs.paginator.navAriaLabel",
// message: "Docs pages",
// description: "The ARIA label for the docs pagination"
// });
const {
siteConfig: { customFields: { apiProxyUrl } }
siteConfig: {
customFields: { apiProxyUrl },
},
} = useDocusaurusContext();

useEffect(() => {
Expand All @@ -28,21 +53,34 @@ export const ArticleMeta: FC<IArticleMetaProps> = (props) => {
if (data?.pv) {
setViewCount(data.pv);
}
if (data?.body) {
setAIContent(data.body);
}
});
}, [apiProxyUrl, id]);

const onClickCopySection = useCallback(() => {
const postAI = () => {
setAIGenLoading(true);
setAIGen(true);
get(`${apiProxyUrl}/v1/social/wiki/content`, { id })
.then((resp) => {
const { data } = resp;
})
.finally(() => {
setAIGenLoading(false);
});
};

}, []);
const onClickCopySection = useCallback(() => {}, []);

useEffect(() => {
// @ts-ignore
const clipboard = new ClipboardJS("#copy_trigger");
clipboard.on("success", function(e) {
clipboard.on("success", function (e) {
e.clearSelection();
});

clipboard.on("error", function(e) {
clipboard.on("error", function (e) {
console.error("Action:", e.action);
console.error("Trigger:", e.trigger);
});
Expand All @@ -51,17 +89,45 @@ export const ArticleMeta: FC<IArticleMetaProps> = (props) => {
return (
<div className={"article-meta flex items-center justify-between text-sm"}>
<div className="info">
{!!viewCount &&
<span className={"view-count"}>{viewCount} 人学过 .</span>
}
<span className={"updated-at"}> {translate({
id: "article.meta.updated_at"
}, { datetime: updatedAt })}</span>
{!!viewCount && (
<span className={"view-count"}>
{viewCount} {LocalesMap.peopleLearned[locale]} .
</span>
)}
<span className={"updated-at"}>
{" "}
{translate(
{
id: "article.meta.updated_at",
},
{ datetime: updatedAt }
)}
</span>
</div>
<div className="actions">
{/*<div className="copy-section" id={"copy_trigger"} onClick={onClickCopySection}>*/}
{/* <div className="copy-link" />*/}
{/*</div>*/}

{/* 没有 AI 内容并且没点击过生成 */}
{/* {!AIContent && aiGen && (
<div className="text-xs">{LocalesMap.aiGenUnderReview[locale]}</div>
)}
{!AIContent && !aiGen && (
<div className="relative group">
<span className="px-2 py-1 hover:bg-gray-200 rounded cursor-pointer flex items-center hover:text-white justify-center">
···
</span>
<div className="absolute z-[-1] opacity-0 group-hover:z-50 group-hover:opacity-100 whitespace-nowrap">
<button
className="outline-none bg-white px-2 py-1 rounded border-[var(--ifm-color-gray-300)] border-solid border hover:bg-opacity-80 cursor-pointer"
onClick={postAI}
>
{LocalesMap.aiGen[locale]}
</button>
</div>
</div>
)} */}
</div>
</div>
);
Expand Down
Loading

0 comments on commit 1f6a928

Please sign in to comment.