Skip to content

Commit d7d425d

Browse files
committed
feat: 重构提示词的拼接逻辑
1 parent e4db5cb commit d7d425d

File tree

3 files changed

+94
-29
lines changed

3 files changed

+94
-29
lines changed

src/pages/CopyButton.tsx

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ import Snackbar from '@mui/material/Snackbar';
44
import Alert from '@mui/material/Alert';
55
import {FileInfo} from "../types/types.ts";
66
import {keyframes} from '@mui/system';
7+
import {calculateTokenCount, formatTokenCount, generatePrompt} from "../utils/promptBuilder";
78

89
interface CopyButtonProps {
9-
content: string;
10+
roleContent: string;
11+
ruleContent: string;
12+
taskContent: string;
13+
outputContent: string;
1014
files: FileInfo[];
1115
}
1216

@@ -25,41 +29,33 @@ const breathAnimation = keyframes`
2529
}
2630
`;
2731

28-
const formatTokenCount = (count: number): string => {
29-
if (count >= 10000) {
30-
return `${(count / 10000).toFixed(1).replace(/\.0$/, '')}万`;
31-
}
32-
if (count >= 1000) {
33-
return `${(count / 1000).toFixed(1).replace(/\.0$/, '')}k`;
34-
}
35-
return count.toString();
36-
};
37-
38-
const CopyButton: React.FC<CopyButtonProps> = ({content, files}) => {
32+
const CopyButton: React.FC<CopyButtonProps> = ({
33+
roleContent,
34+
ruleContent,
35+
taskContent,
36+
outputContent,
37+
files
38+
}) => {
3939
const [open, setOpen] = useState(false);
4040
const [message, setMessage] = useState<{ text: string; severity: 'success' | 'error' }>({
4141
text: '',
4242
severity: 'success',
4343
});
4444

45-
const tokenCount = useMemo(() => {
46-
const filesContent = files.map(file =>
47-
`\`\`\`${file.path}\n${file.content}\n\`\`\``
48-
).join('\n\n');
49-
const totalContent = `${content}\n\n${filesContent}`;
50-
return Math.ceil(totalContent.length / 4);
51-
}, [content, files]);
45+
const tokenCount = useMemo(() =>
46+
calculateTokenCount(roleContent, ruleContent, taskContent, outputContent, files),
47+
[roleContent, ruleContent, taskContent, outputContent, files]
48+
);
5249

53-
const formattedToken = useMemo(() => formatTokenCount(tokenCount), [tokenCount]);
50+
const formattedToken = useMemo(() =>
51+
formatTokenCount(tokenCount),
52+
[tokenCount]);
5453

5554
const handleCopy = async () => {
56-
const filesContent = files.map(file =>
57-
`\`\`\`${file.path}\n${file.content}\n\`\`\``
58-
).join('\n\n');
59-
6055
try {
61-
await navigator.clipboard.writeText(`${content}\n\n${filesContent}`);
62-
setMessage({text: '内容已复制!', severity: 'success'});
56+
await navigator.clipboard.writeText(
57+
generatePrompt(roleContent, ruleContent, taskContent, outputContent, files)
58+
);
6359
} catch {
6460
setMessage({text: '复制失败', severity: 'error'});
6561
}

src/pages/MarkdownEditor.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({ruleContent, roleContent
117117
</SyntaxHighlighter>
118118
);
119119

120-
const combinedContent = `# 角色\n${roleContent}\n\n# 规则\n${ruleContent}\n\n# 任务\n${markdownContent}\n\n# 输出格式\n${outputContent}`;
121-
122120
return (
123121
<div className="editor-container">
124122
<FileUpload onFilesUploaded={handleFilesUploaded}/>
@@ -225,7 +223,13 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({ruleContent, roleContent
225223
</div>
226224

227225
<div className="copy-button-container">
228-
<CopyButton content={combinedContent} files={files}/>
226+
<CopyButton
227+
roleContent={roleContent}
228+
ruleContent={ruleContent}
229+
taskContent={markdownContent}
230+
outputContent={outputContent}
231+
files={files}
232+
/>
229233
</div>
230234
</div>
231235
);

src/utils/promptBuilder.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* 提示词构造工具函数
3+
* 包含提示词拼接和Token计算相关逻辑
4+
*/
5+
6+
import { FileInfo } from "../types/types.ts";
7+
8+
// 生成完整提示词内容(优化核心算法)
9+
export const generatePrompt = (
10+
roleContent: string,
11+
ruleContent: string,
12+
taskContent: string,
13+
outputContent: string,
14+
files: FileInfo[]
15+
): string => {
16+
const contentSections = [
17+
`# 角色\n${roleContent.trim()}`,
18+
`# 规则\n${ruleContent.trim()}`,
19+
`# 任务\n${taskContent.trim()}`,
20+
`# 输出格式\n${outputContent.trim()}`
21+
].filter(section => section.split('\n')[1]?.trim().length > 0);
22+
23+
const fileSections = files
24+
.filter(file => file.content.trim().length > 0)
25+
.map(file => `\`\`\`${file.path}\n${file.content.trim()}\n\`\`\``);
26+
27+
return [...contentSections, ...fileSections]
28+
.filter(section => section.length > 0)
29+
.join('\n\n');
30+
};
31+
32+
// 增强型Token计算(保持向后兼容)
33+
export const calculateTokenCount = (
34+
roleContent: string,
35+
ruleContent: string,
36+
taskContent: string,
37+
outputContent: string,
38+
files: FileInfo[]
39+
): number => {
40+
const mergedContent = [
41+
roleContent.trim(),
42+
ruleContent.trim(),
43+
taskContent.trim(),
44+
outputContent.trim(),
45+
...files.map(f => f.content.trim())
46+
].join('\n\n');
47+
48+
return Math.ceil(mergedContent.replace(/[\r\n]/g, '').length / 3.5);
49+
};
50+
51+
// 优化显示格式化(支持国际化扩展)
52+
export const formatTokenCount = (count: number): string => {
53+
const formatWithUnit = (value: number, unit: string) =>
54+
`${value.toFixed(1).replace(/\.0+$/, '')}${unit}`;
55+
56+
return count >= 10000 ? formatWithUnit(count / 10000, '万') :
57+
count >= 1000 ? formatWithUnit(count / 1000, 'k') :
58+
count.toString();
59+
};
60+
61+
// 新增质量验证函数
62+
export const validatePromptStructure = (prompt: string): boolean => {
63+
const requiredSections = ['# 角色', '# 规则', '# 任务'];
64+
return requiredSections.every(section => prompt.includes(section));
65+
};

0 commit comments

Comments
 (0)