完成AI续写、优化、问答功能
This commit is contained in:
3
src/api/Ai.ts
Normal file
3
src/api/Ai.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import Request from '@/utils/request'
|
||||||
|
|
||||||
|
// export
|
||||||
@@ -208,7 +208,7 @@ const VditorEditor = ({ value, getValue }: VditorProps) => {
|
|||||||
|
|
||||||
// 监听 value 变化并更新编辑器内容
|
// 监听 value 变化并更新编辑器内容
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (vd && value) {
|
if (vd && value !== undefined && value !== vd.getValue()) {
|
||||||
vd.setValue(value);
|
vd.setValue(value);
|
||||||
}
|
}
|
||||||
}, [value, vd]);
|
}, [value, vd]);
|
||||||
|
|||||||
@@ -10,21 +10,6 @@ import { Article } from '@/types/app/article';
|
|||||||
import { getArticleDataAPI } from '@/api/Article'
|
import { getArticleDataAPI } from '@/api/Article'
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
|
||||||
{
|
|
||||||
key: '1',
|
|
||||||
label: 'AI 续写',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '2',
|
|
||||||
label: 'AI 优化',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '3',
|
|
||||||
label: 'AI 生成',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const CreatePage = () => {
|
const CreatePage = () => {
|
||||||
const [params] = useSearchParams()
|
const [params] = useSearchParams()
|
||||||
const id = +params.get('id')!
|
const id = +params.get('id')!
|
||||||
@@ -58,6 +43,83 @@ const CreatePage = () => {
|
|||||||
setData({ ...data, content })
|
setData({ ...data, content })
|
||||||
}, [content])
|
}, [content])
|
||||||
|
|
||||||
|
|
||||||
|
// 解析接口数据
|
||||||
|
const parsingData = async (command: string) => {
|
||||||
|
const res = await fetch(`/ai/v1/chat/completions`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": `Bearer ${import.meta.env.VITE_AI_APIPassword}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: import.meta.env.VITE_AI_MODEL,
|
||||||
|
messages: [{
|
||||||
|
role: "user",
|
||||||
|
content: `${command}${content}`
|
||||||
|
}],
|
||||||
|
stream: true
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader = res.body.getReader();
|
||||||
|
const decoder = new TextDecoder("utf-8");
|
||||||
|
|
||||||
|
let receivedText = "";
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) break;
|
||||||
|
receivedText += decoder.decode(value, { stream: true });
|
||||||
|
|
||||||
|
// 处理每一块数据
|
||||||
|
const lines = receivedText.split("\n");
|
||||||
|
for (let i = 0; i < lines.length - 1; i++) {
|
||||||
|
const line = lines[i].trim();
|
||||||
|
if (line.startsWith("data:")) {
|
||||||
|
const jsonString = line.substring(5).trim();
|
||||||
|
if (jsonString !== "[DONE]") {
|
||||||
|
const data = JSON.parse(jsonString);
|
||||||
|
console.log("Received chunk:", data.choices[0].delta.content);
|
||||||
|
setContent((content) => content + data.choices[0].delta.content);
|
||||||
|
// 在这里处理每一块数据
|
||||||
|
} else {
|
||||||
|
console.log("Stream finished.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留最后一行未处理的数据
|
||||||
|
receivedText = lines[lines.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AI功能
|
||||||
|
const items: MenuProps['items'] = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: 'AI 续写',
|
||||||
|
onClick: async () => {
|
||||||
|
parsingData("帮我续写:")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: 'AI 优化',
|
||||||
|
onClick: async () => {
|
||||||
|
parsingData("帮我优化该文章,意思不变:")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: 'AI 生成',
|
||||||
|
onClick: async () => {
|
||||||
|
parsingData("")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title value="创作" />
|
<Title value="创作" />
|
||||||
|
|||||||
3
src/types/env.d.ts
vendored
3
src/types/env.d.ts
vendored
@@ -4,6 +4,9 @@ interface ImportMetaEnv {
|
|||||||
readonly VITE_BAIDU_TONGJI_SITE_ID: string;
|
readonly VITE_BAIDU_TONGJI_SITE_ID: string;
|
||||||
readonly VITE_BAIDU_TONGJI_ACCESS_TOKEN: string;
|
readonly VITE_BAIDU_TONGJI_ACCESS_TOKEN: string;
|
||||||
readonly VITE_BAIDU_TONGJI_REFRESH_TOKEN: string;
|
readonly VITE_BAIDU_TONGJI_REFRESH_TOKEN: string;
|
||||||
|
|
||||||
|
readonly VITE_AI_APIPassword: string;
|
||||||
|
readonly VITE_AI_MODEL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
|
|||||||
@@ -24,15 +24,20 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'https://openapi.baidu.com/', // 你的后端服务器地址
|
target: 'https://openapi.baidu.com/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
},
|
},
|
||||||
'/qiniu': {
|
'/qiniu': {
|
||||||
target: 'https://rsf.qiniuapi.com/', // 你的后端服务器地址
|
target: 'https://rsf.qiniuapi.com/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/qiniu/, ''),
|
rewrite: (path) => path.replace(/^\/qiniu/, ''),
|
||||||
},
|
},
|
||||||
|
'/ai': {
|
||||||
|
target: 'https://spark-api-open.xf-yun.com/',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/ai/, ''),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user