优化后台业务

This commit is contained in:
super
2026-04-30 11:36:58 +08:00
parent 9c16c9c589
commit c6ecfb5b77
48 changed files with 1211 additions and 2391 deletions

View File

@@ -4,9 +4,11 @@
import json
import os
import re
import threading
import requests
from flask import Blueprint, request, jsonify, session, current_app
from requests.adapters import HTTPAdapter
from flask import Blueprint, request, jsonify, session, current_app, g
import pymysql
from werkzeug.security import generate_password_hash
@@ -43,6 +45,9 @@ except ImportError:
backend_java_base_url = os.environ.get('BACKEND_JAVA_BASE_URL', 'http://127.0.0.1:18080').rstrip('/')
admin_api = Blueprint('admin_api', __name__, url_prefix='/api/admin')
_backend_java_session_local = threading.local()
_column_sort_schema_checked = False
_column_sort_schema_lock = threading.Lock()
ADMIN_MENU_ACCESS_CONFIG = {
'dedupe-total-data': {
@@ -103,10 +108,22 @@ def _safe_version_key(version):
return s or 'unknown'
def _get_backend_java_session():
http_session = getattr(_backend_java_session_local, 'session', None)
if http_session is None:
http_session = requests.Session()
adapter = HTTPAdapter(pool_connections=8, pool_maxsize=32, max_retries=0)
http_session.mount('http://', adapter)
http_session.mount('https://', adapter)
_backend_java_session_local.session = http_session
return http_session
def _proxy_backend_java(method, path, *, params=None, json_data=None, files=None, data=None, timeout=10):
url = f"{backend_java_base_url}{path}"
try:
resp = requests.request(method=method, url=url, params=params, json=json_data, files=files, data=data, timeout=timeout)
requester = requests if files else _get_backend_java_session()
resp = requester.request(method=method, url=url, params=params, json=json_data, files=files, data=data, timeout=timeout)
except requests.RequestException:
return None, jsonify({'success': False, 'error': 'backend-java 服务不可用'}), 502
try:
@@ -146,6 +163,28 @@ def _parse_optional_int(value):
def _ensure_column_sort_schema():
global _column_sort_schema_checked
if _column_sort_schema_checked:
return
with _column_sort_schema_lock:
if _column_sort_schema_checked:
return
conn = get_db()
try:
with conn.cursor() as cur:
try:
cur.execute("ALTER TABLE columns ADD COLUMN sort_order INT NOT NULL DEFAULT 0 COMMENT '鑿滃崟鎺掑簭' AFTER route_path")
except Exception:
pass
try:
cur.execute("UPDATE columns SET sort_order = id WHERE sort_order IS NULL OR sort_order = 0")
except Exception:
pass
conn.commit()
_column_sort_schema_checked = True
finally:
conn.close()
return
conn = get_db()
try:
with conn.cursor() as cur:
@@ -299,6 +338,10 @@ def _get_current_admin_permission_sets():
user_id = _get_current_admin_id()
if not user_id:
return set(), set()
cache_key = f'_admin_permission_sets_{user_id}'
cached = getattr(g, cache_key, None)
if cached is not None:
return cached
conn = get_db()
try:
with conn.cursor() as cur:
@@ -314,7 +357,9 @@ def _get_current_admin_permission_sets():
conn.close()
key_set = {(row.get('column_key') or '').strip() for row in rows if (row.get('column_key') or '').strip()}
route_set = {(row.get('route_path') or '').strip() for row in rows if (row.get('route_path') or '').strip()}
return key_set, route_set
cached = (key_set, route_set)
setattr(g, cache_key, cached)
return cached
def _ensure_admin_menu_access(*menu_names):
@@ -830,14 +875,6 @@ def list_columns():
if denied:
return denied
menu_type = (request.args.get('menu_type') or '').strip()
params = {'menuType': menu_type} if menu_type else None
result, error_response, status = _proxy_backend_java(
'GET',
'/api/admin/permission-menus',
params=params,
)
if error_response is None:
_sync_local_columns_from_backend([_format_permission_item(item) for item in (result.get('data') or [])])
local_rows = _load_local_columns(menu_type or None)
items = [
{
@@ -1484,32 +1521,7 @@ def _load_expanded_shop_manage_groups(role, current_row):
if error_response is not None:
return None, error_response, status
direct_groups = result.get('data') or []
if role == 'super_admin':
return direct_groups, None, 200
direct_ids = {item.get('id') for item in direct_groups if item.get('id')}
leader_ids = {item.get('leaderUserId') for item in direct_groups if item.get('leaderUserId')}
if not leader_ids:
return direct_groups, None, 200
all_result, error_response, status = _proxy_backend_java(
'GET',
'/api/admin/shop-manages/groups',
params={'superAdmin': 'true'},
)
if error_response is not None:
return None, error_response, status
merged = []
seen_ids = set()
for item in all_result.get('data') or []:
item_id = item.get('id')
if item_id in direct_ids or item.get('leaderUserId') in leader_ids:
if item_id not in seen_ids:
merged.append(item)
seen_ids.add(item_id)
return merged, None, 200
return result.get('data') or [], None, 200
@admin_api.route('/shop-manages')
@@ -1523,59 +1535,6 @@ def list_shop_manages():
group_id_raw = (request.args.get('group_id') or '').strip()
shop_name = (request.args.get('shop_name') or '').strip()
if role != 'super_admin':
groups, error_response, status = _load_expanded_shop_manage_groups(role, current_row)
if error_response is not None:
return error_response, status
accessible_group_ids = [item.get('id') for item in (groups or []) if item.get('id')]
selected_group_id = None
if group_id_raw:
try:
selected_group_id = int(group_id_raw)
except (TypeError, ValueError):
selected_group_id = None
if selected_group_id and selected_group_id not in accessible_group_ids:
return jsonify({'success': True, 'items': [], 'total': 0, 'page': page, 'page_size': page_size})
query_group_ids = [selected_group_id] if selected_group_id else accessible_group_ids
all_items = []
for group_id in query_group_ids:
group_page = 1
while True:
group_params = {
'page': group_page,
'pageSize': 100,
'groupId': group_id,
'superAdmin': 'true',
}
if current_row and current_row.get('id'):
group_params['operatorId'] = current_row.get('id')
if shop_name:
group_params['shopName'] = shop_name
result, error_response, status = _proxy_backend_java(
'GET',
'/api/admin/shop-manages',
params=group_params,
)
if error_response is not None:
return error_response, status
payload = result.get('data') or {}
rows = payload.get('items') or []
all_items.extend(rows)
total = payload.get('total') or 0
if group_page * 100 >= total or not rows:
break
group_page += 1
all_items.sort(key=lambda item: item.get('id') or 0, reverse=True)
total = len(all_items)
offset = (page - 1) * page_size
return jsonify({
'success': True,
'items': [_format_shop_manage_item(item) for item in all_items[offset:offset + page_size]],
'total': total,
'page': page,
'page_size': page_size,
})
params = {'page': page, 'pageSize': page_size}
if current_row and current_row.get('id'):
params['operatorId'] = current_row.get('id')