|
@@ -44,6 +44,52 @@ class SampleService:
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
logger.error(f"初始化 Milvus 集合失败: {e}")
|
|
logger.error(f"初始化 Milvus 集合失败: {e}")
|
|
|
|
|
|
|
|
|
|
+ def _format_document_row(self, item: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
|
+ """格式化文档行数据,处理URL、日期映射和文件名显示"""
|
|
|
|
|
+ if not item:
|
|
|
|
|
+ return item
|
|
|
|
|
+
|
|
|
|
|
+ # 1. 处理 URL 转换
|
|
|
|
|
+ for key in ['file_url', 'md_url', 'json_url']:
|
|
|
|
|
+ if item.get(key):
|
|
|
|
|
+ item[key] = self.minio_manager.get_full_url(item[key])
|
|
|
|
|
+
|
|
|
|
|
+ # 2. 映射字段以适配前端通用显示
|
|
|
|
|
+ source_type = item.get('source_type')
|
|
|
|
|
+ if source_type == 'basis':
|
|
|
|
|
+ # 标准规范特有映射
|
|
|
|
|
+ if 'standard_number' in item:
|
|
|
|
|
+ item['standard_no'] = item.get('standard_number')
|
|
|
|
|
+ elif source_type == 'work':
|
|
|
|
|
+ # 施工方案特有映射
|
|
|
|
|
+ item['issuing_authority'] = item.get('compiling_unit')
|
|
|
|
|
+ item['release_date'] = item.get('compiling_date')
|
|
|
|
|
+ elif source_type == 'job':
|
|
|
|
|
+ # 办公制度特有映射
|
|
|
|
|
+ item['issuing_authority'] = item.get('issuing_department')
|
|
|
|
|
+ item['release_date'] = item.get('publish_date')
|
|
|
|
|
+
|
|
|
|
|
+ # 3. 格式化时间
|
|
|
|
|
+ date_keys = [
|
|
|
|
|
+ 'created_time', 'updated_time', 'release_date',
|
|
|
|
|
+ 'publish_date', 'compiling_date', 'implementation_date',
|
|
|
|
|
+ 'effective_start_date', 'effective_end_date'
|
|
|
|
|
+ ]
|
|
|
|
|
+ for key in date_keys:
|
|
|
|
|
+ val = item.get(key)
|
|
|
|
|
+ if val and hasattr(val, 'isoformat'):
|
|
|
|
|
+ item[key] = val.isoformat()
|
|
|
|
|
+ elif val is not None:
|
|
|
|
|
+ item[key] = str(val)
|
|
|
|
|
+
|
|
|
|
|
+ # 4. 增加格式化文件名供前端显示
|
|
|
|
|
+ if item.get('conversion_status') == 2:
|
|
|
|
|
+ title = item.get('title', 'document')
|
|
|
|
|
+ item['md_display_name'] = f"{title}.md"
|
|
|
|
|
+ item['json_display_name'] = f"{title}.json"
|
|
|
|
|
+
|
|
|
|
|
+ return item
|
|
|
|
|
+
|
|
|
async def get_upload_url(self, filename: str, content_type: str) -> Tuple[bool, str, Dict[str, Any]]:
|
|
async def get_upload_url(self, filename: str, content_type: str) -> Tuple[bool, str, Dict[str, Any]]:
|
|
|
"""获取 MinIO 预签名上传 URL"""
|
|
"""获取 MinIO 预签名上传 URL"""
|
|
|
try:
|
|
try:
|
|
@@ -296,37 +342,7 @@ class SampleService:
|
|
|
|
|
|
|
|
logger.info(f"Executing SQL: {sql} with params: {params}")
|
|
logger.info(f"Executing SQL: {sql} with params: {params}")
|
|
|
cursor.execute(sql, tuple(params))
|
|
cursor.execute(sql, tuple(params))
|
|
|
- items = []
|
|
|
|
|
- for row in cursor.fetchall():
|
|
|
|
|
- item = row
|
|
|
|
|
- # 处理 URL 转换
|
|
|
|
|
- for key in ['file_url', 'md_url', 'json_url']:
|
|
|
|
|
- if item.get(key):
|
|
|
|
|
- item[key] = self.minio_manager.get_full_url(item[key])
|
|
|
|
|
-
|
|
|
|
|
- # 映射字段以适配前端通用显示
|
|
|
|
|
- source_type = item.get('source_type')
|
|
|
|
|
- if source_type == 'work':
|
|
|
|
|
- item['issuing_authority'] = item.get('compiling_unit')
|
|
|
|
|
- item['release_date'] = item.get('compiling_date')
|
|
|
|
|
- elif source_type == 'job':
|
|
|
|
|
- item['issuing_authority'] = item.get('issuing_department')
|
|
|
|
|
- item['release_date'] = item.get('publish_date')
|
|
|
|
|
-
|
|
|
|
|
- # 格式化时间
|
|
|
|
|
- for key in ['created_time', 'updated_time', 'release_date', 'publish_date', 'compiling_date']:
|
|
|
|
|
- if item.get(key) and hasattr(item[key], 'isoformat'):
|
|
|
|
|
- item[key] = item[key].isoformat()
|
|
|
|
|
- elif item.get(key) is not None:
|
|
|
|
|
- item[key] = str(item[key])
|
|
|
|
|
-
|
|
|
|
|
- # 增加格式化文件名供前端显示
|
|
|
|
|
- if item.get('conversion_status') == 2:
|
|
|
|
|
- title = item.get('title', 'document')
|
|
|
|
|
- item['md_display_name'] = f"{title}.md"
|
|
|
|
|
- item['json_display_name'] = f"{title}.json"
|
|
|
|
|
-
|
|
|
|
|
- items.append(item)
|
|
|
|
|
|
|
+ items = [self._format_document_row(row) for row in cursor.fetchall()]
|
|
|
|
|
|
|
|
# 总数
|
|
# 总数
|
|
|
count_sql = f"SELECT COUNT(*) as count FROM {from_sql} {where_sql}"
|
|
count_sql = f"SELECT COUNT(*) as count FROM {from_sql} {where_sql}"
|
|
@@ -386,39 +402,9 @@ class SampleService:
|
|
|
# 将子表字段合并到 doc 中,方便前端使用
|
|
# 将子表字段合并到 doc 中,方便前端使用
|
|
|
# 注意:如果字段名冲突,子表字段会覆盖主表字段(除了 id)
|
|
# 注意:如果字段名冲突,子表字段会覆盖主表字段(除了 id)
|
|
|
sub_data.pop('id', None)
|
|
sub_data.pop('id', None)
|
|
|
-
|
|
|
|
|
- # 特殊处理一些前端需要的映射字段
|
|
|
|
|
- if source_type == 'basis':
|
|
|
|
|
- doc['standard_no'] = sub_data.get('standard_number')
|
|
|
|
|
- elif source_type == 'work':
|
|
|
|
|
- doc['issuing_authority'] = sub_data.get('compiling_unit')
|
|
|
|
|
- doc['release_date'] = sub_data.get('compiling_date')
|
|
|
|
|
- elif source_type == 'job':
|
|
|
|
|
- doc['issuing_authority'] = sub_data.get('issuing_department')
|
|
|
|
|
- doc['release_date'] = sub_data.get('publish_date')
|
|
|
|
|
-
|
|
|
|
|
doc.update(sub_data)
|
|
doc.update(sub_data)
|
|
|
|
|
|
|
|
- # 格式化时间
|
|
|
|
|
- for key in ['created_time', 'updated_time', 'release_date', 'publish_date', 'compiling_date', 'implementation_date']:
|
|
|
|
|
- val = doc.get(key)
|
|
|
|
|
- if val and hasattr(val, 'isoformat'):
|
|
|
|
|
- doc[key] = val.isoformat()
|
|
|
|
|
- elif val is not None:
|
|
|
|
|
- doc[key] = str(val)
|
|
|
|
|
-
|
|
|
|
|
- # 处理 URL 转换
|
|
|
|
|
- for key in ['file_url', 'md_url', 'json_url']:
|
|
|
|
|
- if doc.get(key):
|
|
|
|
|
- doc[key] = self.minio_manager.get_full_url(doc[key])
|
|
|
|
|
-
|
|
|
|
|
- # 增加格式化文件名供前端显示
|
|
|
|
|
- if doc.get('conversion_status') == 2:
|
|
|
|
|
- title = doc.get('title', 'document')
|
|
|
|
|
- doc['md_display_name'] = f"{title}.md"
|
|
|
|
|
- doc['json_display_name'] = f"{title}.json"
|
|
|
|
|
-
|
|
|
|
|
- return doc
|
|
|
|
|
|
|
+ return self._format_document_row(doc)
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
logger.exception("获取文档详情失败")
|
|
logger.exception("获取文档详情失败")
|
|
|
return None
|
|
return None
|
|
@@ -674,6 +660,7 @@ class SampleService:
|
|
|
s.id, s.chinese_name as title, s.standard_number as standard_no,
|
|
s.id, s.chinese_name as title, s.standard_number as standard_no,
|
|
|
s.issuing_authority, s.release_date, s.document_type,
|
|
s.issuing_authority, s.release_date, s.document_type,
|
|
|
s.professional_field, s.validity, s.note,
|
|
s.professional_field, s.validity, s.note,
|
|
|
|
|
+ s.participating_units, s.reference_basis,
|
|
|
s.created_by, u1.username as creator_name, s.created_time,
|
|
s.created_by, u1.username as creator_name, s.created_time,
|
|
|
s.updated_by, u2.username as updater_name, s.updated_time,
|
|
s.updated_by, u2.username as updater_name, s.updated_time,
|
|
|
m.file_url, m.conversion_status, m.md_url, m.json_url
|
|
m.file_url, m.conversion_status, m.md_url, m.json_url
|
|
@@ -925,7 +912,8 @@ class SampleService:
|
|
|
INSERT INTO {table_name} (
|
|
INSERT INTO {table_name} (
|
|
|
id, chinese_name, english_name, standard_number, issuing_authority,
|
|
id, chinese_name, english_name, standard_number, issuing_authority,
|
|
|
release_date, implementation_date, drafting_unit, approving_department,
|
|
release_date, implementation_date, drafting_unit, approving_department,
|
|
|
- participating_units, document_type, professional_field, engineering_phase,
|
|
|
|
|
|
|
+ participating_units,
|
|
|
|
|
+ document_type, professional_field, engineering_phase,
|
|
|
validity, reference_basis, source_url, note,
|
|
validity, reference_basis, source_url, note,
|
|
|
created_by, updated_by, created_time, updated_time
|
|
created_by, updated_by, created_time, updated_time
|
|
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
|
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
|
|
@@ -933,7 +921,8 @@ class SampleService:
|
|
|
params = (
|
|
params = (
|
|
|
doc_id, data.get('title'), data.get('english_name'), data.get('standard_no'),
|
|
doc_id, data.get('title'), data.get('english_name'), data.get('standard_no'),
|
|
|
data.get('issuing_authority'), self._to_date(data.get('release_date')), self._to_date(data.get('implementation_date')),
|
|
data.get('issuing_authority'), self._to_date(data.get('release_date')), self._to_date(data.get('implementation_date')),
|
|
|
- data.get('drafting_unit'), data.get('approving_department'), data.get('participating_units'),
|
|
|
|
|
|
|
+ data.get('drafting_unit'), data.get('approving_department'),
|
|
|
|
|
+ data.get('participating_units'),
|
|
|
data.get('document_type'), data.get('professional_field'), data.get('engineering_phase'),
|
|
data.get('document_type'), data.get('professional_field'), data.get('engineering_phase'),
|
|
|
data.get('validity', '现行'), data.get('reference_basis'), data.get('source_url'), data.get('note'),
|
|
data.get('validity', '现行'), data.get('reference_basis'), data.get('source_url'), data.get('note'),
|
|
|
user_id, user_id
|
|
user_id, user_id
|
|
@@ -988,9 +977,9 @@ class SampleService:
|
|
|
cursor.close()
|
|
cursor.close()
|
|
|
conn.close()
|
|
conn.close()
|
|
|
|
|
|
|
|
- async def edit_basic_info(self, type: str, info_id: str, data: Dict[str, Any], updater_id: str) -> Tuple[bool, str]:
|
|
|
|
|
|
|
+ async def edit_basic_info(self, type: str, doc_id: str, data: Dict[str, Any], updater_id: str) -> Tuple[bool, str]:
|
|
|
"""编辑基本信息"""
|
|
"""编辑基本信息"""
|
|
|
- logger.info(f"Editing basic info for type {type}, id {info_id}: {data}")
|
|
|
|
|
|
|
+ logger.info(f"Editing basic info for type {type}, id {doc_id}: {data}")
|
|
|
conn = get_db_connection()
|
|
conn = get_db_connection()
|
|
|
if not conn:
|
|
if not conn:
|
|
|
return False, "数据库连接失败"
|
|
return False, "数据库连接失败"
|
|
@@ -1012,7 +1001,7 @@ class SampleService:
|
|
|
SET title = %s, file_url = %s, file_extension = %s, updated_by = %s, updated_time = NOW()
|
|
SET title = %s, file_url = %s, file_extension = %s, updated_by = %s, updated_time = NOW()
|
|
|
WHERE id = %s
|
|
WHERE id = %s
|
|
|
""",
|
|
""",
|
|
|
- (data.get('title'), file_url, file_extension, updater_id, info_id)
|
|
|
|
|
|
|
+ (data.get('title'), file_url, file_extension, updater_id, doc_id)
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
# 2. 更新子表 (移除 file_url)
|
|
# 2. 更新子表 (移除 file_url)
|
|
@@ -1022,8 +1011,10 @@ class SampleService:
|
|
|
SET chinese_name = %s, standard_number = %s, issuing_authority = %s, release_date = %s,
|
|
SET chinese_name = %s, standard_number = %s, issuing_authority = %s, release_date = %s,
|
|
|
document_type = %s, professional_field = %s, validity = %s,
|
|
document_type = %s, professional_field = %s, validity = %s,
|
|
|
english_name = %s, implementation_date = %s, drafting_unit = %s,
|
|
english_name = %s, implementation_date = %s, drafting_unit = %s,
|
|
|
- approving_department = %s, participating_units = %s, engineering_phase = %s,
|
|
|
|
|
- reference_basis = %s, source_url = %s, note = %s,
|
|
|
|
|
|
|
+ approving_department = %s, engineering_phase = %s,
|
|
|
|
|
+ participating_units = %s,
|
|
|
|
|
+ reference_basis = %s,
|
|
|
|
|
+ source_url = %s, note = %s,
|
|
|
updated_by = %s, updated_time = NOW()
|
|
updated_by = %s, updated_time = NOW()
|
|
|
WHERE id = %s
|
|
WHERE id = %s
|
|
|
"""
|
|
"""
|
|
@@ -1031,9 +1022,11 @@ class SampleService:
|
|
|
data.get('title'), data.get('standard_no'), data.get('issuing_authority'), self._to_date(data.get('release_date')),
|
|
data.get('title'), data.get('standard_no'), data.get('issuing_authority'), self._to_date(data.get('release_date')),
|
|
|
data.get('document_type'), data.get('professional_field'), data.get('validity'),
|
|
data.get('document_type'), data.get('professional_field'), data.get('validity'),
|
|
|
data.get('english_name'), self._to_date(data.get('implementation_date')), data.get('drafting_unit'),
|
|
data.get('english_name'), self._to_date(data.get('implementation_date')), data.get('drafting_unit'),
|
|
|
- data.get('approving_department'), data.get('participating_units'), data.get('engineering_phase'),
|
|
|
|
|
- data.get('reference_basis'), data.get('source_url'), data.get('note'),
|
|
|
|
|
- updater_id, info_id
|
|
|
|
|
|
|
+ data.get('approving_department'), data.get('engineering_phase'),
|
|
|
|
|
+ data.get('participating_units'),
|
|
|
|
|
+ data.get('reference_basis'),
|
|
|
|
|
+ data.get('source_url'), data.get('note'),
|
|
|
|
|
+ updater_id, doc_id
|
|
|
)
|
|
)
|
|
|
elif type == 'work':
|
|
elif type == 'work':
|
|
|
sql = f"""
|
|
sql = f"""
|
|
@@ -1050,7 +1043,7 @@ class SampleService:
|
|
|
data.get('issuing_authority'), self._to_date(data.get('release_date')),
|
|
data.get('issuing_authority'), self._to_date(data.get('release_date')),
|
|
|
data.get('plan_summary'), data.get('compilation_basis'), data.get('plan_category'),
|
|
data.get('plan_summary'), data.get('compilation_basis'), data.get('plan_category'),
|
|
|
data.get('level_1_classification'), data.get('level_2_classification'), data.get('level_3_classification'), data.get('level_4_classification'),
|
|
data.get('level_1_classification'), data.get('level_2_classification'), data.get('level_3_classification'), data.get('level_4_classification'),
|
|
|
- data.get('note'), updater_id, info_id
|
|
|
|
|
|
|
+ data.get('note'), updater_id, doc_id
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
elif type == 'job':
|
|
elif type == 'job':
|
|
@@ -1064,7 +1057,7 @@ class SampleService:
|
|
|
params = (
|
|
params = (
|
|
|
data.get('title'), data.get('issuing_authority'), data.get('document_type'), self._to_date(data.get('release_date')),
|
|
data.get('title'), data.get('issuing_authority'), data.get('document_type'), self._to_date(data.get('release_date')),
|
|
|
self._to_date(data.get('effective_start_date')), self._to_date(data.get('effective_end_date')), data.get('note'),
|
|
self._to_date(data.get('effective_start_date')), self._to_date(data.get('effective_end_date')), data.get('note'),
|
|
|
- updater_id, info_id
|
|
|
|
|
|
|
+ updater_id, doc_id
|
|
|
)
|
|
)
|
|
|
else:
|
|
else:
|
|
|
return False, "不支持的类型"
|
|
return False, "不支持的类型"
|
|
@@ -1081,7 +1074,7 @@ class SampleService:
|
|
|
cursor.close()
|
|
cursor.close()
|
|
|
conn.close()
|
|
conn.close()
|
|
|
|
|
|
|
|
- async def delete_basic_info(self, type: str, info_id: str) -> Tuple[bool, str]:
|
|
|
|
|
|
|
+ async def delete_basic_info(self, type: str, doc_id: str) -> Tuple[bool, str]:
|
|
|
"""删除基本信息"""
|
|
"""删除基本信息"""
|
|
|
conn = get_db_connection()
|
|
conn = get_db_connection()
|
|
|
if not conn:
|
|
if not conn:
|
|
@@ -1094,13 +1087,13 @@ class SampleService:
|
|
|
return False, "无效的类型"
|
|
return False, "无效的类型"
|
|
|
|
|
|
|
|
# 1. 删除主表记录 (由于设置了 ON DELETE CASCADE,子表记录会自动删除)
|
|
# 1. 删除主表记录 (由于设置了 ON DELETE CASCADE,子表记录会自动删除)
|
|
|
- cursor.execute("DELETE FROM t_samp_document_main WHERE id = %s", (info_id,))
|
|
|
|
|
|
|
+ cursor.execute("DELETE FROM t_samp_document_main WHERE id = %s", (doc_id,))
|
|
|
|
|
|
|
|
# 同步删除任务管理中心的数据
|
|
# 同步删除任务管理中心的数据
|
|
|
try:
|
|
try:
|
|
|
- await task_service.delete_task(info_id)
|
|
|
|
|
|
|
+ await task_service.delete_task(doc_id)
|
|
|
except Exception as task_err:
|
|
except Exception as task_err:
|
|
|
- logger.error(f"同步删除任务中心数据失败 (ID: {info_id}): {task_err}")
|
|
|
|
|
|
|
+ logger.error(f"同步删除任务中心数据失败 (ID: {doc_id}): {task_err}")
|
|
|
|
|
|
|
|
conn.commit()
|
|
conn.commit()
|
|
|
return True, "删除成功"
|
|
return True, "删除成功"
|