正在显示
7 个修改的文件
包含
283 行增加
和
179 行删除
| @@ -452,45 +452,6 @@ export function BgPanel(props: PanelProps) { | @@ -452,45 +452,6 @@ export function BgPanel(props: PanelProps) { | ||
| 452 | 452 | ||
| 453 | return ( | 453 | return ( |
| 454 | <> | 454 | <> |
| 455 | - <ControlParamItem title={Locale.BgRemoval.subTitle}> | ||
| 456 | - <div className={styles["ai-models"]}> | ||
| 457 | - <IconButton | ||
| 458 | - text={Locale.BgRemoval.generateImg} | ||
| 459 | - type="primary" | ||
| 460 | - shadow | ||
| 461 | - onClick={handleGenerateImg} | ||
| 462 | - disabled={isLoading} | ||
| 463 | - /> | ||
| 464 | - <IconButton | ||
| 465 | - text={Locale.BgRemoval.bgRemoveBtn} | ||
| 466 | - type="primary" | ||
| 467 | - shadow | ||
| 468 | - onClick={() => handleProcessImage("visual/segmentation")} | ||
| 469 | - disabled={isLoading} | ||
| 470 | - /> | ||
| 471 | - <IconButton | ||
| 472 | - text={Locale.BgRemoval.downloadImg} | ||
| 473 | - type="primary" | ||
| 474 | - shadow | ||
| 475 | - onClick={handleDownload} | ||
| 476 | - disabled={!previewUrl} | ||
| 477 | - /> | ||
| 478 | - <IconButton | ||
| 479 | - text={Locale.BgRemoval.generateBg} | ||
| 480 | - type="primary" | ||
| 481 | - shadow | ||
| 482 | - onClick={() => handleProcessImage("visual/r-background")} | ||
| 483 | - disabled={isLoading} | ||
| 484 | - /> | ||
| 485 | - <IconButton | ||
| 486 | - text={Locale.BgRemoval.generateBg} | ||
| 487 | - type="primary" | ||
| 488 | - shadow | ||
| 489 | - onClick={() => console.log(Path.BgRemoval)} | ||
| 490 | - disabled={isLoading} | ||
| 491 | - /> | ||
| 492 | - </div> | ||
| 493 | - </ControlParamItem> | ||
| 494 | <ControlParamItem title={Locale.BgRemoval.promptTitle} required={true}> | 455 | <ControlParamItem title={Locale.BgRemoval.promptTitle} required={true}> |
| 495 | <div className={styles["prompt"]}> | 456 | <div className={styles["prompt"]}> |
| 496 | <textarea | 457 | <textarea |
| @@ -528,6 +489,38 @@ export function BgPanel(props: PanelProps) { | @@ -528,6 +489,38 @@ export function BgPanel(props: PanelProps) { | ||
| 528 | /> | 489 | /> |
| 529 | )} | 490 | )} |
| 530 | </ControlParamItem> | 491 | </ControlParamItem> |
| 492 | + <ControlParamItem title={Locale.BgRemoval.subTitle}> | ||
| 493 | + <div className={styles["ai-models"]}> | ||
| 494 | + <IconButton | ||
| 495 | + text={Locale.BgRemoval.generateImg} | ||
| 496 | + type="primary" | ||
| 497 | + shadow | ||
| 498 | + onClick={handleGenerateImg} | ||
| 499 | + disabled={isLoading} | ||
| 500 | + /> | ||
| 501 | + <IconButton | ||
| 502 | + text={Locale.BgRemoval.bgRemoveBtn} | ||
| 503 | + type="primary" | ||
| 504 | + shadow | ||
| 505 | + onClick={() => handleProcessImage("visual/segmentation")} | ||
| 506 | + disabled={isLoading} | ||
| 507 | + /> | ||
| 508 | + <IconButton | ||
| 509 | + text={Locale.BgRemoval.downloadImg} | ||
| 510 | + type="primary" | ||
| 511 | + shadow | ||
| 512 | + onClick={handleDownload} | ||
| 513 | + disabled={!previewUrl} | ||
| 514 | + /> | ||
| 515 | + <IconButton | ||
| 516 | + text={Locale.BgRemoval.generateBg} | ||
| 517 | + type="primary" | ||
| 518 | + shadow | ||
| 519 | + onClick={() => handleProcessImage("visual/r-background")} | ||
| 520 | + disabled={isLoading} | ||
| 521 | + /> | ||
| 522 | + </div> | ||
| 523 | + </ControlParamItem> | ||
| 531 | </> | 524 | </> |
| 532 | ); | 525 | ); |
| 533 | } | 526 | } |
| @@ -102,7 +102,7 @@ export function MindPage() { | @@ -102,7 +102,7 @@ export function MindPage() { | ||
| 102 | if (!content) return; | 102 | if (!content) return; |
| 103 | setIsLoading(true); | 103 | setIsLoading(true); |
| 104 | try { | 104 | try { |
| 105 | - const response = await chatStore.getMindData(newMessages, "gpt-4o-mini"); | 105 | + const response = await chatStore.sendContext(newMessages, "gpt-4o-mini"); |
| 106 | const cleanedContent = response.replace(/^```json|```$/g, ""); | 106 | const cleanedContent = response.replace(/^```json|```$/g, ""); |
| 107 | const parsedData: MindElixirData = JSON.parse(cleanedContent); | 107 | const parsedData: MindElixirData = JSON.parse(cleanedContent); |
| 108 | // 增强校验逻辑 | 108 | // 增强校验逻辑 |
| @@ -115,7 +115,6 @@ export function MindPage() { | @@ -115,7 +115,6 @@ export function MindPage() { | ||
| 115 | setData(parsedData); | 115 | setData(parsedData); |
| 116 | navigate(Path.Mind, { replace: true, state: { msg: null } }); | 116 | navigate(Path.Mind, { replace: true, state: { msg: null } }); |
| 117 | } catch (error) { | 117 | } catch (error) { |
| 118 | - console.log(error); | ||
| 119 | message.error("请求失败,请重试"); | 118 | message.error("请求失败,请重试"); |
| 120 | } finally { | 119 | } finally { |
| 121 | setIsLoading(false); // 确保关闭加载状态 | 120 | setIsLoading(false); // 确保关闭加载状态 |
app/components/writing/menuData.ts
0 → 100644
| 1 | +export const maxWord = 5000; | ||
| 2 | +export const minWord = 200; | ||
| 3 | + | ||
| 4 | +export const rewriteItems = [ | ||
| 5 | + "全文润色", | ||
| 6 | + "全文缩写", | ||
| 7 | + "全文扩写", | ||
| 8 | + "语气更专业", | ||
| 9 | + "语气更口语化", | ||
| 10 | + "语气更易读", | ||
| 11 | + "语气更含蓄", | ||
| 12 | + "语气更学术化", | ||
| 13 | + "语气更有文采", | ||
| 14 | + "语气更有网感", | ||
| 15 | +]; | ||
| 16 | + | ||
| 17 | +export const mergedData = [ | ||
| 18 | + { | ||
| 19 | + title: "写作用途", | ||
| 20 | + required: true, | ||
| 21 | + type: "select", | ||
| 22 | + default: "公司官网", | ||
| 23 | + options: [ | ||
| 24 | + { name: "公司官网", value: "100%" }, | ||
| 25 | + { name: "小红书", value: "400px" }, | ||
| 26 | + { name: "微信公众号", value: "300px" }, | ||
| 27 | + { name: "今日头条", value: "500px" }, | ||
| 28 | + ], | ||
| 29 | + }, | ||
| 30 | + { | ||
| 31 | + title: "图片模式", | ||
| 32 | + type: "select", | ||
| 33 | + required: false, | ||
| 34 | + default: "免费配图", | ||
| 35 | + options: [ | ||
| 36 | + { name: "免费配图", value: "free" }, | ||
| 37 | + { name: "收费配图", value: "paid" }, | ||
| 38 | + ], | ||
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + title: "写作风格", | ||
| 42 | + type: "select", | ||
| 43 | + required: false, | ||
| 44 | + default: "专业", | ||
| 45 | + options: [ | ||
| 46 | + { name: "专业", value: "professional" }, | ||
| 47 | + { name: "活泼", value: "lively" }, | ||
| 48 | + { name: "严谨", value: "strict" }, | ||
| 49 | + ], | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + title: "写作语言", | ||
| 53 | + type: "select", | ||
| 54 | + required: false, | ||
| 55 | + default: "中文", | ||
| 56 | + options: [ | ||
| 57 | + { name: "中文", value: "Chinese" }, | ||
| 58 | + { name: "英文", value: "English" }, | ||
| 59 | + { name: "法文", value: "French" }, | ||
| 60 | + { name: "德文", value: "German" }, | ||
| 61 | + ], | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + title: "写作类型", | ||
| 65 | + type: "select", | ||
| 66 | + required: false, | ||
| 67 | + default: "产品推广文案", | ||
| 68 | + options: [ | ||
| 69 | + { name: "产品推广文案", value: "promotion" }, | ||
| 70 | + { name: "品牌宣传文案", value: "propagandize" }, | ||
| 71 | + { name: "产品说明书", value: "instructionBook" }, | ||
| 72 | + { name: "产品介绍", value: "introduce" }, | ||
| 73 | + ], | ||
| 74 | + }, | ||
| 75 | + { | ||
| 76 | + title: "是否图文", | ||
| 77 | + type: "select", | ||
| 78 | + required: false, | ||
| 79 | + default: "是", | ||
| 80 | + options: [ | ||
| 81 | + { name: "是", value: "true" }, | ||
| 82 | + { name: "否", value: "false" }, | ||
| 83 | + ], | ||
| 84 | + }, | ||
| 85 | +]; | ||
| 86 | + | ||
| 87 | +// 20250408新增写作风格选项映射 | ||
| 88 | +export const getWritingStyleOptions = (purpose: string) => { | ||
| 89 | + switch (purpose) { | ||
| 90 | + case "公司官网": | ||
| 91 | + return [ | ||
| 92 | + { name: "专业", value: "professional" }, | ||
| 93 | + { name: "活泼", value: "lively" }, | ||
| 94 | + { name: "严谨", value: "strict" }, | ||
| 95 | + ]; | ||
| 96 | + case "小红书": | ||
| 97 | + return [ | ||
| 98 | + { name: "俏皮", value: "playful" }, | ||
| 99 | + { name: "幽默", value: "humorous" }, | ||
| 100 | + ]; | ||
| 101 | + case "微信公众号": | ||
| 102 | + return [ | ||
| 103 | + { name: "夸张", value: "exaggerated" }, | ||
| 104 | + { name: "可爱", value: "cute" }, | ||
| 105 | + ]; | ||
| 106 | + case "今日头条": | ||
| 107 | + return [ | ||
| 108 | + { name: "丰满", value: "full" }, | ||
| 109 | + { name: "可爱", value: "cute" }, | ||
| 110 | + { name: "健康", value: "healthy" }, | ||
| 111 | + ]; | ||
| 112 | + default: | ||
| 113 | + return [ | ||
| 114 | + { name: "专业", value: "professional" }, | ||
| 115 | + { name: "活泼", value: "lively" }, | ||
| 116 | + { name: "严谨", value: "strict" }, | ||
| 117 | + ]; | ||
| 118 | + } | ||
| 119 | +}; | ||
| 120 | + | ||
| 121 | +export interface writeMessage { | ||
| 122 | + role: string; | ||
| 123 | + content: string; | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +export interface WritePanelProps { | ||
| 127 | + htmlCode: string; | ||
| 128 | + setHtmlCode: React.Dispatch<React.SetStateAction<string>>; | ||
| 129 | + loading: boolean; | ||
| 130 | + setLoading: React.Dispatch<React.SetStateAction<boolean>>; | ||
| 131 | + setWidth: React.Dispatch<React.SetStateAction<string>>; | ||
| 132 | + setHtmlheader: React.Dispatch<React.SetStateAction<string>>; | ||
| 133 | +} |
| @@ -3,7 +3,7 @@ import { ControlParamItem } from "../sd"; | @@ -3,7 +3,7 @@ import { ControlParamItem } from "../sd"; | ||
| 3 | import { SideBarTail } from "@/app/components/sidebar"; | 3 | import { SideBarTail } from "@/app/components/sidebar"; |
| 4 | import { useState } from "react"; | 4 | import { useState } from "react"; |
| 5 | import { IconButton } from "../button"; | 5 | import { IconButton } from "../button"; |
| 6 | -import { message } from "antd"; | 6 | +import { message as msgModal } from "antd"; |
| 7 | import { useChatStore } from "@/app/store"; | 7 | import { useChatStore } from "@/app/store"; |
| 8 | import { getWrtingPrompt } from "@/app/utils/prompt"; | 8 | import { getWrtingPrompt } from "@/app/utils/prompt"; |
| 9 | import type { writePromptParam } from "@/app/types/prompt"; | 9 | import type { writePromptParam } from "@/app/types/prompt"; |
| @@ -11,119 +11,15 @@ import { processChatFile } from "@/app/utils/fileUtil"; | @@ -11,119 +11,15 @@ import { processChatFile } from "@/app/utils/fileUtil"; | ||
| 11 | import Locale from "@/app/locales"; | 11 | import Locale from "@/app/locales"; |
| 12 | import styles from "./wrtie-panel.module.scss"; | 12 | import styles from "./wrtie-panel.module.scss"; |
| 13 | import DeleteIcon from "@/app/icons/delete.svg"; | 13 | import DeleteIcon from "@/app/icons/delete.svg"; |
| 14 | +import { | ||
| 15 | + getWritingStyleOptions, | ||
| 16 | + maxWord, | ||
| 17 | + mergedData, | ||
| 18 | + minWord, | ||
| 19 | + writeMessage, | ||
| 20 | + WritePanelProps, | ||
| 21 | +} from "./menuData"; | ||
| 14 | 22 | ||
| 15 | -export const mergedData = [ | ||
| 16 | - { | ||
| 17 | - title: "写作用途", | ||
| 18 | - required: true, | ||
| 19 | - type: "select", | ||
| 20 | - default: "公司官网", | ||
| 21 | - options: [ | ||
| 22 | - { name: "公司官网", value: "100%" }, | ||
| 23 | - { name: "小红书", value: "400px" }, | ||
| 24 | - { name: "微信公众号", value: "300px" }, | ||
| 25 | - { name: "今日头条", value: "500px" }, | ||
| 26 | - ], | ||
| 27 | - }, | ||
| 28 | - { | ||
| 29 | - title: "图片模式", | ||
| 30 | - type: "select", | ||
| 31 | - required: false, | ||
| 32 | - default: "免费配图", | ||
| 33 | - options: [ | ||
| 34 | - { name: "免费配图", value: "free" }, | ||
| 35 | - { name: "收费配图", value: "paid" }, | ||
| 36 | - ], | ||
| 37 | - }, | ||
| 38 | - { | ||
| 39 | - title: "写作风格", | ||
| 40 | - type: "select", | ||
| 41 | - required: false, | ||
| 42 | - default: "专业", | ||
| 43 | - options: [ | ||
| 44 | - { name: "专业", value: "professional" }, | ||
| 45 | - { name: "活泼", value: "lively" }, | ||
| 46 | - { name: "严谨", value: "strict" }, | ||
| 47 | - ], | ||
| 48 | - }, | ||
| 49 | - { | ||
| 50 | - title: "写作语言", | ||
| 51 | - type: "select", | ||
| 52 | - required: false, | ||
| 53 | - default: "中文", | ||
| 54 | - options: [ | ||
| 55 | - { name: "中文", value: "Chinese" }, | ||
| 56 | - { name: "英文", value: "English" }, | ||
| 57 | - { name: "法文", value: "French" }, | ||
| 58 | - { name: "德文", value: "German" }, | ||
| 59 | - ], | ||
| 60 | - }, | ||
| 61 | - { | ||
| 62 | - title: "写作类型", | ||
| 63 | - type: "select", | ||
| 64 | - required: false, | ||
| 65 | - default: "产品推广文案", | ||
| 66 | - options: [ | ||
| 67 | - { name: "产品推广文案", value: "promotion" }, | ||
| 68 | - { name: "品牌宣传文案", value: "propagandize" }, | ||
| 69 | - { name: "产品说明书", value: "instructionBook" }, | ||
| 70 | - { name: "产品介绍", value: "introduce" }, | ||
| 71 | - ], | ||
| 72 | - }, | ||
| 73 | - { | ||
| 74 | - title: "是否图文", | ||
| 75 | - type: "select", | ||
| 76 | - required: false, | ||
| 77 | - default: "是", | ||
| 78 | - options: [ | ||
| 79 | - { name: "是", value: "true" }, | ||
| 80 | - { name: "否", value: "false" }, | ||
| 81 | - ], | ||
| 82 | - }, | ||
| 83 | -]; | ||
| 84 | - | ||
| 85 | -// 20250408新增写作风格选项映射 | ||
| 86 | -const getWritingStyleOptions = (purpose: string) => { | ||
| 87 | - switch (purpose) { | ||
| 88 | - case "公司官网": | ||
| 89 | - return [ | ||
| 90 | - { name: "专业", value: "professional" }, | ||
| 91 | - { name: "活泼", value: "lively" }, | ||
| 92 | - { name: "严谨", value: "strict" }, | ||
| 93 | - ]; | ||
| 94 | - case "小红书": | ||
| 95 | - return [ | ||
| 96 | - { name: "俏皮", value: "playful" }, | ||
| 97 | - { name: "幽默", value: "humorous" }, | ||
| 98 | - ]; | ||
| 99 | - case "微信公众号": | ||
| 100 | - return [ | ||
| 101 | - { name: "夸张", value: "exaggerated" }, | ||
| 102 | - { name: "可爱", value: "cute" }, | ||
| 103 | - ]; | ||
| 104 | - case "今日头条": | ||
| 105 | - return [ | ||
| 106 | - { name: "丰满", value: "full" }, | ||
| 107 | - { name: "可爱", value: "cute" }, | ||
| 108 | - { name: "健康", value: "healthy" }, | ||
| 109 | - ]; | ||
| 110 | - default: | ||
| 111 | - return [ | ||
| 112 | - { name: "专业", value: "professional" }, | ||
| 113 | - { name: "活泼", value: "lively" }, | ||
| 114 | - { name: "严谨", value: "strict" }, | ||
| 115 | - ]; | ||
| 116 | - } | ||
| 117 | -}; | ||
| 118 | - | ||
| 119 | -export interface WritePanelProps { | ||
| 120 | - htmlCode: string; | ||
| 121 | - setHtmlCode: React.Dispatch<React.SetStateAction<string>>; | ||
| 122 | - loading: boolean; | ||
| 123 | - setLoading: React.Dispatch<React.SetStateAction<boolean>>; | ||
| 124 | - setWidth: React.Dispatch<React.SetStateAction<string>>; | ||
| 125 | - setHtmlheader: React.Dispatch<React.SetStateAction<string>>; | ||
| 126 | -} | ||
| 127 | export function WritingPanel(props: WritePanelProps) { | 23 | export function WritingPanel(props: WritePanelProps) { |
| 128 | const { | 24 | const { |
| 129 | htmlCode, | 25 | htmlCode, |
| @@ -147,6 +43,7 @@ export function WritingPanel(props: WritePanelProps) { | @@ -147,6 +43,7 @@ export function WritingPanel(props: WritePanelProps) { | ||
| 147 | 43 | ||
| 148 | const [fileData, setFileData] = useState(""); | 44 | const [fileData, setFileData] = useState(""); |
| 149 | const [fileName, setFileName] = useState(""); | 45 | const [fileName, setFileName] = useState(""); |
| 46 | + const messages: writeMessage[] = []; | ||
| 150 | 47 | ||
| 151 | // 生成动态数据 | 48 | // 生成动态数据 |
| 152 | const dynamicMergedData = mergedData.map((item) => { | 49 | const dynamicMergedData = mergedData.map((item) => { |
| @@ -214,14 +111,14 @@ export function WritingPanel(props: WritePanelProps) { | @@ -214,14 +111,14 @@ export function WritingPanel(props: WritePanelProps) { | ||
| 214 | 111 | ||
| 215 | setFileName(name); | 112 | setFileName(name); |
| 216 | } catch { | 113 | } catch { |
| 217 | - message.error(Locale.ComError.UploadErr); | 114 | + msgModal.error(Locale.ComError.UploadErr); |
| 218 | } | 115 | } |
| 219 | }; | 116 | }; |
| 220 | 117 | ||
| 221 | // 提交表单时的处理函数 | 118 | // 提交表单时的处理函数 |
| 222 | const handleSubmit = async () => { | 119 | const handleSubmit = async () => { |
| 223 | if (!prompt.trim()) { | 120 | if (!prompt.trim()) { |
| 224 | - return message.error("请输入提示词"); | 121 | + return msgModal.error("请输入提示词"); |
| 225 | } | 122 | } |
| 226 | try { | 123 | try { |
| 227 | const param: writePromptParam = { | 124 | const param: writePromptParam = { |
| @@ -237,7 +134,13 @@ export function WritingPanel(props: WritePanelProps) { | @@ -237,7 +134,13 @@ export function WritingPanel(props: WritePanelProps) { | ||
| 237 | const input = getWrtingPrompt(param); | 134 | const input = getWrtingPrompt(param); |
| 238 | setLoading(true); | 135 | setLoading(true); |
| 239 | console.log("------------------------" + input); | 136 | console.log("------------------------" + input); |
| 240 | - const response = await chatStore.directLlmInvoke(input, "gpt-4o-mini"); | 137 | + |
| 138 | + messages.push({ role: "user", content: input }); | ||
| 139 | + | ||
| 140 | + const response = await chatStore.sendContext(messages, "gpt-4o-mini"); | ||
| 141 | + | ||
| 142 | + messages.push({ role: "assistant", content: response }); | ||
| 143 | + | ||
| 241 | let cleanedContent = response.startsWith("```html") | 144 | let cleanedContent = response.startsWith("```html") |
| 242 | ? response.substring(8) | 145 | ? response.substring(8) |
| 243 | : response; | 146 | : response; |
| @@ -256,9 +159,11 @@ export function WritingPanel(props: WritePanelProps) { | @@ -256,9 +159,11 @@ export function WritingPanel(props: WritePanelProps) { | ||
| 256 | setHtmlheader(contentUpToBody); //保存html头部 | 159 | setHtmlheader(contentUpToBody); //保存html头部 |
| 257 | } | 160 | } |
| 258 | localStorage.setItem("htmlCode", cleanedContent); | 161 | localStorage.setItem("htmlCode", cleanedContent); |
| 162 | + | ||
| 163 | + localStorage.setItem("aiWrite", JSON.stringify(messages)); | ||
| 259 | setHtmlCode(cleanedContent); | 164 | setHtmlCode(cleanedContent); |
| 260 | } catch (error) { | 165 | } catch (error) { |
| 261 | - message.error("生成失败,请重试"); | 166 | + msgModal.error("生成失败,请重试"); |
| 262 | } finally { | 167 | } finally { |
| 263 | setLoading(false); | 168 | setLoading(false); |
| 264 | } | 169 | } |
| @@ -319,9 +224,9 @@ export function WritingPanel(props: WritePanelProps) { | @@ -319,9 +224,9 @@ export function WritingPanel(props: WritePanelProps) { | ||
| 319 | <input | 224 | <input |
| 320 | aria-label="写作字数" | 225 | aria-label="写作字数" |
| 321 | type="number" | 226 | type="number" |
| 322 | - placeholder="200" | ||
| 323 | - min="200" | ||
| 324 | - max="5000" | 227 | + placeholder={String(minWord)} |
| 228 | + min={minWord} | ||
| 229 | + max={maxWord} | ||
| 325 | value={writingCount} | 230 | value={writingCount} |
| 326 | onChange={handleInputChange} | 231 | onChange={handleInputChange} |
| 327 | /> | 232 | /> |
| @@ -39,14 +39,14 @@ import PptIcon from "@/app/icons/ppt.svg"; | @@ -39,14 +39,14 @@ import PptIcon from "@/app/icons/ppt.svg"; | ||
| 39 | import PdfIcon from "@/app/icons/pdf.svg"; | 39 | import PdfIcon from "@/app/icons/pdf.svg"; |
| 40 | import HtmlIcon from "@/app/icons/HTML.svg"; | 40 | import HtmlIcon from "@/app/icons/HTML.svg"; |
| 41 | 41 | ||
| 42 | -import { message } from "antd"; | 42 | +import { Button, Dropdown, MenuProps, message as msgModal, Space } from "antd"; |
| 43 | import { HTMLPreview } from "../artifacts"; | 43 | import { HTMLPreview } from "../artifacts"; |
| 44 | import { getMindPrompt, getWrtingPrompt } from "@/app/utils/prompt"; | 44 | import { getMindPrompt, getWrtingPrompt } from "@/app/utils/prompt"; |
| 45 | import { htmlToPdf2 } from "@/app/utils/fileExport/toPdf"; | 45 | import { htmlToPdf2 } from "@/app/utils/fileExport/toPdf"; |
| 46 | import { hasTable, htmlToExcel } from "@/app/utils/fileExport/export2Excel"; | 46 | import { hasTable, htmlToExcel } from "@/app/utils/fileExport/export2Excel"; |
| 47 | import { writePromptParam } from "@/app/types/prompt"; | 47 | import { writePromptParam } from "@/app/types/prompt"; |
| 48 | -import { mergedData } from "./writie-panel"; | ||
| 49 | import dynamic from "next/dynamic"; | 48 | import dynamic from "next/dynamic"; |
| 49 | +import { rewriteItems, mergedData } from "./menuData"; | ||
| 50 | 50 | ||
| 51 | const EditorComponent = dynamic( | 51 | const EditorComponent = dynamic( |
| 52 | async () => (await import("./editor")).EditorComponent, | 52 | async () => (await import("./editor")).EditorComponent, |
| @@ -75,6 +75,23 @@ export function WritingPage() { | @@ -75,6 +75,23 @@ export function WritingPage() { | ||
| 75 | const query = useLocation(); //获取路由参数 | 75 | const query = useLocation(); //获取路由参数 |
| 76 | let { msg, writeMessage } = query.state || {}; //获取路由参数 | 76 | let { msg, writeMessage } = query.state || {}; //获取路由参数 |
| 77 | 77 | ||
| 78 | + const items: MenuProps["items"] = rewriteItems.map((item, index) => ({ | ||
| 79 | + key: (index + 1).toString(), | ||
| 80 | + label: ( | ||
| 81 | + <a | ||
| 82 | + target="_blank" | ||
| 83 | + rel="noopener noreferrer" | ||
| 84 | + href="#" | ||
| 85 | + onClick={(e) => { | ||
| 86 | + e.preventDefault(); // 阻止默认行为 | ||
| 87 | + rewrite(item); // 调用 rewrite 函数并传递菜单项文本 | ||
| 88 | + }} | ||
| 89 | + > | ||
| 90 | + {item} | ||
| 91 | + </a> | ||
| 92 | + ), | ||
| 93 | + })); | ||
| 94 | + | ||
| 78 | useEffect(() => { | 95 | useEffect(() => { |
| 79 | if (!msg) { | 96 | if (!msg) { |
| 80 | return; | 97 | return; |
| @@ -121,7 +138,7 @@ export function WritingPage() { | @@ -121,7 +138,7 @@ export function WritingPage() { | ||
| 121 | localStorage.setItem("htmlCode", cleanedContent); | 138 | localStorage.setItem("htmlCode", cleanedContent); |
| 122 | setHtmlCode(cleanedContent); | 139 | setHtmlCode(cleanedContent); |
| 123 | } catch (error) { | 140 | } catch (error) { |
| 124 | - message.error("生成失败,请重试"); | 141 | + msgModal.error("生成失败,请重试"); |
| 125 | } finally { | 142 | } finally { |
| 126 | setLoading(false); | 143 | setLoading(false); |
| 127 | } | 144 | } |
| @@ -159,11 +176,9 @@ export function WritingPage() { | @@ -159,11 +176,9 @@ export function WritingPage() { | ||
| 159 | const blob = new Blob([htmlCode], { type: "text/html" }); | 176 | const blob = new Blob([htmlCode], { type: "text/html" }); |
| 160 | const clipboardItem = new ClipboardItem({ "text/html": blob }); | 177 | const clipboardItem = new ClipboardItem({ "text/html": blob }); |
| 161 | await navigator.clipboard.write([clipboardItem]); | 178 | await navigator.clipboard.write([clipboardItem]); |
| 162 | - message.success("复制成功!"); | 179 | + msgModal.success("复制成功!"); |
| 163 | } catch (error) { | 180 | } catch (error) { |
| 164 | - console.log(error); | ||
| 165 | - | ||
| 166 | - message.error("复制失败"); | 181 | + msgModal.error("复制失败"); |
| 167 | } | 182 | } |
| 168 | }; | 183 | }; |
| 169 | //跳转到ppt页面 | 184 | //跳转到ppt页面 |
| @@ -211,12 +226,67 @@ export function WritingPage() { | @@ -211,12 +226,67 @@ export function WritingPage() { | ||
| 211 | a.download = fileName; | 226 | a.download = fileName; |
| 212 | a.click(); | 227 | a.click(); |
| 213 | URL.revokeObjectURL(url); | 228 | URL.revokeObjectURL(url); |
| 214 | - message.success("导出成功"); | 229 | + msgModal.success("导出成功"); |
| 215 | } catch (error) { | 230 | } catch (error) { |
| 216 | - message.error("导出失败"); | 231 | + msgModal.error("导出失败"); |
| 217 | } | 232 | } |
| 218 | }, [wrapContentInDivWithWidth]); | 233 | }, [wrapContentInDivWithWidth]); |
| 219 | 234 | ||
| 235 | + async function rewrite(msg: string) { | ||
| 236 | + const messagesStr = localStorage.getItem("aiWrite"); | ||
| 237 | + if (!messagesStr) return; | ||
| 238 | + | ||
| 239 | + let messages: any; | ||
| 240 | + try { | ||
| 241 | + messages = JSON.parse(messagesStr); | ||
| 242 | + } catch (error) { | ||
| 243 | + return; | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + // 检查是否是数组且包含合法 message 对象 | ||
| 247 | + if (!Array.isArray(messages)) return; | ||
| 248 | + if ( | ||
| 249 | + !messages.every( | ||
| 250 | + (m) => | ||
| 251 | + typeof m === "object" && | ||
| 252 | + m !== null && | ||
| 253 | + "role" in m && | ||
| 254 | + "content" in m && | ||
| 255 | + typeof m.role === "string" && | ||
| 256 | + typeof m.content === "string", | ||
| 257 | + ) | ||
| 258 | + ) | ||
| 259 | + return; | ||
| 260 | + try { | ||
| 261 | + setLoading(true); | ||
| 262 | + const response = await chatStore.sendContext(messages, "gpt-4o-mini"); | ||
| 263 | + messages.push({ role: "assistant", content: response }); | ||
| 264 | + | ||
| 265 | + let cleanedContent = response.startsWith("```html") | ||
| 266 | + ? response.substring(8) | ||
| 267 | + : response; | ||
| 268 | + if (cleanedContent.endsWith("```")) { | ||
| 269 | + cleanedContent = cleanedContent.substring(0, cleanedContent.length - 4); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + const bodyTagRegex = /<body[^>]*>/i; | ||
| 273 | + const bodyTagMatch = cleanedContent.match(bodyTagRegex); | ||
| 274 | + if (bodyTagMatch?.index !== undefined) { | ||
| 275 | + setHtmlheader( | ||
| 276 | + cleanedContent.slice(0, bodyTagMatch.index + bodyTagMatch[0].length), | ||
| 277 | + ); | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + localStorage.setItem("htmlCode", cleanedContent); | ||
| 281 | + localStorage.setItem("aiWrite", JSON.stringify(messages)); | ||
| 282 | + setHtmlCode(cleanedContent); | ||
| 283 | + } catch (error) { | ||
| 284 | + msgModal.error("重写失败,请重试"); | ||
| 285 | + } finally { | ||
| 286 | + setLoading(false); | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + | ||
| 220 | useEffect(() => { | 290 | useEffect(() => { |
| 221 | localStorage.setItem("htmlCode", htmlCode); | 291 | localStorage.setItem("htmlCode", htmlCode); |
| 222 | }, [htmlCode]); | 292 | }, [htmlCode]); |
| @@ -257,12 +327,18 @@ export function WritingPage() { | @@ -257,12 +327,18 @@ export function WritingPage() { | ||
| 257 | <div className={chatStyles["chat-message-actions"]}> | 327 | <div className={chatStyles["chat-message-actions"]}> |
| 258 | {htmlCode && ( | 328 | {htmlCode && ( |
| 259 | <div className={chatStyles["chat-input-actions"]}> | 329 | <div className={chatStyles["chat-input-actions"]}> |
| 260 | - <ChatAction | ||
| 261 | - text={Locale.Chat.Actions.ReWrite} | ||
| 262 | - icon={<ReloadIcon />} | ||
| 263 | - onClick={() => {}} | ||
| 264 | - disabled={isEdit} | ||
| 265 | - /> | 330 | + <Dropdown |
| 331 | + menu={{ items }} | ||
| 332 | + placement="bottom" | ||
| 333 | + arrow={{ pointAtCenter: true }} | ||
| 334 | + > | ||
| 335 | + <Button> | ||
| 336 | + <Space> | ||
| 337 | + <ReloadIcon /> | ||
| 338 | + {Locale.Chat.Actions.ReWrite} | ||
| 339 | + </Space> | ||
| 340 | + </Button> | ||
| 341 | + </Dropdown> | ||
| 266 | <ChatAction | 342 | <ChatAction |
| 267 | text={Locale.Chat.Actions.Copy} | 343 | text={Locale.Chat.Actions.Copy} |
| 268 | icon={<CopyIcon />} | 344 | icon={<CopyIcon />} |
| @@ -895,7 +895,7 @@ export const useChatStore = createPersistStore( | @@ -895,7 +895,7 @@ export const useChatStore = createPersistStore( | ||
| 895 | }); | 895 | }); |
| 896 | }, | 896 | }, |
| 897 | 897 | ||
| 898 | - async getMindData( | 898 | + async sendContext( |
| 899 | messages: Array<{ role: string; content: string }>, | 899 | messages: Array<{ role: string; content: string }>, |
| 900 | model: string, | 900 | model: string, |
| 901 | ): Promise<string> { | 901 | ): Promise<string> { |
| @@ -12,8 +12,6 @@ export function getWrtingPrompt(param: writePromptParam): string { | @@ -12,8 +12,6 @@ export function getWrtingPrompt(param: writePromptParam): string { | ||
| 12 | writingCount, | 12 | writingCount, |
| 13 | fileData, | 13 | fileData, |
| 14 | } = param; | 14 | } = param; |
| 15 | - console.log("********************", fileData); | ||
| 16 | - console.log("**********************", prompt); | ||
| 17 | 15 | ||
| 18 | // 根据用途调整文案类型描述 | 16 | // 根据用途调整文案类型描述 |
| 19 | const purposeMap: Record<string, string> = { | 17 | const purposeMap: Record<string, string> = { |
-
请 注册 或 登录 后发表评论