添加文件配置查询接口,提供可用文件列表以供文档生成使用,同时增强错误处理信息。更新前端逻辑以自动加载文件列表并优化用户交互体验。

This commit is contained in:
python 2025-12-11 09:23:07 +08:00
parent 2a5952f3f5
commit 3a3b38cd78
7 changed files with 224 additions and 18 deletions

Binary file not shown.

80
app.py
View File

@ -5,6 +5,7 @@ from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS from flask_cors import CORS
from flasgger import Swagger from flasgger import Swagger
import os import os
import pymysql
from datetime import datetime from datetime import datetime
from dotenv import load_dotenv from dotenv import load_dotenv
@ -284,6 +285,85 @@ def extract():
return error_response(2001, f"AI解析超时或发生错误: {str(e)}") return error_response(2001, f"AI解析超时或发生错误: {str(e)}")
@app.route('/api/file-configs', methods=['GET'])
def get_file_configs():
"""
获取可用的文件配置列表
用于查询可用的fileId供文档生成接口使用
---
tags:
- 字段配置
summary: 获取文件配置列表
description: 返回所有启用的文件配置包含fileId和文件名称
responses:
200:
description: 成功
schema:
type: object
properties:
code:
type: integer
example: 0
data:
type: object
properties:
fileConfigs:
type: array
items:
type: object
properties:
fileId:
type: integer
description: 文件配置ID
example: 1765273961563507
fileName:
type: string
description: 文件名称
example: 1.请示报告卡XXX
filePath:
type: string
description: MinIO文件路径
example: /615873064429507639/TEMPLATE/2025/12/1.请示报告卡XXX.docx
isSuccess:
type: boolean
example: true
"""
try:
conn = document_service.get_connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
try:
sql = """
SELECT id, name, file_path
FROM f_polic_file_config
WHERE tenant_id = %s
AND state = 1
ORDER BY name
"""
cursor.execute(sql, (document_service.tenant_id,))
configs = cursor.fetchall()
file_configs = []
for config in configs:
file_configs.append({
'fileId': config['id'],
'fileName': config['name'],
'filePath': config['file_path'] or ''
})
return success_response({
'fileConfigs': file_configs
})
finally:
cursor.close()
conn.close()
except Exception as e:
return error_response(500, f"查询文件配置失败: {str(e)}")
@app.route('/api/fields', methods=['GET']) @app.route('/api/fields', methods=['GET'])
def get_fields(): def get_fields():
""" """

64
get_available_file_ids.py Normal file
View File

@ -0,0 +1,64 @@
"""
获取所有可用的文件ID列表用于测试
"""
import pymysql
import os
# 数据库连接配置
DB_CONFIG = {
'host': os.getenv('DB_HOST', '152.136.177.240'),
'port': int(os.getenv('DB_PORT', 5012)),
'user': os.getenv('DB_USER', 'finyx'),
'password': os.getenv('DB_PASSWORD', '6QsGK6MpePZDE57Z'),
'database': os.getenv('DB_NAME', 'finyx'),
'charset': 'utf8mb4'
}
TENANT_ID = 615873064429507639
def get_available_file_configs():
"""获取所有可用的文件配置"""
conn = pymysql.connect(**DB_CONFIG)
cursor = conn.cursor(pymysql.cursors.DictCursor)
try:
sql = """
SELECT id, name, file_path, state
FROM f_polic_file_config
WHERE tenant_id = %s
AND state = 1
ORDER BY name
"""
cursor.execute(sql, (TENANT_ID,))
configs = cursor.fetchall()
print("="*80)
print("可用的文件配置列表state=1")
print("="*80)
print(f"\n共找到 {len(configs)} 个启用的文件配置:\n")
for i, config in enumerate(configs, 1):
print(f"{i}. ID: {config['id']}")
print(f" 名称: {config['name']}")
print(f" 文件路径: {config['file_path'] or '(空)'}")
print()
# 输出JSON格式方便复制
print("\n" + "="*80)
print("JSON格式可用于测试:")
print("="*80)
print("[")
for i, config in enumerate(configs):
comma = "," if i < len(configs) - 1 else ""
print(f' {{"fileId": {config["id"]}, "fileName": "{config["name"]}.doc"}}{comma}')
print("]")
return configs
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
get_available_file_configs()

View File

@ -215,7 +215,12 @@ class DocumentService:
# 获取文件配置 # 获取文件配置
file_config = self.get_file_config_by_id(file_id) file_config = self.get_file_config_by_id(file_id)
if not file_config: if not file_config:
raise Exception(f"文件ID {file_id} 对应的模板不存在或未启用") # 提供更详细的错误信息
raise Exception(
f"文件ID {file_id} 对应的模板不存在或未启用。"
f"请通过查询 f_polic_file_config 表获取有效的文件ID"
f"或访问 /api/file-configs 接口查看可用的文件配置列表。"
)
# 检查file_path是否存在 # 检查file_path是否存在
file_path = file_config.get('file_path') file_path = file_config.get('file_path')

View File

