# coding=utf-8 """管理系统公开接口:拉取基地列表(需 X-API-Key)。""" try: import requests except ImportError: requests = None from dao.settings import DISH_MGMT_API_KEY, DISH_MGMT_API_TIMEOUT, DISH_MGMT_API_URL class MgmtApiError(RuntimeError): pass def fetch_bases(url=None, api_key=None, timeout=None): """ GET /api/public/bases 返回 items 列表(原始 dict),失败抛 MgmtApiError。 """ if requests is None: raise MgmtApiError('缺少 requests 库,请 pip install requests') url = (url or DISH_MGMT_API_URL or '').strip() api_key = (api_key if api_key is not None else DISH_MGMT_API_KEY) or '' api_key = str(api_key).strip() timeout = float(timeout if timeout is not None else DISH_MGMT_API_TIMEOUT) if not url: raise MgmtApiError('未配置 DISH_MGMT_API_URL') if not api_key: raise MgmtApiError('未配置 DISH_MGMT_API_KEY') headers = { 'X-API-Key': api_key, 'Accept': 'application/json', } try: resp = requests.get(url, headers=headers, timeout=timeout) except Exception as exc: raise MgmtApiError(f'请求管理系统失败: {exc}') from exc if resp.status_code != 200: body = (resp.text or '')[:300] raise MgmtApiError(f'管理系统 HTTP {resp.status_code}: {body}') try: data = resp.json() except Exception as exc: raise MgmtApiError(f'管理系统返回非 JSON: {exc}') from exc if isinstance(data, list): return data if isinstance(data, dict): items = data.get('items') if isinstance(items, list): return items # 兼容 { data: [...] } / { list: [...] } for key in ('data', 'list', 'bases', 'rows'): if isinstance(data.get(key), list): return data[key] raise MgmtApiError(f'无法解析基地列表,响应类型={type(data).__name__}') def map_remote_base(item): """ 管理系统字段 → 本地 bases 字段。 不把远程 id 当作本地主键,改存 external_id。 """ if not isinstance(item, dict): return None code = (item.get('code') or '').strip() name = (item.get('name') or '').strip() if not code or not name: return None province = (item.get('province') or '').strip() or None city = (item.get('city') or '').strip() or None district = (item.get('district') or '').strip() or None region_parts = [p for p in (province, city, district) if p] region = '/'.join(region_parts) if region_parts else None status = item.get('status') try: is_active = 1 if int(status) == 1 else 0 except (TypeError, ValueError): is_active = 1 external_id = item.get('id') try: external_id = int(external_id) if external_id is not None else None except (TypeError, ValueError): external_id = None sort_order = item.get('sortOrder', 0) try: sort_order = int(sort_order) except (TypeError, ValueError): sort_order = 0 return { 'external_id': external_id, 'base_code': code[:128], 'base_name': name[:100], 'branch_name': ((item.get('branchName') or '').strip() or None), 'region': region, 'province': province, 'city': city, 'district': district, 'address': ((item.get('address') or '').strip() or None), 'contact': ((item.get('contact') or '').strip() or None), 'phone': ((item.get('phone') or '').strip() or None), 'description': ((item.get('description') or '').strip() or None), 'is_active': is_active, 'sort_order': sort_order, 'longitude': item.get('longitude'), 'latitude': item.get('latitude'), }