完善提示词管理和配置管理的增删改查
This commit is contained in:
@@ -40,13 +40,13 @@ export const EXTENDED_ENVIRONMENT_LABELS: Record<string, string> = {
|
||||
};
|
||||
|
||||
interface ConfigData {
|
||||
id: string;
|
||||
id: number;
|
||||
name: string;
|
||||
type: string;
|
||||
environment: string;
|
||||
is_active: boolean;
|
||||
config: Record<string, unknown>;
|
||||
remarks?: string;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
interface LoaderData {
|
||||
@@ -76,11 +76,11 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
config = detailResponse.data;
|
||||
}
|
||||
|
||||
return json<LoaderData>({
|
||||
return Response.json({
|
||||
config,
|
||||
isEdit: !!config,
|
||||
types: optionsResponse.data.types,
|
||||
environments: optionsResponse.data.environments
|
||||
types: optionsResponse.data?.types || [],
|
||||
environments: optionsResponse.data?.environments || []
|
||||
});
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
const environment = formData.get("environment") as string;
|
||||
const config = formData.get("config") as string;
|
||||
const is_active = formData.get("is_active") === "true";
|
||||
const remarks = formData.get("remarks") as string;
|
||||
const remark = formData.get("remark") as string;
|
||||
|
||||
const errors: ActionData["errors"] = {};
|
||||
|
||||
@@ -131,7 +131,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
}
|
||||
|
||||
if (Object.keys(errors).length > 0) {
|
||||
return json<ActionData>({ errors });
|
||||
return Response.json({ errors });
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -141,7 +141,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
environment,
|
||||
config: JSON.parse(config),
|
||||
is_active,
|
||||
remarks
|
||||
remark
|
||||
};
|
||||
|
||||
if (id) {
|
||||
@@ -161,7 +161,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
return redirect("/config-lists");
|
||||
} catch (error) {
|
||||
console.error("保存配置失败:", error);
|
||||
return json<ActionData>({
|
||||
return Response.json({
|
||||
success: false,
|
||||
errors: {
|
||||
general: "保存配置失败,请稍后重试"
|
||||
@@ -170,18 +170,17 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
// JSON模板数据
|
||||
const JSON_TEMPLATES = {
|
||||
// 配置模板常量
|
||||
const CONFIG_TEMPLATES = {
|
||||
database: {
|
||||
database: {
|
||||
host: "localhost",
|
||||
port: 5432,
|
||||
username: "db_user",
|
||||
password: "******",
|
||||
name: "app_database",
|
||||
pool_size: 10,
|
||||
timeout: 5000,
|
||||
ssl: false
|
||||
host: "localhost",
|
||||
port: 5432,
|
||||
database: "mydb",
|
||||
username: "admin",
|
||||
password: "******",
|
||||
pool: {
|
||||
min: 2,
|
||||
max: 10
|
||||
}
|
||||
},
|
||||
file: {
|
||||
@@ -220,6 +219,9 @@ export default function ConfigNew() {
|
||||
const [selectedModule, setSelectedModule] = useState<string>("");
|
||||
const [selectedEnvironment, setSelectedEnvironment] = useState<string>("");
|
||||
|
||||
// 在 ConfigNew 组件中添加状态来跟踪当前选中的模板
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<keyof typeof CONFIG_TEMPLATES | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 初始化配置数据
|
||||
if (config) {
|
||||
@@ -268,6 +270,7 @@ export default function ConfigNew() {
|
||||
|
||||
// 格式化JSON
|
||||
const handleFormatJson = () => {
|
||||
|
||||
if (configDataValue.trim() === "") return;
|
||||
|
||||
try {
|
||||
@@ -283,50 +286,6 @@ export default function ConfigNew() {
|
||||
}
|
||||
};
|
||||
|
||||
// 加载JSON模板
|
||||
const handleLoadTemplate = (type: keyof typeof JSON_TEMPLATES) => {
|
||||
const template = JSON_TEMPLATES[type];
|
||||
setConfigDataValue(JSON.stringify(template, null, 2));
|
||||
setJsonError(null);
|
||||
};
|
||||
|
||||
// 显示JSON语法高亮
|
||||
const renderJsonWithSyntaxHighlight = (json: string) => {
|
||||
try {
|
||||
// 如果是空字符串,直接返回
|
||||
if (!json.trim()) return "";
|
||||
|
||||
// 解析并格式化JSON
|
||||
const parsed = JSON.parse(json);
|
||||
const formatted = JSON.stringify(parsed, null, 2);
|
||||
|
||||
// 添加语法高亮
|
||||
return formatted
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, (match) => {
|
||||
let cls = 'number';
|
||||
if (/^"/.test(match)) {
|
||||
if (/:$/.test(match)) {
|
||||
cls = 'key';
|
||||
match = match.replace(':', '');
|
||||
} else {
|
||||
cls = 'string';
|
||||
}
|
||||
} else if (/true|false/.test(match)) {
|
||||
cls = 'boolean';
|
||||
} else if (/null/.test(match)) {
|
||||
cls = 'null';
|
||||
}
|
||||
return `<span class="code-json ${cls}">${match}</span>`;
|
||||
});
|
||||
} catch (e) {
|
||||
// 如果解析失败,返回原始JSON
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="config-new-page">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
@@ -342,6 +301,12 @@ export default function ConfigNew() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{actionData?.errors?.general && (
|
||||
<div className="mb-4 w-full">
|
||||
<div className="error-message general-error">{actionData.errors.general}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Card className="config-form-card">
|
||||
<Form method="post" id="configForm" className="config-form">
|
||||
@@ -412,7 +377,7 @@ export default function ConfigNew() {
|
||||
<div className="error-message">{actionData.errors.type}</div>
|
||||
)}
|
||||
<div className="tag-buttons mt-2">
|
||||
{types.map(type => (
|
||||
{types.map((type: string) => (
|
||||
<button
|
||||
key={type}
|
||||
type="button"
|
||||
@@ -449,7 +414,7 @@ export default function ConfigNew() {
|
||||
<div className="error-message">{actionData.errors.environment}</div>
|
||||
)}
|
||||
<div className="tag-buttons mt-2">
|
||||
{environments.map(env => (
|
||||
{environments.map((env: string) => (
|
||||
<button
|
||||
key={env}
|
||||
type="button"
|
||||
@@ -484,7 +449,10 @@ export default function ConfigNew() {
|
||||
<Button
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={handleFormatJson}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleFormatJson();
|
||||
}}
|
||||
>
|
||||
<i className="ri-braces-line mr-1"></i> 格式化JSON
|
||||
</Button>
|
||||
@@ -501,32 +469,62 @@ export default function ConfigNew() {
|
||||
<div className="example-title">配置示例</div>
|
||||
</div>
|
||||
<div className="example-content">
|
||||
<pre
|
||||
className="example-pre"
|
||||
dangerouslySetInnerHTML={{ __html: renderJsonWithSyntaxHighlight(exampleJsonValue) }}
|
||||
/>
|
||||
<div className="json-display">
|
||||
{exampleJsonValue.split('\n').map((line, index) => (
|
||||
<div key={index} className="json-line">
|
||||
{line.split('').map((char, charIndex) => {
|
||||
let className = 'json-char';
|
||||
if (char === '{' || char === '}') className += ' json-brace';
|
||||
if (char === '[' || char === ']') className += ' json-bracket';
|
||||
if (char === '"') className += ' json-quote';
|
||||
if (char === ':') className += ' json-colon';
|
||||
if (char === ',') className += ' json-comma';
|
||||
return (
|
||||
<span key={charIndex} className={className}>
|
||||
{char}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="example-footer">
|
||||
<div className="text-sm font-medium mb-2">常用配置模板:</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
type="default"
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={() => handleLoadTemplate('database')}
|
||||
className={`${selectedTemplate === 'database' ? 'border-[#00684a] text-[#00684a] focus:ring-0' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setExampleJsonValue(JSON.stringify(CONFIG_TEMPLATES.database, null, 2));
|
||||
setSelectedTemplate('database');
|
||||
}}
|
||||
>
|
||||
数据库配置
|
||||
</Button>
|
||||
<Button
|
||||
type="default"
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={() => handleLoadTemplate('file')}
|
||||
className={`${selectedTemplate === 'file' ? 'border-[#00684a] text-[#00684a] focus:ring-0' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setExampleJsonValue(JSON.stringify(CONFIG_TEMPLATES.file, null, 2));
|
||||
setSelectedTemplate('file');
|
||||
}}
|
||||
>
|
||||
文件存储配置
|
||||
</Button>
|
||||
<Button
|
||||
type="default"
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={() => handleLoadTemplate('ai')}
|
||||
className={`${selectedTemplate === 'ai' ? 'border-[#00684a] text-[#00684a] focus:ring-0' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setExampleJsonValue(JSON.stringify(CONFIG_TEMPLATES.ai, null, 2));
|
||||
setSelectedTemplate('ai');
|
||||
}}
|
||||
>
|
||||
AI服务配置
|
||||
</Button>
|
||||
@@ -542,12 +540,12 @@ export default function ConfigNew() {
|
||||
|
||||
{/* 备注 */}
|
||||
<div className="form-group">
|
||||
<label htmlFor="remarks" className="form-label">备注</label>
|
||||
<label htmlFor="remark" className="form-label">备注</label>
|
||||
<textarea
|
||||
id="remarks"
|
||||
name="remarks"
|
||||
id="remark"
|
||||
name="remark"
|
||||
className="form-textarea"
|
||||
defaultValue={config?.remarks || ''}
|
||||
defaultValue={config?.remark || ''}
|
||||
rows={2}
|
||||
placeholder="请输入配置备注信息"
|
||||
/>
|
||||
@@ -556,11 +554,7 @@ export default function ConfigNew() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{actionData?.errors?.general && (
|
||||
<div className="form-row">
|
||||
<div className="error-message general-error">{actionData.errors.general}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</Form>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user