@ -327,10 +327,13 @@
<div class="form-group"> <div class="form-group">
<label>文件列表</label> <label>文件列表</label>
<div style="margin-bottom: 10px;">
<button class="btn btn-secondary" onclick="loadAvailableFiles()" style="margin-right: 10px;">📋 加载可用文件列表</button>
<button class="btn btn-secondary" onclick="addFileItem()">+ 手动添加文件</button>
</div>
<div id="fileListContainer"> <div id="fileListContainer">
<!-- 动态生成的文件列表 --> <!-- 动态生成的文件列表 -->
</div> </div>
<button class="btn btn-secondary" onclick="addFileItem()">+ 添加文件</button>
</div> </div>
</div> </div>
@ -548,28 +551,82 @@
// ==================== 文档生成接口相关 ==================== // ==================== 文档生成接口相关 ====================
function initGenerateTab() { async function loadAvailableFiles() {
try {
const response = await fetch('/api/file-configs');
const result = await response.json();
if (result.isSuccess && result.data && result.data.fileConfigs) {
const container = document.getElementById('fileListContainer');
container.innerHTML = ''; // 清空现有列表
// 只添加有filePath的文件有模板文件的
const filesWithPath = result.data.fileConfigs.filter(f => f.filePath);
if (filesWithPath.length === 0) {
alert('没有找到可用的文件配置需要有filePath');
return;
}
// 添加前5个文件作为示例
filesWithPath.slice(0, 5).forEach(file => {
addFileItem(file.fileId, file.fileName);
});
if (filesWithPath.length > 5) {
alert(`已加载前5个文件共找到 ${filesWithPath.length} 个可用文件`);
} else {
alert(`已加载 ${filesWithPath.length} 个可用文件`);
}
} else {
alert('获取文件列表失败: ' + (result.errorMsg || '未知错误'));
}
} catch (error) {
alert('加载文件列表失败: ' + error.message);
}
}
async function initGenerateTab() {
// 初始化默认字段(完整的虚拟测试数据) // 初始化默认字段(完整的虚拟测试数据)
addGenerateField('target_name', '张三'); addGenerateField('target_name', '张三');
addGenerateField('target_gender', '男'); addGenerateField('target_gender', '男');
addGenerateField('target_age', '44'); addGenerateField('target_age', '34');
addGenerateField('target_date_of_birth', '198005'); addGenerateField('target_date_of_birth', '199009');
addGenerateField('target_organization_and_position', '某公司总经理'); addGenerateField('target_organization_and_position', '云南省农业机械公司党支部书记、经理');
addGenerateField('target_organization', '某公司'); addGenerateField('target_organization', '云南省农业机械公司');
addGenerateField('target_position', '总经理'); addGenerateField('target_position', '党支部书记、经理');
addGenerateField('target_education_level', '本科'); addGenerateField('target_education_level', '研究生');
addGenerateField('target_political_status', '中共党员'); addGenerateField('target_political_status', '中共党员');
addGenerateField('target_professional_rank', '正处级'); addGenerateField('target_professional_rank', '');
addGenerateField('clue_source', '群众举报'); addGenerateField('clue_source', '');
addGenerateField('target_issue_description', '违反国家计划生育有关政策规定于2010年10月生育二胎。'); addGenerateField('target_issue_description', '张三多次在私下聚会、网络群组中发表抹黑党中央决策部署的言论传播歪曲党的理论和路线方针政策的错误观点频繁接受管理服务对象安排的高档宴请、私人会所聚餐以及高尔夫球、高端足浴等娱乐活动相关费用均由对方全额承担在干部选拔任用、岗位调整工作中利用职务便利收受他人财物利用职权为其亲属经营的公司谋取不正当利益帮助该公司违规承接本单位及关联单位工程项目3个合同总额超200万元从中收受亲属给予的"感谢费"15万元其本人沉迷赌博活动每周至少参与1次大额赌资赌博单次赌资超1万元累计赌资达数十万元。');
addGenerateField('department_opinion', '建议进行初步核实'); addGenerateField('department_opinion', '');
addGenerateField('filler_name', '李四'); addGenerateField('filler_name', '');
// 初始化默认文件使用fileId不再需要templateCode // 自动加载可用的文件列表只加载前2个作为示例
// fileId可以从f_polic_file_config表查询获取 try {
const response = await fetch('/api/file-configs');
const result = await response.json();
if (result.isSuccess && result.data && result.data.fileConfigs) {
// 只添加有filePath的文件有模板文件的
const filesWithPath = result.data.fileConfigs.filter(f => f.filePath);
// 添加前2个文件作为示例
filesWithPath.slice(0, 2).forEach(file => {
addFileItem(file.fileId, file.fileName);
});
} else {
// 如果加载失败使用默认的fileId
addFileItem(1765273961883544, '初步核实审批表.doc'); // 2.初步核实审批表XXX addFileItem(1765273961883544, '初步核实审批表.doc'); // 2.初步核实审批表XXX
addFileItem(1765273961563507, '请示报告卡.doc'); // 1.请示报告卡XXX addFileItem(1765273961563507, '请示报告卡.doc'); // 1.请示报告卡XXX
} }
} catch (error) {
// 如果加载失败使用默认的fileId
addFileItem(1765273961883544, '初步核实审批表.doc');
addFileItem(1765273961563507, '请示报告卡.doc');
}
}
function addGenerateField(fieldCode = '', fieldValue = '') { function addGenerateField(fieldCode = '', fieldValue = '') {
const container = document.getElementById('generateFieldsContainer'); const container = document.getElementById('generateFieldsContainer');