diff --git a/vue-fastapi-backend/config/env.py b/vue-fastapi-backend/config/env.py
index 6af5783..1401c1b 100644
--- a/vue-fastapi-backend/config/env.py
+++ b/vue-fastapi-backend/config/env.py
@@ -14,7 +14,7 @@ class AppSettings(BaseSettings):
app_env: str = 'dev'
app_name: str = 'RuoYi-FasAPI'
- app_root_path: str = '/dev-api'
+ app_root_path: str = '/default-api'
app_host: str = '0.0.0.0'
app_port: int = 9099
app_version: str = '1.0.0'
diff --git a/vue-fastapi-backend/module_admin/controller/approval_controller.py b/vue-fastapi-backend/module_admin/controller/approval_controller.py
new file mode 100644
index 0000000..cc22957
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/controller/approval_controller.py
@@ -0,0 +1,57 @@
+import json
+import os
+import shutil
+from fastapi import APIRouter, Depends, Request, UploadFile, File, Form
+from sqlalchemy.ext.asyncio import AsyncSession
+from config.get_db import get_db
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject
+from module_admin.service.login_service import LoginService
+from module_admin.service.approval_service import ApprovalService
+from utils.log_util import logger
+from utils.response_util import ResponseUtil
+
+approvalController = APIRouter(prefix='/approval', dependencies=[Depends(LoginService.get_current_user)])
+
+
+@approvalController.post("/apply")
+async def flow_apply(request: Request,
+ apply: ApplyModel,
+ query_db: AsyncSession = Depends(get_db)):
+ apply_result = await ApprovalService.apply_services(query_db, apply)
+ return ResponseUtil.success(msg=apply_result.message)
+
+
+@approvalController.post("/operate")
+async def flow_operate(request: Request,
+ operate: OperateModel,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ operate_result = await ApprovalService.operate_services(query_db, operate, current_user)
+ return ResponseUtil.success(msg=operate_result.message)
+
+
+@approvalController.get("/list")
+async def flow_list(request: Request,
+ query_param: ApprovalQueryObject = Depends(ApprovalQueryObject.as_query),
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ meta_query_result = await ApprovalService.get_flow_list_services(query_db, query_param, current_user)
+ return ResponseUtil.success(data=meta_query_result)
+
+
+@approvalController.get("/waitingTotal")
+async def getWaitingTotal(request: Request,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ meta_query_result = await ApprovalService.get_waiting_total_services(query_db, current_user)
+ return ResponseUtil.success(data=meta_query_result)
+
+
+@approvalController.post("/cancelApply/{flow_id}")
+async def cancel_apply(request: Request,
+ flow_id: str,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ operate_result = await ApprovalService.cancel_apply_services(query_db, flow_id, current_user)
+ return ResponseUtil.success(msg=operate_result.message)
diff --git a/vue-fastapi-backend/module_admin/controller/meta_controller.py b/vue-fastapi-backend/module_admin/controller/meta_controller.py
new file mode 100644
index 0000000..8a7de27
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/controller/meta_controller.py
@@ -0,0 +1,41 @@
+from fastapi import APIRouter, Depends, Request
+from sqlalchemy.ext.asyncio import AsyncSession
+from config.get_db import get_db
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from module_admin.service.login_service import LoginService
+from utils.response_util import ResponseUtil
+
+from module_admin.service.meta_service import MetaService
+from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject, SuppleModel
+
+metaController = APIRouter(prefix='/dasset', dependencies=[Depends(LoginService.get_current_user)])
+
+
+@metaController.get("/meta/get")
+async def get_meta_list(request: Request, meta_query: MetaPageObject = Depends(MetaPageObject.as_query),
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ meta_query_result = await MetaService.get_meta_list_services(query_db, meta_query, current_user)
+ return ResponseUtil.success(data=meta_query_result)
+
+
+@metaController.get("/meta/column/list")
+async def get_meta_list(request: Request, meta_query: MetaColObject = Depends(MetaColObject.as_query),
+ query_db: AsyncSession = Depends(get_db)):
+ meta_query_result = await MetaService.get_meta_col_list_services(query_db, meta_query)
+ return ResponseUtil.success(data=meta_query_result)
+
+
+@metaController.get("/meta/clas/list")
+async def get_meta_clas_list(request: Request, query_db: AsyncSession = Depends(get_db)):
+ result = await MetaService.get_meta_clas_list_services(query_db)
+ return ResponseUtil.success(data=result)
+
+
+@metaController.post("/meta/supp")
+async def meta_supp(request: Request,
+ supple: SuppleModel,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+ result = await MetaService.meta_supp(query_db, supple, current_user)
+ return ResponseUtil.success(msg=result.message)
diff --git a/vue-fastapi-backend/module_admin/dao/approval_dao.py b/vue-fastapi-backend/module_admin/dao/approval_dao.py
new file mode 100644
index 0000000..b74cd70
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/dao/approval_dao.py
@@ -0,0 +1,78 @@
+from sqlalchemy import desc, delete, func, select, update
+from sqlalchemy.ext.asyncio import AsyncSession
+from module_admin.entity.do.approval_do import FlowApproval
+from module_admin.entity.vo.approval_vo import ApprovalQueryObject
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from sqlalchemy import select, text, cast, Integer, and_, or_, outerjoin, func, join
+from utils.page_util import PageUtil
+
+
+class ApprovalDao:
+ """
+ 菜单管理模块数据库操作层
+ """
+
+ @classmethod
+ async def add_flow_approval(cls, db: AsyncSession, flow_approval: FlowApproval):
+ db.add(flow_approval)
+ await db.flush()
+ return flow_approval
+
+ @classmethod
+ async def get_flow_by_id(cls, db: AsyncSession, flowId: str):
+ result = (
+ (
+ await db.execute(
+ select(FlowApproval).where(
+ FlowApproval.id == flowId
+ )
+ )
+ )
+ .scalars()
+ .first()
+ )
+ return result
+
+ @classmethod
+ async def edit_flow_approval(cls, db: AsyncSession, flow: dict):
+ await db.execute(update(FlowApproval), [flow])
+
+ @classmethod
+ async def get_flow_list(cls, db: AsyncSession, query_param: ApprovalQueryObject, current_user: CurrentUserModel):
+ query = (
+ select(FlowApproval)
+ .where(
+ (FlowApproval.applicant == query_param.status) if query_param.applicant else True,
+ (FlowApproval.businessType == query_param.businessType) if query_param.businessType else True,
+ or_(
+ FlowApproval.approver == current_user.user.user_name,
+ FlowApproval.approver.in_(current_user.roles)
+ ) if current_user.user.user_name != 'admin' else True
+ )
+ .order_by(FlowApproval.applyTime)
+ .distinct()
+ )
+ # 注意:这里不执行查询,而是将查询对象传递给 paginate 方法
+ result = await PageUtil.paginate(db, query, query_param.page_num, query_param.page_size, True)
+ return result
+
+ @classmethod
+ async def get_waiting_total(cls, db: AsyncSession, current_user: CurrentUserModel):
+ return (await db.execute(select(func.count()).select_from(FlowApproval)
+ .where(FlowApproval.approver == current_user.user.user_name))).scalar()
+
+ @classmethod
+ async def get_flow_by_idAndUser(cls, db: AsyncSession, flow_id: str, username: str):
+ result = (
+ (
+ await db.execute(
+ select(FlowApproval).where(
+ FlowApproval.id == flow_id,
+ FlowApproval.applicant == username
+ )
+ )
+ )
+ .scalars()
+ .first()
+ )
+ return result
diff --git a/vue-fastapi-backend/module_admin/dao/meta_dao.py b/vue-fastapi-backend/module_admin/dao/meta_dao.py
new file mode 100644
index 0000000..4502705
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/dao/meta_dao.py
@@ -0,0 +1,321 @@
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy import select, text, cast, Integer, and_, or_, outerjoin, func, join, update, desc
+from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject
+from module_admin.entity.do.meta_do import MetadataExtractInfo, MetadataSuppInfo, MetadataFldTabExtractInfo, \
+ MetadataFldSuppInfo, MetadataClas, MetadataSuppInfoVett, MetadataFldSuppInfoVett
+import json
+import re
+from utils.time_format_util import object_format_datetime, list_format_datetime, format_datetime_dict_list
+from datetime import datetime, time
+from typing import Union, List
+from utils.log_util import logger
+import uuid
+import datetime
+from utils.page_util import PageUtil
+
+
+class MetaDao:
+
+ @classmethod
+ async def get_meta_rel_list(cls, db: AsyncSession, query_object: MetaPageObject):
+ """
+ 根据查询参数获取用户列表信息
+ """
+ # 主查询
+ query = (
+ select(
+ MetadataExtractInfo.onum.label('extract_onum'),
+ MetadataExtractInfo.extract_ver_num,
+ MetadataExtractInfo.ver_desc.label('extract_ver_desc'),
+ MetadataExtractInfo.ssys_cd,
+ MetadataExtractInfo.data_whs_name,
+ MetadataExtractInfo.mdl_name,
+ MetadataExtractInfo.tab_no,
+ MetadataExtractInfo.tab_type,
+ MetadataExtractInfo.tab_eng_name,
+ MetadataExtractInfo.tab_cn_name,
+ MetadataExtractInfo.tab_rec_num,
+ MetadataExtractInfo.upd_time.label('extract_upd_time'),
+ MetadataSuppInfo.onum.label('supp_onum'),
+ MetadataSuppInfo.crrct_ver_num.label('supp_crrct_ver_num'),
+ MetadataSuppInfo.tab_crrct_name,
+ MetadataSuppInfo.tab_desc,
+ MetadataSuppInfo.pic,
+ MetadataSuppInfo.gov_flag,
+ MetadataSuppInfo.rec_stat.label('supp_rec_stat'),
+ MetadataSuppInfo.tab_clas,
+ MetadataSuppInfo.rec_subm_prsn,
+ MetadataSuppInfo.upd_time.label('supp_upd_time')
+ ).join(MetadataSuppInfo,
+ and_(
+ MetadataExtractInfo.ssys_cd == MetadataSuppInfo.ssys_cd,
+ MetadataExtractInfo.mdl_name == MetadataSuppInfo.mdl_name,
+ MetadataExtractInfo.tab_eng_name == MetadataSuppInfo.tab_eng_name
+ ), isouter=True)
+ .join(
+ MetadataFldTabExtractInfo,
+ and_(
+ MetadataExtractInfo.ssys_cd == MetadataFldTabExtractInfo.ssys_cd,
+ MetadataExtractInfo.mdl_name == MetadataFldTabExtractInfo.mdl_name,
+ MetadataExtractInfo.tab_eng_name == MetadataFldTabExtractInfo.tab_eng_name
+ ), isouter=True)
+ .join(
+ MetadataFldSuppInfo,
+ and_(
+ MetadataExtractInfo.ssys_cd == MetadataFldSuppInfo.ssys_cd,
+ MetadataExtractInfo.mdl_name == MetadataFldSuppInfo.mdl_name,
+ MetadataExtractInfo.tab_eng_name == MetadataFldSuppInfo.tab_eng_name
+ ), isouter=True)
+ .where(
+ MetadataExtractInfo.ssys_cd == query_object.ssys_cd if query_object.ssys_cd else True,
+ MetadataExtractInfo.mdl_name == query_object.mdl_name if query_object.mdl_name else True,
+ or_(MetadataExtractInfo.tab_eng_name.like(f'%{query_object.tab_name}%'),
+ MetadataExtractInfo.tab_cn_name.like(f'%{query_object.tab_name}%'),
+ MetadataSuppInfo.tab_eng_name.like(f'%{query_object.tab_name}%'),
+ MetadataSuppInfo.tab_crrct_name.like(f'%{query_object.tab_name}%'),
+ ) if query_object.tab_name else True,
+ or_(
+ MetadataFldTabExtractInfo.fld_eng_name.like(f'%{query_object.col_name}%'),
+ MetadataFldTabExtractInfo.fld_cn_name.like(f'%{query_object.col_name}%'),
+ MetadataFldSuppInfo.fld_eng_name.like(f'%{query_object.col_name}%'),
+ MetadataFldSuppInfo.fld_crrct_name.like(f'%{query_object.col_name}%'),
+ ) if query_object.col_name else True,
+ MetadataExtractInfo.tab_type == query_object.tab_type if query_object.tab_type else True,
+ MetadataExtractInfo.rec_stat == query_object.rec_stat if query_object.rec_stat else True,
+ ).distinct()
+ )
+ result = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, True)
+ return result
+
+ @classmethod
+ async def get_meta_col_list(cls, db: AsyncSession, query_object: MetaColObject):
+ query_result = (
+ (
+ await db.execute(
+ select(
+ MetadataFldTabExtractInfo.onum.label('extract_onum'),
+ MetadataFldTabExtractInfo.extract_ver_num,
+ MetadataFldTabExtractInfo.ssys_cd,
+ MetadataFldTabExtractInfo.data_whs_name,
+ MetadataFldTabExtractInfo.mdl_name,
+ MetadataFldTabExtractInfo.tab_no,
+ MetadataFldTabExtractInfo.tab_eng_name,
+ MetadataFldTabExtractInfo.fld_no,
+ MetadataFldTabExtractInfo.fld_eng_name,
+ MetadataFldTabExtractInfo.fld_cn_name,
+ MetadataFldTabExtractInfo.fld_type,
+ MetadataFldTabExtractInfo.pk_flag,
+ MetadataFldTabExtractInfo.require_flag,
+ MetadataFldTabExtractInfo.idx_flag,
+ MetadataFldTabExtractInfo.upd_time.label('extract_upd_time'),
+ MetadataFldSuppInfo.onum.label('supp_onum'),
+ MetadataFldSuppInfo.crrct_ver_num,
+ MetadataFldSuppInfo.fld_crrct_name,
+ MetadataFldSuppInfo.crrct_pk_flag,
+ MetadataFldSuppInfo.fld_desc,
+ MetadataFldSuppInfo.pic,
+ MetadataFldSuppInfo.fld_clas,
+ MetadataFldSuppInfo.fld_null_rate,
+ MetadataFldSuppInfo.rec_stat.label('supp_rec_stat'),
+ MetadataFldSuppInfo.upd_time.label('supp_upd_time')
+ ).select_from(
+ join(
+ MetadataFldTabExtractInfo,
+ MetadataFldSuppInfo,
+ and_(
+ MetadataFldTabExtractInfo.ssys_cd == MetadataFldSuppInfo.ssys_cd,
+ MetadataFldTabExtractInfo.mdl_name == MetadataFldSuppInfo.mdl_name,
+ MetadataFldTabExtractInfo.tab_eng_name == MetadataFldSuppInfo.tab_eng_name,
+ MetadataFldTabExtractInfo.fld_eng_name == MetadataFldSuppInfo.fld_eng_name
+ ), isouter=True
+ )
+ ).where(
+ MetadataFldTabExtractInfo.ssys_cd == query_object.ssys_cd,
+ MetadataFldTabExtractInfo.mdl_name == query_object.mdl_name,
+ MetadataFldTabExtractInfo.tab_eng_name == query_object.tab_name
+ ).distinct()
+ )
+ ).all()
+ )
+ return [row._asdict() for row in query_result]
+
+ @classmethod
+ async def get_meta_clas_list(cls, db: AsyncSession):
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataClas).where(MetadataClas.clas_eff_flag == 1).distinct()
+ )
+ ).scalars().all()
+ )
+ return query_result
+
+ @classmethod
+ async def get_lastest_meta_data_supp_vett(cls, db: AsyncSession, ssys_cd: str, mdl_name: str, tab_eng_name: str):
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataSuppInfoVett).where(MetadataSuppInfoVett.ssys_cd == ssys_cd,
+ MetadataSuppInfoVett.mdl_name == mdl_name,
+ MetadataSuppInfoVett.tab_eng_name == tab_eng_name)
+ .order_by(desc(MetadataSuppInfoVett.apply_time))
+ .distinct().limit(1)
+ )
+ ).scalars().first()
+ )
+ return query_result
+
+ @classmethod
+ async def insertMetadataSuppInfoVett(cls, table: MetadataSuppInfoVett, db: AsyncSession):
+ db.add(table)
+ await db.flush()
+ return table
+
+ @classmethod
+ async def updateMetadataSuppInfoVett(cls, onum: str, operateType: str, db: AsyncSession):
+ table = dict(
+ onum=onum,
+ apply_status=operateType
+ )
+ await db.execute(update(MetadataSuppInfoVett), [table])
+
+ @classmethod
+ async def insertMetadataSuppInfo(cls, table: MetadataSuppInfoVett, db: AsyncSession):
+ suppTable = MetadataSuppInfo()
+ suppTable.onum = uuid.uuid4()
+ suppTable.ssys_cd = table.ssys_cd
+ suppTable.mdl_name = table.mdl_name
+ suppTable.tab_eng_name = table.tab_eng_name
+ suppTable.tab_crrct_name = table.tab_crrct_name
+ suppTable.tab_desc = table.tab_desc
+ suppTable.pic = table.pic
+ suppTable.gov_flag = table.gov_flag
+ suppTable.rec_stat = table.rec_stat
+ suppTable.tab_clas = table.tab_clas
+ suppTable.rec_subm_prsn = table.rec_subm_prsn
+ suppTable.upd_time = table.upd_time
+ db.add(suppTable)
+ await db.flush()
+ return suppTable
+
+ @classmethod
+ async def updateMetadataSuppInfo(cls, onum: str, table: MetadataSuppInfoVett, db: AsyncSession):
+ suppTable = dict(
+ onum=onum,
+ tab_crrct_name=table.tab_crrct_name,
+ tab_desc=table.tab_desc,
+ pic=table.pic,
+ gov_flag=table.gov_flag,
+ rec_stat=table.rec_stat,
+ tab_clas=table.tab_clas,
+ rec_subm_prsn=table.rec_subm_prsn,
+ upd_time=table.upd_time
+ )
+ await db.execute(update(MetadataSuppInfo), [suppTable])
+
+ @classmethod
+ async def get_supp_table_vett_by_id(cls, suppId: str, db: AsyncSession):
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataSuppInfoVett).where(MetadataSuppInfoVett.onum == suppId).distinct()
+ )
+ ).scalars().first()
+ )
+ return query_result
+
+ @classmethod
+ async def get_supp_table_by_vett(cls, sysCode: str, mdlName: str, tableName: str, db: AsyncSession):
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataSuppInfo).where(MetadataSuppInfo.ssys_cd == sysCode,
+ MetadataSuppInfo.mdl_name == mdlName,
+ MetadataSuppInfo.tab_eng_name == tableName).distinct()
+ )
+ ).scalars().first()
+ )
+ return query_result
+
+ @classmethod
+ async def insertMetadataFldSuppInfoVett(cls, column: MetadataFldSuppInfoVett, db: AsyncSession):
+ db.add(column)
+ await db.flush()
+ return column
+
+ @classmethod
+ async def updateMetadataFldSuppInfoVett(cls, onum: str, operateType: str, db: AsyncSession):
+ updateColumn = dict(
+ onum=onum, apply_status=operateType
+ )
+ await db.execute(update(MetadataFldSuppInfoVett), [updateColumn])
+
+ @classmethod
+ async def updateMetadataFldSuppInfo(cls, onum: str, column: MetadataFldSuppInfoVett, db: AsyncSession):
+ updateColumn = dict(
+ onum=onum,
+ fld_crrct_name=column.fld_crrct_name,
+ crrct_pk_flag=column.crrct_pk_flag,
+ fld_desc=column.fld_desc,
+ pic=column.pic,
+ fld_clas=column.fld_clas,
+ fld_null_rate=column.fld_null_rate,
+ rec_stat=column.rec_stat,
+ upd_time=column.upd_time,
+ )
+ await db.execute(update(MetadataFldSuppInfo), [updateColumn])
+
+ @classmethod
+ async def insertMetadataFldSuppInfo(cls, column: MetadataFldSuppInfoVett, db: AsyncSession):
+ suppColumn = MetadataFldSuppInfo()
+ suppColumn.onum = uuid.uuid4()
+ suppColumn.ssys_cd = column.ssys_cd
+ suppColumn.mdl_name = column.mdl_name
+ suppColumn.tab_eng_name = column.tab_eng_name
+ suppColumn.fld_eng_name = column.fld_eng_name
+ suppColumn.fld_crrct_name = column.fld_crrct_name
+ suppColumn.crrct_pk_flag = column.crrct_pk_flag
+ suppColumn.fld_desc = column.fld_desc
+ suppColumn.pic = column.pic
+ suppColumn.fld_clas = column.fld_clas
+ suppColumn.fld_null_rate = column.fld_null_rate
+ suppColumn.rec_stat = column.rec_stat
+ suppColumn.upd_time = column.upd_time
+ db.add(suppColumn)
+ await db.flush()
+ return suppColumn
+
+ @classmethod
+ async def get_meta_col_supp_vett(cls, table: MetadataSuppInfoVett, db: AsyncSession):
+ sql_query = text("select max(apply_time) from t_metadata_fld_supp_info_vett where ssys_cd ='" + table.ssys_cd +
+ "' and mdl_name = '" + table.mdl_name + "' and tab_eng_name = '" + table.tab_eng_name +
+ "'")
+ maxTime = (await db.execute(sql_query)).scalar()
+
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataFldSuppInfoVett)
+ .where(MetadataFldSuppInfoVett.ssys_cd == table.ssys_cd,
+ MetadataFldSuppInfoVett.mdl_name == table.mdl_name,
+ MetadataFldSuppInfoVett.tab_eng_name == table.tab_eng_name,
+ MetadataFldSuppInfoVett.apply_time == maxTime).distinct()
+ )
+ ).scalars().all()
+ )
+ return query_result
+
+ @classmethod
+ async def get_supp_column_by_vett(cls, column: MetadataFldSuppInfoVett, db: AsyncSession):
+ query_result = (
+ (
+ await db.execute(
+ select(MetadataFldSuppInfo)
+ .where(MetadataFldSuppInfo.ssys_cd == column.ssys_cd,
+ MetadataFldSuppInfo.mdl_name == column.mdl_name,
+ MetadataFldSuppInfo.tab_eng_name == column.tab_eng_name,
+ MetadataFldSuppInfo.fld_eng_name == column.fld_eng_name).distinct()
+ )
+ ).scalars().first()
+ )
+ return query_result
diff --git a/vue-fastapi-backend/module_admin/entity/do/aichat_do.py b/vue-fastapi-backend/module_admin/entity/do/aichat_do.py
index fc85b07..0a9e50d 100644
--- a/vue-fastapi-backend/module_admin/entity/do/aichat_do.py
+++ b/vue-fastapi-backend/module_admin/entity/do/aichat_do.py
@@ -1,6 +1,7 @@
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text
from config.database import Base
from datetime import datetime
+from sqlalchemy.dialects.mysql import LONGTEXT
class AiChatHistory(Base):
@@ -17,7 +18,7 @@ class AiChatHistory(Base):
isStop = Column(Boolean, default=None, comment='是否停止')
user = Column(Integer, default=None, comment='所属用户')
time = Column(String(50), default=None, comment='问答时间')
- content = Column(Text, default=None, comment='问答内容')
+ content = Column(LONGTEXT, default=None, comment='问答内容')
operate = Column(String(50), default=None, comment='点赞,差评等操作')
thumbDownReason = Column(String(255), default=None, comment='差评原因')
file = Column(String(255), default=None, comment='文件id集合')
diff --git a/vue-fastapi-backend/module_admin/entity/do/approval_do.py b/vue-fastapi-backend/module_admin/entity/do/approval_do.py
new file mode 100644
index 0000000..c9a273b
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/entity/do/approval_do.py
@@ -0,0 +1,20 @@
+from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text
+from config.database import Base
+from datetime import datetime
+
+
+class FlowApproval(Base):
+ """
+ 流程审批表
+ """
+ __tablename__ = 'flow_approval'
+
+ id = Column(String(50), primary_key=True, comment='id')
+ businessType = Column(String(50), default='', comment='业务审批模块')
+ businessId = Column(String(255), default='', comment='业务id串')
+ applicant = Column(String(50), default=None, comment='申请人')
+ applyTime = Column(String(50), default=None, comment='审批时间')
+ approver = Column(String(50), default=None, comment='下一步审批人')
+ nextStep = Column(Integer, default=None, comment="下一步编号")
+ status = Column(String(10), default=None, comment='状态')
+ approvalFlow = Column(Text, default=None, comment='审批流') # [{审批人:‘’,审批时间:‘’,'审批结果':‘’,审批意见:''},{}]数组
diff --git a/vue-fastapi-backend/module_admin/entity/do/meta_do.py b/vue-fastapi-backend/module_admin/entity/do/meta_do.py
new file mode 100644
index 0000000..703fbb2
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/entity/do/meta_do.py
@@ -0,0 +1,156 @@
+from sqlalchemy import Column, Float, Integer, String, Text, DateTime, Boolean, ForeignKey, UniqueConstraint, Index, \
+ text
+from config.database import Base
+from datetime import datetime
+
+
+class MetadataExtractInfo(Base):
+ """
+ 元数据采集信息表
+ """
+ __tablename__ = 't_metadata_extract_info'
+
+ onum = Column(Integer, primary_key=True, comment='唯一编号')
+ extract_ver_num = Column(String(50, collation='utf8_general_ci'), comment='采集版本号')
+ ver_desc = Column(String(250, collation='utf8_general_ci'), comment='版本描述')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ data_whs_name = Column(String(50, collation='utf8_general_ci'), comment='数据仓库名称')
+ mdl_name = Column(String(50, collation='utf8_general_ci'), comment='模式名称')
+ tab_no = Column(Integer, comment='表编号')
+ tab_type = Column(String(50, collation='utf8_general_ci'), comment='表类型')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ tab_cn_name = Column(String(250, collation='utf8_general_ci'), comment='表中文名称')
+ tab_rec_num = Column(Integer, comment='记录数')
+ upd_time = Column(DateTime, comment='更新时间')
+
+
+class MetadataSuppInfo(Base):
+ """
+ 元数据补充信息表
+ """
+ __tablename__ = 't_metadata_supp_info'
+
+ # onum = Column(Integer, primary_key=True, comment='唯一编号')
+ onum = Column(String(36, collation='utf8mb4_unicode_ci'), primary_key=True, comment='唯一编号')
+ crrct_ver_num = Column(String(50, collation='utf8_general_ci'), comment='补录版本号')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ mdl_name = Column(String(50, collation='utf8_general_ci'), comment='模型名称')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ tab_crrct_name = Column(String(250, collation='utf8_general_ci'), comment='表补录名称')
+ tab_desc = Column(String(500, collation='utf8_general_ci'), comment='表描述')
+ pic = Column(String(64, collation='utf8_general_ci'), comment='表图片')
+ gov_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='治理标志(0否 1是)')
+ rec_stat = Column(String(1, collation='utf8_general_ci'), default='0', comment='记录状态(0有效 1无效)')
+ tab_clas = Column(Text, comment='表分类')
+ rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人')
+ upd_time = Column(DateTime, comment='更新时间')
+
+
+class MetadataSuppInfoVett(Base):
+ """
+ 元数据补充信息审批表
+ """
+ __tablename__ = 't_metadata_supp_info_vett'
+
+ # onum = Column(Integer, primary_key=True, comment='唯一编号')
+ onum = Column(String(36, collation='utf8mb4_unicode_ci'), primary_key=True, comment='唯一编号')
+ crrct_ver_num = Column(String(50, collation='utf8_general_ci'), comment='补录版本号')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ mdl_name = Column(String(50, collation='utf8_general_ci'), comment='模型名称')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ tab_crrct_name = Column(String(250, collation='utf8_general_ci'), comment='表补录名称')
+ tab_desc = Column(String(500, collation='utf8_general_ci'), comment='表描述')
+ pic = Column(String(64, collation='utf8_general_ci'), comment='表图片')
+ gov_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='治理标志(0否 1是)')
+ rec_stat = Column(String(1, collation='utf8_general_ci'), default='0', comment='记录状态(0有效 1无效)')
+ tab_clas = Column(Text, comment='表分类')
+ rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人')
+ apply_time = Column(String(255, collation='utf8_general_ci'), comment='申请时间')
+ apply_status = Column(String(255, collation='utf8_general_ci'), comment='申请状态')
+ upd_time = Column(String(255, collation='utf8_general_ci'), comment='更新时间')
+
+
+class MetadataClas(Base):
+ """
+ 元数据分类表
+ """
+ __tablename__ = 't_metadata_clas'
+
+ clas_onum = Column(Integer, primary_key=True, comment='分类编号')
+ clas_pri_clas = Column(String(50, collation='utf8_general_ci'), comment='一级分类')
+ clas_scd_clas = Column(String(50, collation='utf8_general_ci'), comment='二级分类')
+ clas_thre_clas = Column(String(50, collation='utf8_general_ci'), comment='三级分类')
+ clas_name = Column(String(255, collation='utf8_general_ci'), comment='分类名称')
+ clas_eff_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='生效标志(0有效 1无效)')
+ rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人')
+ upd_time = Column(DateTime, comment='更新时间')
+
+
+class MetadataFldTabExtractInfo(Base):
+ """
+ 字段采集信息表
+ """
+ __tablename__ = 't_metadata_fld_tab_extract_info'
+
+ onum = Column(Integer, primary_key=True, comment='唯一编号')
+ extract_ver_num = Column(String(50, collation='utf8_general_ci'), comment='采集版本号')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ data_whs_name = Column(String(255, collation='utf8_general_ci'), comment='数据仓库名称')
+ mdl_name = Column(String(255, collation='utf8_general_ci'), comment='模块名称')
+ tab_no = Column(String(50, collation='utf8_general_ci'), comment='表编号')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ fld_no = Column(Integer, comment='字段编号')
+ fld_eng_name = Column(String(255, collation='utf8_general_ci'), comment='字段英文名称')
+ fld_cn_name = Column(String(255, collation='utf8_general_ci'), comment='字段中文名称')
+ fld_type = Column(String(50, collation='utf8_general_ci'), comment='字段类型')
+ pk_flag = Column(Boolean, default=False, comment='是否为主键') #待确认字段类型
+ require_flag = Column(Boolean, default=False, comment='是否必填')
+ idx_flag = Column(Boolean, default=False, comment='是否为索引')
+ upd_time = Column(DateTime, comment='更新时间')
+
+
+class MetadataFldSuppInfo(Base):
+ """
+ 字段补充信息表
+ """
+ __tablename__ = 't_metadata_fld_supp_info'
+
+ onum = Column(String(50, collation='utf8_general_ci'), primary_key=True, comment='唯一编号')
+ crrct_ver_num = Column(String(50, collation='utf8_general_ci'), comment='补充版本号')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ mdl_name = Column(String(255, collation='utf8_general_ci'), comment='模块名称')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ fld_eng_name = Column(String(255, collation='utf8_general_ci'), comment='字段英文名称')
+ fld_crrct_name = Column(String(255, collation='utf8_general_ci'), comment='补充字段名称')
+ crrct_pk_flag = Column(Boolean, default=False, comment='是否为主键')
+ fld_desc = Column(String(255, collation='utf8_general_ci'), comment='字段描述')
+ pic = Column(String(255, collation='utf8_general_ci'), comment='图片字段')
+ fld_clas = Column(Text, comment='字段分类')
+ fld_null_rate = Column(String(50, collation='utf8_general_ci'), comment='字段空值率')
+ rec_stat = Column(String(50, collation='utf8_general_ci'), comment='记录状态')
+ upd_time = Column(DateTime, comment='更新时间')
+
+
+class MetadataFldSuppInfoVett(Base):
+ """
+ 字段补充信息表
+ """
+ __tablename__ = 't_metadata_fld_supp_info_vett'
+
+ onum = Column(String(50, collation='utf8_general_ci'), primary_key=True, comment='唯一编号')
+ crrct_ver_num = Column(String(50, collation='utf8_general_ci'), comment='补充版本号')
+ ssys_cd = Column(String(50, collation='utf8_general_ci'), comment='系统代码')
+ mdl_name = Column(String(255, collation='utf8_general_ci'), comment='模块名称')
+ tab_eng_name = Column(String(250, collation='utf8_general_ci'), comment='表英文名称')
+ fld_eng_name = Column(String(255, collation='utf8_general_ci'), comment='字段英文名称')
+ fld_crrct_name = Column(String(255, collation='utf8_general_ci'), comment='补充字段名称')
+ crrct_pk_flag = Column(Boolean, default=False, comment='是否为主键')
+ fld_desc = Column(String(255, collation='utf8_general_ci'), comment='字段描述')
+ pic = Column(String(255, collation='utf8_general_ci'), comment='图片字段')
+ fld_clas = Column(Text, comment='字段分类')
+ fld_null_rate = Column(String(50, collation='utf8_general_ci'), comment='字段空值率')
+ rec_stat = Column(String(50, collation='utf8_general_ci'), comment='记录状态')
+ upd_time = Column(DateTime, comment='更新时间')
+ rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人')
+ apply_time = Column(String(255, collation='utf8_general_ci'), comment='申请时间')
+ apply_status = Column(String(255, collation='utf8_general_ci'), comment='申请状态')
diff --git a/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py b/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py
new file mode 100644
index 0000000..1fcce05
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py
@@ -0,0 +1,34 @@
+from pydantic import BaseModel
+from typing import Union, Optional, List
+from module_admin.annotation.pydantic_annotation import as_query
+from pydantic import BaseModel, ConfigDict, Field, model_validator
+from pydantic.alias_generators import to_camel
+
+
+class ApplyModel(BaseModel):
+ businessType: Optional[str] = None
+ businessId: Optional[str] = None
+ applicant: Optional[str] = None
+
+
+class OperateModel(BaseModel):
+ flowId: Optional[str] = None # 流程编号
+ operateType: Optional[str] = None # 操作:驳回,同意:reject, success
+ operateComment: Optional[str] = None # 审批意见
+
+
+@as_query
+class ApprovalQueryObject(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ page_num: int
+ page_size: int
+ applicant: Optional[str] = None
+ businessType: Optional[str] = None
+
+
+class EditObjectModel(BaseModel):
+ id: Optional[str] = None
+ status: Optional[str] = None
+ approver: Optional[str] = None
+ nextStep: Optional[int] = None
+ approvalFlow: Optional[str] = None
diff --git a/vue-fastapi-backend/module_admin/entity/vo/meta_vo.py b/vue-fastapi-backend/module_admin/entity/vo/meta_vo.py
new file mode 100644
index 0000000..88dfa5a
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/entity/vo/meta_vo.py
@@ -0,0 +1,56 @@
+from typing import Union, Optional, List
+from datetime import datetime
+from module_admin.annotation.pydantic_annotation import as_query
+from pydantic import BaseModel, ConfigDict, Field, model_validator
+from pydantic.alias_generators import to_camel
+
+
+class MetaModel(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ ssys_cd: Optional[str] = Field(default=None, description='系统名称')
+ mdl_name: Optional[str] = Field(default=None, description='模式名称')
+ tab_name: Optional[str] = Field(default=None, description='表名')
+ tab_type: Optional[str] = Field(default=None, description='表类型')
+ col_name: Optional[str] = Field(default=None, description='字段名称')
+ tag_name: Optional[str] = Field(default=None, description='标签名称')
+ rec_stat: Optional[str] = Field(default=None, description='补录状态')
+
+
+@as_query
+class MetaPageObject(MetaModel):
+ page_num: int
+ page_size: int
+
+
+@as_query
+class MetaColObject(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ ssys_cd: Optional[str] = Field(default=None, description='系统名称')
+ mdl_name: Optional[str] = Field(default=None, description='模式名称')
+ tab_name: Optional[str] = Field(default=None, description='表名')
+
+
+class ColumnSuppleModel(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ fld_eng_name: Optional[str] = None
+ fld_crrct_name: Optional[str] = None
+ crrct_pk_flag: Optional[int] = None
+ fld_desc: Optional[str] = None
+ pic: Optional[str] = None
+ fld_clas: Optional[str] = None
+ fld_null_rate: Optional[str] = None
+ rec_stat: Optional[str] = None
+
+
+class SuppleModel(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ ssys_cd: Optional[str] = None
+ mdl_name: Optional[str] = None
+ tab_eng_name: Optional[str] = None
+ tab_crrct_name: Optional[str] = None
+ tab_desc: Optional[str] = None
+ pic: Optional[str] = None
+ gov_flag: Optional[str] = None
+ rec_stat: Optional[str] = None
+ tab_clas: Optional[str] = None
+ columnInfo: Optional[List[ColumnSuppleModel]] = None
diff --git a/vue-fastapi-backend/module_admin/service/approval_service.py b/vue-fastapi-backend/module_admin/service/approval_service.py
new file mode 100644
index 0000000..1235c5e
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/service/approval_service.py
@@ -0,0 +1,121 @@
+import json
+import uuid
+
+from typing import Optional
+from sqlalchemy.ext.asyncio import AsyncSession
+from module_admin.entity.vo.common_vo import CrudResponseModel
+from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject, EditObjectModel
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from module_admin.entity.do.approval_do import FlowApproval
+from exceptions.exception import ServiceException, ServiceWarning
+from datetime import datetime
+from utils.common_util import CamelCaseUtil
+from module_admin.dao.approval_dao import ApprovalDao
+from module_admin.dao.meta_dao import MetaDao
+
+
+class ApprovalService:
+ """
+ 智能问答服务层
+ """
+
+ @classmethod
+ async def apply_services(cls, result_db: AsyncSession, apply: ApplyModel):
+ flow_approval = FlowApproval()
+ flow_approval.id = uuid.uuid4()
+ flow_approval.businessType = apply.businessType
+ flow_approval.businessId = apply.businessId
+ flow_approval.applicant = apply.applicant
+ flow_approval.applyTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ flow_approval.status = 'waiting'
+ # todo 后期进行流程配置,角色 or 人员 下一步审批人
+ flow_approval.approver = 'admin'
+ flow_approval.nextStep = '1'
+ await ApprovalDao.add_flow_approval(result_db, flow_approval)
+ await result_db.commit()
+ return CrudResponseModel(is_success=True, message='申请成功')
+
+ @classmethod
+ async def operate_services(cls, result_db: AsyncSession, operate: OperateModel, current_user: CurrentUserModel):
+ flow_approval = await ApprovalDao.get_flow_by_id(result_db, operate.flowId)
+ if flow_approval is None:
+ raise ServiceException(message=f'所操作的流程不存在')
+ if flow_approval.status == 'succeed' or flow_approval.status == 'rejected':
+ raise ServiceException(message='所操作的流程已结束')
+ if flow_approval.status == 'canceled':
+ raise ServiceException(message='所操作的流程已撤回')
+ array = []
+ if flow_approval.approvalFlow is not None:
+ array = json.loads(flow_approval.approvalFlow)
+ array.append({'operator': current_user.user.user_name,
+ 'operateTime': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ 'operate': operate.operateType,
+ 'operateComment': operate.operateComment,
+ })
+ edit = EditObjectModel()
+ edit.id = flow_approval.id
+ edit.approvalFlow = json.dumps(array)
+ if operate.operateType == 'success':
+ # todo 增加流程配置,并查询出下一步操作人以及步骤
+ edit.status = 'succeed' # 有下一步执行人,则设置为 pending
+ edit.approver = None
+ edit.nextStep = -1
+ if operate.operateType == 'reject':
+ edit.status = 'rejected'
+ edit.approver = None
+ edit.nextStep = -1
+ if flow_approval.businessType == 't_metadata_supp_info':
+ await cls.syncSuppInfo(result_db, flow_approval.businessId, operate.operateType)
+ await ApprovalDao.edit_flow_approval(result_db, edit.model_dump(exclude_unset=True))
+ await result_db.commit()
+ return CrudResponseModel(is_success=True, message='操作成功')
+
+ @classmethod
+ async def syncSuppInfo(cls, result_db: AsyncSession, suppId: str, operateType: str):
+ table = await MetaDao.get_supp_table_vett_by_id(suppId, result_db)
+ if table is None:
+ raise ServiceException(message='所查询的业务数据不存在')
+ if table.apply_status == 'succeed' or table.apply_status == 'rejected':
+ raise ServiceException(message='所改业务已审核完毕')
+ column_list = await MetaDao.get_meta_col_supp_vett(table, result_db)
+ if column_list is not None and len(column_list) > 0:
+ for column in column_list:
+ column.apply_status = operateType
+ suppColumn = await MetaDao.get_supp_column_by_vett(column, result_db)
+ await MetaDao.updateMetadataFldSuppInfoVett(column.onum, operateType, result_db)
+ if suppColumn is None:
+ await MetaDao.insertMetadataFldSuppInfo(column, result_db)
+ else:
+ await MetaDao.updateMetadataFldSuppInfo(suppColumn.onum, column, result_db)
+ suppTable = await MetaDao.get_supp_table_by_vett(table.ssys_cd, table.mdl_name, table.tab_eng_name, result_db)
+ await MetaDao.updateMetadataSuppInfoVett(table.onum, operateType, result_db)
+ if suppTable is None:
+ await MetaDao.insertMetadataSuppInfo(table, result_db)
+ else:
+ await MetaDao.updateMetadataSuppInfo(suppTable.onum, table, result_db)
+ return CrudResponseModel(is_success=True, message='操作成功')
+
+ @classmethod
+ async def get_flow_list_services(cls, query_db: AsyncSession, query_param: ApprovalQueryObject,
+ current_user: CurrentUserModel):
+ result = await ApprovalDao.get_flow_list(query_db, query_param, current_user)
+ return result
+
+ @classmethod
+ async def get_waiting_total_services(cls, query_db: AsyncSession, current_user: CurrentUserModel):
+ result = await ApprovalDao.get_waiting_total(query_db, current_user)
+ return result
+
+ @classmethod
+ async def cancel_apply_services(cls, query_db: AsyncSession, flow_id: str,
+ current_user: CurrentUserModel):
+ flow = await ApprovalDao.get_flow_by_idAndUser(flow_id, current_user.user.user_name)
+ if flow is None:
+ raise ServiceException(message=f'所操作的流程不存在')
+ if flow.status == 'succeed' or flow.status == 'rejected':
+ raise ServiceException(message='所操作的流程已结束,无需撤回')
+ if flow.status == 'canceled':
+ raise ServiceException(message='所操作的流程已撤回,无需重复操作')
+ flow.status = 'canceled'
+ await ApprovalDao.edit_flow_approval(query_db, flow)
+ return CrudResponseModel(is_success=True, message='操作成功')
diff --git a/vue-fastapi-backend/module_admin/service/meta_service.py b/vue-fastapi-backend/module_admin/service/meta_service.py
new file mode 100644
index 0000000..db5df8d
--- /dev/null
+++ b/vue-fastapi-backend/module_admin/service/meta_service.py
@@ -0,0 +1,126 @@
+import uuid
+
+from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject, SuppleModel
+from module_admin.entity.do.meta_do import MetadataSuppInfo, MetadataFldSuppInfo, MetadataSuppInfoVett, \
+ MetadataFldSuppInfoVett
+from module_admin.dao.meta_dao import MetaDao
+from datetime import datetime
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from module_admin.entity.vo.approval_vo import ApplyModel
+from sqlalchemy.ext.asyncio import AsyncSession
+from exceptions.exception import ServiceException, ServiceWarning
+from utils.pwd_util import *
+from utils.common_util import *
+from utils.log_util import logger
+from module_admin.service.login_service import LoginService
+from module_admin.service.approval_service import ApprovalService
+
+from module_admin.entity.vo.common_vo import CrudResponseModel
+from module_admin.entity.vo.user_vo import CurrentUserModel
+from utils.common_util import CamelCaseUtil
+import re
+
+
+class MetaService:
+
+ @classmethod
+ async def get_meta_list_services(cls, result_db: AsyncSession, query_object: MetaPageObject,
+ current_user: CurrentUserModel):
+ """
+ 获取元信息service
+ :param result_db: orm对象
+ :param query_object: 查询参数对象
+ :param data_scope_sql: 数据权限对应的查询sql语句
+ :return: 用户列表信息对象
+ """
+ # print("********")
+ # 0,正常,1已发布,2审核中,3已审核,4已作废
+ if 'admin' in current_user.roles:
+ meta_rel_list = await MetaDao.get_meta_rel_list(result_db, query_object)
+ return meta_rel_list
+ else:
+ # meta_rel_list = MetaDao.get_meta_rel_list(result_db, query_object, data_scope_sql)
+ return None
+
+ @classmethod
+ async def get_meta_col_list_services(cls, result_db: AsyncSession, query_object: MetaColObject):
+ meta_result = await MetaDao.get_meta_col_list(result_db, query_object)
+ return cls.convert_json_keys(meta_result)
+
+ @classmethod
+ async def get_meta_clas_list_services(cls, result_db: AsyncSession):
+ result = await MetaDao.get_meta_clas_list(result_db)
+ return CamelCaseUtil.transform_result(result)
+
+ @classmethod
+ async def meta_supp(cls, result_db: AsyncSession, supple: SuppleModel, current_user: CurrentUserModel):
+ # 0,暂存 waiting,申请中,pending审核中,succeed,rejected已审核,canceled已取消
+ hasTable = await MetaDao.get_lastest_meta_data_supp_vett(result_db, supple.ssys_cd, supple.mdl_name,
+ supple.tab_eng_name)
+ tableOnum = uuid.uuid4()
+ if hasTable is not None:
+ if hasTable.apply_status == 'waiting':
+ raise ServiceException(message=f'所补录对象已存在补录待审核记录,请等待审批完成或撤回申请后,再行补录')
+ if hasTable.apply_status == 'pending':
+ raise ServiceException(message=f'所补录对象已存在待审核记录,请等待审批完成后,再行补录')
+ suppTableInfo = MetadataSuppInfoVett()
+ suppTableInfo.onum = tableOnum
+ suppTableInfo.ssys_cd = supple.ssys_cd
+ suppTableInfo.mdl_name = supple.mdl_name
+ suppTableInfo.tab_eng_name = supple.tab_eng_name
+ suppTableInfo.tab_crrct_name = supple.tab_crrct_name
+ suppTableInfo.tab_desc = supple.tab_desc
+ suppTableInfo.pic = supple.pic
+ suppTableInfo.gov_flag = supple.gov_flag
+ suppTableInfo.tab_clas = supple.tab_clas
+ suppTableInfo.rec_subm_prsn = current_user.user.user_name
+ suppTableInfo.apply_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ suppTableInfo.apply_status = 'waiting'
+ await MetaDao.insertMetadataSuppInfoVett(suppTableInfo, result_db)
+ await result_db.commit()
+ if supple.columnInfo is not None and len(supple.columnInfo) > 0:
+ for column in supple.columnInfo:
+ suppColumnInfo = MetadataFldSuppInfoVett()
+ suppColumnInfo.onum = uuid.uuid4()
+ suppColumnInfo.ssys_cd = supple.ssys_cd
+ suppColumnInfo.mdl_name = supple.mdl_name
+ suppColumnInfo.tab_eng_name = supple.tab_eng_name
+ suppColumnInfo.fld_eng_name = column.fld_eng_name
+ suppColumnInfo.fld_crrct_name = column.fld_crrct_name
+ suppColumnInfo.crrct_pk_flag = column.crrct_pk_flag
+ suppColumnInfo.fld_desc = column.fld_desc
+ suppColumnInfo.pic = column.pic
+ suppColumnInfo.fld_clas = column.fld_clas
+ suppColumnInfo.fld_null_rate = column.fld_null_rate
+ suppColumnInfo.rec_stat = column.rec_stat
+ suppColumnInfo.rec_subm_prsn = current_user.user.user_name
+ suppColumnInfo.apply_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ suppColumnInfo.apply_status = 'waiting'
+ await MetaDao.insertMetadataFldSuppInfoVett(suppColumnInfo, result_db)
+ await result_db.commit()
+ applyModel = ApplyModel()
+ applyModel.businessType = "t_metadata_supp_info"
+ applyModel.businessId = tableOnum
+ applyModel.applicant = current_user.user.user_name
+ await ApprovalService.apply_services(result_db, applyModel)
+ return CrudResponseModel(is_success=True, message='操作成功')
+
+ @classmethod
+ def snake_to_camel(cls, snake_str: str):
+ # 将字符串按下划线分割成列表
+ components = snake_str.split('_')
+ # 第一个单词保持小写,后续单词首字母大写
+ camel_str = components[0] + ''.join(word.capitalize() for word in components[1:])
+ return camel_str
+
+ @classmethod
+ def convert_json_keys(cls, data):
+ if isinstance(data, dict):
+ # 如果数据是字典,则转换键名并递归处理值
+ return {cls.snake_to_camel(k): cls.convert_json_keys(v) for k, v in data.items()}
+ elif isinstance(data, list):
+ # 如果数据是列表,则递归处理列表中的每个元素
+ return [cls.convert_json_keys(element) for element in data]
+ else:
+ # 如果数据不是字典或列表,则直接返回(即基本数据类型,如字符串、数字等)
+ return data
diff --git a/vue-fastapi-backend/server.py b/vue-fastapi-backend/server.py
index ed6968a..e80a196 100644
--- a/vue-fastapi-backend/server.py
+++ b/vue-fastapi-backend/server.py
@@ -24,7 +24,9 @@ from module_admin.controller.server_controller import serverController
from module_admin.controller.user_controller import userController
from module_admin.controller.aichat_controller import aichatController
from module_admin.controller.metatask_controller import metataskController
+from module_admin.controller.meta_controller import metaController
from module_admin.controller.metasecurity_controller import metaSecurityController
+from module_admin.controller.approval_controller import approvalController
from sub_applications.handle import handle_sub_applications
from utils.common_util import worship
from utils.log_util import logger
@@ -83,6 +85,8 @@ controller_list = [
{'router': metataskController, 'tags': ['元数据管理-元数据任务模块']},
{'router': metaSecurityController, 'tags': ['元数据管理-数据安全']},
{'router': aichatController, 'tags': ['智能问答模块']},
+ {'router': metaController, 'tags': ['元数据信息模块']},
+ {'router': approvalController, 'tags': ['审批模块']},
]
for controller in controller_list:
diff --git a/vue-fastapi-frontend/package.json b/vue-fastapi-frontend/package.json
index a306739..e981d5b 100644
--- a/vue-fastapi-frontend/package.json
+++ b/vue-fastapi-frontend/package.json
@@ -24,6 +24,7 @@
"@vueuse/core": "10.11.0",
"ant-design-vue": "^4.1.1",
"axios": "0.28.1",
+ "codemirror-editor-vue3": "^2.8.0",
"echarts": "5.5.1",
"element-plus": "2.8.0",
"file-saver": "2.0.5",
@@ -36,6 +37,7 @@
"nprogress": "0.2.0",
"pinia": "2.1.7",
"remixicon": "^4.6.0",
+ "sql-formatter": "^15.4.10",
"uuid": "^11.0.4",
"vue": "3.4.15",
"vue-clipboard3": "^2.0.0",
diff --git a/vue-fastapi-frontend/src/api/aichat/aichat.js b/vue-fastapi-frontend/src/api/aichat/aichat.js
index 52097a3..c0b15e2 100644
--- a/vue-fastapi-frontend/src/api/aichat/aichat.js
+++ b/vue-fastapi-frontend/src/api/aichat/aichat.js
@@ -8,7 +8,7 @@ export function listChatHistory(sessionId) {
sessionId = '0'
}
return request({
- url: '/aichat/session/list/'+sessionId,
+ url: '/default-api/aichat/session/list/'+sessionId,
method: 'get',
params: {}
})
diff --git a/vue-fastapi-frontend/src/api/flow/flow.js b/vue-fastapi-frontend/src/api/flow/flow.js
new file mode 100644
index 0000000..5249b41
--- /dev/null
+++ b/vue-fastapi-frontend/src/api/flow/flow.js
@@ -0,0 +1,25 @@
+import request from '@/utils/request'
+
+
+export function getApprovalList(data) {
+ return request({
+ url: '/default-api/approval/list',
+ method: 'get',
+ params: data
+ })
+}
+
+export function getWaitingFlowCount() {
+ return request({
+ url: '/default-api/approval/waitingTotal',
+ method: 'get'
+ })
+}
+
+export function operateProcess(data) {
+ return request({
+ url: '/default-api/approval/operate',
+ method: 'post',
+ data: data
+ })
+}
\ No newline at end of file
diff --git a/vue-fastapi-frontend/src/api/meta/metaInfo.js b/vue-fastapi-frontend/src/api/meta/metaInfo.js
new file mode 100644
index 0000000..d2ae8cb
--- /dev/null
+++ b/vue-fastapi-frontend/src/api/meta/metaInfo.js
@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+// 查询参数列表
+export function getDataSourceList(query) {
+ return request({
+ url: '/ds-api/dolphinscheduler/datasources/withpwdlist?pageNo=1&pageSize=100',
+ method: 'get',
+ headers: {dashUserName:query.userName,dashPassword:query.password}
+ })
+}
+// 查询参数列表
+export function getMetaDataList(query) {
+ return request({
+ url: '/default-api/dasset/meta/get',
+ method: 'get',
+ params: query
+ })
+}
+
+export function getColumnList(query){
+ return request({
+ url:'/default-api/dasset/meta/column/list',
+ method: 'get',
+ params: query
+ })
+}
+
+export function getMetaClasList(){
+ return request({
+ url:'/default-api/dasset/meta/clas/list',
+ method: 'get',
+ })
+}
+
+export function postMetaSupp(data){
+ return request({
+ url:'/default-api/dasset/meta/supp',
+ method: 'post',
+ data: data
+ })
+}
+
+
+
+
+
diff --git a/vue-fastapi-frontend/src/components/TopNav/index.vue b/vue-fastapi-frontend/src/components/TopNav/index.vue
index 52b40ea..b2594db 100644
--- a/vue-fastapi-frontend/src/components/TopNav/index.vue
+++ b/vue-fastapi-frontend/src/components/TopNav/index.vue
@@ -44,7 +44,7 @@ const visibleNumber = ref(null);
// 当前激活菜单的 index
const currentIndex = ref(null);
// 隐藏侧边栏路由
-const hideList = ['/index', '/user/profile'];
+const hideList = ['/index', '/user/profile', 'system/flow/index'];
const appStore = useAppStore()
const settingsStore = useSettingsStore()
diff --git a/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirror.vue b/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirror.vue
new file mode 100644
index 0000000..eb817ca
--- /dev/null
+++ b/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirror.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vue-fastapi-frontend/src/layout/components/Navbar.vue b/vue-fastapi-frontend/src/layout/components/Navbar.vue
index 05e15af..75db2de 100644
--- a/vue-fastapi-frontend/src/layout/components/Navbar.vue
+++ b/vue-fastapi-frontend/src/layout/components/Navbar.vue
@@ -8,8 +8,13 @@
-
-
+
+
+
+
+
+
+
@@ -55,16 +60,20 @@ import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import HeaderSearch from '@/components/HeaderSearch'
-import RuoYiGit from '@/components/RuoYi/Git'
+// import RuoYiGit from '@/components/RuoYi/Git'
+import { ref, nextTick, computed, watch, reactive, onMounted } from 'vue'
import RuoYiDoc from '@/components/RuoYi/Doc'
import useAppStore from '@/store/modules/app'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
+import cache from "@/plugins/cache";
+import {getWaitingFlowCount} from "@/api/flow/flow.js"
+
const appStore = useAppStore()
const userStore = useUserStore()
const settingsStore = useSettingsStore()
-
+const totalFlow = ref(cache.local.get("waitingTotal") || 0)
function toggleSideBar() {
appStore.toggleSideBar()
}
@@ -98,6 +107,24 @@ const emits = defineEmits(['setLayout'])
function setLayout() {
emits('setLayout');
}
+onMounted(()=>{
+ getWaitingFlowCount().then(res=>{
+ cache.local.set("waitingTotal",res.data)
+ })
+})
+// 监听 storage 事件
+const handleStorageChange = (event) => {
+ console.log(event)
+ if (event.key === 'waitingTotal') {
+ console.log(event)
+ totalFlow.value = event.newValue || 0;
+ }
+};
+
+onMounted(() => {
+ window.addEventListener('storage', handleStorageChange);
+});
+
\ No newline at end of file
diff --git a/vue-fastapi-frontend/src/views/system/flow/conf.vue b/vue-fastapi-frontend/src/views/system/flow/conf.vue
new file mode 100644
index 0000000..052a691
--- /dev/null
+++ b/vue-fastapi-frontend/src/views/system/flow/conf.vue
@@ -0,0 +1,11 @@
+
+
+ 你好
+
+
+
+
\ No newline at end of file
diff --git a/vue-fastapi-frontend/src/views/system/flow/index.vue b/vue-fastapi-frontend/src/views/system/flow/index.vue
new file mode 100644
index 0000000..afc9886
--- /dev/null
+++ b/vue-fastapi-frontend/src/views/system/flow/index.vue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 元数据信息补录
+
+
+
+
+ {{ scope.row.businessId }}
+
+
+
+
+
+
+ 未审批
+ 未审批
+ 已审批
+ 已驳回
+
+
+
+
+ {{ scope.row.approver }}
+
+
+
+
+ 同意
+ 驳回
+
+
+
+
+
+
+
+
+
diff --git a/vue-fastapi-frontend/vite.config.js b/vue-fastapi-frontend/vite.config.js
index 9b7128e..23af531 100644
--- a/vue-fastapi-frontend/vite.config.js
+++ b/vue-fastapi-frontend/vite.config.js
@@ -36,7 +36,8 @@ export default defineConfig(({ mode, command }) => {
rewrite: (p) => p.replace(/^\/default-api/, '')
},
'/aichat-api': {
- target: 'http://127.0.0.1:8000',
+ target: 'http://47.121.207.11:7861',
+ // target: 'http://127.0.0.1:8000',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/aichat-api/, '')
},