更新处理相关内容

This commit is contained in:
super
2026-05-09 00:20:52 +08:00
parent a2d0bd3c1c
commit 52095eb992
54 changed files with 636585 additions and 21916 deletions

View File

@@ -48,6 +48,8 @@ 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()
_product_category_schema_checked = False
_product_category_schema_lock = threading.Lock()
ADMIN_MENU_ACCESS_CONFIG = {
'dedupe-total-data': {
@@ -70,6 +72,11 @@ ADMIN_MENU_ACCESS_CONFIG = {
'route_path': 'query-asin',
'error': '无权访问查询 ASIN 模块',
},
'product-categories': {
'column_key': 'admin_product_categories',
'route_path': 'product-categories',
'error': '无权访问商品类目模块',
},
}
ADMIN_MENU_ACCESS_CONFIG.update({
@@ -300,6 +307,92 @@ def _get_next_local_column_sort_order():
conn.close()
PRODUCT_CATEGORY_DEFAULT_TREE = [
{
'name': '护肤品',
'key': 'skincare',
'children': [
('面霜', 'skincare_cream'),
('精华', 'skincare_essence'),
('面膜', 'skincare_mask'),
('爽肤水', 'skincare_toner'),
('身体乳', 'skincare_body_lotion'),
],
},
{
'name': '彩妆',
'key': 'makeup',
'children': [
('口红', 'makeup_lipstick'),
('粉底', 'makeup_foundation'),
('眼影', 'makeup_eyeshadow'),
('睫毛', 'makeup_mascara'),
],
},
{
'name': '洗护',
'key': 'haircare',
'children': [
('洗发水', 'haircare_shampoo'),
('护发素', 'haircare_conditioner'),
('染发剂', 'haircare_hair_dye'),
('烫发膏', 'haircare_perm_cream'),
],
},
{
'name': '功效类',
'key': 'functional',
'children': [
('防晒', 'functional_sunscreen'),
('祛斑', 'functional_spot_removal'),
('美白', 'functional_whitening'),
('祛痘产品', 'functional_acne_care'),
],
},
{
'name': '香氛',
'key': 'fragrance',
'children': [
('香水', 'fragrance_perfume'),
('香薰精油(高酒精属于危险品)', 'fragrance_essential_oil_hazardous'),
],
},
]
def _ensure_local_admin_menu_item(name, column_key, route_path, sort_order):
_ensure_column_sort_schema()
conn = get_db()
try:
with conn.cursor() as cur:
cur.execute(
"""
INSERT INTO columns (name, column_key, menu_type, route_path, sort_order)
VALUES (%s, %s, 'admin', %s, %s)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
menu_type = 'admin',
route_path = VALUES(route_path),
sort_order = VALUES(sort_order)
""",
(name, column_key, route_path, int(sort_order)),
)
conn.commit()
finally:
conn.close()
def _ensure_product_category_schema():
global _product_category_schema_checked
if _product_category_schema_checked:
return
with _product_category_schema_lock:
if _product_category_schema_checked:
return
_ensure_local_admin_menu_item('商品类目', 'admin_product_categories', 'product-categories', 66)
_product_category_schema_checked = True
def _swap_local_column_sort_order(column_id, target_id):
_ensure_column_sort_schema()
conn = get_db()
@@ -440,6 +533,20 @@ def _ensure_backend_menu_access(*menu_names):
return role, current_row, (jsonify({'success': False, 'error': error_message}), 403)
def _ensure_product_category_access():
role, current_row, items, denied = _load_current_backend_menu_items()
if denied:
return role, current_row, denied
if role == 'super_admin':
return role, current_row, None
for item in items or []:
if (item.get('column_key') or '').strip() == 'admin_product_categories':
return role, current_row, None
if (item.get('route_path') or '').strip() == 'product-categories':
return role, current_row, None
return role, current_row, (jsonify({'success': False, 'error': '无权访问商品类目模块'}), 403)
def _get_column_ids_by_route_paths(route_paths, menu_type='admin'):
normalized_paths = [(path or '').strip() for path in (route_paths or []) if (path or '').strip()]
if not normalized_paths:
@@ -496,6 +603,7 @@ def get_admin_current_user():
@admin_api.route('/current-user/menus')
@login_required
def get_admin_current_user_menus():
_ensure_product_category_schema()
_, _, items, denied = _load_current_backend_menu_items()
if denied:
return denied
@@ -874,6 +982,7 @@ def list_columns():
_, _, denied = _ensure_admin_menu_access('columns', 'users')
if denied:
return denied
_ensure_product_category_schema()
menu_type = (request.args.get('menu_type') or '').strip()
local_rows = _load_local_columns(menu_type or None)
items = [
@@ -1072,6 +1181,117 @@ def _set_user_column_permissions(cur, user_id, column_ids):
# ---------- 版本管理web_config ----------
# ---------- 商品类目 ----------
def _format_product_category_item(item, include_children=True):
formatted = {
'id': item.get('id'),
'parent_id': item.get('parentId'),
'name': item.get('name') or '',
'category_key': item.get('categoryKey') or '',
'sort_order': item.get('sortOrder') if item.get('sortOrder') is not None else 0,
'description': item.get('description') or '',
'is_builtin': bool(item.get('isBuiltin')),
'child_count': item.get('childCount') if item.get('childCount') is not None else 0,
'level': item.get('level') if item.get('level') is not None else 0,
'path': item.get('path') or '',
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
'updated_at': (item.get('updatedAt') or '').replace('T', ' ')[:16],
}
if include_children:
formatted['children'] = [_format_product_category_item(child) for child in (item.get('children') or [])]
return formatted
def _build_product_category_payload_for_java(data):
sort_order = data.get('sort_order') if 'sort_order' in data else data.get('sortOrder')
parent_id = data.get('parent_id') if 'parent_id' in data else data.get('parentId')
if parent_id == '':
parent_id = None
if sort_order == '':
sort_order = None
return {
'parentId': parent_id,
'name': (data.get('name') or '').strip(),
'sortOrder': sort_order,
'description': (data.get('description') or '').strip(),
}
@admin_api.route('/product-categories')
@login_required
def list_product_categories():
_ensure_product_category_schema()
_, _, denied = _ensure_product_category_access()
if denied:
return denied
result, error_response, status = _proxy_backend_java('GET', '/api/admin/product-categories')
if error_response is not None:
return error_response, status
payload = result.get('data') or {}
return jsonify({
'success': True,
'tree': [_format_product_category_item(item) for item in (payload.get('tree') or [])],
'items': [_format_product_category_item(item, include_children=False) for item in (payload.get('items') or [])],
})
@admin_api.route('/product-category', methods=['POST'])
@login_required
def create_product_category():
_ensure_product_category_schema()
_, _, denied = _ensure_product_category_access()
if denied:
return denied
result, error_response, status = _proxy_backend_java(
'POST',
'/api/admin/product-category',
json_data=_build_product_category_payload_for_java(request.get_json() or {}),
)
if error_response is not None:
return error_response, status
return jsonify({
'success': True,
'msg': result.get('message') or '创建成功',
'item': _format_product_category_item(result.get('data') or {}, include_children=False),
})
@admin_api.route('/product-category/<int:item_id>', methods=['PUT'])
@login_required
def update_product_category(item_id):
_ensure_product_category_schema()
_, _, denied = _ensure_product_category_access()
if denied:
return denied
result, error_response, status = _proxy_backend_java(
'PUT',
f'/api/admin/product-category/{item_id}',
json_data=_build_product_category_payload_for_java(request.get_json() or {}),
)
if error_response is not None:
return error_response, status
return jsonify({
'success': True,
'msg': result.get('message') or '保存成功',
'item': _format_product_category_item(result.get('data') or {}, include_children=False),
})
@admin_api.route('/product-category/<int:item_id>', methods=['DELETE'])
@login_required
def delete_product_category(item_id):
_ensure_product_category_schema()
_, _, denied = _ensure_product_category_access()
if denied:
return denied
result, error_response, status = _proxy_backend_java('DELETE', f'/api/admin/product-category/{item_id}')
if error_response is not None:
return error_response, status
return jsonify({'success': True, 'msg': result.get('message') or '删除成功'})
@admin_api.route('/versions')
@admin_required
def list_versions():