Files
leaudit-platform-frontend/html/配置-新增.html
T

627 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>中国烟草AI合同及卷宗审核系统 - 新增/编辑系统配置</title>
<link href="https://unpkg.com/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
<link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<!-- <link href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> -->
<!-- 引入外部CSS文件 -->
<link href="main.css" rel="stylesheet">
<style>
.json-editor {
width: 100%;
min-height: 320px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
font-size: 14px;
line-height: 1.6;
border: 1px solid #e2e8f0;
border-radius: 4px;
padding: 12px;
background-color: #f8f9fc;
color: #374151;
}
.editor-actions {
text-align: right;
margin-top: 8px;
}
.json-error {
color: #e53e3e;
margin-top: 8px;
font-size: 0.875rem;
}
.example-card {
height: 100%;
display: flex;
flex-direction: column;
background-color: #f8f9fc;
border-radius: 4px;
border: 1px solid #e2e8f0;
overflow: hidden;
}
.example-header {
padding: 12px;
border-bottom: 1px solid #e2e8f0;
background-color: #f1f5f9;
}
.example-title {
font-weight: 500;
color: #4a5568;
}
.example-content {
padding: 12px;
flex-grow: 1;
overflow: auto;
}
.example-pre {
margin: 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
font-size: 14px;
line-height: 1.6;
color: #374151;
}
.example-footer {
padding: 12px;
border-top: 1px solid #e2e8f0;
background-color: #f1f5f9;
}
/* 标签按钮样式 */
.tag-buttons {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
}
.tag-button {
display: inline-flex;
align-items: center;
padding: 4px 12px;
border-radius: 16px;
font-size: 12px;
background-color: #f3f4f6;
color: #4b5563;
border: 1px solid #e5e7eb;
cursor: pointer;
transition: all 0.2s;
}
.tag-button:hover {
background-color: rgba(0, 104, 74, 0.1);
border-color: var(--primary-color);
color: var(--primary-color);
}
.tag-button.active {
background-color: rgba(0, 104, 74, 0.15);
border-color: var(--primary-color);
color: var(--primary-color);
}
/* 代码语法高亮基础样式 */
.code-json .key { color: #07a; }
.code-json .string { color: #690; }
.code-json .number { color: #905; }
.code-json .boolean { color: #07a; }
.code-json .null { color: #999; }
</style>
</head>
<body>
<div class="layout-container">
<!-- 侧边栏 -->
<div class="sidebar">
<div class="py-6 px-4 border-b border-gray-100">
<div class="flex items-center">
<i class="ri-file-search-line text-primary text-xl mr-2"></i>
<h2 class="text-lg font-medium">AI审核系统</h2>
</div>
</div>
<div class="py-4">
<div class="sidebar-menu-item">
<a href="#" class="flex items-center text-sm font-medium">
<i class="ri-dashboard-line mr-3"></i>
<span>首页</span>
</a>
</div>
<div class="sidebar-menu-item">
<a href="#" class="flex items-center text-sm font-medium">
<i class="ri-file-upload-line mr-3"></i>
<span>文件上传</span>
</a>
</div>
<div class="sidebar-menu-item">
<a href="#" class="flex items-center text-sm font-medium">
<i class="ri-list-check-2 mr-3"></i>
<span>评查规则库</span>
</a>
</div>
<div class="sidebar-menu-item">
<a href="#" class="flex items-center text-sm font-medium">
<i class="ri-history-line mr-3"></i>
<span>审核历史</span>
</a>
</div>
<div class="sidebar-menu-item active">
<a href="#" class="flex items-center text-sm font-medium">
<i class="ri-settings-3-line mr-3"></i>
<span>系统设置</span>
</a>
</div>
</div>
</div>
<!-- 主内容区 -->
<div class="main-content">
<!-- 面包屑导航 -->
<div class="breadcrumb">
<span class="breadcrumb-item">首页</span>
<span class="breadcrumb-item">系统设置</span>
<span class="breadcrumb-item">系统配置管理</span>
<span class="breadcrumb-item" id="page-title">新增系统配置</span>
</div>
<!-- 页面头部 -->
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-medium" id="header-title">新增系统配置</h2>
<div>
<button class="ant-btn ant-btn-default mr-2" onclick="window.location.href='配置-列表.html'">
<i class="ri-arrow-left-line"></i> 返回
</button>
<button class="ant-btn ant-btn-primary" id="save-btn">
<i class="ri-save-line"></i> 保存
</button>
</div>
</div>
<!-- 表单 -->
<div class="ant-card">
<div class="ant-card-body">
<form id="config-form">
<div class="grid grid-cols-1 gap-6">
<!-- 配置名称和状态放在同一行 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="form-group">
<label class="form-label">配置名称 <span class="text-red-500">*</span></label>
<input type="text" class="form-input" id="config-name" name="config_name" placeholder="请输入配置名称(如:database_connection" required>
<div class="text-sm text-secondary mt-1">唯一标识符,建议使用下划线命名法</div>
</div>
<div class="form-group">
<label class="form-label">状态</label>
<div class="mt-2">
<label class="inline-flex items-center">
<input type="checkbox" class="form-checkbox" id="is-active" name="is_active" checked>
<span class="ml-2">启用此配置</span>
</label>
</div>
<div class="text-sm text-secondary mt-1">禁用配置后,系统将不会读取此配置</div>
</div>
</div>
<!-- 修改所属模块为输入框+标签按钮(使用中文显示) -->
<div class="form-group">
<label class="form-label">所属模块 <span class="text-red-500">*</span></label>
<input type="text" class="form-input" id="module" name="module" placeholder="请输入或选择所属模块" required>
<div class="tag-buttons" id="module-tags">
<span class="tag-button" data-value="system">系统</span>
<span class="tag-button" data-value="auth">认证</span>
<span class="tag-button" data-value="file">文件</span>
<span class="tag-button" data-value="ai">AI配置</span>
<span class="tag-button" data-value="notification">通知</span>
</div>
<div class="text-sm text-secondary mt-1">将配置按功能模块进行分类,便于管理和查找</div>
</div>
<!-- 修改环境为输入框+标签按钮(使用中文显示,增加通用选项) -->
<div class="form-group">
<label class="form-label">环境 <span class="text-red-500">*</span></label>
<input type="text" class="form-input" id="environment" name="environment" placeholder="请输入或选择环境" required>
<div class="tag-buttons" id="env-tags">
<span class="tag-button" data-value="dev">开发环境</span>
<span class="tag-button" data-value="test">测试环境</span>
<span class="tag-button" data-value="prod">生产环境</span>
<span class="tag-button" data-value="common">通用</span>
</div>
<div class="text-sm text-secondary mt-1">不同环境可以使用相同的配置名称,系统会自动识别当前环境并使用对应配置</div>
</div>
<!-- 修改配置数据为左右等高两栏布局 -->
<div class="form-group">
<label class="form-label">配置数据 (JSON) <span class="text-red-500">*</span></label>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4" style="min-height: 390px;">
<!-- 左侧JSON编辑区 -->
<div class="h-full">
<textarea class="json-editor" id="config-data" name="config_data" required placeholder='请输入JSON格式的配置数据'></textarea>
<div class="editor-actions">
<button type="button" class="ant-btn ant-btn-text" id="btn-format-json">
<i class="ri-braces-line"></i> 格式化JSON
</button>
</div>
<div id="json-error" class="json-error hidden"></div>
</div>
<!-- 右侧示例区 -->
<div class="h-full">
<div class="example-card">
<div class="example-header">
<div class="example-title">配置示例</div>
</div>
<div class="example-content">
<pre class="example-pre" id="example-json"></pre>
</div>
<div class="example-footer">
<div class="text-sm font-medium mb-2">常用配置模板:</div>
<div class="flex flex-wrap gap-2">
<button type="button" class="ant-btn ant-btn-sm" onclick="loadTemplateJson('database')">数据库配置</button>
<button type="button" class="ant-btn ant-btn-sm" onclick="loadTemplateJson('file')">文件存储配置</button>
<button type="button" class="ant-btn ant-btn-sm" onclick="loadTemplateJson('ai')">AI服务配置</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 备注移到最后 -->
<div class="form-group">
<label class="form-label">备注</label>
<textarea class="form-textarea" id="remarks" name="remarks" placeholder="请输入配置备注信息" rows="2"></textarea>
<div class="text-sm text-secondary mt-1">可选填项,用于描述配置的用途、注意事项等</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 获取页面参数
const urlParams = new URLSearchParams(window.location.search);
const configId = urlParams.get('id');
// 判断是新增还是编辑模式
if (configId) {
document.getElementById('page-title').textContent = '编辑系统配置';
document.getElementById('header-title').textContent = '编辑系统配置';
// 加载配置数据
// 实际应用中应通过AJAX请求获取数据
loadConfigData(configId);
}
// 初始化示例JSON
initExampleJson();
// 格式化JSON按钮点击事件
document.getElementById('btn-format-json').addEventListener('click', function() {
formatJSON();
});
// 保存按钮点击事件
document.getElementById('save-btn').addEventListener('click', function() {
saveConfig();
});
// 初始化标签按钮事件
initTagButtons();
});
// 初始化示例JSON
function initExampleJson() {
const exampleObj = {
database: {
host: "db.cluster.com",
port: 5432,
pool_size: 20,
ssl: true
},
cache: {
ttl: 3600,
max_entries: 1000
},
feature_flags: ["new_ui", "analytics_v2"]
};
const exampleElement = document.getElementById('example-json');
exampleElement.innerHTML = syntaxHighlightJson(JSON.stringify(exampleObj, null, 2));
}
// JSON语法高亮
function syntaxHighlightJson(json) {
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(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>';
});
}
// 初始化标签按钮事件
function initTagButtons() {
// 模块标签点击事件
document.querySelectorAll('#module-tags .tag-button').forEach(button => {
button.addEventListener('click', function() {
document.getElementById('module').value = this.textContent.trim();
// 更新选中状态
document.querySelectorAll('#module-tags .tag-button').forEach(btn => {
btn.classList.remove('active');
});
this.classList.add('active');
});
});
// 环境标签点击事件
document.querySelectorAll('#env-tags .tag-button').forEach(button => {
button.addEventListener('click', function() {
document.getElementById('environment').value = this.textContent.trim();
// 更新选中状态
document.querySelectorAll('#env-tags .tag-button').forEach(btn => {
btn.classList.remove('active');
});
this.classList.add('active');
});
});
}
// 加载配置数据
function loadConfigData(id) {
// 模拟数据
let configData = {
id: id,
config_name: 'database_connection',
module: 'system',
environment: 'prod',
is_active: true,
remarks: '数据库连接配置,包含主库和从库配置',
config_data: {
database: {
host: "db.cluster.com",
port: 5432,
pool_size: 20,
ssl: true
},
cache: {
ttl: 3600,
max_entries: 1000
},
feature_flags: ["new_ui", "analytics_v2"]
}
};
if (id === '2') {
configData.config_name = 'text_extraction_ai';
configData.module = 'ai';
configData.environment = 'test';
configData.remarks = 'AI文本抽取服务配置';
} else if (id === '3') {
configData.config_name = 'notification_service';
configData.module = 'notification';
configData.environment = 'dev';
configData.is_active = false;
configData.remarks = '通知服务配置,目前处于开发测试阶段';
} else if (id === '4') {
configData.config_name = 'file_storage';
configData.module = 'file';
configData.environment = 'common';
configData.remarks = '文件存储通用配置,适用于所有环境';
}
// 填充表单
document.getElementById('config-name').value = configData.config_name;
document.getElementById('module').value = getModuleDisplayName(configData.module);
document.getElementById('environment').value = getEnvironmentDisplayName(configData.environment);
document.getElementById('is-active').checked = configData.is_active;
document.getElementById('remarks').value = configData.remarks || '';
document.getElementById('config-data').value = JSON.stringify(configData.config_data, null, 2);
// 更新标签选中状态
updateTagSelection('module', configData.module);
updateTagSelection('environment', configData.environment);
}
// 获取模块显示名称
function getModuleDisplayName(moduleCode) {
const moduleMap = {
'system': '系统',
'auth': '认证',
'file': '文件',
'ai': 'AI配置',
'notification': '通知'
};
return moduleMap[moduleCode] || moduleCode;
}
// 获取环境显示名称
function getEnvironmentDisplayName(envCode) {
const envMap = {
'dev': '开发环境',
'test': '测试环境',
'prod': '生产环境',
'common': '通用'
};
return envMap[envCode] || envCode;
}
// 更新标签选中状态
function updateTagSelection(type, value) {
const selector = type === 'module' ? '#module-tags .tag-button' : '#env-tags .tag-button';
document.querySelectorAll(selector).forEach(btn => {
if (btn.getAttribute('data-value') === value) {
btn.classList.add('active');
} else {
btn.classList.remove('active');
}
});
}
// 加载模板JSON
function loadTemplateJson(type) {
let template = {};
if (type === 'database') {
template = {
database: {
host: "localhost",
port: 5432,
username: "db_user",
password: "******",
name: "app_database",
pool_size: 10,
timeout: 5000,
ssl: false
}
};
} else if (type === 'file') {
template = {
storage: {
type: "local", // or "s3", "oss"
path: "/data/uploads",
allowed_types: ["pdf", "docx", "jpg", "png"],
max_size: 10485760, // 10MB
backup_enabled: true
}
};
} else if (type === 'ai') {
template = {
ai_service: {
provider: "openai",
api_key: "sk-******",
model: "gpt-4",
max_tokens: 2000,
temperature: 0.7,
timeout: 30000,
rate_limit: 10 // requests per minute
}
};
}
document.getElementById('config-data').value = JSON.stringify(template, null, 2);
formatJSON();
}
// 格式化JSON
function formatJSON() {
const jsonArea = document.getElementById('config-data');
const jsonError = document.getElementById('json-error');
try {
const jsonStr = jsonArea.value.trim();
if (!jsonStr) {
return;
}
const jsonObj = JSON.parse(jsonStr);
jsonArea.value = JSON.stringify(jsonObj, null, 2);
jsonError.classList.add('hidden');
} catch (error) {
jsonError.textContent = '无效的JSON格式: ' + error.message;
jsonError.classList.remove('hidden');
}
}
// 保存配置
function saveConfig() {
const form = document.getElementById('config-form');
// 表单验证
if (!form.checkValidity()) {
form.reportValidity();
return;
}
// 验证JSON
const jsonArea = document.getElementById('config-data');
const jsonError = document.getElementById('json-error');
let configDataObj = null;
try {
configDataObj = JSON.parse(jsonArea.value);
jsonError.classList.add('hidden');
} catch (error) {
jsonError.textContent = '无效的JSON格式: ' + error.message;
jsonError.classList.remove('hidden');
return;
}
// 获取表单数据
const configName = document.getElementById('config-name').value;
const moduleDisplay = document.getElementById('module').value;
const environmentDisplay = document.getElementById('environment').value;
const isActive = document.getElementById('is-active').checked;
const remarks = document.getElementById('remarks').value;
// 获取模块和环境的实际值
const module = getModuleCodeFromDisplay(moduleDisplay);
const environment = getEnvironmentCodeFromDisplay(environmentDisplay);
// 构建要提交的数据
const formData = {
id: urlParams.get('id') || null,
config_name: configName,
module: module,
environment: environment,
is_active: isActive,
remarks: remarks,
config_data: configDataObj
};
// console.log('提交数据:', formData);
// 实际应用中应通过AJAX提交数据
setTimeout(() => {
alert('保存成功!');
window.location.href = '配置-列表.html';
}, 500);
}
// 从显示名称获取模块代码
function getModuleCodeFromDisplay(displayName) {
const moduleMap = {
'系统': 'system',
'认证': 'auth',
'文件': 'file',
'AI配置': 'ai',
'通知': 'notification'
};
return moduleMap[displayName] || displayName;
}
// 从显示名称获取环境代码
function getEnvironmentCodeFromDisplay(displayName) {
const envMap = {
'开发环境': 'dev',
'测试环境': 'test',
'生产环境': 'prod',
'通用': 'common'
};
return envMap[displayName] || displayName;
}
</script>
</body>
</html>