完善提示词管理和配置管理的增删改查
This commit is contained in:
+214
-214
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useSubmit, useNavigation } from "@remix-run/react";
|
||||
import { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs, json, redirect } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useNavigation, useActionData, Form } from "@remix-run/react";
|
||||
import { Button } from "~/components/ui/Button";
|
||||
import { PromptTemplate } from "./prompts._index";
|
||||
import newStyles from "~/styles/pages/prompts_new.css?url";
|
||||
import { getPromptTemplate, createPromptTemplate, updatePromptTemplate, type PromptTemplateUI } from "~/api/prompts/prompts";
|
||||
|
||||
// 样式链接
|
||||
export function links() {
|
||||
@@ -32,111 +32,34 @@ export const handle = {
|
||||
};
|
||||
|
||||
interface LoaderData {
|
||||
template: PromptTemplate;
|
||||
template: PromptTemplateUI | null;
|
||||
mode: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// 从模拟数据中获取模板
|
||||
const getTemplateById = (id: string): PromptTemplate | undefined => {
|
||||
// 与prompts._index.tsx中的模拟数据保持一致
|
||||
const MOCK_TEMPLATES: PromptTemplate[] = [
|
||||
{
|
||||
id: "1",
|
||||
template_name: "行政处罚-抽取通用模板",
|
||||
template_type: "Extraction",
|
||||
description: "本模板用于抽取行政处罚决定书编号等信息",
|
||||
version: "v1.0",
|
||||
status: "system",
|
||||
created_by: "system",
|
||||
template_content: `你是一个专业的文档信息抽取助手。请从以下{docType}文档中抽取关键信息:
|
||||
1. 处罚决定书编号
|
||||
2. 处罚对象名称
|
||||
3. 处罚事由
|
||||
4. 处罚依据
|
||||
5. 处罚内容
|
||||
6. 处罚金额
|
||||
7. 发文日期
|
||||
请将结果以JSON格式输出,包含以上字段。如果某个字段在文档中未找到,则该字段的值设为null。`,
|
||||
variables: JSON.stringify({ "docType": "文档类型" })
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
template_name: "销售合同-甲方信息评估",
|
||||
template_type: "Evaluation",
|
||||
description: "评估销售合同中甲方信息是否完整",
|
||||
version: "v1.2",
|
||||
status: "active",
|
||||
created_by: "admin",
|
||||
template_content: `你是一个专业的合同审核助手。请评估以下{docType}中甲方信息的完整性:
|
||||
请检查以下要素是否存在且完整:
|
||||
1. 甲方全称
|
||||
2. 注册地址
|
||||
3. 统一社会信用代码
|
||||
4. 法定代表人
|
||||
5. 联系方式
|
||||
请给出评估结果,并标明缺失或不完整的信息。`,
|
||||
variables: JSON.stringify({ "docType": "文档类型" })
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
template_name: "专卖许可证-摘要模板",
|
||||
template_type: "Summary",
|
||||
description: "生成专卖许可证申请文件的内容摘要",
|
||||
version: "v1.0",
|
||||
status: "active",
|
||||
created_by: "admin",
|
||||
template_content: `你是一个专业的文档摘要助手。请为以下{docType}生成一份简洁的摘要:
|
||||
摘要应包含以下要点:
|
||||
1. 申请人基本信息
|
||||
2. 许可证类型
|
||||
3. 申请事项
|
||||
4. 经营范围
|
||||
5. 申请日期
|
||||
请控制摘要在200字以内,保留关键信息。`,
|
||||
variables: JSON.stringify({ "docType": "文档类型" })
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
template_name: "采购合同-乙方资质抽取",
|
||||
template_type: "Extraction",
|
||||
description: "抽取采购合同中乙方的资质信息",
|
||||
// 定义本地表单数据接口
|
||||
interface FormDataState extends Omit<PromptTemplateUI, 'variables'> {
|
||||
variables: string; // 在表单状态中我们保存变量为 JSON 字符串
|
||||
}
|
||||
|
||||
version: "v1.1",
|
||||
status: "inactive",
|
||||
created_by: "zhangsan",
|
||||
template_content: `你是一个专业的合同信息抽取助手。请从以下{docType}中抽取乙方的资质信息:
|
||||
需要抽取的信息包括:
|
||||
1. 乙方全称
|
||||
2. 资质证书类型
|
||||
3. 资质证书编号
|
||||
4. 资质等级
|
||||
5. 证书有效期
|
||||
请将结果以JSON格式输出,包含以上字段。`,
|
||||
variables: JSON.stringify({ "docType": "文档类型" })
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
template_name: "合同通用-关键条款评估",
|
||||
template_type: "Evaluation",
|
||||
description: "评估合同中关键条款是否明确、合规",
|
||||
version: "v2.0",
|
||||
status: "active",
|
||||
created_by: "lisi",
|
||||
template_content: `你是一个专业的{industry}行业合同审核助手。请评估以下合同中的关键条款是否明确、合规:
|
||||
请重点关注以下条款:
|
||||
1. 合同标的
|
||||
2. 价格条款
|
||||
3. 付款条件
|
||||
4. 交付方式
|
||||
5. 违约责任
|
||||
6. 争议解决
|
||||
请对每一项给出评估结果,并指出不明确或存在风险的条款。`,
|
||||
variables: JSON.stringify({ "industry": "行业类型", "docType": "文档类型" })
|
||||
}
|
||||
];
|
||||
|
||||
return MOCK_TEMPLATES.find(t => t.id === id);
|
||||
};
|
||||
interface ActionData {
|
||||
success?: boolean;
|
||||
errors?: {
|
||||
template_name?: string;
|
||||
template_type?: string;
|
||||
template_content?: string;
|
||||
general?: string;
|
||||
};
|
||||
formData?: {
|
||||
template_name: string;
|
||||
template_type: "Extraction" | "Evaluation" | "Summary" | "Common";
|
||||
description: string;
|
||||
template_content: string;
|
||||
variables: string;
|
||||
status: "active" | "inactive" | "system";
|
||||
version: string;
|
||||
};
|
||||
}
|
||||
|
||||
// 加载函数
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
@@ -149,25 +72,27 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
let template = null;
|
||||
|
||||
if (id) {
|
||||
// 实际应用中,这里应该调用API获取数据
|
||||
// const response = await fetch(`${process.env.API_BASE_URL}/api/prompt-templates/${id}`);
|
||||
// if (!response.ok) throw new Error(`获取提示词模板失败: ${response.status}`);
|
||||
// template = await response.json();
|
||||
// 从API获取数据
|
||||
const result = await getPromptTemplate(id);
|
||||
|
||||
// 使用模拟数据
|
||||
template = getTemplateById(id);
|
||||
if (result.error) {
|
||||
console.error('获取提示词模板失败:', result.error);
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
template = result.data || null;
|
||||
if (!template) {
|
||||
throw new Error(`未找到ID为${id}的模板`);
|
||||
}
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
return json<LoaderData>({
|
||||
template,
|
||||
mode
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("加载提示词模板失败:", error);
|
||||
return Response.json(
|
||||
return json<LoaderData>(
|
||||
{
|
||||
template: null,
|
||||
mode: "create",
|
||||
@@ -180,69 +105,102 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
|
||||
// Action函数 - 处理表单提交
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
const id = formData.get("id") as string;
|
||||
const template_name = formData.get("template_name") as string;
|
||||
const template_type = formData.get("template_type") as "Extraction" | "Evaluation" | "Summary" | "Common";
|
||||
const description = formData.get("description") as string;
|
||||
const template_content = formData.get("template_content") as string;
|
||||
const variables = formData.get("variables") as string;
|
||||
const status = formData.get("status") as string;
|
||||
const version = formData.get("version") as string;
|
||||
|
||||
const errors: ActionData["errors"] = {};
|
||||
|
||||
// 表单验证
|
||||
if (!template_name || template_name.trim() === "") {
|
||||
errors.template_name = "模板名称不能为空";
|
||||
}
|
||||
|
||||
if (!template_type) {
|
||||
errors.template_type = "请选择模板类型";
|
||||
}
|
||||
|
||||
if (!template_content || template_content.trim() === "") {
|
||||
errors.template_content = "模板内容不能为空";
|
||||
}
|
||||
|
||||
if (Object.keys(errors).length > 0) {
|
||||
return json({ errors });
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = await request.formData();
|
||||
const templateData = Object.fromEntries(formData);
|
||||
|
||||
// 表单验证
|
||||
const errors: Record<string, string> = {};
|
||||
|
||||
if (!templateData.template_name) {
|
||||
errors.template_name = "模板名称不能为空";
|
||||
}
|
||||
|
||||
if (!templateData.template_type) {
|
||||
errors.template_type = "请选择模板类型";
|
||||
}
|
||||
|
||||
if (!templateData.template_content) {
|
||||
errors.template_content = "模板内容不能为空";
|
||||
}
|
||||
|
||||
if (Object.keys(errors).length > 0) {
|
||||
return Response.json({ errors, success: false }, { status: 400 });
|
||||
}
|
||||
|
||||
// 实际应用中,这里应该调用API保存数据
|
||||
// const apiUrl = templateData.id
|
||||
// ? `${process.env.API_BASE_URL}/api/prompt-templates/${templateData.id}`
|
||||
// : `${process.env.API_BASE_URL}/api/prompt-templates`;
|
||||
//
|
||||
// const response = await fetch(apiUrl, {
|
||||
// method: templateData.id ? "PUT" : "POST",
|
||||
// headers: { "Content-Type": "application/json" },
|
||||
// body: JSON.stringify(templateData)
|
||||
// });
|
||||
//
|
||||
// if (!response.ok) throw new Error(`保存提示词模板失败: ${response.status}`);
|
||||
// const result = await response.json();
|
||||
|
||||
// 模拟API响应
|
||||
console.log("提交的模板数据:", templateData);
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "提示词模板保存成功",
|
||||
template: {
|
||||
...templateData,
|
||||
id: templateData.id || Math.random().toString(36).substring(2, 10),
|
||||
created_by: "当前用户",
|
||||
created_at: new Date().toISOString()
|
||||
// 准备变量数据
|
||||
let variablesData: Record<string, string> = {};
|
||||
try {
|
||||
if (variables) {
|
||||
variablesData = JSON.parse(variables);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('解析变量JSON失败:', e);
|
||||
}
|
||||
|
||||
// 准备API数据
|
||||
const apiTemplate: Partial<PromptTemplateUI> = {
|
||||
template_name,
|
||||
template_type,
|
||||
description,
|
||||
template_content,
|
||||
variables: variablesData,
|
||||
status: status === "active" ? "active" : "inactive",
|
||||
version: version || "v1.0"
|
||||
};
|
||||
|
||||
let result;
|
||||
if (id) {
|
||||
// 更新模板
|
||||
result = await updatePromptTemplate(id, apiTemplate);
|
||||
} else {
|
||||
// 创建模板
|
||||
result = await createPromptTemplate(apiTemplate);
|
||||
}
|
||||
|
||||
if (result.error) {
|
||||
return json({
|
||||
errors: { general: result.error },
|
||||
formData: {
|
||||
template_name,
|
||||
template_type,
|
||||
description,
|
||||
template_content,
|
||||
variables,
|
||||
status,
|
||||
version
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return redirect("/prompts");
|
||||
} catch (error) {
|
||||
console.error("保存提示词模板失败:", error);
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "保存提示词模板失败"
|
||||
return json({
|
||||
errors: {
|
||||
general: error instanceof Error ? error.message : "保存提示词模板失败"
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
formData: {
|
||||
template_name,
|
||||
template_type,
|
||||
description,
|
||||
template_content,
|
||||
variables,
|
||||
status,
|
||||
version
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 提取变量函数
|
||||
// 提取变量函数 例如:{var1} {var2} {var3}
|
||||
const extractVariables = (content: string) => {
|
||||
const regex = /{([^{}]+)}/g;
|
||||
const variables: Record<string, string> = {};
|
||||
@@ -260,13 +218,13 @@ const extractVariables = (content: string) => {
|
||||
|
||||
// 页面组件
|
||||
export default function PromptsNew() {
|
||||
const { template, mode } = useLoaderData<typeof loader>();
|
||||
const submit = useSubmit();
|
||||
const { template, mode, error } = useLoaderData<typeof loader>();
|
||||
const actionData = useActionData<ActionData>();
|
||||
const navigation = useNavigation();
|
||||
const isSubmitting = navigation.state === "submitting";
|
||||
|
||||
// 表单状态
|
||||
const [formData, setFormData] = useState<Partial<PromptTemplate>>({
|
||||
const [formData, setFormData] = useState<FormDataState>({
|
||||
id: "",
|
||||
template_name: "",
|
||||
template_type: "Common",
|
||||
@@ -274,7 +232,10 @@ export default function PromptsNew() {
|
||||
version: "v1.0",
|
||||
status: "active",
|
||||
template_content: "",
|
||||
variables: "{}"
|
||||
created_by: 1,
|
||||
variables: "{}",
|
||||
created_at: "",
|
||||
updated_at: ""
|
||||
});
|
||||
|
||||
// 模式状态
|
||||
@@ -282,43 +243,57 @@ export default function PromptsNew() {
|
||||
const [pageTitle, setPageTitle] = useState("新增提示词模板");
|
||||
|
||||
// 变量相关状态
|
||||
// 检测到的变量
|
||||
const [detectedVariables, setDetectedVariables] = useState<Record<string, string>>({});
|
||||
// 示例值
|
||||
const [exampleValues, setExampleValues] = useState<Record<string, string>>({});
|
||||
// 预览内容
|
||||
const [previewContent, setPreviewContent] = useState("");
|
||||
|
||||
// 初始化表单数据
|
||||
useEffect(() => {
|
||||
if (template) {
|
||||
if (actionData?.formData) {
|
||||
// 如果有保存失败的表单数据,使用它
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
...actionData.formData,
|
||||
variables: actionData.formData?.variables || "{}",
|
||||
status: actionData.formData?.status || "active"
|
||||
}));
|
||||
} else if (template) {
|
||||
// 否则使用模板数据
|
||||
const variablesJson = typeof template.variables === 'string'
|
||||
? template.variables
|
||||
: JSON.stringify(template.variables);
|
||||
|
||||
const newFormData = {
|
||||
...template,
|
||||
// 如果是克隆模式,则清除ID并修改名称
|
||||
id: mode === "clone" ? "" : template.id,
|
||||
template_name: mode === "clone" ? `${template.template_name} (副本)` : template.template_name,
|
||||
// 如果是克隆模式,重置版本
|
||||
version: mode === "clone" ? "v1.0" : template.version
|
||||
version: mode === "clone" ? "v1.0" : template.version,
|
||||
variables: variablesJson
|
||||
};
|
||||
|
||||
setFormData(newFormData);
|
||||
|
||||
try {
|
||||
// 解析模板变量
|
||||
const vars = JSON.parse(template.variables);
|
||||
const vars = typeof template.variables === 'string'
|
||||
? JSON.parse(template.variables)
|
||||
: template.variables;
|
||||
|
||||
setExampleValues(vars);
|
||||
} catch (e) {
|
||||
console.error("解析变量失败:", e);
|
||||
}
|
||||
|
||||
// 检测模板内容中的变量
|
||||
if (template.template_content) {
|
||||
const vars = extractVariables(template.template_content);
|
||||
setDetectedVariables(vars);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置页面模式
|
||||
setIsViewMode(mode === "view");
|
||||
|
||||
// 设置页面标题
|
||||
if (mode === "view") {
|
||||
setPageTitle("查看提示词模板");
|
||||
} else if (mode === "edit") {
|
||||
@@ -328,7 +303,7 @@ export default function PromptsNew() {
|
||||
} else {
|
||||
setPageTitle("新增提示词模板");
|
||||
}
|
||||
}, [template, mode]);
|
||||
}, [template, mode, actionData?.formData]);
|
||||
|
||||
// 处理输入变化
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
@@ -337,16 +312,18 @@ export default function PromptsNew() {
|
||||
// 如果是模板内容,检测变量
|
||||
if (name === "template_content") {
|
||||
const vars = extractVariables(value);
|
||||
// console.log("检测到的变量:",vars);
|
||||
setDetectedVariables(vars);
|
||||
|
||||
// 更新变量JSON
|
||||
const varsJson = JSON.stringify(
|
||||
Object.keys(vars).reduce((acc, key) => {
|
||||
acc[key] = exampleValues[key] || key;
|
||||
acc[key] = exampleValues[key] || "";
|
||||
return acc;
|
||||
}, {} as Record<string, string>)
|
||||
);
|
||||
|
||||
// console.log("更新变量JSON:",varsJson);
|
||||
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
@@ -362,11 +339,19 @@ export default function PromptsNew() {
|
||||
|
||||
// 处理状态切换
|
||||
const handleStatusToggle = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// console.log("状态切换前:", formData.status);
|
||||
const status = e.target.checked ? "active" : "inactive";
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
status
|
||||
}));
|
||||
// console.log("新状态值:", status);
|
||||
|
||||
// 直接更新formData状态
|
||||
setFormData(prev => {
|
||||
const newState = {
|
||||
...prev,
|
||||
status: status as "active" | "inactive" | "system"
|
||||
};
|
||||
// console.log("状态更新后:", newState.status);
|
||||
return newState;
|
||||
});
|
||||
};
|
||||
|
||||
// 处理示例值变更
|
||||
@@ -383,7 +368,7 @@ export default function PromptsNew() {
|
||||
|
||||
// 替换变量
|
||||
Object.entries(detectedVariables).forEach(([key]) => {
|
||||
const exampleValue = exampleValues[key] || `[${key}]`;
|
||||
const exampleValue = exampleValues[key] || ``;
|
||||
const regex = new RegExp(`{${key}}`, 'g');
|
||||
content = content.replace(regex, exampleValue);
|
||||
});
|
||||
@@ -395,7 +380,7 @@ export default function PromptsNew() {
|
||||
useEffect(() => {
|
||||
const varsJson = JSON.stringify(
|
||||
Object.keys(detectedVariables).reduce((acc, key) => {
|
||||
acc[key] = exampleValues[key] || key;
|
||||
acc[key] = exampleValues[key] || "";
|
||||
return acc;
|
||||
}, {} as Record<string, string>)
|
||||
);
|
||||
@@ -405,23 +390,6 @@ export default function PromptsNew() {
|
||||
variables: varsJson
|
||||
}));
|
||||
}, [detectedVariables, exampleValues]);
|
||||
|
||||
// 处理表单提交
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (isViewMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formElement = e.target as HTMLFormElement;
|
||||
const submittingFormData = new FormData(formElement);
|
||||
|
||||
// 确保变量JSON被包含在提交中
|
||||
submittingFormData.set("variables", formData.variables || "{}");
|
||||
|
||||
submit(submittingFormData, { method: "post" });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="prompt-new-page">
|
||||
@@ -439,7 +407,7 @@ export default function PromptsNew() {
|
||||
type="primary"
|
||||
icon="ri-save-line"
|
||||
disabled={isSubmitting}
|
||||
onClick={() => document.getElementById("template-form")?.dispatchEvent(new Event("submit", { cancelable: true, bubbles: true }))}
|
||||
form="template-form"
|
||||
>
|
||||
{isSubmitting ? "保存中..." : "保存"}
|
||||
</Button>
|
||||
@@ -447,6 +415,21 @@ export default function PromptsNew() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 错误信息 */}
|
||||
{error && (
|
||||
<div className="alert alert-error mb-4">
|
||||
<i className="ri-error-warning-line"></i>
|
||||
<div>{error}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{actionData?.errors?.general && (
|
||||
<div className="alert alert-error mb-4">
|
||||
<i className="ri-error-warning-line"></i>
|
||||
<div>{actionData.errors.general}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 查看模式提示 */}
|
||||
{isViewMode && (
|
||||
<div className="alert alert-info">
|
||||
@@ -458,7 +441,7 @@ export default function PromptsNew() {
|
||||
)}
|
||||
|
||||
{/* 模板表单 */}
|
||||
<form id="template-form" method="post" onSubmit={handleSubmit}>
|
||||
<Form id="template-form" method="post">
|
||||
{/* 模板ID - 隐藏字段 */}
|
||||
<input type="hidden" name="id" value={formData.id || ''} />
|
||||
|
||||
@@ -474,7 +457,7 @@ export default function PromptsNew() {
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className={`form-input py-1 ${isViewMode ? 'read-only-field' : ''}`}
|
||||
className={`form-input py-1 ${isViewMode ? 'read-only-field' : ''} ${actionData?.errors?.template_name ? 'input-error' : ''}`}
|
||||
id="template-name"
|
||||
name="template_name"
|
||||
placeholder="请输入模板名称"
|
||||
@@ -483,6 +466,9 @@ export default function PromptsNew() {
|
||||
readOnly={isViewMode}
|
||||
required
|
||||
/>
|
||||
{actionData?.errors?.template_name && (
|
||||
<div className="error-message">{actionData.errors.template_name}</div>
|
||||
)}
|
||||
<div className="help-text text-xs">建议使用"文档类型-功能"的命名方式</div>
|
||||
</div>
|
||||
|
||||
@@ -492,7 +478,7 @@ export default function PromptsNew() {
|
||||
模板类型 <span className="text-error">*</span>
|
||||
</label>
|
||||
<select
|
||||
className={`form-select py-1 ${isViewMode ? 'read-only-field' : ''}`}
|
||||
className={`form-select py-1 ${isViewMode ? 'read-only-field' : ''} ${actionData?.errors?.template_type ? 'input-error' : ''}`}
|
||||
id="template-type"
|
||||
name="template_type"
|
||||
value={formData.template_type || ''}
|
||||
@@ -506,6 +492,9 @@ export default function PromptsNew() {
|
||||
<option value="Evaluation">评估(Evaluation) - 对文档内容进行评估</option>
|
||||
<option value="Summary">摘要(Summary) - 生成文档内容摘要</option>
|
||||
</select>
|
||||
{actionData?.errors?.template_type && (
|
||||
<div className="error-message">{actionData.errors.template_type}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 模板描述 */}
|
||||
@@ -535,15 +524,22 @@ export default function PromptsNew() {
|
||||
<input
|
||||
type="checkbox"
|
||||
id="status-toggle"
|
||||
name="status"
|
||||
checked={formData.status === 'active'}
|
||||
onChange={handleStatusToggle}
|
||||
disabled={isViewMode}
|
||||
/>
|
||||
{/* 移除name属性,只使用隐藏字段传递状态值 */}
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<span id="status-text">{formData.status === 'active' ? '启用' : '停用'}</span>
|
||||
|
||||
</div>
|
||||
{/* 使用隐藏字段传递状态值 */}
|
||||
<input
|
||||
type="hidden"
|
||||
name="status"
|
||||
value={formData.status}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 模板版本 */}
|
||||
@@ -584,7 +580,7 @@ export default function PromptsNew() {
|
||||
模板内容 <span className="text-error">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
className={`form-code-editor w-full ${isViewMode ? 'read-only-field' : ''}`}
|
||||
className={`form-code-editor w-full ${isViewMode ? 'read-only-field' : ''} ${actionData?.errors?.template_content ? 'input-error' : ''}`}
|
||||
id="template-content"
|
||||
name="template_content"
|
||||
placeholder="在此输入提示词模板内容..."
|
||||
@@ -594,6 +590,9 @@ export default function PromptsNew() {
|
||||
rows={15}
|
||||
required
|
||||
></textarea>
|
||||
{actionData?.errors?.template_content && (
|
||||
<div className="error-message">{actionData.errors.template_content}</div>
|
||||
)}
|
||||
<div className="help-text">提示词模板是AI完成特定任务的指令,请清晰描述任务需求和输出格式</div>
|
||||
</div>
|
||||
|
||||
@@ -642,6 +641,7 @@ export default function PromptsNew() {
|
||||
className="form-input"
|
||||
value={varName}
|
||||
readOnly
|
||||
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
@@ -703,7 +703,7 @@ export default function PromptsNew() {
|
||||
</Link>
|
||||
{!isViewMode && (
|
||||
<button
|
||||
type="submit"
|
||||
form="template-form"
|
||||
className="ant-btn ant-btn-primary"
|
||||
disabled={isSubmitting}
|
||||
id="save-btn-bottom"
|
||||
@@ -713,7 +713,7 @@ export default function PromptsNew() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user