diff --git a/vue-fastapi-backend/module_admin/controller/cdplb_controller.py b/vue-fastapi-backend/module_admin/controller/cdplb_controller.py index a8a1f33..f6f1acf 100644 --- a/vue-fastapi-backend/module_admin/controller/cdplb_controller.py +++ b/vue-fastapi-backend/module_admin/controller/cdplb_controller.py @@ -1,6 +1,6 @@ from typing import List -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, File, UploadFile, Query from sqlalchemy.ext.asyncio import AsyncSession from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel @@ -8,6 +8,7 @@ from module_admin.entity.vo.dataint_vo import CdplbPageObject, SaveCdplbModel from module_admin.service.login_service import LoginService from module_admin.service.cdplb_service import CdplbService from utils.response_util import ResponseUtil +from utils.common_util import bytes2file_response cdplbController = APIRouter(prefix='/dataint/cdplb', dependencies=[Depends(LoginService.get_current_user)]) @@ -36,3 +37,20 @@ async def delete_tsmcb(request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): result = await CdplbService.delete_cdplb(query_db, array) return ResponseUtil.success(msg=result.message) + + +@cdplbController.post("/importTemplate") +async def export_system_user_template(request: Request, query_db: AsyncSession = Depends(get_db)): + meta_import_template_result = await CdplbService.get_import_template_services() + return ResponseUtil.streaming(data=bytes2file_response(meta_import_template_result)) + + +@cdplbController.post("/upload") +async def batch_import_cdplb_data( + request: Request, + file: UploadFile = File(...), + overWrite: bool = Query(alias='overWrite'), + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + batch_import_result = await CdplbService.batch_import_cdplb_data(query_db, file, overWrite, current_user) + return ResponseUtil.success(data=batch_import_result) diff --git a/vue-fastapi-backend/module_admin/controller/fccbd_controller.py b/vue-fastapi-backend/module_admin/controller/fccbd_controller.py index 4e654c6..94455ea 100644 --- a/vue-fastapi-backend/module_admin/controller/fccbd_controller.py +++ b/vue-fastapi-backend/module_admin/controller/fccbd_controller.py @@ -1,6 +1,6 @@ from typing import List -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, UploadFile, File, Query from sqlalchemy.ext.asyncio import AsyncSession from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel @@ -8,6 +8,7 @@ from module_admin.entity.vo.dataint_vo import FccbdPageObject, SaveFccbdModel from module_admin.service.login_service import LoginService from module_admin.service.fccbd_service import FccbdService from utils.response_util import ResponseUtil +from utils.common_util import bytes2file_response fccbdController = APIRouter(prefix='/dataint/fccbd', dependencies=[Depends(LoginService.get_current_user)]) @@ -36,3 +37,20 @@ async def delete_tsmcb(request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): result = await FccbdService.delete_fccbd(query_db, array) return ResponseUtil.success(msg=result.message) + + +@fccbdController.post("/importTemplate") +async def export_system_user_template(request: Request, query_db: AsyncSession = Depends(get_db)): + meta_import_template_result = await FccbdService.get_import_template_services() + return ResponseUtil.streaming(data=bytes2file_response(meta_import_template_result)) + + +@fccbdController.post("/upload") +async def batch_import_fccbd_data( + request: Request, + file: UploadFile = File(...), + overWrite: bool = Query(alias='overWrite'), + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + batch_import_result = await FccbdService.batch_import_fccbd_data(query_db, file, overWrite, current_user) + return ResponseUtil.success(data=batch_import_result) diff --git a/vue-fastapi-backend/module_admin/controller/tsmcb_controller.py b/vue-fastapi-backend/module_admin/controller/tsmcb_controller.py index e4bfd62..50736a7 100644 --- a/vue-fastapi-backend/module_admin/controller/tsmcb_controller.py +++ b/vue-fastapi-backend/module_admin/controller/tsmcb_controller.py @@ -1,6 +1,6 @@ from typing import List -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, UploadFile, File, Query from sqlalchemy.ext.asyncio import AsyncSession from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel @@ -8,34 +8,49 @@ from module_admin.entity.vo.dataint_vo import TsmcbPageObject, SaveTsmcbModel from module_admin.service.login_service import LoginService from module_admin.service.tsmcb_service import TsmcbService from utils.response_util import ResponseUtil - +from utils.common_util import bytes2file_response tsmcbController = APIRouter(prefix='/dataint/tsmcb', dependencies=[Depends(LoginService.get_current_user)]) @tsmcbController.get("/list") async def get_tsmcb_list(request: Request, tsmcb_query: TsmcbPageObject = Depends(TsmcbPageObject.as_query), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): meta_query_result = await TsmcbService.get_tsmcb_list_services(query_db, tsmcb_query, current_user) return ResponseUtil.success(data=meta_query_result) @tsmcbController.post("/save") async def save_tsmcb(request: Request, - saveTsmcbModel: SaveTsmcbModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + saveTsmcbModel: SaveTsmcbModel, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): result = await TsmcbService.save_tsmcb(query_db, saveTsmcbModel, current_user) return ResponseUtil.success(msg=result.message) + @tsmcbController.post("/delete") async def delete_tsmcb(request: Request, - array: List[str], - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + array: List[str], + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): result = await TsmcbService.delete_tsmcb(query_db, array) return ResponseUtil.success(msg=result.message) +@tsmcbController.post("/upload") +async def batch_import_tsmcb_data( + request: Request, + file: UploadFile = File(...), + overWrite: bool = Query(alias='overWrite'), + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + batch_import_result = await TsmcbService.batch_import_tsmcb_data(query_db, file, overWrite, current_user) + return ResponseUtil.success(data=batch_import_result) + +@tsmcbController.post("/importTemplate") +async def export_tsmcb_template(request: Request, query_db: AsyncSession = Depends(get_db)): + meta_import_template_result = await TsmcbService.get_import_template_services() + return ResponseUtil.streaming(data=bytes2file_response(meta_import_template_result)) diff --git a/vue-fastapi-backend/module_admin/dao/fccbd_dao.py b/vue-fastapi-backend/module_admin/dao/fccbd_dao.py index 827aa9d..c380e8e 100644 --- a/vue-fastapi-backend/module_admin/dao/fccbd_dao.py +++ b/vue-fastapi-backend/module_admin/dao/fccbd_dao.py @@ -18,9 +18,9 @@ class FccbdDao: async def get_fccbd_list(cls, db: AsyncSession, fccbd_query: FccbdPageObject): query = ( select(SysFccbd).where( - SysFccbd.pos == fccbd_query.pos if fccbd_query.pos else True, - SysFccbd.pos_name == fccbd_query.pos_name if fccbd_query.pos_name else True, - SysFccbd.term == fccbd_query.term if fccbd_query.term else True, + SysFccbd.pos.like(f'%{fccbd_query.pos}%') if fccbd_query.pos else True, + SysFccbd.pos_name.like(f'%{fccbd_query.pos_name}%') if fccbd_query.pos_name else True, + SysFccbd.term.like(f'%{fccbd_query.term}%') if fccbd_query.term else True, SysFccbd.status == fccbd_query.status if fccbd_query.status else True ).distinct() ) diff --git a/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py index 46e6ca0..2d85853 100644 --- a/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py +++ b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py @@ -59,7 +59,7 @@ class MetadataConfigDao: 获取标签信息列表(支持分页) """ query = select(MetadataClas).where( - MetadataClas.belt_batch_content==query_object.belt_batch_content if query_object.belt_batch_content else True, + MetadataClas.belt_batch_content.in_([int(x) for x in query_object.onumStr.split(',')]) if query_object.onumStr else True, MetadataClas.clas_name.like(f"%{query_object.clas_name}%") if query_object.clas_name else True, MetadataClas.clas_eff_flag == query_object.clas_eff_flag if query_object.clas_eff_flag else True, MetadataClas.upd_time.between( diff --git a/vue-fastapi-backend/module_admin/dao/metatask_dao.py b/vue-fastapi-backend/module_admin/dao/metatask_dao.py index aa2ab32..2e96d25 100644 --- a/vue-fastapi-backend/module_admin/dao/metatask_dao.py +++ b/vue-fastapi-backend/module_admin/dao/metatask_dao.py @@ -58,7 +58,7 @@ class MetataskDao: Metatask.metatask_name.like(f'%{query_object.metatask_name}%') if query_object.metatask_name else True, Metatask.metatask_id == query_object.metatask_id if query_object.metatask_id else True, Metatask.metatask_type == query_object.metatask_type if query_object.metatask_type else True, - Metatask.dbRCode == query_object.dbRCode if query_object.dbRCode else False, + Metatask.dbRCode.in_([int(x) for x in query_object.dbRcodeStr.split(',')]) if query_object.dbRcodeStr else True, Metatask.create_time.between( datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)), datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)), diff --git a/vue-fastapi-backend/module_admin/dao/sscf_dao.py b/vue-fastapi-backend/module_admin/dao/sscf_dao.py index 4d38615..5e57af8 100644 --- a/vue-fastapi-backend/module_admin/dao/sscf_dao.py +++ b/vue-fastapi-backend/module_admin/dao/sscf_dao.py @@ -19,9 +19,9 @@ class SscfDao: async def get_sscf_list(cls, db: AsyncSession, sscf_query: SscfPageObject): query = ( select(SysSscf).where( - SysSscf.keyword == sscf_query.keyword if sscf_query.keyword else True, - SysSscf.type == sscf_query.type if sscf_query.type else True, - SysSscf.dasset_id == sscf_query.dasset_id if sscf_query.dasset_id else True, + SysSscf.keyword.like(f'%{sscf_query.keyword}%') if sscf_query.keyword else True, + SysSscf.type.like(f'%{sscf_query.type}%') if sscf_query.type else True, + SysSscf.dasset_id.in_(sscf_query.dasset_id.split(',')) if sscf_query.dasset_id else True, SysSscf.status == sscf_query.status if sscf_query.status else True ).distinct() ) diff --git a/vue-fastapi-backend/module_admin/dao/tsmcb_dao.py b/vue-fastapi-backend/module_admin/dao/tsmcb_dao.py index 6b5dd72..c74c859 100644 --- a/vue-fastapi-backend/module_admin/dao/tsmcb_dao.py +++ b/vue-fastapi-backend/module_admin/dao/tsmcb_dao.py @@ -18,9 +18,9 @@ class TsmcbDao: async def get_tsmcb_list(cls, db: AsyncSession, tsmcb_query: TsmcbPageObject): query = ( select(SysTsmcb).where( - SysTsmcb.pos == tsmcb_query.pos if tsmcb_query.pos else True, - SysTsmcb.type == tsmcb_query.type if tsmcb_query.type else True, - SysTsmcb.std_rpl_str == tsmcb_query.std_rpl_str if tsmcb_query.std_rpl_str else True, + SysTsmcb.pos.like(f'%{tsmcb_query.pos}%') if tsmcb_query.pos else True, + SysTsmcb.type.like(f'%{tsmcb_query.type}%') if tsmcb_query.type else True, + SysTsmcb.std_rpl_str.like(f'%{tsmcb_query.std_rpl_str}%') if tsmcb_query.std_rpl_str else True, SysTsmcb.status == tsmcb_query.status if tsmcb_query.status else True ).distinct() ) diff --git a/vue-fastapi-backend/module_admin/dao/vecset_dao.py b/vue-fastapi-backend/module_admin/dao/vecset_dao.py index 0c6aa57..344b1a5 100644 --- a/vue-fastapi-backend/module_admin/dao/vecset_dao.py +++ b/vue-fastapi-backend/module_admin/dao/vecset_dao.py @@ -18,12 +18,12 @@ class VecsetDao: async def get_vecset_list(cls, db: AsyncSession, vecset_query: VecsetPageObject): query = ( select(SysVecset).where( - SysVecset.dasset_id == vecset_query.dasset_id if vecset_query.dasset_id else True, - SysVecset.stab_name == vecset_query.stab_name if vecset_query.stab_name else True, - SysVecset.squery == vecset_query.squery if vecset_query.squery else True, - SysVecset.sanal_plan == vecset_query.sanal_plan if vecset_query.sanal_plan else True, + SysVecset.dasset_id.in_(vecset_query.dasset_id.split(',')) if vecset_query.dasset_id else True, + SysVecset.stab_name.like(f'%{vecset_query.stab_name}%') if vecset_query.stab_name else True, + SysVecset.squery.like(f'%{vecset_query.squery}%') if vecset_query.squery else True, + SysVecset.sanal_plan.like(f'%{vecset_query.sanal_plan}%') if vecset_query.sanal_plan else True, + SysVecset.data_domain.like(f'%{vecset_query.data_domain}%') if vecset_query.data_domain else True, SysVecset.status == vecset_query.status if vecset_query.status else True, - SysVecset.data_domain == vecset_query.data_domain if vecset_query.data_domain else True, ).distinct() ) query_result = await PageUtil.paginate(db, query, vecset_query.page_num, vecset_query.page_size, True) diff --git a/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py index d91d3bf..d0117d0 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py @@ -35,6 +35,7 @@ class MetadataClasQueryModel(MetadataClasModel): """ 标签信息不分页查询模型 """ + onumStr: Optional[str] = Field(default=None, description='ids') begin_time: Optional[str] = Field(default=None, description='开始时间') end_time: Optional[str] = Field(default=None, description='结束时间') @@ -44,6 +45,7 @@ class MetadataClasPageQueryModel(MetadataClasQueryModel): """ 标签信息分页查询模型 """ + page_num: int = Field(default=1, description='当前页码') page_size: int = Field(default=10, description='每页记录数') diff --git a/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py b/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py index 952db9a..d5de986 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py @@ -50,6 +50,7 @@ class MetataskQueryModel(MetataskModel): """ 元数据任务不分页查询模型 """ + dbRcodeStr: Optional[str] = Field(default=None, description='系统集合') begin_time: Optional[str]= Field(default=None, description='开始时间') end_time: Optional[str]= Field(default=None, description='结束时间') diff --git a/vue-fastapi-backend/module_admin/service/cdplb_service.py b/vue-fastapi-backend/module_admin/service/cdplb_service.py index 51b0d69..bb232a8 100644 --- a/vue-fastapi-backend/module_admin/service/cdplb_service.py +++ b/vue-fastapi-backend/module_admin/service/cdplb_service.py @@ -1,7 +1,11 @@ +import io import json import uuid from typing import Optional, List + +import pandas as pd +from fastapi import UploadFile from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -10,7 +14,7 @@ from module_admin.entity.do.dataint_do import SysCdplb from module_admin.dao.cdplb_dao import CdplbDao from exceptions.exception import ServiceException, ServiceWarning from datetime import datetime -from utils.common_util import CamelCaseUtil +from utils.common_util import * class CdplbService: @@ -52,3 +56,99 @@ class CdplbService: await db.commit() return CrudResponseModel(is_success=True, message='操作成功') + @staticmethod + async def get_import_template_services(): + """ + 获取元数据导入模板service + :return: 元数据导入模板excel的二进制数据 + """ + table_header_list = ['批量对象表名', '批里对象字段名', '频次', '词性', '词性名称', '状态'] + selector_header_list = ['状态'] + option_list = [{'状态': ['正常', '停用']}] + + sheet_config1 = dict( + sheet_name="词典批量补充", header_list=table_header_list, data_list=[], selector_header_list=selector_header_list + ) + + sheet_configs = [sheet_config1] + binary_data = get_excel_template_with_sheets( + sheet_configs, # 每个Sheet的配置(包含表头、选择器等) + option_list + ) + + return binary_data + + @classmethod + async def batch_import_cdplb_data(cls, + result_db: AsyncSession, + file: UploadFile, + overWrite: bool, + current_user: CurrentUserModel): + table_header_dict = { + '批量对象表名': 'bath_obj_tab_name', + '批里对象字段名': 'bath_obj_fld_name', + '频次': 'freq', + '词性': 'pos', + '词性名称': 'pos_name', + '状态': 'status' + } + contents = await file.read() + excel_file = pd.ExcelFile(io.BytesIO(contents)) + await file.close() + # 获取所有sheet名称 + sheet_names = excel_file.sheet_names + # 逐个读取 + tableSheet = sheet_names[0] + result_list = { + "rows": [], + "successCount": 0 + } + if tableSheet == '词典批量补充': + df = excel_file.parse(sheet_name=tableSheet, dtype=str, keep_default_na=False, na_values=[]) + df.rename(columns=table_header_dict, inplace=True) + for index, row in df.iterrows(): + noneValid = '' + if row['bath_obj_tab_name'] is None or len(row['bath_obj_tab_name']) == 0: + noneValid += "批量对象表名不能为空" + if row['bath_obj_fld_name'] is None or len(row['bath_obj_fld_name']) == 0: + if len(noneValid) > 0: + noneValid += ",批里对象字段名不能为空" + else: + noneValid += "批里对象字段名不能为空" + if row['freq'] is None or len(row['freq']) == 0: + if len(noneValid) > 0: + noneValid += ",频次不能为空" + else: + noneValid += "频次不能为空" + if row['pos'] is None or len(row['pos']) == 0: + if len(noneValid) > 0: + noneValid += ",词性不能为空" + else: + noneValid += "词性不能为空" + if row['pos_name'] is None or len(row['pos_name']) == 0: + if len(noneValid) > 0: + noneValid += ",词性名称不能为空" + else: + noneValid += "词性名称不能为空" + if row['status'] is None or len(row['status']) == 0: + if len(noneValid) > 0: + noneValid += ",状态不能为空" + else: + noneValid += "状态不能为空" + if len(noneValid) > 0: + result_list['rows'].append({ + "row": index + 2, + "errorInfo": noneValid + }) + continue + cdplb = SaveCdplbModel() + cdplb.bath_obj_tab_name = row['bath_obj_tab_name'] + cdplb.bath_obj_fld_name = row['bath_obj_fld_name'] + cdplb.freq = row['freq'] + cdplb.pos = row['pos'] + cdplb.pos_name = row['pos_name'] + cdplb.status = '1' if row['status'] == '正常' else '0' + await cls.save_cdplb(result_db, cdplb, current_user) + result_list['successCount'] += 1 + return result_list + diff --git a/vue-fastapi-backend/module_admin/service/fccbd_service.py b/vue-fastapi-backend/module_admin/service/fccbd_service.py index c5a4e0b..de19cb8 100644 --- a/vue-fastapi-backend/module_admin/service/fccbd_service.py +++ b/vue-fastapi-backend/module_admin/service/fccbd_service.py @@ -1,7 +1,10 @@ import json import uuid -from typing import Optional, List +from typing import Optional, List, io + +import pandas as pd +from fastapi import UploadFile from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -10,7 +13,7 @@ from module_admin.entity.do.dataint_do import SysFccbd from module_admin.dao.fccbd_dao import FccbdDao from exceptions.exception import ServiceException, ServiceWarning from datetime import datetime -from utils.common_util import CamelCaseUtil +from utils.common_util import * class FccbdService: @@ -52,3 +55,92 @@ class FccbdService: await db.commit() return CrudResponseModel(is_success=True, message='操作成功') + @staticmethod + async def get_import_template_services(): + """ + 获取元数据导入模板service + :return: 元数据导入模板excel的二进制数据 + """ + table_header_list = ['词语', '频次', '词性', '词性名称', '状态'] + selector_header_list = ['状态'] + option_list = [{'状态': ['正常', '停用']}] + + sheet_config1 = dict( + sheet_name="分词词典补充", header_list=table_header_list,data_list=[], selector_header_list=selector_header_list + ) + + sheet_configs = [sheet_config1] + binary_data = get_excel_template_with_sheets( + sheet_configs, # 每个Sheet的配置(包含表头、选择器等) + option_list + ) + + return binary_data + + @classmethod + async def batch_import_fccbd_data(cls, + result_db: AsyncSession, + file: UploadFile, + overWrite: bool, + current_user: CurrentUserModel): + table_header_dict = { + '词语': 'term', + '频次': 'freq', + '词性': 'pos', + '词性名称': 'pos_name', + '状态': 'status' + } + contents = await file.read() + excel_file = pd.ExcelFile(io.BytesIO(contents)) + await file.close() + # 获取所有sheet名称 + sheet_names = excel_file.sheet_names + # 逐个读取 + tableSheet = sheet_names[0] + result_list = { + "rows": [], + "successCount": 0 + } + if tableSheet == '分词词典补充': + df = excel_file.parse(sheet_name=tableSheet, dtype=str, keep_default_na=False, na_values=[]) + df.rename(columns=table_header_dict, inplace=True) + for index, row in df.iterrows(): + noneValid = '' + if row['term'] is None or len(row['term']) == 0: + noneValid += "词语不能为空" + if row['freq'] is None or len(row['freq']) == 0: + if len(noneValid) > 0: + noneValid += ",频次不能为空" + else: + noneValid += "频次不能为空" + if row['pos'] is None or len(row['pos']) == 0: + if len(noneValid) > 0: + noneValid += ",词性不能为空" + else: + noneValid += "词性不能为空" + if row['pos_name'] is None or len(row['pos_name']) == 0: + if len(noneValid) > 0: + noneValid += ",词性名称不能为空" + else: + noneValid += "词性名称不能为空" + if row['status'] is None or len(row['status']) == 0: + if len(noneValid) > 0: + noneValid += ",状态不能为空" + else: + noneValid += "状态不能为空" + if len(noneValid) > 0: + result_list['rows'].append({ + "row": index + 2, + "errorInfo": noneValid + }) + continue + fccbd = SaveFccbdModel() + fccbd.term = row['term'] + fccbd.freq = row['freq'] + fccbd.pos = row['pos'] + fccbd.pos_name = row['pos_name'] + fccbd.status = '1' if row['status'] == '1' else '0' + await cls.save_fccbd(result_db, fccbd, current_user) + result_list['successCount'] += 1 + return result_list + diff --git a/vue-fastapi-backend/module_admin/service/tsmcb_service.py b/vue-fastapi-backend/module_admin/service/tsmcb_service.py index e253289..96f52a1 100644 --- a/vue-fastapi-backend/module_admin/service/tsmcb_service.py +++ b/vue-fastapi-backend/module_admin/service/tsmcb_service.py @@ -1,7 +1,11 @@ +import io import json import uuid from typing import Optional, List + +import pandas as pd +from fastapi import UploadFile from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -10,7 +14,7 @@ from module_admin.entity.do.dataint_do import SysTsmcb from module_admin.dao.tsmcb_dao import TsmcbDao from exceptions.exception import ServiceException, ServiceWarning from datetime import datetime -from utils.common_util import CamelCaseUtil +from utils.common_util import * class TsmcbService: @@ -52,3 +56,99 @@ class TsmcbService: await db.commit() return CrudResponseModel(is_success=True, message='操作成功') + @staticmethod + async def get_import_template_services(): + """ + 获取元数据导入模板service + :return: 元数据导入模板excel的二进制数据 + """ + table_header_list = ['词性', '类型', '标准化替换字符', '前缀补充字符', '后缀补充字符', '状态'] + selector_header_list = ['状态'] + option_list = [{'状态': ['正常', '停用']}] + + sheet_config1 = dict( + sheet_name="特殊名词补充", header_list=table_header_list, data_list=[], selector_header_list=selector_header_list + ) + + sheet_configs = [sheet_config1] + binary_data = get_excel_template_with_sheets( + sheet_configs, # 每个Sheet的配置(包含表头、选择器等) + option_list + ) + + return binary_data + + @classmethod + async def batch_import_tsmcb_data(cls, + result_db: AsyncSession, + file: UploadFile, + overWrite: bool, + current_user: CurrentUserModel): + table_header_dict = { + '词性': 'pos', + '类型': 'type', + '标准化替换字符': 'std_rpl_str', + '前缀补充字符': 'prefix_supp_str', + '后缀补充字符': 'suffix_supp_str', + '状态': 'status' + } + contents = await file.read() + excel_file = pd.ExcelFile(io.BytesIO(contents)) + await file.close() + # 获取所有sheet名称 + sheet_names = excel_file.sheet_names + # 逐个读取 + tableSheet = sheet_names[0] + result_list = { + "rows": [], + "successCount": 0 + } + if tableSheet == '特殊名词补充': + df = excel_file.parse(sheet_name=tableSheet, dtype=str, keep_default_na=False, na_values=[]) + df.rename(columns=table_header_dict, inplace=True) + for index, row in df.iterrows(): + noneValid = '' + if row['pos'] is None or len(row['pos']) == 0: + noneValid += "词性不能为空" + if row['type'] is None or len(row['type']) == 0: + if len(noneValid) > 0: + noneValid += ",类型不能为空" + else: + noneValid += "类型不能为空" + if row['std_rpl_str'] is None or len(row['std_rpl_str']) == 0: + if len(noneValid) > 0: + noneValid += ",标准化替换字符不能为空" + else: + noneValid += "标准化替换字符不能为空" + if row['prefix_supp_str'] is None or len(row['prefix_supp_str']) == 0: + if len(noneValid) > 0: + noneValid += ",前缀补充字符不能为空" + else: + noneValid += "前缀补充字符不能为空" + if row['suffix_supp_str'] is None or len(row['suffix_supp_str']) == 0: + if len(noneValid) > 0: + noneValid += ",后缀补充字符名称不能为空" + else: + noneValid += "后缀补充字符名称不能为空" + if row['status'] is None or len(row['status']) == 0: + if len(noneValid) > 0: + noneValid += ",状态不能为空" + else: + noneValid += "状态不能为空" + if len(noneValid) > 0: + result_list['rows'].append({ + "row": index + 2, + "errorInfo": noneValid + }) + continue + tsmcb = SaveTsmcbModel() + tsmcb.pos = row['pos'] + tsmcb.type = row['type'] + tsmcb.std_rpl_str = row['std_rpl_str'] + tsmcb.prefix_supp_str = row['prefix_supp_str'] + tsmcb.suffix_supp_str = row['suffix_supp_str'] + tsmcb.status = '1' if row['status'] == '正常' else '0' + await cls.save_tsmcb(result_db, tsmcb, current_user) + result_list['successCount'] += 1 + return result_list + diff --git a/vue-fastapi-frontend/src/views/aichat/aichat.vue b/vue-fastapi-frontend/src/views/aichat/aichat.vue index d00e063..c980e8d 100644 --- a/vue-fastapi-frontend/src/views/aichat/aichat.vue +++ b/vue-fastapi-frontend/src/views/aichat/aichat.vue @@ -30,7 +30,7 @@