更新测试页面和更新接口swagger文档
This commit is contained in:
parent
d0ad41fddd
commit
42c254fe51
Binary file not shown.
23
app.py
23
app.py
@ -52,6 +52,10 @@ swagger_template = {
|
|||||||
"name": "AI解析",
|
"name": "AI解析",
|
||||||
"description": "AI字段提取相关接口"
|
"description": "AI字段提取相关接口"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "文档生成",
|
||||||
|
"description": "文档生成相关接口"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "字段配置",
|
"name": "字段配置",
|
||||||
"description": "字段配置查询接口"
|
"description": "字段配置查询接口"
|
||||||
@ -465,6 +469,25 @@ def generate_document():
|
|||||||
fpolicFieldParamFileList:
|
fpolicFieldParamFileList:
|
||||||
type: array
|
type: array
|
||||||
description: 文件列表(包含filePath)
|
description: 文件列表(包含filePath)
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
fileId:
|
||||||
|
type: integer
|
||||||
|
description: 文件ID
|
||||||
|
example: 1
|
||||||
|
fileName:
|
||||||
|
type: string
|
||||||
|
description: 文件名称
|
||||||
|
example: 请示报告卡.doc
|
||||||
|
templateCode:
|
||||||
|
type: string
|
||||||
|
description: 模板编码
|
||||||
|
example: PRELIMINARY_VERIFICATION_APPROVAL
|
||||||
|
filePath:
|
||||||
|
type: string
|
||||||
|
description: MinIO相对路径
|
||||||
|
example: /202511261123/请示报告卡.doc
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
example: ok
|
example: ok
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>智慧监督AI文书写作 - 解析接口测试</title>
|
<title>智慧监督AI文书写作 - API接口测试</title>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 1200px;
|
max-width: 1400px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@ -44,10 +44,43 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-bottom: 2px solid #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
flex: 1;
|
||||||
|
padding: 15px 20px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #666;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:hover {
|
||||||
|
background: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab.active {
|
||||||
|
background: #667eea;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
display: none;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-content.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
@ -96,15 +129,12 @@
|
|||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-fields {
|
.field-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 2fr;
|
grid-template-columns: 1fr 2fr;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
align-items: start;
|
||||||
|
|
||||||
.input-fields input {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
@ -134,13 +164,23 @@
|
|||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background: #f44336;
|
||||||
|
padding: 8px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.result-box {
|
.result-box {
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
border: 2px solid #e0e0e0;
|
border: 2px solid #e0e0e0;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
max-height: 500px;
|
max-height: 600px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,18 +243,22 @@
|
|||||||
border-left-color: #4caf50;
|
border-left-color: #4caf50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-field-btn {
|
.info-link {
|
||||||
background: #4caf50;
|
text-align: center;
|
||||||
padding: 8px 15px;
|
margin-top: 20px;
|
||||||
font-size: 14px;
|
padding: 15px;
|
||||||
margin-top: 10px;
|
background: #e3f2fd;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-field-btn {
|
.info-link a {
|
||||||
background: #f44336;
|
color: #667eea;
|
||||||
padding: 6px 12px;
|
text-decoration: none;
|
||||||
font-size: 12px;
|
font-weight: 500;
|
||||||
margin-left: 10px;
|
}
|
||||||
|
|
||||||
|
.info-link a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@ -222,135 +266,208 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>智慧监督AI文书写作</h1>
|
<h1>智慧监督AI文书写作</h1>
|
||||||
<p>解析接口测试工具 - 初步核实审批表</p>
|
<p>API接口测试工具 - 解析接口 & 文档生成接口</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<!-- 标签页 -->
|
||||||
<!-- 输入区域 -->
|
<div class="tabs">
|
||||||
|
<button class="tab active" onclick="switchTab('extract')">AI解析接口</button>
|
||||||
|
<button class="tab" onclick="switchTab('generate')">文档生成接口</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 解析接口标签页 -->
|
||||||
|
<div id="extract-tab" class="tab-content active">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">输入数据</div>
|
<div class="section-title">输入数据</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label>业务类型</label>
|
|
||||||
<select id="businessType">
|
|
||||||
<option value="INVESTIGATION">INVESTIGATION (调查核实)</option>
|
|
||||||
<option value="COMPLAINT">COMPLAINT (投诉举报)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>输入字段数据</label>
|
<label>输入字段数据</label>
|
||||||
<div id="inputFieldsContainer">
|
<div id="inputFieldsContainer">
|
||||||
<!-- 动态生成的输入字段 -->
|
<!-- 动态生成的输入字段 -->
|
||||||
</div>
|
</div>
|
||||||
<button class="btn add-field-btn" onclick="addInputField()">+ 添加输入字段</button>
|
<button class="btn btn-secondary" onclick="addInputField()">+ 添加输入字段</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>输出字段列表(需要提取的字段)</label>
|
||||||
|
<div id="outputFieldsContainer">
|
||||||
|
<!-- 动态生成的输出字段 -->
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-secondary" onclick="addOutputField()">+ 添加输出字段</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<button class="btn" onclick="extractData()" id="extractBtn">开始解析</button>
|
<button class="btn" onclick="extractData()" id="extractBtn">开始解析</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 加载提示 -->
|
<div class="loading" id="extractLoading">
|
||||||
<div class="loading" id="loading">
|
|
||||||
<div class="spinner"></div>
|
<div class="spinner"></div>
|
||||||
<p>AI正在解析中,请稍候...</p>
|
<p>AI正在解析中,请稍候...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 结果展示 -->
|
<div class="section" id="extractResultSection" style="display: none;">
|
||||||
<div class="section" id="resultSection" style="display: none;">
|
|
||||||
<div class="section-title">解析结果</div>
|
<div class="section-title">解析结果</div>
|
||||||
<div class="result-box" id="resultBox"></div>
|
<div class="result-box" id="extractResultBox"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 文档生成接口标签页 -->
|
||||||
|
<div id="generate-tab" class="tab-content">
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">输入数据</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>字段数据(用于填充模板)</label>
|
||||||
|
<div id="generateFieldsContainer">
|
||||||
|
<!-- 动态生成的字段 -->
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-secondary" onclick="addGenerateField()">+ 添加字段</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文件列表</label>
|
||||||
|
<div id="fileListContainer">
|
||||||
|
<!-- 动态生成的文件列表 -->
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-secondary" onclick="addFileItem()">+ 添加文件</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<button class="btn" onclick="generateDocument()" id="generateBtn">生成文档</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="loading" id="generateLoading">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
<p>正在生成文档,请稍候...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" id="generateResultSection" style="display: none;">
|
||||||
|
<div class="section-title">生成结果</div>
|
||||||
|
<div class="result-box" id="generateResultBox"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-link">
|
||||||
|
<a href="/api-docs" target="_blank">📖 查看完整的API文档 (Swagger)</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let inputFields = [];
|
|
||||||
let outputFields = [];
|
|
||||||
|
|
||||||
// 页面加载时初始化
|
// 页面加载时初始化
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
loadFields();
|
initExtractTab();
|
||||||
initDefaultInputFields();
|
initGenerateTab();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载字段配置
|
// 切换标签页
|
||||||
async function loadFields() {
|
function switchTab(tabName) {
|
||||||
try {
|
// 隐藏所有标签页内容
|
||||||
const response = await fetch('/api/fields?businessType=INVESTIGATION');
|
document.querySelectorAll('.tab-content').forEach(content => {
|
||||||
const result = await response.json();
|
content.classList.remove('active');
|
||||||
|
});
|
||||||
|
|
||||||
if (result.isSuccess && result.data) {
|
// 移除所有标签页的active类
|
||||||
outputFields = result.data.output_fields || [];
|
document.querySelectorAll('.tab').forEach(tab => {
|
||||||
// 可以在这里使用outputFields来显示字段信息
|
tab.classList.remove('active');
|
||||||
}
|
});
|
||||||
} catch (error) {
|
|
||||||
console.error('加载字段配置失败:', error);
|
// 显示选中的标签页
|
||||||
}
|
document.getElementById(tabName + '-tab').classList.add('active');
|
||||||
|
event.target.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化默认输入字段
|
// ==================== 解析接口相关 ====================
|
||||||
function initDefaultInputFields() {
|
|
||||||
addInputField('clue_info', '线索信息', '被举报用户名称是张三,年龄30岁,某公司总经理');
|
function initExtractTab() {
|
||||||
addInputField('target_basic_info_clue', '被核查人员工作基本情况线索', '张三,男,汉族,1980年5月出生,山西太原人,本科学历,2000年参加工作,2005年加入中国共产党。');
|
// 初始化默认输入字段
|
||||||
|
addInputField('clue_info', '被举报用户名称是张三,年龄30岁,某公司总经理,男性,1980年5月出生,中共党员,正处级');
|
||||||
|
|
||||||
|
// 初始化默认输出字段
|
||||||
|
addOutputField('target_name');
|
||||||
|
addOutputField('target_gender');
|
||||||
|
addOutputField('target_organization_and_position');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加输入字段
|
function addInputField(fieldCode = 'clue_info', fieldValue = '') {
|
||||||
function addInputField(fieldCode = '', fieldName = '', fieldValue = '') {
|
|
||||||
const container = document.getElementById('inputFieldsContainer');
|
const container = document.getElementById('inputFieldsContainer');
|
||||||
const fieldDiv = document.createElement('div');
|
const fieldDiv = document.createElement('div');
|
||||||
fieldDiv.className = 'input-fields';
|
fieldDiv.className = 'field-row';
|
||||||
fieldDiv.innerHTML = `
|
fieldDiv.innerHTML = `
|
||||||
<input type="text" placeholder="字段编码 (如: clue_info)" value="${fieldCode}" class="field-code">
|
<input type="text" placeholder="字段编码 (如: clue_info)" value="${fieldCode}" class="field-code">
|
||||||
<div style="display: flex; gap: 10px;">
|
<div style="display: flex; gap: 10px;">
|
||||||
<input type="text" placeholder="字段值" value="${fieldValue}" class="field-value" style="flex: 1;">
|
<textarea placeholder="字段值(原始文本)" class="field-value" style="flex: 1; min-height: 60px;">${fieldValue}</textarea>
|
||||||
<button class="btn remove-field-btn" onclick="removeInputField(this)">删除</button>
|
<button class="btn btn-danger" onclick="removeField(this)">删除</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
container.appendChild(fieldDiv);
|
container.appendChild(fieldDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入字段
|
function addOutputField(fieldCode = '') {
|
||||||
function removeInputField(btn) {
|
const container = document.getElementById('outputFieldsContainer');
|
||||||
btn.closest('.input-fields').remove();
|
const fieldDiv = document.createElement('div');
|
||||||
|
fieldDiv.className = 'field-row';
|
||||||
|
fieldDiv.innerHTML = `
|
||||||
|
<input type="text" placeholder="字段编码 (如: target_name)" value="${fieldCode}" class="output-field-code">
|
||||||
|
<div style="display: flex; gap: 10px;">
|
||||||
|
<div style="flex: 1;"></div>
|
||||||
|
<button class="btn btn-danger" onclick="removeField(this)">删除</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(fieldDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取数据
|
|
||||||
async function extractData() {
|
async function extractData() {
|
||||||
const extractBtn = document.getElementById('extractBtn');
|
const extractBtn = document.getElementById('extractBtn');
|
||||||
const loading = document.getElementById('loading');
|
const loading = document.getElementById('extractLoading');
|
||||||
const resultSection = document.getElementById('resultSection');
|
const resultSection = document.getElementById('extractResultSection');
|
||||||
const resultBox = document.getElementById('resultBox');
|
const resultBox = document.getElementById('extractResultBox');
|
||||||
|
|
||||||
// 收集输入数据
|
// 收集输入数据
|
||||||
const inputFields = [];
|
const inputData = [];
|
||||||
const fieldContainers = document.querySelectorAll('#inputFieldsContainer .input-fields');
|
const fieldContainers = document.querySelectorAll('#inputFieldsContainer .field-row');
|
||||||
|
|
||||||
fieldContainers.forEach(container => {
|
fieldContainers.forEach(container => {
|
||||||
const fieldCode = container.querySelector('.field-code').value.trim();
|
const fieldCode = container.querySelector('.field-code').value.trim();
|
||||||
const fieldValue = container.querySelector('.field-value').value.trim();
|
const fieldValue = container.querySelector('.field-value').value.trim();
|
||||||
|
|
||||||
if (fieldCode && fieldValue) {
|
if (fieldCode && fieldValue) {
|
||||||
inputFields.push({
|
inputData.push({
|
||||||
fieldCode: fieldCode,
|
fieldCode: fieldCode,
|
||||||
fieldValue: fieldValue
|
fieldValue: fieldValue
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (inputFields.length === 0) {
|
// 收集输出字段
|
||||||
|
const outputData = [];
|
||||||
|
const outputContainers = document.querySelectorAll('#outputFieldsContainer .field-row');
|
||||||
|
|
||||||
|
outputContainers.forEach(container => {
|
||||||
|
const fieldCode = container.querySelector('.output-field-code').value.trim();
|
||||||
|
|
||||||
|
if (fieldCode) {
|
||||||
|
outputData.push({
|
||||||
|
fieldCode: fieldCode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (inputData.length === 0) {
|
||||||
alert('请至少添加一个输入字段');
|
alert('请至少添加一个输入字段');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const businessType = document.getElementById('businessType').value;
|
if (outputData.length === 0) {
|
||||||
|
alert('请至少添加一个输出字段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 构建请求数据
|
// 构建请求数据(新接口格式)
|
||||||
const requestData = {
|
const requestData = {
|
||||||
businessType: businessType,
|
inputData: inputData,
|
||||||
inputData: inputFields
|
outputData: outputData
|
||||||
};
|
};
|
||||||
|
|
||||||
// 显示加载状态
|
// 显示加载状态
|
||||||
@ -359,7 +476,7 @@
|
|||||||
resultSection.style.display = 'none';
|
resultSection.style.display = 'none';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/ai/extract', {
|
const response = await fetch('/ai/extract', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@ -368,22 +485,19 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
displayExtractResult(result, requestData);
|
||||||
// 显示结果
|
|
||||||
displayResult(result, requestData);
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
displayError(error.message);
|
displayError('extract', error.message);
|
||||||
} finally {
|
} finally {
|
||||||
extractBtn.disabled = false;
|
extractBtn.disabled = false;
|
||||||
loading.classList.remove('active');
|
loading.classList.remove('active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示结果
|
function displayExtractResult(result, requestData) {
|
||||||
function displayResult(result, requestData) {
|
const resultSection = document.getElementById('extractResultSection');
|
||||||
const resultSection = document.getElementById('resultSection');
|
const resultBox = document.getElementById('extractResultBox');
|
||||||
const resultBox = document.getElementById('resultBox');
|
|
||||||
|
|
||||||
resultSection.style.display = 'block';
|
resultSection.style.display = 'block';
|
||||||
|
|
||||||
@ -395,19 +509,20 @@
|
|||||||
|
|
||||||
// 显示响应结果
|
// 显示响应结果
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
html += '<div class="result-item success"><strong>解析成功!</strong></div>';
|
html += '<div class="result-item success"><strong>✓ 解析成功!</strong></div>';
|
||||||
|
|
||||||
if (result.data && result.data.outData) {
|
if (result.data && result.data.outData) {
|
||||||
html += '<div class="result-item"><strong>提取的字段:</strong></div>';
|
html += '<div class="result-item"><strong>提取的字段:</strong></div>';
|
||||||
result.data.outData.forEach(item => {
|
result.data.outData.forEach(item => {
|
||||||
|
const value = item.fieldValue || '(空)';
|
||||||
html += `<div class="result-item">
|
html += `<div class="result-item">
|
||||||
<strong>${item.fieldCode}:</strong> ${item.fieldValue || '(空)'}
|
<strong>${item.fieldCode}:</strong> ${value}
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
html += `<div class="result-item error">
|
html += `<div class="result-item error">
|
||||||
<strong>解析失败!</strong><br>
|
<strong>✗ 解析失败!</strong><br>
|
||||||
错误码: ${result.code}<br>
|
错误码: ${result.code}<br>
|
||||||
错误信息: ${result.errorMsg}
|
错误信息: ${result.errorMsg}
|
||||||
</div>`;
|
</div>`;
|
||||||
@ -418,15 +533,195 @@
|
|||||||
html += '<div class="result-item"><pre>' + JSON.stringify(result, null, 2) + '</pre></div>';
|
html += '<div class="result-item"><pre>' + JSON.stringify(result, null, 2) + '</pre></div>';
|
||||||
|
|
||||||
resultBox.innerHTML = html;
|
resultBox.innerHTML = html;
|
||||||
|
|
||||||
// 滚动到结果区域
|
|
||||||
resultSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
resultSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示错误
|
// ==================== 文档生成接口相关 ====================
|
||||||
function displayError(errorMsg) {
|
|
||||||
const resultSection = document.getElementById('resultSection');
|
function initGenerateTab() {
|
||||||
const resultBox = document.getElementById('resultBox');
|
// 初始化默认字段
|
||||||
|
addGenerateField('target_name', '张三');
|
||||||
|
addGenerateField('target_gender', '男');
|
||||||
|
addGenerateField('target_organization_and_position', '某公司总经理');
|
||||||
|
|
||||||
|
// 初始化默认文件
|
||||||
|
addFileItem(1, '初步核实审批表.doc', 'PRELIMINARY_VERIFICATION_APPROVAL');
|
||||||
|
}
|
||||||
|
|
||||||
|
function addGenerateField(fieldCode = '', fieldValue = '') {
|
||||||
|
const container = document.getElementById('generateFieldsContainer');
|
||||||
|
const fieldDiv = document.createElement('div');
|
||||||
|
fieldDiv.className = 'field-row';
|
||||||
|
fieldDiv.innerHTML = `
|
||||||
|
<input type="text" placeholder="字段编码 (如: target_name)" value="${fieldCode}" class="generate-field-code">
|
||||||
|
<div style="display: flex; gap: 10px;">
|
||||||
|
<input type="text" placeholder="字段值" value="${fieldValue}" class="generate-field-value" style="flex: 1;">
|
||||||
|
<button class="btn btn-danger" onclick="removeField(this)">删除</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(fieldDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFileItem(fileId = '', fileName = '', templateCode = '') {
|
||||||
|
const container = document.getElementById('fileListContainer');
|
||||||
|
const fileDiv = document.createElement('div');
|
||||||
|
fileDiv.className = 'field-row';
|
||||||
|
fileDiv.innerHTML = `
|
||||||
|
<input type="number" placeholder="文件ID" value="${fileId}" class="file-id" style="width: 150px;">
|
||||||
|
<div style="display: flex; gap: 10px; flex: 1;">
|
||||||
|
<input type="text" placeholder="文件名称 (如: 初步核实审批表.doc)" value="${fileName}" class="file-name" style="flex: 1;">
|
||||||
|
<input type="text" placeholder="模板编码 (如: PRELIMINARY_VERIFICATION_APPROVAL)" value="${templateCode}" class="template-code" style="flex: 1;">
|
||||||
|
<button class="btn btn-danger" onclick="removeField(this)">删除</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(fileDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateDocument() {
|
||||||
|
const generateBtn = document.getElementById('generateBtn');
|
||||||
|
const loading = document.getElementById('generateLoading');
|
||||||
|
const resultSection = document.getElementById('generateResultSection');
|
||||||
|
const resultBox = document.getElementById('generateResultBox');
|
||||||
|
|
||||||
|
// 收集字段数据
|
||||||
|
const inputData = [];
|
||||||
|
const fieldContainers = document.querySelectorAll('#generateFieldsContainer .field-row');
|
||||||
|
|
||||||
|
fieldContainers.forEach(container => {
|
||||||
|
const fieldCode = container.querySelector('.generate-field-code').value.trim();
|
||||||
|
const fieldValue = container.querySelector('.generate-field-value').value.trim();
|
||||||
|
|
||||||
|
if (fieldCode) {
|
||||||
|
inputData.push({
|
||||||
|
fieldCode: fieldCode,
|
||||||
|
fieldValue: fieldValue || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 收集文件列表
|
||||||
|
const fileList = [];
|
||||||
|
const fileContainers = document.querySelectorAll('#fileListContainer .field-row');
|
||||||
|
|
||||||
|
fileContainers.forEach(container => {
|
||||||
|
const fileId = container.querySelector('.file-id').value.trim();
|
||||||
|
const fileName = container.querySelector('.file-name').value.trim();
|
||||||
|
const templateCode = container.querySelector('.template-code').value.trim();
|
||||||
|
|
||||||
|
if (fileId && fileName && templateCode) {
|
||||||
|
fileList.push({
|
||||||
|
fileId: parseInt(fileId),
|
||||||
|
fileName: fileName,
|
||||||
|
templateCode: templateCode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (inputData.length === 0) {
|
||||||
|
alert('请至少添加一个字段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileList.length === 0) {
|
||||||
|
alert('请至少添加一个文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求数据
|
||||||
|
const requestData = {
|
||||||
|
inputData: inputData,
|
||||||
|
fpolicFieldParamFileList: fileList
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示加载状态
|
||||||
|
generateBtn.disabled = true;
|
||||||
|
loading.classList.add('active');
|
||||||
|
resultSection.style.display = 'none';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/ai/generate-document', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(requestData)
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
displayGenerateResult(result, requestData);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
displayError('generate', error.message);
|
||||||
|
} finally {
|
||||||
|
generateBtn.disabled = false;
|
||||||
|
loading.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayGenerateResult(result, requestData) {
|
||||||
|
const resultSection = document.getElementById('generateResultSection');
|
||||||
|
const resultBox = document.getElementById('generateResultBox');
|
||||||
|
|
||||||
|
resultSection.style.display = 'block';
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
// 显示请求数据
|
||||||
|
html += '<div class="result-item"><strong>请求数据:</strong></div>';
|
||||||
|
html += '<div class="result-item"><pre>' + JSON.stringify(requestData, null, 2) + '</pre></div>';
|
||||||
|
|
||||||
|
// 显示响应结果
|
||||||
|
if (result.isSuccess) {
|
||||||
|
html += '<div class="result-item success"><strong>✓ 文档生成成功!</strong></div>';
|
||||||
|
|
||||||
|
if (result.data) {
|
||||||
|
if (result.data.documentId) {
|
||||||
|
html += `<div class="result-item">
|
||||||
|
<strong>文档ID:</strong> ${result.data.documentId}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.data.documentName) {
|
||||||
|
html += `<div class="result-item">
|
||||||
|
<strong>文档名称:</strong> ${result.data.documentName}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.data.fpolicFieldParamFileList && result.data.fpolicFieldParamFileList.length > 0) {
|
||||||
|
html += '<div class="result-item"><strong>生成的文件:</strong></div>';
|
||||||
|
result.data.fpolicFieldParamFileList.forEach(file => {
|
||||||
|
html += `<div class="result-item">
|
||||||
|
<strong>${file.fileName}:</strong><br>
|
||||||
|
文件路径: ${file.filePath || '(无路径)'}
|
||||||
|
</div>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html += `<div class="result-item error">
|
||||||
|
<strong>✗ 文档生成失败!</strong><br>
|
||||||
|
错误码: ${result.code}<br>
|
||||||
|
错误信息: ${result.errorMsg}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示完整响应
|
||||||
|
html += '<div class="result-item"><strong>完整响应:</strong></div>';
|
||||||
|
html += '<div class="result-item"><pre>' + JSON.stringify(result, null, 2) + '</pre></div>';
|
||||||
|
|
||||||
|
resultBox.innerHTML = html;
|
||||||
|
resultSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 通用函数 ====================
|
||||||
|
|
||||||
|
function removeField(btn) {
|
||||||
|
btn.closest('.field-row').remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayError(tabType, errorMsg) {
|
||||||
|
const resultSection = document.getElementById(tabType + 'ResultSection');
|
||||||
|
const resultBox = document.getElementById(tabType + 'ResultBox');
|
||||||
|
|
||||||
resultSection.style.display = 'block';
|
resultSection.style.display = 'block';
|
||||||
resultBox.innerHTML = `<div class="result-item error">
|
resultBox.innerHTML = `<div class="result-item error">
|
||||||
@ -437,4 +732,3 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
203
测试页面使用指南.md
Normal file
203
测试页面使用指南.md
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
# 测试页面使用指南
|
||||||
|
|
||||||
|
## 🎯 概述
|
||||||
|
|
||||||
|
测试页面提供了两个API接口的可视化测试功能:
|
||||||
|
1. **AI解析接口** - 从非结构化文本中提取结构化字段
|
||||||
|
2. **文档生成接口** - 根据字段数据填充Word模板并生成文档
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 功能说明
|
||||||
|
|
||||||
|
### 1. AI解析接口测试
|
||||||
|
|
||||||
|
#### 功能描述
|
||||||
|
使用AI大模型从输入文本中提取结构化字段数据。
|
||||||
|
|
||||||
|
#### 使用步骤
|
||||||
|
|
||||||
|
1. **切换到"AI解析接口"标签页**
|
||||||
|
- 点击页面顶部的"AI解析接口"标签
|
||||||
|
|
||||||
|
2. **添加输入字段**
|
||||||
|
- 输入字段编码(如:`clue_info`)
|
||||||
|
- 输入字段值(原始文本)
|
||||||
|
- 可以添加多个输入字段
|
||||||
|
- 点击"+ 添加输入字段"添加更多
|
||||||
|
|
||||||
|
3. **添加输出字段**
|
||||||
|
- 输入需要提取的字段编码(如:`target_name`)
|
||||||
|
- 可以添加多个输出字段
|
||||||
|
- 点击"+ 添加输出字段"添加更多
|
||||||
|
|
||||||
|
4. **开始解析**
|
||||||
|
- 点击"开始解析"按钮
|
||||||
|
- 等待AI处理(可能需要一些时间)
|
||||||
|
- 查看解析结果
|
||||||
|
|
||||||
|
#### 示例数据
|
||||||
|
|
||||||
|
**输入字段:**
|
||||||
|
```
|
||||||
|
字段编码: clue_info
|
||||||
|
字段值: 被举报用户名称是张三,年龄30岁,某公司总经理,男性,1980年5月出生,中共党员,正处级
|
||||||
|
```
|
||||||
|
|
||||||
|
**输出字段:**
|
||||||
|
```
|
||||||
|
target_name
|
||||||
|
target_gender
|
||||||
|
target_organization_and_position
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 预期结果
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"data": {
|
||||||
|
"outData": [
|
||||||
|
{
|
||||||
|
"fieldCode": "target_name",
|
||||||
|
"fieldValue": "张三"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "target_gender",
|
||||||
|
"fieldValue": "男"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "target_organization_and_position",
|
||||||
|
"fieldValue": "某公司总经理"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isSuccess": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. 文档生成接口测试
|
||||||
|
|
||||||
|
#### 功能描述
|
||||||
|
根据字段数据填充Word模板,生成填充后的文档并上传到MinIO。
|
||||||
|
|
||||||
|
#### 使用步骤
|
||||||
|
|
||||||
|
1. **切换到"文档生成接口"标签页**
|
||||||
|
- 点击页面顶部的"文档生成接口"标签
|
||||||
|
|
||||||
|
2. **添加字段数据**
|
||||||
|
- 输入字段编码(如:`target_name`)
|
||||||
|
- 输入字段值(如:`张三`)
|
||||||
|
- 可以添加多个字段
|
||||||
|
- 点击"+ 添加字段"添加更多
|
||||||
|
|
||||||
|
3. **添加文件配置**
|
||||||
|
- 输入文件ID(如:`1`)
|
||||||
|
- 输入文件名称(如:`初步核实审批表.doc`)
|
||||||
|
- 输入模板编码(如:`PRELIMINARY_VERIFICATION_APPROVAL`)
|
||||||
|
- 可以添加多个文件
|
||||||
|
- 点击"+ 添加文件"添加更多
|
||||||
|
|
||||||
|
4. **生成文档**
|
||||||
|
- 点击"生成文档"按钮
|
||||||
|
- 等待文档生成和上传(可能需要一些时间)
|
||||||
|
- 查看生成结果
|
||||||
|
|
||||||
|
#### 示例数据
|
||||||
|
|
||||||
|
**字段数据:**
|
||||||
|
```
|
||||||
|
target_name: 张三
|
||||||
|
target_gender: 男
|
||||||
|
target_organization_and_position: 某公司总经理
|
||||||
|
```
|
||||||
|
|
||||||
|
**文件配置:**
|
||||||
|
```
|
||||||
|
文件ID: 1
|
||||||
|
文件名称: 初步核实审批表.doc
|
||||||
|
模板编码: PRELIMINARY_VERIFICATION_APPROVAL
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 预期结果
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"data": {
|
||||||
|
"documentId": "DOC202411260001",
|
||||||
|
"documentName": "初步核实审批表_张三.docx",
|
||||||
|
"fpolicFieldParamFileList": [
|
||||||
|
{
|
||||||
|
"fileId": 1,
|
||||||
|
"fileName": "初步核实审批表.doc",
|
||||||
|
"filePath": "/202511261123/初步核实审批表.doc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isSuccess": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
|
### AI解析接口
|
||||||
|
|
||||||
|
1. **字段编码必须正确**
|
||||||
|
- 字段编码需要与数据库中的配置一致
|
||||||
|
- 可以使用数据库中已有的字段编码
|
||||||
|
|
||||||
|
2. **输出字段必须存在**
|
||||||
|
- 输出字段必须在数据库中已配置
|
||||||
|
- 如果字段不存在,可能无法提取
|
||||||
|
|
||||||
|
3. **AI服务配置**
|
||||||
|
- 需要配置 `SILICONFLOW_API_KEY` 在 `.env` 文件中
|
||||||
|
- 如果未配置,解析将失败
|
||||||
|
|
||||||
|
### 文档生成接口
|
||||||
|
|
||||||
|
1. **模板编码必须正确**
|
||||||
|
- 模板编码需要与数据库中的文件配置一致
|
||||||
|
- 必须使用 `template_code` 字段的值
|
||||||
|
|
||||||
|
2. **MinIO配置**
|
||||||
|
- 需要配置MinIO连接信息
|
||||||
|
- 模板文件必须存在于MinIO中
|
||||||
|
|
||||||
|
3. **字段值匹配**
|
||||||
|
- Word模板中的占位符需要与字段编码匹配
|
||||||
|
- 未匹配的占位符将保持为空
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 相关链接
|
||||||
|
|
||||||
|
- **Swagger API文档**: http://localhost:7500/api-docs
|
||||||
|
- **测试页面**: http://localhost:7500/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 常见问题
|
||||||
|
|
||||||
|
### Q: 解析接口一直加载怎么办?
|
||||||
|
A: 检查AI服务配置是否正确,查看浏览器控制台是否有错误信息。
|
||||||
|
|
||||||
|
### Q: 文档生成失败?
|
||||||
|
A:
|
||||||
|
1. 检查模板编码是否正确
|
||||||
|
2. 检查MinIO配置和连接
|
||||||
|
3. 检查模板文件是否存在于MinIO
|
||||||
|
|
||||||
|
### Q: 如何查看详细的接口文档?
|
||||||
|
A: 点击页面底部的"查看完整的API文档 (Swagger)"链接。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**祝测试顺利!** 🎉
|
||||||
|
|
||||||
143
测试页面和Swagger更新总结.md
Normal file
143
测试页面和Swagger更新总结.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# 测试页面和Swagger更新总结
|
||||||
|
|
||||||
|
## ✅ 更新完成
|
||||||
|
|
||||||
|
### 1. 测试页面更新 (`static/index.html`)
|
||||||
|
|
||||||
|
#### 主要改动
|
||||||
|
|
||||||
|
- ✅ **双标签页设计**
|
||||||
|
- 新增标签页切换功能
|
||||||
|
- AI解析接口标签页
|
||||||
|
- 文档生成接口标签页
|
||||||
|
- 清晰的界面导航
|
||||||
|
|
||||||
|
- ✅ **AI解析接口更新**
|
||||||
|
- 移除了 `businessType` 选择框(新接口不再需要)
|
||||||
|
- 新增 `outputData` 输入区域
|
||||||
|
- 支持动态添加/删除输入字段
|
||||||
|
- 支持动态添加/删除输出字段
|
||||||
|
- 使用新的接口格式(`inputData` + `outputData`)
|
||||||
|
|
||||||
|
- ✅ **文档生成接口支持**
|
||||||
|
- 新增字段数据输入区域
|
||||||
|
- 新增文件列表配置区域
|
||||||
|
- 支持多个文件同时生成
|
||||||
|
- 显示完整的生成结果(文档ID、文档名称、文件路径)
|
||||||
|
|
||||||
|
- ✅ **界面优化**
|
||||||
|
- 现代化的UI设计
|
||||||
|
- 清晰的结果展示区域
|
||||||
|
- 友好的错误提示
|
||||||
|
- 链接到Swagger API文档
|
||||||
|
|
||||||
|
#### 接口路径
|
||||||
|
|
||||||
|
- 解析接口: `/ai/extract` 或 `/api/ai/extract`
|
||||||
|
- 文档生成接口: `/ai/generate-document` 或 `/api/ai/generate-document`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Swagger配置更新 (`app.py`)
|
||||||
|
|
||||||
|
#### 主要改动
|
||||||
|
|
||||||
|
- ✅ **新增标签定义**
|
||||||
|
- 添加"文档生成"标签到Swagger配置
|
||||||
|
- 标签列表包含:AI解析、文档生成、字段配置
|
||||||
|
|
||||||
|
- ✅ **接口文档完整性**
|
||||||
|
- ✅ AI解析接口 (`/ai/extract`)
|
||||||
|
- 完整的请求参数说明
|
||||||
|
- 完整的响应结构说明
|
||||||
|
- 错误码定义(2001, 2002等)
|
||||||
|
|
||||||
|
- ✅ 文档生成接口 (`/ai/generate-document`)
|
||||||
|
- 完整的请求参数说明
|
||||||
|
- 完整的响应结构说明
|
||||||
|
- 错误码定义(1001, 3001, 3002等)
|
||||||
|
- 包含 `filePath` 字段说明
|
||||||
|
|
||||||
|
#### Swagger访问
|
||||||
|
|
||||||
|
- URL: http://localhost:7500/api-docs
|
||||||
|
- 可以查看和测试所有接口
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 功能对比
|
||||||
|
|
||||||
|
### 之前 vs 现在
|
||||||
|
|
||||||
|
| 功能 | 之前 | 现在 |
|
||||||
|
|------|------|------|
|
||||||
|
| 解析接口测试 | ✅ 支持 | ✅ 支持(新格式) |
|
||||||
|
| 文档生成测试 | ❌ 不支持 | ✅ 支持 |
|
||||||
|
| businessType参数 | ✅ 需要 | ❌ 已移除 |
|
||||||
|
| outputData参数 | ❌ 不支持 | ✅ 支持 |
|
||||||
|
| 标签页切换 | ❌ 不支持 | ✅ 支持 |
|
||||||
|
| Swagger文档 | ✅ 部分接口 | ✅ 完整接口 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 测试指南
|
||||||
|
|
||||||
|
### 快速测试步骤
|
||||||
|
|
||||||
|
1. **启动服务**
|
||||||
|
```bash
|
||||||
|
python app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **访问测试页面**
|
||||||
|
- 打开浏览器访问: http://localhost:7500/
|
||||||
|
|
||||||
|
3. **测试解析接口**
|
||||||
|
- 切换到"AI解析接口"标签页
|
||||||
|
- 添加输入字段和输出字段
|
||||||
|
- 点击"开始解析"
|
||||||
|
|
||||||
|
4. **测试文档生成接口**
|
||||||
|
- 切换到"文档生成接口"标签页
|
||||||
|
- 添加字段数据和文件配置
|
||||||
|
- 点击"生成文档"
|
||||||
|
|
||||||
|
5. **查看API文档**
|
||||||
|
- 访问: http://localhost:7500/api-docs
|
||||||
|
- 或点击测试页面底部的链接
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 相关文档
|
||||||
|
|
||||||
|
- `测试页面使用指南.md` - 详细的使用说明
|
||||||
|
- `测试页面更新说明.md` - 更新内容说明
|
||||||
|
- `技术文档/智慧监督AI文书写作接口定义-20251204-1.md` - 接口定义文档
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ 亮点功能
|
||||||
|
|
||||||
|
1. **双标签页设计** - 方便在两个接口之间切换
|
||||||
|
2. **动态字段管理** - 可以随时添加/删除字段
|
||||||
|
3. **完整的结果展示** - 显示请求数据、响应结果和完整响应
|
||||||
|
4. **友好的错误提示** - 清晰的错误信息展示
|
||||||
|
5. **Swagger集成** - 完整的API文档和测试功能
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 验证清单
|
||||||
|
|
||||||
|
- [x] 测试页面已更新为双标签页
|
||||||
|
- [x] AI解析接口使用新格式(无businessType)
|
||||||
|
- [x] 支持outputData参数
|
||||||
|
- [x] 文档生成接口测试功能完整
|
||||||
|
- [x] Swagger配置已更新
|
||||||
|
- [x] 两个接口都在Swagger中
|
||||||
|
- [x] 接口文档完整准确
|
||||||
|
- [x] 错误码定义完整
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**所有更新已完成!可以开始测试了!** 🎉
|
||||||
|
|
||||||
106
测试页面更新说明.md
Normal file
106
测试页面更新说明.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# 测试页面更新说明
|
||||||
|
|
||||||
|
## ✅ 更新内容
|
||||||
|
|
||||||
|
### 1. 测试页面更新 (`static/index.html`)
|
||||||
|
|
||||||
|
#### 新增功能
|
||||||
|
|
||||||
|
1. **双标签页设计**
|
||||||
|
- AI解析接口标签页
|
||||||
|
- 文档生成接口标签页
|
||||||
|
- 可以在两个接口之间切换测试
|
||||||
|
|
||||||
|
2. **AI解析接口更新**
|
||||||
|
- ✅ 取消 `businessType` 参数选择
|
||||||
|
- ✅ 新增 `outputData` 输入区域
|
||||||
|
- ✅ 支持动态添加/删除输入字段和输出字段
|
||||||
|
- ✅ 使用新的接口格式
|
||||||
|
|
||||||
|
3. **文档生成接口支持**
|
||||||
|
- ✅ 字段数据输入区域
|
||||||
|
- ✅ 文件列表配置区域
|
||||||
|
- ✅ 支持多个文件同时生成
|
||||||
|
- ✅ 显示文档ID、文档名称和文件路径
|
||||||
|
|
||||||
|
4. **界面优化**
|
||||||
|
- ✅ 现代化的标签页设计
|
||||||
|
- ✅ 清晰的结果展示
|
||||||
|
- ✅ 友好的错误提示
|
||||||
|
- ✅ 链接到Swagger API文档
|
||||||
|
|
||||||
|
### 2. Swagger配置更新
|
||||||
|
|
||||||
|
- ✅ 添加"文档生成"标签
|
||||||
|
- ✅ 两个接口都已包含在Swagger文档中
|
||||||
|
- ✅ 完整的接口文档说明
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 使用说明
|
||||||
|
|
||||||
|
### 测试AI解析接口
|
||||||
|
|
||||||
|
1. 切换到"AI解析接口"标签页
|
||||||
|
2. 添加输入字段(字段编码 + 字段值)
|
||||||
|
3. 添加输出字段(只需字段编码)
|
||||||
|
4. 点击"开始解析"按钮
|
||||||
|
5. 查看解析结果
|
||||||
|
|
||||||
|
### 测试文档生成接口
|
||||||
|
|
||||||
|
1. 切换到"文档生成接口"标签页
|
||||||
|
2. 添加字段数据(字段编码 + 字段值)
|
||||||
|
3. 添加文件配置(文件ID + 文件名称 + 模板编码)
|
||||||
|
4. 点击"生成文档"按钮
|
||||||
|
5. 查看生成结果(包括文件路径)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 接口路径
|
||||||
|
|
||||||
|
- **解析接口**: `/ai/extract` 或 `/api/ai/extract`
|
||||||
|
- **文档生成接口**: `/ai/generate-document` 或 `/api/ai/generate-document`
|
||||||
|
- **API文档**: `/api-docs`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 示例数据
|
||||||
|
|
||||||
|
### AI解析接口示例
|
||||||
|
|
||||||
|
**输入字段:**
|
||||||
|
- 字段编码: `clue_info`
|
||||||
|
- 字段值: `被举报用户名称是张三,年龄30岁,某公司总经理,男性,1980年5月出生,中共党员,正处级`
|
||||||
|
|
||||||
|
**输出字段:**
|
||||||
|
- `target_name`
|
||||||
|
- `target_gender`
|
||||||
|
- `target_organization_and_position`
|
||||||
|
|
||||||
|
### 文档生成接口示例
|
||||||
|
|
||||||
|
**字段数据:**
|
||||||
|
- `target_name`: `张三`
|
||||||
|
- `target_gender`: `男`
|
||||||
|
- `target_organization_and_position`: `某公司总经理`
|
||||||
|
|
||||||
|
**文件配置:**
|
||||||
|
- 文件ID: `1`
|
||||||
|
- 文件名称: `初步核实审批表.doc`
|
||||||
|
- 模板编码: `PRELIMINARY_VERIFICATION_APPROVAL`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 验证清单
|
||||||
|
|
||||||
|
- [x] 测试页面已更新
|
||||||
|
- [x] 支持解析接口测试
|
||||||
|
- [x] 支持文档生成接口测试
|
||||||
|
- [x] Swagger配置已更新
|
||||||
|
- [x] 两个接口都在Swagger中
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**更新完成!** 🎉
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user