This commit is contained in:
2025-10-31 14:30:42 +08:00
parent 93d412b8fe
commit bd0815d0e7
23 changed files with 2394 additions and 28 deletions

1
service/__init__.py Normal file
View File

@ -0,0 +1 @@
# Service package initialization

285
service/api_http_client.py Normal file
View File

@ -0,0 +1,285 @@
from logging import exception
from typing import Optional, Dict, Any
import time
import threading
import requests
from models import LoginResponse
from config.ini_manager import ini_manager
class BaseHttpClient:
"""基础HTTP客户端 - 纯网络请求功能"""
def __init__(self):
"""初始化基础HTTP客户端"""
self._session = requests.Session()
self._settings = None
def request(self, method: str, url: str, data: Dict[str, Any] = None,
headers: Dict[str, str] = None, timeout: int = None,
retries: int = 0, retry_interval: float = 1.0,
**kwargs) -> Dict[str, Any]:
"""
发送HTTP请求支持重试机制
Args:
method: HTTP方法
url: 请求URL
data: 请求数据
headers: 请求头
timeout: 超时时间
retries: 重试次数(可选,默认使用配置中的重试次数)
retry_interval: 重试间隔默认1秒
**kwargs: 其他参数
Returns:
Dict[str, Any]: 响应数据
"""
if headers is None:
headers = {}
# 重试逻辑
for attempt in range(retries + 1):
try:
if method.upper() == 'GET':
response = self._session.get(
url, headers=headers, timeout=timeout, **kwargs
)
elif method.upper() == 'POST':
response = self._session.post(
url, json=data, headers=headers, timeout=timeout, **kwargs
)
else:
raise ValueError(f"不支持的HTTP方法: {method}")
# 检查响应状态
response.raise_for_status()
# 解析JSON响应
return response.json()
except exception as e:
# 如果是最后一次尝试,直接抛出异常
if attempt == retries:
print(f"请求失败(第{attempt + 1}次尝试): {e}")
raise
# 打印重试信息
print(f"请求失败(第{attempt + 1}次尝试),{retry_interval}秒后重试: {e}")
# 等待重试间隔
time.sleep(retry_interval)
def get(self, url: str, headers: Dict[str, str] = None,
timeout: int = None, retries: int = 0, retry_interval: float = 1.0,
**kwargs) -> Dict[str, Any]:
"""
GET请求
Args:
url: 请求URL
headers: 请求头
timeout: 超时时间
**kwargs: 其他参数
Returns:
Dict[str, Any]: 响应数据
"""
return self.request('GET', url, headers=headers, timeout=timeout, retries=retries, retry_interval=retry_interval, **kwargs)
def post(self, url: str, data: Dict[str, Any] = None,
headers: Dict[str, str] = None, timeout: int = None,
retries: int = 0, retry_interval: float = 1.0,
**kwargs) -> Dict[str, Any]:
"""
POST请求
Args:
url: 请求URL
data: 请求数据
headers: 请求头
timeout: 超时时间
retries: 重试次数(可选,默认使用配置中的重试次数)
retry_interval: 重试间隔默认1秒
**kwargs: 其他参数
Returns:
Dict[str, Any]: 响应数据
"""
return self.request('POST', url, data=data, headers=headers, timeout=timeout, retries=retries, retry_interval=retry_interval, **kwargs)
class ApiHttpClient(BaseHttpClient):
"""API客户端 - 业务API调用整合认证和单例功能"""
def __init__(self):
"""初始化API客户端"""
"""初始化API客户端"""
super().__init__()
# 认证缓存
self._auth_cache = {
'app_id': None,
'expire_time': None,
'sign_token': None,
'zr_jwt': None
}
self._cache_lock = threading.RLock()
@property
def settings(self):
"""获取配置对象,由子类实现"""
if self._settings is None:
self._settings = ini_manager
return self._settings
def login(self) -> bool:
"""
用户登录获取AppID
Args:
url: 登录URL可选默认使用配置中的URL
login_model: 登录请求模型(可选,默认使用配置中的模型)
Returns:
bool: 登录是否成功
"""
url = self.settings.api_login_url
login_model = self.settings.api_login_model
print("开始登录...")
try:
# 发送登录请求
response_data = self.request(
method='POST',
url=url,
data=login_model,
timeout=self.settings.api_timeout
)
# 解析登录响应
login_response = LoginResponse(**response_data)
if login_response.Code != 200:
error_msg = login_response.Message or "登录失败"
print(f"获取AppID失败: {error_msg}")
return False
# 更新认证缓存
with self._cache_lock:
self._auth_cache.update({
'app_id': login_response.app_id,
'expire_time': login_response.expire_time,
'sign_token': login_response.sign_token,
'zr_jwt': login_response.zr_jwt
})
print(f"成功获取AppID: {self._auth_cache['app_id']}")
print(f"过期时间: {self._auth_cache['expire_time']}")
return True
except Exception as e:
print(f"登录过程中出现异常: {e}")
self._clear_auth_cache()
return False
def is_app_id_valid(self) -> bool:
"""检查AppID是否有效"""
with self._cache_lock:
expire_time = self._auth_cache.get('expire_time')
if not expire_time:
return False
# 检查是否过期提前12小时过期避免临界情况
try:
expire_timestamp = time.mktime(time.strptime(expire_time, '%Y-%m-%d %H:%M:%S'))
is_valid = time.time() < expire_timestamp - self.settings.api_auth_timeout
if not is_valid:
print("认证信息已过期")
return is_valid
except (ValueError, TypeError):
print("日期格式不正确")
return False
def _get_auth_headers(self) -> Dict[str, str]:
"""获取认证头信息"""
with self._cache_lock:
app_id = self._auth_cache.get('app_id')
headers = {
'AppID': app_id,
'Content-Type': 'application/json'
}
return headers
def get(self, url: str, auth: bool = True, **kwargs) -> Dict[str, Any]:
"""
GET请求支持认证检查
Args:
url: 请求URL
auth: 是否需要认证
timeout: 超时时间
retries: 重试次数
retry_interval: 重试间隔
**kwargs: 其他参数
Returns:
Dict[str, Any]: 响应数据
"""
if auth:
if not self.is_app_id_valid():
self.login()
if not self.is_app_id_valid():
raise Exception("登录失败无法获取有效AppID")
auth_headers = self._get_auth_headers()
return self.request(method='GET', url=url, headers=auth_headers, timeout=self.settings.api_timeout,
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
else:
return self.request(method='GET', url=url, timeout=self.settings.api_timeout,
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
def post(self, url: str, data: Dict[str, Any] = None, auth: bool = True,**kwargs) -> Dict[str, Any]:
"""
POST请求支持认证检查
Args:
url: 请求URL
data: 请求数据
auth: 是否需要认证
timeout: 超时时间
retries: 重试次数
retry_interval: 重试间隔
**kwargs: 其他参数
Returns:
Dict[str, Any]: 响应数据
"""
if auth:
if not self.is_app_id_valid():
self.login()
if not self.is_app_id_valid():
raise Exception("登录失败无法获取有效AppID")
auth_headers = self._get_auth_headers()
return self.request(method='POST', url=url, data=data, headers=auth_headers, timeout=self.settings.api_timeout,
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
else:
return self.request(method='POST', url=url, data=data, timeout=self.settings.api_timeout,
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
def _clear_auth_cache(self):
"""清除认证缓存"""
with self._cache_lock:
self._auth_cache.clear()
# 重新初始化必要的键
self._auth_cache.update({
'app_id': None,
'expire_time': None,
'sign_token': None,
'zr_jwt': None
})
print("认证缓存已清除")
api_http_client = ApiHttpClient()

158
service/mould_service.py Normal file
View File

@ -0,0 +1,158 @@
from datetime import datetime, timedelta
from common.sqlite_handler import SQLiteHandler
from typing import Optional, List
from api_http_client import api_http_client
from busisness.models import ArtifactInfo, TaskInfo, LoginRequest
from config.ini_manager import ini_manager
class MouldService:
"""模具服务类提供模具相关的API调用"""
def __init__(self):
"""初始化模具服务"""
self._api_client = api_http_client
self._host = ini_manager.api_base_url
def get_task_info(self, task_id: str) -> Optional[TaskInfo]:
"""
获取任务单信息
Args:
task_id: 任务单编号
Returns:
任务单信息对象如果失败返回None
"""
url = f"{self._host}/api/ext/artifact/task?TaskId={task_id}"
try:
# 调用API获取数据
response_data = self._api_client.get(url, auth=True)
# 检查响应状态
if response_data.get('Code') != 200:
print(f"获取任务单信息失败: {response_data.get('Message')}")
return None
# 解析数据
data = response_data.get('Data', {})
if not data:
print(f"未获取到任务单 {task_id} 的信息")
return None
# 转换为任务单信息对象
task_info = TaskInfo(**data)
return task_info
except Exception as e:
print(f"请求任务单信息异常: {e}")
return None
def get_not_pour_artifacts(self) -> Optional[List[ArtifactInfo]]:
"""
获取已入模绑定未浇筑的管片信息
Returns:
未浇筑管片列表如果失败返回None
"""
url = f"{self._host}/api/ext/artifact/not_pour"
try:
# 调用API获取数据
response_data = self._api_client.get(url, auth=True)
# 检查响应状态
if response_data.get('Code') != 200:
print(f"获取未浇筑管片信息失败: {response_data.get('Message')}")
return None
# 解析数据
data_list = response_data.get('Data', [])
if not data_list:
print("当前没有未浇筑的管片")
return []
# 转换为管片信息对象列表
artifacts = [ArtifactInfo(**item) for item in data_list]
return artifacts
except Exception as e:
print(f"请求未浇筑管片信息异常: {e}")
return None
if __name__ == "__main__":
# 创建模具服务实例
mould_service = MouldService()
db = SQLiteHandler.get_instance("db/three.db", max_readers=50, busy_timeout=4000)
# 测试获取未浇筑管片信息
not_poured = mould_service.get_not_pour_artifacts()
if not_poured:
for item in not_poured:
artifact = db.fetch_one("SELECT * FROM ArtifactTask WHERE ArtifactID = ?", (item.ArtifactID,))
if not artifact:
dict={
"ArtifactID": item.ArtifactID,
"ArtifactActionID": item.ArtifactActionID,
"ArtifactIDVice1": item.ArtifactIDVice1,
"ProduceRingNumber": item.ProduceRingNumber,
"MouldCode": item.MouldCode,
"SkeletonID": item.SkeletonID,
"RingTypeCode": item.RingTypeCode,
"SizeSpecification": item.SizeSpecification,
"BuriedDepth": item.BuriedDepth,
"BlockNumber": item.BlockNumber,
"BetonVolume": item.BetonVolume,
"BetonTaskID": item.BetonTaskID,
"HoleRingMarking": item.HoleRingMarking,
"GroutingPipeMarking": item.GroutingPipeMarking,
"PolypropyleneFiberMarking": item.PolypropyleneFiberMarking,
"Status": 1,
"Source": 1
}
db.insert("ArtifactTask", dict)
dict={
"TaskID": item.BetonTaskID,
"ProjectName": "上海市轨道交通19号线工程盾构区间管片生产2标",
"ProduceMixID": "20251030-02",
"VinNo": "",
"BetonVolume": item.BetonVolume,
"MouldCode": item.MouldCode,
"SkeletonID": item.SkeletonID,
"RingTypeCode": item.RingTypeCode,
"SizeSpecification": item.SizeSpecification,
"BuriedDepth": item.BuriedDepth,
"BlockNumber": item.BlockNumber,
"Mode": 1,
"Status": 1,
"Source": 1,
"OptTime": str(datetime.now() - timedelta(minutes=5)),
"CreateTime": str(datetime.now())
}
db.insert("PDRecord", dict)
# for i in range(2, 5):
# row = db.fetch_one("SELECT * FROM ArtifactTask WHERE ID = ?", (i,))
# if row:
# dict={
# "TaskID": row["BetonTaskID"],
# "ProjectName": "上海市轨道交通19号线工程盾构区间管片生产2标",
# "ProduceMixID": "20251030-02",
# "VinNo": "",
# "BetonVolume": row["BetonVolume"],
# "MouldCode": row["MouldCode"],
# "SkeletonID": row["SkeletonID"],
# "RingTypeCode": row["RingTypeCode"],
# "SizeSpecification": row["SizeSpecification"],
# "BuriedDepth": row["BuriedDepth"],
# "BlockNumber": row["BlockNumber"],
# "Mode": 1,
# "Status": 1,
# "Source": 1,
# "OptTime": str(datetime.now() - timedelta(minutes=5)),
# "CreateTime": str(datetime.now())
# }
# db.insert("PDRecord", dict)