代码优化
This commit is contained in:
@@ -3,6 +3,8 @@ import {
|
||||
GetContentItemListParams,
|
||||
CreateContentItemParams,
|
||||
UpdateContentItemParams,
|
||||
AIRewriteParams,
|
||||
ReplaceContentParams,
|
||||
} from "./data";
|
||||
|
||||
// 获取素材列表
|
||||
@@ -35,3 +37,13 @@ export function deleteContentItem(id: string) {
|
||||
export function getContentLibraryDetail(id: string) {
|
||||
return request("/v1/content/library/detail", { id }, "GET");
|
||||
}
|
||||
|
||||
// AI改写内容
|
||||
export function aiRewriteContent(params: AIRewriteParams) {
|
||||
return request("/v1/content/library/aiEditContent", params, "GET");
|
||||
}
|
||||
|
||||
// 替换原内容
|
||||
export function replaceContent(params: ReplaceContentParams) {
|
||||
return request("/v1/content/library/aiEditContent", params, "POST");
|
||||
}
|
||||
|
||||
@@ -104,3 +104,15 @@ export interface UpdateContentItemParams
|
||||
extends Partial<CreateContentItemParams> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// AI改写参数
|
||||
export interface AIRewriteParams {
|
||||
id: string;
|
||||
aiPrompt: string;
|
||||
}
|
||||
|
||||
// 替换内容参数
|
||||
export interface ReplaceContentParams {
|
||||
id: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
@@ -613,3 +613,145 @@
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
// AI改写弹框样式
|
||||
.ai-popup-content {
|
||||
padding: 20px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
background: #f9fbfd;
|
||||
|
||||
.ai-popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #e8f4ff;
|
||||
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #1677ff;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 18px;
|
||||
background: #1677ff;
|
||||
margin-right: 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-form {
|
||||
.ai-form-item {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.ai-form-label {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
background: #1677ff;
|
||||
margin-right: 6px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.ai-result-description {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.ai-submit {
|
||||
margin: 24px 0;
|
||||
|
||||
button {
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(22, 119, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.ai-result-box {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e0f0ff;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
min-height: 150px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.ai-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.ai-result-content {
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
color: #333;
|
||||
white-space: pre-wrap;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.ai-result-placeholder {
|
||||
color: #999;
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.placeholder-icon {
|
||||
font-size: 28px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-replace-action {
|
||||
margin-top: 20px;
|
||||
|
||||
button {
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
background: #52c41a;
|
||||
border-color: #52c41a;
|
||||
box-shadow: 0 2px 6px rgba(82, 196, 26, 0.2);
|
||||
|
||||
&:hover, &:focus {
|
||||
background: #73d13d;
|
||||
border-color: #73d13d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { Toast, SpinLoading, Dialog, Card } from "antd-mobile";
|
||||
import { Input, Pagination, Button } from "antd";
|
||||
import { Toast, SpinLoading, Dialog, Card, Popup, TextArea } from "antd-mobile";
|
||||
import { Input, Pagination, Button, Spin } from "antd";
|
||||
import {
|
||||
PlusOutlined,
|
||||
SearchOutlined,
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from "@ant-design/icons";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import NavCommon from "@/components/NavCommon";
|
||||
import { getContentItemList, deleteContentItem } from "./api";
|
||||
import { getContentItemList, deleteContentItem, aiRewriteContent, replaceContent } from "./api";
|
||||
import { ContentItem } from "./data";
|
||||
import style from "./index.module.scss";
|
||||
|
||||
@@ -42,6 +42,14 @@ const MaterialsList: React.FC = () => {
|
||||
const [total, setTotal] = useState(0);
|
||||
const pageSize = 20;
|
||||
|
||||
// AI改写相关状态
|
||||
const [showAIRewritePopup, setShowAIRewritePopup] = useState(false);
|
||||
const [currentMaterial, setCurrentMaterial] = useState<ContentItem | null>(null);
|
||||
const [aiPrompt, setAiPrompt] = useState("");
|
||||
const [aiResult, setAiResult] = useState("");
|
||||
const [aiLoading, setAiLoading] = useState(false);
|
||||
const [replaceLoading, setReplaceLoading] = useState(false);
|
||||
|
||||
// 获取素材列表
|
||||
const fetchMaterials = useCallback(async () => {
|
||||
if (!id) return;
|
||||
@@ -104,9 +112,75 @@ const MaterialsList: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleView = (materialId: number) => {
|
||||
// 可以跳转到素材详情页面或显示弹窗
|
||||
console.log("查看素材:", materialId);
|
||||
const handleAIRewrite = (material: ContentItem) => {
|
||||
setCurrentMaterial(material);
|
||||
setAiPrompt("重写这条朋友圈 要求: 1、原本的字数和意思不要修改超过10% 2、出现品牌名或个人名字就去除 3、适当的换行及加些表情点缀");
|
||||
setAiResult("");
|
||||
setShowAIRewritePopup(true);
|
||||
};
|
||||
|
||||
const handleSubmitAIRewrite = async () => {
|
||||
if (!currentMaterial) return;
|
||||
|
||||
try {
|
||||
setAiLoading(true);
|
||||
const response = await aiRewriteContent({
|
||||
id: currentMaterial.id.toString(),
|
||||
aiPrompt: aiPrompt
|
||||
});
|
||||
|
||||
setAiResult(response.contentAfter || "暂无改写结果");
|
||||
|
||||
// 可以在这里显示原内容和改写后内容的对比
|
||||
console.log("原内容:", response.contentFront);
|
||||
console.log("改写后内容:", response.contentAfter);
|
||||
} catch (error) {
|
||||
console.error("AI改写失败:", error);
|
||||
Toast.show({
|
||||
content: "AI改写失败,请重试",
|
||||
position: "top",
|
||||
});
|
||||
} finally {
|
||||
setAiLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReplaceContent = async () => {
|
||||
if (!currentMaterial || !aiResult) return;
|
||||
|
||||
try {
|
||||
setReplaceLoading(true);
|
||||
await replaceContent({
|
||||
id: currentMaterial.id.toString(),
|
||||
content: aiResult
|
||||
});
|
||||
|
||||
Toast.show({
|
||||
content: "内容已成功替换",
|
||||
position: "top",
|
||||
});
|
||||
|
||||
// 刷新素材列表
|
||||
fetchMaterials();
|
||||
|
||||
// 关闭弹窗
|
||||
closeAIRewritePopup();
|
||||
} catch (error) {
|
||||
console.error("替换内容失败:", error);
|
||||
Toast.show({
|
||||
content: "替换内容失败,请重试",
|
||||
position: "top",
|
||||
});
|
||||
} finally {
|
||||
setReplaceLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const closeAIRewritePopup = () => {
|
||||
setShowAIRewritePopup(false);
|
||||
setCurrentMaterial(null);
|
||||
setAiPrompt("");
|
||||
setAiResult("");
|
||||
};
|
||||
|
||||
const handleRefresh = () => {
|
||||
@@ -381,7 +455,7 @@ const MaterialsList: React.FC = () => {
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => handleView(material.id)}
|
||||
onClick={() => handleAIRewrite(material)}
|
||||
className={style["action-btn"]}
|
||||
>
|
||||
<BarChartOutlined />
|
||||
@@ -402,6 +476,100 @@ const MaterialsList: React.FC = () => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* AI改写弹框 */}
|
||||
<Popup
|
||||
visible={showAIRewritePopup}
|
||||
onMaskClick={closeAIRewritePopup}
|
||||
bodyStyle={{
|
||||
borderRadius: "16px 16px 0 0",
|
||||
maxHeight: "90vh",
|
||||
boxShadow: "0 -4px 12px rgba(0, 0, 0, 0.1)"
|
||||
}}
|
||||
>
|
||||
<div className={style["ai-popup-content"]}>
|
||||
<div className={style["ai-popup-header"]}>
|
||||
<h3>AI内容改写</h3>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={closeAIRewritePopup}
|
||||
>
|
||||
关闭
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className={style["ai-form"]}>
|
||||
{/* 提示词输入区 */}
|
||||
<div className={style["ai-form-item"]}>
|
||||
<div className={style["ai-form-label"]}>提示词</div>
|
||||
<div className={style["ai-form-control"]}>
|
||||
<TextArea
|
||||
placeholder="请输入提示词指导AI如何改写内容"
|
||||
value={aiPrompt}
|
||||
onChange={val => setAiPrompt(val)}
|
||||
rows={4}
|
||||
showCount
|
||||
maxLength={500}
|
||||
style={{
|
||||
border: "1px solid #d9e8ff",
|
||||
borderRadius: "8px",
|
||||
padding: "12px",
|
||||
fontSize: "14px"
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style["ai-submit"]}>
|
||||
<Button
|
||||
block
|
||||
color="primary"
|
||||
onClick={handleSubmitAIRewrite}
|
||||
loading={aiLoading}
|
||||
disabled={aiLoading || !aiPrompt.trim()}
|
||||
>
|
||||
{aiLoading ? "生成中..." : "生成内容"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 改写结果区 */}
|
||||
<div className={style["ai-form-item"]}>
|
||||
<div className={style["ai-form-label"]}>改写结果</div>
|
||||
<div className={style["ai-result-description"]}>AI生成的内容将显示在下方区域</div>
|
||||
<div className={style["ai-result-box"]}>
|
||||
{aiLoading ? (
|
||||
<div className={style["ai-loading"]}>
|
||||
<Spin tip="AI正在思考中..." />
|
||||
</div>
|
||||
) : aiResult ? (
|
||||
<div className={style["ai-result-content"]}>
|
||||
{aiResult}
|
||||
</div>
|
||||
) : (
|
||||
<div className={style["ai-result-placeholder"]}>
|
||||
<div className={style["placeholder-icon"]}>✨</div>
|
||||
<div className={style["placeholder-text"]}>点击"生成内容"按钮获取AI改写结果</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 替换按钮 */}
|
||||
{aiResult && (
|
||||
<div className={style["ai-replace-action"]}>
|
||||
<Button
|
||||
block
|
||||
color="primary"
|
||||
onClick={handleReplaceContent}
|
||||
loading={replaceLoading}
|
||||
disabled={replaceLoading || !aiResult}
|
||||
>
|
||||
{replaceLoading ? "替换中..." : "替换原内容"}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user