feat: 员工同步配置支持多租户
All checks were successful
continuous-integration/drone/push Build is passing

- 后端新增员工同步配置API(获取/保存/测试连接)
- employee_sync_service 从数据库读取配置
- 前端系统设置页面添加"员工同步"Tab
- 支持配置:数据库主机、端口、库名、用户名、密码、表名
- 保留默认配置用于向后兼容
This commit is contained in:
yuliang_guo
2026-01-31 17:01:30 +08:00
parent 8500308919
commit 78e1bb3dc3
3 changed files with 435 additions and 11 deletions

View File

@@ -23,17 +23,59 @@ logger = get_logger(__name__)
class EmployeeSyncService:
"""员工同步服务"""
# 外部数据库连接配置
EXTERNAL_DB_URL = "mysql+aiomysql://neuron_new:NWxGM6CQoMLKyEszXhfuLBIIo1QbeK@120.77.144.233:29613/neuron_new?charset=utf8mb4"
# 默认外部数据库连接配置(向后兼容)
DEFAULT_DB_URL = "mysql+aiomysql://neuron_new:NWxGM6CQoMLKyEszXhfuLBIIo1QbeK@120.77.144.233:29613/neuron_new?charset=utf8mb4"
DEFAULT_TABLE_NAME = "v_钉钉员工表"
def __init__(self, db: AsyncSession):
def __init__(self, db: AsyncSession, tenant_id: int = 1):
self.db = db
self.tenant_id = tenant_id
self.external_engine = None
self.table_name = self.DEFAULT_TABLE_NAME
self._db_url = None
async def _get_config_from_db(self) -> tuple:
"""从数据库获取员工同步配置"""
result = await self.db.execute(
text("""
SELECT config_key, config_value
FROM tenant_configs
WHERE tenant_id = :tenant_id AND config_group = 'employee_sync'
"""),
{"tenant_id": self.tenant_id}
)
rows = result.fetchall()
config = {}
for key, value in rows:
config[key] = value
return config
async def _build_db_url(self) -> str:
"""构建数据库连接URL"""
config = await self._get_config_from_db()
db_host = config.get('DB_HOST')
db_port = config.get('DB_PORT')
db_name = config.get('DB_NAME')
db_user = config.get('DB_USER')
db_password = config.get('DB_PASSWORD')
self.table_name = config.get('TABLE_NAME') or self.DEFAULT_TABLE_NAME
# 如果配置完整使用配置的URL
if all([db_host, db_port, db_name, db_user, db_password]):
return f"mysql+aiomysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}?charset=utf8mb4"
# 否则使用默认配置
logger.warning(f"租户 {self.tenant_id} 未配置员工同步数据库,使用默认配置")
return self.DEFAULT_DB_URL
async def __aenter__(self):
"""异步上下文管理器入口"""
self._db_url = await self._build_db_url()
self.external_engine = create_async_engine(
self.EXTERNAL_DB_URL,
self._db_url,
echo=False,
pool_pre_ping=True,
pool_recycle=3600
@@ -52,9 +94,9 @@ class EmployeeSyncService:
Returns:
员工数据列表
"""
logger.info("开始从钉钉员工表获取数据...")
logger.info(f"开始从员工表 {self.table_name} 获取数据...")
query = """
query = f"""
SELECT
员工姓名,
手机号,
@@ -67,7 +109,7 @@ class EmployeeSyncService:
钉钉用户ID,
入职日期,
工作地点
FROM v_钉钉员工表
FROM {self.table_name}
WHERE 是否在职 = 1
ORDER BY 员工姓名
"""